nirs4all.synthesis.sources module

Multi-source dataset generation for synthetic NIRS data.

This module provides tools for generating synthetic datasets with multiple data sources, such as combining NIR spectra with molecular markers or auxiliary measurements.

Example

>>> from nirs4all.synthesis.sources import MultiSourceGenerator
>>>
>>> generator = MultiSourceGenerator(random_state=42)
>>>
>>> dataset = generator.generate(
...     n_samples=500,
...     sources=[
...         {"name": "NIR_low", "type": "nir", "wavelength_range": (1000, 1700)},
...         {"name": "NIR_high", "type": "nir", "wavelength_range": (1700, 2500)},
...         {"name": "markers", "type": "aux", "n_features": 15},
...     ]
... )
class nirs4all.synthesis.sources.MultiSourceGenerator(random_state: int | None = None)[source]

Bases: object

Generate synthetic multi-source NIRS datasets.

This class creates datasets combining multiple data sources, such as: - Multiple NIR spectral ranges (e.g., visible-NIR + shortwave-NIR) - NIR spectra + molecular markers - NIR spectra + auxiliary measurements

The generated sources share common underlying structure through component concentrations, creating realistic inter-source correlations.

Variables:

rng – NumPy random generator.

Parameters:

random_state – Random seed for reproducibility.

Example

>>> generator = MultiSourceGenerator(random_state=42)
>>>
>>> result = generator.generate(
...     n_samples=500,
...     sources=[
...         {
...             "name": "NIR",
...             "type": "nir",
...             "wavelength_range": (1000, 2500),
...             "complexity": "realistic"
...         },
...         {
...             "name": "markers",
...             "type": "aux",
...             "n_features": 20,
...             "correlation_with_target": 0.7
...         }
...     ],
...     target_range=(0, 100)
... )
>>>
>>> print(result.source_names)
['NIR', 'markers']
create_dataset(n_samples: int, sources: Sequence[SourceConfig | dict[str, Any]], *, train_ratio: float = 0.8, target_range: tuple[float, float] | None = None, name: str = 'multi_source_synthetic') → SpectroDataset[source]

Create a SpectroDataset from multi-source generation.

Parameters:
  • n_samples – Number of samples to generate.

  • sources – List of source configurations.

  • train_ratio – Proportion of samples for training.

  • target_range – Optional (min, max) for target scaling.

  • name – Dataset name.

Returns:

SpectroDataset with multiple sources configured.

Example

>>> dataset = generator.create_dataset(
...     n_samples=500,
...     sources=[
...         {"name": "NIR", "type": "nir", "wavelength_range": (1000, 2500)},
...         {"name": "markers", "type": "aux", "n_features": 10}
...     ],
...     train_ratio=0.8
... )
generate(n_samples: int, sources: Sequence[SourceConfig | dict[str, Any]], *, target_range: tuple[float, float] | None = None, concentration_method: str = 'dirichlet', n_components: int = 5) → MultiSourceResult[source]

Generate a multi-source dataset.

All sources share underlying component concentrations, which creates realistic correlations between sources. NIR sources generate spectra from these concentrations, while auxiliary sources create features correlated with the same underlying structure.

Parameters:
  • n_samples – Number of samples to generate.

  • sources – List of source configurations (SourceConfig or dict).

  • target_range – Optional (min, max) for scaling target values.

  • concentration_method – Method for generating component concentrations.

  • n_components – Number of underlying components.

Returns:

MultiSourceResult containing all generated data.

Example

>>> result = generator.generate(
...     n_samples=300,
...     sources=[
...         {"name": "VIS-NIR", "type": "nir", "wavelength_range": (400, 1100)},
...         {"name": "SWIR", "type": "nir", "wavelength_range": (1100, 2500)},
...     ]
... )
class nirs4all.synthesis.sources.MultiSourceResult(sources: dict[str, ~numpy.ndarray], targets: ~numpy.ndarray, source_configs: list[~nirs4all.synthesis.sources.SourceConfig], wavelengths: dict[str, ~numpy.ndarray] = <factory>, metadata: dict[str, ~typing.Any] | None = None)[source]

Bases: object

Container for multi-source generation results.

Variables:
get_combined_features() → ndarray[source]

Concatenate all sources into single feature matrix.

metadata: dict[str, Any] | None = None
property n_features_total: int

Get total number of features across all sources.

property n_samples: int

Get number of samples.

source_configs: list[SourceConfig]
property source_names: list[str]

Get list of source names.

sources: dict[str, ndarray]
targets: ndarray
wavelengths: dict[str, ndarray]
class nirs4all.synthesis.sources.SourceConfig(name: str, source_type: Literal['nir', 'vis', 'aux', 'markers'] = 'nir', n_features: int | None = None, wavelength_start: float | None = None, wavelength_end: float | None = None, wavelength_step: float = 2.0, components: list[str] | None = None, complexity: Literal['simple', 'realistic', 'complex'] = 'simple', distribution: Literal['normal', 'uniform', 'lognormal'] = 'normal', correlation_with_target: float = 0.5)[source]

Bases: object

Configuration for a single data source.

Variables:
  • name (str) – Unique identifier for the source.

  • source_type (Literal['nir', 'vis', 'aux', 'markers']) – Type of source (‘nir’, ‘vis’, ‘aux’, ‘markers’).

  • n_features (int | None) – Number of features (auto-calculated for NIR sources).

  • NIR-specific (#)

  • wavelength_start (float | None) – Start wavelength for NIR sources.

  • wavelength_end (float | None) – End wavelength for NIR sources.

  • wavelength_step (float) – Wavelength step for NIR sources.

  • components (list[str] | None) – Component names for NIR sources.

  • complexity (Literal['simple', 'realistic', 'complex']) – Complexity level for NIR sources.

  • Auxiliary-specific (#)

  • distribution (Literal['normal', 'uniform', 'lognormal']) – Distribution for auxiliary features.

  • correlation_with_target (float) – How correlated aux features are with target.

complexity: Literal['simple', 'realistic', 'complex'] = 'simple'
components: list[str] | None = None
correlation_with_target: float = 0.5
distribution: Literal['normal', 'uniform', 'lognormal'] = 'normal'
classmethod from_dict(config: dict[str, Any]) → SourceConfig[source]

Create SourceConfig from dictionary.

n_features: int | None = None
name: str
source_type: Literal['nir', 'vis', 'aux', 'markers'] = 'nir'
wavelength_end: float | None = None
wavelength_start: float | None = None
wavelength_step: float = 2.0
nirs4all.synthesis.sources.generate_multi_source(n_samples: int, sources: list[dict[str, Any]] | None = None, *, random_state: int | None = None, target_range: tuple[float, float] | None = None, as_dataset: bool = True, train_ratio: float = 0.8, name: str = 'multi_source_synthetic') → SpectroDataset | MultiSourceResult[source]

Convenience function for generating multi-source datasets.

Parameters:
  • n_samples – Number of samples.

  • sources – List of source configurations. If None, uses default single NIR source with wavelength range (1000, 2500).

  • random_state – Random seed.

  • target_range – Target value range.

  • as_dataset – If True, returns SpectroDataset.

  • train_ratio – Training set proportion.

  • name – Dataset name.

Returns:

SpectroDataset or MultiSourceResult depending on as_dataset.

Example

>>> dataset = generate_multi_source(
...     n_samples=500,
...     sources=[
...         {"name": "NIR", "type": "nir", "wavelength_range": (1000, 2500)},
...         {"name": "markers", "type": "aux", "n_features": 15}
...     ],
...     random_state=42
... )