Exemplo n.º 1
0
def folding(eventfile, Porb, nbins):
    """
    Folding the events by some orbital period
    """
    times = fits.open(eventfile)[1].data['TIME']  #getting array of times
    gtis_data = fits.open(eventfile)[2].data  #getting GTIs
    T = sum([
        gtis_data[i]['STOP'] - gtis_data[i]['START']
        for i in range(len(gtis_data))
    ])  #exposure time

    gtis_conform = []
    for i in range(len(gtis_data)):
        gtis_conform.append([gtis_data[i][0], gtis_data[i][1]
                             ])  #conform to the input that Stingray uses

    phase_sr, prof_sr, err_sr = fold_events(times,
                                            1 / Porb,
                                            gtis=np.array(gtis_conform),
                                            ref_time=times[0],
                                            nbin=nbins)
    phase_sr_expo, prof_sr_expo, err_sr_expo = fold_events(
        times,
        1 / Porb,
        gtis=np.array(gtis_conform),
        ref_time=times[0],
        expocorr=True,
        nbin=nbins)

    total_phase_sr = list(phase_sr) + list(phase_sr + 1)
    total_prof_sr = list(prof_sr) * 2
    total_err_sr = list(err_sr) * 2

    total_phase_sr_expo = list(phase_sr_expo) + list(phase_sr_expo + 1)
    total_prof_sr_expo = list(prof_sr_expo) * 2
    total_err_sr_expo = list(err_sr_expo) * 2

    plt.figure()
    plt.errorbar(x=total_phase_sr,
                 y=total_prof_sr / T,
                 yerr=total_err_sr / T,
                 color='r',
                 drawstyle='steps-mid')
    plt.errorbar(x=total_phase_sr_expo,
                 y=total_prof_sr_expo / T,
                 yerr=total_err_sr_expo / T,
                 color='b',
                 drawstyle='steps-mid')
    plt.legend(('Folded profile', 'Exposure-corrected'),
               loc='best',
               fontsize=12)
    plt.title(str(pathlib.Path(eventfile).name) +
              ', exposure-corrected (using Stingray fold_events)',
              fontsize=12)
    plt.xlabel('Phase', fontsize=12)
    plt.ylabel('Counts/s', fontsize=12)

    return total_phase_sr_expo, total_prof_sr_expo / T, total_err_sr_expo / T
Exemplo n.º 2
0
 def test_plot_profile(self):
     import matplotlib.pyplot as plt
     phase, prof, _ = fold_events(self.event_times,
                                  self.pulse_frequency)
     ax = plot_profile(phase, prof)
     plt.savefig('profile_direct.png')
     plt.close(plt.gcf())
Exemplo n.º 3
0
 def test_plot_profile_existing_ax(self):
     import matplotlib.pyplot as plt
     fig = plt.figure('Pulse profile')
     ax = plt.subplot()
     phase, prof, _ = fold_events(self.event_times,
                                  self.pulse_frequency, ax=ax)
     ax = plot_profile(phase, prof, ax=ax)
     plt.savefig('profile_existing_ax.png')
     plt.close(fig)
Exemplo n.º 4
0
 def test_plot_profile_existing_ax(self):
     import matplotlib.pyplot as plt
     fig = plt.figure('Pulse profile')
     ax = plt.subplot()
     phase, prof, _ = fold_events(self.event_times,
                                  self.pulse_frequency,
                                  ax=ax)
     ax = plot_profile(phase, prof, ax=ax)
     plt.savefig('profile_existing_ax.png')
     plt.close(fig)
Exemplo n.º 5
0
    def test_pulse_profile1(self):
        nbin = 16
        times = np.arange(0, 1, 1/nbin)

        period = 1
        ph, p, pe = fold_events(times, 1, nbin=nbin)

        np.testing.assert_array_almost_equal(p, np.ones(nbin))
        np.testing.assert_array_almost_equal(ph, np.arange(nbin)/nbin +
                                             0.5/nbin)
        np.testing.assert_array_almost_equal(pe, np.ones(nbin))
