Example #1
0
    def test_process_and_accuracy(self):
        # Checks that instantiating an observatory and phasing of
        # topocentric times works.  Verifies accuracy to the sub-mus
        # level by comparison with stored Tempo2 "Fermi plugin" results.

        modelin = pint.models.get_model(parfile)
        get_satellite_observatory("Fermi", ft2file)
        tl = load_Fermi_TOAs(eventfileraw, weightcolumn="PSRJ0030+0451")
        # ts = toa.TOAs(toalist=tl)
        ts = toa.get_TOAs_list(tl,
                               include_gps=False,
                               include_bipm=False,
                               planets=False,
                               ephem="DE405")
        iphss, phss = modelin.phase(ts, abs_phase=True)
        ph_pint = phss % 1

        with fits.open(eventfileraw) as f:
            ph_tempo2 = f[1].data.field("pulse_phase")

        dphi = ph_pint - ph_tempo2
        dphi[dphi < -0.1] += 1
        dphi[dphi > 0.1] -= 1
        resids_mus = dphi / modelin.F0.value * 1e6
        # if the "2 mus" problem exists, the scatter in these values will
        # be 4-5 mus, whereas if everything is OK it should be few 100 ns
        # require range in TOAs to be less than 200ns
        self.assertTrue((resids_mus.max() - resids_mus.min()) < 0.2)
        # require absolute phase to be within 500 ns; NB this relies on
        # GBT clock corrections since the TZR is referenced there
        self.assertTrue(max(abs(resids_mus)) < 0.5)
Example #2
0
    def get_TZR_toa(self, toas):
        """Get the TOAs class for the TZRMJD.

        We are treating the TZRMJD as a special TOA.
        Note that any observatory clock corrections will be applied
        to this TOA, as with any other TOA. This does not affect the
        value of the TZRMJD parmeter, however.
        """

        if self.tz_cache is not None:
            # This should also verify that the clkc_info is the same so it is valid.
            return self.tz_cache
        else:
            # NOTE: Using TZRMJD.quantity.jd[1,2] so that the time scale can be properly
            # set to the TZRSITE default timescale (e.g. UTC for TopoObs and TDB for SSB)
            TZR_toa = toa.TOA(
                (self.TZRMJD.quantity.jd1 - 2400000.5,
                 self.TZRMJD.quantity.jd2),
                obs=self.TZRSITE.value,
                freq=self.TZRFRQ.quantity,
            )
            clkc_info = toas.clock_corr_info
            tz = toa.get_TOAs_list(
                [TZR_toa],
                include_bipm=clkc_info["include_bipm"],
                include_gps=clkc_info["include_gps"],
                ephem=toas.ephem,
                planets=toas.planets,
            )
            self.tz_cache = tz
            return tz
Example #3
0
def test_generate_polycos(tmpdir, par_file, obs, obsfreq, nspan, ncoeff):
    output_polyco = tmpdir / "B1855_polyco_round_trip_from_par.dat"
    mjd_start, mjd_end = 55000.0, 55001.0

    model = get_model(str(par_file))

    p = Polycos()
    p.generate_polycos(model, mjd_start, mjd_end, obs, nspan, ncoeff, obsfreq)
    p.write_polyco_file(output_polyco)
    q = Polycos()
    q.read_polyco_file(output_polyco)

    mjds = np.linspace(mjd_start, mjd_end, 51)

    t = toa.get_TOAs_list(
        [toa.TOA(mjd, obs=obs, freq=obsfreq) for mjd in mjds],
        ephem=model.EPHEM.value)
    ph1 = p.eval_abs_phase(mjds)
    ph2 = q.eval_abs_phase(mjds)
    ph3 = model.phase(t, abs_phase=True)

    assert np.allclose(ph1.int.value[0], ph3.int.value[0])
    assert np.allclose(ph1.frac.value[0], ph3.frac.value[0])
    assert np.allclose(ph2.int.value[0], ph3.int.value[0])
    assert np.allclose(ph2.frac.value[0], ph3.frac.value[0])
Example #4
0
    def __call__(self, time):
        """Create list of TOAs for one or more times.

        Parameters
        ----------
        time : `~astropy.time.Time`
            Input time stamps.

        Returns
        -------
        toas : `~pint.toa.TOAs`
            Combining all TOAs.
        """
        # local import since we cannot count on PINT being present,
        # and doing it globally messes up sphinx.
        from pint import toa

        if time.scale == 'utc':
            time = time.replicate(format='pulsar_mjd')

        freq, _ = np.broadcast_arrays(self.frequency, time.jd1, subok=True)
        time = time._apply(np.broadcast_to, freq.shape)
        toa_list = []
        for t, f in zip(time.ravel(), freq.ravel()):
            # This format converting should be done by PINT in the future.
            toa_entry = toa.TOA(t, obs=self.observatory, freq=f)
            toa_list.append(toa_entry)

        toas = toa.get_TOAs_list(toa_list, **self.control_params)
        toas.shape = time.shape
        return toas
Example #5
0
def main(argv=None):
    parser = argparse.ArgumentParser(description="PINT tool for command-line barycentering calculations.")

    parser.add_argument("time",help="MJD (UTC, by default)")
    parser.add_argument("--timescale",default="utc",
        help="Time scale for MJD argument ('utc', 'tt', 'tdb'), default=utc")
    parser.add_argument("--format",
        help="Format for time argument ('mjd' or any astropy.Time format (e.g. 'isot'), see <http://docs.astropy.org/en/stable/time/#time-format>)",
        default="mjd")
    parser.add_argument("--freq",type=float,default=np.inf,
        help="Frequency to use, MHz")
    parser.add_argument("--obs",default="Geocenter",
        help="Observatory code (default = Geocenter)")
    parser.add_argument("--parfile",help="par file to read model from",default=None)
    parser.add_argument("--ra",
        help="RA to use (e.g. '12h22m33.2s' if not read from par file)")
    parser.add_argument("--dec",
        help="Decl. to use (e.g. '19d21m44.2s' if not read from par file)")
    parser.add_argument("--dm",
        help="DM to use (if not read from par file)",type=float,default=0.0)
    parser.add_argument("--ephem",default="DE421",help="Ephemeris to use")
    parser.add_argument("--use_gps",default=False,action='store_true',help="Apply GPS to UTC clock corrections")
    parser.add_argument("--use_bipm",default=False,action='store_true',help="Use TT(BIPM) instead of TT(TAI)")


    args = parser.parse_args(argv)

    if args.format in ("mjd","jd", "unix"):
        # These formats require conversion from string to longdouble first
        fmt = args.format
        # Never allow format == 'mjd' because it fails when scale is 'utc'
        # Change 'mjd' to 'pulsar_mjd' to deal with this.
        if fmt == "mjd":
            fmt = "pulsar_mjd"
        t = Time(np.longdouble(args.time),scale=args.timescale,format=fmt,
            precision=9)
        print(t)
    else:
        t = Time(args.time,scale=args.timescale,format=args.format, precision=9)
    log.debug(t.iso)

    t = toa.TOA(t,freq=args.freq,obs=args.obs)
    # Build TOAs and compute TDBs and positions from ephemeris
    ts = toa.get_TOAs_list([t],ephem=args.ephem, include_bipm=args.use_bipm,
        include_gps=args.use_gps, planets=False)

    if args.parfile is not None:
        m=pint.models.get_model(args.parfile)
    else:
        # Construct model by hand
        m=pint.models.StandardTimingModel
        # Should check if 12:13:14.2 syntax is used and support that as well!
        m.RAJ.quantity = Angle(args.ra)
        m.DECJ.quantity = Angle(args.dec)
        m.DM.quantity = args.dm*u.parsec/u.cm**3

    tdbtimes = m.get_barycentric_toas(ts)

    print("{0:.16f}".format(tdbtimes[0].value))
    return
Example #6
0
def get_barycentric_correction(orbfile, parfile, dt=5, ephem='DE421'):
    no = SatelliteObs(name="NuSTAR", FPorbname=orbfile, tt2tdb_mode="pint")
    with fits.open(orbfile) as hdul:
        mjdref = high_precision_keyword_read(hdul[1].header, 'MJDREF')

    mjds = np.arange(no.X.x[1], no.X.x[-2], dt / 86400)
    mets = (mjds - mjdref) * 86400

    obs, scale = 'nustar', "tt"
    toalist = [None] * len(mjds)

    for i in range(len(mjds)):
        # Create TOA list
        toalist[i] = toa.TOA(mjds[i], obs=obs, scale=scale)

    if parfile is not None and os.path.exists(parfile):
        modelin = pint.models.get_model(parfile)
    else:
        modelin = get_dummy_parfile_for_position(orbfile)

    ts = toa.get_TOAs_list(
        toalist,
        ephem=ephem,
        include_bipm=False,
        include_gps=False,
        planets=False,
        tdb_method='default',
    )
    bats = modelin.get_barycentric_toas(ts)
    return interp1d(mets, (bats.value - mjds) * 86400,
                    assume_sorted=True,
                    bounds_error=False,
                    fill_value='extrapolate',
                    kind='quadratic')
Example #7
0
def test_toas_read_list():
    x = toa.get_TOAs("test1.tim")
    toas, commands = toa.read_toa_file("test1.tim")
    y = toa.get_TOAs_list(toas,
                          commands=commands,
                          filename=x.filename,
                          hashes=x.hashes)
    assert x == y
Example #8
0
    def _gen_polyco(self, parfile, MJD_start, segLength = 60.0, ncoeff = 15, \
                       maxha=12.0, method="TEMPO", numNodes=20, usePINT = True):
        """
        This will be a convenience function to generate polycos and subsequent parameters to replace the values in a 
        PSRFITS file header. The default way to do this will be to use PINT (usePINT = True), with other methods
        currently unsupported. The input values are:
        parfile [string] : path to par file used to generate the polycos. The observing frequency, and observatory will 
                            come from the par file
        MJD_start [float] : Start MJD of the polyco. Should start no later than the beginning of the observation
        segLength [float] : Length in minutes of the range covered by the polycos generated. Default is 60 minutes
        ncoeff [int] : number of polyco coeffeicients to generate. Default is 15, the same as in the PSRFITS file
        maxha [float] : max hour angle needed by PINT. Default is 12.0
        method [string] : Method PINT uses to generate the polyco. Currently only TEMPO is supported.
        numNodes [int] : Number of nodes PINT will use to fit the polycos. Must be larger than ncoeff
        usePINT [bool] : Method used to generate polycos. Currently only PINT is supported.
        """
        if usePINT:
            # Define dictionary to put parameters into
            polyco_dict = {'NSPAN': segLength, 'NCOEF': ncoeff}
            # load parfile to PINT model object
            m = models.get_model(parfile)
            # Determine MJD_end based on segLength
            MJD_end = MJD_start + np.double(
                make_quant(segLength, 'min').to('day').value)  # MJD
            # Determine obseratory and observing frequency
            obsFreq = m.TZRFRQ.value  # in MHz
            polyco_dict['REF_FREQ'] = obsFreq
            obs = m.TZRSITE.value  # string
            polyco_dict['NSITE'] = obs.encode(
                'utf-8')  # observatory code needs to be in binary
            # Get pulsar frequency
            polyco_dict['REF_F0'] = m.F0.value
            # get the polycos
            pcs = polycos.Polycos()
            pcs.generate_polycos(m, MJD_start, MJD_end, obs, segLength, ncoeff, obsFreq, maxha=12.0, method="TEMPO", \
                                     numNodes=20)
            coeffs = pcs.polycoTable['entry'][-1].coeffs
            polyco_dict['COEFF'] = coeffs
            # Now we need to determine the reference MJD, and phase
            REF_MJD = np.double(pcs.polycoTable['tmid'][-1])
            polyco_dict['REF_MJD'] = REF_MJD
            # Now find the phase difference
            tmid_toa = toa.get_TOAs_list(
                [toa.TOA(REF_MJD, obs=obs, freq=obsFreq)])
            ref_phase = m.phase(tmid_toa)
            # Need to force positive value
            if ref_phase.frac.value[0] < 0.0:
                ref_frac_phase = 1.0 - abs(ref_phase.frac.value[0])
            else:
                ref_frac_phase = ref_phase.frac.value[0]
            polyco_dict['REF_PHS'] = ref_frac_phase

            return polyco_dict

        else:
            print("Only PINT is currently supported for generating polycos")
            raise NotImplementedError()
