Source code for pystellibs.marcs

import numpy as np
from .stellib import AtmosphereLib
from .config import libsdir
from .simpletable import SimpleTable
try:
    from astropy.io import fits as pyfits
except ImportError:
    import pyfits


[docs]class Marcs(AtmosphereLib): """ MARCS stellar atmosphere models Gustafsson et al 2008. http://marcs.astro.uu.se/ """ def __init__(self, *args, **kwargs): self.name = 'MARCS 2008' self.source = libsdir + '/marcs.grid.fits' self._load_() AtmosphereLib.__init__(self, *args, **kwargs) def _load_(self): with pyfits.open(self.source) as f: # load data self._getWaveLength_(f) self._getTGZ_(f) self._getSpectra_(f) self._getWaveLength_units(f) def _getWaveLength_units(self, f): self.wavelength_unit = 'angstrom' def _getWaveLength_(self, f): self._wavelength = f[0].data[-1] def _getTGZ_(self, f): self.grid = SimpleTable(f[1].data) self.grid.header.update(f[1].header.items()) self.grid.header['NAME'] = 'TGZ' def _getSpectra_(self, f): self.spectra = f[0].data[:-1]
[docs] def bbox(self, dlogT=0.05, dlogg=0.25): """ Boundary of Kurucz 2004 library Parameters ---------- dlogT: float log-temperature tolerance before extrapolation limit dlogg: float log-g tolerance before extrapolation limit Returns ------- bbox: ndarray (logT, logg) edges of the bounding polygon """ bbox = [(3.39794 - dlogT, 5.500 + dlogg), (3.39794 - dlogT, 3.000 - dlogg), (3.47700 - dlogT, 3.000 - dlogg), (3.47700 - dlogT, 0.000 - dlogg), (3.51853 - dlogT, 0.000 - dlogg), (3.51853 - dlogT, -0.500 - dlogg), (3.62903 - dlogT, -0.5000 - dlogg), (3.62903 - dlogT, 0.0000 - dlogg), (3.720, 0.000 - dlogg), (3.778 + dlogT, 0.500), (3.829 + dlogT, 1.000), (3.860 + dlogT, 1.500), (3.906, 2.000 - dlogg), (3.906 + dlogT, 2.000), (3.906 + dlogT, 2.500), (3.906 + dlogT, 3.000), (3.906 + dlogT, 3.500), (3.906 + dlogT, 4.000), (3.906 + dlogT, 4.500), (3.906 + dlogT, 5.000 + dlogg), (3.591 + dlogT, 5.000 + dlogg), (3.591 + dlogT, 5.500 + dlogg) ] return np.array(bbox)
[docs] def get_interpolation_data(self): """ interpolation needs alpha """ return np.array([self.logT, self.logg, self.logZ, self.alpha]).T
@property def logT(self): return np.log10(self.grid['teff']) @property def logg(self): return self.grid['logg'] @property def Teff(self): return self.grid['teff'] @property def Z(self): return 10 ** self.logZ @property def logZ(self): return self.grid['logz'] @property def alpha(self): return self.grid['alpha']
[docs] def generate_stellar_spectrum(self, logT, logg, logL, Z, alpha=0., raise_extrapolation=True, **kwargs): """ Generates individual spectrum for the given stars APs and the stellar library Returns NaN spectra if the boundary conditions are not met (no extrapolation) Parameters ---------- logT: float temperature logg: float log-gravity logL: float log-luminosity Z: float metallicity alpha: float alpha element raise_extrapolation: bool if set throw error on extrapolation null: value value of the flux when extrapolation and raise_extrapolation is not set returns ------- s0: ndarray, shape=(len(stars), len(l0)) array of spectra, one per input star Spectrum in ergs/s/AA or ergs/s/AA/Lsun """ null_value = kwargs.pop('null', np.nan) # weights to apply during the interpolation (note that radii must be in cm) weights = self.get_weights(logT, logg, logL) logZ = np.log10(Z) l0 = self.wavelength # check boundary conditions, keep the data but do not compute the sed # if outside if not self.points_inside(np.atleast_2d([logT, logg]))[0]: if raise_extrapolation: raise RuntimeError('Outside library interpolation range') else: return l0, np.full(len(self.wavelength), null_value) aps = logT, logg, logZ, alpha spec = self.interpolator.interp(aps) * weights return spec
[docs] def generate_individual_spectra(self, stars, nthreads=0, **kwargs): """ Generates individual spectra for the given stars and stellar library Returns NaN spectra if the boundary conditions are not met (no extrapolation) Parameters ---------- stars: Table contains at least (logT, logg, logL, Z) of the considered stars returns ------- l0: ndarray, ndim=1 wavelength definition of the spectra wavelength in AA s0: ndarray, shape=(len(stars), len(l0)) array of spectra, one per input star Spectrum in ergs/s/AA or ergs/s/AA/Lsun """ null_value = kwargs.pop('null', np.nan) ndata = len(stars) logT, logg, logL, Z = stars['logT'], stars['logg'], stars['logL'], stars['Z'] try: alpha = stars['alpha'] except: alpha = np.zeros_like(logT) # weights to apply during the interpolation (note that radii must be in cm) weights = self.get_weights(logT, logg, logL) # check boundary conditions, keep the data but do not compute the sed # if outside bound = self.points_inside(np.array([logT, logg]).T) specs = np.empty((ndata, len(self._wavelength)), dtype=float) specs[~bound] = np.full(len(self.wavelength), null_value) logZ = np.log10(Z) aps = np.array([logT, logg, logZ, alpha]).T s = self.interpolator.interp(aps[bound]) * weights[bound, None] specs[bound] = s l0 = self.wavelength specs = specs * self.flux_units return l0, specs