Exemplo n.º 6
0
    def test_pulse_profile2(self):
        nbin = 16
        dt = 1/nbin
        times = np.arange(0, 2, dt)
        gtis = np.array([[-0.5*dt, 2 + 0.5*dt]])

        period = 1
        ph, p, pe = fold_events(times, 1, nbin=nbin, expocorr=True, gtis=gtis)

        np.testing.assert_array_almost_equal(ph, np.arange(nbin)/nbin +
                                             0.5/nbin)
        np.testing.assert_array_almost_equal(p, 2 * np.ones(nbin))
        np.testing.assert_array_almost_equal(pe, 2**0.5 * np.ones(nbin))
Exemplo n.º 7
0
    def test_pulse_profile3(self):
        nbin = 16
        dt = 1 / nbin
        times = np.arange(0, 2 - dt, dt)
        gtis = np.array([[-0.5 * dt, 2 - dt]])

        ph, p, pe = fold_events(times, 1, nbin=nbin, expocorr=True, gtis=gtis)

        np.testing.assert_array_almost_equal(
            ph,
            np.arange(nbin) / nbin + 0.5 / nbin)
        np.testing.assert_array_almost_equal(p, 2 * np.ones(nbin))
        expected_err = 2**0.5 * np.ones(nbin)
        expected_err[-1] = 2  # Because of the change of exposure
        np.testing.assert_array_almost_equal(pe, expected_err)
Exemplo n.º 8
0
    def test_pulse_profile3(self):
        nbin = 16
        dt = 1/nbin
        times = np.arange(0, 2 - dt, dt)
        gtis = np.array([[-0.5*dt, 2 - dt]])

        ph, p, pe = fold_events(times, 1, nbin=nbin, expocorr=True,
                                gtis=gtis)

        np.testing.assert_array_almost_equal(ph, np.arange(nbin)/nbin +
                                             0.5/nbin)
        np.testing.assert_array_almost_equal(p, 2 * np.ones(nbin))
        expected_err = 2**0.5 * np.ones(nbin)
        expected_err[-1] = 2  # Because of the change of exposure
        np.testing.assert_array_almost_equal(pe, expected_err)
Exemplo n.º 9
0
def pulsar_events_mp(length,
                     period,
                     ctrate,
                     pulsed_fraction,
                     mean_obs,
                     bkg_ctrate,
                     detlev,
                     nbin=128):

    nustar_orb = 5808

    dt = period / 20
    # The total length of the time series should be the number of pointings times the time per orbit.
    # Add one orbit for buffer.
    N_orb = int(round(length / mean_obs, 0))
    tot_len = (N_orb + 1) * nustar_orb

    # The orbital period is 5808s. Every 5808s, a continuous observation with min_obs < length < max_obs begins
    start_t = numpy.multiply(
        numpy.arange(N_orb),
        numpy.random.normal(loc=nustar_orb, scale=60, size=N_orb))
    point_t = numpy.random.uniform(low=mean_obs - 500,
                                   high=mean_obs + 500,
                                   size=N_orb)
    end_t = numpy.add(start_t, point_t)

    times = numpy.arange(dt / 2, tot_len + dt / 2, dt)
    cont_lc = numpy.random.poisson(
        (ctrate *
         (1 + pulsed_fraction * numpy.cos(2 * numpy.pi / period * times)) *
         dt)) + numpy.random.poisson(bkg_ctrate * dt)

    lc = Lightcurve(time=times,
                    counts=cont_lc,
                    gti=numpy.column_stack((start_t, end_t)),
                    dt=dt)
    exposure = numpy.sum(point_t)
    events = EventList()
    events.gti = lc.gti
    events.simulate_times(lc)
    phase = numpy.arange(0, 1, 1 / nbin)
    zsq = z_n(phase,
              n=2,
              norm=fold_events(events.time, 1 / period, nbin=nbin)[1])
    detected = zsq > detlev
    return (detected, exposure)
Exemplo n.º 10
0
 def test_plot_profile(self):
     import matplotlib.pyplot as plt
     phase, prof, _ = fold_events(self.event_times, self.pulse_frequency)
     ax = plot_profile(phase, prof)
     plt.savefig('profile_direct.png')
     plt.close(plt.gcf())
Exemplo n.º 11
0
def get_TOAs_from_events(events, folding_length, *frequency_derivatives,
                         **kwargs):
    """Get TOAs of pulsation.

    Parameters
    ----------
    events : array-like
        event arrival times
    folding_length : float
        length of sub-intervals to fold
    *frequency_derivatives : floats
        pulse frequency, first derivative, second derivative, etc.

    Other parameters
    ----------------
    pepoch : float, default None
        Epoch of timing solution, in the same units as ev_times. If none, the
        first event time is used.
    mjdref : float, default None
        Reference MJD
    template : array-like, default None
        The pulse template
    nbin : int, default 16
        The number of bins in the profile (overridden by the dimension of the
        template)
    timfile : str, default 'out.tim'
        file to save the TOAs to (if PINT is installed)
    gti: [[g0_0, g0_1], [g1_0, g1_1], ...]
         Good time intervals. Defaults to None
    quick: bool
         If True, use a quicker fitting algorithms for TOAs. Defaults to False
    position: `astropy.SkyCoord` object
         Position of the object

    Returns
    -------
    toas : array-like
        list of times of arrival. If ``mjdref`` is specified, they are
        expressed as MJDs, otherwise in MET
    toa_err : array-like
        errorbars on TOAs, in the same units as TOAs.
    """
    import matplotlib.pyplot as plt
    template = kwargs['template'] if 'template' in kwargs else None
    mjdref = kwargs['mjdref'] if 'mjdref' in kwargs else None
    nbin = kwargs['nbin'] if 'nbin' in kwargs else 16
    pepoch = kwargs['pepoch'] if 'pepoch' in kwargs else None
    timfile = kwargs['timfile'] if 'timfile' in kwargs else 'out.tim'
    gti = kwargs['gti'] if 'gti' in kwargs else None
    label = kwargs['label'] if 'label' in kwargs else None
    quick = kwargs['quick'] if 'quick' in kwargs else False
    position = kwargs['position'] if 'position' in kwargs else None

    pepoch = assign_value_if_none(pepoch, events[0])
    gti = assign_value_if_none(gti, [[events[0], events[-1]]])
    # run exposure correction only if there are less than 1000 pulsations
    # in the interval
    length = gti.max() - gti.min()
    expocorr = folding_length < (1000 / frequency_derivatives[0])

    if template is not None:
        nbin = len(template)
        additional_phase = np.argmax(template) / nbin
    else:
        phase, profile, profile_err = \
            fold_events(copy.deepcopy(events), *frequency_derivatives,
                        ref_time=pepoch, gtis=copy.deepcopy(gti),
                        expocorr=expocorr, nbin=nbin)
        fit_pars_save, _, _ = \
            fit_profile_with_sinusoids(profile, profile_err, nperiods=1,
                                       baseline=True)
        template = std_fold_fit_func(fit_pars_save, phase)
        fig = plt.figure()
        plt.plot(phase, profile, drawstyle='steps-mid')
        plt.plot(phase, template, drawstyle='steps-mid')
        plt.savefig(timfile.replace('.tim', '') + '.png')
        plt.close(fig)
        # start template from highest bin!
        # template = np.roll(template, -np.argmax(template))
        template *= folding_length / length
        template_fine = std_fold_fit_func(fit_pars_save,
                                          np.arange(0, 1, 0.001))
        additional_phase = np.argmax(template_fine) / len(template_fine)

    starts = np.arange(gti[0, 0], gti[-1, 1], folding_length)

    toas = []
    toa_errs = []
    for start in show_progress(starts):
        stop = start + folding_length
        good = (events >= start) & (events < stop)
        events_tofold = events[good]
        if len(events_tofold) < nbin:
            continue
        gtis_tofold = \
            copy.deepcopy(gti[(gti[:, 0] < stop) & (gti[:, 1] > start)])
        gtis_tofold[0, 0] = start
        gtis_tofold[-1, 1] = stop

        local_f = frequency_derivatives[0]
        for i_f, f in enumerate(frequency_derivatives[1:]):
            local_f += 1 / np.math.factorial(i_f + 1) * (start -
                                                         pepoch)**(i_f + 1) * f

        fder = copy.deepcopy(list(frequency_derivatives))
        fder[0] = local_f
        phase, profile, profile_err = \
            fold_events(events_tofold, *fder,
                        ref_time=start, gtis=gtis_tofold,
                        expocorr=expocorr, nbin=nbin)

        # BAD!BAD!BAD!
        # [[Pay attention to time reference here.
        # We are folding wrt pepoch, and calculating TOAs wrt start]]

        toa, toaerr = \
            get_TOA(profile, 1/frequency_derivatives[0], start,
                    template=template, additional_phase=additional_phase,
                    quick=quick, debug=True)
        toas.append(toa)
        toa_errs.append(toaerr)

    toas, toa_errs = np.array(toas), np.array(toa_errs)

    if mjdref is not None:
        toas = toas / 86400 + mjdref
        toa_errs = toa_errs * 1e6
        if HAS_PINT:
            label = assign_value_if_none(label, 'hendrics')
            toa_list = _load_and_prepare_TOAs(toas, errs_us=toa_errs)
            # workaround until PR #368 is accepted in pint
            toa_list.table['clkcorr'] = 0
            toa_list.write_TOA_file(timfile, name=label, format='Tempo2')

        print('TOA(MJD)  TOAerr(us)')
    else:
        print('TOA(MET)  TOAerr(us)')

    for t, e in zip(toas, toa_errs):
        print(t, e)

    return toas, toa_errs
