Dimension-aware ML pipelines for scientific data
Project description
XDFlow
Dimension-aware, metadata-driven ML pipelines for scientific data
xdflow is a machine learning framework for scientific data stored as labeled xarray objects. Transforms, predictors, validators, and tuners work with dimensions and coordinates such as trial, channel, time, stimulus, session, and subject, instead of losing that information when data is reshaped to anonymous (samples, features) arrays.
In a NumPy/sklearn workflow, that structure usually becomes side data:
X.shape # (180, 100) # was (180, 4, 25)
y # was a coordinate
sessions # tracked separately
channel_names # tracked separately
Every split, transform, prediction, and score then depends on keeping those arrays in sync. A bad reindex or reshape can still produce valid-looking arrays and scores.
xdflow keeps dimensions, coordinates, targets, groups, split settings, and transform state in the pipeline contract. Validators can split by named coordinates, stateful steps refit inside each fold, and fold-invariant work can be reused across CV and tuning.
This cuts down custom split/cache code and catches many alignment and leakage errors earlier.
Installation
# Core framework (minimal dependencies)
pip install xdflow
# With hyperparameter tuning
pip install xdflow[tuning]
# With all extras (LightGBM, visualization, MLflow, spectral analysis)
pip install xdflow[all]
Requirements: Python 3.11+
Quick Example
This example works with the core install. A full runnable version lives at examples/quickstart.py.
import numpy as np
import xarray as xr
from sklearn.linear_model import LogisticRegression
from xdflow.composite import Pipeline
from xdflow.core import DataContainer
from xdflow.cv import KFoldValidator
from xdflow.transforms.basic_transforms import FlattenTransform
from xdflow.transforms.normalization import ZScoreTransform
from xdflow.transforms.sklearn_transform import SKLearnPredictor
rng = np.random.default_rng(0)
stimuli = np.repeat(["rest", "tone", "odor"], 60)
rng.shuffle(stimuli)
values = rng.normal(0.0, 1.2, size=(stimuli.size, 4, 25))
values[stimuli == "tone", 1, 8:15] += 1.5
values[stimuli == "odor", 2, 14:22] += 1.5
data = xr.DataArray(
values,
dims=("trial", "channel", "time"),
coords={
"trial": np.arange(stimuli.size),
"channel": [f"ch{i}" for i in range(4)],
"time": np.linspace(-0.2, 0.8, 25),
"stimulus": ("trial", stimuli),
},
)
container = DataContainer(data)
pipeline = Pipeline(
name="core_quickstart",
steps=[
("zscore", ZScoreTransform(by_dim=["trial"])),
("flatten", FlattenTransform(dims=("channel", "time"))),
(
"classifier",
SKLearnPredictor(
LogisticRegression,
sample_dim="trial",
target_coord="stimulus",
max_iter=500,
),
),
],
)
cv = KFoldValidator(
n_splits=5,
shuffle=True,
random_state=0,
stratify_coord="stimulus",
scoring="f1_weighted",
verbose=False,
)
cv.set_pipeline(pipeline)
score = cv.cross_validate(container, verbose=False)
print(f"Weighted F1: {score:.3f}")
# Coordinates stay attached, and stateful steps are refit per fold.
Key Features
- Dimension contracts: transforms declare the dimensions they consume and produce, so invalid reshapes and step handoffs fail earlier.
- Composition primitives: sequential
Pipeline, parallelTransformUnion, conditionalSwitchTransform, per-groupGroupApplyTransform, and toggleableOptionalTransform. - Leakage-aware cross-validation: validators split on named trial, target, and group coordinates; stateful steps refit only on training folds; out-of-fold predictions are emitted for stacking and ensembles.
- Fold-invariant caching: expensive stateless work such as spectrograms or filtering can run once and be reused across folds and tuning trials.
- Hyperparameter tuning: Optuna-based search across pipeline architectures, reusable static-prefix caching across tuning trials, optional MLflow logging, and explicit seed management.
- Pluggable estimators: any class implementing the sklearn API — sklearn itself, LightGBM, XGBoost, or your own — drops into the pipeline via
SKLearnTransformerandSKLearnPredictor. - Multi-output support: a unified interface for multi-target regression, multilabel classification, and sample-weighted training with sklearn-compatible estimators.
- Explicit API contracts: focused transform and pipeline interfaces keep custom code small enough to write, test, review, and generate with LLM coding tools.
Relation to sklearn and pipeline frameworks
xdflow does not replace sklearn. It wraps sklearn estimators when they fit, and keeps named dimensions and coordinates intact around them. It also does not replace pipeline orchestrators like Kedro or ZenML; an xdflow pipeline can live inside one of their nodes. The layer it fills is between: opinionated transform and CV semantics for data whose axes mean something.
Documentation
Quick Links:
- Data Contract
- Installation & Setup
- 5-Minute Core Quickstart
- Core Concepts
- Tutorials
- Using XDFlow With LLMs
- API Reference
Contributing
We welcome contributions! Whether you're:
- Adding a new transform
- Improving documentation
- Reporting bugs
- Requesting features
- Sharing use cases
See CONTRIBUTING.md for guidelines.
Early adopters especially welcome - the API is still stabilizing, and your feedback shapes the future of this project.
Development Setup
This project uses uv for dependency management.
# Install uv (if you don't have it)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone and install
git clone https://github.com/canaery/xdflow.git
cd xdflow
uv sync --all-extras # creates .venv and installs everything
# Run commands via uv
uv run pytest # run tests
uv run ruff check xdflow tests examples # lint
# Or activate the venv directly
source .venv/bin/activate
pytest
License
MIT License - see LICENSE for details.
Acknowledgments
- xarray - Labeled multidimensional arrays
- scikit-learn - ML fundamentals
- Optuna - Hyperparameter optimization
- MLflow - Experiment tracking
Contact
- Lead maintainer: Julien Bloch
- GitHub Issues: Report bugs or request features
- Discussions: Ask questions, share ideas
Project details
Release history Release notifications | RSS feed
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 xdflow-0.1.1.tar.gz.
File metadata
- Download URL: xdflow-0.1.1.tar.gz
- Upload date:
- Size: 604.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91c7154e63602e3a369496f2345802b2514d07c8f268ce6173ae847758a9dfc7
|
|
| MD5 |
06c67acc8ff22f6133b8aa5247003822
|
|
| BLAKE2b-256 |
dd389c2f79141269e8842cafbfd22baef27f6306ece5d311994f8fd3808a8f64
|
Provenance
The following attestation bundles were made for xdflow-0.1.1.tar.gz:
Publisher:
ci.yml on canaery/xdflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xdflow-0.1.1.tar.gz -
Subject digest:
91c7154e63602e3a369496f2345802b2514d07c8f268ce6173ae847758a9dfc7 - Sigstore transparency entry: 1592358710
- Sigstore integration time:
-
Permalink:
canaery/xdflow@5854e1ee8dd5b2501263db8e87d6b3ed72984b43 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/canaery
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@5854e1ee8dd5b2501263db8e87d6b3ed72984b43 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xdflow-0.1.1-py3-none-any.whl.
File metadata
- Download URL: xdflow-0.1.1-py3-none-any.whl
- Upload date:
- Size: 183.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dbb3492a12028bf8e56fd86c657cffcaa9059e01d8c1ea68967fe796b154085
|
|
| MD5 |
1de7fca95a0ef035a7d609329b3cec8e
|
|
| BLAKE2b-256 |
2fff6fc5fccf9236d4f8f9667d8ebc11940c73bce4b26ce17a791e5fdf480b03
|
Provenance
The following attestation bundles were made for xdflow-0.1.1-py3-none-any.whl:
Publisher:
ci.yml on canaery/xdflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xdflow-0.1.1-py3-none-any.whl -
Subject digest:
9dbb3492a12028bf8e56fd86c657cffcaa9059e01d8c1ea68967fe796b154085 - Sigstore transparency entry: 1592359635
- Sigstore integration time:
-
Permalink:
canaery/xdflow@5854e1ee8dd5b2501263db8e87d6b3ed72984b43 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/canaery
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@5854e1ee8dd5b2501263db8e87d6b3ed72984b43 -
Trigger Event:
push
-
Statement type: