Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,8 @@ ngff-zarr upgrade src.zarr -o dst.zarr --to 0.5

The target version is selected with `--to` (alias `--version`), one of `0.4`,
`0.5`, `0.6`, or `0.9.dev1` (default `0.6`). `0.9.dev1` is the development
version that adopts RFC-3; OME publishes no JSON Schema for it yet, so
`--validate` cannot check a store at that version. Add `--validate` to validate
the source metadata against the NGFF schema while reading. For the write-to-new-store mode,
version that adopts RFC-3. Add `--validate` to validate the source metadata
against the NGFF schema while reading. For the write-to-new-store mode,
`--overwrite` (the default) replaces any pre-existing data at the output store,
while `--no-overwrite` refuses to; both flags are ignored for an in-place
upgrade, which never overwrites array data.
Expand Down
6 changes: 3 additions & 3 deletions docs/spec_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ supported by `ngff-zarr`.
and transformations.
- **OME-Zarr 0.9.dev1**: Reads and writes the development version that adopts
RFC-3, which extends support for the number, names, types and order
of axes. It is opt-in: pass `version="0.9.dev1"` explicitly. The default
target is unchanged, and OME publishes no JSON Schema for it yet, so schema
validation is unavailable at that version.
of axes. It is opt-in: pass `version="0.9.dev1"` explicitly, the default
target is unchanged. The schemas of the `0.9.dev1` release are bundled, so
`validate=True` checks a store at that version as it does at any other.

## High Content Screening (HCS)

Expand Down
3 changes: 3 additions & 0 deletions docs/validation/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ finest-to-coarsest dataset ordering, OMERO channel color format, RFC 4
anatomical orientation, and HCS plate/well consistency. Most rules enforce v0.4
MUSTs; two additional rules (`zarr-format`, `ome-namespace`) enforce the v0.5
`ome`-namespace and Zarr v3 store conventions and fire only for v0.5 metadata.
The three RFC 4 orientation rules are normative from OME-Zarr 0.9.dev1: they
are inert when the caller declares an earlier version and stay on, as a
strictness choice, when no version is declared (see [[rule-reference]]).

The rules operate on the already-parsed metadata object (the `Metadata`,
`Plate`, and `Well` dataclasses in Python; their equivalents in TypeScript), so
Expand Down
19 changes: 18 additions & 1 deletion docs/validation/parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ for usage, see [[api]].

## The contract

Both ports must agree on five observable dimensions:
Both ports must agree on six observable dimensions:

1. **Rule identifiers** — the same `SpecRule` string values, in the same
canonical declaration/iteration order.
Expand All @@ -42,6 +42,10 @@ Both ports must agree on five observable dimensions:
inert for the versions that adopt the RFC-3 free-form axis model. Both ports
must treat exactly the same version strings as RFC-3, or the same metadata
validates in one language and not the other.
6. **The RFC-4 orientation version set** — the three orientation rules gate the
opposite way: they are normative at exactly the versions that adopt RFC-4
(and when no version is given), and inert below. Both ports must treat the
same version strings as RFC-4 for the same reason.

Because both test suites assert these facts against the **same literal
identifier list**, adding, removing, renaming, or reordering a rule — or
Expand Down Expand Up @@ -85,6 +89,15 @@ at every other. Rule 4, `axis-names-unique`, is never inert: RFC-3 *adds* it,
and ngff-zarr applies it at all versions as a strictness choice (see
[[rule-reference]]).

The versions at which the RFC-4 orientation rules are normative are pinned the
same way, as a `CANONICAL_RFC4_VERSIONS` literal:

1. `0.9.dev1`

Rules 9–11 gate the opposite way from the RFC-3 set: they are enforced at
those versions and when no version is given, and inert at every earlier
version, where RFC-4 has no normative status (see [[rule-reference]]).

## The parity tests

| Language | Test file |
Expand Down Expand Up @@ -116,6 +129,10 @@ Each suite independently locks:
`CANONICAL_RFC3_VERSIONS` and enforced at every other supported version and
when no version is given, asserted through the public orchestrator rather
than through the internal predicate.
- **RFC-4 orientation version set** — the orientation rules are enforced at
exactly the versions in `CANONICAL_RFC4_VERSIONS` (and when no version is
given) and inert at every other supported version, asserted the same way,
once per orientation rule.

Four of the fifteen rules never appear in `EXPECTED_EVALUATION_ORDER`, each for
its own reason. The two v0.5 namespacing rules (`zarr-format`, `ome-namespace`)
Expand Down
30 changes: 18 additions & 12 deletions docs/validation/rule-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ stable, lower-kebab-case identifier (the `SpecRule` value) that is identical
across the Python and TypeScript ports — see [[parity]] for the guarantee. Most
rules enforce OME-Zarr v0.4 MUSTs; the two v0.5 namespacing rules
(`zarr-format`, `ome-namespace`) fire only for v0.5 metadata and are inert (a
no-op) for v0.4. For the conceptual background and the two validation levels,
see [[overview]]; for invocation, see [[api]].
no-op) for v0.4. The three RFC 4 orientation rules (9–11) are normative from
OME-Zarr 0.9.dev1, which incorporates RFC-4 through `ome/ngff-spec#190`: they are
inert when the caller declares 0.4, 0.5 or 0.6, where RFC 4 has no normative
status, and stay on when no version is declared — a strictness choice, like
`axis-names-unique` below 0.9.dev1. For the conceptual background and the two
validation levels, see [[overview]]; for invocation, see [[api]].