Example #9
0
 def test_roundtrip_bary_toa_Tempo2format(self):
     # Create a barycentric TOA
     t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="tdb")
     t1 = toa.TOA(t1time, obs="Barycenter", freq=0.0)
     ts = toa.get_TOAs_list([t1], ephem="DE421")
     ts.write_TOA_file("testbary.tim", format="Tempo2")
     ts2 = toa.get_TOAs("testbary.tim")
     print(ts.table, ts2.table)
     assert np.abs(ts.table["mjd"][0] - ts2.table["mjd"][0]) < 1.0e-15 * u.d
     assert np.abs(ts.table["tdb"][0] - ts2.table["tdb"][0]) < 1.0e-15 * u.d
Example #10
0
 def test_roundtrip_topo_toa_TEMPOformat(self):
     # Create a barycentric TOA
     t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="utc")
     t1 = toa.TOA(t1time, obs="gbt", freq=0.0)
     ts = toa.get_TOAs_list([t1], ephem="DE421")
     ts.write_TOA_file("testtopot1.tim", format="TEMPO")
     ts2 = toa.get_TOAs("testtopot1.tim")
     print(ts.table, ts2.table)
     assert ts.table["mjd"][0] - ts2.table["mjd"][0] < 1.0e-15
     assert ts.table["tdb"][0] - ts2.table["tdb"][0] < 1.0e-15
Example #11
0
    def __call__(self, time):
        """Create list of TOAs for one or more times.

        Parameters
        ----------
        time : `~astropy.time.Time`
            Input time stamps.
        """
        toa_list = make_toa_list(time, self.observatory, self.frequency)
        return toa.get_TOAs_list(toa_list, **self.control_params)
Example #12
0
def test_roundtrip_topo_toa_TEMPOformat(tmpdir):
    # Create a barycentric TOA
    t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="utc")
    t1 = toa.TOA(t1time, obs="gbt", freq=0.0)
    ts = toa.get_TOAs_list([t1], ephem="DE421")
    outnm = os.path.join(tmpdir, "testtopot1.tim")
    ts.write_TOA_file(outnm, format="TEMPO")
    ts2 = toa.get_TOAs(outnm)
    assert np.abs(ts.table["mjd"][0] - ts2.table["mjd"][0]) < 1.0e-15 * u.d
    assert np.abs(ts.table["tdb"][0] - ts2.table["tdb"][0]) < 1.0e-15 * u.d
Example #13
0
 def get_TZR_toa(self, toas):
     """ Get the TOAs class for the TZRMJD. We are treating the TZRMJD as a
         special TOA.
     """
     TZR_toa = toa.TOA(self.TZRMJD.quantity,
                       obs=self.TZRSITE.value,
                       freq=self.TZRFRQ.quantity)
     clkc_info = toas.clock_corr_info
     tz = toa.get_TOAs_list([
         TZR_toa,
     ],
                            include_bipm=clkc_info['include_bipm'],
                            include_gps=clkc_info['include_gps'],
                            ephem=toas.ephem,
                            planets=toas.planets)
     return tz
Example #14
0
    def get_TZR_toa(self, toas):
        """Get the TOAs class for the TZRMJD.

        We are treating the TZRMJD as a special TOA.
        Note that any observatory clock corrections will be applied
        to this TOA, as with any other TOA. This does not affect the
        value of the TZRMJD parmeter, however.
        """
        clkc_info = toas.clock_corr_info
        # If we have cached the TZR TOA and all the TZR* and clock info has not changed, then don't rebuild it
        if self.tz_cache is not None:
            if (self.tz_clkc_info["include_bipm"] == clkc_info["include_bipm"]
                    and self.tz_clkc_info["include_gps"]
                    == clkc_info["include_gps"]
                    and self.tz_planets == toas.planets
                    and self.tz_ephem == toas.ephem and self.tz_hash == hash(
                        (self.TZRMJD.value, self.TZRSITE.value,
                         self.TZRFRQ.value))):
                return self.tz_cache
        # Otherwise we have to build the TOA and apply clock corrections
        # NOTE: Using TZRMJD.quantity.jd[1,2] so that the time scale can be properly
        # set to the TZRSITE default timescale (e.g. UTC for TopoObs and TDB for SSB)
        log.debug(
            "Creating and dealing with the single TZR_toa for absolute phase")
        TZR_toa = toa.TOA(
            (self.TZRMJD.quantity.jd1 - 2400000.5, self.TZRMJD.quantity.jd2),
            obs=self.TZRSITE.value,
            freq=self.TZRFRQ.quantity,
        )
        tz = toa.get_TOAs_list(
            [TZR_toa],
            include_bipm=clkc_info["include_bipm"],
            include_gps=clkc_info["include_gps"],
            ephem=toas.ephem,
            planets=toas.planets,
        )
        log.debug("Done with TZR_toa")
        self.tz_cache = tz
        self.tz_hash = hash(
            (self.TZRMJD.value, self.TZRSITE.value, self.TZRFRQ.value))
        self.tz_clkc_info = clkc_info
        self.tz_planets = toas.planets
        self.tz_ephem = toas.ephem
        return tz
Example #15
0
 def get_TZR_toa(self, toas):
     """ Get the TOAs class for the TZRMJD. We are treating the TZRMJD as a
         special TOA.
     """
     # NOTE: Using TZRMJD.quantity.jd[1,2] so that the time scale can be properly
     # set to the TZRSITE default timescale (e.g. UTC for TopoObs and TDB for SSB)
     TZR_toa = toa.TOA(
         (self.TZRMJD.quantity.jd1 - 2400000.5, self.TZRMJD.quantity.jd2),
         obs=self.TZRSITE.value,
         freq=self.TZRFRQ.quantity)
     clkc_info = toas.clock_corr_info
     tz = toa.get_TOAs_list([
         TZR_toa,
     ],
                            include_bipm=clkc_info['include_bipm'],
                            include_gps=clkc_info['include_gps'],
                            ephem=toas.ephem,
                            planets=toas.planets)
     return tz
Example #16
0
    def change_pepoch(self, new_epoch, toas=None, delay=None):
        """Move PEPOCH to a new time and change the related paramters.

        Parameters
        ----------
        new_epoch: float or `astropy.Time` object
            The new PEPOCH value.
        toas: `toa` object, optional.
            If current PEPOCH is not provided, the first pulsar frame toa will
            be treated as PEPOCH.
        delay: `numpy.array` object
            If current PEPOCH is not provided, it is required for computing the
            first pulsar frame toa.
        """
        if isinstance(new_epoch, Time):
            new_epoch = Time(new_epoch, scale='tdb', precision=9)
        else:
            new_epoch = Time(new_epoch, scale='tdb', format='mjd', precision=9)
        # make new_epoch a toa for delay calculation.
        new_epoch_toa = toa.get_TOAs_list([
            toa.TOA(new_epoch),
        ],
                                          ephem=toas.ephem)

        if self.PEPOCH.value is None:
            if toas is None or delay is None:
                raise ValueError(
                    "`PEPOCH` is not in the model, thus, 'toa' and"
                    " 'delay' shoule be givne.")
            tbl = toas.table
            phsepoch_ld = time_to_longdouble(tbl['tdb'][0] - delay[0])
        else:
            phsepoch_ld = time_to_longdouble(self.PEPOCH.quantity)
        dt = ((time_to_longdouble(new_epoch) - phsepoch_ld) * u.day)
        fterms = [0.0 * u.Unit("")] + self.get_spin_terms()
        # rescale the fterms
        for n in range(len(fterms) - 1):
            f_par = getattr(self, 'F{}'.format(n))
            f_par.value = taylor_horner_deriv(dt.to(u.second),
                                              fterms,
                                              deriv_order=n + 1)
        self.PEPOCH.value = new_epoch
Example #17
0
def test_commenting_toas(tmpdir):
    # Create a barycentric TOA
    t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="utc")
    t1 = toa.TOA(t1time, obs="gbt", freq=0.0)
    t2 = toa.TOA(t1time, obs="gbt", freq=0.0)
    ts = toa.get_TOAs_list([t1, t2], ephem="DE421")
    assert ts.ntoas == 2
    outnm = os.path.join(tmpdir, "testtopo.tim")
    ts.write_TOA_file(outnm)
    ts2 = toa.get_TOAs(outnm)
    assert ts2.ntoas == 2  # none should be commented
    ts.table[0]["flags"]["cut"] = "do_not_like"  # cut flag
    ts.table[1]["flags"]["ignore"] = str(1)  # ignore flag
    ts.write_TOA_file(outnm)
    ts3 = toa.get_TOAs(outnm)  # defaut is to not comment
    assert ts3.ntoas == 2  # none should be commented by default
    ts.write_TOA_file(outnm, commentflag="cut")
    ts4 = toa.get_TOAs(outnm)
    assert ts4.ntoas == 1  # one should be commented
    ts.write_TOA_file(outnm, commentflag="ignore")
    ts5 = toa.get_TOAs(outnm)
    assert ts5.ntoas == 1  # one should be commented
Example #18
0
    def test_roundtrip_topo_toa_TEMPOformat(self):
        # Create a barycentric TOA
        t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="utc")
        t1 = toa.TOA(t1time, obs="gbt", freq=0.0)
        ts = toa.get_TOAs_list([t1], ephem="DE421")
        ts.write_TOA_file("testtopot1.tim", format="TEMPO")
        ts2 = toa.get_TOAs("testtopot1.tim")
        print(ts.table, ts2.table)
        assert np.abs(ts.table["mjd"][0] - ts2.table["mjd"][0]) < 1.0e-15 * u.d
        assert np.abs(ts.table["tdb"][0] - ts2.table["tdb"][0]) < 1.0e-15 * u.d

        # Comment out because TEMPO2 distro doesn't include gmrt2gps.clk so far
        # def test_roundtrip_gmrt_toa_Tempo2format(self):
        #     if os.getenv("TEMPO2") is None:
        #         pytest.skip("TEMPO2 evnironment variable is not set, can't run this test")
        #     # Create a barycentric TOA
        #     t1time = Time(58534.0, 0.0928602471130208, format="mjd", scale="utc")
        #     t1 = toa.TOA(t1time, obs="gmrt", freq=0.0)
        #     ts = toa.get_TOAs_list([t1], ephem="DE421")
        #     ts.write_TOA_file("testgmrt.tim", format="Tempo2")
        #     ts2 = toa.get_TOAs("testgmrt.tim")
        #     print(ts.table, ts2.table)
        assert np.abs(ts.table["mjd"][0] - ts2.table["mjd"][0]) < 1.0e-15 * u.d
        assert np.abs(ts.table["tdb"][0] - ts2.table["tdb"][0]) < 1.0e-15 * u.d
