5. Zarr Store Structure¶
5.1 Root Structure¶
A ZV store is a Zarr v3 group at its root. Its on-disk layout (below — chunk keys use the dot-separated dimensional encoding):
<store>/
├── zarr.json # root group metadata; carries:
│ # "multiscales": [{"axes":[...], "datasets":[...]}]
│ # "zarr_vectors": { zv_version, chunk_shape,
│ # bounds, geometry_types,
│ # conventions, capabilities, ... }
├── 0/ # full-resolution level (required)
│ ├── zarr.json # group metadata; "zarr_vectors_level": {...}
│ ├── vertices/
│ │ ├── zarr.json # 1-D uint8 single-chunk-per-coord
│ │ ├── <i.j.k> # raw or Draco vertex bytes
│ │ └── …
│ ├── vertex_fragments/
│ │ ├── zarr.json
│ │ ├── <i.j.k> # fragment-index blob (see §7.3)
│ │ └── …
│ ├── links/
│ │ ├── 0/ # delta = 0 (same level)
│ │ │ ├── zarr.json # carries link_width, num_links
│ │ │ ├── <i.j.k>
│ │ │ └── …
│ │ └── +1/ # delta = +1 (optional, see §9.6)
│ │ └── …
│ ├── link_fragments/
│ │ ├── zarr.json
│ │ ├── <i.j.k> # parallels links/0/<i.j.k>
│ │ └── …
│ ├── vertex_attributes/
│ │ └── <name>/
│ │ ├── zarr.json
│ │ └── <i.j.k> # row-aligned to vertices/<i.j.k>
│ ├── fragment_attributes/
│ │ └── <name>/
│ │ ├── zarr.json
│ │ └── <i.j.k> # row-aligned to vertex_fragments/<i.j.k>
│ ├── link_attributes/
│ │ └── <name>/
│ │ └── 0/
│ │ └── <i.j.k> # row-aligned to links/0/<i.j.k>
│ ├── object_index/
│ │ ├── zarr.json
│ │ └── data # manifest-block stream (§7.6)
│ ├── object_attributes/
│ │ └── <name>/
│ │ ├── zarr.json
│ │ └── data
│ ├── groups/
│ │ ├── zarr.json
│ │ └── data # ragged CSR per group → object ids
│ ├── group_attributes/
│ │ └── <name>/
│ │ └── data
│ ├── cross_chunk_links/
│ │ └── 0/
│ │ ├── zarr.json # link_width, num_links, level_delta=0
│ │ └── data
│ └── cross_chunk_link_attributes/
│ └── <name>/
│ └── 0/
│ └── data
├── 1/ # optional coarser level
│ ├── zarr.json # may override "chunk_shape" (v0.7)
│ ├── vertices/ …
│ ├── links/
│ │ ├── 0/ # intra-level edges at this level
│ │ └── +1/ # optional fine→coarse links
│ ├── cross_chunk_links/
│ │ ├── 0/
│ │ └── +1/ # optional
│ └── …
└── N/
5.2 Zarr Version Requirements¶
Required Zarr version: v3.
Per-array layout: every ZV array (vertices, fragments, links, attributes, object_index, groups, cross-chunk links, …) is a 1-D
uint8, single-chunk-per-coord array — a project-internal byte layout wrapped in a Zarr group. The internal layouts (fragment index, manifest-block stream, link payloads) are documented in §7; Zarr handles compression and storage, not record framing.No ragged-array codec required: ragged structure is expressed by the byte-blob layouts above, not by Zarr v3’s variable-length-chunk feature.
Codecs used: Blosc + Zstd (
clevel=5,shuffle=1/BYTE for positions / attributes / fragment-index / object_index;shuffle=2/BITSHUFFLE forlinks). See §11 and thezarr_vectors.encoding.compressionmap.
5.3 Store Backend Requirements¶
ZV stores work on any Zarr v3 store implementation:
Object stores: S3, GCS, Azure Blob (via fsspec or store-specific adapters).
Filesystems: POSIX, distributed FS, in-memory.
Transactional backends: icechunk and similar enable safe concurrent appends to
object_index/
Concurrency:
Writes to different spatial chunks are independent — each chunk’s
vertices/<i.j.k>,vertex_fragments/<i.j.k>, link payloads, and attribute blobs can be authored without coordination.object_index/data,groups/data, andcross_chunk_links/<delta>/ dataare global per-level arrays; writers either serialize updates or rely on a transactional backend.
Atomicity is per Zarr’s storage model (per-blob writes are atomic on common backends; multi-blob updates are not atomic and must be serialized when needed).
5.4 Naming Conventions¶
Canonical array names — these match ALL_ARRAY_NAMES in the
implementation (zarr_vectors.constants):
Name |
Description |
|---|---|
|
per-chunk vertex byte blobs |
|
per-chunk fragment index over |
|
per-chunk fragment index over |
|
per-(delta, chunk) link byte blobs |
|
per-(name, chunk) attribute blobs, row-aligned to vertices |
|
per-(name, chunk) attribute blobs, row-aligned to vertex_fragments |
|
per-(name, delta, chunk) attribute blobs |
|
flat manifest-block stream (§7.6) |
|
per-(name) dense object-row arrays |
|
flat ragged CSR — object ids per group |
|
per-(name) dense group-row arrays |
|
per-delta records spanning chunk boundaries |
|
per-(name, delta) attribute blobs parallel to CCL records |
Resolution level groups are named as bare integers (0/, 1/, …,
N/). The legacy resolution_0/ / resolution_1/ prefix was
dropped in 0.4.1 to align with OME-Zarr image-pyramid level naming.
Metadata is carried under Zarr v3’s standard zarr.json files; ZV
extends each zarr.json with a namespaced sub-object:
root:
zarr.json["zarr_vectors"]for ZV fields andzarr.json["multiscales"]for NGFF axes (RFC 4) + per-level datasets entry,per-level group:
zarr.json["zarr_vectors_level"],per-array group:
zarr.json["zv_array"]discriminator plus a small shape/dtype block.