Location strings are dotted-segment, JSON-Pointer-style identifiers of the
offending metadata node, emitted byte-for-byte identically in both languages.
Expand All @@ -44,9 +48,9 @@ the `SpecRule` enum declares them and the orchestrators evaluate them.
| 6 | `global-coord-transform-after-per-level` | images/multiscales | Exactly one `scale` per dataset, and a `translation` must follow — not precede — its `scale`. | v0.4: each dataset defines exactly one scale; a translation follows its scale. | `multiscales[0].datasets[1].coordinateTransformations` |
| 7 | `dataset-order-highest-to-lowest` | images/multiscales | Datasets ordered finest → coarsest; the spatial scale must not decrease as the level index rises. | v0.4: multiscale datasets ordered from highest to lowest resolution. | `multiscales[0].datasets[2]` |
| 8 | `omero-channel-color-format` | OMERO | Each OMERO channel `color` is exactly six hexadecimal digits (RGB). | v0.4: OMERO channel color is 6 hex digits. | `multiscales[0].omero.channels[0].color` |
| 9 | `axis-orientation-anatomical-type` | RFC 4 orientation | Every declared spatial-axis `orientation` has `type` `anatomical`. | RFC 4: an orientation's `type` is `anatomical`. | `multiscales[0].axes` |
| 10| `axis-orientation-on-non-space` | RFC 4 orientation | An `orientation` is declared only on `space` axes, never on a non-spatial axis. | RFC 4: orientation applies to spatial axes only. | `multiscales[0].axes[0]` |
| 11| `axis-orientation-unique-axis` | RFC 4 orientation | No two spatial axes declare orientations describing the same anatomical axis. | RFC 4: each spatial axis describes a distinct anatomical axis. | `multiscales[0].axes` |
| 9 | `axis-orientation-anatomical-type` | RFC 4 orientation | Every declared spatial-axis `orientation` has `type` `anatomical`. Inert below 0.9.dev1 when the caller declares a version; kept on when none is given. | RFC 4 (normative from 0.9.dev1): an orientation's `type` is `anatomical`. No released spec below 0.9.dev1 adopts RFC 4, so enforcement without a declared version is a strictness choice, not a spec MUST of those versions. | `multiscales[0].axes` |
| 10| `axis-orientation-on-non-space` | RFC 4 orientation | An `orientation` is declared only on `space` axes, never on a non-spatial axis. Inert below 0.9.dev1 when the caller declares a version; kept on when none is given. | RFC 4 (normative from 0.9.dev1): orientation applies to spatial axes only. Same below-0.9.dev1 status as rule 9. | `multiscales[0].axes[0]` |
| 11| `axis-orientation-unique-axis` | RFC 4 orientation | No two spatial axes declare orientations describing the same anatomical axis. Inert below 0.9.dev1 when the caller declares a version; kept on when none is given. | RFC 4 (normative from 0.9.dev1): each spatial axis describes a distinct anatomical axis. Same below-0.9.dev1 status as rule 9. | `multiscales[0].axes` |
| 12| `zarr-format` | images/multiscales (v0.5) | A v0.5 entry implies a Zarr v3 store; a `zarr_format` value that leaked into the entry must be exactly `3`. Inert for v0.4. | v0.5: metadata is backed by a Zarr v3 store (`zarr_format == 3`). | `multiscales[0]` |
| 13| `ome-namespace` | images/multiscales (v0.5) | A v0.5 entry must not retain a group-level `ome` or `multiscales` wrapper key — the `ome` namespace wraps the group attributes, not each entry. Inert for v0.4. | v0.5: multiscales live under the top-level `ome` namespace, with `version` hoisted to `ome.version`. | `multiscales[0]` |
| 14| `plate-row-index-consistency` | HCS plate | Each well's `path` is `<row>/<column>`, naming declared row/column entries, with `rowIndex`/`columnIndex` equal to those entries' positions. | v0.4: well `rowIndex`/`columnIndex` match the named row/column positions in `plate.rows`/`plate.columns`. | `plate.wells[3]` |
Expand All @@ -65,11 +69,12 @@ rules:
class-ordering then spatial-name ordering for `axis-order`; per-dataset
scale-count then transform-ordering for
`global-coord-transform-after-per-level`. The v0.5 namespacing rules (12 and
13) run last and are inert for v0.4 input. The orientation rules
`axis-orientation-on-non-space` (10) and `axis-orientation-unique-axis` (11)
fire only for specific axis shapes, so the linear fail-fast cascade for a v0.4
metadata is an 11-step sequence ending at
`axis-orientation-anatomical-type`.
13) run last and are inert for v0.4 input, and the orientation rules (9–11)
are inert when the caller declares a version below 0.9.dev1. The orientation
rules `axis-orientation-on-non-space` (10) and `axis-orientation-unique-axis`
(11) fire only for specific axis shapes, so the linear fail-fast cascade for
a v0.4-shaped metadata validated with no declared version is an 11-step
sequence ending at `axis-orientation-anatomical-type`.
- **`validate_plate` / `validatePlate`** evaluates rule **14**
(`plate-row-index-consistency`).
- **`validate_well` / `validateWell`** evaluates rule **15**
Expand All @@ -96,8 +101,9 @@ TypeScript by checking the target version in `axisViews`.
`global-coord-transform-after-per-level`,
`dataset-order-highest-to-lowest`.
- **OMERO** — `omero-channel-color-format`.
- **RFC 4 orientation** — `axis-orientation-anatomical-type`,
`axis-orientation-on-non-space`, `axis-orientation-unique-axis`.
- **RFC 4 orientation** (normative from 0.9.dev1) —
`axis-orientation-anatomical-type`, `axis-orientation-on-non-space`,
`axis-orientation-unique-axis`.
- **v0.5 namespacing** — `zarr-format`, `ome-namespace` (inert for v0.4).
- **HCS plate / well** — `plate-row-index-consistency`,
`well-acquisition-missing`.
Original file line number Diff line number Diff line change
Expand Up @@ -372,14 +372,14 @@
"items": {
"type": "number"
},
"description": "Names of the input axes for this transformation."
"description": "Indices of the input axes for this transformation."
},
"outputAxes": {
"type": "array",
"items": {
"type": "number"
},
"description": "Names of the output axes for this transformation."
"description": "Indices of the output axes for this transformation."
}
},
"required": [
Expand Down
2 changes: 1 addition & 1 deletion py/ngff_zarr/spec/0.6/schemas/image.schema
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
]
},
{
"description": "A sequence of a ingle scale followed by a single translation",
"description": "A sequence of a single scale followed by a single translation",
"type": "object",
"properties": {
"type": {"const": "sequence"},
Expand Down
10 changes: 10 additions & 0 deletions py/ngff_zarr/spec/0.9/schemas/_version.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/_version.schema",
"title": "OME-Zarr version",
"description": "OME-Zarr version.",
"type": "string",
"enum": [
"0.9.dev1"
]
}
46 changes: 46 additions & 0 deletions py/ngff_zarr/spec/0.9/schemas/axes.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/axes.schema",
"title": "Axes",
"description": "OME-Zarr Axes.",
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"$ref": "#/$defs/axis"
},
"$defs": {
"axis": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"description": "Name of the axis. Must be unique within the coordinate system."
},
"longName": {
"type": "string",
"description": "Longer name or description of the axis."
},
"type": {
"type": "string",
"description": "Type of the axis. Can be a predefined type or custom type."
},
"discrete": {
"type": "boolean",
"description": "Whether the dimension is discrete"
},
"unit": {
"type": "string",
"description": "Unit for the axis"
},
"orientation": {
"$ref": "axis_orientation.schema"
}
},
"required": [
"name"
]
}
}
}
41 changes: 41 additions & 0 deletions py/ngff_zarr/spec/0.9/schemas/axis_orientation.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/axis_orientation.schema",
"title": "Axis Orientation",
"description": "Controlled vocabulary for orientation of each spatial axis according to subject or subject-global reference.",
"type": "object",
"properties": {
"type": {
"enum": ["anatomical"]
},
"value": {
"enum": [
"left-to-right",
"right-to-left",
"anterior-to-posterior",
"posterior-to-anterior",
"inferior-to-superior",
"superior-to-inferior",
"dorsal-to-ventral",
"ventral-to-dorsal",
"dorsal-to-palmar",
"palmar-to-dorsal",
"dorsal-to-plantar",
"plantar-to-dorsal",
"rostral-to-caudal",
"caudal-to-rostral",
"cranial-to-caudal",
"caudal-to-cranial",
"proximal-to-distal",
"distal-to-proximal",
"superficial-to-deep",
"deep-to-superficial",
"apical-to-basal",
"basal-to-apical",
"apex-to-base",
"base-to-apex"
]
}
},
"required": ["type", "value"]
}
32 changes: 32 additions & 0 deletions py/ngff_zarr/spec/0.9/schemas/bf2raw.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/bf2raw.schema",
"title": "bioformats2raw",
"description": "OME-Zarr bioformats2raw metadata.",
"type": "object",
"properties": {
"ome": {
"description": "The versioned OME-Zarr Metadata namespace",
"type": "object",
"properties": {
"bioformats2raw.layout": {
"description": "The top-level identifier metadata added by bioformats2raw",
"type": "number",
"enum": [
3
]
},
"version": {
"$ref": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/_version.schema"
}
},
"required": [
"bioformats2raw.layout",
"version"
]
}
},
"required": [
"ome"
]
}
31 changes: 31 additions & 0 deletions py/ngff_zarr/spec/0.9/schemas/coordinate_systems.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ngff.openmicroscopy.org/0.9.dev1/schemas/coordinate_systems.schema",
"title": "Coordinate systems",
"description": "OME-Zarr coordinate system.",
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/coordinateSystem"
},
"$defs": {
"coordinateSystem": {
"description": "Coordinate Systems for OME-NGFF",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"description": "Name of coordinate system. Must be unique among all coordinate systems."
},
"axes": {
"$ref": "axes.schema"
}
},
"required": [
"name",
"axes"
]
}
}
}
Loading
Loading