Source code for eradiate.spectral.mono

from __future__ import annotations

import logging
import typing as t

import attrs
import numpy as np
import pint
import pinttr
import xarray as xr

from .index import MonoSpectralIndex
from .spectral_set import SpectralSet
from ..attrs import documented, parse_docs
from ..constants import SPECTRAL_RANGE_MAX, SPECTRAL_RANGE_MIN
from ..units import to_quantity
from ..units import unit_context_config as ucc
from ..units import unit_registry as ureg

logger = logging.getLogger(__name__)


[docs] @parse_docs @attrs.define(eq=False, frozen=True, slots=True) class WavelengthSet(SpectralSet): """ A data class representing a wavelength set used in monochromatic modes. See Also -------- :class:`~.BinSet` Notes ----- This is class is a simple container for an array of wavelengths at which a monochromatic experiment is to be performed. Its design is inspired by :class:`~.BinSet`. """ wavelengths: pint.Quantity = documented( pinttr.field( units=ucc.deferred("length"), on_setattr=None, converter=np.atleast_1d, ), doc="Wavelengths.", type="quantity", init_type="quantity or array-like or float", ) def spectral_indices(self) -> t.Generator[MonoSpectralIndex]: for w in self.wavelengths: yield MonoSpectralIndex(w=w)
[docs] @classmethod def from_absorption_dataset(cls, dataset: xr.Dataset) -> WavelengthSet: """ Create a wavelength set from an absorption dataset. Parameters ---------- dataset : Dataset Absorption dataset. Returns ------- :class:`.WavelengthSet` Generated wavelength set. """ # we dont know if the absorption dataset 'w' variable holds # wavelengths or wavenumbers, so we check the units w = to_quantity(dataset.w) if w.check("[length]^-1"): wavelengths = np.sort(1 / w).to( "nm" ) # ordered wavenumbers are reversed in wavelength-space elif w.check("[length]"): wavelengths = w return cls(wavelengths=wavelengths)
[docs] @classmethod def arange( cls, start: pint.Quantity, stop: pint.Quantity, step: pint.Quantity, ) -> WavelengthSet: """ Create a wavelength set from an array of wavelengths. Parameters ---------- start : quantity First wavelength. stop : quantity Last wavelength. step : quantity Wavelength step. Returns ------- :class:`.WavelengthSet` Generated wavelength set. """ wunits = ucc.get("wavelength") return cls( wavelengths=np.arange( start.m_as(wunits), stop.m_as(wunits), step.m_as(wunits), ) * wunits )
[docs] @classmethod def from_srf( cls, srf: xr.Dataset, step: pint.Quantity = 10.0 * ureg.nm, ) -> WavelengthSet: """ Generate a wavelength set with linearly spaced bins, that covers the spectral range of a spectral response function. Parameters ---------- srf: Dataset Spectral response function dataset. step : quantity Wavelength step. """ wavelengths = to_quantity(srf.w) wmin = wavelengths.min() wmax = wavelengths.max() return cls.arange( start=wmin - step, stop=wmax + step, step=step, )
[docs] @classmethod def default(cls) -> WavelengthSet: """ Generate a default wavelength set, which covers Eradiate's default spectral range with 1 nm spacing. """ dw = 1.0 * ureg.nm return cls.arange( start=SPECTRAL_RANGE_MIN, stop=SPECTRAL_RANGE_MAX + dw, step=dw, )