Skip to content

Commit 8f0c02c

Browse files
authored
feat: Added flexible backends with the Zarr(s)-Python and Tensorstore support. (#393)
* feat: Added flexible backends with the Zarr(s)-Python and Tensorstore support. Writing OME-Zarr v0.4 is unsupported, we can only write OME-Zarr v0.5 now. BREAKING CHANGE: Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * ci: set python 3.12 as the min version Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * fix: added append Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * style: ruff format Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * fix: Adjusted tensorstore shims Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * style: added more ruff rules Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * ci: removed pytest-xdist -n for ci Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * fix: Fixed nonexistent .path attribute for tensorstore Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * fix: Fix annotatoin evaluation and ArrayIndex Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * test: num_processes = 1 for hypothesis n Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * fix: remove Pool(1) Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * refactor: changed NGFFNDARRAY -> NGFFArray n Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> * test: use raw strings, add tests for arrays and registry n Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org> --------- Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org>
1 parent 02b7525 commit 8f0c02c

51 files changed

Lines changed: 3681 additions & 2648 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- uses: actions/checkout@v5
1616
- uses: astral-sh/setup-uv@v7
1717
with:
18-
python-version: "3.11"
18+
python-version: "3.13"
1919
enable-cache: true
2020
- run: uv sync --group doc
2121
- run: uv run zensical build --clean

.github/workflows/pr.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
runs-on: ubuntu-latest
2323
strategy:
2424
matrix:
25-
python-version: ["3.11", "3.12", "3.13"]
25+
python-version: ["3.12", "3.13", "3.14"]
2626

2727
steps:
2828
- uses: actions/checkout@v4
@@ -47,7 +47,7 @@ jobs:
4747
- uses: actions/checkout@v4
4848
- uses: astral-sh/setup-uv@v7
4949
with:
50-
python-version: "3.11"
50+
python-version: "3.12"
5151
enable-cache: true
5252
- run: uv sync --group doc
5353
- run: uv run zensical build --clean

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
max-parallel: 2
1414
matrix:
1515
platform: [ubuntu-latest, windows-latest, macos-latest]
16-
python-version: ["3.11", "3.12", "3.13"]
16+
python-version: ["3.12", "3.13", "3.14"]
1717
steps:
1818
- uses: actions/checkout@v4
1919

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
| :----------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
55
| **Status** | [![Docs][badge-docs]][link-docs] [![Tests][badge-tests]][link-tests] |
66
| **Package** | [![PyPI][badge-pypi]][link-pypi] [![Python][badge-python]][link-pypi] |
7-
| **Meta** | [![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] |
7+
| **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] |
88
| **Cite** | [![DOI][badge-doi]][link-doi] |
99

1010
[badge-docs]: https://github.com/czbiohub-sf/iohub/actions/workflows/docs.yml/badge.svg
@@ -13,6 +13,8 @@
1313
[badge-python]: https://img.shields.io/pypi/pyversions/iohub
1414
[badge-hatch]: https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg
1515
[badge-uv]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json
16+
[badge-spec0]: https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038
17+
[link-spec0]: https://scientific-python.org/specs/spec-0000/
1618
[badge-ruff]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
1719
[badge-prek]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json
1820
[badge-license]: https://img.shields.io/badge/License-BSD--3--Clause-blue.svg
@@ -44,8 +46,7 @@ used at the Biohub and in the broader imaging community.
4446

4547
### Write
4648

47-
- OME-Zarr ([OME-NGFF v0.5](https://ngff.openmicroscopy.org/0.5/), OME-NGFF v0.4)
48-
- Multi-page TIFF stacks organized in a directory hierarchy that mimics OME-NGFF (WIP)
49+
- OME-Zarr ([OME-NGFF v0.5](https://ngff.openmicroscopy.org/0.5/))
4950

5051
## Quick start
5152

docs/examples/run_multi_fov_hcs_ome_zarr.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,7 @@
3838
)
3939

4040
with open_ome_zarr(
41-
store_path,
42-
layout="hcs",
43-
mode="w-",
44-
channel_names=["DAPI", "GFP", "Brightfield"],
41+
store_path, layout="hcs", mode="w-", channel_names=["DAPI", "GFP", "Brightfield"], implementation="tensorstore"
4542
) as dataset:
4643
# Create and write to positions
4744
# This affects the tile arrangement in visualization

pyproject.toml

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,45 @@
11
[build-system]
22
build-backend = "hatchling.build"
3-
requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"]
3+
requires = ["hatchling", "uv-dynamic-versioning>=0.14.0"]
44

55
[project]
66
name = "iohub"
77
description = "N-dimensional bioimaging data I/O with OME metadata in Python"
88
authors = [
9-
{name = "CZ Biohub and iohub contributors", email = "iohub@czbiohub.org"},
9+
{name = "Biohub and iohub contributors", email = "iohub@czbiohub.org"},
1010
]
1111
license = {file = "LICENSE"}
1212
readme = "README.md"
13-
requires-python = ">=3.11"
13+
requires-python = ">=3.12"
1414
classifiers = [
1515
"Development Status :: 3 - Alpha",
1616
"Intended Audience :: Science/Research",
1717
"License :: OSI Approved :: BSD License",
1818
"Programming Language :: Python :: 3 :: Only",
19-
"Programming Language :: Python :: 3.11",
2019
"Programming Language :: Python :: 3.12",
2120
"Programming Language :: Python :: 3.13",
21+
"Programming Language :: Python :: 3.14",
2222
"Topic :: Scientific/Engineering",
2323
"Topic :: Scientific/Engineering :: Image Processing",
2424
"Operating System :: Microsoft :: Windows",
2525
"Operating System :: POSIX :: Linux",
2626
"Operating System :: MacOS :: MacOS X",
2727
]
2828
dependencies = [
29-
"pandas>=1.5.2",
29+
"pandas>=2",
3030
"pydantic>=2.8.2",
3131
"pydantic_extra_types>=2.9.0",
3232
"tifffile>=2025.5.21",
33-
"natsort>=7.1.1",
33+
"natsort>=8.4.0",
3434
"ndtiff>=2.2.1",
35-
"zarr>=3.0.8",
35+
"zarr>=3.1.6",
3636
"rich",
3737
"tqdm",
3838
"pillow>=9.4.0",
3939
"blosc2",
4040
"xarray>=2024.1.1",
4141
"dask[array]",
42+
"zarrs>=0.2.3",
4243
]
4344
dynamic = ["version"]
4445

@@ -52,13 +53,18 @@ Source = "https://github.com/czbiohub-sf/iohub"
5253
tensorstore = [
5354
"tensorstore>=0.1.64",
5455
]
56+
57+
[project.entry-points."iohub.zarr-implementations"]
58+
zarr = "iohub.core.implementations.zarr_python:ZarrPythonImplementation"
59+
tensorstore = "iohub.core.implementations.tensorstore:TensorStoreImplementation"
60+
5561
[dependency-groups]
5662
test = [
5763
"iohub[tensorstore]",
5864
"ngff-zarr[validate]",
59-
"pytest>=5.0.0",
65+
"pytest>=9.0.2",
6066
"pytest-cov",
61-
"hypothesis>=6.61.0",
67+
"hypothesis>=6.151.0",
6268
"requests>=2.22.0",
6369
"wget>=3.2",
6470
"ome-zarr>=0.12.0",
@@ -67,7 +73,7 @@ acquire-zarr = [
6773
"acquire-zarr",
6874
]
6975
doc = [
70-
"zensical>=0.0.11",
76+
"zensical>=0.0.29",
7177
"mkdocstrings-python>=2.0.2",
7278
"mkdocs-click>=0.8",
7379
]
@@ -93,15 +99,58 @@ style = "pep440"
9399
bump = true
94100
fallback-version = "0.0.0"
95101

102+
[tool.pytest]
103+
minversion="9.0"
104+
strict = true
105+
testpaths = [ "tests" ]
106+
addopts = [
107+
"-ra",
108+
"--import-mode=importlib",
109+
]
110+
96111
[tool.ruff]
97112
line-length = 120
98-
99-
[tool.ruff.format]
100-
quote-style = "double"
101-
indent-style = "space"
102-
docstring-code-format = true
103-
docstring-code-line-length = "dynamic"
104-
105-
[tool.ruff.lint]
106-
select = ["E", "F", "W", "I"]
107-
ignore = ["E203", "E731"]
113+
src = [ "src" ]
114+
extend-include = [ "*.ipynb" ]
115+
format.quote-style = "double"
116+
format.indent-style = "space"
117+
format.docstring-code-format = true
118+
format.docstring-code-line-length = "dynamic"
119+
lint.select = [
120+
"B", # flake8-bugbear
121+
"BLE", # flake8-blind-except
122+
"C4", # flake8-comprehensions
123+
"D", # pydocstyle
124+
"E", # pycodestyle errors
125+
"F", # pyflakes
126+
"I", # isort
127+
"NPY", # NumPy-specific rules
128+
"PERF", # Perflint
129+
"PT", # pytest
130+
"PTH", # pathlib
131+
"RUF", # Ruff-specific rules
132+
"TID", # flake8-tidy-imports
133+
"UP", # pyupgrade
134+
"W", # pycodestyle warnings
135+
]
136+
lint.ignore = [
137+
"B008", # function calls in argument defaults are fine when result is immutable
138+
"D100", # Missing docstring in public module
139+
"D101", # Missing docstring in public class
140+
"D102", # Missing docstring in public method
141+
"D103", # Missing docstring in public function
142+
"D104", # Missing docstring in public package
143+
"D105", # __magic__ methods are often self-explanatory
144+
"D107", # Missing docstring in __init__
145+
"D203", # no blank line before class docstring (conflicts with D211)
146+
"D213", # docstrings start immediately after opening triple quote (conflicts with D212)
147+
"D400", # first line should end with period (doesn't work with single-line docstrings)
148+
"D401", # first line in imperative mood
149+
"E203", # slice whitespace (handled by formatter)
150+
"E501", # line too long (formatter handles code; long comments are acceptable)
151+
"E731", # lambda assignments are convenient
152+
]
153+
lint.per-file-ignores."*/__init__.py" = [ "F401" ]
154+
lint.per-file-ignores."docs/*" = [ "D", "I", "NPY002", "PTH", "PERF401", "BLE001" ]
155+
lint.per-file-ignores."tests/*" = [ "D" ]
156+
lint.pydocstyle.convention = "numpy"

src/iohub/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""
22
iohub
3+
34
=====
45
56
N-dimensional bioimaging data I/O with OME metadata in Python

0 commit comments

Comments
 (0)