Source code for skplatform.solar

import numpy as np
import scipy.signal


# -----------------------------------------------------------------------------
#               SolarSpectrum
# -----------------------------------------------------------------------------
[docs] class SolarSpectrum: ''' A class used to load solar irradiance spectrum. The class currently supports the following spectra: #. SAO2010 #. Fontela UVIS to 3 microns #. Fontela UVIS to 100 micron, The choice of solar spectrum is specified in the constructor, the default is `sao2010`. The other values are 'fontela_uvis3micron` and `fontela_uvis100micron'. The solar data are implemented as python data arrays stored in the source code and can a second or two to load. But we have written the code so the solar data are only imported in for the model you request and only when you request it. ''' def __init__(self, spectrum_name: str = 'sao2010', fwhm=None): self._solardistanceinAU = 1.0 self._samplespacing = 0.01 self._resolution_nm = 0.05 self._wavelen_nm: np.ndarray = None self._irradiance: np.ndarray = None self._loadspectrum(spectrum_name) if fwhm is not None: smooth = self._smooth_spectrum(fwhm) self._irradiance = smooth self._resolution_nm = fwhm def _load_sao2010(self): from .solar_spectrum_impl.sao2010 import solar_spectrum_sao2010 self._wavelen_nm, self._irradiance = solar_spectrum_sao2010() self._samplespacing = 0.01 self._resolution_nm = 0.04 # FWHM in nm def _load_fontela_3micron(self): from .solar_spectrum_impl.fontela_uvis3micron import solar_spectrum_fontelaspectrum self._wavelen_nm, self._irradiance = solar_spectrum_fontelaspectrum() self._samplespacing = 0.02 self._resolution_nm = 0.1 # FWHM in nm def _load_fontela_100micron(self): from .solar_spectrum_impl.fontela_uvis100micron import solar_spectrum_fontelaspectrum100 self._wavelen_nm, self._irradiance = solar_spectrum_fontelaspectrum100() self._samplespacing = 0.2 self._resolution_nm = 1.0 # FWHM in nm def _loadspectrum(self, spectrum_name: str): name = spectrum_name.lower() if (name == 'sao2010'): self._load_sao2010() elif (name == 'fontela_uvis3micron'): self._load_fontela_3micron() elif (name == 'fontela_uvis100micron'): self._load_fontela_100micron() else: raise ValueError("Invalid solar spectrum value {}. Valid values for the solar spectrum are 'sao2010', 'fontela_uvis3micron', or 'fontela_uvis100micron'".format(spectrum_name)) # ----------------------------------------------------------------------------- # irradiance # -----------------------------------------------------------------------------
[docs] def irradiance(self, nm: np.ndarray): ''' Returns the solar irradiance at 1 A.U. at the requested wavelengths. Parameters ---------- nm : np.ndarray An array of wavelengths in nanometers. The current solar irradiance table is linearly interpolated to the desired wavelengths. The irradiance signal is set to 0.0 for all wavelengths outside of the current solar table wavelength bounds. Returns ------- np.ndarray The solar irradiance for each of the requested wavelengtths ''' irrad = np.interp(nm, self._wavelen_nm, self._irradiance, left=0.0, right=0.0) / (self._solardistanceinAU * self._solardistanceinAU) return irrad
# ----------------------------------------------------------------------------- # set_solar_distance_au # -----------------------------------------------------------------------------
[docs] def set_solar_distance_au(self, au: float): ''' Sets the distance of the sun in astronomical units (AU). Parameters ---------- au: float The distance of the Sun in astronomical units. The default upon initialization is 1.0 ''' self._solardistanceinAU = au
@property def sample_spacing(self) -> float: ''' The spacing in nanometers between spectral samples in the table. ''' return self._samplespacing @property def resolution_fwhm(self) -> float: ''' The FWHM in nanometers of the instrument resolution used to measure the current solar spectrum. ''' return self._resolution_nm @property def min_valid_wavelength(self): ''' The minimum wavelength in nanometers in the current table. ''' return self._wavelen_nm[0] @property def max_valid_wavelength(self): ''' The maximum wavelength in nanometers in the curreent table ''' return self._wavelen_nm[-1] def _smooth_spectrum(self, fwhm_nm) -> np.ndarray: stdev = fwhm_nm / 2.3548200450309493820231386529194 # Get the stanradr deviation required by the user hires_stdev = self.resolution_fwhm / 2.3548200450309493820231386529194 # get the standard deviation of the high resolution solar signal sigma2 = (stdev ** 2 - hires_stdev ** 2) # get the modified standrad deviation, subtract the solar standard deviation assert sigma2 > 0.0 sigma = np.sqrt(sigma2) dw = self.sample_spacing x = np.arange(-20 * sigma, 20 * sigma, dw) g = np.exp(-0.5 * np.square(x) / sigma2) / (np.sqrt(2.0 * np.pi * sigma2)) * dw smooth = scipy.signal.fftconvolve(self._irradiance, g, mode='same') return smooth