T-MIDAS
A plugin for batch processing of confocal and whole-slide microscopy images of biological tissues
napari-tmidas
Need fast batch processing for confocal & whole-slide microscopy images of biological cells and tissues?
This open-source napari plugin integrates state-of-the-art AI + analysis tools in an interactive GUI with side-by-side result comparison! Transform, analyze, and quantify microscopy data at scale including deep learning - from file conversion to segmentation, tracking, and analysis.
✨ Key Features
🤖 AI Methods Built-In
- Virtual staining (VisCy) • Denoising (CAREamics) • Spot detection (Spotiflow) • Segmentation (Cellpose, Convpaint) • Tracking (Trackastra, HOCT, Ultrack)
- Auto-install in isolated environments • No dependency conflicts • GPU acceleration
🔄 Universal File Conversion
- Convert LIF, ND2, CZI, NDPI, Acquifer → TIFF or OME-Zarr
- Preserve spatial metadata automatically
⚡ Batch Processing
- Process entire folders with one click • 40+ processing functions • Progress tracking & quality control
- One Dimension Order setting, shared by every function — set it once per batch, not per function
� Interactive Workflow
- Side-by-side table view of original and processed images • Click to instantly compare results • Quickly iterate parameter values • Real-time visual feedback
�📊 Complete Analysis Pipeline
- Segmentation → Tracking → Quantification → Colocalization
🚀 Quick Start
Supports Python 3.11+; commands below use Python 3.12. We recommend installing with uv, which downloads Python for you — no conda needed.
# 1. Install uv (one-time; Windows: see Installation below)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Create an environment with napari and the plugin
uv venv --python 3.12 ~/napari-tmidas-env
source ~/napari-tmidas-env/bin/activate
uv pip install "napari[all]" napari-tmidas
# 3. Launch napari
napari
Then find napari-tmidas in the Plugins menu. Watch video tutorials →
💡 Tip: AI methods (SAM2, Cellpose, Spotiflow, etc.) auto-install into isolated environments on first use - no manual setup required! They are built with uv, which also downloads a different Python where a method needs one. If you install packages through a mirror configured in
pip.conf(uv does not read it), setNAPARI_TMIDAS_NO_UV=1to build them with pip instead.
⚠️ Before a batch run: set Dimension Order (top of the batch widget) to match your data —
TZYXfor a 3D time series,ZYXfor a Z-stack,TYXfor a 2D movie. Most microscopy TIFFs carry no usable axis metadata, so onAutoa function that builds 3D objects cannot tell Z from T: it will either stop with an error or label the same object once per Z slice. The widget reads each file's rank up front, shows it next to the dropdown, and warns before the run starts.
📖 Documentation
AI-Powered Methods
| Method | Description | Documentation |
|---|---|---|
| 🎨 VisCy | Virtual staining from phase/DIC | Guide |
| 🔧 CAREamics | Noise2Void/CARE denoising | Guide |
| 🎯 Spotiflow | Spot/puncta detection | Guide |
| 🔬 Cellpose | Cell/nucleus segmentation | Guide |
| 🎨 Convpaint | Custom semantic/instance segmentation | Guide |
| 📈 Trackastra | Transformer-based cell tracking | Guide |
| 🧬 HOCT | Transformer-based cell tracking (Higher-Order Cell Tracking Transformer) | Guide |
| 🔗 Ultrack | Cell tracking based on segmentation ensemble | Guide |
Core Workflows
- File Conversion - Multi-format microscopy file conversion (LIF, ND2, CZI, NDPI, Acquifer)
- Batch Processing - All 40+ processing functions in one place
- Frame Removal - Interactive human-in-the-loop frame removal from time series
- Label-Based Cropping - Interactive ROI extraction with label expansion
- Quality Control - Visual QC with grid overlay
- Quantification - Extract measurements from labels
Advanced Features
- Batch Crop Anything - Interactive object cropping with SAM2
- Batch Label Inspection - Manual label verification and editing, with one-click delete/relabel across all timepoints, click-to-split for merged objects, and click-to-merge-neighbors for over-segmented ones
- Multichannel Processing - Channel selection and per-channel processing
💻 Installation
Recommended: uv
1. Install uv (one-time). Close and reopen your terminal afterwards so uv is on your PATH.
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
2. Create an environment and install napari with the plugin. uv downloads Python 3.12 if you don't have it. On Windows (PowerShell), write $HOME\napari-tmidas-env wherever these commands say ~/napari-tmidas-env.
uv venv --python 3.12 ~/napari-tmidas-env
source ~/napari-tmidas-env/bin/activate # Windows: $HOME\napari-tmidas-env\Scripts\activate
uv pip install "napari[all]" napari-tmidas
| Your Needs | Command (in the activated environment) |
|---|---|
| Standard installation | uv pip install napari-tmidas |
| Want the latest dev features | uv pip install "napari-tmidas @ git+https://github.com/MercaderLabAnatomy/napari-tmidas.git" |
3. Start napari whenever you want to use it: activate the environment, then run napari.
source ~/napari-tmidas-env/bin/activate # Windows: $HOME\napari-tmidas-env\Scripts\activate
napari
Updating napari-tmidas
Activate the environment, then upgrade the package:
source ~/napari-tmidas-env/bin/activate # Windows: $HOME\napari-tmidas-env\Scripts\activate
# Installed from PyPI (standard installation)
uv pip install --upgrade napari-tmidas
# Installed from GitHub (dev version): fetches the newest commit
uv pip install --upgrade "napari-tmidas @ git+https://github.com/MercaderLabAnatomy/napari-tmidas.git"
# Check which version you have
uv pip show napari-tmidas
--upgrade also brings napari-tmidas's dependencies (which can include napari) up to their newest compatible versions. To upgrade only napari-tmidas and leave everything else as it is, use uv pip install --upgrade-package napari-tmidas napari-tmidas instead. The AI methods' own environments in ~/.napari-tmidas/envs are separate and are left as they are. If one misbehaves after an update, delete its folder (e.g. ~/.napari-tmidas/envs/cellpose) and it is rebuilt the next time you use that method. To update uv itself, run uv self update.
Alternative: conda / mamba
mamba create -y -n napari-tmidas -c conda-forge python=3.12
mamba activate napari-tmidas
python -m pip install "napari[all]" napari-tmidas
Update with python -m pip install --upgrade napari-tmidas inside the activated environment. conda is not needed by the AI methods: their environments are built with uv either way.
🖼️ Screenshots
File Conversion Widget
Convert proprietary formats to open standards with metadata preservation.
Batch Processing Interface
Select files → Choose processing function → Run on entire dataset.
Label Inspection
Inspect and manually correct segmentation results.
SAM2 Crop Anything
Interactive object selection and cropping with SAM2.
📋 TODO
Memory-Efficient Streaming
Most of this is done. Batch processing no longer materializes whole stacks: the worker keeps large inputs lazy and streams results back to disk block by block (256 MB budget), 15 functions map their existing body over blocks via the @chunked decorator, and 6 more own their I/O outright via skip_load. Measured end to end on a real (31, 2, 57, 2720, 2720) uint16 acquisition — 52 GB dense — Gamma Correction peaks at 3.15 GB RSS in 8.8 min, byte-identical to the dense path. Convpaint prediction, Cellpose segmentation and Trackastra tracking all write per-timepoint now. The mechanism is documented in _chunked.py, and the behaviour is pinned by TestZarrOutputStreaming, TestSplitChannelsStreaming, TestLazyTiffLoading, TestCLAHEDaskMemory and TestRollingBallPerPlane.
What is left:
- CAREamics denoising and VisCy virtual staining still run dense. Both allocate the full output array and take the input as a NumPy array. Neither has been audited for real — that needs their dedicated virtualenvs installed.
- ~14 registered functions still scale linearly with input size. That is now a known list rather than an unknown one. Each needs either a
@chunkedconversion or a check that it cannot take one: functions using global statistics (Convert to 8-bitrescales by the whole-stack min/max) and functions with cross-block topology (Mirror Labels) both resist it. - The structural decision. Dense functions opt into laziness one at a time, by accepting
_source_filepath. Whether to keep converting them individually or change the worker's contract for all of them at once is still open.
Other Known Issues
Resize Zarr by YX Scale (OME-Zarr native)writes zarr v3 stores: attributes live inzarr.json(multiscales nested under anomekey), not in a v2.zattrs. Anything downstream that reads.zattrsdirectly will find no file there — useome_output_utils._read_root_attrs(), which handles both layouts.
🤝 Contributing
Contributions are welcome! Development uses uv; dependency versions are pinned in uv.lock, which CI installs exactly. Please ensure tests pass before submitting PRs:
git clone https://github.com/MercaderLabAnatomy/napari-tmidas.git
cd napari-tmidas
uv sync # creates .venv with the package and dev tools
uv run pytest -m "not slow" # run the test suite
After changing dependencies in pyproject.toml, run uv lock and commit the updated uv.lock. tox still works for testing against a fresh resolve.
📄 License
BSD-3 License - see LICENSE for details.
🐛 Issues
Found a bug or have a feature request? Open an issue
🙏 Acknowledgments
Built with napari and powered by:
AI/ML Methods:
Core Scientific Stack:
- NumPy • scikit-image • PyTorch
File Format Support:
- OME-Zarr • tifffile • nd2 • pylibCZIrw • readlif
Version:
- 0.5.16
Last updated:
- 2026-09-25
First released:
- 2025-03-05
License:
- Copyright (c) 2025, Marco Meer...
Supported data:
- Information not submitted
Plugin type:
Save extension:
Python versions supported:
Operating system:
- Information not submitted
Requirements:
- numpy>=1.23.0
- magicgui
- tqdm
- qtpy
- scikit-image>=0.19.0
- pyqt5
- zarr>=3
- ome-zarr
- napari-ome-zarr
- nd2
- pylibCZIrw
- readlif
- tifffile<2025.5.21,>=2023.7.4
- tiffslide
- acquifer-napari
- psygnal>=0.9.0
- ome-zarr>=0.8.0
- uv
- tox; extra == "testing"
- pytest>=7.0.0; extra == "testing"
- pytest-cov; extra == "testing"
- pytest-qt; extra == "testing"
- pytest-timeout; extra == "testing"
- napari; extra == "testing"
- pyqt5; extra == "testing"
- psygnal>=0.8.0; extra == "testing"
- napari-tmidas[testing]; extra == "all"

