Пример #1
0
def load_Fermi_TOAs(ft1name,weightcolumn=None,targetcoord=None,logeref=4.1,
                    logesig=0.5,minweight=0.0, minmjd=0.0, maxmjd=np.inf):
    '''
    TOAlist = load_Fermi_TOAs(ft1name)
      Read photon event times out of a Fermi FT1 file and return
      a list of PINT TOA objects.
      Correctly handles raw FT1 files, or ones processed with gtbary
      to have barycentered or geocentered TOAs.

      weightcolumn specifies the FITS column name to read the photon weights
      from.  The special value 'CALC' causes the weights to be computed empirically
      as in Philippe Bruel's SearchPulsation code.
      logeref and logesig are parameters for the weight computation and are only
      used when weightcolumn='CALC'.

      When weights are loaded, or computed, events are filtered by weight >= minweight
    '''
    import astropy.io.fits as pyfits
    # Load photon times from FT1 file
    hdulist = pyfits.open(ft1name)
    ft1hdr=hdulist[1].header
    ft1dat=hdulist[1].data

    # TIMESYS will be 'TT' for unmodified Fermi LAT events (or geocentered), and
    #                 'TDB' for events barycentered with gtbary
    # TIMEREF will be 'GEOCENTER' for geocentered events,
    #                 'SOLARSYSTEM' for barycentered,
    #             and 'LOCAL' for unmodified events

    timesys = ft1hdr['TIMESYS']
    log.info("TIMESYS {0}".format(timesys))
    timeref = ft1hdr['TIMEREF']
    log.info("TIMEREF {0}".format(timeref))

    # Read time column from FITS file
    mjds = read_fits_event_mjds_tuples(hdulist[1])
    if len(mjds) == 0:
        log.error('No MJDs read from file!')
        raise

    energies = ft1dat.field('ENERGY')*u.MeV
    if weightcolumn is not None:
        if weightcolumn == 'CALC':
            photoncoords = SkyCoord(ft1dat.field('RA')*u.degree,ft1dat.field('DEC')*u.degree,frame='icrs')
            weights = calc_lat_weights(ft1dat.field('ENERGY'),
                photoncoords.separation(targetcoord), logeref=logeref,
                logesig=logesig)
        else:
            weights = ft1dat.field(weightcolumn)
        if minweight > 0.0:
            idx = np.where(weights>minweight)[0]
            mjds = mjds[idx]
            energies = energies[idx]
            weights = weights[idx]

    # limit the TOAs to ones in selected MJD range
    mjds_float = np.array([r[0] + r[1] for r in mjds])
    idx = np.logical_and((mjds_float > minmjd),(mjds_float < maxmjd))
    mjds = mjds[idx]
    energies = energies[idx]
    if weightcolumn is not None:
        weights = weights[idx]

    if timesys == 'TDB':
        log.info("Building barycentered TOAs")
        if weightcolumn is None:
            toalist=[toa.TOA(m,obs='Barycenter',scale='tdb',energy=e) for m,e in zip(mjds,energies)]
        else:
            toalist=[toa.TOA(m,obs='Barycenter',scale='tdb',energy=e,weight=w) for m,e,w in zip(mjds,energies,weights)]
    else:
        if timeref == 'LOCAL':
            log.info('Building spacecraft local TOAs, with MJDs in range {0} to {1}'.format(mjds[0],mjds[-1]))
            assert timesys == 'TT'
            fermiobs = get_observatory('Fermi')

            try:
                if weightcolumn is None:
                    toalist=[toa.TOA(m, obs='Fermi', scale='tt',energy=e)
                            for m,e in zip(mjds,energies)]
                else:
                    toalist=[toa.TOA(m, obs='Fermi', scale='tt',energy=e,weight=w)
                            for m,e,w in zip(mjds,energies,weights)]
            except KeyError:
                log.error('Error processing Fermi TOAs. You may have forgotten to specify an FT2 file with --ft2')
                raise
        else:
            log.info("Building geocentered TOAs")
            if weightcolumn is None:
                toalist=[toa.TOA(m, obs='Geocenter', scale='tt',energy=e) for m,e in zip(mjds,energies)]
            else:
                toalist=[toa.TOA(m, obs='Geocenter', scale='tt',energy=e,weight=w) for m,e,w in zip(mjds,energies,weights)]

    return toalist
Пример #2
0
def load_Fermi_TOAs(ft1name,
                    weightcolumn=None,
                    targetcoord=None,
                    logeref=4.1,
                    logesig=0.5,
                    minweight=0.0,
                    minmjd=0.0,
                    maxmjd=np.inf):
    '''
    TOAlist = load_Fermi_TOAs(ft1name)
      Read photon event times out of a Fermi FT1 file and return
      a list of PINT TOA objects.
      Correctly handles raw FT1 files, or ones processed with gtbary
      to have barycentered or geocentered TOAs.

      weightcolumn specifies the FITS column name to read the photon weights
      from.  The special value 'CALC' causes the weights to be computed empirically
      as in Philippe Bruel's SearchPulsation code.
      logeref and logesig are parameters for the weight computation and are only
      used when weightcolumn='CALC'.

      When weights are loaded, or computed, events are filtered by weight >= minweight
    '''
    import astropy.io.fits as pyfits
    # Load photon times from FT1 file
    hdulist = pyfits.open(ft1name)
    ft1hdr = hdulist[1].header
    ft1dat = hdulist[1].data

    # TIMESYS will be 'TT' for unmodified Fermi LAT events (or geocentered), and
    #                 'TDB' for events barycentered with gtbary
    # TIMEREF will be 'GEOCENTER' for geocentered events,
    #                 'SOLARSYSTEM' for barycentered,
    #             and 'LOCAL' for unmodified events

    timesys = ft1hdr['TIMESYS']
    log.info("TIMESYS {0}".format(timesys))
    timeref = ft1hdr['TIMEREF']
    log.info("TIMEREF {0}".format(timeref))

    # Read time column from FITS file
    mjds = read_fits_event_mjds_tuples(hdulist[1])
    if len(mjds) == 0:
        log.error('No MJDs read from file!')
        raise

    energies = ft1dat.field('ENERGY') * u.MeV
    if weightcolumn is not None:
        if weightcolumn == 'CALC':
            photoncoords = SkyCoord(ft1dat.field('RA') * u.degree,
                                    ft1dat.field('DEC') * u.degree,
                                    frame='icrs')
            weights = calc_lat_weights(ft1dat.field('ENERGY'),
                                       photoncoords.separation(targetcoord),
                                       logeref=logeref,
                                       logesig=logesig)
        else:
            weights = ft1dat.field(weightcolumn)
        if minweight > 0.0:
            idx = np.where(weights > minweight)[0]
            mjds = mjds[idx]
            energies = energies[idx]
            weights = weights[idx]

    # limit the TOAs to ones in selected MJD range
    mjds_float = np.array([r[0] + r[1] for r in mjds])
    idx = np.logical_and((mjds_float > minmjd), (mjds_float < maxmjd))
    mjds = mjds[idx]
    energies = energies[idx]
    if weightcolumn is not None:
        weights = weights[idx]

    if timesys == 'TDB':
        log.info("Building barycentered TOAs")
        if weightcolumn is None:
            toalist = [
                toa.TOA(m,
                        obs='Barycenter',
                        scale='tdb',
                        energy=e,
                        error=1.0 * u.us) for m, e in zip(mjds, energies)
            ]
        else:
            toalist = [
                toa.TOA(m,
                        obs='Barycenter',
                        scale='tdb',
                        energy=e,
                        weight=w,
                        error=1.0 * u.us)
                for m, e, w in zip(mjds, energies, weights)
            ]
    else:
        if timeref == 'LOCAL':
            log.info(
                'Building spacecraft local TOAs, with MJDs in range {0} to {1}'
                .format(mjds[0], mjds[-1]))
            assert timesys == 'TT'
            try:
                fermiobs = get_observatory('Fermi')
            except KeyError:
                log.error(
                    'Fermi observatory not defined. Make sure you have specified an FT2 file!'
                )
                raise

            try:
                if weightcolumn is None:
                    toalist = [
                        toa.TOA(m,
                                obs='Fermi',
                                scale='tt',
                                energy=e,
                                error=1.0 * u.us)
                        for m, e in zip(mjds, energies)
                    ]
                else:
                    toalist = [
                        toa.TOA(m,
                                obs='Fermi',
                                scale='tt',
                                energy=e,
                                weight=w,
                                error=1.0 * u.us)
                        for m, e, w in zip(mjds, energies, weights)
                    ]
            except KeyError:
                log.error(
                    'Error processing Fermi TOAs. You may have forgotten to specify an FT2 file with --ft2'
                )
                raise
        else:
            log.info("Building geocentered TOAs")
            if weightcolumn is None:
                toalist = [
                    toa.TOA(m, obs='Geocenter', scale='tt', energy=e)
                    for m, e in zip(mjds, energies)
                ]
            else:
                toalist = [
                    toa.TOA(m, obs='Geocenter', scale='tt', energy=e, weight=w)
                    for m, e, w in zip(mjds, energies, weights)
                ]

    return toalist
Пример #3
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
Пример #4
0
def load_fits_TOAs(
    eventname,
    mission,
    weights=None,
    extension=None,
    timesys=None,
    timeref=None,
    minmjd=-np.inf,
    maxmjd=np.inf,
):
    """
    Read photon event times out of a FITS file as PINT TOA objects.

    Correctly handles raw event files, or ones processed with axBary to have
    barycentered TOAs. Different conditions may apply to different missions.

    The minmjd/maxmjd parameters can be used to avoid instantiation of TOAs
    we don't want, which can otherwise be very slow.

    Parameters
    ----------
    eventname : str
        File name of the FITS event list
    mission : str
        Name of the mission (e.g. RXTE, XMM)
    weights : array or None
        The array has to be of the same size as the event list. Overwrites
        possible weight lists from mission-specific FITS files
    extension : str
        FITS extension to read
    timesys : str, default None
        Force this time system
    timeref : str, default None
        Forse this time reference
    minmjd : float, default "-infinity"
        minimum MJD timestamp to return
    maxmjd : float, default "infinity"
        maximum MJD timestamp to return

    Returns
    -------
    toalist : list of TOA objects
    """
    # Load photon times from event file
    hdulist = pyfits.open(eventname)
    if mission not in mission_config:
        log.warning("Mission not recognized. Using generic")
        mission = "generic"

    if (extension is not None and isinstance(extension, str)
            and hdulist[1].name not in extension.split(",")):
        raise RuntimeError(
            "First table in FITS file" +
            "must be {}. Found {}".format(extension, hdulist[1].name))
    if isinstance(extension, int) and extension != 1:
        raise ValueError(
            "At the moment, only data in the first FITS extension is supported"
        )

    if timesys is None:
        timesys = _get_timesys(hdulist[1])
    if timeref is None:
        timeref = _get_timeref(hdulist[1])
    check_timesys(timesys)
    check_timeref(timeref)

    if not mission_config[mission]["allow_local"] and timesys != "TDB":
        log.error("Raw spacecraft TOAs not yet supported for " + mission)

    obs, scale = _default_obs_and_scale(mission, timesys, timeref)

    # Read time column from FITS file
    mjds = read_fits_event_mjds_tuples(hdulist[1])

    new_kwargs = _get_columns_from_fits(
        hdulist[1], mission_config[mission]["fits_columns"])

    hdulist.close()

    if weights is not None:
        new_kwargs["weights"] = weights

    # mask out times/columns outside of mjd range
    mjds_float = np.asarray([r[0] + r[1] for r in mjds])
    idx = (minmjd < mjds_float) & (mjds_float < maxmjd)
    mjds = mjds[idx]
    for key in new_kwargs.keys():
        new_kwargs[key] = new_kwargs[key][idx]

    toalist = [None] * len(mjds)
    kw = {}
    for i in range(len(mjds)):
        # Create TOA list
        for key in new_kwargs.keys():
            kw[key] = new_kwargs[key][i]
        toalist[i] = toa.TOA(mjds[i], obs=obs, scale=scale, **kw)

    return toalist
