Пример #1
0
def create_gti(fname,
               filter_expr,
               safe_interval=[0, 0],
               outfile=None,
               minimum_length=0):
    """Create a GTI list by using boolean operations on file data.

    Parameters
    ----------
    fname : str
        File name. The file must be in HENDRICS format.
    filter_expr : str
        A boolean condition on one or more of the arrays contained in the data.
        E.g. '(lc > 10) & (lc < 20)'

    Returns
    -------
    gtis : [[gti0_0, gti0_1], [gti1_0, gti1_1], ...]
        The newly created GTIs

    Other parameters
    ----------------
    safe_interval : float or [float, float]
        A safe interval to exclude at both ends (if single float) or the start
        and the end (if pair of values) of GTIs.
    outfile : str
        The output file name. If None, use a default root + '_gti' combination
    """
    # Necessary as nc variables are sometimes defined as array
    from numpy import array  # NOQA

    ftype, data = get_file_type(fname, raw_data=True)

    instr = data['instr']
    if ftype == 'lc' and instr.lower() == 'pca':
        logging.warning('RXTE/PCA data; normalizing lc per no. PCUs')
        # If RXTE, plot per PCU count rate
        data['counts'] /= data['nPCUs']
    mjdref = data['mjdref']
    # Map all entries of data to local variables
    locals().update(data)

    good = eval(filter_expr)

    gtis = create_gti_from_condition(locals()['time'],
                                     good,
                                     safe_interval=safe_interval)

    gtis = filter_gti_by_length(gtis, minimum_length)

    outfile = _assign_value_if_none(
        outfile,
        hen_root(fname) + '_gti' + HEN_FILE_EXTENSION)
    save_data({
        'gti': gtis,
        'mjdref': mjdref,
        '__sr__class__type__': 'gti'
    }, outfile)

    return gtis
Пример #2
0
def lcurve_from_fits(
    fits_file,
    gtistring="GTI",
    timecolumn="TIME",
    ratecolumn=None,
    ratehdu=1,
    fracexp_limit=0.9,
    outfile=None,
    noclobber=False,
    outdir=None,
):
    """Load a lightcurve from a fits file.

    .. note ::
        FITS light curve handling is still under testing.
        Absolute times might be incorrect depending on the light curve format.

    Parameters
    ----------
    fits_file : str
        File name of the input light curve in FITS format

    Returns
    -------
    data : dict
        Dictionary containing all information needed to create a
        :class:`stingray.Lightcurve` object

    Other Parameters
    ----------------
    gtistring : str
        Name of the GTI extension in the FITS file
    timecolumn : str
        Name of the column containing times in the FITS file
    ratecolumn : str
        Name of the column containing rates in the FITS file
    ratehdu : str or int
        Name or index of the FITS extension containing the light curve
    fracexp_limit : float
        Minimum exposure fraction allowed
    noclobber : bool
        If True, do not overwrite existing files
    """
    warnings.warn(
        """WARNING! FITS light curve handling is still under testing.
        Absolute times might be incorrect."""
    )
    # TODO:
    # treat consistently TDB, UTC, TAI, etc. This requires some documentation
    # reading. For now, we assume TDB
    from astropy.io import fits as pf
    from astropy.time import Time
    import numpy as np
    from stingray.gti import create_gti_from_condition

    lchdulist = pf.open(fits_file)
    lctable = lchdulist[ratehdu].data

    # Units of header keywords
    tunit = lchdulist[ratehdu].header["TIMEUNIT"]

    try:
        mjdref = high_precision_keyword_read(
            lchdulist[ratehdu].header, "MJDREF"
        )
        mjdref = Time(mjdref, scale="tdb", format="mjd")
    except Exception:
        mjdref = None

    try:
        instr = lchdulist[ratehdu].header["INSTRUME"]
    except Exception:
        instr = "EXTERN"

    # ----------------------------------------------------------------
    # Trying to comply with all different formats of fits light curves.
    # It's a madness...
    try:
        tstart = high_precision_keyword_read(
            lchdulist[ratehdu].header, "TSTART"
        )
        tstop = high_precision_keyword_read(lchdulist[ratehdu].header, "TSTOP")
    except Exception:  # pragma: no cover
        raise (Exception("TSTART and TSTOP need to be specified"))

    # For nulccorr lcs this whould work

    timezero = high_precision_keyword_read(
        lchdulist[ratehdu].header, "TIMEZERO"
    )
    # Sometimes timezero is "from tstart", sometimes it's an absolute time.
    # This tries to detect which case is this, and always consider it
    # referred to tstart
    timezero = assign_value_if_none(timezero, 0)

    # for lcurve light curves this should instead work
    if tunit == "d":
        # TODO:
        # Check this. For now, I assume TD (JD - 2440000.5).
        # This is likely wrong
        timezero = Time(2440000.5 + timezero, scale="tdb", format="jd")
        tstart = Time(2440000.5 + tstart, scale="tdb", format="jd")
        tstop = Time(2440000.5 + tstop, scale="tdb", format="jd")
        # if None, use NuSTAR defaulf MJDREF
        mjdref = assign_value_if_none(
            mjdref,
            Time(
                np.longdouble("55197.00076601852"), scale="tdb", format="mjd"
            ),
        )

        timezero = (timezero - mjdref).to("s").value
        tstart = (tstart - mjdref).to("s").value
        tstop = (tstop - mjdref).to("s").value

    if timezero > tstart:
        timezero -= tstart

    time = np.array(lctable.field(timecolumn), dtype=np.longdouble)
    if time[-1] < tstart:
        time += timezero + tstart
    else:
        time += timezero

    try:
        dt = high_precision_keyword_read(lchdulist[ratehdu].header, "TIMEDEL")
        if tunit == "d":
            dt *= 86400
    except Exception:
        warnings.warn(
            "Assuming that TIMEDEL is the median difference between the"
            " light curve times",
            AstropyUserWarning,
        )
        # Avoid NaNs
        good = time == time
        dt = np.median(np.diff(time[good]))

    # ----------------------------------------------------------------
    if ratecolumn is None:
        for name in ["RATE", "RATE1", "COUNTS"]:
            if name in lctable.names:
                ratecolumn = name
                break
        else:  # pragma: no cover
            raise ValueError(
                "None of the accepted rate columns were found in the file")

    rate = np.array(lctable.field(ratecolumn), dtype=float)

    errorcolumn = "ERROR"
    if ratecolumn == "RATE1":
        errorcolumn = "ERROR1"

    try:
        rate_e = np.array(lctable.field(errorcolumn), dtype=np.longdouble)
    except Exception:
        rate_e = np.zeros_like(rate)

    if "RATE" in ratecolumn:
        rate *= dt
        rate_e *= dt

    try:
        fracexp = np.array(lctable.field("FRACEXP"), dtype=np.longdouble)
    except Exception:
        fracexp = np.ones_like(rate)

    good_intervals = (
        (rate == rate) * (fracexp >= fracexp_limit) * (fracexp <= 1)
    )

    rate[good_intervals] /= fracexp[good_intervals]
    rate_e[good_intervals] /= fracexp[good_intervals]

    rate[~good_intervals] = 0

    try:
        gtitable = lchdulist[gtistring].data
        gti_list = np.array(
            [
                [a, b]
                for a, b in zip(
                    gtitable.field("START"), gtitable.field("STOP")
                )
            ],
            dtype=np.longdouble,
        )
    except Exception:
        gti_list = create_gti_from_condition(time, good_intervals)

    lchdulist.close()

    res = {"time": time,
           "counts": rate,
           "err": rate_e,
           "gti": gti_list,
           "mjdref": mjdref.mjd,
           "dt": dt,
           "instr": instr,
           "header": lchdulist[ratehdu].header.tostring()}
    return res
Пример #3
0
def lcurve_from_fits(fits_file,
                     gtistring='GTI',
                     timecolumn='TIME',
                     ratecolumn=None,
                     ratehdu=1,
                     fracexp_limit=0.9,
                     outfile=None,
                     noclobber=False,
                     outdir=None):
    """
    Load a lightcurve from a fits file and save it in HENDRICS format.

    .. note ::
        FITS light curve handling is still under testing.
        Absolute times might be incorrect depending on the light curve format.

    Parameters
    ----------
    fits_file : str
        File name of the input light curve in FITS format

    Returns
    -------
    outfile : [str]
        Returned as a list with a single element for consistency with
        `lcurve_from_events`

    Other Parameters
    ----------------
    gtistring : str
        Name of the GTI extension in the FITS file
    timecolumn : str
        Name of the column containing times in the FITS file
    ratecolumn : str
        Name of the column containing rates in the FITS file
    ratehdu : str or int
        Name or index of the FITS extension containing the light curve
    fracexp_limit : float
        Minimum exposure fraction allowed
    outfile : str
        Output file name
    noclobber : bool
        If True, do not overwrite existing files
    """
    logging.warning(
        """WARNING! FITS light curve handling is still under testing.
        Absolute times might be incorrect.""")
    # TODO:
    # treat consistently TDB, UTC, TAI, etc. This requires some documentation
    # reading. For now, we assume TDB
    from astropy.io import fits as pf
    from astropy.time import Time
    import numpy as np
    from stingray.gti import create_gti_from_condition

    outfile = assign_value_if_none(outfile, hen_root(fits_file) + '_lc')
    outfile = outfile.replace(HEN_FILE_EXTENSION, '') + HEN_FILE_EXTENSION
    outdir = assign_value_if_none(outdir,
                                  os.path.dirname(os.path.abspath(fits_file)))

    _, outfile = os.path.split(outfile)
    mkdir_p(outdir)
    outfile = os.path.join(outdir, outfile)

    if noclobber and os.path.exists(outfile):
        warnings.warn('File exists, and noclobber option used. Skipping')
        return [outfile]

    lchdulist = pf.open(fits_file)
    lctable = lchdulist[ratehdu].data

    # Units of header keywords
    tunit = lchdulist[ratehdu].header['TIMEUNIT']

    try:
        mjdref = high_precision_keyword_read(lchdulist[ratehdu].header,
                                             'MJDREF')
        mjdref = Time(mjdref, scale='tdb', format='mjd')
    except:
        mjdref = None

    try:
        instr = lchdulist[ratehdu].header['INSTRUME']
    except:
        instr = 'EXTERN'

    # ----------------------------------------------------------------
    # Trying to comply with all different formats of fits light curves.
    # It's a madness...
    try:
        tstart = high_precision_keyword_read(lchdulist[ratehdu].header,
                                             'TSTART')
        tstop = high_precision_keyword_read(lchdulist[ratehdu].header, 'TSTOP')
    except:
        raise (Exception('TSTART and TSTOP need to be specified'))

    # For nulccorr lcs this whould work

    timezero = high_precision_keyword_read(lchdulist[ratehdu].header,
                                           'TIMEZERO')
    # Sometimes timezero is "from tstart", sometimes it's an absolute time.
    # This tries to detect which case is this, and always consider it
    # referred to tstart
    timezero = assign_value_if_none(timezero, 0)

    # for lcurve light curves this should instead work
    if tunit == 'd':
        # TODO:
        # Check this. For now, I assume TD (JD - 2440000.5).
        # This is likely wrong
        timezero = Time(2440000.5 + timezero, scale='tdb', format='jd')
        tstart = Time(2440000.5 + tstart, scale='tdb', format='jd')
        tstop = Time(2440000.5 + tstop, scale='tdb', format='jd')
        # if None, use NuSTAR defaulf MJDREF
        mjdref = assign_value_if_none(
            mjdref,
            Time(np.longdouble('55197.00076601852'), scale='tdb',
                 format='mjd'))

        timezero = (timezero - mjdref).to('s').value
        tstart = (tstart - mjdref).to('s').value
        tstop = (tstop - mjdref).to('s').value

    if timezero > tstart:
        timezero -= tstart

    time = np.array(lctable.field(timecolumn), dtype=np.longdouble)
    if time[-1] < tstart:
        time += timezero + tstart
    else:
        time += timezero

    try:
        dt = high_precision_keyword_read(lchdulist[ratehdu].header, 'TIMEDEL')
        if tunit == 'd':
            dt *= 86400
    except:
        warnings.warn('Assuming that TIMEDEL is the difference between the'
                      ' first two times of the light curve')
        dt = time[1] - time[0]

    # ----------------------------------------------------------------
    ratecolumn = assign_value_if_none(
        ratecolumn,
        _look_for_array_in_array(['RATE', 'RATE1', 'COUNTS'], lctable.names))

    rate = np.array(lctable.field(ratecolumn), dtype=np.float)

    try:
        rate_e = np.array(lctable.field('ERROR'), dtype=np.longdouble)
    except:
        rate_e = np.zeros_like(rate)

    if 'RATE' in ratecolumn:
        rate *= dt
        rate_e *= dt

    try:
        fracexp = np.array(lctable.field('FRACEXP'), dtype=np.longdouble)
    except:
        fracexp = np.ones_like(rate)

    good_intervals = (rate == rate) * (fracexp >= fracexp_limit) * \
        (fracexp <= 1)

    rate[good_intervals] /= fracexp[good_intervals]
    rate_e[good_intervals] /= fracexp[good_intervals]

    rate[np.logical_not(good_intervals)] = 0

    try:
        gtitable = lchdulist[gtistring].data
        gti_list = np.array(
            [[a, b]
             for a, b in zip(gtitable.field('START'), gtitable.field('STOP'))],
            dtype=np.longdouble)
    except:
        gti_list = create_gti_from_condition(time, good_intervals)

    lchdulist.close()

    lc = Lightcurve(time=time,
                    counts=rate,
                    err=rate_e,
                    gti=gti_list,
                    mjdref=mjdref.mjd)

    lc.instr = instr
    lc.header = lchdulist[ratehdu].header.tostring()

    logging.info('Saving light curve to %s' % outfile)
    save_lcurve(lc, outfile)
    return [outfile]
Пример #4
0
 def test_gti_from_condition_fail(self):
     t = np.array([0, 1, 2, 3])
     condition = np.array([1, 1, 1], dtype=bool)
     with pytest.raises(StingrayError) as excinfo:
         _ = create_gti_from_condition(t, condition, safe_interval=1)
     assert "The length of the" in str(excinfo.value)
Пример #5
0
 def test_gti_from_condition2(self):
     t = np.array([0, 1, 2, 3, 4, 5, 6])
     condition = np.array([1, 1, 1, 1, 0, 1, 0], dtype=bool)
     gti = create_gti_from_condition(t, condition, safe_interval=1)
     assert np.allclose(gti, np.array([[0.5, 2.5]]))
Пример #6
0
 def test_gti_from_condition1(self):
     t = np.array([0, 1, 2, 3, 4, 5, 6])
     condition = np.array([1, 1, 0, 0, 1, 0, 0], dtype=bool)
     gti = create_gti_from_condition(t, condition)
     assert np.allclose(gti, np.array([[-0.5, 1.5], [3.5, 4.5]]))