Exemplo n.º 12
0
    def fold_events(self,
                    *frequency_derivatives,
                    time_intervals=None,
                    pi_min=35,
                    pi_max=1909,
                    region_filter=False,
                    centroid=None,
                    radius=None,
                    ref_time=None,
                    nbin=64,
                    weights=1,
                    gtis=None,
                    expocorr=False,
                    weight_pos=False,
                    z_n=2):

        # Epoch folding without livetime correction.
        # Includes region and energy filtering, position weighting, and custom weighting.

        if region_filter or weight_pos:
            if centroid == None:
                centroid = self.centroid
            if radius == None:
                radius = self.radius
        if time_intervals == None:
            time_intervals = [[self.time[0], self.time[-1]]]
        if ref_time == None:
            ref_time = self.time[0]
        if gtis == None:
            gtis = self.gti

        time_mask = np.zeros(np.shape(self.time))
        if np.shape(time_intervals)[-1] != 2:
            print('The array of time intervals has the wrong shape')
            return None
        for interval in time_intervals:
            start_time, end_time = interval
            if (start_time < np.min(self.time)):
                print('Invalid start time')
                return None
            elif (end_time > np.max(self.time)):
                print('Invalid end time')
                return None
            time_mask = time_mask + ((self.time >= start_time) *
                                     (self.time <= end_time))
        time_mask = time_mask.astype(bool)
        pi_mask = ((self.pi > pi_min) * (self.pi < pi_max)).astype(bool)

        reg_mask = np.ones(np.shape(self.time)).astype(bool)
        p_weights = 1.0
        if region_filter:
            # if weight_pos:
            # print('Region filtering overrides position weighting.')
            reg_mask = (np.sqrt(
                np.square(self.x - centroid[0]) +
                np.square(self.y - centroid[1])) < radius).astype(bool)
        elif weight_pos:
            #             print('Make sure you have called set_xy_weights')
            p_weights = self.xy_weights[time_mask * pi_mask * reg_mask]


#             print([g.x_mean, g.y_mean, g.amplitude, g.x_stddev, g.y_stddev])

# The times to actually fold into a profile
        fold_times = self.time[time_mask * pi_mask * reg_mask]
        # The phase of each folded event
        fold_phases = plsr.pulse_phase(fold_times, *frequency_derivatives)

        phase_bins, profile, profile_err = plsr.fold_events(fold_times, *frequency_derivatives, ref_time=ref_time, \
                                                           nbin=nbin, weights=weights * p_weights, gtis=gtis, expocorr=expocorr)

        z_stat = plsr.z_n(fold_phases, n=z_n, norm=weights * p_weights)

        return phase_bins, profile, profile_err, z_stat
Exemplo n.º 13
0
    def fold_events_ltcorr(self, *frequency_derivatives, time_intervals= None, pi_min=35, pi_max=1909, \
                           region_filter=False, centroid = None, radius=None, ref_time=None, nbin = 64, weights  = 1, gtis = None, expocorr=False, weight_pos=False):
        # Do Epoch folding to look for pulsations while also correction for livetime variations. This is important for high count rates and high pulse fractions.
        # Includes region and energy filtering, position weighting, and custom weighting.

        if centroid == None:
            centroid = self.centroid
        if radius == None:
            radius = self.radius
        if time_intervals == None:
            time_intervals = [[self.time[0], self.time[-1]]]
        if ref_time == None:
            ref_time = self.time[0]
        if gtis == None:
            gtis = self.gti

        time_mask = np.zeros(np.shape(self.time))
        if np.shape(time_intervals)[-1] != 2:
            print('The array of time intervals has the wrong shape')
            return None
        for interval in time_intervals:
            start_time, end_time = interval
            if (start_time < np.min(self.time)):
                print('Invalid start time')
                return None
            elif (end_time > np.max(self.time)):
                print('Invalid end time')
                return None
            time_mask = time_mask + ((self.time >= start_time) *
                                     (self.time <= end_time))
        time_mask = time_mask.astype(bool)
        pi_mask = ((self.pi > pi_min) * (self.pi < pi_max)).astype(bool)

        reg_mask = np.ones(np.shape(self.time)).astype(bool)
        p_weights = 1.0
        if region_filter:
            if weight_pos:
                print('Region filtering overrides position weighting.')
            reg_mask = (np.sqrt(
                np.square(self.x - centroid[0]) +
                np.square(self.y - centroid[1])) < radius).astype(bool)
        elif weight_pos:
            #             print('Make sure you have called set_xy_weights')
            p_weights = self.xy_weights[time_mask * pi_mask * reg_mask]
#             print([g.x_mean, g.y_mean, g.amplitude, g.x_stddev, g.y_stddev])

# The times to actually fold into a profile
        fold_times = self.time[time_mask * pi_mask * reg_mask]
        # The phase of each folded event
        fold_phases = plsr.pulse_phase(fold_times, *frequency_derivatives)

        # We should use PRIOR from every event though
        temp_times = self.time[time_mask]
        temp_prior = self.prior[time_mask]
        temp_phases = plsr.pulse_phase(temp_times, *frequency_derivatives)

        #         print(frequency_derivatives)
        p_derivs = plsr.p_to_f(*frequency_derivatives)
        p_t = np.zeros(np.shape(temp_times))
        # Taylor expand P(t)
        for i in range(len(p_derivs)):
            p_t = p_t + (p_derivs[i] * np.power(temp_times - ref_time, i) /
                         scipy.special.factorial(i, exact=True))

        phase_bins, profile, profile_err = plsr.fold_events(fold_times, *frequency_derivatives, ref_time=ref_time, \
                                                           nbin=nbin, weights=weights * p_weights, gtis=gtis, expocorr=expocorr)
        livetime_profile = np.zeros(np.shape(profile))

        # During which phase bin did PRIOR start counting before each event?
        start_bins = np.floor(nbin * (temp_phases - (temp_prior / p_t)))
        # What phase bin is each event at?
        end_bins = np.floor(nbin * temp_phases)

        # Add 1 to every phase bin for which PRIOR was active.
        for i in range(len(start_bins)):
            start = start_bins[i]
            end = end_bins[i]
            #             print(start)
            # If PRIOR started counting in a previous cycle, add 1 to each full cycle and to the partial cycles
            if start < 0:
                for j in range(int(np.floor(np.abs(start) / nbin))):
                    livetime_profile = livetime_profile + 1
                livetime_profile[int(start %
                                     nbin):] = livetime_profile[int(start %
                                                                    nbin):] + 1
                livetime_profile[:int(end)] = livetime_profile[:int(end)] + 1

            # Else, just add 1 to the portion of this cycle during which PRIOR was counting
            else:
                livetime_profile[int(start):int(
                    end)] = livetime_profile[int(start):int(end)] + 1

        # livetime corresponding to the phase bin for each photon
        fold_lts = np.array(
            [livetime_profile[int(b)] for b in np.floor(nbin * fold_phases)])

        z_stat = plsr.z_n(fold_phases,
                          n=2,
                          norm=weights * p_weights * np.max(livetime_profile) /
                          fold_lts)
        #         livetime_profile = livetime_profile/np.max(livetime_profile)

        return phase_bins, profile, profile_err, livetime_profile, z_stat
Exemplo n.º 14
0
             color='b',
             drawstyle='steps-mid')
plt.title(str(pathlib.Path(eventfile_xmm).name) +
          ', exposure-corrected (using Lv2_phase)',
          fontsize=12)
plt.xlabel('Phase', fontsize=12)
plt.ylabel('Counts/s', fontsize=12)
plt.legend(('Folded profile', 'Exposure-corrected profile'),
           loc='best',
           fontsize=12)

##### Using stingray.pulse.pulsar's fold_events
phase_sr, prof_sr, err_sr = fold_events(times_xmm,
                                        1 / pb,
                                        freqdot,
                                        freqdotdot,
                                        gtis=np.array(gtis_conform),
                                        ref_time=times_xmm[0] - phaseoff * pb,
                                        nbin=nbins)
phase_sr_expo, prof_sr_expo, err_sr_expo = fold_events(
    times_xmm,
    1 / pb,
    freqdot,
    freqdotdot,
    gtis=np.array(gtis_conform),
    ref_time=times_xmm[0] - phaseoff * pb,
    expocorr=True,
    nbin=nbins)

total_phase_sr = np.array(list(phase_sr) + list(phase_sr + 1))
total_prof_sr = np.array(list(prof_sr) * 2)
Exemplo n.º 15
0
         for i in range(len(gtis))])  #exposure time

gtis_conform = []
for i in range(len(gtis)):
    gtis_conform.append([gtis[i][0],
                         gtis[i][1]])  #conform to the input that Stingray uses

freq = 622.12202499673376738
freqdot = -6.5114520166830696246e-15
freqdotdot = 0
nbins = 20

phase_sr, prof_sr, err_sr = fold_events(times,
                                        freq,
                                        freqdot,
                                        freqdotdot,
                                        gtis=np.array(gtis_conform),
                                        ref_time=times[0],
                                        nbin=nbins)
phase_sr_expo, prof_sr_expo, err_sr_expo = fold_events(
    times,
    freq,
    freqdot,
    freqdotdot,
    gtis=np.array(gtis_conform),
    ref_time=times[0],
    expocorr=True,
    nbin=nbins)

total_phase_sr = list(phase_sr) + list(phase_sr + 1)
total_prof_sr = list(prof_sr) * 2
 def profile(self):
     ph, profile, profile_err = fold_events(self.times,
                                            self.pulse_frequency,
                                            nbin=self.nbin,
                                            gtis=self.T_star_stop)
     return (ph, profile, profile_err)