Example #19
0
    def generate_polycos(self,
                         model,
                         mjdStart,
                         mjdEnd,
                         obs,
                         segLength,
                         ncoeff,
                         obsFreq,
                         maxha,
                         method="TEMPO",
                         numNodes=20):
        """
        Generate the polyco file data file. 

        Parameters
        ---------
        model : TimingModel
            TimingModel for generate the Polycos with parameters
            setup.

        mjdStart : float / nump longdouble
            Start time of polycos in mjd

        mjdEnd : float / nump longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength : 
            Length of polyco segement [unit: minutes]

        ncoeff : 
            number of coefficents

        obsFreq : 
            observing frequency

        maxha :
            Maximum hour angle

        method : sting optional ['TEMPO','TEMPO2',...] Default TEMPO
            Method to generate polycos. Now it is only support the TEMPO method. 

        numNodes : int optional. Default 20
            Number of nodes for fitting. It can not be less then the number of 
            coefficents.
        Return 
        ---------

        A polyco table. 


        """
        mjdStart = np.longdouble(mjdStart) * u.day
        mjdEnd = np.longdouble(mjdEnd) * u.day
        timeLength = mjdEnd - mjdStart
        segLength = np.longdouble(segLength) * u.min
        obsFreq = float(obsFreq)
        month = [
            'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
            'Oct', 'Nov', 'Dec'
        ]
        # Alocate memery
        coeffs = np.longdouble(np.zeros(ncoeff))
        entryList = []
        entryIntvl = np.arange(mjdStart.value, mjdEnd.value,
                               segLength.to('day').value)
        if entryIntvl[-1] < mjdEnd.value:
            entryIntvl = np.append(entryIntvl, mjdEnd.value)

        # Make sure the number of nodes is bigger then number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff + 1

    # generate the ploynomial coefficents
        if method == "TEMPO":
            # Using tempo1 method to create polycos
            for i in range(len(entryIntvl) - 1):
                tStart = entryIntvl[i]
                tStop = entryIntvl[i + 1]
                nodes = np.linspace(tStart, tStop, numNodes)
                tmid = ((tStart + tStop) / 2.0) * u.day
                toaMid = toa.get_TOAs_list([
                    toa.TOA((np.modf(tmid.value)[1], np.modf(tmid.value)[0]),
                            obs=obs,
                            freq=obsFreq),
                ])
                refPhase = model.phase(toaMid.table)
                mjdSpan = ((tStop - tStart) * u.day).to('min')
                # Create node toas(Time sample using TOA class)
                toaList = [
                    toa.TOA((np.modf(toaNode)[1], np.modf(toaNode)[0]),
                            obs=obs,
                            freq=obsFreq) for toaNode in nodes
                ]

                toas = toa.get_TOAs_list(toaList)

                ph = model.phase(toas.table)
                dt = (nodes * u.day - tmid).to('min')  # Use constant
                rdcPhase = ph - refPhase
                rdcPhase = rdcPhase.int - dt.value * model.F0.value * 60.0 + rdcPhase.frac
                dtd = dt.value.astype(float)  # Trancate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd, rdcPhased, ncoeff - 1)
                coeffs = coeffs[::-1]
                midTime = at.Time(int(tmid.value),
                                  np.modf(tmid.value)[0],
                                  format='mjd',
                                  scale='utc')
                date, hms = midTime.iso.split()
                yy, mm, dd = date.split('-')
                date = dd + '-' + month[int(mm) - 1] + '-' + yy[2:4]
                hms = hms.replace(':', "")
                entry = polycoEntry(tmid.value,
                                    mjdSpan.to('day').value, refPhase.int,
                                    refPhase.frac, model.F0.value, ncoeff,
                                    coeffs, obs)
                entryList.append(
                    (model.PSR.value, date, hms, tmid.value, model.DM.value,
                     0.0, 0.0, 0.0, obsFreq, entry))

            pTable = table.Table(rows=entryList,
                                 names=('psr', 'date', 'utc', 'tmid', 'dm',
                                        'dopper', 'logrms', 'binary_phase',
                                        'obsfreq', 'entry'),
                                 meta={'name': 'Ployco Data Table'})
            self.polycoTable = pTable

        else:
            #  Reading from an old polycofile
            pass
Example #20
0
def main(argv=None):
    import argparse
    parser = argparse.ArgumentParser(
        description=
        "Use PINT to compute event phases and make plots of photon event files."
    )
    parser.add_argument(
        "eventfile",
        help=
        "Photon event FITS file name (e.g. from NICER, RXTE, XMM, Chandra).")
    parser.add_argument("parfile", help="par file to construct model from")
    parser.add_argument("--orbfile", help="Name of orbit file", default=None)
    parser.add_argument("--maxMJD",
                        help="Maximum MJD to include in analysis",
                        default=None)
    parser.add_argument("--plotfile",
                        help="Output figure file name (default=None)",
                        default=None)
    parser.add_argument("--addphase",
                        help="Write FITS file with added phase column",
                        default=False,
                        action='store_true')
    parser.add_argument(
        "--absphase",
        help="Write FITS file with integral portion of pulse phase (ABS_PHASE)",
        default=False,
        action='store_true')
    parser.add_argument(
        "--barytime",
        help=
        "Write FITS file with a column containing the barycentric time as double precision MJD.",
        default=False,
        action='store_true')
    parser.add_argument(
        "--outfile",
        help="Output FITS file name (default=same as eventfile)",
        default=None)
    parser.add_argument("--ephem",
                        help="Planetary ephemeris to use (default=DE421)",
                        default="DE421")
    parser.add_argument(
        '--tdbmethod',
        help="Method for computing TT to TDB (default=astropy)",
        default="default")
    parser.add_argument("--plot",
                        help="Show phaseogram plot.",
                        action='store_true',
                        default=False)
    parser.add_argument("--use_gps",
                        default=False,
                        action='store_true',
                        help="Apply GPS to UTC clock corrections")
    parser.add_argument("--use_bipm",
                        default=False,
                        action='store_true',
                        help="Use TT(BIPM) instead of TT(TAI)")
    #    parser.add_argument("--fix",help="Apply 1.0 second offset for NICER", action='store_true', default=False)
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # If plotfile is specified, that implies plot
    if args.plotfile is not None:
        args.plot = True

    # Read event file header to figure out what instrument is is from
    hdr = pyfits.getheader(args.eventfile, ext=1)

    log.info('Event file TELESCOPE = {0}, INSTRUMENT = {1}'.format(
        hdr['TELESCOP'], hdr['INSTRUME']))
    if hdr['TELESCOP'] == 'NICER':
        # Instantiate NICERObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            log.info('Setting up NICER observatory')
            NICERObs(name='NICER', FPorbname=args.orbfile, tt2tdb_mode='pint')
        # Read event file and return list of TOA objects
        try:
            tl = load_NICER_TOAs(args.eventfile)
        except KeyError:
            log.error(
                "Observatory not recognized.  This probably means you need to provide an orbit file or barycenter the event file."
            )
            sys.exit(1)
    elif hdr['TELESCOP'] == 'XTE':
        # Instantiate RXTEObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            # Determine what observatory type is.
            log.info('Setting up RXTE observatory')
            RXTEObs(name='RXTE', FPorbname=args.orbfile, tt2tdb_mode='pint')
        # Read event file and return list of TOA objects
        tl = load_RXTE_TOAs(args.eventfile)
    elif hdr['TELESCOP'].startswith('XMM'):
        # Not loading orbit file here, since that is not yet supported.
        tl = load_XMM_TOAs(args.eventfile)
    elif hdr['TELESCOP'].startswith('NuSTAR'):
        # Not loading orbit file here, since that is not yet supported.
        tl = load_NuSTAR_TOAs(args.eventfile)
    else:
        log.error(
            "FITS file not recognized, TELESCOPE = {0}, INSTRUMENT = {1}".
            format(hdr['TELESCOP'], hdr['INSTRUME']))
        sys.exit(1)

    # Now convert to TOAs object and compute TDBs and posvels
    if len(tl) == 0:
        log.error("No TOAs, exiting!")
        sys.exit(0)

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    use_planets = False
    if 'PLANET_SHAPIRO' in modelin.params:
        if modelin.PLANET_SHAPIRO.value:
            use_planets = True

    # Discard events outside of MJD range
    if args.maxMJD is not None:
        tlnew = []
        print("pre len : ", len(tl))
        maxT = Time(float(args.maxMJD), format='mjd')
        print("maxT : ", maxT)
        for tt in tl:
            if tt.mjd < maxT:
                tlnew.append(tt)
        tl = tlnew
        print("post len : ", len(tlnew))

    ts = toa.get_TOAs_list(tl,
                           ephem=args.ephem,
                           include_bipm=args.use_bipm,
                           include_gps=args.use_gps,
                           planets=use_planets,
                           tdb_method=args.tdbmethod)
    ts.filename = args.eventfile
    #    if args.fix:
    #        ts.adjust_TOAs(TimeDelta(np.ones(len(ts.table))*-1.0*u.s,scale='tt'))

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(), mjds.max())

    # Compute model phase for each TOA
    iphss, phss = modelin.phase(ts, abs_phase=True)
    # ensure all postive
    negmask = phss < 0.0 * u.cycle
    phases = np.where(negmask, phss + 1.0 * u.cycle, phss)
    h = float(hm(phases))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))
    if args.plot:
        phaseogram_binned(mjds, phases, bins=100, plotfile=args.plotfile)

    if args.addphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile, mode='update')
        else:
            hdulist = pyfits.open(args.eventfile)
        if len(hdulist[1].data) != len(phases):
            raise RuntimeError(
                'Mismatch between length of FITS table ({0}) and length of phase array ({1})!'
                .format(len(hdulist[1].data), len(phases)))
        data_to_add = {'PULSE_PHASE': [phases, 'D']}
        if args.absphase:
            data_to_add['ABS_PHASE'] = [iphss - negmask * u.cycle, 'K']
        if args.barytime:
            bats = modelin.get_barycentric_toas(ts)
            data_to_add['BARY_TIME'] = [bats, 'D']
        datacol = []
        for key in data_to_add.keys():
            if key in hdulist[1].columns.names:
                log.info('Found existing %s column, overwriting...' % key)
                # Overwrite values in existing Column
                hdulist[1].data[key] = data_to_add[key][0]
            else:
                # Construct and append new column, preserving HDU header and name
                log.info('Adding new %s column.' % key)
                datacol.append(
                    pyfits.ColDefs([
                        pyfits.Column(name=key,
                                      format=data_to_add[key][1],
                                      array=data_to_add[key][0])
                    ]))
        if len(datacol) > 0:
            cols = hdulist[1].columns
            for c in datacol:
                cols = cols + c
            bt = pyfits.BinTableHDU.from_columns(cols,
                                                 header=hdulist[1].header,
                                                 name=hdulist[1].name)
            hdulist[1] = bt
        if args.outfile is None:
            # Overwrite the existing file
            log.info('Overwriting existing FITS file ' + args.eventfile)
            hdulist.flush(verbose=True, output_verify='warn')
        else:
            # Write to new output file
            log.info('Writing output FITS file ' + args.outfile)
            hdulist.writeto(args.outfile,
                            overwrite=True,
                            checksum=True,
                            output_verify='warn')
