diff --git a/latest/examples/plate_strict/.config.json b/latest/examples/plate_strict/.config.json new file mode 100644 index 00000000..a49b1743 --- /dev/null +++ b/latest/examples/plate_strict/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/strict_plate.schema" +} diff --git a/latest/examples/plate_strict/plate_2wells.json b/latest/examples/plate_strict/plate_2wells.json new file mode 100644 index 00000000..3578798f --- /dev/null +++ b/latest/examples/plate_strict/plate_2wells.json @@ -0,0 +1,91 @@ +{ + "plate": { + "acquisitions": [ + { + "id": 1, + "maximumfieldcount": 1, + "name": "single acquisition", + "starttime": 1343731272000 + } + ], + "columns": [ + { + "name": "1" + }, + { + "name": "2" + }, + { + "name": "3" + }, + { + "name": "4" + }, + { + "name": "5" + }, + { + "name": "6" + }, + { + "name": "7" + }, + { + "name": "8" + }, + { + "name": "9" + }, + { + "name": "10" + }, + { + "name": "11" + }, + { + "name": "12" + } + ], + "field_count": 1, + "name": "sparse test", + "rows": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "D" + }, + { + "name": "E" + }, + { + "name": "F" + }, + { + "name": "G" + }, + { + "name": "H" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "C/5", + "rowIndex": 2, + "columnIndex": 4 + }, + { + "path": "D/7", + "rowIndex": 3, + "columnIndex": 6 + } + ] + } +} diff --git a/latest/examples/plate_strict/plate_6wells.json b/latest/examples/plate_strict/plate_6wells.json new file mode 100644 index 00000000..d2f06389 --- /dev/null +++ b/latest/examples/plate_strict/plate_6wells.json @@ -0,0 +1,72 @@ +{ + "plate": { + "acquisitions": [ + { + "id": 1, + "maximumfieldcount": 2, + "name": "Meas_01(2012-07-31_10-41-12)", + "starttime": 1343731272000 + }, + { + "id": 2, + "maximumfieldcount": 2, + "name": "Meas_02(201207-31_11-56-41)", + "starttime": 1343735801000 + } + ], + "columns": [ + { + "name": "1" + }, + { + "name": "2" + }, + { + "name": "3" + } + ], + "field_count": 4, + "name": "test", + "rows": [ + { + "name": "A" + }, + { + "name": "B" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + }, + { + "path": "A/2", + "rowIndex": 0, + "columnIndex": 1 + }, + { + "path": "A/3", + "rowIndex": 0, + "columnIndex": 2 + }, + { + "path": "B/1", + "rowIndex": 1, + "columnIndex": 0 + }, + { + "path": "B/2", + "rowIndex": 1, + "columnIndex": 1 + }, + { + "path": "B/3", + "rowIndex": 1, + "columnIndex": 2 + } + ] + } +} diff --git a/latest/examples/well_strict/.config.json b/latest/examples/well_strict/.config.json new file mode 100644 index 00000000..129ac69c --- /dev/null +++ b/latest/examples/well_strict/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/strict_well.schema" +} diff --git a/latest/examples/well_strict/well_2fields.json b/latest/examples/well_strict/well_2fields.json new file mode 100644 index 00000000..6f43a911 --- /dev/null +++ b/latest/examples/well_strict/well_2fields.json @@ -0,0 +1,15 @@ +{ + "well": { + "images": [ + { + "acquisition": 0, + "path": "0" + }, + { + "acquisition": 3, + "path": "1" + } + ], + "version": "0.5-dev" + } +} \ No newline at end of file diff --git a/latest/examples/well_strict/well_4fields.json b/latest/examples/well_strict/well_4fields.json new file mode 100644 index 00000000..c2285d53 --- /dev/null +++ b/latest/examples/well_strict/well_4fields.json @@ -0,0 +1,23 @@ +{ + "well": { + "images": [ + { + "acquisition": 1, + "path": "0" + }, + { + "acquisition": 1, + "path": "1" + }, + { + "acquisition": 2, + "path": "2" + }, + { + "acquisition": 2, + "path": "3" + } + ], + "version": "0.5-dev" + } +} \ No newline at end of file diff --git a/latest/index.bs b/latest/index.bs index 00b06c29..26bb77aa 100644 --- a/latest/index.bs +++ b/latest/index.bs @@ -496,173 +496,18 @@ custom attributes of the plate group under the `plate` key. For example the following JSON object defines a plate with two acquisitions and 6 wells (2 rows and 3 columns), containing up to 2 fields of view per acquisition. -```json -"plate": { - "acquisitions": [ - { - "id": 1, - "maximumfieldcount": 2, - "name": "Meas_01(2012-07-31_10-41-12)", - "starttime": 1343731272000 - }, - { - "id": 2, - "maximumfieldcount": 2, - "name": "Meas_02(201207-31_11-56-41)", - "starttime": 1343735801000 - } - ], - "columns": [ - { - "name": "1" - }, - { - "name": "2" - }, - { - "name": "3" - } - ], - "field_count": 4, - "name": "test", - "rows": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "version": "0.5-dev", - "wells": [ - { - "path": "A/1", - "rowIndex": 0, - "columnIndex": 0 - }, - { - "path": "A/2" - "rowIndex": 0, - "columnIndex": 1 - }, - { - "path": "A/3" - "rowIndex": 0, - "columnIndex": 2 - }, - { - "path": "B/1" - "rowIndex": 1, - "columnIndex": 0 - }, - { - "path": "B/2" - "rowIndex": 1, - "columnIndex": 1 - }, - { - "path": "B/3" - "rowIndex": 1, - "columnIndex": 2 - } - ] - } -``` +
+path: examples/plate_strict/plate_6wells.json
+highlight: json
+
The following JSON object defines a sparse plate with one acquisition and 2 wells in a 96 well plate, containing one field of view per acquisition. -```json -"plate": { - "acquisitions": [ - { - "id": 1, - "maximumfieldcount": 1, - "name": "single acquisition", - "starttime": 1343731272000 - }, - ], - "columns": [ - { - "name": "1" - }, - { - "name": "2" - }, - { - "name": "3" - }, - { - "name": "4" - }, - { - "name": "5" - }, - { - "name": "6" - }, - { - "name": "7" - }, - { - "name": "8" - }, - { - "name": "9" - }, - { - "name": "10" - }, - { - "name": "11" - }, - { - "name": "12" - } - ], - "field_count": 1, - "name": "sparse test", - "rows": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "D" - }, - { - "name": "E" - }, - { - "name": "F" - }, - { - "name": "G" - }, - { - "name": "H" - } - ], - "version": "0.1", - "wells": [ - { - "path": "C/5" - "rowIndex": 2, - "columnIndex": 4 - }, - { - "path": "D/7" - "rowIndex": 3, - "columnIndex": 6 - } - ] - } -``` +
+path: examples/plate_strict/plate_2wells.json
+highlight: json
+
"well" metadata {#well-md} -------------------------- @@ -687,49 +532,19 @@ For example the following JSON object defines a well with four fields of view. The first two fields of view were part of the first acquisition while the last two fields of view were part of the second acquisition. -```json -"well": { - "images": [ - { - "acquisition": 1, - "path": "0" - }, - { - "acquisition": 1, - "path": "1" - }, - { - "acquisition": 2, - "path": "2" - }, - { - "acquisition": 2, - "path": "3" - } - ], - "version": "0.5-dev" - } -``` +
+path: examples/well_strict/well_4fields.json
+highlight: json
+
The following JSON object defines a well with two fields of view in a plate with four acquisitions. The first field is part of the first acquisition, and the second field is part of the last acquisition. -```json -"well": { - "images": [ - { - "acquisition": 0, - "path": "0" - }, - { - "acquisition": 3, - "path": "1" - } - ], - "version": "0.1" -} -``` +
+path: examples/well_strict/well_2fields.json
+highlight: json
+
Specification naming style {#naming-style} ========================================== diff --git a/latest/schemas/plate.schema b/latest/schemas/plate.schema new file mode 100644 index 00000000..417f156d --- /dev/null +++ b/latest/schemas/plate.schema @@ -0,0 +1,136 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/plate.schema", + "title": "OME-NGFF plate schema", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "plate": { + "type": "object", + "properties": { + "acquisitions": { + "description": "The acquisitions for this plate", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "A unique identifier within the context of the plate", + "type": "integer", + "minimum": 0 + }, + "maximumfieldcount": { + "description": "The maximum number of fields of view for the acquisition", + "type": "integer", + "exclusiveMinimum": 0 + }, + "name": { + "description": "The name of the acquisition", + "type": "string" + }, + "starttime": { + "description": "The start timestamp of the acquisition, expressed as epoch time i.e. the number seconds since the Epoch", + "type": "integer", + "minimum": 0 + }, + "endtime": { + "description": "The end timestamp of the acquisition, expressed as epoch time i.e. the number seconds since the Epoch", + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "id" + ] + } + }, + "version": { + "description": "The version of the specification", + "type": "string", + "enum": [ + "0.5-dev" + ] + }, + "field_count": { + "description": "The maximum number of fields per view across all wells", + "type": "integer", + "exclusiveMinimum": 0 + }, + "name": { + "description": "The name of the plate", + "type": "string" + }, + "columns": { + "description": "The columns of the plate", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The column name", + "type": "string", + "pattern": "^[A-Za-z0-9]+$" + } + }, + "required": [ + "name" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "rows": { + "description": "The rows of the plate", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "description": "The row name", + "type": "string", + "pattern": "^[A-Za-z0-9]+$" + } + }, + "required": [ + "name" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "wells": { + "description": "The wells of the plate", + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "description": "The path to the well subgroup", + "type": "string", + "pattern": "^[A-Za-z0-9]+/[A-Za-z0-9]+$" + }, + "rowIndex": { + "description": "The index of the well in the rows list", + "type": "integer", + "minimum": 0 + }, + "columnIndex": { + "description": "The index of the well in the columns list", + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "path", "rowIndex", "columnIndex" + ] + }, + "minItems": 1, + "uniqueItems": true + } + }, + "required": [ + "columns", "rows", "wells" + ] + } + } +} diff --git a/latest/schemas/strict_plate.schema b/latest/schemas/strict_plate.schema new file mode 100644 index 00000000..5a88ab72 --- /dev/null +++ b/latest/schemas/strict_plate.schema @@ -0,0 +1,28 @@ +{ + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/strict_plate.schema", + "allOf": [ + { + "$ref": "https://ngff.openmicroscopy.org/0.4/schemas/plate.schema" + }, + { + "properties": { + "plate": { + "properties": { + "acquisitions": { + "items": { + "required": [ + "name", + "maximumfieldcount" + ] + } + } + }, + "required": [ + "name", + "version" + ] + } + } + } + ] +} diff --git a/latest/schemas/strict_well.schema b/latest/schemas/strict_well.schema new file mode 100644 index 00000000..1e200294 --- /dev/null +++ b/latest/schemas/strict_well.schema @@ -0,0 +1,17 @@ +{ + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/strict_well.schema", + "allOf": [ + { + "$ref": "https://ngff.openmicroscopy.org/0.4/schemas/well.schema" + }, + { + "properties": { + "well": { + "required": [ + "version" + ] + } + } + } + ] +} diff --git a/latest/schemas/well.schema b/latest/schemas/well.schema new file mode 100644 index 00000000..891abd05 --- /dev/null +++ b/latest/schemas/well.schema @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/0.4/schemas/well.schema", + "title": "OME-NGFF well schema", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "well": { + "type": "object", + "properties": { + "images": { + "description": "The fields of view for this well", + "type": "array", + "items": { + "type": "object", + "properties": { + "acquisition": { + "description": "A unique identifier within the context of the plate", + "type": "integer" + }, + "path": { + "description": "The path for this field of view subgroup", + "type": "string", + "pattern": "^[A-Za-z0-9]+$" + } + }, + "required": [ + "path" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "version": { + "description": "The version of the specification", + "type": "string", + "enum": [ + "0.5-dev" + ] + } + }, + "required": [ + "images" + ] + } + } +} diff --git a/latest/tests/plate_suite.json b/latest/tests/plate_suite.json new file mode 100644 index 00000000..c19ad60e --- /dev/null +++ b/latest/tests/plate_suite.json @@ -0,0 +1,819 @@ +{ + "description": "Tests for the plate JSON schema", + "schema": { + "id": "schemas/plate.schema" + }, + "tests": [ + { + "formerly": "plate/minimal_no_acquisitions", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": true + }, + { + "formerly": "plate/minimal_acquisitions", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": true + }, + { + "formerly": "plate/missing_rows", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/empty_rows", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/duplicate_rows", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + }, + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_columns", + "data": { + "plate": { + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/empty_columns", + "data": { + "plate": { + "columns": [], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/duplicate_columns", + "data": { + "plate": { + "columns": [ + { + "name": "A" + }, + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_wells", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/empty_wells", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": {} + } + }, + "valid": false + }, + { + "formerly": "plate/duplicate_rows", + "data": { + "plate": { + "columns": [ + { + "name": "A" + }, + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + }, + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_column_name", + "data": { + "plate": { + "columns": [ + { + "concentration": 10 + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_row_name", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "concentration": 10 + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_well_path", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_well_rowIndex", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_well_columnIndex", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/well_1group", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A1", + "rowIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/well_3groups", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "plate/A/1", + "rowIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/invalid_version", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ], + "version": "foo" + } + }, + "valid": false + }, + { + "formerly": "plate/non_alphanumeric_column", + "data": { + "plate": { + "columns": [ + { + "name": "A-1" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A-1/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/non_alphanumeric_row", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "A1" + } + ], + "wells": [ + { + "path": "A/A1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": true + }, + { + "formerly": "plate/missing_acquisition_id", + "data": { + "plate": { + "acquisitions": [ + { + "maximumfieldcount": 1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/non_integer_acquisition_id", + "data": { + "plate": { + "acquisitions": [ + { + "id": "0" + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/negative_acquisition_id", + "data": { + "plate": { + "acquisitions": [ + { + "id": -1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/non_integer_acquisition_maximumfieldcount", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "maximumfieldcount": "0" + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/acquisition_zero_maximumfieldcount", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "maximumfieldcount": 0 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/acquisition_noninteger_starttime", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "starttime": "2022-05-13T13:48:06+00:00" + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/acquisition_negative_starttime", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "starttime": -1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/acquisition_noninteger_endtime", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "endtime": "2022-05-13T13:48:06+00:00" + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/negative_endtime", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "endtime": -1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/zero_field_count", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "field_count": 0, + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + } + ] +} diff --git a/latest/tests/strict_plate_suite.json b/latest/tests/strict_plate_suite.json new file mode 100644 index 00000000..931cf7e7 --- /dev/null +++ b/latest/tests/strict_plate_suite.json @@ -0,0 +1,187 @@ +{ + "description": "Tests for the strict plate JSON schema", + "schema": { + "id": "schemas/strict_plate.schema" + }, + "tests": [ + { + "formerly": "plate/strict_no_acquisitions", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "name": "test plate", + "rows": [ + { + "name": "1" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": true + }, + { + "formerly": "plate/missing_name", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "rows": [ + { + "name": "1" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_version", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } + ], + "name": "test plate", + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/strict_acquisitions", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "name": "0", + "maximumfieldcount": 1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "name": "test plate", + "rows": [ + { + "name": "1" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": true + }, + { + "formerly": "plate/missing_acquisition_name", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "maximumfieldcount": 1 + } + ], + "columns": [ + { + "name": "A" + } + ], + "name": "test plate", + "rows": [ + { + "name": "1" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_acquisition_maximumfieldcount", + "data": { + "plate": { + "acquisitions": [ + { + "id": 0, + "name": "0" + } + ], + "columns": [ + { + "name": "A" + } + ], + "name": "test plate", + "rows": [ + { + "name": "1" + } + ], + "version": "0.5-dev", + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] + } + }, + "valid": false + } + ] +} diff --git a/latest/tests/strict_well_suite.json b/latest/tests/strict_well_suite.json new file mode 100644 index 00000000..edfb2936 --- /dev/null +++ b/latest/tests/strict_well_suite.json @@ -0,0 +1,50 @@ +{ + "description": "Tests for the strict well JSON schema", + "schema": { + "id": "schemas/strict_well.schema" + }, + "tests": [ + { + "formerly": "well/strict_no_acquisitions", + "data": { + "well": { + "images": [ + { + "path": "0" + } + ], + "version": "0.5-dev" + } + }, + "valid": true + }, + { + "formerly": "plate/missing_version", + "data": { + "well": { + "images": [ + { + "path": "0" + } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/strict_acquisitions", + "data": { + "well": { + "images": [ + { + "acquisition": 0, + "path": "0" + } + ], + "version": "0.5-dev" + } + }, + "valid": true + } + ] +} diff --git a/latest/tests/test_validation.py b/latest/tests/test_validation.py index 83f49911..9e441fad 100644 --- a/latest/tests/test_validation.py +++ b/latest/tests/test_validation.py @@ -1,5 +1,6 @@ import json import glob +import os from dataclasses import dataclass from typing import List @@ -9,11 +10,15 @@ from jsonschema import RefResolver, Draft202012Validator as Validator from jsonschema.exceptions import ValidationError +schema_store = {} +for schema_filename in glob.glob("schemas/*"): + with open(schema_filename) as f: + schema = json.load(f) + schema_store[schema["$id"]] = schema @dataclass class Suite: schema: dict - schema_store: dict data: dict valid: bool = True @@ -54,7 +59,7 @@ def pytest_generate_tests(metafunc): schema = json.load(f) for test in suite["tests"]: ids.append("validate_" + str(test["formerly"]).split("/")[-1][0:-5]) - suites.append(Suite(schema, {schema["$id"]: schema}, test["data"], test["valid"])) + suites.append(Suite(schema, test["data"], test["valid"])) # Examples for config_filename in glob.glob("examples/*/.config.json"): @@ -63,13 +68,14 @@ def pytest_generate_tests(metafunc): schema = data["schema"] with open(schema) as f: schema = json.load(f) - for filename in glob.glob("examples/*/*.json"): + example_folder = os.path.dirname(config_filename) + for filename in glob.glob(f"{example_folder}/*.json"): with open(filename) as f: # Strip comments data = ''.join(line for line in f if not line.lstrip().startswith('//')) data = json.loads(data) ids.append("example_" + str(filename).split("/")[-1][0:-5]) - suites.append(Suite(schema, {schema["$id"]: schema}, data, True)) # Assume true + suites.append(Suite(schema, data, True)) # Assume true metafunc.parametrize("suite", suites, ids=ids, indirect=True) @@ -80,6 +86,6 @@ def suite(request): def test_run(suite): - resolver = RefResolver.from_schema(suite.schema, store=suite.schema_store) + resolver = RefResolver.from_schema(suite.schema, store=schema_store) validator = Validator(suite.schema, resolver=resolver) suite.validate(validator) diff --git a/latest/tests/well_suite.json b/latest/tests/well_suite.json new file mode 100644 index 00000000..0f752551 --- /dev/null +++ b/latest/tests/well_suite.json @@ -0,0 +1,88 @@ +{ + "description": "Tests for the well JSON schema", + "schema": { + "id": "schemas/well.schema" + }, + "tests": [ + { + "formerly": "well/minimal_no_acquisition", + "data": { + "well": { + "images": [ + { + "path": "0" + } + ] + } + }, + "valid": true + }, + { + "formerly": "well/minimal_acquisitions", + "data": { + "well": { + "images": [ + { + "acquisition": 1, + "path": "0" + } + ] + } + }, + "valid": true + }, + { + "formerly": "well/empty_images", + "data": { + "well": { + "images": [] + } + }, + "valid": false + }, + { + "formerly": "well/duplicate_images", + "data": { + "well": { + "images": [ + { + "path": "0" + }, + { + "path": "0" + } + ] + } + }, + "valid": false + }, + { + "formerly": "well/invalid_version", + "data": { + "well": { + "images": [ + { + "path": "0" + } + ], + "version": "foo" + } + }, + "valid": false + }, + { + "formerly": "well/non_integer_acquisition_id", + "data": { + "well": { + "images": [ + { + "acquisition": "0", + "path": "0" + } + ] + } + }, + "valid": false + } + ] +}