nirs4all.data.synthetic.reconstruction.inversion module

Variable projection inversion for per-sample spectral fitting.

Implements the core inversion algorithm: - Outer loop: optimize nonlinear parameters (path_length, per-sample shift) - Inner loop: solve linear parameters via NNLS/QP (concentrations, baseline)

Uses multiscale schedule to avoid local minima.

class nirs4all.data.synthetic.reconstruction.inversion.InversionResult(concentrations: ndarray, baseline_coeffs: ndarray, continuum_coeffs: ndarray | None = None, path_length: float = 1.0, wl_shift_residual: float = 0.0, scatter_coeffs: ndarray | None = None, fitted_spectrum: ndarray | None = None, residuals: ndarray | None = None, r_squared: float = 0.0, rmse: float = inf, converged: bool = False, temperature_delta: float = 0.0, water_activity: float = 0.5, scattering_power: float = 1.5, scattering_amplitude: float = 0.0)[source]

Bases: object

Result of per-sample inversion.

concentrations

Fitted component concentrations.

Type:

numpy.ndarray

baseline_coeffs

Fitted baseline coefficients.

Type:

numpy.ndarray

continuum_coeffs

Fitted continuum coefficients.

Type:

numpy.ndarray | None

path_length

Fitted path length factor.

Type:

float

wl_shift_residual

Per-sample wavelength shift correction.

Type:

float

scatter_coeffs

Fitted scatter coefficients (reflectance).

Type:

numpy.ndarray | None

fitted_spectrum

Reconstructed spectrum.

Type:

numpy.ndarray | None

residuals

Fitting residuals.

Type:

numpy.ndarray | None

r_squared

Coefficient of determination.

Type:

float

rmse

Root mean squared error.

Type:

float

converged

Whether optimization converged.

Type:

bool

temperature_delta

Fitted temperature deviation (°C from reference).

Type:

float

water_activity

Fitted water activity (0-1 scale).

Type:

float

scattering_power

Fitted scattering wavelength exponent.

Type:

float

scattering_amplitude

Fitted scattering baseline amplitude.

Type:

float

baseline_coeffs: ndarray
concentrations: ndarray
continuum_coeffs: ndarray | None = None
converged: bool = False
fitted_spectrum: ndarray | None = None
property linear_params: ndarray

Get all linear parameters as single array.

path_length: float = 1.0
r_squared: float = 0.0
residuals: ndarray | None = None
rmse: float = inf
scatter_coeffs: ndarray | None = None
scattering_amplitude: float = 0.0
scattering_power: float = 1.5
temperature_delta: float = 0.0
to_dict() Dict[str, Any][source]

Convert to dictionary.

water_activity: float = 0.5
wl_shift_residual: float = 0.0
class nirs4all.data.synthetic.reconstruction.inversion.MultiscaleSchedule(smooth_sigmas: List[float] = <factory>, derivative_weights: List[float] = <factory>, baseline_regularization: List[float] = <factory>, max_iterations: List[int] = <factory>)[source]

Bases: object

Configuration for multiscale fitting curriculum.

Fits coarse features first, then progressively adds detail: 1. Smooth target + no derivatives + strong baseline prior 2. Less smooth + partial derivative weight 3. Full resolution + full preprocessing

smooth_sigmas

Gaussian sigma values for each stage (0 = no smoothing).

Type:

List[float]

derivative_weights

Weight on derivative space at each stage.

Type:

List[float]

baseline_regularization

Baseline regularization at each stage.

Type:

List[float]

max_iterations

Max iterations at each stage.

Type:

List[int]

baseline_regularization: List[float]
derivative_weights: List[float]
max_iterations: List[int]
property n_stages: int

Number of stages in schedule.

classmethod quick() MultiscaleSchedule[source]

Quick schedule for fast fitting.

smooth_sigmas: List[float]
classmethod thorough() MultiscaleSchedule[source]

Thorough schedule for best accuracy.

class nirs4all.data.synthetic.reconstruction.inversion.VariableProjectionSolver(path_length_bounds: Tuple[float, float] = (0.5, 2.0), wl_shift_bounds: Tuple[float, float] = (-2.0, 2.0), concentration_regularization: float = 1e-06, baseline_smoothness_penalty: float = 0.0001, use_derivatives: bool = False, verbose: bool = False, fit_environmental: bool = False, temperature_bounds: Tuple[float, float] = (-15.0, 15.0), water_activity_bounds: Tuple[float, float] = (0.1, 0.9), scattering_power_bounds: Tuple[float, float] = (0.5, 3.0), scattering_amplitude_bounds: Tuple[float, float] = (0.0, 0.2), environmental_prior_weight: float = 0.1)[source]