Example #21
0
    def d_phase_d_toa(self, toas, time_intval = 60 ,method = None,
                      num_sample = 20, order = 11):
        """Return the derivative of phase wrt TOA
            time_intval: is in seconds
            method: with finite difference and chebyshev interpolation


        """
        d_phase_d_toa = np.zeros(len(toas))

        if method is None or "FDM":
        # Using finite difference to calculate the derivitve
            dt = np.longdouble(time_intval)/np.longdouble(num_sample)
            num_sample = int(num_sample)/2*2+1

            for i,singal_toa in enumerate(toas):
                toa_utc_ld = utils.time_to_longdouble(singal_toa['mjd'])
                # Resample the toa points
                domain = (toa_utc_ld-time_intval/2.0,toa_utc_ld+time_intval/2.0)
                sample = np.linspace(domain[0],domain[1],num_sample)

                toa_list = []
                for sample_time in sample:
                    toa_list.append(toa.TOA((np.modf(sample_time)[1],
                                np.modf(sample_time)[0]),obs = singal_toa['obs'],
                                freq = singal_toa['freq']))

                sample_toalist = toa.get_TOAs_list(toa_list)
                ph = self.phase(sample_toalist.table)
                p = ph.int-ph.int.min()+ph.frac
                p = np.array(p,dtype='float64')
                # Reduce the value of samples in order to use double precision
                reduce_samepl = np.array((sample-sample.min())*86400.0,dtype = 'float64')
                dx = np.gradient(reduce_samepl)
                dp = np.gradient(p-p.mean(),dx)
                d_phase_d_toa[i] = dp[num_sample/2]

        if method is "chebyshev":
        # Using chebyshev interpolation to calculate the

            for i,singal_toa in enumerate(toas):
                # Have more sample point around toa
                toa_utc_ld = utils.time_to_longdouble(singal_toa['mjd'])
                domain = (toa_utc_ld-time_intval/2.0,toa_utc_ld+time_intval/2.0)
                sample = np.linspace(domain[0],domain[1],num_sample)

                toa_list = []
                for sample_time in sample:
                    toa_list.append(toa.TOA((np.modf(sample_time)[1],
                                np.modf(sample_time)[0]),obs = singal_toa['obs'],
                                freq = singal_toa['freq']))

                sample_toalist = toa.get_TOAs_list(toa_list)
                # Calculate phase
                ph = self.phase(sample_toalist.table)
                p = ph.int-ph.int.min()+ph.frac
                p = np.array(p,dtype='float64')
                # reduce the phase value to use double precision
                reduce_samepl = np.array((sample-sample.min())*86400.0,dtype = 'float64')
                coeff = np.polynomial.chebyshev.chebfit(reduce_samepl, p,order)
                dcoeff = np.polynomial.chebyshev.chebder(coeff)
                dy =  np.polynomial.chebyshev.chebval(reduce_samepl,dcoeff)
                d_phase_d_toa[i] = dy[num_sample/2]

        return d_phase_d_toa
Example #22
0
def main(argv=None):
    import argparse

    parser = argparse.ArgumentParser(
        description=
        "Use PINT to compute event phases and make plots of photon event files."
    )
    parser.add_argument(
        "eventfile",
        help=
        "Photon event FITS file name (e.g. from NICER, RXTE, XMM, Chandra).",
    )
    parser.add_argument("parfile", help="par file to construct model from")
    parser.add_argument("--orbfile", help="Name of orbit file", default=None)
    parser.add_argument("--maxMJD",
                        help="Maximum MJD to include in analysis",
                        default=None)
    parser.add_argument("--plotfile",
                        help="Output figure file name (default=None)",
                        default=None)
    parser.add_argument(
        "--addphase",
        help="Write FITS file with added phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--addorbphase",
        help="Write FITS file with added orbital phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--absphase",
        help="Write FITS file with integral portion of pulse phase (ABS_PHASE)",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--barytime",
        help=
        "Write FITS file with a column containing the barycentric time as double precision MJD.",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--outfile",
        help="Output FITS file name (default=same as eventfile)",
        default=None,
    )
    parser.add_argument("--ephem",
                        help="Planetary ephemeris to use (default=DE421)",
                        default="DE421")
    parser.add_argument(
        "--tdbmethod",
        help="Method for computing TT to TDB (default=astropy)",
        default="default",
    )
    parser.add_argument("--plot",
                        help="Show phaseogram plot.",
                        action="store_true",
                        default=False)
    parser.add_argument(
        "--use_gps",
        default=False,
        action="store_true",
        help="Apply GPS to UTC clock corrections",
    )
    parser.add_argument(
        "--use_bipm",
        default=False,
        action="store_true",
        help="Use TT(BIPM) instead of TT(TAI)",
    )
    #    parser.add_argument("--fix",help="Apply 1.0 second offset for NICER", action='store_true', default=False)
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # If plotfile is specified, that implies plot
    if args.plotfile is not None:
        args.plot = True

    # Read event file header to figure out what instrument is is from
    hdr = pyfits.getheader(args.eventfile, ext=1)

    log.info("Event file TELESCOPE = {0}, INSTRUMENT = {1}".format(
        hdr["TELESCOP"], hdr["INSTRUME"]))

    if hdr["TELESCOP"] == "NICER":

        # Instantiate NICERObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            log.info("Setting up NICER observatory")
            NICERObs(name="NICER", FPorbname=args.orbfile, tt2tdb_mode="pint")
        # Read event file and return list of TOA objects
        try:
            tl = load_NICER_TOAs(args.eventfile)
        except KeyError:
            log.error(
                "Observatory not recognized.  This probably means you need to provide an orbit file or barycenter the event file."
            )
            sys.exit(1)
    elif hdr["TELESCOP"] == "XTE":

        # Instantiate RXTEObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            # Determine what observatory type is.
            log.info("Setting up RXTE observatory")
            RXTEObs(name="RXTE", FPorbname=args.orbfile, tt2tdb_mode="pint")
        # Read event file and return list of TOA objects
        tl = load_RXTE_TOAs(args.eventfile)
    elif hdr["TELESCOP"].startswith("XMM"):
        # Not loading orbit file here, since that is not yet supported.
        tl = load_XMM_TOAs(args.eventfile)
    elif hdr["TELESCOP"].lower().startswith("nustar"):
        if args.orbfile is not None:
            log.info("Setting up NuSTAR observatory")
            NuSTARObs(name="NuSTAR",
                      FPorbname=args.orbfile,
                      tt2tdb_mode="pint")
        tl = load_NuSTAR_TOAs(args.eventfile)
    else:
        log.error(
            "FITS file not recognized, TELESCOPE = {0}, INSTRUMENT = {1}".
            format(hdr["TELESCOP"], hdr["INSTRUME"]))
        sys.exit(1)

    # Now convert to TOAs object and compute TDBs and posvels
    if len(tl) == 0:
        log.error("No TOAs, exiting!")
        sys.exit(0)

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    use_planets = False
    if "PLANET_SHAPIRO" in modelin.params:
        if modelin.PLANET_SHAPIRO.value:
            use_planets = True
    if "AbsPhase" not in modelin.components:
        log.error(
            "TimingModel does not include AbsPhase component, which is required "
            "for computing phases. Make sure you have TZR* parameters in your par file!"
        )
        raise ValueError("Model missing AbsPhase component.")

    if args.addorbphase and (not hasattr(modelin, "binary_model_name")):
        log.error(
            "TimingModel does not include a binary model, which is required for "
            "computing orbital phases. Make sure you have BINARY and associated "
            "model parameters in your par file!")
        raise ValueError("Model missing BINARY component.")

    # Discard events outside of MJD range
    if args.maxMJD is not None:
        tlnew = []
        print("pre len : ", len(tl))
        maxT = Time(float(args.maxMJD), format="mjd")
        print("maxT : ", maxT)
        for tt in tl:
            if tt.mjd < maxT:
                tlnew.append(tt)
        tl = tlnew
        print("post len : ", len(tlnew))

    ts = toa.get_TOAs_list(
        tl,
        ephem=args.ephem,
        include_bipm=args.use_bipm,
        include_gps=args.use_gps,
        planets=use_planets,
        tdb_method=args.tdbmethod,
    )
    ts.filename = args.eventfile
    #    if args.fix:
    #        ts.adjust_TOAs(TimeDelta(np.ones(len(ts.table))*-1.0*u.s,scale='tt'))

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(), mjds.max())

    # Compute model phase for each TOA
    iphss, phss = modelin.phase(ts, abs_phase=True)
    # ensure all postive
    negmask = phss < 0.0
    phases = np.where(negmask, phss + 1.0, phss)
    h = float(hm(phases))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))
    if args.plot:
        phaseogram_binned(mjds, phases, bins=100, plotfile=args.plotfile)

    # Compute orbital phases for each photon TOA
    if args.addorbphase:
        delay = modelin.delay(ts)
        orbits = modelin.binary_instance.orbits()
        # These lines are already in orbits.orbit_phase() in binary_orbits.py.
        # What is the correct syntax is to call this function here?
        norbits = np.array(np.floor(orbits), dtype=np.long)
        orbphases = orbits - norbits  # fractional phase

    if args.addphase or args.addorbphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile, mode="update")
        else:
            hdulist = pyfits.open(args.eventfile)

        datacol = []
        data_to_add = {}

        if args.addphase:
            if len(hdulist[1].data) != len(phases):
                raise RuntimeError(
                    "Mismatch between length of FITS table ({0}) and length of phase array ({1})!"
                    .format(len(hdulist[1].data), len(phases)))
            data_to_add["PULSE_PHASE"] = [phases, "D"]

        if args.absphase:
            data_to_add["ABS_PHASE"] = [iphss - negmask, "K"]

        if args.barytime:
            bats = modelin.get_barycentric_toas(ts)
            data_to_add["BARY_TIME"] = [bats, "D"]

        if args.addorbphase:
            if len(hdulist[1].data) != len(orbphases):
                raise RuntimeError(
                    "Mismatch between length of FITS table ({0}) and length of orbital phase array ({1})!"
                    .format(len(hdulist[1].data), len(orbphases)))
            data_to_add["ORBIT_PHASE"] = [orbphases, "D"]
        # End if args.addorbphase

        for key in data_to_add.keys():
            if key in hdulist[1].columns.names:
                log.info("Found existing %s column, overwriting..." % key)
                # Overwrite values in existing Column
                hdulist[1].data[key] = data_to_add[key][0]
            else:
                # Construct and append new column, preserving HDU header and name
                log.info("Adding new %s column." % key)
                datacol.append(
                    pyfits.ColDefs([
                        pyfits.Column(
                            name=key,
                            format=data_to_add[key][1],
                            array=data_to_add[key][0],
                        )
                    ]))

        if len(datacol) > 0:
            cols = hdulist[1].columns
            for c in datacol:
                cols = cols + c
            bt = pyfits.BinTableHDU.from_columns(cols,
                                                 header=hdulist[1].header,
                                                 name=hdulist[1].name)
            hdulist[1] = bt

        if args.outfile is None:
            # Overwrite the existing file
            log.info("Overwriting existing FITS file " + args.eventfile)
            hdulist.flush(verbose=True, output_verify="warn")
        else:
            # Write to new output file
            log.info("Writing output FITS file " + args.outfile)
            hdulist.writeto(args.outfile,
                            overwrite=True,
                            checksum=True,
                            output_verify="warn")
Example #23
0
def main(argv=None):
    import argparse
    parser = argparse.ArgumentParser(description="Use PINT to compute event phases and make plots of photon event files.")
    parser.add_argument("eventfile",help="Photon event FITS file name (e.g. from NICER, RXTE, XMM, Chandra).")
    parser.add_argument("parfile",help="par file to construct model from")
    parser.add_argument("--orbfile",help="Name of orbit file", default=None)
    parser.add_argument("--maxMJD",help="Maximum MJD to include in analysis", default=None)
    parser.add_argument("--plotfile",help="Output figure file name (default=None)", default=None)
    parser.add_argument("--addphase",help="Write FITS file with added phase column",default=False,action='store_true')
    parser.add_argument("--absphase",help="Write FITS file with integral portion of pulse phase (ABS_PHASE)",default=False,action='store_true')
    parser.add_argument("--barytime",help="Write FITS file with a column containing the barycentric time as double precision MJD.",default=False,action='store_true')
    parser.add_argument("--outfile",help="Output FITS file name (default=same as eventfile)", default=None)
    parser.add_argument("--ephem",help="Planetary ephemeris to use (default=DE421)", default="DE421")
    parser.add_argument('--tdbmethod',help="Method for computing TT to TDB (default=astropy)", default="default")
    parser.add_argument("--plot",help="Show phaseogram plot.", action='store_true', default=False)
    parser.add_argument("--use_gps",default=False,action='store_true',help="Apply GPS to UTC clock corrections")
    parser.add_argument("--use_bipm",default=False,action='store_true',help="Use TT(BIPM) instead of TT(TAI)")
#    parser.add_argument("--fix",help="Apply 1.0 second offset for NICER", action='store_true', default=False)
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # If plotfile is specified, that implies plot
    if args.plotfile is not None:
        args.plot = True

    # Read event file header to figure out what instrument is is from
    hdr = pyfits.getheader(args.eventfile,ext=1)

    log.info('Event file TELESCOPE = {0}, INSTRUMENT = {1}'.format(hdr['TELESCOP'],
        hdr['INSTRUME']))

    if hdr['TELESCOP'] == 'NICER':

        # Instantiate NICERObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            log.info('Setting up NICER observatory')
            NICERObs(name='NICER',FPorbname=args.orbfile,tt2tdb_mode='pint')
        # Read event file and return list of TOA objects
        try:
            tl  = load_NICER_TOAs(args.eventfile)
        except KeyError:
            log.error("Observatory not recognized.  This probably means you need to provide an orbit file or barycenter the event file.")
            sys.exit(1)
    elif hdr['TELESCOP'] == 'XTE':

        # Instantiate RXTEObs once so it gets added to the observatory registry
        if args.orbfile is not None:
            # Determine what observatory type is.
            log.info('Setting up RXTE observatory')
            RXTEObs(name='RXTE',FPorbname=args.orbfile,tt2tdb_mode='pint')
        # Read event file and return list of TOA objects
        tl  = load_RXTE_TOAs(args.eventfile)
    elif hdr['TELESCOP'].startswith('XMM'):
        # Not loading orbit file here, since that is not yet supported.
        tl  = load_XMM_TOAs(args.eventfile)
    elif hdr['TELESCOP'].lower().startswith('nustar'):
        if args.orbfile is not None:
            log.info('Setting up NuSTAR observatory')
            NuSTARObs(name='NuSTAR',FPorbname=args.orbfile, tt2tdb_mode='pint')
        tl = load_NuSTAR_TOAs(args.eventfile)
    else:
        log.error("FITS file not recognized, TELESCOPE = {0}, INSTRUMENT = {1}".format(
            hdr['TELESCOP'], hdr['INSTRUME']))
        sys.exit(1)


    # Now convert to TOAs object and compute TDBs and posvels
    if len(tl) == 0:
        log.error("No TOAs, exiting!")
        sys.exit(0)

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    use_planets=False
    if 'PLANET_SHAPIRO' in modelin.params:
        if modelin.PLANET_SHAPIRO.value:
            use_planets=True

    # Discard events outside of MJD range
    if args.maxMJD is not None:
        tlnew = []
        print("pre len : ",len(tl))
        maxT = Time(float(args.maxMJD),format='mjd')
        print("maxT : ",maxT)
        for tt in tl:
            if tt.mjd < maxT:
                tlnew.append(tt)
        tl=tlnew
        print("post len : ",len(tlnew))

    ts = toa.get_TOAs_list(tl, ephem=args.ephem, include_bipm=args.use_bipm,
        include_gps=args.use_gps, planets=use_planets, tdb_method=args.tdbmethod)
    ts.filename = args.eventfile
#    if args.fix:
#        ts.adjust_TOAs(TimeDelta(np.ones(len(ts.table))*-1.0*u.s,scale='tt'))

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(),mjds.max())


    # Compute model phase for each TOA
    iphss,phss = modelin.phase(ts,abs_phase=True)
    # ensure all postive
    negmask = phss < 0.0 * u.cycle
    phases = np.where(negmask, phss + 1.0 * u.cycle, phss)
    h = float(hm(phases))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h,h2sig(h)))
    if args.plot:
        phaseogram_binned(mjds,phases,bins=100,plotfile = args.plotfile)

    if args.addphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile,mode='update')
        else:
            hdulist = pyfits.open(args.eventfile)
        if len(hdulist[1].data) != len(phases):
            raise RuntimeError('Mismatch between length of FITS table ({0}) and length of phase array ({1})!'.format(len(hdulist[1].data),len(phases)))
        data_to_add = {'PULSE_PHASE':[phases,'D']}
        if args.absphase:
            data_to_add['ABS_PHASE'] = [iphss-negmask*u.cycle,'K']
        if args.barytime:
            bats = modelin.get_barycentric_toas(ts)
            data_to_add['BARY_TIME'] = [bats,'D']
        datacol = []
        for key in data_to_add.keys():
            if key in hdulist[1].columns.names:
                log.info('Found existing %s column, overwriting...'%key)
                # Overwrite values in existing Column
                hdulist[1].data[key] = data_to_add[key][0]
            else:
                # Construct and append new column, preserving HDU header and name
                log.info('Adding new %s column.'%key)
                datacol.append(pyfits.ColDefs([pyfits.Column(name=key,
                    format=data_to_add[key][1], array=data_to_add[key][0])]))
        if len(datacol)>0:
            cols = hdulist[1].columns
            for c in datacol:
                cols = cols + c
            bt = pyfits.BinTableHDU.from_columns(cols, header=hdulist[1].header,
                name=hdulist[1].name)
            hdulist[1] = bt
        if args.outfile is None:
            # Overwrite the existing file
            log.info('Overwriting existing FITS file '+args.eventfile)
            hdulist.flush(verbose=True, output_verify='warn')
        else:
            # Write to new output file
            log.info('Writing output FITS file '+args.outfile)
            hdulist.writeto(args.outfile,overwrite=True, checksum=True, output_verify='warn')
Example #24
0
def main(argv=None):

    parser = argparse.ArgumentParser(
        description=
        "Use PINT to compute H-test and plot Phaseogram from a Fermi FT1 event file."
    )
    parser.add_argument("eventfile", help="Fermi event FITS file name.")
    parser.add_argument("parfile", help="par file to construct model from")
    parser.add_argument(
        "weightcol",
        help="Column name for event weights (or 'CALC' to compute them)")
    parser.add_argument("--ft2", help="Path to FT2 file.", default=None)
    parser.add_argument(
        "--addphase",
        help="Write FT1 file with added phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument("--plot",
                        help="Show phaseogram plot.",
                        action="store_true",
                        default=False)
    parser.add_argument("--plotfile",
                        help="Output figure file name (default=None)",
                        default=None)
    parser.add_argument("--maxMJD",
                        help="Maximum MJD to include in analysis",
                        default=None)
    parser.add_argument(
        "--outfile",
        help="Output figure file name (default is to overwrite input file)",
        default=None,
    )
    parser.add_argument(
        "--planets",
        help="Use planetary Shapiro delay in calculations (default=False)",
        default=False,
        action="store_true",
    )
    parser.add_argument("--ephem",
                        help="Planetary ephemeris to use (default=DE421)",
                        default="DE421")
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    if "ELONG" in modelin.params:
        tc = SkyCoord(
            modelin.ELONG.quantity,
            modelin.ELAT.quantity,
            frame="barycentrictrueecliptic",
        )
    else:
        tc = SkyCoord(modelin.RAJ.quantity,
                      modelin.DECJ.quantity,
                      frame="icrs")

    if args.ft2 is not None:
        # Instantiate FermiObs once so it gets added to the observatory registry
        FermiObs(name="Fermi", ft2name=args.ft2)

    # Read event file and return list of TOA objects
    tl = load_Fermi_TOAs(args.eventfile,
                         weightcolumn=args.weightcol,
                         targetcoord=tc)

    # Discard events outside of MJD range
    if args.maxMJD is not None:
        tlnew = []
        print("pre len : ", len(tl))
        maxT = Time(float(args.maxMJD), format="mjd")
        print("maxT : ", maxT)
        for tt in tl:
            if tt.mjd < maxT:
                tlnew.append(tt)
        tl = tlnew
        print("post len : ", len(tlnew))

    # Now convert to TOAs object and compute TDBs and posvels
    # For Fermi, we are not including GPS or TT(BIPM) corrections
    ts = toa.get_TOAs_list(
        tl,
        include_gps=False,
        include_bipm=False,
        planets=args.planets,
        ephem=args.ephem,
    )
    ts.filename = args.eventfile

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(), mjds.max())

    # Compute model phase for each TOA
    iphss, phss = modelin.phase(ts, abs_phase=True)
    # ensure all postive
    phases = np.where(phss < 0.0 * u.cycle, phss + 1.0 * u.cycle, phss)
    mjds = ts.get_mjds()
    weights = np.array([w["weight"] for w in ts.table["flags"]])
    h = float(hmw(phases, weights))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))
    if args.plot:
        log.info("Making phaseogram plot with {0} photons".format(len(mjds)))
        phaseogram(mjds, phases, weights, bins=100, plotfile=args.plotfile)

    if args.addphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile, mode="update")
        else:
            hdulist = pyfits.open(args.eventfile)
        event_hdu = hdulist[1]
        event_hdr = event_hdu.header
        event_dat = event_hdu.data
        if len(event_dat) != len(phases):
            raise RuntimeError(
                "Mismatch between length of FITS table ({0}) and length of phase array ({1})!"
                .format(len(event_dat), len(phases)))
        if "PULSE_PHASE" in event_hdu.columns.names:
            log.info("Found existing PULSE_PHASE column, overwriting...")
            # Overwrite values in existing Column
            event_dat["PULSE_PHASE"] = phases
        else:
            # Construct and append new column, preserving HDU header and name
            log.info("Adding new PULSE_PHASE column.")
            phasecol = pyfits.ColDefs(
                [pyfits.Column(name="PULSE_PHASE", format="D", array=phases)])
            bt = pyfits.BinTableHDU.from_columns(event_hdu.columns + phasecol,
                                                 header=event_hdr,
                                                 name=event_hdu.name)
            hdulist[1] = bt
        if args.outfile is None:
            # Overwrite the existing file
            log.info("Overwriting existing FITS file " + args.eventfile)
            hdulist.flush(verbose=True, output_verify="warn")
        else:
            # Write to new output file
            log.info("Writing output FITS file " + args.outfile)
            hdulist.writeto(args.outfile,
                            overwrite=True,
                            checksum=True,
                            output_verify="warn")

    return 0
Example #25
0
    def generate_polycos(
        self,
        model,
        mjdStart,
        mjdEnd,
        obs,
        segLength,
        ncoeff,
        obsFreq,
        maxha=12.0,
        method="TEMPO",
        numNodes=20,
    ):
        """
        Generate the polyco data.

        Parameters
        ---------
        model : TimingModel
            TimingModel to generate the Polycos with parameters
            setup.

        mjdStart : float / nump longdouble
            Start time of polycos in mjd

        mjdEnd : float / nump longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength : float
            Length of polyco segement [unit: minutes]

        ncoeff : int
            number of coefficents

        obsFreq : float
            observing frequency [unit: MHz]

        maxha : float optional. Default 12.0
            Maximum hour angle

        method : string optional ['TEMPO','TEMPO2',...] Default TEMPO
            Method to generate polycos. Only the TEMPO method is supported for now.

        numNodes : int optional. Default 20
            Number of nodes for fitting. It cannot be less then the number of
            coefficents.

        Return
        ---------
        A polyco table.


        """
        mjdStart = data2longdouble(mjdStart) * u.day
        mjdEnd = data2longdouble(mjdEnd) * u.day
        timeLength = mjdEnd - mjdStart
        segLength = data2longdouble(segLength) * u.min
        obsFreq = float(obsFreq)
        month = [
            "Jan",
            "Feb",
            "Mar",
            "Apr",
            "May",
            "Jun",
            "Jul",
            "Aug",
            "Sep",
            "Oct",
            "Nov",
            "Dec",
        ]
        # Alocate memery
        coeffs = data2longdouble(np.zeros(ncoeff))
        entryList = []
        entryIntvl = np.arange(mjdStart.value, mjdEnd.value,
                               segLength.to("day").value)
        if entryIntvl[-1] < mjdEnd.value:
            entryIntvl = np.append(entryIntvl, mjdEnd.value)

        # Make sure the number of nodes is bigger then number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff + 1

        # generate the ploynomial coefficents
        if method == "TEMPO":
            # Using tempo1 method to create polycos
            for i in range(len(entryIntvl) - 1):
                tStart = entryIntvl[i]
                tStop = entryIntvl[i + 1]
                nodes = np.linspace(tStart, tStop, numNodes)
                tmid = ((tStart + tStop) / 2.0) * u.day
                toaMid = toa.get_TOAs_list([
                    toa.TOA(
                        (np.modf(tmid.value)[1], np.modf(tmid.value)[0]),
                        obs=obs,
                        freq=obsFreq,
                    )
                ])
                refPhase = model.phase(toaMid)
                mjdSpan = ((tStop - tStart) * u.day).to("min")
                # Create node toas(Time sample using TOA class)
                toaList = [
                    toa.TOA(
                        (np.modf(toaNode)[1], np.modf(toaNode)[0]),
                        obs=obs,
                        freq=obsFreq,
                    ) for toaNode in nodes
                ]

                toas = toa.get_TOAs_list(toaList)

                ph = model.phase(toas)
                dt = (nodes * u.day - tmid).to("min")  # Use constant
                rdcPhase = ph - refPhase
                rdcPhase = (rdcPhase.int -
                            (dt.value * model.F0.value * 60.0) * u.cycle +
                            rdcPhase.frac)
                dtd = dt.value.astype(float)  # Truncate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd, rdcPhased, ncoeff - 1)
                coeffs = coeffs[::-1]
                midTime = Time(int(tmid.value),
                               np.modf(tmid.value)[0],
                               format="mjd",
                               scale="utc")
                date, hms = midTime.iso.split()
                yy, mm, dd = date.split("-")
                date = dd + "-" + month[int(mm) - 1] + "-" + yy[2:4]
                hms = hms.replace(":", "")
                entry = PolycoEntry(
                    tmid.value,
                    mjdSpan.to("day").value,
                    refPhase.int,
                    refPhase.frac,
                    model.F0.value,
                    ncoeff,
                    coeffs,
                    obs,
                )
                entryList.append((
                    model.PSR.value,
                    date,
                    hms,
                    tmid.value,
                    model.DM.value,
                    0.0,
                    0.0,
                    0.0,
                    mjdSpan.to("day").value,
                    tStart,
                    tStop,
                    obs,
                    obsFreq,
                    entry,
                ))

            pTable = table.Table(
                rows=entryList,
                names=(
                    "psr",
                    "date",
                    "utc",
                    "tmid",
                    "dm",
                    "doppler",
                    "logrms",
                    "binary_phase",
                    "mjd_span",
                    "t_start",
                    "t_stop",
                    "obs",
                    "obsfreq",
                    "entry",
                ),
                meta={"name": "Polyco Data Table"},
            )
            self.polycoTable = pTable
            if len(self.polycoTable) == 0:
                raise ValueError("Zero polycos found for table")
        else:
            #  Reading from an old polycofile
            pass
Example #26
0
def main(argv=None):

    parser = argparse.ArgumentParser(description="Use PINT to compute H-test and plot Phaseogram from a Fermi FT1 event file.")
    parser.add_argument("eventfile",help="Fermi event FITS file name.")
    parser.add_argument("parfile",help="par file to construct model from")
    parser.add_argument("weightcol",help="Column name for event weights (or 'CALC' to compute them)")
    parser.add_argument("--ft2",help="Path to FT2 file.",default=None)
    parser.add_argument("--addphase",help="Write FT1 file with added phase column",
        default=False,action='store_true')
    parser.add_argument("--plot",help="Show phaseogram plot.", action='store_true', default=False)
    parser.add_argument("--plotfile",help="Output figure file name (default=None)", default=None)
    parser.add_argument("--maxMJD",help="Maximum MJD to include in analysis", default=None)
    parser.add_argument("--outfile",help="Output figure file name (default is to overwrite input file)", default=None)
    parser.add_argument("--planets",help="Use planetary Shapiro delay in calculations (default=False)", default=False, action="store_true")
    parser.add_argument("--ephem",help="Planetary ephemeris to use (default=DE421)", default="DE421")
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    if 'ELONG' in modelin.params:
        tc = SkyCoord(modelin.ELONG.quantity,modelin.ELAT.quantity,
            frame='barycentrictrueecliptic')
    else:
        tc = SkyCoord(modelin.RAJ.quantity,modelin.DECJ.quantity,frame='icrs')

    if args.ft2 is not None:
        # Instantiate FermiObs once so it gets added to the observatory registry
        FermiObs(name='Fermi',ft2name=args.ft2)

    # Read event file and return list of TOA objects
    tl  = load_Fermi_TOAs(args.eventfile, weightcolumn=args.weightcol,
                          targetcoord=tc)

    # Discard events outside of MJD range
    if args.maxMJD is not None:
        tlnew = []
        print("pre len : ",len(tl))
        maxT = Time(float(args.maxMJD),format='mjd')
        print("maxT : ",maxT)
        for tt in tl:
            if tt.mjd < maxT:
                tlnew.append(tt)
        tl=tlnew
        print("post len : ",len(tlnew))

    # Now convert to TOAs object and compute TDBs and posvels
    # For Fermi, we are not including GPS or TT(BIPM) corrections
    ts = toa.get_TOAs_list(tl,include_gps=False,include_bipm=False,planets=args.planets,ephem=args.ephem)
    ts.filename = args.eventfile

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(),mjds.max())

    # Compute model phase for each TOA
    iphss,phss = modelin.phase(ts,abs_phase=True)
    # ensure all postive
    phases = np.where(phss < 0.0 * u.cycle, phss + 1.0 * u.cycle, phss)
    mjds = ts.get_mjds()
    weights = np.array([w['weight'] for w in ts.table['flags']])
    h = float(hmw(phases,weights))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h,h2sig(h)))
    if args.plot:
        log.info("Making phaseogram plot with {0} photons".format(len(mjds)))
        phaseogram(mjds,phases,weights,bins=100,plotfile = args.plotfile)

    if args.addphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile,mode='update')
        else:
            hdulist = pyfits.open(args.eventfile)
        event_hdu = hdulist[1]
        event_hdr=event_hdu.header
        event_dat=event_hdu.data
        if len(event_dat) != len(phases):
            raise RuntimeError('Mismatch between length of FITS table ({0}) and length of phase array ({1})!'.format(len(event_dat),len(phases)))
        if 'PULSE_PHASE' in event_hdu.columns.names:
            log.info('Found existing PULSE_PHASE column, overwriting...')
            # Overwrite values in existing Column
            event_dat['PULSE_PHASE'] = phases
        else:
            # Construct and append new column, preserving HDU header and name
            log.info('Adding new PULSE_PHASE column.')
            phasecol = pyfits.ColDefs([pyfits.Column(name='PULSE_PHASE', format='D',
                array=phases)])
            bt = pyfits.BinTableHDU.from_columns( event_hdu.columns + phasecol,
                header=event_hdr,name=event_hdu.name)
            hdulist[1] = bt
        if args.outfile is None:
            # Overwrite the existing file
            log.info('Overwriting existing FITS file '+args.eventfile)
            hdulist.flush(verbose=True, output_verify='warn')
        else:
            # Write to new output file
            log.info('Writing output FITS file '+args.outfile)
            hdulist.writeto(args.outfile,overwrite=True, checksum=True, output_verify='warn')

    return 0
Example #27
0
def main(argv=None):
    import argparse

    parser = argparse.ArgumentParser(
        description=
        "Use PINT to compute event phases and make plots of photon event files.",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        "eventfile",
        help=
        "Photon event FITS file name (e.g. from NICER, RXTE, XMM, Chandra).",
    )
    parser.add_argument("parfile", help="par file to construct model from")
    parser.add_argument("--orbfile", help="Name of orbit file", default=None)
    parser.add_argument("--maxMJD",
                        help="Maximum MJD to include in analysis",
                        default=None)
    parser.add_argument("--minMJD",
                        help="Minimum MJD to include in analysis",
                        default=None)
    parser.add_argument("--plotfile",
                        help="Output figure file name",
                        default=None)
    parser.add_argument(
        "--addphase",
        help="Write FITS file with added phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--addorbphase",
        help="Write FITS file with added orbital phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--absphase",
        help="Write FITS file with integral portion of pulse phase (ABS_PHASE)",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--barytime",
        help=
        "Write FITS file with a column containing the barycentric time as double precision MJD.",
        default=False,
        action="store_true",
    )
    parser.add_argument(
        "--outfile",
        help="Output FITS file name (default=same as eventfile)",
        default=None,
    )
    parser.add_argument("--ephem",
                        help="Planetary ephemeris to use",
                        default="DE421")
    parser.add_argument(
        "--tdbmethod",
        help="Method for computing TT to TDB (default=astropy)",
        default="default",
    )
    parser.add_argument("--plot",
                        help="Show phaseogram plot.",
                        action="store_true",
                        default=False)
    parser.add_argument(
        "--use_gps",
        default=False,
        action="store_true",
        help="Apply GPS to UTC clock corrections",
    )
    parser.add_argument(
        "--use_bipm",
        default=False,
        action="store_true",
        help="Use TT(BIPM) instead of TT(TAI)",
    )
    parser.add_argument(
        "--log-level",
        type=str,
        choices=("TRACE", "DEBUG", "INFO", "WARNING", "ERROR"),
        default="WARNING",
        help="Logging level",
        dest="loglevel",
    )
    #    parser.add_argument("--fix",help="Apply 1.0 second offset for NICER", action='store_true', default=False)
    parser.add_argument(
        "--polycos",
        default=False,
        action="store_true",
        help=
        "Use polycos to calculate phases; use when working with very large event files",
    )
    args = parser.parse_args(argv)
    log.remove()
    log.add(
        sys.stderr,
        level=args.loglevel,
        colorize=True,
        format=pint.logging.format,
        filter=pint.logging.LogFilter(),
    )

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # If plotfile is specified, that implies plot
    if args.plotfile is not None:
        args.plot = True

    # set MJD ranges
    maxmjd = np.inf if (args.maxMJD is None) else float(args.maxMJD)
    minmjd = 0.0 if (args.minMJD is None) else float(args.minMJD)

    # Read event file header to figure out what instrument is is from
    hdr = pyfits.getheader(args.eventfile, ext=1)

    log.info("Event file TELESCOPE = {0}, INSTRUMENT = {1}".format(
        hdr["TELESCOP"], hdr["INSTRUME"]))

    telescope = hdr["TELESCOP"].lower()

    # Instantiate observatory once so it gets added to the observatory registry
    if args.orbfile is not None:
        log.info(f"Setting up {telescope.upper()} observatory")
        try:
            get_satellite_observatory(telescope, args.orbfile)
        except Exception:
            log.error(
                "The orbit file is not recognized. It is likely that this mission is not supported. "
                "Please barycenter the event file using the official mission tools before processing with PINT"
            )
    # Read event file and return list of TOA objects, if not using polycos
    if args.polycos == False:
        try:
            tl = load_event_TOAs(args.eventfile,
                                 telescope,
                                 minmjd=minmjd,
                                 maxmjd=maxmjd)
        except KeyError:
            log.error(
                "Observatory not recognized. This probably means you need to provide an orbit file or barycenter the event file."
            )
            sys.exit(1)

        # Now convert to TOAs object and compute TDBs and posvels
        if len(tl) == 0:
            log.error("No TOAs, exiting!")
            sys.exit(0)

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    use_planets = False
    if "PLANET_SHAPIRO" in modelin.params:
        if modelin.PLANET_SHAPIRO.value:
            use_planets = True
    if "AbsPhase" not in modelin.components:
        log.error(
            "TimingModel does not include AbsPhase component, which is required "
            "for computing phases. Make sure you have TZR* parameters in your par file!"
        )
        raise ValueError("Model missing AbsPhase component.")

    if args.addorbphase and (not hasattr(modelin, "binary_model_name")):
        log.error(
            "TimingModel does not include a binary model, which is required for "
            "computing orbital phases. Make sure you have BINARY and associated "
            "model parameters in your par file!")
        raise ValueError("Model missing BINARY component.")

    # Use polycos to calculate pulse phases
    if args.polycos:
        log.info("Using polycos to get pulse phases.")

        if args.addorbphase:
            raise ValueError("Cannot use orbphase with polycos.")

        # Polycos parameters
        segLength = 120  # in minutes
        ncoeff = 10
        obsfreq = 0

        # Open event file and get start and end mjds
        hdulist = pyfits.open(args.eventfile)
        data = hdulist[1].data
        mjds = read_fits_event_mjds(hdulist[1])
        minmjd = min(mjds)
        maxmjd = max(mjds)

        # Check if event file is barycentered
        if hdulist[1].header["TIMESYS"] != "TDB":
            raise ValueError(
                "The event file has not been barycentered. Polycos can only be used with barycentered data."
            )

        # Create polycos table
        log.debug("Generating polycos")
        telescope_n = "@"
        p = polycos.Polycos()
        ptable = p.generate_polycos(modelin, minmjd, maxmjd, telescope_n,
                                    segLength, ncoeff, obsfreq)

        # Calculate phases
        log.debug("Evaluating polycos")
        phases = p.eval_phase(mjds)
        phases[phases < 0] += 1.0
        h = float(hm(phases))
        print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))
    else:  # Normal mode, not polycos
        ts = toa.get_TOAs_list(
            tl,
            ephem=args.ephem,
            include_bipm=args.use_bipm,
            include_gps=args.use_gps,
            planets=use_planets,
            tdb_method=args.tdbmethod,
        )
        ts.filename = args.eventfile
        #    if args.fix:
        #        ts.adjust_TOAs(TimeDelta(np.ones(len(ts.table))*-1.0*u.s,scale='tt'))

        print(ts.get_summary())
        mjds = ts.get_mjds()
        print(mjds.min(), mjds.max())

        # Compute model phase for each TOA
        iphss, phss = modelin.phase(ts, abs_phase=True)
        phases = phss.value % 1
        h = float(hm(phases))
        print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))

    if args.plot:
        phaseogram_binned(mjds, phases, bins=100, plotfile=args.plotfile)

    # Compute orbital phases for each photon TOA
    if args.addorbphase:
        delay = modelin.delay(ts)
        orbits = modelin.binary_instance.orbits()
        # These lines are already in orbits.orbit_phase() in binary_orbits.py.
        # What is the correct syntax is to call this function here?
        norbits = np.array(np.floor(orbits), dtype=int)
        orbphases = orbits - norbits  # fractional phase

    if args.addphase or args.addorbphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile, mode="update")
        else:
            hdulist = pyfits.open(args.eventfile)

        datacol = []
        data_to_add = {}

        # Handle case where minMJD/maxMJD do not exceed length of events
        mjds_float = read_fits_event_mjds(hdulist[1])
        time_mask = np.logical_and((mjds_float > minmjd),
                                   (mjds_float < maxmjd))
        if args.polycos:
            time_mask = np.logical_and((mjds_float >= minmjd),
                                       (mjds_float <= maxmjd))

        if args.addphase:
            if time_mask.sum() != len(phases):
                raise RuntimeError(
                    "Mismatch between data selection {0} and length of phase array ({1})!"
                    .format(time_mask.sum(), len(phases)))
            data_to_add["PULSE_PHASE"] = [phases, "D"]

        if args.absphase:
            data_to_add["ABS_PHASE"] = [iphss, "K"]

        if args.barytime:
            bats = modelin.get_barycentric_toas(ts)
            data_to_add["BARY_TIME"] = [bats, "D"]

        if args.addorbphase:
            if time_mask.sum() != len(orbphases):
                raise RuntimeError(
                    "Mismatch between data selection ({0}) and length of orbital phase array ({1})!"
                    .format(time_mask.sum(), len(orbphases)))
            data_to_add["ORBIT_PHASE"] = [orbphases, "D"]
        # End if args.addorbphase

        for key in data_to_add.keys():
            if key in hdulist[1].columns.names:
                log.info("Found existing %s column, overwriting..." % key)
                # Overwrite values in existing Column
                hdulist[1].data[key][time_mask] = data_to_add[key][0]
            else:
                # Construct and append new column, preserving HDU header and name
                log.info("Adding new %s column." % key)
                new_dat = np.full(time_mask.shape,
                                  -1,
                                  dtype=data_to_add[key][0].dtype)
                new_dat[time_mask] = data_to_add[key][0]
                datacol.append(
                    pyfits.ColDefs([
                        pyfits.Column(name=key,
                                      format=data_to_add[key][1],
                                      array=new_dat)
                    ]))

        if len(datacol) > 0:
            cols = hdulist[1].columns
            for c in datacol:
                cols = cols + c
            bt = pyfits.BinTableHDU.from_columns(cols,
                                                 header=hdulist[1].header,
                                                 name=hdulist[1].name)
            hdulist[1] = bt

        if args.outfile is None:
            # Overwrite the existing file
            log.info("Overwriting existing FITS file " + args.eventfile)
            hdulist.flush(verbose=True, output_verify="warn")
        else:
            # Write to new output file
            log.info("Writing output FITS file " + args.outfile)
            hdulist.writeto(args.outfile,
                            overwrite=True,
                            checksum=True,
                            output_verify="warn")
Example #28
0
    def generate_polycos(
        self,
        model,
        mjdStart,
        mjdEnd,
        obs,
        segLength,
        ncoeff,
        obsFreq,
        maxha=12.0,
        method="TEMPO",
        numNodes=20,
    ):
        """
        Generate the polyco data.

        Parameters
        ----------
        model : TimingModel
            TimingModel to generate the Polycos with parameters
            setup.

        mjdStart : float / numpy longdouble
            Start time of polycos in mjd

        mjdEnd : float / numpy longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength : int
            Length of polyco segement [minutes]

        ncoeff : int
            Number of coefficents

        obsFreq : float
            Observing frequency [MHz]

        maxha : float optional. Default 12.0
            Maximum hour angle. Only 12.0 is supported for now.

        method : string optional ["TEMPO", "TEMPO2", ...] Default TEMPO
            Method to generate polycos. Only the TEMPO method is supported for now.

        numNodes : int optional. Default 20
            Number of nodes for fitting. It cannot be less then the number of
            coefficents.

        Return
        ---------
        A polyco table.
        """
        mjdStart = data2longdouble(mjdStart)
        mjdEnd = data2longdouble(mjdEnd)
        segLength = int(segLength)
        obsFreq = float(obsFreq)

        # Use the planetary ephemeris specified in the model, if available.
        if model.EPHEM.value is not None:
            ephem = model.EPHEM.value
        else:
            log.info(
                "No ephemeris specified in model, using DE421 to generate polycos"
            )
            ephem = "DE421"

        if maxha != 12.0:
            raise ValueError("Maximum hour angle != 12.0 is not supported.")

        # Make sure the number of nodes is bigger than number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff + 1

        mjdSpan = data2longdouble(segLength / MIN_PER_DAY)
        # Generate "nice" MJDs for consistency with what tempo2 does
        tmids = np.arange(
            int(mjdStart * 24) * 60,
            int(mjdEnd * 24) * 60 + segLength, segLength)
        tmids = data2longdouble(tmids) / MIN_PER_DAY

        # generate the ploynomial coefficents
        if method == "TEMPO":
            entryList = []
            # Using tempo1 method to create polycos
            # If you want to disable the progress bar, add disable=True to the tqdm() call.
            for tmid in tqdm(tmids):
                tStart = tmid - mjdSpan / 2
                tStop = tmid + mjdSpan / 2
                nodes = np.linspace(tStart, tStop, numNodes)

                toaMid = toa.get_TOAs_list(
                    [
                        toa.TOA((np.modf(tmid)[1], np.modf(tmid)[0]),
                                obs=obs,
                                freq=obsFreq)
                    ],
                    ephem=ephem,
                )

                refPhase = model.phase(toaMid, abs_phase=True)

                # Create node toas(Time sample using TOA class)
                toaList = [
                    toa.TOA(
                        (np.modf(toaNode)[1], np.modf(toaNode)[0]),
                        obs=obs,
                        freq=obsFreq,
                    ) for toaNode in nodes
                ]

                toas = toa.get_TOAs_list(toaList, ephem=ephem)

                ph = model.phase(toas, abs_phase=True)
                dt = (nodes - tmid) * MIN_PER_DAY
                rdcPhase = ph - refPhase
                rdcPhase = rdcPhase.int - (dt * model.F0.value *
                                           60.0) + rdcPhase.frac
                dtd = dt.astype(float)  # Truncate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd, rdcPhased, ncoeff - 1)[::-1]

                date, hms = Time(tmid, format="mjd", scale="utc").iso.split()
                yy, mm, dd = date.split("-")
                date = dd + "-" + MONTHS[int(mm) - 1] + "-" + yy[-2:]
                hms = float(hms.replace(":", ""))

                entry = PolycoEntry(
                    tmid,
                    segLength,
                    refPhase.int,
                    refPhase.frac,
                    model.F0.value,
                    ncoeff,
                    coeffs,
                )

                entry_dict = OrderedDict()
                entry_dict["psr"] = model.PSR.value
                entry_dict["date"] = date
                entry_dict["utc"] = hms
                entry_dict["tmid"] = tmid
                entry_dict["dm"] = model.DM.value
                entry_dict["doppler"] = 0.0
                entry_dict["logrms"] = 0.0
                entry_dict["mjd_span"] = segLength
                entry_dict["t_start"] = entry.tstart
                entry_dict["t_stop"] = entry.tstop
                entry_dict["obs"] = obs
                entry_dict["obsfreq"] = obsFreq

                if model.is_binary:
                    binphase = model.orbital_phase(toaMid, radians=False)[0]
                    entry_dict["binary_phase"] = binphase
                    b = model.get_components_by_category()["pulsar_system"][0]
                    entry_dict["f_orbit"] = 1 / b.PB.value

                entry_dict["entry"] = entry
                entryList.append(entry_dict)

            pTable = table.Table(entryList, meta={"name": "Polyco Data Table"})

            self.polycoTable = pTable
            if len(self.polycoTable) == 0:
                raise ValueError("Zero polycos found for table")

        else:
            raise NotImplementedError(
                "Only TEMPO method has been implemented.")
