Update spec for 0.9.dev1 including RFCs 3 & 4 - #190
Conversation
Automated Review URLs |
|
@jni thanks for starting this work. We're looking forward to having a first rendered version of this specification as well as dev schemas that we can use to validate datasets generated by implementations! Immediate question: is the next version number 0.9dev1 (as in this PR) or 0.9.dev1 (used in a few public discussions)? We have no opinion one way or the other, but we have used the latter so far so if the consensus is to move towards the first form, we will need to update our implementation and regenerate sample data /cc @melissalinkert |
This came up with the dev versions in 0.6. Because we use python tooling in the build step of the repo, we normalised on PEP440-style version specifiers Standard SemVer would use something like IMO we should stick with PEP440 ( |
|
Just to be clear, then, is the use of |
|
Apologies, for the confusion, my confusion indeed stemmed from the inconsistency between 0.6.devN and 0.6rcN noted by @clbarnes above. I think consistency with the 0.6 series makes sense, which means I'll update this PR to match that. In short @melissalinkert @sbesson, let's go with 0.9.dev1, no need to change your outputs, I will update this PR accordingly. |
|
Here's the current validation test failures: Most of these are because they have now become valid, so I'll move them. But these two: I don't understand why they are failing. Here's the orientation schema, which specifies that the strings must come from specific lists: and here's the relevant part of the files that are unexpectedly passing validation: I'm a noob with jsonschema so I would appreciate any tips or advice here! |
The development version that carries RFC-3 is 0.9.dev1. ome/ngff-spec#190 titles the specification 0.9.dev1 and its _version.schema enum holds that value; bioformats2raw#330 writes the same string. Renames the package py/ngff_zarr/v10 to v09 and its test module, the NgffVersion member V10DEV to V09dev1, and the version string in both ports. LATEST stays 0.6.dev4 and the version stays opt-in.
The development version that carries RFC-3 is 0.9.dev1. ome/ngff-spec#190 titles the specification 0.9.dev1 and its _version.schema enum holds that value; bioformats2raw#330 writes the same string. Renames the package py/ngff_zarr/v10 to v09 and its test module, the NgffVersion member V10DEV to V09dev1, and the version string in both ports. LATEST stays 0.6.dev4 and the version stays opt-in.
Update axes and cooordinate transformations schemas to remove axes restrictions as per RFC-3.
First, copied schema directly from RFC-4. Then, harmonised it to other schemas: - 2 spaces for indents - schema and ID at top - ID is NGFF url - add title and description - removed additionalproperties, metamodel, and version fields Added ref to orientation in axes schema and moved orientation def to top level.
- Add valid image data with axis orientation - Add invalid orientation attribute files - Add invalid orientation zarr folders - xfail duplicate orientation and orientation on non-space axes (these can't be easily expressed in jsonschema)
- index.md - Add 0.9.dev1 to version history - Update version string in all schemas - Update version in _version.py - Update version number on all examples - Update version string in omero valid test
|
@joshmoore @clbarnes @jo-mueller This should be ready for review. I've also rebased my changes into logical commits to make review easier. Especially if you skip the last commit (which updates the version string in every file), the list of changes should be manageable. |
| case_fnames = sorted(attrs_dir.rglob("*.json")) | ||
|
|
||
| xfails = set() | ||
| xfails = set([ |
There was a problem hiding this comment.
Extremely minor point: can use a set literal {} here.
| "value". Currently, "type" may only be "anatomical", and "value" may | ||
| only be one from the list given in [list of possible anatomical | ||
| orientation values](orientation-values). A specific orientation value or | ||
| its inverse MUST NOT appear more than once in a given coordinate system. |
There was a problem hiding this comment.
Could RECOMMEND TCZYX here for backwards-compatibility, if there's any benefit to that? Or alternatively, add a {hint} that axis ordering could affect performance of certain quries in combination with configuration of the array chunking/ sharding/ transposing.
There was a problem hiding this comment.
@clbarnes I'm puzzled about the line you chose to make this comment on? I don't see why axis an orientation note would recommend anything about axis ordering?
At any rate, I think hints about performance can come in future iterations of the 0.9.devN series.
There was a problem hiding this comment.
I am also puzzled by my choice of line here. Maybe I fat-fingered the touchpad.
| - If there are three spatial axes where two correspond to the image plane (`yx`) | ||
| and images are stacked along the other (anisotropic) axis (`z`), | ||
| the spatial axes SHOULD be ordered as `zyx`. | ||
| 0. The length of the axis names MUST match the number of axes of the array. |
There was a problem hiding this comment.
I'd be inclined towards 1-basing for ordered lists. The audience is obviously technical but in text 1-based is much more common.
There was a problem hiding this comment.
... But the wrong tick marks in point 5 should definitely be fixed 😂
There was a problem hiding this comment.
ok I fixed both the numbering and the quotes.
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules and the readers' raw RFC-4 hooks now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The TypeScript v0.6 reader also serves 0.9.dev1, so its hook keeps firing there; a 0.9.dev1 store with a stray orientation is still refused on read. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the old read-path rejection now pin the new acceptance; their fixtures also carried an (x, y, z) spatial order that the early RFC-4 raise had masked from the structural pass. Refs fideus-labs#667
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
The development version that carries RFC-3 is 0.9.dev1. ome/ngff-spec#190 titles the specification 0.9.dev1 and its _version.schema enum holds that value; bioformats2raw#330 writes the same string. Renames the package py/ngff_zarr/v10 to v09 and its test module, the NgffVersion member V10DEV to V09dev1, and the version string in both ports. LATEST stays 0.6.dev4 and the version stays opt-in.
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
The development version that carries RFC-3 is 0.9.dev1. ome/ngff-spec#190 titles the specification 0.9.dev1 and its _version.schema enum holds that value; bioformats2raw#330 writes the same string. Renames the package py/ngff_zarr/v10 to v09 and its test module, the NgffVersion member V10DEV to V09dev1, and the version string in both ports. LATEST stays 0.6.dev4 and the version stays opt-in.
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
|
Kudos, @jni! ❤️ For everyone working towards OME-Zarr 1.0, this will be the first of many dev tags. |
|
Adding a late 👍 following a discussion yesterday at the weekly OME Formats meeting. From a consumer perspective, are we expecting the development specification to be published under https://ngff.openmicroscopy.org/specifications/dev/index.html or https://ngff.openmicroscopy.org/specifications/0.9.dev1/index.html? Is that possibly waiting on |
|
dev/ is waiting for 0.6.0 to be released (there can be only one 👨🏴🌩️). 0.9.dev1/ should be served shortly, see ome/ngff#581 for some discussion. |
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
RFC-4 anatomical orientation is normative from OME-Zarr 0.9.dev1 (ome/ngff-spec#190); the released 0.4, 0.5 and 0.6 specs give it no status. Decided in fideus-labs#667: the three axis-orientation rules now gate on the declared version, becoming a no-op below 0.9.dev1. An omitted version keeps the checks on, as a strictness choice, exactly like axis-names-unique below 0.9.dev1, so every existing no-version caller is unchanged. The gate mirrors the RFC-3 helper's form with the polarity inverted: RFC-3 lifts axis restrictions at 0.9.dev1 while RFC-4 adds requirements, so is_rfc4_orientation_enforced exits the rules early below 0.9.dev1 rather than at it. The Python v0.4 reader now passes the store's declared version to validate_structural, as the TypeScript reader already did. The readers' raw RFC-4 hooks are removed. They ran validate_rfc4 orientation on the raw axis dicts before parsing, which the structural pass repeats on the parsed axes with the same function and the same verdicts (the RFC-4 JSON Schema's root object declares no properties, so its final pass constrains nothing); they fired before the structural rules, out of the canonical evaluation order; and the v0.6 Python hook read a flat axes list the v0.6 layout does not have. The orientation rule is now the single enforcement point in each port. No rule is added, renamed or reordered. The parity suites pin the new version set as CANONICAL_RFC4_VERSIONS in both ports. Two tests that pinned the raw hooks' read-path rejection now pin the read-path acceptance below 0.9.dev1; their fixtures carried an (x, y, z) spatial order that the hooks' early raise had kept from the structural pass. Refs fideus-labs#667
"OME-Zarr 0.9.dev1, the version `ome/ngff-spec#190` folds RFC-4 into" reads the issue number as a version and leaves the verb without an object. The version is 0.9.dev1; ome/ngff-spec#190 is what incorporates RFC-4 into it.
|
Just looking at https://github.com/ome/ngff-spec/releases/tag/0.9.dev1 it's a shame that page doesn't mention that RFC3 and RFC4 are part of 0.9dev1. |
|
I'm not sure but I don't believe updating the text here will update it on the release page. Still, I'll do it for future releases. We can also write a more thorough description for 0.9.dev2 which we can tag reasonably quickly. |

0.9.dev1 is intended to be:
probablyomero fields optional #87in current WIP this only includes RFC3. I need to get RFC4 in before we merge this.
Edit 1 (2026-08-20): updated title to 0.9.dev1 to reflect discussion and match PEP-440.
Edit 2 (2026-08-21): This PR now contains all of the listed requirements (RFC3, RFC4, #87 omero fields optional) and should be ready to merge to allow implementations to start to be written against it. Some notes below.
notes
The limits removals on coordinate-transformations are the thing I'm least sure about, would appreciate extra eyes there.
In
schemas/coordinate_transformations.schema,rotationis defined by a 2, 3, 4, or 5-dimensional rotation matrix. This is incompatible with RFC-3 but cannot be easily extended to an arbitrary number of dimensions.Possible solutions:
I'm also not sure about 6199f0e and the difference to 93c1ba7.
Finally I don't know how to express that orientation can only be present if axis type is "space".