ngff_zarr.upgrade_ome_zarr

Examples

Upgrade a 0.5 store to 0.6 in place, keeping all array chunks:

upgrade_ome_zarr("image.ome.zarr", version="0.6")

Write an upgraded copy to a new store:

upgrade_ome_zarr("image_v04.ome.zarr", "image_v05.ome.zarr", version="0.5")

Upgrade an OME-Zarr store from one specification version to another.

upgrade_ome_zarr changes the OME-Zarr specification version recorded in a store. It offers two modes:

In-place metadata-only rewrite. When no output is given (or output resolves to the same store as input) and the source and target share the same underlying Zarr format – for example 0.5 -> 0.6, both Zarr v3 – only the root group’s metadata (zarr.json) is rewritten. Every array chunk on disk is left byte-for-byte untouched. This is the fix for issue #219, where the previous “read, erase, re-write” approach destroyed the array data it was meant to preserve.

In-place upgrades that cross the Zarr v2<->v3 boundary in the upgrade direction (OME-Zarr 0.4->0.5 or 0.4->0.6) are also metadata-only: each array’s Zarr v3 zarr.json is given a v2 chunk-key encoding matching the source separator so the existing chunk binaries resolve unchanged (see

func:

_rewrite_v2_group_to_v3). The reverse, an in-place downgrade across the boundary (0.5/0.6->0.4), cannot preserve chunk keys and is rejected with a clear ValueError; pass an output store instead.

Write-to-new-store conversion. When an output store distinct from input is given, the source is read lazily and re-written to output at the requested version through the standard, tested write pipeline. Every supported transition (0.4<->0.5<->0.6) works in this mode. Array data streams from the source; the source store is never erased.

Module Contents

Functions

_normalize_target_version

Return the API version string ("0.4"/"0.5"/"0.6").

_zarr_format_for_version

OME-Zarr < 0.5 lives in Zarr v2; 0.5 and later live in Zarr v3.

_store_fspath

Best-effort local filesystem path for store, else None.

_stores_are_same

Whether output designates the same store as input.

_resolve_write_store

Wrap a remote URL output in an FsspecStore when needed.

_read_root_attrs

Read the root-group attributes of store without loading arrays.

_read_source_version

Detect the on-disk OME-Zarr version string of store.

_validate_target_version

Reject a target version that upgrade_ome_zarr cannot produce.

_reject_plate_or_container

Reject an HCS plate root or bioformats2raw container root.

_upgrade_in_place

Rewrite only the root-group metadata of store to target_version.

_parent_group_paths

Return every intermediate group path implied by array_paths.

_delete_v2_sidecars

Delete the Zarr v2 metadata sidecars from store, sparing chunks.

_rewrite_v2_group_to_v3

Rewrite a Zarr v2 (OME-Zarr 0.4) group to Zarr v3 in place, keeping chunks.

upgrade_ome_zarr

Upgrade an OME-Zarr store to a different specification version.

API

ngff_zarr.upgrade_ome_zarr._normalize_target_version(
version: str | ngff_zarr._supported_versions.NgffVersion,
) str

Return the API version string ("0.4"/"0.5"/"0.6").

Both the API alias "0.6" and the on-disk development string "0.6.dev4" normalize to "0.6" so the value can be handed to Metadata.to_version (which only knows the three released versions).

ngff_zarr.upgrade_ome_zarr._zarr_format_for_version(version: str) int

OME-Zarr < 0.5 lives in Zarr v2; 0.5 and later live in Zarr v3.

ngff_zarr.upgrade_ome_zarr._store_fspath(store: ngff_zarr._zarr_types.StoreLike) pathlib.Path | None

Best-effort local filesystem path for store, else None.

Used only to detect input/output aliasing. Remote and in-memory stores return None and are therefore treated as distinct unless they are the very same object.

ngff_zarr.upgrade_ome_zarr._stores_are_same(
input: ngff_zarr._zarr_types.StoreLike,
output: ngff_zarr._zarr_types.StoreLike | None,
) bool

Whether output designates the same store as input.

output is None always means “same store” (an in-place request). Two string/URL forms are compared directly; local paths are compared by their resolved filesystem path so foo and ./foo/ match.

ngff_zarr.upgrade_ome_zarr._resolve_write_store(
store: ngff_zarr._zarr_types.StoreLike,
storage_options: dict | None,
) ngff_zarr._zarr_types.StoreLike

Wrap a remote URL output in an FsspecStore when needed.

to_ome_zarr has no storage_options parameter, so a remote output URL combined with storage_options is resolved to a store object here, exactly as from_ome_zarr resolves remote inputs. Local and in-memory stores pass through unchanged.

ngff_zarr.upgrade_ome_zarr._read_root_attrs(
store: ngff_zarr._zarr_types.StoreLike,
storage_options: dict | None,
) dict

Read the root-group attributes of store without loading arrays.

Mirrors the auto-detection (and Zarr v2 fallback) that from_ome_zarr performs internally: a Zarr v2 (OME-Zarr 0.4) store opened without an explicit format on zarr-python 3 yields an empty root, so it is retried as Zarr v2. Used for both source-version detection and HCS/container rejection.

