# iohub

|              |                                                                                                                                                                             |
| :----------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|  **Status**  | [![Docs][badge-docs]][link-docs] [![Tests][badge-tests]][link-tests]                                                                                                        |
| **Package**  | [![PyPI][badge-pypi]][link-pypi] [![Python][badge-python]][link-pypi]                                                                                                       |
|   **Meta**   | [![SPEC 0][badge-spec0]][link-spec0] [![Hatch][badge-hatch]][link-hatch] [![uv][badge-uv]][link-uv] [![Ruff][badge-ruff]][link-ruff] [![prek][badge-prek]][link-prek] [![License][badge-license]][link-license]  |
|   **Cite**   | [![DOI][badge-doi]][link-doi]                                                                                                                                               |

[badge-docs]: https://github.com/czbiohub-sf/iohub/actions/workflows/docs.yml/badge.svg
[badge-tests]: https://github.com/czbiohub-sf/iohub/actions/workflows/test.yml/badge.svg
[badge-pypi]: https://img.shields.io/pypi/v/iohub.svg
[badge-python]: https://img.shields.io/pypi/pyversions/iohub
[badge-hatch]: https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg
[badge-uv]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json
[badge-spec0]: https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038
[link-spec0]: https://scientific-python.org/specs/spec-0000/
[badge-ruff]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
[badge-prek]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json
[badge-license]: https://img.shields.io/badge/License-BSD--3--Clause-blue.svg
[badge-doi]: https://zenodo.org/badge/DOI/10.5281/zenodo.15022067.svg

[link-docs]: https://czbiohub-sf.github.io/iohub
[link-tests]: https://github.com/czbiohub-sf/iohub/actions/workflows/test.yml
[link-pypi]: https://pypi.org/project/iohub
[link-hatch]: https://github.com/pypa/hatch
[link-uv]: https://github.com/astral-sh/uv
[link-ruff]: https://github.com/astral-sh/ruff
[link-prek]: https://github.com/j178/prek
[link-license]: https://opensource.org/licenses/BSD-3-Clause
[link-doi]: https://doi.org/10.5281/zenodo.15022067

N-dimensional bioimaging produces data and metadata in various formats,
and iohub aims to become a unified Python interface to the most common formats
used at the Biohub and in the broader imaging community.

## Supported formats

### Read

- OME-Zarr ([OME-NGFF v0.5](https://ngff.openmicroscopy.org/0.5/), OME-NGFF v0.4)
- Micro-Manager TIFF sequence, OME-TIFF (MMStack), and NDTiff datasets
- Custom data formats generated by Biohub microscopes
  - Supported: Falcon (PTI), Dorado (ClearControl), Dragonfly (OpenCell OME-TIFF), Mantis (NDTiff)
  - WIP: DaXi

### Write

- OME-Zarr ([OME-NGFF v0.5](https://ngff.openmicroscopy.org/0.5/))

## Quick start

### Installation

Install iohub from PyPI:

```sh
pip install iohub
```

With optional TensorStore support:

```sh
pip install "iohub[tensorstore]"
```

Or install the latest development version:

```sh
pip install git+https://github.com/czbiohub-sf/iohub.git
```

> For development setup, see the [contributing guide](CONTRIBUTING.md#setting-up-development-environment).

### Command-line interface

To check if iohub works for a dataset:

```sh
iohub info /path/to/data/
```

The CLI can show a summary of the dataset,
point to relevant Python calls,
and convert other data formats to the latest OME-Zarr.
See the full CLI help message by typing `iohub` or `iohub [command] --help` in the terminal.

### Working with OME-Zarr

Load and modify an [example OME-Zarr](https://zenodo.org/record/7274533#.Y-q9uOzMJqv) dataset:

```py
import numpy as np
from iohub import open_ome_zarr

with open_ome_zarr(
    "20200812-CardiomyocyteDifferentiation14-Cycle1.zarr",
    mode="r",
    layout="auto",
) as dataset:
    dataset.print_tree()  # prints the hierarchy of the zarr store
    channel_names = dataset.channel_names
    print(channel_names)
    img_array = dataset[
        "B/03/0/0"
    ]  # lazy Zarr array for the raw image in the first position
    raw_data = img_array.numpy()  # loads a CZYX 4D array into RAM
    print(raw_data.mean())  # does some analysis

with open_ome_zarr(
    "max_intensity_projection.zarr",
    mode="w-",
    layout="hcs",
    channel_names=channel_names,
) as dataset:
    new_fov = dataset.create_position(
        "B", "03", "0"
    )  # creates fov with the same path
    new_fov["0"] = raw_data.max(axis=1).reshape(
        (1, 1, 1, *raw_data.shape[2:])
    )  # max projection along Z axis and prepend dims to 5D
    dataset.print_tree()  # checks that new data has been written
```

For more about API usage, refer to the [documentation](https://czbiohub-sf.github.io/iohub/)
and the [example scripts](https://github.com/czbiohub-sf/iohub/tree/main/docs/examples).

### Reading Micro-Manager TIFF data

Read a directory containing a TIFF dataset:

```py
from iohub import read_images

reader = read_images("/path/to/data/")
print(reader)
```

## Why iohub?

This project is inspired by the existing Python libraries for bioimaging data I/O,
including [ome-zarr-py](https://github.com/ome/ome-zarr-py), [tifffile](https://github.com/cgohlke/tifffile) and [aicsimageio](https://github.com/AllenCellModeling/aicsimageio).
They support some of the most widely adopted and/or promising formats in microscopy,
such as OME-Zarr and OME-TIFF.

iohub bridges the gaps among them with the following features:

- Efficient reading of data in various TIFF-based formats produced by the Micro-Manager/Pycro-Manager acquisition stack.
- Efficient and customizable conversion of data and metadata from TIFF to OME-Zarr.
- Pythonic and atomic access of OME-Zarr data with parallelized analysis in mind.
- OME-Zarr metadata is automatically constructed and updated for writing,
and verified against the specification when reading.
- Adherence to the latest OME-NGFF specification (v0.5) whenever possible.
