nirs4all.synthesis.components module

Spectral components for synthetic NIRS spectra generation.

This module provides the core building blocks for defining NIR absorption bands and spectral components based on physical spectroscopy principles.

Classes:

NIRBand: Represents a single NIR absorption band with Voigt profile. SpectralComponent: A chemical compound or functional group with multiple bands. ComponentLibrary: Collection of spectral components for generation.

class nirs4all.synthesis.components.NIRBand(center: float, sigma: float, gamma: float = 0.0, amplitude: float = 1.0, name: str = '')[source]

Bases: object

Represents a single NIR absorption band.

This class models an absorption band using a Voigt profile, which is the convolution of Gaussian (thermal broadening) and Lorentzian (pressure broadening) line shapes.

Variables:
  • center (float) – Central wavelength in nm.

  • sigma (float) – Gaussian width (standard deviation) in nm.

  • gamma (float) – Lorentzian width (HWHM) in nm. Use 0 for pure Gaussian.

  • amplitude (float) – Peak amplitude in absorbance units.

  • name (str) – Descriptive name of the band (e.g., “O-H 1st overtone”).

Example

>>> band = NIRBand(center=1450, sigma=25, gamma=3, amplitude=0.8)
>>> wavelengths = np.arange(1400, 1500, 1)
>>> spectrum = band.compute(wavelengths)
amplitude: float = 1.0
center: float
compute(wavelengths: ndarray) → ndarray[source]

Compute the band profile at given wavelengths using Voigt profile.

Parameters:

wavelengths – Array of wavelengths in nm at which to evaluate the band.

Returns:

Array of absorbance values at each wavelength.

Note

When gamma=0, a pure Gaussian profile is used for efficiency. Otherwise, the full Voigt profile (Gaussian ⊗ Lorentzian) is computed.

gamma: float = 0.0
name: str = ''
sigma: float
class nirs4all.synthesis.components.SpectralComponent(name: str, bands: list[NIRBand] = <factory>, correlation_group: int | None = None, category: str = '', subcategory: str = '', synonyms: list[str] = <factory>, formula: str = '', cas_number: str = '', references: list[str] = <factory>, tags: list[str] = <factory>)[source]

Bases: object

A spectral component representing a chemical compound or functional group.

Each component consists of multiple absorption bands that together define the characteristic NIR signature of the compound.

Variables:
  • name (str) – Component name (e.g., “water”, “protein”, “lipid”).

  • bands (list[nirs4all.synthesis.components.NIRBand]) – List of NIRBand objects defining the spectral signature.

  • correlation_group (int | None) – Optional group ID for components that should have correlated concentrations (e.g., protein and nitrogen compounds).

  • category (str) – Primary category (e.g., “carbohydrates”, “proteins”, “lipids”).

  • subcategory (str) – More specific classification (e.g., “monosaccharides”, “amino_acids”).

  • synonyms (list[str]) – Alternative names (e.g., [“vitamin C”] for ascorbic_acid).

  • formula (str) – Chemical formula (e.g., “C6H12O6” for glucose).

  • cas_number (str) – CAS registry number for chemical identification.

  • references (list[str]) – Literature citations for band assignments.

  • tags (list[str]) – Classification tags (e.g., [“food”, “pharma”, “agriculture”]).

Example

>>> water = SpectralComponent(
...     name="water",
...     bands=[
...         NIRBand(center=1450, sigma=25, gamma=3, amplitude=0.8),
...         NIRBand(center=1940, sigma=30, gamma=4, amplitude=1.0),
...     ],
...     correlation_group=1,
...     category="water_related",
...     formula="H2O",
... )
>>> wavelengths = np.arange(1000, 2500, 2)
>>> spectrum = water.compute(wavelengths)
bands: list[NIRBand]
cas_number: str = ''
category: str = ''
compute(wavelengths: ndarray) → ndarray[source]

Compute the full component spectrum by summing all bands.

Parameters:

wavelengths – Array of wavelengths in nm at which to evaluate.

Returns:

Array of absorbance values representing the combined spectrum.

correlation_group: int | None = None
formula: str = ''
has_bands_in_range(wavelength_range: tuple[float, float]) → bool[source]

Check if component has any bands with centers in the given wavelength range.

Parameters:

wavelength_range – (min, max) wavelength in nm.

Returns:

True if at least one band center is within the range.

info() → str[source]

Return formatted information about the component.

Returns:

Human-readable string with component details.

is_normalized(tolerance: float = 0.01) → bool[source]

Check if the component’s band amplitudes are max-normalized (max amplitude = 1.0).

Parameters:

tolerance – Acceptable deviation from 1.0 for max amplitude.

Returns:

True if max amplitude is within tolerance of 1.0.

name: str
normalized(method: str = 'max') → SpectralComponent[source]

Return a new SpectralComponent with normalized band amplitudes.

Parameters:

method – Normalization method. - “max”: Scale so max amplitude = 1.0 (default) - “sum”: Scale so sum of amplitudes = 1.0

Returns:

New SpectralComponent with normalized amplitudes.

Example

>>> component = SpectralComponent(name="test", bands=[
...     NIRBand(center=1450, sigma=25, amplitude=0.8),
...     NIRBand(center=1940, sigma=30, amplitude=2.0),
... ])
>>> normalized = component.normalized()
>>> print(max(b.amplitude for b in normalized.bands))  # 1.0
references: list[str]
subcategory: str = ''
synonyms: list[str]
tags: list[str]
validate() → list[str][source]

Validate component parameters.

Returns:

List of validation issues (empty if all valid).

Example

>>> component = SpectralComponent(name="test", bands=[])
>>> issues = component.validate()
>>> if issues:
...     print("Issues found:", issues)
nirs4all.synthesis.components.available_components() → list[str][source]

Return list of all available predefined component names.

Returns:

Sorted list of component names.

Example

>>> names = available_components()
>>> print(f"Available: {len(names)} components")
>>> print(names[:5])
nirs4all.synthesis.components.component_info(name: str) → str[source]

Return formatted information about a component.

Parameters:

name – Component name.

Returns:

Human-readable string with component details.

Example

>>> print(component_info("water"))
nirs4all.synthesis.components.get_component(name: str) → SpectralComponent[source]

Get a single predefined component by name or synonym.

Parameters:

name – Component name (e.g., “water”, “protein”, “lipid”) or synonym (e.g., “amylose” for “starch”).

Returns:

SpectralComponent object.

Raises:

ValueError – If component name is not found.

Example

>>> water = get_component("water")
>>> print(water.category)
>>> print(len(water.bands))
>>>
>>> # Using synonyms
>>> starch = get_component("amylose")  # Returns starch component
nirs4all.synthesis.components.list_categories() → dict[str, list[str]][source]

Return dictionary of categories to component names.

Returns:

Dictionary mapping category names to lists of component names.

Example

>>> categories = list_categories()
>>> for cat, components in categories.items():
...     print(f"{cat}: {len(components)} components")
nirs4all.synthesis.components.normalize_component_amplitudes(component: SpectralComponent, method: str = 'max') → SpectralComponent[source]

Normalize band amplitudes for a component.

This is a convenience wrapper around SpectralComponent.normalized().

Parameters:
  • component – SpectralComponent to normalize.

  • method – Normalization method (“max” or “sum”).

Returns:

New SpectralComponent with normalized amplitudes.

Example

>>> comp = get_component("water")
>>> normalized = normalize_component_amplitudes(comp)
nirs4all.synthesis.components.search_components(query: str | None = None, category: str | None = None, subcategory: str | None = None, tags: list[str] | None = None, wavelength_range: tuple[float, float] | None = None) → list[str][source]

Search components by various criteria.

Parameters:
  • query – Fuzzy match on name or synonyms.

  • category – Filter by category (e.g., “proteins”, “carbohydrates”).

  • subcategory – Filter by subcategory (e.g., “monosaccharides”).

  • tags – Filter by tags (any match).

  • wavelength_range – Filter by components with bands in range (min, max).

Returns:

List of matching component names.

Example

>>> # Find all protein-related components
>>> proteins = search_components(category="proteins")
>>>
>>> # Find components with bands in visible-NIR region
>>> vis_nir = search_components(wavelength_range=(400, 1000))
>>>
>>> # Find components tagged for pharmaceutical use
>>> pharma = search_components(tags=["pharma"])
nirs4all.synthesis.components.validate_component_coverage(wavelength_range: tuple[float, float] = (350, 2500)) → dict[str, list[str]][source]

Check which components have bands in the given wavelength range.

Parameters:

wavelength_range – (min, max) wavelength in nm.

Returns:

Dictionary with ‘covered’ and ‘not_covered’ component lists.

Example

>>> coverage = validate_component_coverage((1000, 2500))
>>> print(f"Covered: {len(coverage['covered'])}")
>>> print(f"Not covered: {coverage['not_covered']}")
nirs4all.synthesis.components.validate_predefined_components() → list[str][source]

Validate all predefined components.

Returns:

List of validation warnings/errors (empty if all valid).

Example

>>> issues = validate_predefined_components()
>>> if issues:
...     for issue in issues:
...         print(issue)
... else:
...     print("All components valid!")