Skip to content

zarr: read the regular_bounded chunk grid - #1133

Draft
rhoadesScholar wants to merge 6 commits into
google:masterfrom
rhoadesScholar:zarr-offset-chunk-key-encoding
Draft

rhoadesScholar wants to merge 6 commits into
google:masterfrom
rhoadesScholar:zarr-offset-chunk-key-encoding

Conversation

@rhoadesScholar

@rhoadesScholar rhoadesScholar commented Oct 15, 2026 •

Copy link
Copy Markdown

Reads arrays on the regular_bounded chunk grid (zarr-developers/zarr-extensions#81, planned in zarr-developers/zarr-extensions#79). It is a regular grid with an origin (the array coordinate where chunk 0 starts) and a lower_bound (the coordinate of the first element), under which chunk keys may be negative and the first chunk may be partly filled. Writers use it to grow an array in front without moving chunks (zarr-developers/zarr-python#4516, google/tensorstore#296).

Chunk coordinates are taken relative to the origin, as the precomputed source does with its voxel offset:

  • the voxel bounds are [lower_bound - origin, lower_bound - origin + shape);
  • the chunk-to-multiscale transform maps them to an index space that starts at the first element, by adding origin - lower_bound;
  • a bare array's scale transform translates by lower_bound, so its model bounds start there;
  • inside an OME multiscale group each level's translation locates its first element, as the NGFF coordinate convention defines the index space, so the lower bound does not enter the OME transforms.

Grid positions, and so keys, come out negative without any change to key formatting. Chunks that extend below lowerVoxelBound were already supported.

Before and after. Before, chunk_grid must be regular, so such an array fails to parse. After, it opens with the right bounds.

Tests.

  • Parse tests in regular_bounded.spec.ts.
  • Three example stores written by zarr-python, added to the metadata snapshot tests. One bare array was grown in front by prepend. Another has a non-zero origin on both axes, and its snapshot shows the origin in the transform and the permuted voxel bounds. The third is the simple_0.5 OME group grown in front at both levels, with each level's translation moved to its new first element; its per-level transforms come out identical to the ungrown group's.

tensorstore reads the two bare stores identically. vitest, the browser snapshot tests (headless Chromium), tsc, eslint, oxlint and prettier all pass. Not verified: rendering voxel data in a browser session.

@google-cla

google-cla Bot commented Oct 15, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for the Zarr v3 "offset" chunk key encoding extension. It refactors chunk key generation into a centralized encodeChunkKey function, updates metadata parsing to validate and extract offset configurations, and adds comprehensive unit and snapshot tests. The feedback suggests a minor improvement in encodeChunkKey to use optional chaining and nullish coalescing for safer and more concise offset resolution.

Comment thread src/datasource/zarr/metadata/index.ts Resolved
@rhoadesScholar
rhoadesScholar force-pushed the zarr-offset-chunk-key-encoding branch from dbee33e to 397b44b Compare October 15, 2026 23:17
@rhoadesScholar
rhoadesScholar marked this pull request as ready for review October 16, 2026 00:13
@rhoadesScholar

Copy link
Copy Markdown
Author

Ready for review. The encoding is proposed in zarr-developers/zarr-extensions#80; this is the reader side. cc @jbms

@chrisj

chrisj commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

@rhoadesScholar we should convert this to a draft until the change is adopted by Zarr

@rhoadesScholar
rhoadesScholar marked this pull request as draft October 16, 2026 19:48
@rhoadesScholar

Copy link
Copy Markdown
Author

Agreed, converted. The design is being worked out in zarr-developers/zarr-extensions#79; this branch will be reworked to match.

@rhoadesScholar

Copy link
Copy Markdown
Author

The metadata form is being settled in ZEP 12 (zarr-developers/zeps#72, spec text zarr-developers/zarr-specs#400). This PR stays on the regular_bounded grid until that lands, then moves its metadata read to the ZEP's fields; the rest of the change is unaffected.

The `offset` encoding (zarr-extensions chunk-key-encodings/offset) stores
a chunk under the `default` key of its grid coordinate plus a fixed
per-dimension integer offset, so a writer can grow an array in the
negative direction by whole chunks without renaming chunks. Parse the
name and its `offset` (one integer per dimension, `/` separator by
default), and add the offset where grid coordinates become keys. The key
string composition moves out of the chunk source into `encodeChunkKey`
so it can be unit-tested; `default` and `v2` keys are unchanged.

Adds an example store that grew by one chunk row in front (keys c/-1/*)
to the metadata snapshot tests.
Rework following zarr-extensions#79: the `offset` chunk key encoding is
removed. `regular_bounded` is a regular chunk grid with an `origin` (the
array coordinate where chunk 0 starts) and a `lower_bound` (the
coordinate of the first element), so chunk grid indices may be negative
and the first chunk may be partly filled.

Chunk coordinates are taken relative to the origin, as the precomputed
source does with its voxel offset: the voxel bounds are
`[lower_bound - origin, lower_bound - origin + shape)`, the origin is
added in the chunk-to-multiscale transform, and the model bounds start
at `lower_bound`. Grid positions, and so keys, come out negative where
they should without any change to key formatting.

Two example stores written by zarr-python are added to the metadata
snapshot tests: one grown in front by `Array.prepend`, and one with a
non-zero origin on both axes. tensorstore reads both identically.
A regular_bounded array inside an OME multiscale group was placed with
`translation` at coordinate 0, which displaced it by lower_bound * scale.
The chunk space now maps to an index space that starts at the first
element, as OME-NGFF defines it; a bare array keeps its own coordinates
through the scale transform. Adds the regular_bounded_0.5 fixture,
simple_0.5 grown in front at both levels, whose per-level transforms
match the ungrown group.
Moves a mid-file import to the top (E402) and applies ruff format to the
two zarr fixture generators.
@rhoadesScholar
rhoadesScholar force-pushed the zarr-offset-chunk-key-encoding branch from 1038d1b to 0250eca Compare October 27, 2026 18:30

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants