Exemplo n.º 1
0
def trim_throughput(indir, outdir):
    '''downsample throughput files'''
    assert os.path.basename(indir) == 'throughput'
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    for targettype in ('elg', 'lrg', 'perfect', 'qso', 'sky', 'star'):
        filename = 'fiberloss-{}.dat'.format(targettype)
        shutil.copy(os.path.join(indir, filename),
                    os.path.join(outdir, filename))

    for filename in ['thru-b.fits', 'thru-r.fits', 'thru-z.fits']:
        fx = fits.open(indir + '/' + filename)
        hdus = HDUList()
        hdus.append(fx[0])
        hdus.append(BinTableHDU(fx[1].data[::20], header=fx[1].header))
        hdus.append(BinTableHDU(fx[2].data[::20], header=fx[2].header))
        hdus.writeto(outdir + '/' + filename)
        fx.close()

    for filename in [
            'DESI-0347_blur.ecsv', 'DESI-0347_offset.ecsv',
            'DESI-0347_random_offset_1.fits'
    ]:
        shutil.copy(os.path.join(indir, filename),
                    os.path.join(outdir, filename))
Exemplo n.º 2
0
    def setup_class(self):
        self.data1 = np.array(list(
            zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], [2.3, 4.5, 6.7, 8.9])),
                              dtype=[('a', int), ('b', 'U1'), ('c', float)])
        self.data2 = np.array(list(
            zip([1.4, 2.3, 3.2, 4.7], [2.3, 4.5, 6.7, 8.9])),
                              dtype=[('p', float), ('q', float)])
        hdu1 = PrimaryHDU()
        hdu2 = BinTableHDU(self.data1, name='first')
        hdu3 = BinTableHDU(self.data2, name='second')

        self.hdus = HDUList([hdu1, hdu2, hdu3])
Exemplo n.º 3
0
def table_to_bintablehdu(table, extname=None):
    """
    Convert an astropy Table object to a BinTableHDU before writing to disk.

    Parameters
    ----------
    table: astropy.table.Table instance
        the table to be converted to a BinTableHDU
    extname: str
        name to go in the EXTNAME field of the FITS header

    Returns
    -------
    BinTableHDU
    """
    add_header_to_table(table)
    array = table.as_array()
    header = table.meta['header'].copy()
    if extname:
        header['EXTNAME'] = (extname, 'added by AstroData')
    coldefs = []
    for n, name in enumerate(array.dtype.names, 1):
        coldefs.append(
            Column(name=header.get('TTYPE{}'.format(n)),
                   format=header.get('TFORM{}'.format(n)),
                   unit=header.get('TUNIT{}'.format(n)),
                   null=header.get('TNULL{}'.format(n)),
                   bscale=header.get('TSCAL{}'.format(n)),
                   bzero=header.get('TZERO{}'.format(n)),
                   disp=header.get('TDISP{}'.format(n)),
                   start=header.get('TBCOL{}'.format(n)),
                   dim=header.get('TDIM{}'.format(n)),
                   array=array[name]))

    return BinTableHDU(data=FITS_rec.from_columns(coldefs), header=header)
Exemplo n.º 4
0
 def test_read_from_fileobj(self, tmpdir):
     filename = str(tmpdir.join('test_read_from_fileobj.fits'))
     hdu = BinTableHDU(self.data)
     hdu.writeto(filename, overwrite=True)
     with open(filename, 'rb') as f:
         t = Table.read(f)
     assert equal_data(t, self.data)
Exemplo n.º 5
0
 def test_read_with_nonstandard_units(self):
     hdu = BinTableHDU(self.data)
     hdu.columns[0].unit = 'RADIANS'
     hdu.columns[1].unit = 'spam'
     hdu.columns[2].unit = 'millieggs'
     t = Table.read(hdu)
     assert equal_data(t, self.data)
Exemplo n.º 6
0
def create_psf_table_hdu(
    psf,
    true_energy_bins,
    source_offset_bins,
    fov_offset_bins,
    extname="PSF",
    **header_cards,
):
    """
    Create a fits binary table HDU in GADF format for the PSF table.
    See the specification at
    https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/psf/psf_table/index.html

    Parameters
    ----------
    psf: astropy.units.Quantity[(solid angle)^-1]
        Point spread function array, must have shape
        (n_energy_bins, n_fov_offset_bins, n_source_offset_bins)
    true_energy_bins: astropy.units.Quantity[energy]
        Bin edges in true energy
    source_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the source offset.
    fov_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the field of view offset.
        For Point-Like IRFs, only giving a single bin is appropriate.
    extname: str
        Name for BinTableHDU
    **header_cards
        Additional metadata to add to the header, use this to set e.g. TELESCOP or
        INSTRUME.
    """

    psf = QTable({
        "ENERG_LO":
        u.Quantity(true_energy_bins[:-1], ndmin=2).to(u.TeV),
        "ENERG_HI":
        u.Quantity(true_energy_bins[1:], ndmin=2).to(u.TeV),
        "THETA_LO":
        u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg),
        "THETA_HI":
        u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg),
        "RAD_LO":
        u.Quantity(source_offset_bins[:-1], ndmin=2).to(u.deg),
        "RAD_HI":
        u.Quantity(source_offset_bins[1:], ndmin=2).to(u.deg),
        # transpose as FITS uses opposite dimension order
        "RPSF":
        psf.T[np.newaxis, ...].to(1 / u.sr),
    })

    # required header keywords
    header = DEFAULT_HEADER.copy()
    header["HDUCLAS1"] = "RESPONSE"
    header["HDUCLAS2"] = "PSF"
    header["HDUCLAS3"] = "FULL-ENCLOSURE"
    header["HDUCLAS4"] = "PSF_TABLE"
    header["DATE"] = Time.now().utc.iso
    _add_header_cards(header, **header_cards)

    return BinTableHDU(psf, header=header, name=extname)
Exemplo n.º 7
0
def create_energy_dispersion_hdu(
    energy_dispersion,
    true_energy_bins,
    migration_bins,
    fov_offset_bins,
    point_like=True,
    extname="EDISP",
    **header_cards,
):
    """
    Create a fits binary table HDU in GADF format for the energy dispersion.
    See the specification at
    https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/aeff/index.html

    Parameters
    ----------
    energy_dispersion: numpy.ndarray
        Energy dispersion array, must have shape
        (n_energy_bins, n_migra_bins, n_source_offset_bins)
    true_energy_bins: astropy.units.Quantity[energy]
        Bin edges in true energy
    migration_bins: numpy.ndarray
        Bin edges for the relative energy migration (``reco_energy / true_energy``)
    fov_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the field of view offset.
        For Point-Like IRFs, only giving a single bin is appropriate.
    point_like: bool
        If the provided effective area was calculated after applying a direction cut,
        pass ``True``, else ``False`` for a full-enclosure effective area.
    extname: str
        Name for BinTableHDU
    **header_cards
        Additional metadata to add to the header, use this to set e.g. TELESCOP or
        INSTRUME.
    """

    psf = QTable(
        {
            "ENERG_LO": u.Quantity(true_energy_bins[:-1], ndmin=2).to(u.TeV),
            "ENERG_HI": u.Quantity(true_energy_bins[1:], ndmin=2).to(u.TeV),
            "MIGRA_LO": u.Quantity(migration_bins[:-1], ndmin=2).to(u.one),
            "MIGRA_HI": u.Quantity(migration_bins[1:], ndmin=2).to(u.one),
            "THETA_LO": u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg),
            "THETA_HI": u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg),
            # transpose as FITS uses opposite dimension order
            "MATRIX": u.Quantity(energy_dispersion.T[np.newaxis, ...]).to(u.one),
        }
    )

    # required header keywords
    header = DEFAULT_HEADER.copy()
    header["HDUCLAS1"] = "RESPONSE"
    header["HDUCLAS2"] = "EDISP"
    header["HDUCLAS3"] = "POINT-LIKE" if point_like else "FULL-ENCLOSURE"
    header["HDUCLAS4"] = "EDISP_2D"
    header["DATE"] = Time.now().utc.iso
    _add_header_cards(header, **header_cards)

    return BinTableHDU(psf, header=header, name=extname)
Exemplo n.º 8
0
 def test_read_with_unit_aliases(self, table_type):
     hdu = BinTableHDU(self.data)
     hdu.columns[0].unit = 'Angstroms'
     hdu.columns[2].unit = 'ergs/(cm.s.Angstroms)'
     with u.set_enabled_aliases(dict(Angstroms=u.AA, ergs=u.erg)):
         t = table_type.read(hdu)
     assert t['a'].unit == u.AA
     assert t['c'].unit == u.erg / (u.cm * u.s * u.AA)
Exemplo n.º 9
0
 def test_read_with_nonstandard_units(self):
     hdu = BinTableHDU(self.data)
     hdu.columns[0].unit = 'RADIANS'
     hdu.columns[1].unit = 'spam'
     hdu.columns[2].unit = 'millieggs'
     with pytest.warns(u.UnitsWarning, match="did not parse as fits unit"):
         t = Table.read(hdu)
     assert equal_data(t, self.data)
Exemplo n.º 10
0
def fake_hdulist(extver=1, version=2, timesys="TDB", telescop="KEPLER"):
    new_header = fake_header(extver, version, timesys, telescop)
    return [
        HDUList(hdus=[
            PrimaryHDU(header=new_header),
            BinTableHDU(header=new_header, name="LIGHTCURVE")
        ])
    ]
Exemplo n.º 11
0
def test_exposure_extra_hdu(exposure, index):

    extra_hdu = BinTableHDU(Table(rows=[[1, 2, 3]], names=["a", "b", "c"]))
    exposure.add_hdu(extra_hdu, index=index)

    hdulist = exposure.to_hdu()
    assert len(hdulist) == 2

    hdu_index = 1 if index is None else index
    assert isinstance(hdulist[hdu_index], BinTableHDU)
Exemplo n.º 12
0
    def setup_class(self):
        self.data1 = np.array(list(
            zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], [2.3, 4.5, 6.7, 8.9])),
                              dtype=[('a', int), ('b', 'U1'), ('c', float)])
        self.data2 = np.array(list(
            zip([1.4, 2.3, 3.2, 4.7], [2.3, 4.5, 6.7, 8.9])),
                              dtype=[('p', float), ('q', float)])
        self.data3 = np.array(list(zip([1, 2, 3, 4], [2.3, 4.5, 6.7, 8.9])),
                              dtype=[('A', int), ('B', float)])
        hdu0 = PrimaryHDU()
        hdu1 = BinTableHDU(self.data1, name='first')
        hdu2 = BinTableHDU(self.data2, name='second')
        hdu3 = ImageHDU(np.ones((3, 3)), name='third')
        hdu4 = BinTableHDU(self.data3)

        self.hdus = HDUList([hdu0, hdu1, hdu2, hdu3, hdu4])
        self.hdusb = HDUList([hdu0, hdu3, hdu2, hdu1])
        self.hdus3 = HDUList([hdu0, hdu3, hdu2])
        self.hdus2 = HDUList([hdu0, hdu1, hdu3])
        self.hdus1 = HDUList([hdu0, hdu1])
Exemplo n.º 13
0
def trim_quickpsf(indir, outdir, filename):
    assert os.path.abspath(indir) != os.path.abspath(outdir)
    infile = os.path.join(indir, filename)
    outfile = os.path.join(outdir, filename)
    fx = fits.open(infile)
    hdus = HDUList()
    hdus.append(fx[0])
    for i in [1,2,3]:
        d = fx[i].data
        hdus.append(BinTableHDU(d[::10], header=fx[i].header))
    hdus.writeto(outfile, clobber=True)
    fx.close()
Exemplo n.º 14
0
def create_rad_max_hdu(
    rad_max,
    reco_energy_bins,
    fov_offset_bins,
    point_like=True,
    extname="RAD_MAX",
    **header_cards,
):
    """
    Create a fits binary table HDU in GADF format for the directional cut.
    See the specification at
    https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/aeff/index.html

    Parameters
    ----------
    rad_max: astropy.units.Quantity[angle]
        Array of the directional (theta) cut.
        Must have shape (n_reco_energy_bins, n_fov_offset_bins)
    reco_energy_bins: astropy.units.Quantity[energy]
        Bin edges in reconstructed energy
    fov_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the field of view offset.
        For Point-Like IRFs, only giving a single bin is appropriate.
    extname: str
        Name for BinTableHDU
    **header_cards
        Additional metadata to add to the header, use this to set e.g. TELESCOP or
        INSTRUME.
    """
    rad_max_table = QTable({
        "ENERG_LO":
        u.Quantity(reco_energy_bins[:-1], ndmin=2).to(u.TeV),
        "ENERG_HI":
        u.Quantity(reco_energy_bins[1:], ndmin=2).to(u.TeV),
        "THETA_LO":
        u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg),
        "THETA_HI":
        u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg),
        # transpose as FITS uses opposite dimension order
        "RAD_MAX":
        rad_max.T[np.newaxis, ...].to(u.deg),
    })

    # required header keywords
    header = DEFAULT_HEADER.copy()
    header["HDUCLAS1"] = "RESPONSE"
    header["HDUCLAS2"] = "RAD_MAX"
    header["HDUCLAS3"] = "POINT-LIKE"
    header["HDUCLAS4"] = "RAD_MAX_2D"
    header["DATE"] = Time.now().utc.iso
    _add_header_cards(header, **header_cards)

    return BinTableHDU(rad_max_table, header=header, name=extname)
Exemplo n.º 15
0
def create_background_2d_hdu(
    background_2d,
    reco_energy_bins,
    fov_offset_bins,
    extname="BACKGROUND",
    **header_cards,
):
    """
    Create a fits binary table HDU in GADF format for the background 2d table.
    See the specification at
    https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/bkg/index.html#bkg-2d

    Parameters
    ----------
    background_2d: astropy.units.Quantity[(MeV s sr)^-1]
        Background rate, must have shape
        (n_energy_bins, n_fov_offset_bins)
    reco_energy_bins: astropy.units.Quantity[energy]
        Bin edges in reconstructed energy
    fov_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the field of view offset.
    extname: str
        Name for BinTableHDU
    **header_cards
        Additional metadata to add to the header, use this to set e.g. TELESCOP or
        INSTRUME.
    """

    bkg = QTable({
        "ENERG_LO":
        u.Quantity(reco_energy_bins[:-1], ndmin=2).to(u.TeV),
        "ENERG_HI":
        u.Quantity(reco_energy_bins[1:], ndmin=2).to(u.TeV),
        "THETA_LO":
        u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg),
        "THETA_HI":
        u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg),
        # transpose as FITS uses opposite dimension order
        "BKG":
        background_2d.T[np.newaxis, ...].to(GADF_BACKGROUND_UNIT),
    })

    # required header keywords
    header = DEFAULT_HEADER.copy()
    header["HDUCLAS1"] = "RESPONSE"
    header["HDUCLAS2"] = "BKG"
    header["HDUCLAS3"] = "FULL-ENCLOSURE"
    header["HDUCLAS4"] = "BKG_2D"
    header["DATE"] = Time.now().utc.iso
    _add_header_cards(header, **header_cards)

    return BinTableHDU(bkg, header=header, name=extname)
Exemplo n.º 16
0
def create_aeff2d_hdu(
    effective_area,
    true_energy_bins,
    fov_offset_bins,
    extname="EFFECTIVE AREA",
    point_like=True,
    **header_cards,
):
    """
    Create a fits binary table HDU in GADF format for effective area.
    See the specification at
    https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/aeff/index.html

    Parameters
    ----------
    effective_area: astropy.units.Quantity[area]
        Effective area array, must have shape (n_energy_bins, n_fov_offset_bins)
    true_energy_bins: astropy.units.Quantity[energy]
        Bin edges in true energy
    fov_offset_bins: astropy.units.Quantity[angle]
        Bin edges in the field of view offset.
        For Point-Like IRFs, only giving a single bin is appropriate.
    point_like: bool
        If the provided effective area was calculated after applying a direction cut,
        pass ``True``, else ``False`` for a full-enclosure effective area.
    extname: str
        Name for BinTableHDU
    **header_cards
        Additional metadata to add to the header, use this to set e.g. TELESCOP or
        INSTRUME.
    """
    aeff = QTable()
    aeff["ENERG_LO"] = u.Quantity(true_energy_bins[:-1], ndmin=2).to(u.TeV)
    aeff["ENERG_HI"] = u.Quantity(true_energy_bins[1:], ndmin=2).to(u.TeV)
    aeff["THETA_LO"] = u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg)
    aeff["THETA_HI"] = u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg)
    # transpose because FITS uses opposite dimension order than numpy
    aeff["EFFAREA"] = effective_area.T[np.newaxis, ...].to(u.m**2)

    # required header keywords
    header = DEFAULT_HEADER.copy()
    header["HDUCLAS1"] = "RESPONSE"
    header["HDUCLAS2"] = "EFF_AREA"
    header["HDUCLAS3"] = "POINT-LIKE" if point_like else "FULL-ENCLOSURE"
    header["HDUCLAS4"] = "AEFF_2D"
    header["DATE"] = Time.now().utc.iso
    _add_header_cards(header, **header_cards)

    return BinTableHDU(aeff, header=header, name=extname)
