"""
@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