nirs4all.synthesis.reconstruction.forward module

Forward model components for physical signal-chain reconstruction.

This module implements the forward measurement chain:

Canonical physical model → Instrument effects → Domain transform → Preprocessing

Key principle: Keep one latent physical model on a canonical grid, then apply dataset-specific transforms to match observed data.

class nirs4all.synthesis.reconstruction.forward.CanonicalForwardModel(canonical_grid: ndarray, component_names: List[str] = <factory>, baseline_order: int = 5, continuum_order: int = 3, _component_spectra: ndarray | None = None, _baseline_basis: ndarray | None = None, _continuum_basis: ndarray | None = None)[source]

Bases: object

Physical model on canonical high-resolution wavelength grid.

Computes absorption coefficient K(λ) from chemical components:

K(λ) = Σ c_k * ε_k(λ) + K0(λ)

where:
  • c_k: concentration of component k

  • ε_k(λ): molar absorptivity (from component library)

  • K0(λ): continuum/background absorption (low-frequency)

canonical_grid

High-resolution wavelength grid (nm).

Type:

numpy.ndarray

component_names

Names of components to include.

Type:

List[str]

component_spectra

Pre-computed component spectra on canonical grid.

baseline_order

Order of Chebyshev baseline polynomial.

Type:

int

continuum_order

Order of continuum absorption polynomial.

Type:

int

__post_init__()[source]

Initialize component spectra and basis matrices.

baseline_order: int = 5
canonical_grid: ndarray
component_names: List[str]
compute_absorption(concentrations: ndarray, path_length: float = 1.0, baseline_coeffs: ndarray | None = None, continuum_coeffs: ndarray | None = None) ndarray[source]

Compute absorption coefficient on canonical grid.

Parameters:
  • concentrations – Component concentrations, shape (n_components,).

  • path_length – Optical path length factor.

  • baseline_coeffs – Baseline polynomial coefficients.

  • continuum_coeffs – Continuum absorption coefficients.

Returns:

Absorbance spectrum on canonical grid.

continuum_order: int = 3
get_design_matrix(path_length: float = 1.0) ndarray[source]

Get full design matrix for linear fitting.

Returns:

Design matrix of shape (n_wavelengths, n_components + n_baseline + n_continuum).

property n_baseline: int

Number of baseline coefficients.

property n_components: int

Number of chemical components.

property n_continuum: int

Number of continuum coefficients.

property n_linear_params: int

Total number of linear parameters.

class nirs4all.synthesis.reconstruction.forward.DomainTransform(domain: Literal['absorbance', 'reflectance', 'transmittance', 'km'] = 'absorbance', scatter_coeffs: ndarray | None = None, scatter_wavelength_exp: float = 0.0)[source]

Bases: object

Transform between physical domains (absorbance, reflectance, etc.).

For absorbance datasets: A(λ) = absorption coefficient (direct) For reflectance datasets: R(λ) computed via Kubelka-Munk or approximation

domain

Domain type (‘absorbance’, ‘reflectance’, ‘transmittance’, ‘km’).

Type:

Literal[‘absorbance’, ‘reflectance’, ‘transmittance’, ‘km’]

scatter_coeffs

Scattering coefficients for KM model (reflectance).

Type:

numpy.ndarray | None

scatter_wavelength_dep

Wavelength-dependent scatter (λ^-n).

domain: Literal['absorbance', 'reflectance', 'transmittance', 'km'] = 'absorbance'
inverse_transform(spectrum: ndarray, wavelengths: ndarray, scatter: ndarray | None = None) ndarray[source]

Inverse transform from domain to absorption.

Parameters:
  • spectrum – Spectrum in domain representation.

  • wavelengths – Wavelength grid.

  • scatter – Scattering coefficient for reflectance.

Returns:

Absorption coefficient.

scatter_coeffs: ndarray | None = None
scatter_wavelength_exp: float = 0.0
transform(absorption: ndarray, wavelengths: ndarray, scatter: ndarray | None = None) ndarray[source]

Transform absorption to target domain.

Parameters:
  • absorption – Absorption coefficient K(λ).

  • wavelengths – Wavelength grid.

  • scatter – Scattering coefficient S(λ) for reflectance.

Returns:

Spectrum in target domain representation.

class nirs4all.synthesis.reconstruction.forward.ForwardChain(canonical_model: CanonicalForwardModel, instrument_model: InstrumentModel, domain_transform: DomainTransform, preprocessing: PreprocessingOperator, environmental_model: 'EnvironmentalEffectsModel' | None = None)[source]

Bases: object

Complete forward measurement chain combining all components.

Chain: CanonicalForwardModel → [EnvironmentalEffects] → DomainTransform → InstrumentModel → PreprocessingOperator

canonical_model

Physical model on canonical grid.

Type:

CanonicalForwardModel

environmental_model

Optional environmental effects (temperature, moisture, scattering).

Type:

Optional[‘EnvironmentalEffectsModel’]

instrument_model

Instrument effects.

Type:

InstrumentModel

domain_transform

Domain conversion.

Type:

DomainTransform

preprocessing

Dataset preprocessing.

Type:

PreprocessingOperator

canonical_model: CanonicalForwardModel
classmethod create(canonical_grid: ndarray, target_grid: ndarray, component_names: List[str], domain: str = 'absorbance', preprocessing_type: str = 'none', instrument_params: Dict[str, float] | None = None, baseline_order: int = 5, continuum_order: int = 3, sg_window: int = 15, sg_polyorder: int = 2, include_environmental: bool = False) ForwardChain[source]

Convenience factory method to create ForwardChain.

Parameters:
  • canonical_grid – High-resolution canonical wavelength grid.

  • target_grid – Target dataset wavelength grid.

  • component_names – Names of components to include.

  • domain – Domain type (‘absorbance’, ‘reflectance’).

  • preprocessing_type – Preprocessing type.

  • instrument_params – Instrument parameters dict.

  • baseline_order – Baseline polynomial order.

  • continuum_order – Continuum polynomial order.

  • sg_window – Savitzky-Golay window.

  • sg_polyorder – Savitzky-Golay polynomial order.

  • include_environmental – Whether to include environmental effects model.

Returns:

Configured ForwardChain instance.

domain_transform: DomainTransform
environmental_model: 'EnvironmentalEffectsModel' | None = None
forward(concentrations: ndarray, path_length: float = 1.0, baseline_coeffs: ndarray | None = None, continuum_coeffs: ndarray | None = None, scatter: ndarray | None = None) ndarray[source]

Run full forward chain.

Parameters:
  • concentrations – Component concentrations.

  • path_length – Optical path length factor.

  • baseline_coeffs – Baseline polynomial coefficients.

  • continuum_coeffs – Continuum absorption coefficients.

  • scatter – Scattering coefficients for reflectance.

Returns:

Spectrum on target grid with preprocessing applied.

forward_design_matrix(path_length: float = 1.0) ndarray[source]

Get transformed design matrix for linear fitting.

Returns the design matrix after applying instrument and preprocessing transforms. Note: Domain transform is not applied here as it may be nonlinear (KM).

instrument_model: InstrumentModel
preprocessing: PreprocessingOperator
class nirs4all.synthesis.reconstruction.forward.InstrumentModel(target_grid: ndarray, wl_shift: float = 0.0, wl_stretch: float = 1.0, wl_poly_coeffs: ndarray | None = None, ils_sigma: float = 4.0, stray_light: float = 0.0, gain: float = 1.0, offset: float = 0.0)[source]

Bases: object

Instrument effects: warp, ILS convolution, gain/offset, resampling.

Transforms spectrum from canonical grid to target instrument grid:
  1. Wavelength warp: λ* → λ’ (shift + stretch + optional higher order)

  2. ILS convolution: Gaussian or Voigt line shape

  3. Stray light / gain / offset

  4. Resample to target grid

target_grid

Target wavelength grid (dataset grid).

Type:

numpy.ndarray

wl_shift

Wavelength shift in nm (default 0).

Type:

float

wl_stretch

Wavelength scale factor (default 1).

Type:

float

wl_poly_coeffs

Higher-order polynomial warp coefficients.

Type:

numpy.ndarray | None

ils_sigma

Instrument line shape Gaussian sigma in nm.

Type:

float

stray_light

Stray light fraction (default 0).

Type:

float

gain

Photometric gain (default 1).

Type:

float

offset

Photometric offset (default 0).

Type:

float

apply(spectrum: ndarray, canonical_grid: ndarray) ndarray[source]

Apply instrument chain to transform spectrum.

Parameters:
  • spectrum – Input spectrum on canonical grid.

  • canonical_grid – Canonical wavelength grid.

Returns:

Transformed spectrum on target grid.

classmethod from_params(target_grid: ndarray, params: Dict[str, float]) InstrumentModel[source]

Create InstrumentModel from parameter dictionary.

gain: float = 1.0
get_jacobian_wrt_ils_sigma(spectrum: ndarray, canonical_grid: ndarray, eps: float = 0.1) ndarray[source]

Numerical Jacobian w.r.t. ILS sigma.

get_jacobian_wrt_wl_shift(spectrum: ndarray, canonical_grid: ndarray, eps: float = 0.1) ndarray[source]

Numerical Jacobian w.r.t. wavelength shift.

ils_sigma: float = 4.0
offset: float = 0.0
stray_light: float = 0.0
target_grid: ndarray
wl_poly_coeffs: ndarray | None = None
wl_shift: float = 0.0
wl_stretch: float = 1.0
class nirs4all.synthesis.reconstruction.forward.PreprocessingOperator(preprocessing_type: Literal['none', 'first_derivative', 'second_derivative', 'snv', 'msc', 'detrend', 'mean_centered'] = 'none', sg_window: int = 15, sg_polyorder: int = 2, sg_deriv: int = 0, reference_spectrum: ndarray | None = None)[source]

Bases: object

Apply dataset preprocessing to match stored representation.

Implements exact preprocessing steps:
  • Savitzky-Golay derivatives (1st, 2nd order)

  • SNV (Standard Normal Variate)

  • MSC (Multiplicative Scatter Correction)

  • Detrend

  • Mean centering

preprocessing_type

Type of preprocessing.

Type:

Literal[‘none’, ‘first_derivative’, ‘second_derivative’, ‘snv’, ‘msc’, ‘detrend’, ‘mean_centered’]

sg_window

Savitzky-Golay window length.

Type:

int

sg_polyorder

Savitzky-Golay polynomial order.

Type:

int

sg_deriv

Derivative order (0, 1, 2).

Type:

int

reference_spectrum

Reference for MSC (mean of calibration set).

Type:

numpy.ndarray | None

apply(spectrum: ndarray) ndarray[source]

Apply preprocessing to spectrum.

Parameters:

spectrum – Input spectrum, shape (n_wavelengths,) or (n_samples, n_wavelengths).

Returns:

Preprocessed spectrum(a).

apply_to_matrix(X: ndarray) ndarray[source]

Apply preprocessing to design matrix columns.

classmethod from_detection(preprocessing_type: str, sg_window: int = 15, sg_polyorder: int = 2) PreprocessingOperator[source]

Create PreprocessingOperator from detected preprocessing type.

preprocessing_type: Literal['none', 'first_derivative', 'second_derivative', 'snv', 'msc', 'detrend', 'mean_centered'] = 'none'
reference_spectrum: ndarray | None = None
sg_deriv: int = 0
sg_polyorder: int = 2
sg_window: int = 15