ngff_zarr._zarrista_utils¶
Compatibility layer between ngff-zarr and zarrista (Rust/zarrs-backed Zarr).
zarrista is v3-focused and its API surface differs from zarr-python in ways that matter for OME-Zarr writing. The empirically verified constraints this module works around (see the Phase 01 capability spike):
No group-create API for either zarr format: group metadata (
zarr.jsonfor format 3,.zgroup/.zattrsfor format 2) is hand-written JSON.ArrayBuilderemits only zarr format 3 metadata: format 2 arrays are created viaArray.from_metadatawith a.zarray-style dict, which writes real v2 stores that zarr-python reads back correctly.Consolidated
.zmetadatacannot be written by zarrista for format 2: it is hand-written by aggregating the per-node JSON documents.Every write requires C-contiguous input, and arrays expose
shapeas alistanddtypeas zarrista’s ownDataType: dask interop goes through a thin adapter (:class:_ZarristaArrayAdapter).Supported stores are
FilesystemStore/MemoryStore/read-onlyZipStoreonly: :func:normalize_storerestricts targets to local directory paths.
Sharding vocabulary differs from zarr-python: the builder chunk grid is the
shard (outer chunk) grid and subchunk_shape is the read chunk, so
ngff-zarr’s chunks_per_shard multiplies chunks into the builder grid
shape while chunks itself becomes the subchunk shape.
zarrista is imported lazily inside each function to keep module import cheap.
Module Contents¶
Classes¶
Minimal numpy-protocol surface over a zarrista |
|
Handle for an array node within a local directory store. |
|
Read-only handle for a group node within a local directory store. |
Functions¶
Return value as a C-contiguous, native-byte-order ndarray. |
|
|
|
Normalize any accepted compressor form to a |
|
Resolve constructor-defaulted blosc typesize/shuffle from the dtype. |
|
Map a compressor to the numcodecs config dict stored in |
|
Map a compressor to a zarrista bytes-to-bytes codec (zarr format 3). |
|
Whether store is a local directory path zarrista can target directly. |
|
Root path of a zarrista |
|
Resolve store to the local directory path backing it, or |
|
Normalize store to a local directory path zarrista can target. |
|
Run operation, retrying the transient Windows sharing violation. |
|
Read a zarr metadata document, tolerating a concurrent replace. |
|
Attributes of the group at group_path within store. |
|
Whether the store at store carries consolidated metadata. |
|
Attributes of the group already at path, or |
|
Serialize doc to path atomically (temp file + rename). |
|
Create group metadata at path and return the opened zarrista group. |
|
Create the group at group_path within the store at store. |
|
Rewrite a zarrista-written array metadata document for engine parity. |
|
Create a zarr array under the store at path and return it. |
|
Write dask array darr into an existing zarrista array. |
|
Open the existing array at component within the store at path. |
|
Whether obj is a raw |
|
Wrap zarrista |
|
Open the array at component within path as a lazy dask array. |
|
Store handle for reading the zip archive ( |
|
Open the array at component within zip-archive store lazily. |
|
Whether store is a key-to-bytes mapping for the pure-Python reader. |
|
Open the array at component within store as a lazy dask array. |
|
|
|
User attributes for the node at dirpath ( |
|
Open the node at node_path within the local directory store store. |
|
A handle on |
|
Open the array at |
|
Write consolidated metadata for the store at path. |
Data¶
API¶
- ngff_zarr._zarrista_utils.__all__¶
[‘LocalZarrArray’, ‘LocalZarrGroup’, ‘OME_ROOT_KEYS’, ‘consolidate_metadata’, ‘create_zarrista_array…
- ngff_zarr._zarrista_utils._BLOSC_SHUFFLE_TO_INT¶
None
- ngff_zarr._zarrista_utils._BLOSC_SHUFFLE_TO_STR¶
None
- ngff_zarr._zarrista_utils.OME_ROOT_KEYS¶
‘frozenset(…)’
- ngff_zarr._zarrista_utils._native_contiguous(value) numpy.ndarray¶
Return value as a C-contiguous, native-byte-order ndarray.
zarrista ingests write input through DLPack, which rejects both non-contiguous buffers and non-native byte order (e.g. big-endian
>u2input); the target array’s stored byte order comes from its metadata, so byteswapping the in-memory values is safe.
- ngff_zarr._zarrista_utils._normalize_selection(
- shape,
- selection,
selectionas one unit-step slice per axis, the axes an integer index drops, and the residual striding to apply to the fetched block.An ellipsis and missing trailing axes expand to full slices. An integer becomes the length-1 slice zarrista reads it as, and its axis is reported so numpy semantics, where the axis is dropped, can be restored. A stepped (or negative-step) slice becomes the ascending unit-step span covering the selected indices, and the residual (
Nonewhen every step is 1) restores the requested stride and direction on the fetched block: zarrista serves unit steps only, and the covering span is what its chunks decode anyway.
- class ngff_zarr._zarrista_utils._ZarristaArrayAdapter(
- arr,
- store_path: pathlib.Path | None = None,
- node_path: str | None = None,
Minimal numpy-protocol surface over a zarrista
Arrayfor dask.zarrista exposes
shapeas alist,dtypeas its ownDataType, has no.chunksattribute, and rejects non-C-contiguous or non-native-byte-order write input. dask needs a tupleshape, a numpydtype, ndarray__getitem__results, and a tolerant__setitem__(see :func:_native_contiguous).store_pathandnode_pathrecord where an array of a local store lives, so the writer can tell that an image still reads from the store it is about to replace. They areNonefor arrays without a local directory.Initialization
- _fetch(selection) numpy.ndarray¶
Materialize selection; the async remote adapter overrides this.
- __getitem__(selection)¶
- __setitem__(selection, value)¶
- ngff_zarr._zarrista_utils._canonical_compressor(compressor) tuple[str, dict] | None¶
Normalize any accepted compressor form to a
(name, params)pair.Accepts a numcodecs codec object, a zarr v3 codec object, a bare codec name string, a numcodecs-style config dict (
{"id": ...}), or a zarr v3 codec dict ({"name": ..., "configuration": ...}). ReturnsNoneforNone.
- ngff_zarr._zarrista_utils._evolve_blosc_params(compressor, params: dict, itemsize: int) dict¶
Resolve constructor-defaulted blosc typesize/shuffle from the dtype.
zarr-python’s
BloscCodecserializes unset attrs astypesize=1/shuffle="bitshuffle", records which were defaulted in_tunable_attrs, and evolves those from the dtype at write time. Mirror that so the stored metadata matches what zarr-python would write; explicitly chosen values are kept.
- ngff_zarr._zarrista_utils._compressor_to_v2_config(compressor, dtype: numpy.dtype) dict | None¶
Map a compressor to the numcodecs config dict stored in
.zarray.
- ngff_zarr._zarrista_utils._compressor_to_zarrista_codec(compressor, dtype: numpy.dtype)¶
Map a compressor to a zarrista bytes-to-bytes codec (zarr format 3).
- ngff_zarr._zarrista_utils._is_local_path(store) bool¶
Whether store is a local directory path zarrista can target directly.
True for
str/pathlib.Path/os.PathLiketargets that are neither remote URL strings nor.zip/.ozxarchive paths (zarrista can only read zip archives);MutableMappings and store objects are excluded.
- ngff_zarr._zarrista_utils._FILESYSTEM_STORE_REPR¶
‘compile(…)’
- ngff_zarr._zarrista_utils._zarrista_filesystem_store_path(store) pathlib.Path | None¶
Root path of a zarrista
FilesystemStore, orNoneotherwise.zarrista’s stores are pyo3 classes with no Python-visible attributes; the only channel for the root path is the round-trippable
repr(FilesystemStore(path='...'), quoted per Python’s stringrepr), parsed withast.literal_eval. Tests pin the format so upstream drift surfaces as a failure rather than a silently unresolvable store.
- ngff_zarr._zarrista_utils.resolve_store_path(store) pathlib.Path | None¶
Resolve store to the local directory path backing it, or
None.Accepts plain
str/pathlib.Path/os.PathLiketargets (e.g. the defaultconfig.cache_store) and zarristaFilesystemStorehandles. ReturnsNonefor anything with no local directory (in-memory mappings, remote URL strings, store objects, …).
- ngff_zarr._zarrista_utils.normalize_store(store) pathlib.Path¶
Normalize store to a local directory path zarrista can target.
Accepts
str/pathlib.Path/os.PathLikedirectory paths and zarristaFilesystemStorehandles. RaisesTypeErrorfor anything else (in-memory mappings, remote URL strings, zarr store objects, …) andValueErrorfor zip targets, which zarrista can only read.
- ngff_zarr._zarrista_utils._retry_on_windows_sharing_violation(operation, cleanup=None)¶
Run operation, retrying the transient Windows sharing violation.
os.replaceswaps group documents in place. Windows denies access to the destination for the instant the swap takes, so a concurrent reader or writer of that path seesPermissionErrorwhere POSIX sees the old or new file. Retry briefly, then give up and let the error surface.
- ngff_zarr._zarrista_utils._read_doc_text(doc: pathlib.Path) str¶
Read a zarr metadata document, tolerating a concurrent replace.
- ngff_zarr._zarrista_utils.read_group_attributes(
- store,
- group_path=None,
- *,
- zarr_format: int,
Attributes of the group at group_path within store.
Returns
Nonewhen no group node exists there and{}for a group with no attributes, so callers can distinguish “absent” from “empty” (the compat-layer equivalent of a zarr-python membership test plusattrs.asdict()). RaisesValueErrorwhen the path holds an array node, mirroring zarr-python’s refusal to open a group over an array.
- ngff_zarr._zarrista_utils.has_consolidated_metadata(store, zarr_format: int) bool¶
Whether the store at store carries consolidated metadata.
Checks the root
zarr.jsonfor an inlineconsolidated_metadatablock (zarr format 3) or for a.zmetadatasidecar (format 2), so in-place metadata rewrites can refresh consolidation exactly when zarr-python would.
- ngff_zarr._zarrista_utils._existing_group_attributes(path: pathlib.Path, zarr_format: int) dict¶
Attributes of the group already at path, or
{}when absent.
- ngff_zarr._zarrista_utils._write_group_doc(path: pathlib.Path, doc: dict) None¶
Serialize doc to path atomically (temp file + rename).
Group documents on shared ancestors (e.g. an HCS row group) can be read and rewritten by concurrent well/field writers; the atomic replace keeps readers from ever observing a truncated document.
On Windows
os.replaceraisesPermissionErrorwhen another writer or reader momentarily holds the destination open, so the replace is retried briefly. POSIX renames onto an open file without complaint.
- ngff_zarr._zarrista_utils.create_zarrista_group( )¶
Create group metadata at path and return the opened zarrista group.
zarrista has no group-create API, so the metadata documents are written directly:
.zgroup+.zattrsfor zarr format 2,zarr.jsonfor format 3. Withoverwriteany existing content below path is removed first, matchingzarr.open_group(mode="w"); otherwise an existing group’s attributes are preserved and updated with attributes, matchingmode="a"followed by per-key attribute assignment. The returnedzarrista.Groupreads the documents back, hiding the hand-written JSON from callers.
- ngff_zarr._zarrista_utils.create_zarrista_subgroup( )¶
Create the group at group_path within the store at store.
Missing ancestor groups along group_path are created with empty attributes, matching zarr-python’s implicit-parent creation; an existing leaf group keeps its other attributes (see :func:
create_zarrista_group). Returns the zarrista group for the leaf.
- ngff_zarr._zarrista_utils._normalize_array_metadata_doc(
- doc_path: pathlib.Path,
- zarr_format: int,
- itemsize: int,
Rewrite a zarrista-written array metadata document for engine parity.
zarrs’ serialization differs from zarr-python’s in ways that are spec-legal but break byte-level store equivalence: it stamps
node_typeinto v2.zarraydocs and a_zarrsprovenance attribute into v3 docs, omits the always-materializedstorage_transformers/attributesfields, and writes an explicitendianfor thebytescodec even for single-byte dtypes (where zarr-python omits the configuration). Only the document is rewritten; the already-open zarrista array keeps its in-memory metadata.
- ngff_zarr._zarrista_utils.create_zarrista_array(
- path,
- name: str,
- shape: tuple[int, ...],
- dtype,
- chunks: int | tuple[int, ...],
- zarr_format: int,
- compressor=None,
- chunks_per_shard: int | tuple[int, ...] | None = None,
- dimension_names: tuple[str, ...] | None = None,
- dimension_separator: str = '/',
- compressors=None,
- shards: tuple[int, ...] | None = None,
- fill_value=None,
- attributes: dict | None = None,
- chunk_key_encoding: dict | None = None,
Create a zarr array under the store at path and return it.
name is the array’s path within the store (e.g.
"0"). compressor accepts the same forms as ngff-zarr’s writer: a numcodecs codec, a zarr v3 codec, or their config dicts;Nonemeans no compression. compressors (format 3 only) is an ordered sequence of bytes-to-bytes codecs written after thebytescodec; it overrides compressor, and an empty sequence means no compression. Sharding (format 3 only) is requested either viachunks_per_shard— an int or per-dimension tuple of chunks per shard, matchingto_ngff_zarr— or viashards, the explicit outer shard shape whose subchunks are chunks. fill_valueNonemeans the dtype’s zero, matching zarr-python. attributes are the array’s user attributes. chunk_key_encoding (format 3 only) is the zarr v3 metadata form (e.g.{"name": "v2", "configuration": {"separator": "/"}}), used by in-place v2->v3 upgrades to keep existing chunk keys resolvable. The metadata is stored immediately; the returnedzarrista.Arrayis ready for chunk writes.
- ngff_zarr._zarrista_utils.write_dask_array(darr, zarrista_array, region=None) None¶
Write dask array darr into an existing zarrista array.
Writes are chunk-aligned: darr is rechunked to the target’s write granularity (the shard shape for sharded arrays) so concurrent block writes never touch the same stored chunk, then streamed with
dask.array.store. A region (tuple of slices) selects the target subset and should be aligned to the same granularity. Empty arrays (a zero-length dimension) are a no-op.
- ngff_zarr._zarrista_utils.open_zarrista_array(path, component: str | None = None)¶
Open the existing array at component within the store at path.
Returns the raw
zarrista.Array, ready for region__setitem__writes into an already-created array (either zarr format). Write input must be C-contiguous; :class:_ZarristaArrayAdapteror- Func:
write_dask_arrayhandle that for adapter-mediated writes.
- ngff_zarr._zarrista_utils.zarrista_array_to_dask(
- arr,
- store_path: pathlib.Path | None = None,
- node_path: str | None = None,
Wrap zarrista
Arrayarr as a lazy dask array.Chunks follow the stored chunk grid, using the subchunk (inner chunk) shape for sharded arrays so reads stay at the efficient granularity. store_path and node_path name the array’s place in a local store (see :class:
_ZarristaArrayAdapter).
- ngff_zarr._zarrista_utils.open_zarrista_lazy(path, component: str | None = None) dask.array.Array¶
Open the array at component within path as a lazy dask array.
- ngff_zarr._zarrista_utils.open_ozx_store(path)¶
Store handle for reading the zip archive (
.ozx/.zip) at path.A :class:
~.rfc9_zip.ZipReadStore: metadata and group navigation go through the pure-Python mapping reader while pixel data reads through zarrista’s native zip store (see :func:open_zip_lazy).
- ngff_zarr._zarrista_utils.open_zip_lazy(
- store: ngff_zarr.rfc9_zip.ZipReadStore,
- component: str | None = None,
Open the array at component within zip-archive store lazily.
Routes through zarrista’s read-only zip store rather than the mapping reader because
.ozxarchives hold sharded zarr v3 arrays by default, which only zarrista can decode. The node path combines the store’s prefix (HCS well/field views) with component.
- ngff_zarr._zarrista_utils._is_bytes_mapping(store) bool¶
Whether store is a key-to-bytes mapping for the pure-Python reader.
str/Pathare excluded even though paths are iterable: only real mapping objects (plain dicts, zip-archive views, tifffile’s aszarr store) go through :mod:._v2_store_reader.
- ngff_zarr._zarrista_utils.open_lazy_array(store, component: str | None = None) dask.array.Array¶
Open the array at component within store as a lazy dask array.
The single read-dispatch point: zip-archive views read pixels through zarrista’s zip store, remote store handles through zarrista’s async API over obstore, other bytes mappings go through the pure-Python store reader (either zarr format), and local paths through zarrista. Any other store object raises
TypeError.
- ngff_zarr._zarrista_utils._load_local_doc(doc_path: pathlib.Path) dict¶
- ngff_zarr._zarrista_utils._local_node_document(
- dirpath: pathlib.Path,
- zarr_format: int,
(node_type, metadata document)for the node at dirpath.Returns
Nonewhen no node of zarr_format exists there. For format 2 an array wins when both.zarrayand.zgroupare present, matching zarr-python.
- ngff_zarr._zarrista_utils._local_node_attrs(
- dirpath: pathlib.Path,
- doc: dict,
- zarr_format: int,
User attributes for the node at dirpath (
.zattrsor inline).
- class ngff_zarr._zarrista_utils.LocalZarrArray(store_root: pathlib.Path, path: str, zarr_format: int, doc: dict)¶
Handle for an array node within a local directory store.
Exposes the node’s
shape,dtype,chunksandattrs, numpy style[]reads and writes through zarrista, and :meth:to_daskfor lazy pixel access. A write lands on the stored chunks it covers, so a producer filling a store created withmetadata_only=Trueneeds no lock while its regions follow the chunk grid.Initialization
- property dtype: numpy.dtype¶
- __getitem__(selection) numpy.ndarray¶
- to_dask() dask.array.Array¶
- class ngff_zarr._zarrista_utils.LocalZarrGroup(store_root: pathlib.Path, path: str, zarr_format: int, doc: dict)¶
Read-only handle for a group node within a local directory store.
Provides the slice of the zarr-python
Groupsurface the read path uses –attrs(a dict withasdict()),__contains__/__getitem__path navigation, andkeys()– backed by direct metadata-document reads (.zgroup/.zattrsfor zarr format 2,zarr.jsonfor format 3). Child arrays open their pixel data lazily through zarrista.Initialization
- __getitem__(name)¶
- ngff_zarr._zarrista_utils.open_local_node(store, node_path=None, *, zarr_format: int)¶
Open the node at node_path within the local directory store store.
The compat-layer read equivalent of
zarr.open: metadata documents are read directly from the filesystem, no zarr-python involved. Returns a- Class:
LocalZarrGroupor :class:LocalZarrArray, orNonewhen no node of zarr_format exists at that path.
- ngff_zarr._zarrista_utils._remote_handle(store, storage_options: dict | None)¶
A handle on
store’s remote backend, orNonewhen it has none.The reader’s own rule (
from_ome_zarr): a URL string, or a handle already built around one. A zarr-pythonFsspecStorewrapping a URL is neither – itsstr()is a repr rather than the URL obstore would be given – and the reader does not route one here either, so it keeps the local path it has today.
- ngff_zarr._zarrista_utils.open_array(store, path: str | None = None, storage_options: dict | None = None)¶
Open the array at
pathwithinstore.The handle reads and writes regions through zarrista and needs no other Zarr library:
to_ome_zarr(..., metadata_only=True)creates the arrays of a store, and this opens one of them for a producer to fill. The node is looked up as zarr format 3 first, then format 2.A URL (http(s), S3, GCS, Azure) is opened through the same async engine
from_ome_zarrreads it with, and comes back read-only: writing a region needs a local directory store.storage_optionsis passed to that engine, fsspec-style names included.
- ngff_zarr._zarrista_utils.consolidate_metadata(path, zarr_format: int) None¶
Write consolidated metadata for the store at path.
zarrista cannot write zarr format 2 consolidated metadata, so
.zmetadatais hand-written by aggregating the per-node JSON documents (what OME-Zarr 0.4 stores carry). Format 3 consolidation is likewise hand-inlined into the rootzarr.json: routing it through zarrista’s consolidation API would re-serialize the child documents with zarrs conventions (e.g. the bare-string shorthand for configuration-less codecs) that zarr-python’s reader rejects, so the raw documents are embedded verbatim instead, matchingzarr.consolidate_metadata.