Skip to main content

zarrnii

ZarrNii is a Python library for working with OME-Zarr, NIfTI, and Imaris formats. ZarrNii bridges the gap between these popular formats, enabling seamless data transformation, metadata preservation, and efficient processing of biomedical images. The motivating application is for whole brain lightsheet microscopy and ultra-high field MRI, but it can generally be used for any 3D+[channel,time] datasets.

ZarrNii allows you to:

  • Read and write OME-Zarr, NIfTI, and Imaris datasets
  • Perform transformations like cropping, downsampling, and interpolation.
  • Preserve and manipulate metadata from OME-Zarr (e.g., axes, coordinate transformations, OME annotations).

Installation

Using pip (recommended)

pip install zarrnii

Optional Dependencies

For additional format support:

# For Imaris (.ims) file support
pip install zarrnii[imaris]

Development installation

For contributing or development, clone the repository and install with uv:

git clone https://github.com/khanlab/zarrnii.git
cd zarrnii
uv sync --dev

Key Features

  • Seamless Format Conversion: Easily convert between OME-Zarr, NIfTI, and Imaris while preserving spatial metadata.
  • ZipStore Support: Read and write OME-Zarr files in compressed ZIP format (.ozx) for efficient storage and sharing.
  • Transformations: Apply common operations like affine transformations, downsampling, and upsampling.
  • Multiscale Support: Work with multiscale OME-Zarr pyramids.
  • Metadata Handling: Access and modify OME-Zarr metadata like axes and transformations.
  • Lazy Loading: Leverage Dask arrays for efficient processing of large datasets.
  • Segmentation Plugins: Extensible plugin architecture for image segmentation algorithms.

Physical Units Invariant

ZarrNii always stores all spatial coordinates, spacing, and translations internally in millimeters (mm). This invariant is enforced automatically at every import path:

Import method Source unit if not specified Action on import
from_darr (caller-provided axes_units) converts non-mm → mm
from_ome_zarr from OME-Zarr metadata converts non-mm → mm
from_nifti from NIfTI header converts non-mm → mm
from_ome_tif "micrometer" default converts non-mm → mm
from_imaris "micrometer" default converts non-mm → mm
from_tif_stack (caller-provided axes_units) converts non-mm → mm

What this means in practice

  • Existing mm pipelines are completely unaffected — images already in mm are stored as-is.
  • Non-mm images (e.g. lightsheet data typically stored in µm) are automatically scaled and axes_units is updated to "millimeter" on load. Downstream code always receives mm values without any silent surprises.
  • Outputs (to_nifti, to_ome_zarr, etc.) produce mm values by default because the internal representation is already mm.
  • There is no global configuration for the internal unit — mm is the unconditional invariant.
import dask.array as da
from zarrnii import ZarrNii

# Loading a µm OME-TIFF: spacing is automatically converted to mm on import.
znii = ZarrNii.from_ome_tif("lightsheet.ome.tif")
print(znii.scale)         # e.g. {'z': 0.001, 'y': 0.000325, 'x': 0.000325}  [all mm]
print(znii.ngff_image.axes_units)  # {'z': 'millimeter', 'y': 'millimeter', 'x': 'millimeter'}

# Crop using mm coordinates — no unit conversion needed.
cropped = znii.crop(x_min=0.0, x_max=1.0, y_min=0.0, y_max=1.0)

# NIfTI output is in mm by default.
znii.to_nifti("output.nii.gz")

Advanced Topics

Orientation Metadata Backwards Compatibility

Starting from version 0.2.0, ZarrNii implements improved orientation metadata handling with backwards compatibility for existing OME-Zarr files:

New Format (v0.2.0+)

  • Metadata Key: xyz_orientation
  • Axis Order: Always in XYZ axes order for consistency
  • Example: "RAS" means Right-to-left, Anterior-to-posterior, Superior-to-inferior in XYZ space

Legacy Format (pre-v0.2.0)

  • Metadata Key: orientation
  • Axis Order: ZYX axes order (reversed from XYZ)
  • Example: "SAR" in ZYX order is equivalent to "RAS" in XYZ order

Automatic Conversion

ZarrNii automatically handles both formats when loading OME-Zarr files:

# Loading prioritizes xyz_orientation, falls back to orientation (with reversal)
znimg = ZarrNii.from_ome_zarr("legacy_file.zarr")  # Works with both formats

# New files always use xyz_orientation format
znimg.to_ome_zarr("new_file.zarr")  # Saves with xyz_orientation

Migration Guide

  • Existing files: Continue to work without modification
  • New files: Use the improved xyz_orientation format automatically
  • API: The orientation property maintains backwards compatibility

Segmentation Plugin System

ZarrNii includes a plugin architecture for image segmentation algorithms, starting with Otsu thresholding:

from zarrnii import ZarrNii, OtsuSegmentation

# Load your image
znimg = ZarrNii.from_ome_zarr("image.ome.zarr")

# Apply Otsu thresholding segmentation
segmented = znimg.segment_otsu(nbins=256)

# Or use the generic plugin interface
plugin = OtsuSegmentation(nbins=128)
segmented = znimg.segment(plugin)

# Save segmented results
segmented.to_ome_zarr("segmented_image.ome.zarr")

Custom Plugins

Create your own segmentation algorithms by extending the SegmentationPlugin base class:

from zarrnii.plugins.segmentation import SegmentationPlugin

class CustomSegmentation(SegmentationPlugin):
    def segment(self, image, metadata=None):
        # Your segmentation logic here
        return binary_mask.astype(np.uint8)
    
    @property
    def name(self):
        return "Custom Algorithm"
    
    @property 
    def description(self):
        return "Description of your algorithm"

Quick Start

from zarrnii import ZarrNii

# Load an OME-Zarr dataset
znimg = ZarrNii.from_ome_zarr("path/to/zarr_dataset.ome.zarr")

# Or load from Imaris (requires zarrnii[imaris])
# znimg = ZarrNii.from_imaris("path/to/microscopy_data.ims")

# Load from compressed ZIP format
znimg_zip = ZarrNii.from_ome_zarr("path/to/dataset.ome.zarr.zip")

# Perform a transformation (e.g., downsample)
downsampled_znimg = znimg.downsample(level=2)

# Save as NIfTI
downsampled_znimg.to_nifti("output_dataset.nii")

# Save as compressed OME-Zarr ZIP file
downsampled_znimg.to_ome_zarr("compressed_output.ome.zarr.zip")

Development

For development, this project uses:

  • uv for fast dependency management
  • pytest for testing
  • black for code formatting
  • mkdocs for documentation

Available commands (using uv run):

# Run tests
uv run pytest

# Format code
uv run black .

# Build documentation
uv run mkdocs build

# Serve docs locally
uv run mkdocs serve

Using the justfile:

If you have just installed:

# See all available tasks
just help

# Run tests
just test

# Format and lint
just quality_fix

Learn More

Explore the documentation to get started.

Contributing

Contributions are welcome! Please read our contributing guidelines and ensure all tests pass before submitting pull requests.

Metadata

Release files for zarrnii 0.21.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zarrnii 0.21.3
File Size Uploaded
zarrnii-0.21.3.tar.gz 1.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for zarrnii 0.21.3
File Interpreter ABI Platform
zarrnii-0.21.3-py3-none-any.whl Python 3 none any Details

Total release size: 1.9 MB

Release files / zarrnii-0.21.3.tar.gz

Download URL zarrnii-0.21.3.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
aa51664f63cc75d9147adda1e6c61f075d48321f118c9d1e2a27c8c5adba3db0
BLAKE2b-256 checksum
How to use checksums
d3904383abc3d1277143a6f80897d9df0d14810efec4685a491b373872933d08
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 7, 2026.

Transparency log

Release files / zarrnii-0.21.3-py3-none-any.whl

Download URL zarrnii-0.21.3-py3-none-any.whl
Size 154.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ebbc02679e0d71e6e4d19cf38759e1f3f765a3e3658a56c6b0685213876b45e
BLAKE2b-256 checksum
How to use checksums
593c94bb22451fc7ab309685a23f878317d07d072681a39079d8fb637c0a6cd1
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 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.21.3 This release

2 release files

0.21.2

2 release files

0.21.1

2 release files

0.20.2

2 release files

0.19.7

2 release files

0.19.6

2 release files

0.19.5

2 release files

0.19.4

2 release files

0.19.3

2 release files

0.19.2

2 release files

0.19.1

2 release files

0.18.1

2 release files

0.18.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page