Source code for pyckles.spectral_library
import warnings
import numpy as np
from astropy.table import Table
from astropy import units as u
from .utils import load_catalog
[docs]
class SpectralLibrary:
"""
A container for a library of spectra
Holds and returns spectra from various catalogues in various python-friendly
formats, such as: ``synphot.SourceSpectrum``, ``astropy.Quantity``,
``numpy.ndarray``, and ``fits.BinTableHDU``
Spectra can be accessed by using the attribute syntax::
>>> spec_lib = pyckles.SpectralLibrary("pickles")
>>> spec_lib.A0V
or using the item syntax::
>>> spec_lib["A0V"]
The returned spectrum is formatted according to the ``meta["return_style"]``
parameter::
>>> spec_lib.meta["return_style"] = 'fits'
>>> type(spec_lib.A0V)
astropy.io.fits.hdu.table.BinTableHDU
Parameters
----------
catalog_name : str
The name of the spectral catalogue. See ``get_catalog_list``
Keyword arguments
-----------------
use_cache : bool
Default is True. If False, re-downloads the catalogue from the server
Note: if you need to update the catalogue just once, call
``astropy.utils.data.clear_download_cache()``
return_style : str
- ``fits``: Returns the original FITS BinTableHDU object
- ``synphot``: Returns a ``synphot.SourceSpectrum`` object
- ``quantity``: Returns wavelength and flux as ``astropy.Quantity``
- ``array``: Returns wavelength and flux as ``numpy.ndarray``
Examples
--------
List the available spectra::
>>> import pyckles
>>> spec_lib = pyckles.SpectralLibrary("pickles", return_style="quantity")
>>> spec_lib.available_spectra
<Column name='name' dtype='str5' length=131>
A0I
A0III
A0IV
...
K2III
K3III
K4III
Get an A0V spectrum::
>>> vega = spec_lib.A0V
>>> vega
[<Quantity [ 1150., 1155., 1160., ..., 24990., 24995., 25000.] Angstrom>,
<Quantity [0.181751, 0.203323, 0.142062, ..., 0.00699 , 0.006986, 0.006983] erg / (Angstrom cm2 s)>]
Return synphot.SourceSpectrum objects instead of a list of Quantity arrays::
>>> spec_lib.meta["return_style"] = "synphot"
>>> spec_lib.A0V
<synphot.spectrum.SourceSpectrum at 0x251800272e8>
"""
def __init__(self, catalog_name=None, **kwargs):
self.catalog_name = catalog_name
self.catalog = None
self.table = None
self.meta = {"use_cache": True,
"return_style": "fits"}
self.meta.update(kwargs)
self.load(catalog_name)
[docs]
def load(self, catalog_name):
""" Loads the catalogue for a valid string ``catalog_name`` """
if catalog_name is not None:
self.catalog = load_catalog(catalog_name, self.meta["use_cache"])
if self.catalog is not None:
self.table = Table(self.catalog[1].data)
else:
warnings.warn("Catalogue '{}' could not be loaded"
"".format(catalog_name))
@property
def available_spectra(self):
return self.table["name"]
def __getattr__(self, item):
"""Looks for item in the 'name' column of self.table"""
spec = None
if item in self.table["name"]:
item_ii = np.where(self.table["name"] == item)[0]
if len(item_ii) == 1:
ext = self.table["ext"][item_ii[0]]
spec = spectrum_from_hdu(self.catalog[ext],
self.meta["return_style"])
else:
print("Cannot return spectrum for ambiguous name: {}"
"".format(item))
else:
raise AttributeError
return spec
def __getitem__(self, item):
return self.__getattr__(item)
[docs]
def spectrum_from_hdu(hdu, return_type="fits"):
"""
Converts a BinTableHDU into the required return_type format
Parameters
----------
hdu : BinTableHDU
A BinTableHDU spectrum with column names: ``wavelength``, ``flux``
return_type : str
The format of the returned spectra - See SpectralLibrary docs
Returns
-------
spec : various
See above
See Also
--------
SpectralLibrary
"""
wave = hdu.data["wavelength"]
flux = hdu.data["flux"]
wave_unit = u.Unit(hdu.header["TUNIT1"])
flux_unit = u.Unit(hdu.header["TUNIT2"])
if return_type.lower() == "quantity":
# only compatible with py >= 3.5 and astropy >= 3.1
# spec = [wave << wave_unit, flux << flux_unit]
spec = [u.Quantity(wave, wave_unit, copy=False),
u.Quantity(flux, flux_unit, copy=False)]
elif return_type.lower() == "array":
spec = [wave, flux]
elif return_type.lower() == "synphot":
from synphot import Empirical1D, SourceSpectrum
spec = SourceSpectrum(Empirical1D,
points=u.Quantity(wave, wave_unit, copy=False),
lookup_table=u.Quantity(flux, flux_unit,
copy=False))
else:
spec = hdu
return spec