ome_zarr_pyramid
Read, write and downscale OME-Zarr (NGFF) image pyramids through a single, lazy,
dask-backed Pyramid object, memory-bound by design, so it scales from a small tile
to large-scale volumes with the same code.
- One object, all levels. A
Pyramidwraps every resolution level as a lazydaskarray plus the full NGFF metadata (axes, scales, units, omero, translations). - Lazy & memory-bound. Nothing is computed until you write or
.compute(). The region writer streams tile-by-tile; the whole volume is never held in RAM. - NGFF-native. Reads/writes multiscales v0.4 and v0.5, TensorStore or threaded backends, local or S3.
- Deferred, progressive downscaling.
downscale()records a plan and builds nothing; the writer streams the base to disk once and derives coarser levels from the stored base. An expensive base (e.g. a segmentation) is computed a single time, not once per level. - Elementwise algebra.
Pyramidobjects support arithmetic, comparison and bitwise operators across every level at once (img > 128,a * b,~mask).
Image processing (filters, segmentation, features, morphology, clustering, …) lives in the sibling package
ome_zarr_pro, which builds on this one.
Install
pip install ome_zarr_pyramid # core: zarr, dask, tensorstore
pip install "ome_zarr_pyramid[s3]" # + s3fs, for writing to https:// (S3) stores
Quickstart
from ome_zarr_pyramid import Pyramid, IO
pyr = IO().read_pyramid("image.ome.zarr") # -> Pyramid (lazy, nothing loaded)
print(pyr.axes, pyr.nlayers) # 'tczyx', 5
print(pyr.base_array.shape, pyr.base_array.dtype) # full-resolution level 0
IO().write_pyramid(pyr, "copy.ome.zarr", overwrite=True)
Everything is a Pyramid
Every operation returns a new Pyramid. Selecting (isel, sublevels), the
elementwise operators (+ - * / > == & ~ …), downscale and rechunk all produce a
fresh, lazy Pyramid, with all resolution levels and metadata preserved, so they
compose and chain naturally. Nothing is materialised until you .compute() an array or write
the pyramid. Throughout this README, pyr and any variable ending in _pyr are
Pyramid objects.
mask_pyr = (IO().read_pyramid("image.ome.zarr").isel(c=0) > 128) # Pyramid -> Pyramid -> Pyramid
IO().write_pyramid(mask_pyr.downscale(n_layers=4), "mask.ome.zarr", overwrite=True)
Inspect the pyramid & its metadata
pyr = IO().read_pyramid("image.ome.zarr")
pyr.axes # 'tczyx' (axis order)
pyr.meta.resolution_paths # ['0', '1', '2', '3']
pyr.meta.unit_list # ['second', None, 'micrometer', 'micrometer', 'micrometer']
for p in pyr.meta.resolution_paths:
arr = pyr.dask_arrays[p] # lazy dask array for this level
scale = pyr.meta.get_scale(p) # physical pixel size per axis
print(p, arr.shape, arr.chunksize, scale)
import numpy as np
level0 = np.asarray(pyr.base_array.compute()) # materialise level 0 to numpy
Select regions, channels and levels
Each of these returns a new Pyramid (a sub-pyramid), not a bare array:
channel0_pyr = pyr.isel(c=0) # -> Pyramid: channel 0 (drops the 'c' axis)
zrange_pyr = pyr.isel(z=slice(10, 40)) # -> Pyramid: a z-range (scale/translation updated)
frame_pyr = pyr.isel(t=0, c=1) # -> Pyramid: one timepoint, one channel
top3_pyr = pyr.sublevels(0, 2) # -> Pyramid: resolution levels 0..2 (finest three)
isel is xarray-style: an int selects one position and drops that axis, a
slice keeps a strided sub-range, applied across every resolution level, with the
coordinate metadata (scale, translation, dropped axes, omero channels) updated to match.
Elementwise algebra (all levels, lazy)
Pyramid behaves like an array under operators, but each operation returns another
Pyramid (every level transformed lazily, metadata preserved), so results chain:
mask_pyr = pyr > 128 # -> Pyramid: boolean mask (thresholding)
scaled_pyr = pyr * 2 + 10 # -> Pyramid: arithmetic with scalars
diff_pyr = a_pyr - b_pyr # -> Pyramid: combine two aligned pyramids
band_pyr = (pyr > 50) & (pyr < 200) # -> Pyramid: bitwise combine of two mask pyramids
inv_pyr = ~mask_pyr # -> Pyramid: unary ops (~, -, abs())
IO().write_pyramid(mask_pyr, "mask.ome.zarr", overwrite=True)
Supported: + - * / // % **, < <= > >= == !=, & | ^, and unary - + abs() ~.
Operands may be scalars or other Pyramid objects; the result is always a Pyramid.
Downscale and write (memory-bound, base computed once)
pyr = IO().read_pyramid("image.ome.zarr")
# downscale() is DEFERRED and returns a Pyramid: it records a plan, builds nothing.
full_pyr = pyr.downscale(n_layers=4) # -> Pyramid (exactly 4 levels)
full_pyr = pyr.downscale(min_dimension_size=128) # -> Pyramid (until largest axis < 128)
# The write streams level 0 once, then derives coarser levels from the on-disk base.
IO().write_pyramid(full_pyr, "out.ome.zarr", overwrite=True)
This matters when level 0 is an expensive lazy graph: the base is computed a single time (during its own write) instead of being recomputed for every pyramid level.
Control storage chunking (independent of processing)
Storage chunk shape is decoupled from whatever chunking an upstream operation imposed. Pass a chunk shape or a target chunk size in MB (isotropic: square in 2-D, cube in 3-D, dtype-aware):
# target MB per chunk (scalar, or per-level sequence / dict)
IO().write_pyramid(full_pyr, "out.ome.zarr", overwrite=True, chunk_size_mb=1.0)
IO().write_pyramid(full_pyr, "out.ome.zarr", overwrite=True, chunk_size_mb=(4, 1, 0.5))
# explicit chunk shape (one tuple for all levels, or per-level dict)
IO().write_pyramid(full_pyr, "out.ome.zarr", overwrite=True, chunk_shape=(1, 1, 256, 256))
IO().write_pyramid(full_pyr, "out.ome.zarr", overwrite=True,
chunk_shape={0: (1, 1, 256, 256), 1: (1, 1, 128, 128)})
# or rechunk the Pyramid itself -> returns a new Pyramid
rechunked_pyr = pyr.rechunk(chunk_size_mb=2.0) # -> Pyramid
When neither is given, a pyramid read from disk is written back with its original on-disk chunking.
Build a pyramid from your own arrays
import dask.array as da
from ome_zarr_pyramid import Pyramid, IO
lvl0 = da.zeros((2, 512, 512), chunks=(1, 256, 256), dtype="uint16") # (c, y, x)
image_pyr = Pyramid().from_arrays( # -> Pyramid
[lvl0],
axis_order="cyx",
unit_list=[None, "micrometer", "micrometer"],
scales=[[1, 0.325, 0.325]], # physical pixel size at level 0
version="0.4", # NGFF version ('0.4' or '0.5')
name="my_image",
)
IO().write_pyramid(image_pyr.downscale(n_layers=3), "my_image.ome.zarr", overwrite=True)
Write backends & options
IO().write_pyramid(pyr, "out.ome.zarr", overwrite=True,
backend="sync", # 'sync' (threaded) or 'tensorstore'
max_workers=4)
IO().write_pyramid(pyr, "https://s3.example.com/bucket/out.ome.zarr") # needs [s3]
License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ome_zarr_pyramid-0.0.5.tar.gz.
File metadata
- Download URL: ome_zarr_pyramid-0.0.5.tar.gz
- Upload date:
- Size: 62.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80c20b9df9ef22df7f5db8df5dd6990503fa7921caab2f7bc39a96825aab3d08
|
|
| MD5 |
9db84e6b5600c6073bc51bd5c0b3fb88
|
|
| BLAKE2b-256 |
e3fb8016135ee771f309ca8cd93ed39eeefaf06a577602a7f7b144ca29326aae
|
Provenance
The following attestation bundles were made for ome_zarr_pyramid-0.0.5.tar.gz:
Publisher:
publish.yml on Euro-BioImaging/ome_zarr_pyramid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ome_zarr_pyramid-0.0.5.tar.gz -
Subject digest:
80c20b9df9ef22df7f5db8df5dd6990503fa7921caab2f7bc39a96825aab3d08 - Sigstore transparency entry: 2224323564
- Sigstore integration time:
-
Permalink:
Euro-BioImaging/ome_zarr_pyramid@3150eb27bcadd064262e32680c6851c5484a99c1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Euro-BioImaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3150eb27bcadd064262e32680c6851c5484a99c1 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file ome_zarr_pyramid-0.0.5-py3-none-any.whl.
File metadata
- Download URL: ome_zarr_pyramid-0.0.5-py3-none-any.whl
- Upload date:
- Size: 64.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eca0ccc924a6f1431b306bb3853b246bf56bbbf7258cc9c5b73696128748bc98
|
|
| MD5 |
f4150383635a19a7ac8d941dc3a93143
|
|
| BLAKE2b-256 |
e4246dc48732545ffeb74322a3dbd9d7d4b2a8842ce4996b3a8eadf85595f90f
|
Provenance
The following attestation bundles were made for ome_zarr_pyramid-0.0.5-py3-none-any.whl:
Publisher:
publish.yml on Euro-BioImaging/ome_zarr_pyramid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ome_zarr_pyramid-0.0.5-py3-none-any.whl -
Subject digest:
eca0ccc924a6f1431b306bb3853b246bf56bbbf7258cc9c5b73696128748bc98 - Sigstore transparency entry: 2224324254
- Sigstore integration time:
-
Permalink:
Euro-BioImaging/ome_zarr_pyramid@3150eb27bcadd064262e32680c6851c5484a99c1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Euro-BioImaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3150eb27bcadd064262e32680c6851c5484a99c1 -
Trigger Event:
workflow_dispatch
-
Statement type: