diff --git a/0.4/examples/label_strict/.config.json b/0.4/examples/label_strict/.config.json new file mode 100644 index 00000000..e7329dc9 --- /dev/null +++ b/0.4/examples/label_strict/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/strict_label.schema" +} diff --git a/0.4/examples/label_strict/colors_properties.json b/0.4/examples/label_strict/colors_properties.json new file mode 100644 index 00000000..2a14cbe4 --- /dev/null +++ b/0.4/examples/label_strict/colors_properties.json @@ -0,0 +1,29 @@ +{ + "image-label": { + "version": "0.4", + "colors": [ + { + "label-value": 1, + "rgba": [255, 255, 255, 255] + }, + { + "label-value": 4, + "rgba": [0, 255, 255, 128] + } + ], + "properties": [ + { + "label-value": 1, + "area (pixels)": 1200, + "class": "foo" + }, + { + "label-value": 4, + "area (pixels)": 1650 + } + ], + "source": { + "image": "../../" + } + } +} diff --git a/0.4/index.bs b/0.4/index.bs index a0c3f83d..18a6656f 100644 --- a/0.4/index.bs +++ b/0.4/index.bs @@ -375,63 +375,37 @@ in which each unique pixel value represents a separate segmented object. `image-label` groups MUST also contain `multiscales` metadata and the two "datasets" series MUST have the same number of entries. -The `colors` key defines a list of JSON objects describing the unique label -values. Each entry in the list MUST contain the key "label-value" with the -pixel value for that label. Additionally, the "rgba" key MAY be present, the -value for which is an RGBA unsigned-int 4-tuple: `[uint8, uint8, uint8, uint8]` -All `label-value`s must be unique. Clients who choose to not throw an error -should ignore all except the _last_ entry. - -Some implementations may represent overlapping labels by using a specially assigned +The `image-label` dictionary SHOULD contain a `colors` key whose value MUST be a +list of JSON objects describing the unique label values. Each color object MUST +contain the `label-value` key whose value MUST be an integer specifying the +pixel value for that label. It MAY contain an `rgba` key whose value MUST be an array +of four integers between 0 and 255 `[uint8, uint8, uint8, uint8]` specifying the label +color as RGBA. All the values under the `label-value` key MUST be unique. Clients +who choose to not throw an error SHOULD ignore all except the _last_ entry. + +Some implementations MAY represent overlapping labels by using a specially assigned value, for example the highest integer available in the pixel range. -The `properties` key defines a list of JSON objects which also describes the unique -label values. Each entry in the list MUST contain the key "label-value" with the -pixel value for that label. Additionally, an arbitrary number of key-value pairs +The `image-label` dictionary MAY contain a `properties` key whose value MUST be a +list of JSON objects which also describes the unique label values. Each property object +MUST contain the `label-value` key whose value MUST be an integer specifying the pixel +value for that label. Additionally, an arbitrary number of key-value pairs MAY be present for each label value denoting associated metadata. Not all label values must share the same key-value pairs within the properties list. -The `source` key is an optional dictionary which contains information on the -image the label is associated with. If included it MAY include a key `image` -whose value is the relative path to a Zarr image group. The default value is -"../../" since most labels are stored under a subgroup named "labels/" (see -above). +The `image-label` dictionary MAY contain a `source` key whose value MUST be a JSON +object containing information on the image the label is associated with. If included, +it MAY include a key `image` whose value MUST be a string specifying the relative +path to a Zarr image group. The default value is "../../" since most labels are stored +under a subgroup named "labels/" (see above). +The `image-label` dictionary SHOULD contain a `version` key whose value MUST be a string +specifying the version of the image-label specification. -```json -"image-label": - { - "version": "0.4", - "colors": [ - { - "label-value": 1, - "rgba": [255, 255, 255, 0] - }, - { - "label-value": 4, - "rgba": [0, 255, 255, 128] - }, - ... - ], - "properties": [ - { - "label-value": 1, - "area (pixels)": 1200, - "class": "foo" - - }, - { - "label-value": 4, - "area (pixels)": 1650 - }, - ... - ] - }, - "source": { - "image": "../../" - } -] -``` +
+path: examples/label_strict/colors_properties.json
+highlight: json
+
"plate" metadata {#plate-md} ---------------------------- diff --git a/0.4/schemas/label.schema b/0.4/schemas/label.schema new file mode 100644 index 00000000..1629d0f9 --- /dev/null +++ b/0.4/schemas/label.schema @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/label.schema", + "title": "OME-NGFF labelled image schema", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "image-label": { + "type": "object", + "properties": { + "colors": { + "description": "The colors for this label image", + "type": "array", + "items": { + "type": "object", + "properties": { + "label-value": { + "description": "The value of the label", + "type": "number" + }, + "rgba": { + "description": "The RGBA color stored as an array of four integers between 0 and 255", + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 4, + "maxItems": 4 + } + }, + "required": [ + "label-value" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "properties": { + "description": "The properties for this label image", + "type": "array", + "items": { + "type": "object", + "properties": { + "label-value": { + "description": "The pixel value for this label", + "type": "integer" + } + }, + "required": [ + "label-value" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "source": { + "description": "The source of this label image", + "type": "object", + "properties": { + "image": { + "type": "string" + } + } + }, + "version": { + "description": "The version of the specification", + "type": "string", + "enum": [ + "0.4" + ] + } + } + } + } +} diff --git a/0.4/schemas/strict_label.schema b/0.4/schemas/strict_label.schema new file mode 100644 index 00000000..af9090da --- /dev/null +++ b/0.4/schemas/strict_label.schema @@ -0,0 +1,18 @@ +{ + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/strict_label.schema", + "allOf": [ + { + "$ref": "https://ngff.openmicroscopy.org/0.4/schemas/label.schema" + }, + { + "properties": { + "image-label": { + "required": [ + "version", + "colors" + ] + } + } + } + ] +} diff --git a/0.4/tests/label_suite.json b/0.4/tests/label_suite.json new file mode 100644 index 00000000..634225c8 --- /dev/null +++ b/0.4/tests/label_suite.json @@ -0,0 +1,131 @@ +{ + "description": "Tests for the image-label JSON schema", + "schema": { + "id": "schemas/label.schema" + }, + "tests": [ + { + "formerly": "image-label/minimal", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": true + }, + { + "formerly": "image-label/minimal_properties", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ], + "properties": [ + { + "label-value": 1 + } + ] + } + }, + "valid": true + }, + { + "formerly": "image-label/empty_colors", + "data": { + "image-label": { + "colors": [] + } + }, + "valid": false + }, + { + "formerly": "image-label/empty_properties", + "data": { + "image-label": { + "properties": [] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_no_label_value", + "data": { + "image-label": { + "colors": [ + { + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/properties_no_label_value", + "data": { + "image-label": { + "properties": [ + { + "value": "foo" + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_rgba_length", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_rgba_type", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 500] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_duplicate", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + }, + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + } + ] +} diff --git a/0.4/tests/strict_label_suite.json b/0.4/tests/strict_label_suite.json new file mode 100644 index 00000000..a4ccf01d --- /dev/null +++ b/0.4/tests/strict_label_suite.json @@ -0,0 +1,31 @@ +{ + "description": "Tests for the strict image-label JSON schema", + "schema": { + "id": "schemas/strict_label.schema" + }, + "tests": [ + { + "formerly": "image-label/no_version", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/no_colors", + "data": { + "image-label": { + "version": "0.4" + } + }, + "valid": false + } + ] +} diff --git a/latest/examples/label_strict/.config.json b/latest/examples/label_strict/.config.json new file mode 100644 index 00000000..e7329dc9 --- /dev/null +++ b/latest/examples/label_strict/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/strict_label.schema" +} diff --git a/latest/examples/label_strict/colors_properties.json b/latest/examples/label_strict/colors_properties.json new file mode 100644 index 00000000..7f1d6f20 --- /dev/null +++ b/latest/examples/label_strict/colors_properties.json @@ -0,0 +1,29 @@ +{ + "image-label": { + "version": "0.5-dev", + "colors": [ + { + "label-value": 1, + "rgba": [255, 255, 255, 255] + }, + { + "label-value": 4, + "rgba": [0, 255, 255, 128] + } + ], + "properties": [ + { + "label-value": 1, + "area (pixels)": 1200, + "class": "foo" + }, + { + "label-value": 4, + "area (pixels)": 1650 + } + ], + "source": { + "image": "../../" + } + } +} diff --git a/latest/index.bs b/latest/index.bs index e2fc6bcf..3ed6d7d7 100644 --- a/latest/index.bs +++ b/latest/index.bs @@ -377,63 +377,37 @@ in which each unique pixel value represents a separate segmented object. `image-label` groups MUST also contain `multiscales` metadata and the two "datasets" series MUST have the same number of entries. -The `colors` key defines a list of JSON objects describing the unique label -values. Each entry in the list MUST contain the key "label-value" with the -pixel value for that label. Additionally, the "rgba" key MAY be present, the -value for which is an RGBA unsigned-int 4-tuple: `[uint8, uint8, uint8, uint8]` -All `label-value`s must be unique. Clients who choose to not throw an error -should ignore all except the _last_ entry. - -Some implementations may represent overlapping labels by using a specially assigned +The `image-label` dictionary SHOULD contain a `colors` key whose value MUST be a +list of JSON objects describing the unique label values. Each color object MUST +contain the `label-value` key whose value MUST be an integer specifying the +pixel value for that label. It MAY contain an `rgba` key whose value MUST be an array +of four integers between 0 and 255 `[uint8, uint8, uint8, uint8]` specifying the label +color as RGBA. All the values under the `label-value` key MUST be unique. Clients +who choose to not throw an error SHOULD ignore all except the _last_ entry. + +Some implementations MAY represent overlapping labels by using a specially assigned value, for example the highest integer available in the pixel range. -The `properties` key defines a list of JSON objects which also describes the unique -label values. Each entry in the list MUST contain the key "label-value" with the -pixel value for that label. Additionally, an arbitrary number of key-value pairs +The `image-label` dictionary MAY contain a `properties` key whose value MUST be a +list of JSON objects which also describes the unique label values. Each property object +MUST contain the `label-value` key whose value MUST be an integer specifying the pixel +value for that label. Additionally, an arbitrary number of key-value pairs MAY be present for each label value denoting associated metadata. Not all label values must share the same key-value pairs within the properties list. -The `source` key is an optional dictionary which contains information on the -image the label is associated with. If included it MAY include a key `image` -whose value is the relative path to a Zarr image group. The default value is -"../../" since most labels are stored under a subgroup named "labels/" (see -above). +The `image-label` dictionary MAY contain a `source` key whose value MUST be a JSON +object containing information on the image the label is associated with. If included, +it MAY include a key `image` whose value MUST be a string specifying the relative +path to a Zarr image group. The default value is "../../" since most labels are stored +under a subgroup named "labels/" (see above). +The `image-label` dictionary SHOULD contain a `version` key whose value MUST be a string +specifying the version of the image-label specification. -```json -"image-label": - { - "version": "0.5-dev", - "colors": [ - { - "label-value": 1, - "rgba": [255, 255, 255, 0] - }, - { - "label-value": 4, - "rgba": [0, 255, 255, 128] - }, - ... - ], - "properties": [ - { - "label-value": 1, - "area (pixels)": 1200, - "class": "foo" - - }, - { - "label-value": 4, - "area (pixels)": 1650 - }, - ... - ] - }, - "source": { - "image": "../../" - } -] -``` +
+path: examples/label_strict/colors_properties.json
+highlight: json
+
"plate" metadata {#plate-md} ---------------------------- diff --git a/latest/schemas/label.schema b/latest/schemas/label.schema new file mode 100644 index 00000000..8b23d577 --- /dev/null +++ b/latest/schemas/label.schema @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/latest/schemas/label.schema", + "title": "OME-NGFF labelled image schema", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "image-label": { + "type": "object", + "properties": { + "colors": { + "description": "The colors for this label image", + "type": "array", + "items": { + "type": "object", + "properties": { + "label-value": { + "description": "The value of the label", + "type": "number" + }, + "rgba": { + "description": "The RGBA color stored as an array of four integers between 0 and 255", + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 4, + "maxItems": 4 + } + }, + "required": [ + "label-value" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "properties": { + "description": "The properties for this label image", + "type": "array", + "items": { + "type": "object", + "properties": { + "label-value": { + "description": "The pixel value for this label", + "type": "integer" + } + }, + "required": [ + "label-value" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "source": { + "description": "The source of this label image", + "type": "object", + "properties": { + "image": { + "type": "string" + } + } + }, + "version": { + "description": "The version of the specification", + "type": "string", + "enum": [ + "0.5-dev" + ] + } + } + } + } +} diff --git a/latest/schemas/strict_label.schema b/latest/schemas/strict_label.schema new file mode 100644 index 00000000..c52dd51b --- /dev/null +++ b/latest/schemas/strict_label.schema @@ -0,0 +1,18 @@ +{ + "$id": "https://ngff.openmicroscopy.org/latest/schemas/strict_label.schema", + "allOf": [ + { + "$ref": "https://ngff.openmicroscopy.org/latest/schemas/label.schema" + }, + { + "properties": { + "image-label": { + "required": [ + "version", + "colors" + ] + } + } + } + ] +} diff --git a/latest/tests/label_suite.json b/latest/tests/label_suite.json new file mode 100644 index 00000000..634225c8 --- /dev/null +++ b/latest/tests/label_suite.json @@ -0,0 +1,131 @@ +{ + "description": "Tests for the image-label JSON schema", + "schema": { + "id": "schemas/label.schema" + }, + "tests": [ + { + "formerly": "image-label/minimal", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": true + }, + { + "formerly": "image-label/minimal_properties", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ], + "properties": [ + { + "label-value": 1 + } + ] + } + }, + "valid": true + }, + { + "formerly": "image-label/empty_colors", + "data": { + "image-label": { + "colors": [] + } + }, + "valid": false + }, + { + "formerly": "image-label/empty_properties", + "data": { + "image-label": { + "properties": [] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_no_label_value", + "data": { + "image-label": { + "colors": [ + { + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/properties_no_label_value", + "data": { + "image-label": { + "properties": [ + { + "value": "foo" + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_rgba_length", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_rgba_type", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 500] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/colors_duplicate", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + }, + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + } + ] +} diff --git a/latest/tests/strict_label_suite.json b/latest/tests/strict_label_suite.json new file mode 100644 index 00000000..9fe0cda2 --- /dev/null +++ b/latest/tests/strict_label_suite.json @@ -0,0 +1,31 @@ +{ + "description": "Tests for the strict image-label JSON schema", + "schema": { + "id": "schemas/strict_label.schema" + }, + "tests": [ + { + "formerly": "image-label/no_version", + "data": { + "image-label": { + "colors": [ + { + "label-value": 1, + "rgba": [0, 0, 0, 0] + } + ] + } + }, + "valid": false + }, + { + "formerly": "image-label/no_colors", + "data": { + "image-label": { + "version": "0.5-dev" + } + }, + "valid": false + } + ] +}