DART-MLCI: Aligning Blueprint and Physical Microfluidic Chip for Design-Aware and Real-Time Capable Live-Cell Image Analysis
Real-time microfluidic RoI image processing. DART-MLCI takes a raw microscopy frame, detects alignment markers, rotates and crops the RoI, masks the region of interest, and segments cells — automatically, for any chip design described by a single JSON config (fine alignment).
Time-constant microfluidic chip mapping. DART-MLCI allows to record several RoI positions on the microfluidic chip when its on the microscopy stage and aligns the microfluidic blueprint providing all RoI positions for any chip design described by a single JSON config (coarse alignment).
The repository covers two complementary capabilities:
- Fine algiment (Masking pipeline) — marker detection, pair matching, rotation correction, polygon masking, and ROI cropping.
- Coarse alignment (Map calibration) — affine alignment of the chip blueprint with microscope stage coordinates, so every chamber can be revisited automatically.
Installation
# From PyPI
pip install dart-mlci
# Or from source
git clone https://github.com/SMLCI/DART-MLCI.git
cd DART-MLCI
pip install ".[dev]" # core + dev extras
YOLO marker-detection weights and the bundled sample images (~40 MB) are
not shipped in the wheel. They download automatically on first use to
~/.cache/dart-mlci/ (Linux/macOS) or %LOCALAPPDATA%\dart-mlci\ (Windows).
You can override the location with DART_ARTIFACTS_DIR=.... No manual
download step is required.
Optional extras: pip install "dart-mlci[api]" for the FastAPI service,
pip install "dart-mlci[segmentation]" to pull in Cellpose-SAM / Omnipose.
Quickstart: Python API
Run the marker detector on a bundled sample image:
# snippet: marker-detection
import cv2
from dart_mlci import ChipStructureLibrary, MarkerDetectionModel, sample_path
lib = ChipStructureLibrary.from_file(sample_path("chips/sak.json"), pixel_size=0.065789)
model = MarkerDetectionModel()
image = cv2.imread(str(sample_path("images/sak/0007.png")))
markers = model.predict_markers(image)
print(f"Detected {len(markers)} markers") # e.g. "Detected 4 markers"
Compose the full pipeline as steps. lib(roi_id) returns the chamber's
polygon and the expected pixel-space positions of its cross/circle markers
(mgp):
# snippet: full-pipeline
import cv2
from dart_mlci import (
ChipStructureLibrary,
ImageRotationStep,
MarkerDetectionStep,
MarkerMatchingStep,
RoIMaskingStep,
sample_path,
)
lib = ChipStructureLibrary.from_file(sample_path("chips/sak.json"), pixel_size=0.065789)
_, polygon, mgp = lib("0000") # any NormaleBox-inner ROI matches 0007.png
image = cv2.imread(str(sample_path("images/sak/0007.png")))
detect = MarkerDetectionStep()
match = MarkerMatchingStep(marker_group_pixel=mgp)
rotate = ImageRotationStep()
mask = RoIMaskingStep(marker_group_pixels=mgp, roi_polygon=polygon)
data = mask(rotate(match(detect(image))))
cropped, chamber_mask = data["image"], data["mask"]
Process Your Own TIFF Stack
scripts/process_folder.py is the CLI for batch-processing time-lapse TIFF
stacks. It works for a single stack just as well as a full experiment — point
its folders dict at one subfolder.
1. Lay out your data
my_data/
├── my_chamber/
│ ├── stack_001.tif # T x H x W, uint16
│ └── stack_002.tif
2. Write a minimal folder_config.json
{
"input_dir": "my_data",
"output_dir": "my_output",
"pixel_size": 0.0928,
"segmenter": "cellpose-sam",
"folders": {
"my_chamber": "NormaleBox-inner"
}
}
Omit chip_config / model_path to use the auto-downloaded defaults (the
SAK chip JSON and the bundled YOLO weights). Override either field with an
absolute path if you have a custom chip.
Set pixel_size to your microscope's µm/px. To list the chamber types
available in your chip JSON:
# snippet: list-chamber-types
from dart_mlci import ChipStructureLibrary, sample_path
lib = ChipStructureLibrary.from_file(sample_path("chips/sak.json"), pixel_size=0.065789)
print(list(lib.polygon_library))
3. Run
python scripts/process_folder.py \
--config folder_config.json \
--save-cropped \
--render-stacks \
--verbose
Useful flags:
| Flag | Purpose |
|---|---|
--render-stacks |
Emit timelapse.mp4 (segmentation overlay) and timelapse_raw.mp4 (rotated raw) per stack. |
--save-cropped |
Save the rotated+cropped raw frames as stack_cropped.tif. |
--min-area-um2, --max-area-um2 |
Drop segmentation artifacts outside the size range. |
--max-files N |
Process only the first N stacks (smoke testing). |
--skip-existing |
Resume a partially complete run. |
4. What you get
Each stack produces stack.tif (instance labels), cells.csv (per-cell
measurements), meta.csv (per-frame metadata), and — with --render-stacks —
two MP4s. The full output schema is in
docs/configuration.md.
Using a chip other than SAK? Author a new chip JSON — see Adapting to a new chip design.
Reproduce the Paper Experiment
A single command runs the full pipeline against the public DART dataset:
bash reproduce.sh # smoke test (1 stack per folder, ~250 MB)
bash reproduce.sh --full # full experiment (all stacks, ~9 GB)
The script creates a conda env, downloads the dataset and calibration data
from Sciebo, calibrates the map, processes all seven chamber types, and
validates the outputs. Per-step details are in
docs/configuration.md.
Map Calibration
The second core contribution: aligning the chip blueprint with microscope stage coordinates so every chamber can be revisited automatically.
# Compute affine transform from 3 calibration images
python scripts/calibrate_map.py \
--config calibration_config.json \
--output calibrated_map.csv \
--output-dir calibration_output/ \
--verbose
# Validate against independent images
python scripts/validate_map.py \
--config validation_config.json \
--output-dir validation_output/ \
--verbose
The calibration step in reproduce.sh invokes both. Validation reports
per-point error in microns and pixels and produces a histogram + spatial
error map.
REST API
pip install "dart-mlci[api]"
uvicorn dart_mlci.api.main:app --host 0.0.0.0 --port 8000
# Interactive docs at http://localhost:8000/docs
import base64, requests
b64 = base64.b64encode(open("image.tif", "rb").read()).decode()
resp = requests.post("http://localhost:8000/process-image",
json={"image": b64, "roi_id": "0050"})
print(resp.json()["chamber_type"])
Or via Docker: docker-compose up --build.
Visit http://localhost:8000/docs for interactive Swagger documentation of
every endpoint. See docs/DOCKER_GUIDE.md for
container deployment.
Adapting to a New Chip Design
The pipeline is chip-agnostic: it only needs one JSON describing chamber
polygons, marker positions, and a blueprint map. Start from the bundled SAK
config as a template (sample_path("chips/sak.json") resolves it on demand),
then follow docs/CHIP_CONFIG.md for the full schema,
polygon conventions, marker-detection trade-offs (reuse the bundled YOLO
weights vs. retrain on new fiducials), and a validation checklist.
License
MIT — Copyright (c) 2026 Johannes Seiffarth, Forschungszentrum Jülich GmbH.
Citation
If you use DART-MLCI in your research, please cite:
@software{dart-mlci,
author = {Seiffarth, Johannes and Pesch, Matthias and Scholtes, Lukas and Kohlheyer, Dietrich and Scharr, Hanno and N{\"o}h, Katharina},
title = {DART-MLCI: A design-aware microfluidic chip paradigm for real-time live-cell image analysis},
year = {2026},
url = {https://github.com/SMLCI/DART-MLCI}
}
Metadata
Release files for dart-mlci 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| dart_mlci-0.3.1.tar.gz | 223.9 kB | With provenance | Details for dart_mlci-0.3.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dart_mlci-0.3.1-py3-none-any.whl | Python 3 | none | any | Details for dart_mlci-0.3.1-py3-none-any.whl |
Total release size: 330.9 kB
Release files / dart_mlci-0.3.1.tar.gz
| Download URL | dart_mlci-0.3.1.tar.gz |
|---|---|
| Size | 223.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bc884e20c24fbc0ef641b3ec1a209f1706a1e7e598d6d9df23deec8a17bd11ed
|
|
BLAKE2b-256 checksum How to use checksums |
dca219efc229b9f1cb138b415cf8b719fc87a75198f3d2893f454205d82e402a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.
Transparency logRelease files / dart_mlci-0.3.1-py3-none-any.whl
| Download URL | dart_mlci-0.3.1-py3-none-any.whl |
|---|---|
| Size | 107.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aaaa16cb58f505e2a62a24baccd3992cf7f00b182f3eef52fce925f66b206b0a
|
|
BLAKE2b-256 checksum How to use checksums |
e39e9f63446331ea0463aeef25fb44f2fc1440ded950677c512fac244ac8de78
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.
Transparency logSecurity for dart-mlci 0.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for dart_mlci-0.3.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.