Source code for eradiate.scenes.spectra._multi_delta

from __future__ import annotations

import attrs
import numpy as np
import pint
import pinttr

from ._core import Spectrum
from ... import validators
from ...attrs import documented, parse_docs
from ...spectral.ckd import BinSet
from ...spectral.mono import WavelengthSet
from ...units import unit_context_kernel as uck
from ...util.misc import summary_repr_vector

[docs] @parse_docs @attrs.define(eq=False, slots=False) class MultiDeltaSpectrum(Spectrum): """ A spectrum made of multiple translated Dirac delta [``multi_delta``]. Notes ----- This spectrum is intended to be used for spectral grid specification. It has no kernel-level representation, and it cannot be evaluated. """ wavelengths: pint.Quantity = documented( pinttr.field( kw_only=True, units=uck.deferred("wavelength"), converter=[ lambda x: np.sort(np.atleast_1d(x)), pinttr.converters.to_units(uck.deferred("wavelength")), lambda x: np.unique(x.m) * x.units, ], validator=validators.all_strictly_positive, repr=lambda x: f"{summary_repr_vector(x.m)} {x.u:~}", ), doc="An array of wavelengths specifying the translation wavelength of each " "Dirac delta. Wavelength values are positive and unique. " "When a single value is provided, it is converted to a 1-element array. " "Wavelength are deduplicated and sorted by ascending values. " 'Unit-enabled field (default: ``ucc["wavelength"]``).', type="quantity", init_type="array-like or quantity", )
[docs] def eval_mono(self, w: pint.Quantity) -> pint.Quantity: raise NotImplementedError
[docs] def eval_ckd(self, w: pint.Quantity, g: float) -> pint.Quantity: raise NotImplementedError
[docs] def integral(self, wmin: pint.Quantity, wmax: pint.Quantity) -> pint.Quantity: raise NotImplementedError
@property def template(self) -> dict: raise NotImplementedError @property def params(self) -> dict: raise NotImplementedError def select_in_wavelength_set(self, wset: WavelengthSet) -> WavelengthSet: # the input wavelength set is completely ignored # only the attribute wavelengths are included in the returned # wavelength set return WavelengthSet(self.wavelengths) def select_in_bin_set(self, binset: BinSet) -> BinSet: bins = binset.bins wunits = "nm" xmin = np.array([bin.wmin.m_as(wunits) for bin in bins]) xmax = np.array([bin.wmax.m_as(wunits) for bin in bins]) x = self.wavelengths.m_as(wunits) selected = _select(xmin, xmax, x) return BinSet(bins=list(np.array(bins)[selected]))
def _select(xmin, xmax, x): selmin = np.searchsorted(xmin, x) selmax = np.searchsorted(xmax, x) + 1 hit = selmin == selmax # Mask where x values which triggered a bin hit # Map x values to selected bin (index -999 means not selected) bin_index = np.where(hit, selmin - 1, np.full_like(x, -999)).astype(np.int64) # Get selected bins only selected = np.unique(bin_index) # mask removes -999 value selected = selected[selected >= 0] return selected