Exemplo n.º 1
0
    def _spectrum_function(self):
        # Extract the photon arrival times from the reference band
        ref_events = self._get_times_from_energy_range(self.events2,
                                                       self.ref_band[0])
        ref_power_noise = poisson_level(norm="none", n_ph=ref_events.size)

        # Calculate the PDS in the reference band. Needed to calculate errors.
        results = avg_pds_from_events(ref_events,
                                      self.gti,
                                      self.segment_size,
                                      self.bin_time,
                                      silent=True,
                                      norm="none")
        freq = results["freq"]
        ref_power = results["power"]
        m_ave = results.meta["m"]

        # Get the frequency bins to be averaged in the final results.
        good = self._get_good_frequency_bins(freq)
        mean_ref_power = np.mean(ref_power[good])
        n_ave_bin = np.count_nonzero(good)

        m_tot = n_ave_bin * m_ave

        f = (self.freq_interval[0] + self.freq_interval[1]) / 2
        for i, eint in enumerate(show_progress(self.energy_intervals)):
            # Extract the photon arrival times from the subject band
            sub_events = self._get_times_from_energy_range(self.events1, eint)
            sub_power_noise = poisson_level(norm="none", n_ph=sub_events.size)

            results_cross = avg_cs_from_events(sub_events,
                                               ref_events,
                                               self.gti,
                                               self.segment_size,
                                               self.bin_time,
                                               silent=True,
                                               norm="none")

            results_ps = avg_pds_from_events(sub_events,
                                             self.gti,
                                             self.segment_size,
                                             self.bin_time,
                                             silent=True,
                                             norm="none")

            if results_cross is None or results_ps is None:
                continue

            cross = results_cross["power"]
            sub_power = results_ps["power"]

            Cmean = np.mean(cross[good])

            mean_sub_power = np.mean(sub_power[good])

            # Is the subject band overlapping with the reference band?
            # This will be used to correct the error bars, following
            # Ingram 2019.
            common_ref = self.same_events and len(
                cross_two_gtis([eint], self.ref_band)) > 0

            _, _, phi_e, _ = error_on_averaged_cross_spectrum(
                Cmean,
                mean_sub_power,
                mean_ref_power,
                m_tot,
                sub_power_noise,
                ref_power_noise,
                common_ref=common_ref)

            lag = np.mean((np.angle(cross[good]) / (2 * np.pi * freq[good])))

            lag_e = phi_e / (2 * np.pi * f)
            self.spectrum[i] = lag
            self.spectrum_error[i] = lag_e
Exemplo n.º 2
0
    def _spectrum_function(self):
        # Extract events from the reference band and calculate the PDS and
        # the Poisson noise level.
        ref_events = self._get_times_from_energy_range(self.events2,
                                                       self.ref_band[0])
        countrate_ref = get_average_ctrate(ref_events, self.gti,
                                           self.segment_size)
        ref_power_noise = poisson_level(norm="abs", meanrate=countrate_ref)

        results = avg_pds_from_events(ref_events,
                                      self.gti,
                                      self.segment_size,
                                      self.bin_time,
                                      silent=True,
                                      norm="abs")
        freq = results["freq"]
        ref_power = results["power"]
        m_ave = results.meta["m"]

        # Select the frequency range to be averaged for the measurement.
        good = (freq >= self.freq_interval[0]) & (freq < self.freq_interval[1])
        n_ave_bin = np.count_nonzero(good)
        mean_ref_power = np.mean(ref_power[good])

        m_tot = m_ave * n_ave_bin
        # Frequency resolution
        delta_nu = n_ave_bin * self.delta_nu

        for i, eint in enumerate(show_progress(self.energy_intervals)):
            # Extract events from the subject band
            sub_events = self._get_times_from_energy_range(self.events1, eint)
            countrate_sub = get_average_ctrate(sub_events, self.gti,
                                               self.segment_size)
            sub_power_noise = poisson_level(norm="abs", meanrate=countrate_sub)

            results_cross = avg_cs_from_events(
                sub_events,
                ref_events,
                self.gti,
                self.segment_size,
                self.bin_time,
                silent=True,
                norm="abs",
            )

            results_ps = avg_pds_from_events(sub_events,
                                             self.gti,
                                             self.segment_size,
                                             self.bin_time,
                                             silent=True,
                                             norm="abs")

            if results_cross is None or results_ps is None:
                continue

            cross = results_cross["power"]
            sub_power = results_ps["power"]
            mean = results_ps.meta["mean"]

            # Is the subject band overlapping with the reference band?
            # This will be used to correct the error bars, following
            # Ingram 2019.
            common_ref = self.same_events and len(
                cross_two_gtis([eint], self.ref_band)) > 0
            Cmean = np.mean(cross[good])
            if common_ref:
                # Equation 6 from Ingram+2019
                Cmean -= sub_power_noise

            Cmean_real = np.abs(Cmean)

            mean_sub_power = np.mean(sub_power[good])

            _, _, _, Ce = error_on_averaged_cross_spectrum(
                Cmean,
                mean_sub_power,
                mean_ref_power,
                m_tot,
                sub_power_noise,
                ref_power_noise,
                common_ref=common_ref)
            if not self.return_complex:
                Cmean = Cmean_real

            # Convert the cross spectrum to a covariance.
            cov, cov_e = cross_to_covariance(np.asarray([Cmean,
                                                         Ce]), mean_ref_power,
                                             ref_power_noise, delta_nu)

            meanrate = mean / self.bin_time

            if self.norm == "frac":
                cov, cov_e = cov / meanrate, cov_e / meanrate

            self.spectrum[i] = cov
            self.spectrum_error[i] = cov_e