ngff_zarr.upgrade_ome_zarr._read_source_version(
store: ngff_zarr._zarr_types.StoreLike,
storage_options: dict | None,
) str

Detect the on-disk OME-Zarr version string of store.

from_ome_zarr always normalizes the metadata it returns to v0.6, so the original version cannot be recovered from the returned object. It is read here straight from the root attributes.

ngff_zarr.upgrade_ome_zarr._validate_target_version(
target_version: str,
requested: str | ngff_zarr._supported_versions.NgffVersion,
) None

Reject a target version that upgrade_ome_zarr cannot produce.

NgffVersion also admits the pre-0.4 drafts (0.1–0.3) that live in SUPPORTED_VERSIONS for read compatibility, but the metadata to_version chains only convert among 0.4/0.5/0.6. Fail early with an actionable message rather than deep in a conversion.

ngff_zarr.upgrade_ome_zarr._reject_plate_or_container(root_attrs: dict) None

Reject an HCS plate root or bioformats2raw container root.

upgrade_ome_zarr upgrades a single image. Whole-plate / whole-container upgrades are out of scope for this effort: each contained image is upgraded by pointing at its own path. This reuses the same detection predicates from_ome_zarr relies on so the two agree on what a plate/container is.

ngff_zarr.upgrade_ome_zarr._upgrade_in_place(
store: ngff_zarr._zarr_types.StoreLike,
multiscales: ngff_zarr.multiscales.NgffMultiscales,
target_version: str,
target_zarr_format: int,
) None

Rewrite only the root-group metadata of store to target_version.

Opens the existing root group for read/write (mode="a") so the array chunks are never rewritten – the crux of the issue #219 fix. Calling to_ome_zarr(..., overwrite=True) on the source instead would erase those arrays.

ngff_zarr.upgrade_ome_zarr._parent_group_paths(array_paths: list[str]) list[str]

Return every intermediate group path implied by array_paths.

For a dataset laid out at scale0/image the intermediate group scale0 must gain a Zarr v3 zarr.json (and keep its .zattrs such as _ARRAY_DIMENSIONS). Flat arrays ("0") imply no intermediate group. Returned sorted so parents precede children.

ngff_zarr.upgrade_ome_zarr._delete_v2_sidecars(store: ngff_zarr._zarr_types.StoreLike) None

Delete the Zarr v2 metadata sidecars from store, sparing chunks.

Removes every .zgroup/.zattrs/.zarray/.zmetadata key so the store is cleanly Zarr v3. Chunk data files never begin with a dot, so they are never matched. Filesystem-backed stores are pruned by unlink; other stores (e.g. MemoryStore) go through the async store API, the same pattern used by rfc9_zip.

ngff_zarr.upgrade_ome_zarr._rewrite_v2_group_to_v3(
store: ngff_zarr._zarr_types.StoreLike,
new_metadata,
target_version: str,
) None

Rewrite a Zarr v2 (OME-Zarr 0.4) group to Zarr v3 in place, keeping chunks.

Each array’s chunk binaries are left exactly where they are: the new Zarr v3 zarr.json is given a v2 chunk_key_encoding whose separator equals the source array’s dimension_separator, so the pre-existing chunk keys (e.g. 0/0/0/0 or 0.0.0.0) resolve unchanged. Only metadata is written or removed; no chunk file is ever moved, rewritten, or deleted. This is the cross-format analogue of the in-place issue #219 fix.

An array whose Zarr v2 encoding cannot be faithfully represented in Zarr v3 (Fortran memory order, filters, or a compressor with no v3 codec equivalent) raises ValueError naming the array, rather than silently corrupting data; the caller is directed to write-to-new-store instead.

ngff_zarr.upgrade_ome_zarr.upgrade_ome_zarr(
input: ngff_zarr._zarr_types.StoreLike,
output: ngff_zarr._zarr_types.StoreLike | None = None,
*,
version: str | ngff_zarr._supported_versions.NgffVersion = '0.6',
validate: bool = False,
storage_options: dict | None = None,
overwrite: bool = True,
) None

Upgrade an OME-Zarr store to a different specification version.

Parameters:
  • input (StoreLike) – Source store or path to read.

  • output (StoreLike, optional) – Destination store or path. If None (or the same store as input), the upgrade is performed in place: only metadata is rewritten and every array chunk on disk is left byte-for-byte untouched (this includes the cross-format 0.4->0.5/0.6 case, which rewrites the array and group metadata to Zarr v3 while preserving chunks). An in-place downgrade across the Zarr v2<->v3 boundary (0.5/0.6->0.4) cannot preserve chunk keys and raises ValueError. If a distinct store, an upgraded copy is written there via the standard write pipeline.

  • version (str or NgffVersion, optional) – Target OME-Zarr specification version. Accepts a string such as "0.6" or an NgffVersion member.

  • validate (bool, optional) – If True, validate the source metadata against the NGFF schema while reading.

  • storage_options (dict, optional) – Storage options for remote input/output URLs (zarr-python 3+).

  • overwrite (bool, optional) – For the write-to-new-store mode, whether to overwrite any pre-existing data at output. Ignored for in-place upgrades, which never overwrite array data.

Returns:

None. The upgraded metadata is written to output (or, for an in-place upgrade, back to input).