Source code for exo_k.util.spectral_object

"""
@author: jeremy leconte

A class with some basic functions for all objects with a spectral dimension
"""
import numpy as np
from .cst import PI
from .radiation import Bnu_integral_num, Bnu

[docs] class Spectral_object(object): """A class with some basic functions for all objects with a spectral dimension """ def __init__(self): """Initializes some attributes to None """ self.wns = None self.wnedges = None self.Nw = None self.wn_unit='cm^-1' @property def wls(self): """Returns the wavelength array for the bin centers (in micron) """ if self.wns is not None: return 10000./self.wns else: raise RuntimeError('self.wns should not be None when requesting wls') @property def wledges(self): """Returns the wavelength array for the bin edges (in micron) """ if self.wnedges is not None: return 10000./self.wnedges else: raise RuntimeError('self.wnedges should not be None when requesting wledges') @property def wnrange(self): """Returns the limits of the wavenumber range. First tries with wnedges (for Ktables) and then wns (Xtables). """ if self.wnedges is not None: return self.wnedges[[0,-1]] elif self.wns is not None: return self.wns[[0,-1]] else: raise RuntimeError('self.wns or wnedges should not be None when requesting wnrange') @property def wlrange(self): """Returns the limits of the wavelength range """ if (self.wnedges is None) and (self.wns is None): raise RuntimeError('self.wns or wnedges should not be None when requesting wlrange') else: return np.sort(10000./self.wnrange)
[docs] def _compute_spectral_range(self, wn_range=None, wl_range=None): """Converts an unordered spectral range in either wavenumber or wavelength in an ordered wavenumber range. Parameters ---------- wn_range: list or array of size 2 Minimum and maximum wavenumber (in cm^-1). wl_range: list or array of size 2 Minimum and maximum wavelength (in micron) """ if wl_range is not None: if wn_range is not None: print('Cannot specify both wl and wn range!') raise RuntimeError() else: _wn_range=np.sort(10000./np.array(wl_range)) else: if wn_range is not None: _wn_range=np.sort(np.array(wn_range)) else: _wn_range=self._wn_range return _wn_range
[docs] def wlindex(self, wl): """Finds and returns the index corresponding to the given wavelength (in microns) """ return min(np.searchsorted(self.wns,10000./wl),self.Nw-1)-1
[docs] def select_spectral_range(self, wn_range=None, wl_range=None): """Select spectral range, without restricting the data (but the spectral axes are modified in place). Should use either wn_range OR wl_range, not both. To be selected, the whole bin must be inside the range. Parameters ---------- wn_range: array, np.ndarray Wavenumber range in cm^-1. wl_range: array, np.ndarray Wavelength range in micron. Returns ------- tuple: iw_min, iw_max the boundary indices of the spectral range """ if (wn_range is None) and (wl_range is None): return None, None if wl_range is not None: if wn_range is not None: raise RuntimeError('Should provide either wn_range or wl_range, not both!') _wn_range=np.sort(10000./np.array(wl_range)) else: _wn_range=np.sort(np.array(wn_range)) iw_min=np.searchsorted(self.wnedges, _wn_range[0], side='left') iw_max=np.searchsorted(self.wnedges, _wn_range[1], side='right') iw_max-=1 if iw_max <= iw_min: raise RuntimeError(f"Spectral range {wn_range} does not contain any point.") self.wnedges=self.wnedges[iw_min:iw_max+1] self.wns=self.wns[iw_min:iw_max] self.Nw=self.wns.size return iw_min, iw_max
[docs] def blackbody(self, Temperature, integral=True): """Computes the surface black body flux (in W/m^2/cm^-1) at Temperature. Parameters ---------- Temperature; float Blackbody temperature integral: boolean, optional * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. Returns ------- Spectrum object Spectral flux in W/m^2/cm^-1 """ if integral: try: piB = PI*Bnu_integral_num(self.wnedges, Temperature)/np.diff(self.wnedges) except: raise RuntimeError('You should use integral=False as this spectral object does not have a wnedges atribute.') else: try: piB = PI*Bnu(self.wns[:], Temperature) except: raise RuntimeError('You should instenciate wns for this spectral object before calling blackbody.') return piB