moczarr.convention
The morton-hive layout convention, read side (pure functions, no I/O).
The layout is owned by the mortie spec (espg/mortie#62); zagg writes it
(zagg.hive); moczarr reads it. Summary::
{store_root}/
morton_hive.json <- static manifest; root-only exception
coverage.moc <- root ranges MOC; root-only exception
{sign+base}/{d1}/.../{d_n}/ <- digit component(s) per level
{full_id}.zarr/ <- vanilla zarr v3 leaf
{full_id}_{window}.zarr/ <- time-windowed leaf (morton-hive/2)
- Ids are morton decimal strings: sign + base digit (
1..6), then one digit1..4per order. A string prefix is a spatial ancestor. - Path components chunk the digit tail per the manifest's
path_grouping(spec §6.1; zagg D21):path_groupingdigits per component, the LAST component carrying the remainder when the order does not divide evenly (leading components stay full-width, so component boundaries are ancestor prefixes shared by deeper shards regardless of their order).1— the default, and every existing store retroactively — is a value of the one generic chunking, never a separate code path; readers chunk per the manifest, never by assumption. - Below the root a node holds only digit children and
*.zarrobjects (the node invariant); the manifest and rootcoverage.mocare the two root-only exceptions. - A leaf is complete iff its root zarr attrs carry the commit stamp
(
morton_hive_commit); an unstamped.zarr/prefix is debris. - Windowed leaf names split on the FIRST
_(morton ids and window labels never contain one); labels use the frozen charset[0-9A-Za-z-]{1,32}.
Everything here is arithmetic on ids and dict validation — the store layer
(phase 2) supplies the bytes. Golden vectors in tests/ pin this
implementation against zagg's writer so the two cannot drift silently.
area29_to_point(word)
Max-encoded POINT twin(s) of order-29 AREA word(s) — the p parse.
Inverse of :func:point_to_area29: area 28 + t28*5 + (t29 + 1) ->
point 48 + t28*4 + t29 (spec §1). Raises on any word that is not an
order-29 area encoding — points exist only at order 29 (§2/§4).
Source code in src/moczarr/convention.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
check_node_invariant(rel_path, *, path_grouping=1)
Raise unless rel_path is a legal hive leaf path.
Below the root only digit components are allowed — {sign+base}
(optional -, one digit 1..6) at the first level, then digit
(1..4) components chunked per path_grouping (spec §6.1): every
component full-width except the last, which carries the remainder —
terminating in {full_id}.zarr (or the windowed
{full_id}_{window}.zarr) whose id equals the concatenated
components. This is the walker's contract: any other name under the root
(bar the manifest and the root coverage.moc) breaks child
classification.
Source code in src/moczarr/convention.py
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | |
decimal_base(decimal)
The {sign+base} component of a decimal id.
Source code in src/moczarr/convention.py
185 186 187 | |
decimal_order(decimal)
HEALPix order of a decimal id (one digit per level past the base).
Source code in src/moczarr/convention.py
180 181 182 | |
decimal_rank(decimal)
Base-4 value of a decimal id's digit tail (digits 1..4 -> 0..3).
The bit/rank convention of the coverage encodings: ascending packed-word (Z-)order within one base cell at a fixed order.
Source code in src/moczarr/convention.py
190 191 192 193 194 195 196 197 198 199 | |
group_digits(digits, path_grouping)
Chunk a digit tail into hive path components (spec §6.1, zagg D21).
Left to right, path_grouping digits per component; the LAST component
carries the remainder when len(digits) % path_grouping != 0. Leading
components stay full-width so every component boundary is a spatial
ancestor prefix (§2) shared by deeper shards regardless of their order —
mixed-order shards share ancestor nodes, the property the digit tree
exists for.
Source code in src/moczarr/convention.py
217 218 219 220 221 222 223 224 225 226 227 | |
is_base_component(name)
Whether name is a {sign+base}-shaped hive root child.
Source code in src/moczarr/convention.py
211 212 213 214 | |
is_point_word(word)
Whether packed word(s) encode an order-29 POINT (spec §1/§4).
Kind is carried by the word's 6-bit suffix — 48..=63 is the point
band; everything below (0..=47) is an AREA element, exact at its
encoded order — never by store or array metadata (§4). Suffix-mask
implementation, golden-tested against the spec §1 table; swaps to
mortie's public kind predicate once released (espg/mortie#116 —
mortie 0.9.0 has none). Scalar in -> bool; array in -> bool array.
Source code in src/moczarr/convention.py
77 78 79 80 81 82 83 84 85 86 87 88 89 | |
leaf_name(full_id, window=None)
The leaf zarr basename: {full_id}_{window}.zarr, or bare.
Source code in src/moczarr/convention.py
249 250 251 252 253 254 | |
leaf_path(shard, window=None, *, path_grouping=1)
Store-relative hive path of a shard's leaf zarr.
path_grouping is the manifest's digit-chunking (spec §6.1; default
1 — every pre-D21 store). At 1 the path is computed by mortie's
hive_path (the convention owner) and re-checked against the node
invariant so drift on either side fails loudly; the grouped form chunks
the decimal here (:func:group_digits) until mortie grows the grouped
hive_path (espg/mortie#62). window selects the time-windowed
leaf at the same node.
Source code in src/moczarr/convention.py
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |
manifest_path_grouping(manifest)
The manifest's path_grouping (D21: absent reads as 1).
Assumes a :func:parse_manifest-validated manifest; the single accessor
keeps the absent->1 normalization in one place.
Source code in src/moczarr/convention.py
230 231 232 233 234 235 236 | |
morton_decimal(word)
Decimal morton string of a packed word (pass-through for strings).
POINT words (§1 suffix 48..=63) render with the terminal p kind
marker — the §2 render/interchange form — via the order-29 area twin's
digits (same path; kind restored by the marker, so the round-trip is
lossless for BOTH kinds, pinned by goldens).
Source code in src/moczarr/convention.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
morton_word(label)
Packed uint64 morton word of a decimal id (pass-through for ints).
Accepts the §2 p kind-suffix on full order-29 POINT ids: the stem
parses as the area word and the §1 point suffix is restored moczarr-side
(:func:area29_to_point) — mortie 0.9.0 predates the p grammar
(espg/mortie#120/#121). An UNMARKED order-29 string parses as the AREA
word, the normative §4 tie-break. Rides mortie's private-but-documented
_decimal_to_word (numpy-only; the public array classes require
pandas — upstream ask for a public export stands, same note as zagg's
boundary helper).
Source code in src/moczarr/convention.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
parse_manifest(payload)
Validate a morton_hive.json payload; returns it as a dict.
Loud on malformed input (a manifest is the reader's bootstrap — there is
no degraded mode without it): unknown spec, missing/non-integer
orders, a /2 manifest without its temporal block, or a temporal block
without a schedule all raise ValueError.
Source code in src/moczarr/convention.py
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
point_to_area29(word)
Order-29 AREA twin(s) of point word(s); area words pass through.
Spec §1 suffix arithmetic on the same body: point 48 + t28*4 + t29
-> area 28 + t28*5 + (t29 + 1). The twin shares the point's full
path, so containment arithmetic (§4: membership of a point at a coarser
level is ordinary truncation) runs uniformly in area space — the
normalization :func:moczarr.coverage.aoi_mask applies. Scalar in ->
int; array in -> uint64 array.
Source code in src/moczarr/convention.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
rank_tail(rank, depth)
Inverse of :func:decimal_rank: the width-depth digit tail.
Source code in src/moczarr/convention.py
202 203 204 205 206 207 208 | |
split_leaf_name(name)
(full_id, window-or-None) from a leaf basename — split on the FIRST _.
Morton decimal ids never contain _ and window labels cannot
(charset), so the first underscore is the one separator. Raises on a
non-.zarr name or a malformed window label.
Source code in src/moczarr/convention.py
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | |
validate_label(label)
Validate a window label against the frozen charset; returns it.
Source code in src/moczarr/convention.py
239 240 241 242 243 244 245 246 | |