Data Workflow
Understanding how NIRS4ALL manages data is crucial. The data layer is designed to make modeling safe and flexible.
Data Layer Mission
Safe means:
No silent sample misalignment
No silent leakage across folds
Traceable transformations
Predictable selection semantics
Flexible means:
Multi-source support (spectra + metadata markers)
Multiple processing branches (try many preprocessing variants)
Dynamic metadata filtering
Augmentation-aware retrieval
The Central Data Object: SpectroDataset
Everything revolves around SpectroDataset — the core data container. It’s not just a wrapper around NumPy arrays. It’s a carefully designed facade over several internal components.
Internal Composition
flowchart TD
A[SpectroDataset] --> B[Features Block]
A --> C[Targets Block]
A --> D[Metadata Block]
A --> E[Indexer]
A --> F[Fold Assignments]
A --> G[Signal Type State]
A --> H[Aggregation and Repetition State]
B --> B1[FeatureSource 0: NIR]
B --> B2[FeatureSource 1: Markers]
B --> B3[FeatureSource N: ...]
E --> E1[sample_id]
E --> E2[origin_id]
E --> E3[partition]
E --> E4[group]
E --> E5[tags]
E --> E6[excluded flag]
This decomposition separates value arrays from index semantics, keeping retrieval logic explicit and mutation logic controlled.
Sample Identity Model
The index tracks two critical identifiers:
sample_id— unique row identifierorigin_id— identifier of the base sample (for augmented samples)
Key Insight
Base samples have
sample_id == origin_idAugmented samples have
sample_id != origin_id
This enables a crucial behavior: augmented samples can have different X values, but y maps back to the origin. This preserves label consistency.
Example scenario:
# You have 100 base samples
# You apply spectral augmentation (add noise, shift, etc.)
# Now you have 500 samples (100 base + 400 augmented)
# During training:
# - All 500 samples are used
# - Augmented samples have different X values
# - But y values map back to their origin_id
# During splitting:
# - Only 100 base samples determine train/test
# - This prevents augmented variants from leaking across folds
Multi-Source Data Model
A dataset can carry one or many sources. Each source can have:
Distinct feature dimensionality (1000 wavelengths vs 20 chemical markers)
Different headers (wavelength units vs marker names)
Independent processing chains
At retrieval time, you can:
Keep sources separate (for multi-input models)
Concatenate them (for unified feature vectors)
Use cases:
Combine NIR spectra with chemical markers
Merge data from multiple instruments
Apply source-specific preprocessing then merge
flowchart LR
A[Dataset] --> B[Source 0: NIR]
A --> C[Source 1: Markers]
B --> D[Preprocessing Chain A]
C --> E[Preprocessing Chain B]
D --> F[Merged Features]
E --> F
F --> G[Model]
Processing Dimension Model
Features are not simply 2D arrays (samples × features). Internally, each FeatureSource stores a 3D array:
Shape: samples × processings × features
Why 3D?
This allows multiple preprocessing variants to coexist without overwriting earlier processings.
Example:
Processing 0: Raw spectra
Processing 1: SNV-corrected
Processing 2: SNV + Savitzky-Golay derivative
When a merge operation needs a flattened representation, it can collapse the processing/source structure.
This supports:
Branch workflows (compare multiple preprocessing paths)
Feature augmentation (add derived features)
Stacking (use processed features from multiple branches)
Retrieval Semantics
When you retrieve data from a SpectroDataset, you have fine-grained control:
Control |
Purpose |
|---|---|
|
Select train, val, or test subsets |
|
Select specific processing chains |
|
Control output tensor shape (2d, 3d, etc.) |
|
Include/exclude augmented samples |
|
Include/exclude flagged-out samples |
|
Select a specific source |
Why so many controls?
Because a wrong default can leak information or break alignment. Controllers use these switches intentionally for each execution mode.
Example: Split Controller
When splitting data into train/test:
include_augmented=False(only base samples determine folds)include_excluded=False(don’t include flagged outliers)partition=None(no partition filter yet)
When training a model:
include_augmented=True(use augmented samples for training)include_excluded=False(exclude flagged outliers)partition="train"(only training partition)
Layout Semantics
Layout is a contract between data retrieval and operator expectations. It changes tensor organization without changing scientific meaning.
Layout |
Enum value |
Conceptual shape |
Typical consumer |
|---|---|---|---|
|
|
samples × (processings * features) |
Classical ML, sklearn estimators |
|
|
samples × (features * processings) |
Models expecting ordered channel alternation |
|
|
samples × processings × features |
Deep learning, custom tensor operators |
|
|
samples × features × processings |
DL variants needing feature-major memory order |
Why layout exists:
NIRS workflows mix classical regression models, deep models, multi-source inputs, and feature-augmented channels. One fixed layout would force repeated ad hoc reshaping. Explicit layout keeps train/predict symmetry easier to maintain.
Practical Rules
Choose layout based on consumer contract, not one-step convenience
Keep layout stable across train and predict for a given chain
Treat layout as part of the reproducibility fingerprint — different layout can produce different fitted artifacts
Advanced: Failure Modes to Avoid
Training with
3dand predicting with2d→ shape mismatchSilent transpose mismatches → incorrect feature ordering
Merging branches with incompatible tensor orientation → crash or wrong results
Augmented Sample Handling
Augmented samples are inclusion-optional at selection time:
For split operations: Only base samples should drive fold assignment
For training: Augmented samples are typically included
For targets: Augmented samples map to origin
yvalues
This keeps augmentation powerful without breaking target consistency.
Excluded Sample Handling
Samples can be marked as excluded. Exclusion is an index flag, not immediate deletion:
Arrays remain structurally stable
Selection can omit excluded samples by default
Diagnostics can re-include excluded samples when needed
Why not delete immediately?
Some stages need full-shape updates (e.g., computing outlier scores for all samples), while others need filtered training subsets (e.g., model fitting without outliers).
Repetition Semantics
Repetition means multiple spectra for one physical sample — a frequent NIRS reality.
The dataset can define a repetition column that drives:
Group-aware split behavior — keep all repetitions of a sample in the same fold
Aggregation in scoring — average predictions across repetitions
Without grouping by repetition, train/test can share the same biological entity, causing data leakage.
Example
You have 50 soil samples, each measured 3 times (150 spectra total).
Wrong approach: Random split on 150 spectra
Repetitions of the same sample can end up in both train and test
Model learns to recognize the specific sample, not general patterns
Test scores are optimistically biased
Right approach: Group-aware split on 50 samples
All repetitions of a sample stay in the same fold
Model generalizes across samples
Test scores are honest
Aggregation Semantics
Aggregation groups predictions by metadata column, repetition semantics, or task-specific policies.
Available methods:
mean — average predictions
median — median predictions
vote — majority vote (classification)
Outlier-aware aggregation can be enabled to handle noisy replicates.
Fold Storage in Dataset
Split controllers write fold assignments into the dataset. Model controllers then consume these fold definitions without recomputing split logic.
This creates a clear separation:
Split controller decides folds
Model controller trains on folds
Benefits:
Consistent fold definitions across pipeline variants
Reproducible splits across runs
Audit trail for fold assignments
DataSelector and Context Coupling
Selection logic is carried through DataSelector, a dataclass inside ExecutionContext. Key fields:
Field |
Purpose |
|---|---|
|
train, val, test |
|
active processing chains |
|
requested array shape |
|
augmented sample inclusion flag |
|
excluded sample inclusion flag |
|
current fold identifier |
|
branch context |
|
specific feature source |
This keeps step behavior deterministic and reduces hidden global assumptions.
Targets and Y-Processing
Targets are handled separately from features. y_processing can transform targets, and these transformations are tracked as named processing states in context.
Use case: Scaling targets for neural network training, then inverse-transforming predictions back to original scale.
Benefits:
Scaled target training
Inverse-consistent prediction logic
Chain persistence of target transforms
Metadata Handling
Metadata is index-aligned and queryable. It participates in:
Grouping (e.g., by site or batch)
Splitting (e.g., stratified by class)
Branching rules (e.g., separate models per site)
Sample selection (e.g., filter by date range)
Reporting (e.g., per-site metrics)
The data layer treats metadata as operational context, not just display context.
Signal Type and Header Semantics
Spectral data comes in different physical representations. The SignalType enum tracks:
Category |
Values |
|---|---|
Core types |
|
Special types |
|
Detection states |
|
Header units (HeaderUnit enum):
cm-1(wavenumber)nm(wavelength)none,text,index
Why this matters:
Some operators need to know signal type (e.g., signal conversion, Kubelka-Munk transform). Wavelength-aware transforms (e.g., resampling, smoothing) need correct units.
Task Type Semantics
The TaskType enum defines three task types:
REGRESSION— continuous target predictionBINARY_CLASSIFICATION— two-class classificationMULTICLASS_CLASSIFICATION— multi-class classification
Task type influences:
Scorer behavior (RMSE vs accuracy)
Aggregation method defaults (mean vs vote)
Model interpretation logic
Probability handling
Leakage Prevention Patterns
Leakage prevention is layered, not a single control:
Split-first logic — define folds before any model fitting
Explicit base-sample selection — only base samples determine folds
Repetition-aware grouping — keep repetitions together
Separate train vs test partition selectors — controllers explicitly request partitions
Exclusion and tag-based filtering — exclude outliers without deleting them
Data Retrieval Modes Matrix
Retrieval intent |
Include augmented |
Include excluded |
Typical user |
|---|---|---|---|
Split calculation |
No |
No |
Splitter controller |
Transform all data |
Usually Yes |
Often Yes |
Transform controller |
Train model |
Often Yes |
No |
Model controller |
Diagnostics |
Optional |
Yes |
Analysis/reporting |
Predict new data |
Context-dependent |
Usually No |
Prediction flow |
Data Logic Concept Map
flowchart LR
A[Raw Sources] --> B[Loaders and Parsers]
B --> C[SpectroDataset]
C --> D[Indexer]
C --> E[Features]
C --> F[Targets]
C --> G[Metadata]
D --> H[Selectors]
H --> I[Partitioned Retrieval]
I --> J[Controllers]
J --> K[Mutated Processings]
J --> L[Fold Assignments]
J --> M[Predictions]
M --> N[Workspace Persistence]
Next Steps
Now that you understand how data flows, learn about:
Pipeline Workflow — How execution orchestrates steps
Controllers Intro — How controllers interact with datasets
Workspace Intro — How data and results are persisted
See also
Related Examples:
U01: Flexible Inputs - All data input formats and SpectroDataset usage
U03: Multi-Source - Working with multi-source datasets
U04: Repetition Aggregation - Handling repeated measurements
U04: Signal Conversion - Signal type detection and conversion