Exemplo n.º 3
0
    def _spectrum_function(self):

        # Get the frequency bins to be averaged in the final results.
        good = self._get_good_frequency_bins()
        n_ave_bin = np.count_nonzero(good)

        # Get the frequency resolution of the final spectrum.
        delta_nu_after_mean = self.delta_nu * n_ave_bin

        for i, eint in enumerate(show_progress(self.energy_intervals)):
            # Extract events from the subject band and calculate the count rate
            # and Poisson noise level.
            sub_events = self._get_times_from_energy_range(self.events1, eint)
            countrate_sub = get_average_ctrate(sub_events, self.gti,
                                               self.segment_size)
            sub_power_noise = poisson_level(norm="abs", meanrate=countrate_sub)

            # If we provided the `events2` array, calculate the rms from the
            # cospectrum, otherwise from the PDS
            if not self.same_events:
                # Extract events from the subject band in the other array, and
                # calculate the count rate and Poisson noise level.
                sub_events2 = self._get_times_from_energy_range(
                    self.events2, eint)
                countrate_sub2 = get_average_ctrate(sub_events2, self.gti,
                                                    self.segment_size)
                sub2_power_noise = poisson_level(norm="abs",
                                                 meanrate=countrate_sub2)

                # Calculate the cross spectrum
                results = avg_cs_from_events(
                    sub_events,
                    sub_events2,
                    self.gti,
                    self.segment_size,
                    self.bin_time,
                    silent=True,
                    norm="abs",
                )
                if results is None:
                    continue
                cross = results["power"]

                m_ave, mean = [results.meta[key] for key in ["m", "mean"]]
                mean_power = np.mean(cross[good])
                power_noise = 0
                rmsnoise = np.sqrt(delta_nu_after_mean *
                                   np.sqrt(sub_power_noise * sub2_power_noise))
            else:
                results = avg_pds_from_events(sub_events,
                                              self.gti,
                                              self.segment_size,
                                              self.bin_time,
                                              silent=True,
                                              norm="abs")
                if results is None:
                    continue
                sub_power = results["power"]
                m_ave, mean = [results.meta[key] for key in ["m", "mean"]]

                mean_power = np.mean(sub_power[good])
                power_noise = sub_power_noise
                rmsnoise = np.sqrt(delta_nu_after_mean * power_noise)

            meanrate = mean / self.bin_time

            rms = np.sqrt(
                np.abs(mean_power - power_noise) * delta_nu_after_mean)

            # Assume coherence 0, use Ingram+2019
            num = rms**4 + rmsnoise**4 + 2 * rms * rmsnoise
            den = 4 * m_ave * n_ave_bin * rms**2

            rms_err = np.sqrt(num / den)
            if self.norm == "frac":
                rms, rms_err = rms / meanrate, rms_err / meanrate

            self.spectrum[i] = rms
            self.spectrum_error[i] = rms_err