cuvis-ai-dataloader
Pluggable hyperspectral DataModules for the cuvis-ai ecosystem.
Overview
cuvis-ai-dataloader ships the concrete hyperspectral DataModules for the
Cuvis.AI ecosystem. A
DataModule is the unit the framework uses for both training and inference: it
bundles the data, the labels, the splits, and the train / val / test /
predict dataloaders.
This single plugin holds every concrete loader, with per-format heavy deps gated
behind optional extras. The cuvis SDK lives only here, behind [cu3s]; no
other Cuvis.AI repo pins it.
Module (data_module_name) |
Reads | Labels | Extra |
|---|---|---|---|
cu3s |
one .cu3s session (or a folder of them) via cuvis |
COCO JSON | [cu3s, coco] |
cu3s_multi |
many .cu3s, one frame per CSV row |
per-day COCO JSON | [cu3s, coco] |
npz_multi |
many .npz, one frame per CSV row |
baked mask array |
none |
tiff_paired |
a folder of *.tif / *.tiff cubes via tifffile |
paired PNG | [tiff] |
Key points:
- One plugin, three DataModules, per-format heavy deps behind extras
- The
cuvisSDK is isolated here, behind[cu3s] - Composable split selectors over an attributed sample universe
cuvis/tifffile/pycocotoolsimport lazily, so the plugin registers with any subset of extras
Splits
Splits are defined in one of two ways:
- Selectors (
splits.json) is the general mechanism, shared by every module. Composable selectors over an attributed sample universe are resolved into a committablesplits.jsonby theresolve-splitsCLI, then referenced from aDataConfig.splits. - One
universe.csvvocabulary (source, index+ optionalmaterialized_path, split, annotation, format, group) is read by bothcu3s_multiandnpz_multithrough a shared parser; each module keeps its own reader.cu3s_multimay carry an inlinesplitcolumn (present → module-owned; absent → needs asplits.json), andresolve-splits --from-csvturns that column into a committablesplits.json.npz_multiis selector-only (it rejects asplitcolumn) and requiresmaterialized_path(the.npz); forcu3s_multi,materialized_pathdefaults tosource(a raw.cu3sis its own file).sourceis the posix identity asplits.jsonselector keys on, so one split resolves against both the raw cu3s data and the converted npz.
Installation
uv pip install "cuvis-ai-dataloader[cu3s,coco]" # cu3s + COCO
uv pip install "cuvis-ai-dataloader[tiff]" # TIFF + paired PNG
uv pip install "cuvis-ai-dataloader[all]" # every format
Extras:
cu3s:.cu3ssession reading via thecuvisSDK bindingcoco: COCO-JSON mask labels (pycocotools,scikit-image)tiff: TIFF cube reading (tifffile)all: All formatsdev: Development dependencies
The cu3s extra carries the Windows cuvis-il<3.5.3 pin (the last build with a
win_amd64 wheel).
Cuvis SDK (system install, required for cu3s)
The [cu3s] extra installs the cuvis binding (with the Windows cuvis-il<3.5.3 pin noted
above), but that binding needs the system-wide C++ Cuvis SDK too, or any .cu3s read fails at
runtime. See the
Cuvis.AI installation guide for OS
support (Windows / Linux; not macOS), the SDK download, and verification. Quick check once
installed:
uv run python -c "import cuvis; print(cuvis.__version__)"
Usage
Inference (restore-pipeline) selects a module and its params on the CLI:
restore-pipeline \
--pipeline-path X.yaml \
--plugins-dir <this-repo>/configs/plugins \
--data-module cu3s \
--data-arg cu3s_file_path=X.cu3s \
--data-arg annotation_json_path=Y.json
Training (Train / RestoreTrainRun) selects the same module via the yaml
DataConfig:
data:
data_module: cu3s
splits:
train:
- { kind: file_indices, source: X.cu3s, ids: [0, 2, 3] }
val:
- { kind: file_indices, source: X.cu3s, ids: [1, 5] }
batch_size: 4
params:
cu3s_file_path: X.cu3s
annotation_json_path: Y.json
processing_mode: Reflectance
In-process / notebooks construct the DataModule directly and run it through
the Predictor:
from cuvis_ai_dataloader.data import Cu3sDataModule
from cuvis_ai_core.training import Predictor
from cuvis_ai_core.utils.restore import restore_pipeline
pipeline = restore_pipeline("X.yaml", plugins_dirs=[...])
dm = Cu3sDataModule(cu3s_file_path="X.cu3s", batch_size=1)
Predictor(pipeline, dm).predict()
NPZ (npz_multi)
npz_multi loads one frame per compressed .npz, selected by a splits.json over a
universe_csv (a universe.csv). It needs no extras (numpy is a core dep) and no Cuvis SDK. Each .npz carries:
cube:[H, W, C]float32wavelengths:[C](cast to int32)mask(optional):[H, W]int32 ground truth (zeros are emitted when absent)class_mask(optional):[H, W]uint8 per-pixel COCO category id (0 = background)
The universe_csv requires source, index plus materialized_path (the .npz, required for npz;
optional annotation, format, group; extra columns are ignored); materialized_path is relative
to the CSV and must not escape it via ... A split column is rejected here (npz is
selector-only). Each sample is
{cube, mask, class_mask, wavelengths, mesu_index, frame_id}. Unlike the cu3s modules, npz_multi
honors pin_memory / persistent_workers / worker_multiprocessing_context (pure-CPU numpy loads
benefit from them).
from cuvis_ai_dataloader.data import MultiNpzDataModule
from cuvis_ai_schemas.training.data import DataSplitConfig, Selector, SelectorKind
splits = DataSplitConfig(
train=[Selector(kind=SelectorKind.FILE_INDICES, source="X.cu3s", ids=[0, 2, 3])],
val=[Selector(kind=SelectorKind.FILE_INDICES, source="X.cu3s", ids=[1, 5])],
)
dm = MultiNpzDataModule(splits=splits, universe_csv="universe.csv", batch_size=4, num_workers=4)
dm.setup("fit")
batch = next(iter(dm.train_dataloader())) # cube [B,H,W,C], mask [B,H,W], ...
In a DataConfig (training / restore-trainrun):
data:
data_module: npz_multi
batch_size: 4
splits:
train:
- { kind: file_indices, source: X.cu3s, ids: [0, 2, 3] }
val:
- { kind: file_indices, source: X.cu3s, ids: [1, 5] }
params:
universe_csv: universe.csv
GUI-authored splits over a cu3s folder (contract)
External split authors (e.g. the CuvisNEXT split designer) write a frozen splits.json
(a serialized DataSplitConfig with file_indices selectors) against a folder of cu3s
files with per-measurement granularity. That contract is cu3s folder mode with
frames: measurements:
data:
data_module: cu3s
batch_size: 1
num_workers: 0
splits:
splits_path: <absolute path to the frozen splits.json>
params:
data_dir: <folder holding the .cu3s files>
frames: measurements
recursive: true # walk per-day subfolders
processing_mode: Reflectance
The frozen rules both sides implement:
- Universe = every
*.cu3sunderdata_dir(recursive whenrecursive: true), one sample per measurement0..N-1, ordered by(source, index). - Source identity is canonical: the absolute path with forward slashes and
filesystem-true case — Python
Path(p).resolve().as_posix(), C++/QtQFileInfo::canonicalFilePath(). Selectors in the authoredsplits.jsonmust carry exactly this form; matching is string equality, so a moved or renamed member file fails loud with "matched 0 samples" rather than silently shrinking a split. uid=<source>#<index>(the sibling COCO image id equals the read position, so it never extends the uid).universe_hash= sha256 over the ordered uids, each followed by\n(cuvis_ai_core.data.splits_io.universe_hash). Forfile_indicessplits the server treats the hash as informational (only positionaldir_indicessplits are hash-verified); staleness detection is the author's concern.- Annotations are the sibling
<stem>.jsonCOCO next to each cu3s (attached automatically); an emptypredictstage means the whole universe. - Training stages require splits.
cu3sdoes not own split semantics:fit/validate/testwith noDataConfig.splitsraise instead of silently iterating the whole universe (which would contaminate statistical initialization with anomalous frames). Split-lesspredictover the whole universe stays valid.
The golden fixture tests/cuvis_ai_dataloader/fixtures/gui_authored_splits.json is the
byte-level reference of the authored shape (the {DATA_DIR} token stands in for the
machine-specific folder); the same file is committed in the CuvisNEXT test suite and its
universe_hash doubles as the shared sha256 test vector. Changing it is a cross-repo
contract change.
Architecture
Concrete DataModules subclass cuvis_ai_core.data.datamodule.BaseCuvisAIDataModule
and implement validate_params plus the selector hooks enumerate(required_attrs)
(the module's attributed sample universe) and build_dataset_from_refs(refs);
a module that owns its own splits also implements build_stage_dataset(stage).
Per-format cube readers and labelers are internal helpers (data/readers/,
data/labelers/), reused but not a plugin contract. Module-top imports stay free
of heavy deps; cuvis / tifffile / pycocotools / scikit-image load lazily
on first use (data/_extras.py).
Development
uv sync --extra dev
uv run pytest tests/ -v
uv run ruff check cuvis_ai_dataloader/ tests/
uv run ruff format cuvis_ai_dataloader/ tests/
uv run mypy cuvis_ai_dataloader/
Git hooks
Enable the repo's hooks once per clone:
git config core.hooksPath .githooks
- pre-commit:
ruff format+ruff check --fixon staged Python, then re-stages. - pre-push:
ruff format --check,ruff check, docstring coverage (uvx interrogate, ≥95%, configured in[tool.interrogate]), andpytest -m "not slow and not gpu".
Skip a hook for one command with --no-verify.
Contributing
Contributions are welcome. Please:
- Ensure tests pass
- Run ruff format and ruff check
- Keep type hints and update docs as needed
License
Licensed under the Apache License 2.0. See LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cuvis_ai_dataloader-0.5.0.tar.gz.
File metadata
- Download URL: cuvis_ai_dataloader-0.5.0.tar.gz
- Upload date:
- Size: 179.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a61a562a3cc18a7eb58c9013f853a18a7bef466fcd850e1953513b7a455d14b
|
|
| MD5 |
5cb75a6f4ffd6157c6a42d95865f17d4
|
|
| BLAKE2b-256 |
ce1a0d88753014febd43d4a18df984472f08e367002d8c440a7cb0676899893b
|
Provenance
The following attestation bundles were made for cuvis_ai_dataloader-0.5.0.tar.gz:
Publisher:
pypi-release.yml on cubert-hyperspectral/cuvis-ai-dataloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cuvis_ai_dataloader-0.5.0.tar.gz -
Subject digest:
8a61a562a3cc18a7eb58c9013f853a18a7bef466fcd850e1953513b7a455d14b - Sigstore transparency entry: 2257339605
- Sigstore integration time:
-
Permalink:
cubert-hyperspectral/cuvis-ai-dataloader@84e888db8c123a631bddd6fef33e4905f04fa3b0 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/cubert-hyperspectral
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@84e888db8c123a631bddd6fef33e4905f04fa3b0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cuvis_ai_dataloader-0.5.0-py3-none-any.whl.
File metadata
- Download URL: cuvis_ai_dataloader-0.5.0-py3-none-any.whl
- Upload date:
- Size: 56.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1700fa9a29c06b0e2798ff9b977b14057f14d8bef1d8cfb943118d8d2a43807
|
|
| MD5 |
3e7b8fbd135cebb58a4aa33083b0f213
|
|
| BLAKE2b-256 |
09bdabe3bbb8c7b27b0f3e10d04f0d1b8bccf871270fb602997944f22fd95f34
|
Provenance
The following attestation bundles were made for cuvis_ai_dataloader-0.5.0-py3-none-any.whl:
Publisher:
pypi-release.yml on cubert-hyperspectral/cuvis-ai-dataloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cuvis_ai_dataloader-0.5.0-py3-none-any.whl -
Subject digest:
a1700fa9a29c06b0e2798ff9b977b14057f14d8bef1d8cfb943118d8d2a43807 - Sigstore transparency entry: 2257339618
- Sigstore integration time:
-
Permalink:
cubert-hyperspectral/cuvis-ai-dataloader@84e888db8c123a631bddd6fef33e4905f04fa3b0 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/cubert-hyperspectral
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-release.yml@84e888db8c123a631bddd6fef33e4905f04fa3b0 -
Trigger Event:
push
-
Statement type: