Skip to content

Commit 657ff11

Browse files
jo-muellerwill-mooredstansbyd-v-bclbarnes
authored
split tests (#4)
* upgrade to Jupyter book 2 * correctly mark examples * bump mystmd dependency * pin mystmd * hashpin template * remove legacy dependencies * Create README.md for OME-NGFF specification * remove legacy files * use auto-built footer for copyright * Update `coordinateSystems` metadata * Updated `axes` metadata and moved under `coordinateSystems` header level * Update array coordinate systems metadata and merge existing examples * Update coordinate convention metadata * Updated coordinate transformations metadata * updated matrix transformations * update transformation types * update transformation types metadata * harmonize link syntax * removed deprecated statement about `byDimension` transform * harmonized indendations and json style * fixed `byDimension` metadata * make examples collapsible * renamed example folder * add orcid logo to editor info * fix reference * change precedence See discussion [here](bogovicj/ngff-rfc5-coordinate-transformation-examples#11 (comment)) * added examples for transformations with discrete axes * fix link to example * untrack autogenerated files * update affine examples and fix variable ordering * Fixed scale examples * removed example from additional details * specify affines/rotations as 2D matrices in parameter table * renamed coordinate transformations schema * Refactor rotation property to use `mtxFlatOrNested` * Delete schemas.md * remove `mtxFloatOrNested` affine/rotation matrices should always be 2D * "zarr array" instead of "binary data" * WIP: Update rfc5 schemas (#1) I'm merging this so that all necessary changes regarding the addition of rfc5-stuff to the main branch of the ngff-spec repo can be in one place. This branch was supposed to be a break-out to keep the commit-history of ome#17 clean. * Update input/output to input_axes/output_axes in schema * Add description and required field to byDimension * Update mapAxis schema to use integer array * Add path and interpolation to displacements schema The displacements object now includes a required 'path' property for specifying the zarr array location and an 'interpolation' property with supported methods. This enhances the schema's ability to describe displacement fields and their application. * Add path and interpolation to coordinates schema Introduces 'path' and 'interpolation' properties to the 'coordinates' object in the schema, specifying the location of the coordinate field and the interpolation method to use. The 'path' property is now required. * only allow paths, no URLs * move required fields to correct places * name musnt't be empty * added axis types to schema * Added descriptions to schemas * updated versions to 0.6dev2 * fix paths and versions * pull schema from correct location * Added action to run the tests * update config reference * update versions in test suite * Revert "update config reference" This reverts commit ff3fedd. * update all version references to "0.6dev2" * update version reference * at least two spatial axes * allow any axis type * update version reference * Add maxItems constraint to axes schema Set a maximum of 5 items for the axes array in the schema to enforce limits on the number of axes allowed. * Refactor image schema for coordinate transformations Refactors the definition of coordinateTransformations and coordinateSystems to use inline array schemas with stricter constraints. Adds a new multiscale_coordinateTransformations definition to support scale and translate transformations for multiscale datasets. * Update to NGFF 0.6dev2 and refactor coordinate systems Updated example and test JSON files to use the NGFF 0.6dev2 specification. Replaced 'axes' with 'coordinateSystems', added explicit 'input' and 'output' fields to coordinateTransformations, and restructured transformation chains for clarity and compliance with the new spec. * fix schema resolution * sync PR with latest RFC5 proposal (#2) Co-authored-by: Will Moore <900055+will-moore@users.noreply.github.com> Co-authored-by: David Stansby <d.stansby@ucl.ac.uk> Co-authored-by: Davis Bennett <davis.v.bennett@gmail.com> * fix links * fix schema resolution * split tests into separate files; add conformance test script * Conformance testing docs Also minor refactor test_validation * Add $schema to strict schemas * Add jsonschema_dingus * replaced `0.6dev2` by `0.6.dev2` --------- Co-authored-by: Will Moore <900055+will-moore@users.noreply.github.com> Co-authored-by: David Stansby <d.stansby@ucl.ac.uk> Co-authored-by: Davis Bennett <davis.v.bennett@gmail.com> Co-authored-by: Chris Barnes <chris.barnes@gerbi-gmb.de>
1 parent da4606b commit 657ff11

181 files changed

Lines changed: 7374 additions & 49 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,78 @@ address issues of scalability and interoperability.
55

66
This repository contains the central [specification text](./ngff_spec/specification.md),
77
a comprehensive list of [metadata examples](./ngff_spec/examples)
8-
as well as [json schemas](./ngff_spec/schemas) to validate written ome-zarr image data.
8+
as well as [json schemas](./ngff_spec/schemas) to validate written ome-zarr image data.
99

1010
The built documentation including contribution hints can be found **[here](https://ngff-spec.readthedocs.io/en/latest/specification.html)**.
11+
12+
## Conformance tests
13+
14+
Conformance can be tested at several levels.
15+
16+
1. Validating that individual fields of a zarr attributes object are valid.
17+
2. Validating a single zarr attributes object (i.e. containing OME-Zarr metadata)
18+
19+
- Validates that correct data can be represented, and that internally inconsistent data can be caught
20+
- Cannot validate references to other objects in the zarr hierarchy
21+
- Cannot validate conformance to other zarr metadata e.g. array data type, dimensionality
22+
23+
3. Validating a metadata-only zarr hierarchy
24+
25+
- Can validate references to other objects and other zarr metadata
26+
- Cannot validate values e.g. the invertibility of an affine matrix defined as a zarr array
27+
28+
4. Validating a zarr hierarchy with data
29+
30+
This repository contains
31+
32+
- JSON schemas which handle level 1
33+
- a set of test zarr attributes JSON for level 2 ([`./tests/attributes`](./tests/attributes/))
34+
- a set of metadata-only zarr hierarchies for level 3 ([`./tests/zarr`](./tests/zarr/))
35+
36+
as well as a tool for feeding these test cases into an external validator.
37+
38+
### Testing tool
39+
40+
See [`ome_zarr_conformance.py`](./ome_zarr_conformance.py).
41+
42+
Run it in either `attributes` or `zarr` mode, optionally with filters for test names or types.
43+
44+
Wrap your own OME-Zarr implementation in a
45+
["dingus"](https://talk.commonmark.org/t/origin-of-the-usage-for-dingus/1226) CLI,
46+
which takes as its last argument the path to either
47+
48+
- attributes mode: a JSON file representing zarr attributes (i.e. containing OME-Zarr metadata)
49+
- zarr mode: a zarr hierarchy root on the file system (i.e. a directory containing `zarr.json`)
50+
51+
The dingus should print to STDOUT a JSON object with the keys:
52+
53+
- `"valid"`: boolean, whether this is valid
54+
- optionally `"message"`: string, free text describing the success/ failure
55+
56+
Call the tool like
57+
58+
```sh
59+
python3 ./ome_zarr_conformance.py attributes -- path/to/my/dingus -dingusArg +argValue 10
60+
```
61+
62+
Each call to the dingus will then look like
63+
64+
```sh
65+
>>> path/to/my/dingus -dingusArg +argValue 10 /home/you/ngff-spec/tests/attributes/spec/valid/custom_type_axes.json
66+
67+
{"valid": true}
68+
```
69+
70+
`ome_zarr_conformance.py` will parse the JSON output and format the results of all requested tests in a tab-separated table.
71+
72+
Full usage information is available with `./ome_zarr_conformance.py --help`.
73+
74+
### JSON Schema tests
75+
76+
You can use the conformance testing tool to test JSON Schema-based validation with
77+
78+
```sh
79+
>>> ./ome_zarr_conformance.py attributes -- uv run jsonschema_dingus.py attributes
80+
```
81+
82+
Some failures are expected as JSON Schema can only handle level 1 validation.

jsonschema_dingus.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env python3
2+
# /// script
3+
# dependencies = [
4+
# "jsonschema",
5+
# "referencing",
6+
# ]
7+
# ///
8+
from __future__ import annotations
9+
from dataclasses import dataclass
10+
from pathlib import Path
11+
import json
12+
from argparse import ArgumentParser
13+
from typing import Any, Self
14+
15+
from referencing import Registry, Resource
16+
from jsonschema import Draft202012Validator as Validator
17+
from jsonschema.exceptions import ValidationError
18+
19+
HERE = Path(__file__).resolve().parent
20+
SCHEMA_DIR = HERE / "ngff_spec" / "schemas"
21+
22+
23+
@dataclass
24+
class SchemasInfo:
25+
generic_id: str
26+
base_url: str
27+
registry: Registry
28+
29+
@classmethod
30+
def load(cls) -> Self:
31+
"""Get the ID of the top-level schema, and the mapping of schema IDs to objects"""
32+
registry = Registry()
33+
generic = None
34+
base_url = None
35+
for p in SCHEMA_DIR.glob("*.schema*"):
36+
schema = json.loads(p.read_text())
37+
resource = Resource.from_contents(schema)
38+
registry = resource @ registry
39+
40+
schema_id = resource.id()
41+
if schema_id is None:
42+
raise RuntimeError("schema has no ID")
43+
if p.stem == "ome_zarr":
44+
generic = schema_id
45+
base_url = generic.split("/schemas/")[0]
46+
47+
if generic is None or base_url is None:
48+
raise RuntimeError("Could not find generic ome_zarr schema")
49+
50+
return cls(generic, base_url, registry)
51+
52+
53+
def main(raw_args=None):
54+
parser = ArgumentParser()
55+
parser.add_argument("mode", choices=["attributes", "zarr"])
56+
parser.add_argument("path", type=Path)
57+
58+
args = parser.parse_args(raw_args)
59+
60+
p: Path = args.path
61+
attrs: None | dict[str, Any] = None
62+
match args.mode:
63+
case "attributes":
64+
attrs = json.loads(p.read_text())
65+
case "zarr":
66+
attrs = json.loads(p.joinpath("zarr.json").read_text())["attributes"]
67+
case _:
68+
raise RuntimeError("unreachable")
69+
70+
if attrs is None:
71+
raise RuntimeError("unreachable")
72+
73+
schemas = SchemasInfo.load()
74+
75+
generic_schema = schemas.registry.get(schemas.generic_id)
76+
if generic_schema is None:
77+
raise RuntimeError("could not find generic schema")
78+
79+
validator = Validator(
80+
generic_schema.contents,
81+
registry=schemas.registry,
82+
)
83+
84+
result = dict()
85+
try:
86+
validator.validate(attrs)
87+
result["valid"] = True
88+
except ValidationError as e:
89+
result["valid"] = False
90+
result["message"] = str(e)
91+
92+
print(json.dumps(result))
93+
94+
95+
if __name__ == "__main__":
96+
main()

ngff_spec/pre_build.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def build_json_examples():
7474
def build_json_schemas():
7575
from json_schema_for_humans.generate import generate_from_filename
7676
from json_schema_for_humans.generation_configuration import GenerationConfiguration
77+
import json
7778

7879
schema_source_dir = 'schemas'
7980
output_directory = '_generated/schemas'

ngff_spec/schemas/strict_coordinate_systems.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
23
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_coordinate_systems.schema",
34
"allOf" : [
45
{

ngff_spec/schemas/strict_image.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
23
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_image.schema",
34
"allOf": [
45
{

ngff_spec/schemas/strict_label.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
23
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_label.schema",
34
"allOf": [
45
{
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_ome_zarr.schema",
4+
"anyOf": [
5+
{
6+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/bf2raw.schema"
7+
},
8+
{
9+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_image.schema"
10+
},
11+
{
12+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_label.schema"
13+
},
14+
{
15+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/ome.schema"
16+
},
17+
{
18+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_plate.schema"
19+
},
20+
{
21+
"$ref": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_well.schema"
22+
}
23+
]
24+
}

ngff_spec/schemas/strict_plate.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
23
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_plate.schema",
34
"allOf": [
45
{

ngff_spec/schemas/strict_well.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
23
"$id": "https://ngff.openmicroscopy.org/0.6.dev2/schemas/strict_well.schema",
34
"allOf": [
45
{

0 commit comments

Comments
 (0)