Bases: object

Variable projection solver for spectral inversion.

Separates optimization into: - Nonlinear params: path_length, per-sample wl_shift, [environmental] (outer loop) - Linear params: concentrations, baseline, continuum (inner NNLS/QP)

path_length_bounds

Bounds for path length.

Type:

Tuple[float, float]

wl_shift_bounds

Per-sample wavelength shift bounds.

Type:

Tuple[float, float]

concentration_regularization

L2 reg on concentrations.

Type:

float

baseline_smoothness_penalty

Penalty on baseline curvature.

Type:

float

use_derivatives

Fit in derivative space (for derivative data).

Type:

bool

fit_environmental

Whether to fit environmental parameters.

Type:

bool

temperature_bounds

Bounds for temperature deviation (°C).

Type:

Tuple[float, float]

water_activity_bounds

Bounds for water activity.

Type:

Tuple[float, float]

scattering_power_bounds

Bounds for scattering exponent.

Type:

Tuple[float, float]

scattering_amplitude_bounds

Bounds for scattering amplitude.

Type:

Tuple[float, float]

environmental_prior_weight

Weight for environmental parameter priors.

Type:

float

baseline_smoothness_penalty: float = 0.0001
concentration_regularization: float = 1e-06
environmental_prior_weight: float = 0.1
fit(target: np.ndarray, forward_chain: ForwardChain, schedule: MultiscaleSchedule | None = None, initial_params: Dict[str, float] | None = None) InversionResult[source]

Fit forward model to target spectrum.

Parameters:
  • target – Target spectrum to fit.

  • forward_chain – Forward chain with calibrated global params.

  • schedule – Multiscale fitting schedule.

  • initial_params – Initial nonlinear parameters.

Returns:

InversionResult with fitted parameters.

fit_batch(X: np.ndarray, forward_chain: ForwardChain, schedule: MultiscaleSchedule | None = None, n_jobs: int = 1) List[InversionResult][source]

Fit multiple spectra.

Parameters:
  • X – Spectra matrix (n_samples, n_wavelengths).

  • forward_chain – Forward chain with calibrated global params.

  • schedule – Multiscale fitting schedule.

  • n_jobs – Number of parallel jobs (1 = sequential).

Returns:

List of InversionResult for each sample.

fit_environmental: bool = False
path_length_bounds: Tuple[float, float] = (0.5, 2.0)
scattering_amplitude_bounds: Tuple[float, float] = (0.0, 0.2)
scattering_power_bounds: Tuple[float, float] = (0.5, 3.0)
temperature_bounds: Tuple[float, float] = (-15.0, 15.0)
use_derivatives: bool = False
verbose: bool = False
water_activity_bounds: Tuple[float, float] = (0.1, 0.9)
wl_shift_bounds: Tuple[float, float] = (-2.0, 2.0)
nirs4all.data.synthetic.reconstruction.inversion.invert_dataset(X: np.ndarray, forward_chain: ForwardChain, schedule: MultiscaleSchedule | None = None, verbose: bool = False, fit_environmental: bool = False) Tuple[List[InversionResult], Dict[str, np.ndarray]][source]

Invert full dataset and collect parameter arrays.

Parameters:
  • X – Spectra matrix (n_samples, n_wavelengths).

  • forward_chain – Forward chain.

  • schedule – Fitting schedule.

  • verbose – Print progress.

  • fit_environmental – Whether to fit environmental parameters.

Returns:

  • concentrations: (n_samples, n_components)

  • baseline_coeffs: (n_samples, n_baseline)

  • path_lengths: (n_samples,)

  • wl_shifts: (n_samples,)

  • r_squared: (n_samples,)

  • temperature_deltas: (n_samples,) [if fit_environmental]

  • water_activities: (n_samples,) [if fit_environmental]

  • scattering_powers: (n_samples,) [if fit_environmental]

  • scattering_amplitudes: (n_samples,) [if fit_environmental]

Return type:

Tuple of (results_list, params_dict) where params_dict contains