CompactedEncoding: mixed-level cell axes in Zarr stores - #33
Conversation
Registered as "compacted" (the zarr-conventions/dggs vocabulary). cellaxis takes the system and the two per-cell columns — level and raw id — validates every pair and the disjointness, and answers a MultiOrderVector; container order is required rather than restored because data arrays are laid out against the stored positions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A MultiOrderLookup axis writes as compacted under :auto — cell_ids plus a cell_levels column on its own dimension, refinement_level: null, no xdggs stamp (its attrs can only describe a dense single-level coordinate). A single-level encoding requested for one keeps the :mixed_level_axis refusal with the expand bridge. dggread routes compacted through a storedlookup seam to a MultiOrderLookup, fully validated by the reader-side cellaxis. The chunk plan groups coarse-ancestor runs on the container itself and the manifest sidecar is keyed by reference-level interval start, with the reference level in its marker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The encoding suite pins the two-column round trip and every refusal by its check symbol on both radices. The write suite pins the on-disk shape (cell_levels on its own dimension, refinement_level null, no xdggs stamp, reference level in the marker) and the narrowed :mixed_level_axis refusal for explicit single-level encodings. The read suite round-trips a coarsened field on HEALPix and IGeo7: cells, values, a Contains query, and a bit-for-bit expand back to the leaf level. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The storage branch's rebase onto main moved `MultiOrderVector` from `Fallbacks` to `Engine`, so the compacted encoding's import, the writer's `reference_level` call and the read test's `covering_position` follow it. `dggwrite`'s stub docstring keeps main's `:ranges`/`:implicit` sentence alongside the compacted one, and the store-io registries stay `public` rather than exported, as main made them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwnXToXzkTdstjqfp8ovhH
|
Updated on top of the refreshed Conflicts and how they were resolved
Beyond the conflicts, three references followed Fast eager path, end to end through a compacted store
Suites (Julia 1.12, |
…check Codex review of #33. Three fixes: - the level column names itself in the store's `dggs` object (`refinement_levels`), the one key an independent reader needs to align it with `cell_ids`; and the docs stop claiming the layout conforms to zarr-conventions/dggs v1, which forbids `compression` other than `none` under `refinement_level: null`. - an encoding INSTANCE now takes the same `write_eligible` check its keyword does, so `encoding = CompactedEncoding()` on a single-level axis answers `not_write_eligible` instead of the self-contradictory `unsupported_encoding`. The fallback keeps a downstream encoding that states no restriction eligible. - a stored level no `Int` can hold is a format error, not an InexactError: membership in the system's levels is tested before narrowing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwnXToXzkTdstjqfp8ovhH
Codex review of the compacted layout — 5 findings, 3 fixed, 1 accepted-not-fixed, 1 rebuttedCodex (GPT-5.6 sol, high reasoning) reviewed 1.
so both radices are affected, not just healpix. The healpix Not fixable by a metadata tweak: the conforming shape for mixed-level healpix is a 2.
3. Out-of-range stored level → 4. 5. Empty compacted axis readable but not writable — [minor] — REBUTTED. Identical. If empty stores should be writable that is a separate change across all four encodings. What Codex could not breakMissing/short/non-integer Suites
|
The #29 review fixes. No conflicts. Two adaptations: that branch made `reference_level` public and exported `covering_position`, so the compacted writer and its read test drop the `Engine.` qualification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwnXToXzkTdstjqfp8ovhH
Stacked on #29 (it needs the
MultiOrderVector/MultiOrderLookupcontainer from that branch and the store-IO layer from main). Retarget tomainonce #29 merges.Implements the mixed-level ("compacted", in zarr-conventions/dggs vocabulary) store layout that #29's harmonization pass left as a named refusal:
CompactedEncodingin the encoding registry as"compacted". Two aligned columns in container order:cell_ids(the grid's own id type, the declared coordinate) andcell_levels(Int8, on its own dimension so it never reads as a data variable). Container order is required on read, not restored — a sort would silently misalign the value arrays (:compacted_axis_order).encoding = :autoselects compacted for aMultiOrderLookupaxis; an explicitly requested single-level encoding keeps the refusal namingexpand.chunks = :autodescends coarse-ancestor runs on the container; the persisted manifest is keyed by reference-level interval start/stop and its marker recordslevel: nullplus a newreference_levelfield.MultiOrderVectoranddggreadreturns aDimArrayover aMultiOrderLookup; selectors work against the read-back axis. A store declaring bothcompression: "compacted"and a non-nullrefinement_levelis refused (:level_with_compacted).Two behavioral decisions to review:
refinement_level: null+compression: "compacted"is the one legal spelling; a non-null level alongside compacted is refused rather than trusted.Numbers: io suite 784/784 offline, 799/799 with
DGG_IO_NETWORK_TESTS=1(live Pori stores still read); full suite 988,086 pass / 17 pre-existing broken / 0 fail. Round trips are value- and axis-identical on HEALPix (radix 4) and IGeo7 (radix 7, unsigned Z7 ids), including acoarsenoutput.Deferred: missing/fill-value support (pre-existing gap in every encoding — it is why the WorldClim tutorial has no write demo); a packed single-column id form (the registry and
storedlookupseam are ready for it); Zarr v3.🤖 Generated with Claude Code