Example #29
0
    def d_phase_d_toa(self,
                      toas,
                      time_intval=60,
                      method=None,
                      num_sample=20,
                      order=11):
        """Return the derivative of phase wrt TOA
            time_intval: is in seconds
            method: with finite difference and chebyshev interpolation


        """
        d_phase_d_toa = np.zeros(len(toas))

        if method is None or "FDM":
            # Using finite difference to calculate the derivitve
            dt = np.longdouble(time_intval) / np.longdouble(num_sample)
            num_sample = int(num_sample) / 2 * 2 + 1

            for i, singal_toa in enumerate(toas):
                toa_utc_ld = utils.time_to_longdouble(singal_toa['mjd'])
                # Resample the toa points
                domain = (toa_utc_ld - time_intval / 2.0,
                          toa_utc_ld + time_intval / 2.0)
                sample = np.linspace(domain[0], domain[1], num_sample)

                toa_list = []
                for sample_time in sample:
                    toa_list.append(
                        toa.TOA(
                            (np.modf(sample_time)[1], np.modf(sample_time)[0]),
                            obs=singal_toa['obs'],
                            freq=singal_toa['freq']))

                sample_toalist = toa.get_TOAs_list(toa_list)
                ph = self.phase(sample_toalist.table)
                p = ph.int - ph.int.min() + ph.frac
                p = np.array(p, dtype='float64')
                # Reduce the value of samples in order to use double precision
                reduce_samepl = np.array((sample - sample.min()) * 86400.0,
                                         dtype='float64')
                dx = np.gradient(reduce_samepl)
                dp = np.gradient(p - p.mean(), dx)
                d_phase_d_toa[i] = dp[num_sample / 2]

        if method is "chebyshev":
            # Using chebyshev interpolation to calculate the

            for i, singal_toa in enumerate(toas):
                # Have more sample point around toa
                toa_utc_ld = utils.time_to_longdouble(singal_toa['mjd'])
                domain = (toa_utc_ld - time_intval / 2.0,
                          toa_utc_ld + time_intval / 2.0)
                sample = np.linspace(domain[0], domain[1], num_sample)

                toa_list = []
                for sample_time in sample:
                    toa_list.append(
                        toa.TOA(
                            (np.modf(sample_time)[1], np.modf(sample_time)[0]),
                            obs=singal_toa['obs'],
                            freq=singal_toa['freq']))

                sample_toalist = toa.get_TOAs_list(toa_list)
                # Calculate phase
                ph = self.phase(sample_toalist.table)
                p = ph.int - ph.int.min() + ph.frac
                p = np.array(p, dtype='float64')
                # reduce the phase value to use double precision
                reduce_samepl = np.array((sample - sample.min()) * 86400.0,
                                         dtype='float64')
                coeff = np.polynomial.chebyshev.chebfit(
                    reduce_samepl, p, order)
                dcoeff = np.polynomial.chebyshev.chebder(coeff)
                dy = np.polynomial.chebyshev.chebval(reduce_samepl, dcoeff)
                d_phase_d_toa[i] = dy[num_sample / 2]

        return d_phase_d_toa
Example #30
0
def main(argv=None):

    parser = argparse.ArgumentParser(
        description=
        "Use PINT to compute H-test and plot Phaseogram from a Fermi FT1 event file."
    )
    parser.add_argument("eventfile", help="Fermi event FITS file name.")
    parser.add_argument("parfile", help="par file to construct model from")
    parser.add_argument(
        "weightcol",
        help="Column name for event weights (or 'CALC' to compute them)")
    parser.add_argument("--ft2", help="Path to FT2 file.", default=None)
    parser.add_argument(
        "--addphase",
        help="Write FT1 file with added phase column",
        default=False,
        action="store_true",
    )
    parser.add_argument("--plot",
                        help="Show phaseogram plot.",
                        action="store_true",
                        default=False)
    parser.add_argument("--plotfile",
                        help="Output figure file name (default=None)",
                        default=None)
    parser.add_argument("--maxMJD",
                        help="Maximum MJD to include in analysis",
                        default=None)
    parser.add_argument("--minMJD",
                        help="Minimum MJD to include in analysis",
                        default=None)
    parser.add_argument(
        "--outfile",
        help="Output figure file name (default is to overwrite input file)",
        default=None,
    )
    parser.add_argument(
        "--planets",
        help="Use planetary Shapiro delay in calculations (default=False)",
        default=False,
        action="store_true",
    )
    parser.add_argument("--ephem",
                        help="Planetary ephemeris to use (default=DE421)",
                        default="DE421")
    args = parser.parse_args(argv)

    # If outfile is specified, that implies addphase
    if args.outfile is not None:
        args.addphase = True

    # Read in model
    modelin = pint.models.get_model(args.parfile)
    if "ELONG" in modelin.params:
        tc = SkyCoord(
            modelin.ELONG.quantity,
            modelin.ELAT.quantity,
            frame="barycentrictrueecliptic",
        )
    else:
        tc = SkyCoord(modelin.RAJ.quantity,
                      modelin.DECJ.quantity,
                      frame="icrs")

    if args.ft2 is not None:
        # Instantiate Fermi observatory once so it gets added to the observatory registry
        get_satellite_observatory("Fermi", args.ft2)

    # Read event file and return list of TOA objects
    maxmjd = np.inf if (args.maxMJD is None) else float(args.maxMJD)
    minmjd = 0.0 if (args.minMJD is None) else float(args.minMJD)
    tl = load_Fermi_TOAs(
        args.eventfile,
        maxmjd=maxmjd,
        minmjd=minmjd,
        weightcolumn=args.weightcol,
        targetcoord=tc,
    )

    # Now convert to TOAs object and compute TDBs and posvels
    # For Fermi, we are not including GPS or TT(BIPM) corrections
    ts = toa.get_TOAs_list(
        tl,
        include_gps=False,
        include_bipm=False,
        planets=args.planets,
        ephem=args.ephem,
    )
    ts.filename = args.eventfile

    print(ts.get_summary())
    mjds = ts.get_mjds()
    print(mjds.min(), mjds.max())

    # Compute model phase for each TOA
    iphss, phss = modelin.phase(ts, abs_phase=True)
    phss %= 1
    phases = phss.value
    mjds = ts.get_mjds()
    weights = np.array([w["weight"] for w in ts.table["flags"]])
    h = float(hmw(phases, weights))
    print("Htest : {0:.2f} ({1:.2f} sigma)".format(h, h2sig(h)))
    if args.plot:
        log.info("Making phaseogram plot with {0} photons".format(len(mjds)))
        phaseogram(mjds, phases, weights, bins=100, plotfile=args.plotfile)

    if args.addphase:
        # Read input FITS file (again).
        # If overwriting, open in 'update' mode
        if args.outfile is None:
            hdulist = pyfits.open(args.eventfile, mode="update")
        else:
            hdulist = pyfits.open(args.eventfile)
        event_hdu = hdulist[1]
        event_hdr = event_hdu.header
        event_dat = event_hdu.data
        event_mjds = read_fits_event_mjds_tuples(event_hdu)
        mjds_float = np.asarray([r[0] + r[1] for r in event_mjds])
        time_mask = np.logical_and((mjds_float > minmjd),
                                   (mjds_float < maxmjd))
        new_phases = np.full(len(event_dat), -1, dtype=float)
        new_phases[time_mask] = phases

        if "PULSE_PHASE" in event_hdu.columns.names:
            log.info("Found existing PULSE_PHASE column, overwriting...")
            # Overwrite values in existing Column
            event_dat["PULSE_PHASE"] = new_phases
        else:
            # Construct and append new column, preserving HDU header and name
            log.info("Adding new PULSE_PHASE column.")
            phasecol = pyfits.ColDefs([
                pyfits.Column(name="PULSE_PHASE", format="D", array=new_phases)
            ])
            bt = pyfits.BinTableHDU.from_columns(event_hdu.columns + phasecol,
                                                 header=event_hdr,
                                                 name=event_hdu.name)
            hdulist[1] = bt
        if args.outfile is None:
            # Overwrite the existing file
            log.info("Overwriting existing FITS file " + args.eventfile)
            hdulist.flush(verbose=True, output_verify="warn")
        else:
            # Write to new output file
            log.info("Writing output FITS file " + args.outfile)
            hdulist.writeto(args.outfile,
                            overwrite=True,
                            checksum=True,
                            output_verify="warn")

    return 0
Example #31
0
    def generate_polycos(self, model, mjdStart, mjdEnd, obs,
                         segLength, ncoeff, obsFreq, maxha,
                         method = "TEMPO",numNodes = 20):
        """
        Generate the polyco file data file.

        Parameters
        ---------
        model : TimingModel
            TimingModel for generate the Polycos with parameters
            setup.

        mjdStart : float / nump longdouble
            Start time of polycos in mjd

        mjdEnd : float / nump longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength :
            Length of polyco segement [unit: minutes]

        ncoeff :
            number of coefficents

        obsFreq :
            observing frequency

        maxha :
            Maximum hour angle

        method : sting optional ['TEMPO','TEMPO2',...] Default TEMPO
            Method to generate polycos. Now it is only support the TEMPO method.

        numNodes : int optional. Default 20
            Number of nodes for fitting. It can not be less then the number of
            coefficents.
        Return
        ---------

        A polyco table.


        """
        mjdStart = np.longdouble(mjdStart)*u.day
        mjdEnd = np.longdouble(mjdEnd)*u.day
        timeLength = mjdEnd-mjdStart
        segLength = np.longdouble(segLength)*u.min
        obsFreq = float(obsFreq)
        month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug',
                 'Sep','Oct','Nov','Dec']
        # Alocate memery
        coeffs = np.longdouble(np.zeros(ncoeff))
        entryList = []
        entryIntvl = np.arange(mjdStart.value,mjdEnd.value,
                                segLength.to('day').value)
        if entryIntvl[-1] < mjdEnd.value:
            entryIntvl = np.append(entryIntvl, mjdEnd.value)

        # Make sure the number of nodes is bigger then number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff+1
        # generate the ploynomial coefficents
        if method == "TEMPO":
            # Using tempo1 method to create polycos
            for i in range(len(entryIntvl)-1):
                tStart = entryIntvl[i]
                tStop = entryIntvl[i+1]
                nodes = np.linspace(tStart,tStop,numNodes)
                tmid = ((tStart+tStop)/2.0)*u.day
                toaMid = toa.get_TOAs_list([toa.TOA((np.modf(tmid.value)[1],
                                    np.modf(tmid.value)[0]),obs = obs,
                                    freq = obsFreq),])
                refPhase = model.phase(toaMid.table)
                mjdSpan = ((tStop-tStart)*u.day).to('min')
                # Create node toas(Time sample using TOA class)
                toaList = [toa.TOA((np.modf(toaNode)[1],
                                    np.modf(toaNode)[0]),obs = obs,
                                    freq = obsFreq) for toaNode in nodes]

                toas = toa.get_TOAs_list(toaList)

                ph = model.phase(toas.table)
                dt = (nodes*u.day - tmid).to('min') # Use constant
                rdcPhase = ph-refPhase
                rdcPhase = rdcPhase.int-dt.value*model.F0.value*60.0+rdcPhase.frac
                dtd = dt.value.astype(float)  # Trancate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd,rdcPhased,ncoeff-1)
                coeffs = coeffs[::-1]
                midTime = at.Time(int(tmid.value),np.modf(tmid.value)[0],
                                  format = 'mjd',scale = 'utc')
                date,hms = midTime.iso.split()
                yy,mm,dd = date.split('-')
                date = dd+'-'+month[int(mm)-1]+'-'+yy[2:4]
                hms = hms.replace(':',"")
                entry = polycoEntry(tmid.value,mjdSpan.to('day').value,
                                refPhase.int,refPhase.frac, model.F0.value, ncoeff,
                                coeffs,obs)
                entryList.append((model.PSR.value, date, hms, tmid.value,
                                  model.DM.value,0.0,0.0,0.0,obsFreq,entry))

            pTable = table.Table(rows = entryList, names = ('psr','date','utc',
                                  'tmid','dm','dopper','logrms','binary_phase',
                                  'obsfreq','entry'),
                                   meta={'name': 'Ployco Data Table'})
            self.polycoTable = pTable

        else:
                #  Reading from an old polycofile
            pass