Пример #5
0
def load_Fermi_TOAs(
    ft1name,
    weightcolumn=None,
    targetcoord=None,
    logeref=4.1,
    logesig=0.5,
    minweight=0.0,
    minmjd=-np.inf,
    maxmjd=np.inf,
    fermiobs="Fermi",
):
    """
    toalist = load_Fermi_TOAs(ft1name)
      Read photon event times out of a Fermi FT1 file and return
      a list of PINT TOA objects.
      Correctly handles raw FT1 files, or ones processed with gtbary
      to have barycentered or geocentered TOAs.


    Parameters
    ----------
    weightcolumn : str
        Specifies the FITS column name to read the photon weights from.
        The special value 'CALC' causes the weights to be computed
        empirically as in Philippe Bruel's SearchPulsation code.
    targetcoord : astropy.SkyCoord
        Source coordinate for weight computation if weightcolumn=='CALC'
    logeref : float
        Parameter for the weight computation if weightcolumn=='CALC'
    logesig : float
        Parameter for the weight computation if weightcolumn=='CALC'
    minweight : float
        If weights are loaded or computed, exclude events with smaller weights.
    minmjd : float
        Events with earlier MJDs are excluded.
    maxmjd : float
        Events with later MJDs are excluded.
    fermiobs: str
      The default observatory name is Fermi, and must have already been
      registered.  The user can specify another name

    Returns
    -------
    toalist : list
        A list of TOA objects corresponding to the Fermi events.
    """

    # Load photon times from FT1 file
    hdulist = fits.open(ft1name)
    ft1hdr = hdulist[1].header
    ft1dat = hdulist[1].data

    # TIMESYS will be 'TT' for unmodified Fermi LAT events (or geocentered), and
    #                 'TDB' for events barycentered with gtbary
    # TIMEREF will be 'GEOCENTER' for geocentered events,
    #                 'SOLARSYSTEM' for barycentered,
    #             and 'LOCAL' for unmodified events

    timesys = ft1hdr["TIMESYS"]
    log.info("TIMESYS {0}".format(timesys))
    timeref = ft1hdr["TIMEREF"]
    log.info("TIMEREF {0}".format(timeref))

    # Read time column from FITS file
    mjds = read_fits_event_mjds_tuples(hdulist[1])
    if len(mjds) == 0:
        log.error("No MJDs read from file!")
        raise

    energies = ft1dat.field("ENERGY") * u.MeV
    if weightcolumn is not None:
        if weightcolumn == "CALC":
            photoncoords = SkyCoord(
                ft1dat.field("RA") * u.degree,
                ft1dat.field("DEC") * u.degree,
                frame="icrs",
            )
            weights = calc_lat_weights(
                ft1dat.field("ENERGY"),
                photoncoords.separation(targetcoord),
                logeref=logeref,
                logesig=logesig,
            )
        else:
            weights = ft1dat.field(weightcolumn)
        if minweight > 0.0:
            idx = np.where(weights > minweight)[0]
            mjds = mjds[idx]
            energies = energies[idx]
            weights = weights[idx]

    # limit the TOAs to ones in selected MJD range
    mjds_float = np.asarray([r[0] + r[1] for r in mjds])
    idx = (minmjd < mjds_float) & (mjds_float < maxmjd)
    mjds = mjds[idx]
    energies = energies[idx]
    if weightcolumn is not None:
        weights = weights[idx]

    if timesys == "TDB":
        log.info("Building barycentered TOAs")
        obs = "Barycenter"
        scale = "tdb"
        msg = "barycentric"
    elif (timesys == "TT") and (timeref == "LOCAL"):
        assert timesys == "TT"
        try:
            get_observatory(fermiobs)
        except KeyError:
            log.error(
                "%s observatory not defined. Make sure you have specified an FT2 file!"
                % fermiobs)
            raise
        obs = fermiobs
        scale = "tt"
        msg = "spacecraft local"
    elif (timesys == "TT") and (timeref == "GEOCENTRIC"):
        obs = "Geocenter"
        scale = "tt"
        msg = "geocentric"
    else:
        raise ValueError("Unrecognized TIMEREF/TIMESYS.")

    log.info("Building {0} TOAs, with MJDs in range {1} to {2}".format(
        msg, mjds[0, 0] + mjds[0, 1], mjds[-1, 0] + mjds[-1, 1]))
    if weightcolumn is None:
        toalist = [
            toa.TOA(m,
                    obs=obs,
                    scale=scale,
                    energy=str(e.to_value(u.MeV)),
                    error=1.0 * u.us) for m, e in zip(mjds, energies)
        ]
    else:
        toalist = [
            toa.TOA(
                m,
                obs=obs,
                scale=scale,
                energy=str(e.to_value(u.MeV)),
                weight=str(w),
                error=1.0 * u.us,
            ) for m, e, w in zip(mjds, energies, weights)
        ]

    return toalist
Пример #6
0
def load_fits_TOAs(
    eventname, mission, weights=None, extension=None, timesys=None, timeref=None
):
    """
    Read photon event times out of a FITS file as PINT TOA objects.

    Correctly handles raw event files, or ones processed with axBary to have
    barycentered  TOAs. Different conditions may apply to different missions.

    Parameters
    ----------
    eventname : str
        File name of the FITS event list
    mission : str
        Name of the mission (e.g. RXTE, XMM)
    weights : array or None
        The array has to be of the same size as the event list. Overwrites
        possible weight lists from mission-specific FITS files
    extension : str
        FITS extension to read
    timesys : str, default None
        Force this time system
    timeref : str, default None
        Forse this time reference

    Returns
    -------
    toalist : list of TOA objects
    """
    # Load photon times from event file
    hdulist = pyfits.open(eventname)

    if extension is not None and hdulist[1].name not in extension.split(","):
        raise RuntimeError(
            "First table in FITS file"
            + "must be {}. Found {}".format(extension, hdulist[1].name)
        )

    if timesys is None:
        timesys = _get_timesys(hdulist[1])
    if timeref is None:
        timeref = _get_timeref(hdulist[1])
    check_timesys(timesys)
    check_timeref(timeref)

    if not mission_config[mission]["allow_local"] and timesys != "TDB":
        log.error("Raw spacecraft TOAs not yet supported for " + mission)

    obs, scale = _default_obs_and_scale(mission, timesys, timeref)

    # Read time column from FITS file
    mjds = read_fits_event_mjds_tuples(hdulist[1])

    new_kwargs = _get_columns_from_fits(
        hdulist[1], mission_config[mission]["fits_columns"]
    )

    hdulist.close()

    if weights is not None:
        new_kwargs["weights"] = weights

    toalist = [None] * len(mjds)
    kw = {}
    for i in range(len(mjds)):
        # Create TOA list
        for key in new_kwargs.keys():
            kw[key] = new_kwargs[key][i]
        toalist[i] = toa.TOA(mjds[i], obs=obs, scale=scale, **kw)

    return toalist