Exemplo n.º 17
0
def write_table_fits(input, output, overwrite=False):
    """
    Write a Table object to a FITS file

    Parameters
    ----------
    input : Table
        The table to write out.
    output : str
        The filename to write the table to.
    overwrite : bool
        Whether to overwrite any existing file without warning.
    """

    # Check if output file already exists
    if isinstance(output, six.string_types) and os.path.exists(output):
        if overwrite:
            os.remove(output)
        else:
            raise IOError("File exists: {0}".format(output))

    # Create a new HDU object
    if input.masked:
        table_hdu = BinTableHDU(np.array(input.filled()))
        for col in table_hdu.columns:
            # The astype is necessary because if the string column is less
            # than one character, the fill value will be N/A by default which
            # is too long, and so no values will get masked.
            fill_value = input[col.name].get_fill_value()
            col.null = fill_value.astype(input[col.name].dtype)
    else:
        table_hdu = BinTableHDU(np.array(input))

    # Set units for output HDU
    for col in table_hdu.columns:
        if input[col.name].units is not None:
            col.unit = input[col.name].units.to_string(format='fits')

    for key, value in input.meta.items():

        if is_column_keyword(key.upper()) or key.upper() in REMOVE_KEYWORDS:

            log.warn("Meta-data keyword {0} will be ignored since it "
                     "conflicts with a FITS reserved keyword".format(key))

        if isinstance(value, list):
            for item in value:
                try:
                    table_hdu.header.append((key, item))
                except ValueError:
                    log.warn("Attribute `{0}` of type {1} cannot be written "
                             "to FITS files - skipping".format(
                                 key, type(value)))
        else:
            try:
                table_hdu.header[key] = value
            except ValueError:
                log.warn("Attribute `{0}` of type {1} cannot be written to "
                         "FITS files - skipping".format(key, type(value)))

    # Write out file
    table_hdu.writeto(output)
Exemplo n.º 18
0
def main():

    usage = "usage: %(prog)s [archive file]"
    description = "Build the extended archive from the master archive YAML file."
    parser = argparse.ArgumentParser(usage=usage, description=description)

    parser.add_argument('--outname', default=None, required=True)

    parser.add_argument('--vernum', default=0, required=True)

    parser.add_argument('masterfile',
                        help='Extended archive master YAML file.')

    args = parser.parse_args()

    npar_max = 5
    sources = yaml.load(open(args.masterfile))
    cols = [
        Column(name='Source_Name', format='18A'),
        Column(name='RAJ2000', format='E', unit='deg', disp='F8.4'),
        Column(name='DEJ2000', format='E', unit='deg', disp='F8.4'),
        Column(name='GLON', format='E', unit='deg', disp='F8.4'),
        Column(name='GLAT', format='E', unit='deg', disp='F8.4'),
        Column(name='Photon_Flux', format='E', unit='ph cm-2 s-1',
               disp='E8.2'),
        Column(name='Energy_Flux',
               format='E',
               unit='erg cm-2 s-1',
               disp='E8.2'),
        Column(name='Model_Form', format='12A'),
        Column(name='Model_SemiMajor', format='E', unit='deg', disp='E7.3'),
        Column(name='Model_SemiMinor', format='E', unit='deg', disp='E7.3'),
        Column(name='Model_PosAng', format='E', unit='deg', disp='E6.1'),
        Column(name='Spatial_Function', format='15A'),
        Column(name='Spatial_Filename', format='50A'),
        Column(name='Spectral_Function', format='12A'),
        Column(name='Spectral_Filename', format='40A'),
        Column(name='Name_1FGL', format='18A'),
        Column(name='Name_2FGL', format='18A'),
        Column(name='Name_3FGL', format='18A'),
        Column(name='Spectral_Param_Name', format='45A9'),
        Column(name='Spectral_Param_Value',
               format='E',
               dim=str(npar_max),
               disp='E9.4'),
        Column(name='Spectral_Param_Error',
               format='E',
               dim=str(npar_max),
               disp='E9.4'),
        Column(name='Spectral_Param_Scale', format='E', dim=str(npar_max)),
    ]

    for c in cols:
        c.array = build_column_array(c.name, sources, npar_max)

    record = FITS_rec.from_columns(cols)
    record.sort(order="RAJ2000")

    outdir = args.outname + "_v" + args.vernum
    mkdir(outdir)

    fitsname = "LAT_extended_sources_v" + args.vernum + ".fits"
    output = BinTableHDU(record)
    output.writeto(os.path.join(outdir, fitsname), overwrite=True)

    xmldir = os.path.join(outdir, 'XML')
    mkdir(xmldir)

    for k, v in sources.items():
        xmlpath = os.path.join(xmldir,
                               v['Source_Name'].replace(' ', '') + '.xml')
        to_xml(xmlpath, v['Source_Name'], v)