+Title: OME-Zarr specification +Shortname: ome-zarr +Level: 1 +Status: w3c/CG-FINAL +TR: https://ngff.openmicroscopy.org/0.5/ +URL: https://ngff.openmicroscopy.org/0.6-dev/ +Repository: https://github.com/ome/ngff +Issue Tracking: Forums https://forum.image.sc/tag/ome-ngff +Logo: http://www.openmicroscopy.org/img/logos/ome-logomark.svg +Local Boilerplate: header yes, copyright yes +Boilerplate: style-darkmode off +Markup Shorthands: markdown yes +Editor: Josh Moore, German BioImaging e.V., https://gerbi-gmb.de/, https://orcid.org/0000-0003-4028-811X +Text Macro: NGFFVERSION 0.5 +Abstract: This document contains next-generation file format (NGFF) +Abstract: specifications for storing bioimaging data in the cloud. +Abstract: All specifications are submitted to the https://image.sc community for review. +Status Text: The current released version of this specification is 0.5. Migration scripts +Status Text: will be provided between numbered versions. Data written with these latest changes +Status Text: (an "editor's draft") will not necessarily be supported. ++ +OME-Zarr specification {#ome-zarr} +---------------------------------- + +The conventions and specifications defined in this document are designed to +enable next-generation file formats to represent the same bioimaging data +that can be represented in \[OME-TIFF](http://www.openmicroscopy.org/ome-files/) +and beyond. + +Document conventions +-------------------- + +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, +“RECOMMENDED”, “MAY”, and “OPTIONAL” are to be interpreted as described in +[RFC 2119](https://tools.ietf.org/html/rfc2119). + +
+Transitional metadata is added to the specification with the +intention of removing it in the future. Implementations may be expected (MUST) or +encouraged (SHOULD) to support the reading of the data, but writing will usually +be optional (MAY). Examples of transitional metadata include custom additions by +implementations that are later submitted as a formal specification. (See [[#bf2raw]]) +
+ +Some of the JSON examples in this document include comments. However, these are only for +clarity purposes and comments MUST NOT be included in JSON objects. + +Storage format {#storage-format} +================================ + +OME-Zarr is implemented using the Zarr format as defined by the +[version 3 of the Zarr specification](https://zarr-specs.readthedocs.io/en/latest/v3/core/v3.0.html). +All features of the Zarr format including codecs, chunk grids, chunk +key encodings, data types and storage transformers may be used with +OME-Zarr unless explicitly disallowed in this specification. + +An overview of the layout of an OME-Zarr fileset should make +understanding the following metadata sections easier. The hierarchy +is represented here as it would appear locally but could equally +be stored on a web server to be accessed via HTTP or in object storage +like S3 or GCS. + +Images {#image-layout} +---------------------- + +The following layout describes the expected Zarr hierarchy for images with +multiple levels of resolutions and optionally associated labels. +Note that the number of dimensions is variable between 2 and 5 and that axis names are arbitrary, see [[#multiscale-md]] for details. + +
+├── 123.zarr # One OME-Zarr image (id=123).
+│ ...
+│
+└── 456.zarr # Another OME-Zarr image (id=456).
+ │
+ ├── zarr.json # Each image is a Zarr group of other groups and arrays.
+ │ # Group level attributes are stored in the `zarr.json` file and include
+ │ # "multiscales" and "omero" (see below).
+ │
+ ├── 0 # Each multiscale level is stored as a separate Zarr array,
+ │ ... # which is a folder containing chunk files which compose the array.
+ ├── n # The name of the array is arbitrary with the ordering defined by
+ │ │ # by the "multiscales" metadata, but is often a sequence starting at 0.
+ │ │
+ │ ├── zarr.json # All image arrays must be up to 5-dimensional
+ │ │ # with the axis of type time before type channel, before spatial axes.
+ │ │
+ │ └─ ... # Chunks are stored conforming to the Zarr array specification and
+ │ # metadata as specified in the array's `zarr.json`.
+ │
+ └── labels
+ │
+ ├── zarr.json # The labels group is a container which holds a list of labels to make the objects easily discoverable
+ │ # All labels will be listed in `zarr.json` e.g. `{ "labels": [ "original/0" ] }`
+ │ # Each dimension of the label should be either the same as the
+ │ # corresponding dimension of the image, or `1` if that dimension of the label
+ │ # is irrelevant.
+ │
+ └── original # Intermediate folders are permitted but not necessary and currently contain no extra metadata.
+ │
+ └── 0 # Multiscale, labeled image. The name is unimportant but is registered in the "labels" group above.
+ ├── zarr.json # Zarr Group which is both a multiscaled image as well as a labeled image.
+ │ # Metadata of the related image and as well as display information under the "image-label" key.
+ │
+ ├── 0 # Each multiscale level is stored as a separate Zarr array, as above, but only integer values
+ └── ... # are supported.
+
+
+
+
+
+High-content screening {#hcs-layout}
+------------------------------------
+
+The following specification defines the hierarchy for a high-content screening
+dataset. Three groups MUST be defined above the images:
+
+- the group above the images defines the well and MUST implement the
+ [well specification](#well-md). All images contained in a well are fields
+ of view of the same well
+- the group above the well defines a row of wells
+- the group above the well row defines an entire plate i.e. a two-dimensional
+ collection of wells organized in rows and columns. It MUST implement the
+ [plate specification](#plate-md)
+
+A well row group SHOULD NOT be present if there are no images in the well row.
+A well group SHOULD NOT be present if there are no images in the well.
+
+
++. +│ +└── 5966.zarr # One OME-Zarr plate (id=5966) + ├── zarr.json # Implements "plate" specification + ├── A # First row of the plate + │ ├── zarr.json + │ │ + │ ├── 1 # First column of row A + │ │ ├── zarr.json # Implements "well" specification + │ │ │ + │ │ ├── 0 # First field of view of well A1 + │ │ │ │ + │ │ │ ├── zarr.json # Implements "multiscales", "omero" + │ │ │ ├── 0 # Resolution levels + │ │ │ ├── ... + │ │ │ └── labels # Labels (optional) + │ │ └── ... # Other fields of view + │ └── ... # Other columns + └── ... # Other rows ++ +OME-Zarr Metadata {#metadata} +============================= + +The "OME-Zarr Metadata" contains metadata keys as specified below +for discovering certain types of data, especially images. + +The OME-Zarr Metadata is stored in the various `zarr.json` files throughout the above array +hierarchy. In this file, the metadata is stored under the namespaced key +`ome` in `attributes`. +The version of the OME-Zarr Metadata is denoted as a string in the `version` attribute within the `ome` namespace. + +The OME-Zarr Metadata version MUST be consistent within a hierarchy. + +```json +{ + ... + "attributes": { + "ome": { + "version": "0.5", + ... + } + } +} +``` + +"axes" metadata {#axes-md} +-------------------------- + +"axes" describes the dimensions of a coordinate systems and adds an interpretation to the data along that dimension. A named collection +of axes forms a coordinate system ([[#coord-sys-md]]) (see below). +It is a list of dictionaries, where each dictionary describes a dimension (axis) and: +- MUST contain the field "name" that gives the name for this dimension. The values MUST be unique across all "name" fields. +- SHOULD contain the field "type". It SHOULD be one of the strings "array", "space", "time", "channel", "coordinate", or + "displacement" but MAY take other string values for custom axis types that are not part of this specification yet. +- SHOULD contain the field "unit" to specify the physical unit of this dimension. The value SHOULD be one of the following strings, which are valid units according to UDUNITS-2. + - Units for "space" axes: 'angstrom', 'attometer', 'centimeter', 'decimeter', 'exameter', 'femtometer', 'foot', 'gigameter', 'hectometer', 'inch', 'kilometer', 'megameter', 'meter', 'micrometer', 'mile', 'millimeter', 'nanometer', 'parsec', 'petameter', 'picometer', 'terameter', 'yard', 'yoctometer', 'yottameter', 'zeptometer', 'zettameter' + - Units for "time" axes: 'attosecond', 'centisecond', 'day', 'decisecond', 'exasecond', 'femtosecond', 'gigasecond', 'hectosecond', 'hour', 'kilosecond', 'megasecond', 'microsecond', 'millisecond', 'minute', 'nanosecond', 'petasecond', 'picosecond', 'second', 'terasecond', 'yoctosecond', 'yottasecond', 'zeptosecond', 'zettasecond' +- MAY contain the field "longName". The value MUST be a string, and can provide a longer name or description of an axis and its properties. + +The "axes" are used as part of [[#multiscale-md]]. The length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. + +
Layout
+ +Typical Zarr layout produced by running `bioformats2raw` on a fileset that contains more than one image (series > 1): + ++series.ome.zarr # One converted fileset from bioformats2raw + ├── zarr.json # Contains "bioformats2raw.layout" metadata + ├── OME # Special group for containing OME metadata + │ ├── zarr.json # Contains "series" metadata + │ └── METADATA.ome.xml # OME-XML file stored within the Zarr fileset + ├── 0 # First image in the collection + ├── 1 # Second image in the collection + └── ... ++ +
Attributes
+ +The OME-Zarr Metadata in the top-level `zarr.json` file must contain the `bioformats2raw.layout` key: ++path: examples/bf2raw/image.json +highlight: json ++ +If the top-level group represents a plate, the `bioformats2raw.layout` metadata will be present but +the "plate" key MUST also be present, takes precedence and parsing of such datasets should follow [[#plate-md]]. It is not +possible to mix collections of images with plates at present. + +
+path: examples/bf2raw/plate.json +highlight: json ++ +The OME-Zarr Metadata in the `zarr.json` file within the OME group may contain the "series" key: + +
+path: examples/ome/series-2.json +highlight: json ++ +
Details
+ +Conforming groups: + +- MUST have the value "3" for the "bioformats2raw.layout" key in their OME-Zarr Metadata in the `zarr.json` at the top of the hierarchy; +- SHOULD have OME metadata representing the entire collection of images in a file named "OME/METADATA.ome.xml" which: + - MUST adhere to the OME-XML specification but + - MUST use `| `identity` + | + | The identity transformation is the default transformation and is typically not explicitly defined. + | |||
|---|---|---|---|---|---|
| `mapAxis` + | `"mapAxis":Dict[String:String]` + | A `maxAxis` transformation specifies an axis permutation as a map between axis names. + | |||
| `translation` + | one of: `"translation":List[number]`, `"path":str` + | translation vector, stored either as a list of numbers (`"translation"`) or as binary data at a location + in this container (`path`). + | |||
| `scale` + | one of: `"scale":List[number]`, `"path":str` + | scale vector, stored either as a list of numbers (`scale`) or as binary data at a location in this + container (`path`). + | |||
| `affine` + | one of: `"affine":List[List[number]]`, `"path":str` + | affine transformation matrix stored as a flat array stored either with json uing the affine field + or as binary data at a location in this container (path). If both are present, the binary values at path should be used. + | |||
| `rotation` + | one of: `"rotation":List[List[number]]`, `"path":str` + | rotation transformation matrix stored as an array stored either + with json or as binary data at a location in this container (path). + If both are present, the binary parameters at path are used. + | |||
| `sequence` + | `"transformations":List[Transformation]` + | A sequence of transformations, Applying the sequence applies the composition of all transforms in the list, in order. + | |||
| `displacements` + | `"path":str` `"interpolation":str` + | Displacement field transformation located at (path). + | |||
| `coordinates` + | `"path":str` `"interpolation":str` + | Coordinate field transformation located at (path). + | |||
| `inverseOf` + | `"transform":Transform` + | The inverse of a transformation. Useful if a transform is not closed-form invertible. See Forward and inverse for details and examples. + | |||
| `bijection` + | `"forward":Transform` `"inverse":Transform` + | Explicitly define an invertible transformation by providing a forward transformation and its inverse. + | |||
| `byDimension` + | `"transformations":List[Transformation]` + | Define a high dimensional transformation using lower dimensional transformations on subsets of
+ dimensions.
+
+ | type | fields | description
+ | |
+store.zarr # Root folder of the zarr store +│ +├── zarr.json # coordinate transformations describing the relationship between two image coordinate systems +│ # are stored in the attributes of their parent group. +│ # transformations between 'volume' and 'crop' coordinate systems are stored here. +│ +├── coordinateTransformations # transformations that use array storage go in a "coordinateTransformations" zarr group. +│ └── displacements # for example, a zarr array containing a displacement field +│ └── zarr.json +│ +├── volume +│ ├── zarr.json # group level attributes (multiscales) +│ └── 0 # a group containing the 0th scale +│ └── image # a zarr array +│ └── zarr.json # physical coordinate system and transformations here +│ # the array attributes +└── crop + ├── .zattrs # group level attributes (multiscales) + └── 0 # a group containing the 0th scale + └── image # a zarr array + └── zarr.json # physical coordinate system and transformations here + # the array attributes ++ +### Additional details + +Input and output dimensionality of a transformation may be determined by the value of the "input" and "output" fields, +respectively. If the value of "input" ("output") is an array, its length gives the number of input (output) dimensions, +otherwise the length of "axes" for the coordinate system with the name of the "input" ("output") value gives the number of input +(output) dimensions. + +Most coordinate transformations MUST specify their input and output coordinate systems using `input` and `output` with a string value +corresponding to the name of a coordinate system. The coordinate system's name may be the path to an array, and therefore may +not appear in the list of coordinate systems. + +Exceptions are if the the coordinate transformation appears in the `transformations` list of a `sequence` or is the +`transformation` of an `inverseOf` transformation. In these two cases input and output SHOULD be omitted (see below for +details). + +Transformations in the `transformations` list of a `byDimensions` transformation MUST provide `input` and `output` as arrays +of strings corresponding to axis names of the parent transformation's input and output coordinate systems (see below for +details). + +
+path: examples/transformations/identity.json +highlight: json ++ +defines the function: + +``` +x = i +y = j +``` + +
+path: examples/transformations/mapAxis1.json +highlight: json ++ +The "equivalent to identity" transformation defines the function: + +``` +x = i +y = j +``` + +and the "permutation" transformation defines the function + +``` +x = j +y = i +``` + +
+path: examples/transformations/mapAxis2.json +highlight: json ++ +The "projection_down" transformation defines the function: + +``` +x = b +``` + +and the "projection_up" transformation defines the function: + +``` +x = a +y = b +z = b +``` +
-
+
- path +
- The path to a zarr-array containing the translation parameters. + The array at this path MUST be 1D, and its length MUST be `N`. +
- scale +
- The scale parameters stored as a JSON list of numbers. The list MUST have length `N`. +
+path: examples/transformations/translation.json +highlight: json ++ +defines the function: + +``` +x = i + 9 +y = j - 1.42 +``` +
-
+
- path +
- The path to a zarr-array containing the scale parameters. + The array at this path MUST be 1D, and its length MUST be `N`. +
- scale +
- The scale parameters stored as a JSON list of numbers. The list MUST have length `N`. +
+path: examples/transformations/scale.json +highlight: json ++ +defines the function: + +``` +x = 3.12 * i +y = 2 * j +``` +
-
+
- path +
- The path to a zarr-array containing the affine parameters. + The array at this path MUST be 2D whose shape MUST be `M x (N+1)`. +
- affine +
- The affine parameters stored in JSON. The matrix MUST be stored as 2D nested array where the outer array MUST be length + `M` and the inner arrays MUST be length `N+1`.
+ path: examples/transformations/affine2d2d.json + highlight: json ++ + defines the function: + + ``` + x = 1*i + 2*j + 3 + y = 4*i + 5*j + 6 + ``` + + it is equivalent to this matrix-vector multiplication in homogeneous coordinates: + + ``` + [ 1 2 3 ][ i ] [ x ] + [ 4 5 6 ][ j ] = [ y ] + [ 0 0 1 ][ 1 ] [ 1 ] + ``` + + where the last row `[0 0 1]` is omitted in the JSON representation. + +
+ path: examples/transformations/affine2d3d.json + highlight: json ++ + defines the function: + + ``` + x = 1*i + 2*j + 3 + y = 4*i + 5*j + 6 + z = 7*i + 8*j + 9 + ``` + + it is equivalent to this matrix-vector multiplication in homogeneous coordinates: + + ``` + [ 1 2 3 ][ i ] [ x ] + [ 4 5 6 ][ j ] = [ y ] + [ 7 8 9 ][ 1 ] [ z ] + [ 0 0 1 ] [ 1 ] + ``` + + where the last row `[0 0 1]` is omitted in the JSON representation. +
-
+
- path +
- The path to an array containing the affine parameters. + The array at this path MUST be 2D whose shape MUST be `N x N`. +
- rotation +
- The parameters stored in JSON. The matrix MUST be stored as a 2D nested array where the outer array MUST be length `N` + and the inner arrays MUST be length `N`.
+ path: examples/transformations/rotation.json + highlight: json ++ + defines the function: + + ``` + x = 0*i - 1*j + y = 1*i + 0*j + ``` +
+ path: examples/transformations/inverseOf.json + highlight: json ++ +
-
+
- transformations +
- A non-empty array of transformations. +
+path: examples/transformations/sequence.json +highlight: json ++ +describes the function + +``` +x = (i + 0.1) * 2 +y = (j + 0.9) * 3 +``` + +and is invertible. +
-
+
- path +
- The location of the coordinate array in this (or another) container. +
- interpolation +
- The `interpolation` attributes MAY be provided. It's value indicates
+ the interpolation to use if transforming points not on the array's discrete grid.
+ Values could be:
+
-
+
linear(default)
+ nearest
+ cubic
+
+
-
+
- transformations +
- A list of transformations, each of which applies to a (non-strict) subset of input and output dimensions (axes). + The values of `input` and `output` fields MUST be an array of strings. + Every axis name in `input` MUST correspond to a name of some axis in this parent object's `input` coordinate system. + Every axis name in the parent byDimension's `output` MUST appear in exactly one of its child transformations' `output`. + +
+path: examples/transformations/byDimension1.json +highlight: json ++ +
+path: examples/transformations/byDimension2.json +highlight: json ++ +
+path: examples/transformations/byDimensionInvalid1.json +highlight: json ++ +It is invalid for two reasons. First because input `0` used by the scale transformation is not an axis of the `byDimension` transformation's `input`. Second, the `x` axis of the `output` does not appear in the `output` of any child transformation. + +
+path: examples/transformations/byDimensionInvalid2.json +highlight: json ++ +This transformation is invalid because the output axis `x` appears in more than one transformation in the `transformations` list. + +
+path: examples/transformations/bijection.json +highlight: json ++ +the input and output of the `forward` and `inverse` transformations are understood to be: + +
+path: examples/transformations/bijection_verbose.json +highlight: json ++ +
+path: examples/multiscales_strict/multiscales_example.json +highlight: json ++ + +If only one multiscale is provided, use it. Otherwise, the user can choose by +name, using the first multiscale as a fallback: + +```python +datasets = [] +for named in multiscales: + if named["name"] == "3D": + datasets = [x["path"] for x in named["datasets"]] + break +if not datasets: + # Use the first by default. Or perhaps choose based on chunk size. + datasets = [x["path"] for x in multiscales[0]["datasets"]] +``` + +"omero" metadata (transitional) {#omero-md} +------------------------------------------- + +[=Transitional=] information specific to the channels of an image and how to render it +can be found under the "omero" key in the group-level metadata: + +```json +"id": 1, # ID in OMERO +"name": "example.tif", # Name as shown in the UI +"channels": [ # Array matching the c dimension size + { + "active": true, + "coefficient": 1, + "color": "0000FF", + "family": "linear", + "inverted": false, + "label": "LaminB1", + "window": { + "end": 1500, + "max": 65535, + "min": 0, + "start": 0 + } + } +], +"rdefs": { + "defaultT": 0, # First timepoint to show the user + "defaultZ": 118, # First Z section to show the user + "model": "color" # "color" or "greyscale" +} +``` + +See the [OMERO WebGateway documentation](https://omero.readthedocs.io/en/stable/developers/Web/WebGateway.html#imgdata) +for more information. + +The "omero" metadata is optional, but if present it MUST contain the field "channels", which is an array of dictionaries describing the channels of the image. +Each dictionary in "channels" MUST contain the field "color", which is a string of 6 hexadecimal digits specifying the color of the channel in RGB format. +Each dictionary in "channels" MUST contain the field "window", which is a dictionary describing the windowing of the channel. +The field "window" MUST contain the fields "min" and "max", which are the minimum and maximum values of the window, respectively. +It MUST also contain the fields "start" and "end", which are the start and end values of the window, respectively. + +"labels" metadata {#labels-md} +------------------------------ + +In OME-Zarr, Zarr arrays representing pixel-annotation data are stored in a group called "labels". Some applications--notably image segmentation--produce +a new image that is in the same coordinate system as a corresponding multiscale image (usually having the same dimensions and coordinate transformations). +This new image is composed of integer values corresponding to certain labels with custom meanings. For example, pixels take the value 1 or 0 +if the corresponding pixel in the original image represents cellular space or intercellular space, respectively. +Such an image is referred to in this specification as a 'label image'. + +The "labels" group is nested within an image group, at the same level of the Zarr hierarchy as the resolution levels for the original image. +The "labels" group is not itself an image; it contains images. The pixels of the label images MUST be integer data types, i.e. one of +[`uint8`, `int8`, `uint16`, `int16`, `uint32`, `int32`, `uint64`, `int64`]. Intermediate groups between "labels" and the images within it are allowed, +but these MUST NOT contain metadata. Names of the images in the "labels" group are arbitrary. + +The OME-Zarr Metadata in the `zarr.json` file associated with the "labels" group MUST contain a JSON object with the key `labels`, whose value is a JSON array of paths to the +labeled multiscale image(s). All label images SHOULD be listed within this metadata file. For example: + +```json +{ + ... + "attributes": { + "ome": { + "version": "0.5", + "labels": [ + "cell_space_segmentation" + ] + } + } +} +``` + +The `zarr.json` file for the label image MUST implement the multiscales specification. Within the `multiscales` object, the JSON array +associated with the `datasets` key MUST have the same number of entries (scale levels) as the original unlabeled image. + +In addition to the `multiscales` key, the OME-Zarr Metadata in this image-level `zarr.json` file SHOULD contain another key, `image-label`, +whose value is also a JSON object. The `image-label` object stores information about the display colors, source image, and optionally, +further arbitrary properties of the label image. That `image-label` object SHOULD contain the following keys: first, a `colors` key, +whose value MUST be a JSON array describing color information for the unique label values. Second, a `version` key, whose value MUST be a +string specifying the version of the OME-Zarr `image-label` schema. + +Conforming readers SHOULD display labels using the colors specified by the `colors` JSON array, as follows. This array contains one +JSON object for each unique custom label. Each of these objects MUST contain the `label-value` key, whose value MUST be the integer +corresponding to a particular label. In addition to the `label-value` key, the objects in this array MAY contain an `rgba` key whose +value MUST be an array of four integers between 0 and 255, inclusive. These integers represent the `uint8` values of red, green, and +blue that comprise the final color to be displayed at the pixels with this label. The fourth integer in the `rgba` array represents alpha, +or the opacity of the color. Additional keys under `colors` are allowed. + +Next, the `image-label` object MAY contain the following keys: a `properties` key, and a `source` key. + +Like the `colors` key, the value of the `properties` key MUST be an array of JSON objects describing the set of unique possible pixel values. +Each object in the `properties` array MUST contain the `label-value` key, whose value again 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 arbitrary metadata associated with that label. +Label-value objects within the `properties` array do not need to have the same keys. + +The value of the `source` key MUST be a JSON object containing information about the original image from which the label image derives. +This object 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 labeled images are stored in a "labels" group that is nested within the original image group. + +Here is an example of a simple `image-label` object for a label image in which 0s and 1s represent intercellular and cellular space, respectively: + +
+path: examples/label_strict/colors_properties.json +highlight: json ++ +In this case, the pixels consisting of a 0 in the Zarr array will be displayed as 50% blue and 50% opacity. Pixels with a 1 in the Zarr array, +which correspond to cellular space, will be displayed as 50% green and 50% opacity. + +"plate" metadata {#plate-md} +---------------------------- + +For high-content screening datasets, the plate layout can be found under the +custom attributes of the plate group under the `plate` key in the group-level metadata. + +The `plate` dictionary MAY contain an `acquisitions` key whose value MUST be a list of +JSON objects defining the acquisitions for a given plate to which wells can refer to. Each +acquisition object MUST contain an `id` key whose value MUST be an unique integer identifier +greater than or equal to 0 within the context of the plate to which fields of view can refer +to (see #well-md). +Each acquisition object SHOULD contain a `name` key whose value MUST be a string identifying +the name of the acquisition. Each acquisition object SHOULD contain a `maximumfieldcount` +key whose value MUST be a positive integer indicating the maximum number of fields of view for the +acquisition. Each acquisition object MAY contain a `description` key whose value MUST be a +string specifying a description for the acquisition. Each acquisition object MAY contain +a `starttime` and/or `endtime` key whose values MUST be integer epoch timestamps specifying +the start and/or end timestamp of the acquisition. + +The `plate` dictionary MUST contain a `columns` key whose value MUST be a list of JSON objects +defining the columns of the plate. Each column object defines the properties of +the column at the index of the object in the list. Each column in the physical plate +MUST be defined, even if no wells in the column are defined. Each column object MUST +contain a `name` key whose value is a string specifying the column name. The `name` MUST +contain only alphanumeric characters, MUST be case-sensitive, and MUST NOT be a duplicate of any +other `name` in the `columns` list. Care SHOULD be taken to avoid collisions on +case-insensitive filesystems (e.g. avoid using both `Aa` and `aA`). + +The `plate` dictionary SHOULD contain a `field_count` key whose value MUST be a positive integer +defining the maximum number of fields per view across all wells. + +The `plate` dictionary SHOULD contain a `name` key whose value MUST be a string defining the +name of the plate. + +The `plate` dictionary MUST contain a `rows` key whose value MUST be a list of JSON objects +defining the rows of the plate. Each row object defines the properties of +the row at the index of the object in the list. Each row in the physical plate +MUST be defined, even if no wells in the row are defined. Each defined row MUST +contain a `name` key whose value MUST be a string defining the row name. The `name` MUST +contain only alphanumeric characters, MUST be case-sensitive, and MUST NOT be a duplicate of any +other `name` in the `rows` list. Care SHOULD be taken to avoid collisions on +case-insensitive filesystems (e.g. avoid using both `Aa` and `aA`). + +The `plate` dictionary MUST contain a `version` key whose value MUST be a string specifying the +version of the plate specification. + +The `plate` dictionary MUST contain a `wells` key whose value MUST be a list of JSON objects +defining the wells of the plate. Each well object MUST contain a `path` key whose value MUST +be a string specifying the path to the well subgroup. The `path` MUST consist of a `name` in +the `rows` list, a file separator (`/`), and a `name` from the `columns` list, in that order. +The `path` MUST NOT contain additional leading or trailing directories. +Each well object MUST contain both a `rowIndex` key whose value MUST be an integer identifying +the index into the `rows` list and a `columnIndex` key whose value MUST be an integer identifying +the index into the `columns` list. `rowIndex` and `columnIndex` MUST be 0-based. The +`rowIndex`, `columnIndex`, and `path` MUST all refer to the same row/column pair. + +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. + +
+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. + +
+path: examples/plate_strict/plate_2wells.json +highlight: json ++ +"well" metadata {#well-md} +-------------------------- + +For high-content screening datasets, the metadata about all fields of views +under a given well can be found under the "well" key in the attributes of the +well group. + +The `well` dictionary MUST contain an `images` key whose value MUST be a list of JSON objects +specifying all fields of views for a given well. Each image object MUST contain a +`path` key whose value MUST be a string specifying the path to the field of view. The `path` +MUST contain only alphanumeric characters, MUST be case-sensitive, and MUST NOT be a duplicate +of any other `path` in the `images` list. If multiple acquisitions were performed in the plate, +it MUST contain an `acquisition` key whose value MUST be an integer identifying the acquisition +which MUST match one of the acquisition JSON objects defined in the plate metadata (see #plate-md). + +The `well` dictionary SHOULD contain a `version` key whose value MUST be a string specifying the +version of the well specification. + +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. + +
+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. + +
+path: examples/well_strict/well_2fields.json +highlight: json ++ +Specification naming style {#naming-style} +========================================== + +Multi-word keys in this specification should use the `camelCase` style. +NB: some parts of the specification don't obey this convention as they +were added before this was adopted, but they should be updated in due course. + +Implementations {#implementations} +================================== + +See [Tools](https://ngff.openmicroscopy.org/tools/index.html). + +Citing {#citing} +================ + +[Next-generation file format (NGFF) specifications for storing bioimaging data in the cloud.](https://ngff.openmicroscopy.org/0.4) +J. Moore, *et al*. Open Microscopy Environment Consortium, 8 February 2022. +This edition of the specification is [https://ngff.openmicroscopy.org/0.5/](https://ngff.openmicroscopy.org/0.5/]). +The latest edition is available at [https://ngff.openmicroscopy.org/latest/](https://ngff.openmicroscopy.org/latest/). +[(doi:10.5281/zenodo.4282107)](https://doi.org/10.5281/zenodo.4282107) + +Version History {#history} +========================== + +
| Revision | +Date | +Description | +
| 0.5.2 | +2025-01-10 | +Clarify that the dimension_names field in axes MUST be included. |
+
| 0.5.1 | +2025-01-10 | +Re-add the improved omero description in PR-191. | +
| 0.5.0 | +2024-11-21 | +use Zarr v3 in OME-Zarr, see RFC-2. | +
| 0.4.1 | +2023-02-09 | +expand on "labels" description | +
| 0.4.1 | +2022-09-26 | +transitional metadata for image collections ("bioformats2raw.layout") | +
| 0.4.0 | +2022-02-08 | +multiscales: add axes type, units and coordinateTransformations | +
| 0.4.0 | +2022-02-08 | +plate: add rowIndex/columnIndex | +
| 0.3.0 | +2021-08-24 | +Add axes field to multiscale metadata | +
| 0.2.0 | +2021-03-29 | +Change chunk dimension separator to "/" | +
| 0.1.4 | +2020-11-26 | +Add HCS specification | +
| 0.1.3 | +2020-09-14 | +Add labels specification | +
| 0.1.2 | +2020-05-07 | +Add description of "omero" metadata | +
| 0.1.1 | +2020-05-06 | +Add info on the ordering of resolutions | +
| 0.1.0 | +2020-04-20 | +First version for internal demo | +
+{
+ "blogNov2020": {
+ "href": "https://blog.openmicroscopy.org/file-formats/community/2020/11/04/zarr-data/",
+ "title": "Public OME-Zarr data (Nov. 2020)",
+ "authors": [
+ "OME Team"
+ ],
+ "status": "Informational",
+ "publisher": "OME",
+ "id": "blogNov2020",
+ "date": "04 November 2020"
+ },
+ "imagesc26952": {
+ "href": "https://forum.image.sc/t/ome-s-position-regarding-file-formats/26952",
+ "title": "OME’s position regarding file formats",
+ "authors": [
+ "OME Team"
+ ],
+ "status": "Informational",
+ "publisher": "OME",
+ "id": "imagesc26952",
+ "date": "19 June 2020"
+ },
+ "n5": {
+ "id": "n5",
+ "href": "https://github.com/saalfeldlab/n5/issues/62",
+ "title": "N5---a scalable Java API for hierarchies of chunked n-dimensional tensors and structured meta-data",
+ "status": "Informational",
+ "authors": [
+ "John A. Bogovic",
+ "Igor Pisarev",
+ "Philipp Hanslovsky",
+ "Neil Thistlethwaite",
+ "Stephan Saalfeld"
+ ],
+ "date": "2020"
+ },
+ "ome-zarr-py": {
+ "id": "ome-zarr-py",
+ "href": "https://doi.org/10.5281/zenodo.4113931",
+ "title": "ome-zarr-py: Experimental implementation of next-generation file format (NGFF) specifications for storing bioimaging data in the cloud.",
+ "status": "Informational",
+ "publisher": "Zenodo",
+ "authors": [
+ "OME",
+ "et al"
+ ],
+ "date": "06 October 2020"
+ },
+ "zarr": {
+ "id": "zarr",
+ "href": "https://doi.org/10.5281/zenodo.4069231",
+ "title": "Zarr: An implementation of chunked, compressed, N-dimensional arrays for Python.",
+ "status": "Informational",
+ "publisher": "Zenodo",
+ "authors": [
+ "Alistair Miles",
+ "et al"
+ ],
+ "date": "06 October 2020"
+ },
+ "itk":{
+ "id": "itk-book",
+ "href": "https://itk.org/ItkSoftwareGuide.pdf",
+ "title": "The ITK Software Guide",
+ "status": "Informational",
+ "publisher": "ITK",
+ "authors": [
+ "Hans J. Johnson",
+ "Matthew M. McCormick",
+ "Luis Ibanez",
+ "Insight Software Consortium"
+ ],
+ "date": "16 April 2021"
+ }
+}
+
diff --git a/0.6-dev/schemas/_version.schema b/0.6-dev/schemas/_version.schema
new file mode 100644
index 00000000..1da06a6d
--- /dev/null
+++ b/0.6-dev/schemas/_version.schema
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema",
+ "title": "OME-Zarr Metadata version",
+ "description": "The version of the OME-Zarr Metadata",
+ "type": "string",
+ "enum": [
+ "0.5"
+ ]
+}
diff --git a/0.6-dev/schemas/axes.schema b/0.6-dev/schemas/axes.schema
new file mode 100644
index 00000000..56b447f2
--- /dev/null
+++ b/0.6-dev/schemas/axes.schema
@@ -0,0 +1,62 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/axes.schema",
+ "title": "NGFF Axes",
+ "description": "JSON from OME-NGFF .zattrs",
+ "type": "array",
+ "uniqueItems": true,
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/axis"
+ },
+ "$comment": "Ensure that there exist at most three space axes",
+ "contains": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "space"
+ ]
+ },
+ "unit": {
+ "type": "string"
+ }
+ }
+ },
+ "minContains": 0,
+ "maxContains": 3,
+ "$defs": {
+ "axis": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the axis"
+ },
+ "longName": {
+ "type": "string",
+ "description": "Longer name or description of the axis."
+ },
+ "type": {
+ "type": "string",
+ "description": "Dimension of the axis"
+ },
+ "discrete": {
+ "type": "boolean",
+ "description": "Whether the dimension is discrete"
+ },
+ "unit": {
+ "type": "string",
+ "description": "Unit for the axis"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ }
+}
diff --git a/0.6-dev/schemas/bf2raw.schema b/0.6-dev/schemas/bf2raw.schema
new file mode 100644
index 00000000..d3c87253
--- /dev/null
+++ b/0.6-dev/schemas/bf2raw.schema
@@ -0,0 +1,32 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/bf2raw.schema",
+ "title": "OME-Zarr container produced by bioformats2raw",
+ "description": "The zarr.json attributes key",
+ "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.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "bioformats2raw.layout",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ]
+}
diff --git a/0.6-dev/schemas/coordinateTransformations.schema b/0.6-dev/schemas/coordinateTransformations.schema
new file mode 100644
index 00000000..8bd35f4f
--- /dev/null
+++ b/0.6-dev/schemas/coordinateTransformations.schema
@@ -0,0 +1,296 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/coordinateTransformations.schema",
+ "title": "NGFF Coordinate Transformations",
+ "description": "JSON from OME-NGFF .zattrs",
+ "type": "array",
+ "minItems": 1,
+ "contains": {
+ "type": "object"
+ },
+ "maxContains": 1,
+ "items": {
+ "$ref": "#/$defs/transformation"
+ },
+ "$defs": {
+ "transformation" : {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/scaleTransformation"
+ },
+ {
+ "$ref": "#/$defs/translationTransformation"
+ },
+ {
+ "$ref": "#/$defs/affineTransformation"
+ },
+ {
+ "$ref": "#/$defs/rotationTransformation"
+ },
+ {
+ "$ref": "#/$defs/inverseOfTransformation"
+ },
+ {
+ "$ref": "#/$defs/sequenceTransformation"
+ },
+ {
+ "$ref": "#/$defs/coordinatesTransformation"
+ },
+ {
+ "$ref": "#/$defs/displacementsTransformation"
+ },
+ {
+ "$ref": "#/$defs/byDimensionTransformation"
+ },
+ {
+ "$ref": "#/$defs/bijectionTransformation"
+ }
+ ]
+ },
+ "scaleTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "scale"
+ ]
+ },
+ "scale": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "oneOf": [
+ {
+ "required": ["scale"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ },
+ "translationTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "translation"
+ ]
+ },
+ "translation": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "oneOf": [
+ {
+ "required": ["translation"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ },
+ "affineTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "affine"
+ ]
+ },
+ "affine": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "oneOf": [
+ {
+ "required": ["affine"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ },
+ "rotationTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "rotation"
+ ]
+ },
+ "rotation": {
+ "type": "object",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "oneOf": [
+ {
+ "required": ["rotation"]
+ },
+ {
+ "required": ["path"]
+ }
+ ]
+ },
+ "inverseOfTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "inverseOf"
+ ]
+ },
+ "transformation": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "type", "transformation"
+ ]
+ },
+ "sequenceTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "sequence"
+ ]
+ },
+ "transformations": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type", "transformations"
+ ]
+ },
+ "coordinatesTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "coordinates"
+ ]
+ },
+ "path": {
+ "type": "string"
+ },
+ "interpolation": {
+ "type": "string",
+ "enum": [
+ "nearest", "linear", "cubic"
+ ]
+ }
+ },
+ "required": [
+ "type", "path", "interpolation"
+ ]
+ },
+ "displacementsTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "displacements"
+ ]
+ },
+ "path": {
+ "type": "string"
+ },
+ "interpolation": {
+ "type": "string",
+ "enum": [
+ "nearest", "linear", "cubic"
+ ]
+ }
+ },
+ "required": [
+ "type", "path", "interpolation"
+ ]
+ },
+ "byDimensionTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "byDimension"
+ ]
+ },
+ "transformations": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type", "transformations"
+ ]
+ },
+ "bijectionTransformation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "bijection"
+ ]
+ },
+ "forward": {
+ "type": "object"
+ },
+ "inverse": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "type", "forward", "inverse"
+ ]
+ }
+ }
+}
diff --git a/0.6-dev/schemas/coordinate_systems.schema b/0.6-dev/schemas/coordinate_systems.schema
new file mode 100644
index 00000000..583d9941
--- /dev/null
+++ b/0.6-dev/schemas/coordinate_systems.schema
@@ -0,0 +1,30 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/coordinate_systems.schema",
+ "title": "NGFF CoordinateSystem",
+ "description": "JSON from OME-NGFF .zattrs",
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/$defs/coordinateSystem"
+ },
+ "$defs": {
+ "coordinateSystem": {
+ "description": "Coordinate Systems for OME-NGFF",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of coordinate system"
+ },
+ "axes": {
+ "$ref": "axes.schema"
+ }
+ },
+ "required": [
+ "name",
+ "axes"
+ ]
+ }
+ }
+}
diff --git a/0.6-dev/schemas/coordinate_systems_and_transforms.schema b/0.6-dev/schemas/coordinate_systems_and_transforms.schema
new file mode 100644
index 00000000..403f78a5
--- /dev/null
+++ b/0.6-dev/schemas/coordinate_systems_and_transforms.schema
@@ -0,0 +1,45 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/coordinate_systems_and_transforms.schema",
+ "title": "NGFF Coordinate Systems and Transforms",
+ "description": "Coordinate Systems and transforms for OME-NGFF",
+ "type": "object",
+ "properties": {
+ "coordinateSystems": {
+ "$ref": "coordinate_systems.schema"
+ },
+ "coordinateTransformations": {
+ "$ref": "coordinate_transformation.schema"
+ },
+ "arrayCoordinateSystem": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of coordinate space"
+ },
+ "axes": {
+ "allOf": [
+ {
+ "$ref": "axes.schema"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "array"
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "required": [
+ "axes"
+ ]
+ }
+ }
+}
diff --git a/0.6-dev/schemas/coordinate_transformation.schema b/0.6-dev/schemas/coordinate_transformation.schema
new file mode 100644
index 00000000..e5156da0
--- /dev/null
+++ b/0.6-dev/schemas/coordinate_transformation.schema
@@ -0,0 +1,344 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/coordinate_transformation.schema",
+ "title": "NGFF Coordinate Systems and Transforms",
+ "description": "Coordinate Systems and transforms for OME-NGFF",
+ "type": "array",
+ "uniqueItems": true,
+ "minItems": 1,
+ "items": {
+ "allOf": [
+ {
+ "$ref": "#/$defs/coordinateTransformation"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "input": {
+ "type": "string"
+ },
+ "output": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "input",
+ "output"
+ ]
+ }
+ ]
+ },
+ "$defs": {
+ "path_w_url": {
+ "description": "Path specification. Schema local solution until https://github.com/ome/ngff/issues/144 is resolved.",
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "required": [
+ "path"
+ ]
+ },
+ "coordinateTransformation": {
+ "description": "OME-NGFF coordinate transformation.",
+ "allOf": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/identity"
+ },
+ {
+ "$ref": "#/$defs/mapAxis"
+ },
+ {
+ "$ref": "#/$defs/scale"
+ },
+ {
+ "$ref": "#/$defs/translation"
+ },
+ {
+ "$ref": "#/$defs/affine"
+ },
+ {
+ "$ref": "#/$defs/rotation"
+ },
+ {
+ "$ref": "#/$defs/inverseOf"
+ },
+ {
+ "$ref": "#/$defs/bijection"
+ },
+ {
+ "$ref": "#/$defs/sequence"
+ },
+ {
+ "$ref": "#/$defs/byDimension"
+ },
+ {
+ "$ref": "#/$defs/displacements"
+ },
+ {
+ "$ref": "#/$defs/coordinates"
+ }
+ ]
+ }
+ ]
+ },
+ "byDimensionTransformation": {
+ "type": "object",
+ "description": "Transformation used inside a byDimension transformation",
+ "allOf": [
+ { "$ref": "#/$defs/coordinateTransformation" },
+ {
+ "properties": {
+ "input": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "output": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ ],
+ "required": ["input", "output"]
+ },
+ "identity": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "identity"
+ }
+ }
+ },
+ "mapAxis": {
+ "type": "object",
+ "description": "Permute axes by name",
+ "properties": {
+ "type": {
+ "const": "mapAxis"
+ },
+ "mapAxis": {
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "mapAxis"
+ ]
+ }
+ },
+ "scale": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "scale"
+ }
+ },
+ "oneOf": [
+ {
+ "$ref": "#/$defs/path_w_url"
+ },
+ {
+ "properties": {
+ "scale": {
+ "type": "array",
+ "items": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ }
+ }
+ },
+ "required": [
+ "scale"
+ ]
+ }
+ ]
+ },
+ "translation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "translation"
+ }
+ },
+ "oneOf": [
+ {
+ "$ref": "#/$defs/path_w_url"
+ },
+ {
+ "properties": {
+ "translation": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": [
+ "translation"
+ ]
+ }
+ ]
+ },
+ "mtxFlatOrNested" : {
+ "type": "array",
+ "oneOf": [
+ {
+ "items": { "type": "number" }
+ },
+ {
+ "items": {
+ "type": "array",
+ "items" : { "type" : "number" }
+ }
+ }
+ ]
+ },
+ "affine": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "affine"
+ }
+ },
+ "oneOf": [
+ {
+ "$ref": "#/$defs/path_w_url"
+ },
+ {
+ "properties": {
+ "affine": {
+ "$ref": "#/$defs/mtxFlatOrNested"
+ },
+ "required": [
+ "affine"
+ ]
+ }
+ }
+ ]
+ },
+ "rotation": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "rotation"
+ }
+ },
+ "oneOf": [
+ {
+ "$ref": "#/$defs/path_w_url"
+ },
+ {
+ "properties": {
+ "rotation": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "rotation"
+ ]
+ }
+ }
+ ]
+ },
+ "inverseOf": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "inverseOf"
+ },
+ "transformation": {
+ "$ref": "#/$defs/coordinateTransformation"
+ }
+ },
+ "required": [
+ "transformation"
+ ]
+ },
+ "bijection": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "const": "bijection"
+ },
+ "forward": {
+ "$ref": "#/$defs/coordinateTransformation"
+ },
+ "inverse": {
+ "$ref": "#/$defs/coordinateTransformation"
+ }
+ },
+ "required": [
+ "forward", "inverse"
+ ]
+ },
+ "sequence": {
+ "description": "A sequence of transformations",
+ "type": "object",
+ "properties": {
+ "type": { "const": "sequence" },
+ "transformations": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/coordinateTransformation"
+ }
+ }
+ }
+ },
+ "byDimension": {
+ "type": "object",
+ "properties": {
+ "type": { "const": "byDimension" },
+ "transformations": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/byDimensionTransformation"
+ }
+ }
+ }
+ },
+ "displacements": {
+ "type": "object",
+ "properties": {
+ "type": { "const": "displacements" }
+ }
+ },
+ "coordinates": {
+ "type": "object",
+ "properties": {
+ "type": { "const": "coordinates" }
+ }
+ }
+ }
+}
diff --git a/0.6-dev/schemas/image.schema b/0.6-dev/schemas/image.schema
new file mode 100644
index 00000000..835c88a3
--- /dev/null
+++ b/0.6-dev/schemas/image.schema
@@ -0,0 +1,435 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/image.schema",
+ "title": "OME-Zarr Image",
+ "description": "The zarr.json attributes key",
+ "type": "object",
+ "properties": {
+ "ome": {
+ "description": "The versioned OME-Zarr Metadata namespace",
+ "type": "object",
+ "properties": {
+ "multiscales": {
+ "$ref": "#/$defs/multiscales"
+ },
+ "omero": {
+ "$ref": "#/$defs/omero"
+ },
+ "version": {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "multiscales",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ],
+ "$defs": {
+ "multiscales": {
+ "description": "The multiscale datasets for this image",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "datasets": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "coordinateTransformations": {
+ "$ref": "coordinate_transformation.schema"
+ }
+ },
+ "required": [
+ "path",
+ "coordinateTransformations"
+ ]
+ }
+ },
+<<<<<<< HEAD:latest/schemas/image.schema
+ "version": {
+ "type": "string",
+ "enum": [
+ "0.5-dev"
+ ]
+ },
+ "coordinateSystems": {
+ "$ref": "coordinate_systems.schema"
+||||||| 449fbca:latest/schemas/image.schema
+ "version": {
+ "type": "string",
+ "enum": [
+ "0.5-dev"
+ ]
+ },
+ "axes": {
+ "$ref": "#/$defs/axes"
+=======
+ "axes": {
+ "$ref": "#/$defs/axes"
+>>>>>>> upstream/main:0.5/schemas/image.schema
+ },
+ "coordinateTransformations": {
+<<<<<<< HEAD:latest/schemas/image.schema
+ "$ref": "coordinate_transformation.schema"
+ }
+||||||| 449fbca:latest/schemas/image.schema
+ "$ref": "#/$defs/coordinateTransformations"
+ }
+=======
+ "$ref": "#/$defs/coordinateTransformations"
+ }
+>>>>>>> upstream/main:0.5/schemas/image.schema
+ },
+ "required": [
+<<<<<<< HEAD:latest/schemas/image.schema
+ "datasets", "coordinateSystems"
+||||||| 449fbca:latest/schemas/image.schema
+ "datasets", "axes"
+=======
+ "datasets",
+ "axes"
+>>>>>>> upstream/main:0.5/schemas/image.schema
+ ]
+ },
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "omero": {
+ "type": "object",
+ "properties": {
+ "channels": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "window": {
+ "type": "object",
+ "properties": {
+ "end": {
+ "type": "number"
+ },
+ "max": {
+ "type": "number"
+ },
+ "min": {
+ "type": "number"
+ },
+ "start": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "start",
+ "min",
+ "end",
+ "max"
+ ]
+ },
+ "label": {
+ "type": "string"
+ },
+ "family": {
+ "type": "string"
+ },
+ "color": {
+ "type": "string"
+ },
+ "active": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "channels"
+ ]
+<<<<<<< HEAD:latest/schemas/image.schema
+ }
+ },
+ "required": [ "multiscales" ]
+||||||| 449fbca:latest/schemas/image.schema
+ }
+ },
+ "required": [ "multiscales" ],
+
+ "$defs": {
+ "axes": {
+ "type": "array",
+ "uniqueItems": true,
+ "minItems": 2,
+ "maxItems": 5,
+ "contains": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": ["space"]
+ },
+ "units": {
+ "type": "string"
+ }
+ }
+ },
+ "minContains": 2,
+ "maxContains": 3,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": ["channel", "time", "space"]
+ }
+ },
+ "required": ["name", "type"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "not": {
+ "enum": ["space", "time", "channel"]
+ }
+ }
+ },
+ "required": ["name"]
+ }
+ ]
+ }
+ },
+ "coordinateTransformations": {
+ "type": "array",
+ "minItems": 1,
+ "contains": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "scale"
+ ]
+ },
+ "scale": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ }
+ },
+ "maxContains": 1,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "scale"
+ ]
+ },
+ "scale": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": ["type", "scale"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "translation"
+ ]
+ },
+ "translation": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": ["type", "translation"]
+ }
+ ]
+ }
+ }
+ }
+=======
+ },
+ "axes": {
+ "type": "array",
+ "uniqueItems": true,
+ "minItems": 2,
+ "maxItems": 5,
+ "contains": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "space"
+ ]
+ },
+ "unit": {
+ "type": "string"
+ }
+ }
+ },
+ "minContains": 2,
+ "maxContains": 3,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "channel",
+ "time",
+ "space"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "type"
+ ]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string",
+ "not": {
+ "enum": [
+ "space",
+ "time",
+ "channel"
+ ]
+ }
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ ]
+ }
+ },
+ "coordinateTransformations": {
+ "type": "array",
+ "minItems": 1,
+ "contains": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "scale"
+ ]
+ },
+ "scale": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ }
+ },
+ "maxContains": 1,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "scale"
+ ]
+ },
+ "scale": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "scale"
+ ]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "translation"
+ ]
+ },
+ "translation": {
+ "type": "array",
+ "minItems": 2,
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": [
+ "type",
+ "translation"
+ ]
+ }
+ ]
+ }
+ }
+ }
+>>>>>>> upstream/main:0.5/schemas/image.schema
+}
diff --git a/0.6-dev/schemas/label.schema b/0.6-dev/schemas/label.schema
new file mode 100644
index 00000000..dd5cb6d6
--- /dev/null
+++ b/0.6-dev/schemas/label.schema
@@ -0,0 +1,91 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/label.schema",
+ "title": "OME-Zarr labelled image schema",
+ "description": "The zarr.json attributes key",
+ "type": "object",
+ "properties": {
+ "ome": {
+ "description": "The versioned OME-Zarr Metadata namespace",
+ "type": "object",
+ "properties": {
+ "image-label": {
+ "$ref": "#/$defs/image-label"
+ },
+ "version": {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "image-label",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ],
+ "$defs": {
+ "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"
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/0.6-dev/schemas/ome.schema b/0.6-dev/schemas/ome.schema
new file mode 100644
index 00000000..36569280
--- /dev/null
+++ b/0.6-dev/schemas/ome.schema
@@ -0,0 +1,33 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/ome.schema",
+ "title": "OME-Zarr group produced by bioformats2raw to contain OME metadata",
+ "description": "The zarr.json attributes key",
+ "type": "object",
+ "properties": {
+ "ome": {
+ "description": "The versioned OME-Zarr Metadata namespace",
+ "type": "object",
+ "properties": {
+ "series": {
+ "description": "An array of the same length and the same order as the images defined in the OME-XML",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "minContains": 1
+ },
+ "version": {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "series",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ]
+}
diff --git a/0.6-dev/schemas/ome_zarr.schema b/0.6-dev/schemas/ome_zarr.schema
new file mode 100644
index 00000000..9b22bba6
--- /dev/null
+++ b/0.6-dev/schemas/ome_zarr.schema
@@ -0,0 +1,24 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/ome_zarr.schema",
+ "anyOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/bf2raw.schema"
+ },
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/image.schema"
+ },
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/label.schema"
+ },
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/ome.schema"
+ },
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/plate.schema"
+ },
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/well.schema"
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/plate.schema b/0.6-dev/schemas/plate.schema
new file mode 100644
index 00000000..3c8a1b97
--- /dev/null
+++ b/0.6-dev/schemas/plate.schema
@@ -0,0 +1,153 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/plate.schema",
+ "title": "OME-Zarr plate schema",
+ "description": "The zarr.json attributes key",
+ "type": "object",
+ "properties": {
+ "ome": {
+ "description": "The versioned OME-Zarr Metadata namespace",
+ "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"
+ },
+ "description": {
+ "description": "The description 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"
+ ]
+ }
+ },
+ "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"
+ ]
+ },
+ "version": {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "plate",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ]
+}
diff --git a/0.6-dev/schemas/strict_axes.schema b/0.6-dev/schemas/strict_axes.schema
new file mode 100644
index 00000000..522602d2
--- /dev/null
+++ b/0.6-dev/schemas/strict_axes.schema
@@ -0,0 +1,30 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/strict_axes.schema",
+ "title": "NGFF Strict Axes",
+ "description": "JSON from OME-NGFF .zattrs",
+ "allOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/latest/schemas/axes.schema"
+ },
+ {
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "array",
+ "channel",
+ "time",
+ "space",
+ "displacement",
+ "coordinate",
+ "frequency"
+ ]
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/strict_coordinate_systems.schema b/0.6-dev/schemas/strict_coordinate_systems.schema
new file mode 100644
index 00000000..425ccbe5
--- /dev/null
+++ b/0.6-dev/schemas/strict_coordinate_systems.schema
@@ -0,0 +1,18 @@
+{
+ "$id": "https://ngff.openmicroscopy.org/latest/schemas/strict_coordinate_systems.schema",
+ "allOf" : [
+ {
+ "$ref": "coordinate_systems.schema"
+ },
+ {
+ "items": {
+ "type": "object",
+ "properties": {
+ "axes": {
+ "$ref": "strict_axes.schema"
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/strict_image.schema b/0.6-dev/schemas/strict_image.schema
new file mode 100644
index 00000000..042790e7
--- /dev/null
+++ b/0.6-dev/schemas/strict_image.schema
@@ -0,0 +1,25 @@
+{
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/strict_image.schema",
+ "allOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/image.schema"
+ },
+ {
+ "properties": {
+ "ome": {
+ "properties": {
+ "multiscales": {
+ "items": {
+ "required": [
+ "metadata",
+ "type",
+ "name"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/strict_label.schema b/0.6-dev/schemas/strict_label.schema
new file mode 100644
index 00000000..f1ec4db5
--- /dev/null
+++ b/0.6-dev/schemas/strict_label.schema
@@ -0,0 +1,21 @@
+{
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/strict_label.schema",
+ "allOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/label.schema"
+ },
+ {
+ "properties": {
+ "ome": {
+ "properties": {
+ "image-label": {
+ "required": [
+ "colors"
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/strict_plate.schema b/0.6-dev/schemas/strict_plate.schema
new file mode 100644
index 00000000..ce678ce8
--- /dev/null
+++ b/0.6-dev/schemas/strict_plate.schema
@@ -0,0 +1,31 @@
+{
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/strict_plate.schema",
+ "allOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/plate.schema"
+ },
+ {
+ "properties": {
+ "ome": {
+ "properties": {
+ "plate": {
+ "properties": {
+ "acquisitions": {
+ "items": {
+ "required": [
+ "name",
+ "maximumfieldcount"
+ ]
+ }
+ }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/strict_well.schema b/0.6-dev/schemas/strict_well.schema
new file mode 100644
index 00000000..43cb58cb
--- /dev/null
+++ b/0.6-dev/schemas/strict_well.schema
@@ -0,0 +1,8 @@
+{
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/strict_well.schema",
+ "allOf": [
+ {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/well.schema"
+ }
+ ]
+}
diff --git a/0.6-dev/schemas/well.schema b/0.6-dev/schemas/well.schema
new file mode 100644
index 00000000..447f51df
--- /dev/null
+++ b/0.6-dev/schemas/well.schema
@@ -0,0 +1,56 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://ngff.openmicroscopy.org/0.5/schemas/well.schema",
+ "title": "OME-Zarr well schema",
+ "description": "JSON from OME-Zarr zarr.json",
+ "type": "object",
+ "properties": {
+ "ome": {
+ "description": "The versioned OME-Zarr Metadata namespace",
+ "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
+ }
+ },
+ "required": [
+ "images"
+ ]
+ },
+ "version": {
+ "$ref": "https://ngff.openmicroscopy.org/0.5/schemas/_version.schema"
+ }
+ },
+ "required": [
+ "well",
+ "version"
+ ]
+ }
+ },
+ "required": [
+ "ome"
+ ]
+}
diff --git a/0.6-dev/tests/image_suite.json b/0.6-dev/tests/image_suite.json
new file mode 100644
index 00000000..df359ce4
--- /dev/null
+++ b/0.6-dev/tests/image_suite.json
@@ -0,0 +1,1040 @@
+{
+ "description": "TBD",
+ "schema": {
+ "id": "schemas/image.schema"
+ },
+ "tests": [
+ {
+ "formerly": "valid/mismatch_axes_units.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "t",
+ "type": "time",
+ "unit": "micrometer"
+ },
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [0.13, 0.13],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid/untyped_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "angle"
+ },
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid/invalid_axis_units.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micron"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [0.13, 0.13],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid/missing_name.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "datasets": [
+ {
+ "path": "path/to/0",
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [1, 1]
+ }
+ ]
+ }
+ ],
+ "type": "gaussian",
+ "metadata": {
+ "method": "skimage.transform.pyramid_gaussian",
+ "version": "0.16.1",
+ "args": ["true", "false"],
+ "kwargs": {
+ "multichannel": true
+ }
+ },
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid/custom_type_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "angle",
+ "type": "custom"
+ },
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "invalid/duplicate_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_space_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "t",
+ "type": "time"
+ },
+ {
+ "name": "c",
+ "type": "channel"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_transformation_type.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "translation"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_scale.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "translation": [1, 1],
+ "type": "translation"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/too_many_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "angle",
+ "type": "custom"
+ },
+ {
+ "name": "t",
+ "type": "time"
+ },
+ {
+ "name": "c",
+ "type": "channel"
+ },
+ {
+ "name": "z",
+ "type": "space"
+ },
+ {
+ "name": "y",
+ "type": "space"
+ },
+ {
+ "name": "x",
+ "type": "space"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1, 1, 1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_channels_color.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "omero": {
+ "channels": [
+ {
+ "active": true,
+ "coefficient": 1.0,
+ "color": 255,
+ "family": "linear",
+ "label": "1234",
+ "window": {
+ "end": 1765.0,
+ "max": 2555.0,
+ "min": 5.0,
+ "start": 0.0
+ }
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_axes_name.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "type": "space",
+ "unit": "micron"
+ },
+ {
+ "type": "space",
+ "unit": "micron"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [0.13, 0.13],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_axes_count.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/one_space_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "t",
+ "type": "time"
+ },
+ {
+ "name": "c",
+ "type": "channel"
+ },
+ {
+ "name": "x",
+ "type": "space"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_path.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": 0,
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_multiscales_transformations.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ],
+ "coordinateTransformations": [
+ {
+ "scale": ["invalid"],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_transformations.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/no_datasets.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": []
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_datasets.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_axis_type.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "invalid",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/duplicate_scale.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ },
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/no_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/too_many_space_axes.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "X",
+ "type": "space"
+ },
+ {
+ "name": "z",
+ "type": "space"
+ },
+ {
+ "name": "y",
+ "type": "space"
+ },
+ {
+ "name": "x",
+ "type": "space"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/no_multiscales.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": []
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/invalid_channels_window.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "omero": {
+ "channels": [
+ {
+ "active": true,
+ "coefficient": 1.0,
+ "color": "ff0000",
+ "family": "linear",
+ "label": "1234",
+ "window": {
+ "end": "100",
+ "max": 2555.0,
+ "min": 5.0,
+ "start": 0.0
+ }
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/empty_transformations.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": []
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "invalid/missing_path.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": false
+ }
+ ]
+}
diff --git a/0.6-dev/tests/label_suite.json b/0.6-dev/tests/label_suite.json
new file mode 100644
index 00000000..66a2d35d
--- /dev/null
+++ b/0.6-dev/tests/label_suite.json
@@ -0,0 +1,158 @@
+{
+ "description": "Tests for the image-label JSON schema",
+ "schema": {
+ "id": "schemas/label.schema"
+ },
+ "tests": [
+ {
+ "formerly": "image-label/minimal",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": [
+ {
+ "label-value": 1,
+ "rgba": [0, 0, 0, 0]
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "image-label/minimal_properties",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": [
+ {
+ "label-value": 1,
+ "rgba": [0, 0, 0, 0]
+ }
+ ],
+ "properties": [
+ {
+ "label-value": 1
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "image-label/empty_colors",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": []
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/empty_properties",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "properties": []
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/colors_no_label_value",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": [
+ {
+ "rgba": [0, 0, 0, 0]
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/properties_no_label_value",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "properties": [
+ {
+ "value": "foo"
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/colors_rgba_length",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": [
+ {
+ "label-value": 1,
+ "rgba": [0, 0, 0]
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/colors_rgba_type",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {
+ "colors": [
+ {
+ "label-value": 1,
+ "rgba": [0, 0, 0, 500]
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "image-label/colors_duplicate",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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.6-dev/tests/plate_suite.json b/0.6-dev/tests/plate_suite.json
new file mode 100644
index 00000000..3db70de7
--- /dev/null
+++ b/0.6-dev/tests/plate_suite.json
@@ -0,0 +1,883 @@
+{
+ "description": "Tests for the plate JSON schema",
+ "schema": {
+ "id": "schemas/plate.schema"
+ },
+ "tests": [
+ {
+ "formerly": "plate/minimal_no_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "plate/minimal_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/empty_rows",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/duplicate_rows",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ },
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_columns",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/empty_columns",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/duplicate_columns",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ },
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_wells",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/empty_wells",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": {}
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/duplicate_rows",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "concentration": 10
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_row_name",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "concentration": 10
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_well_path",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_well_rowIndex",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_well_columnIndex",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/well_1group",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A1",
+ "rowIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/well_3groups",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "plate/A/1",
+ "rowIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/non_alphanumeric_column",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "A1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/A1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "plate/missing_acquisition_id",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "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": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "field_count": 0,
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ }
+ ]
+}
diff --git a/0.6-dev/tests/strict_image_suite.json b/0.6-dev/tests/strict_image_suite.json
new file mode 100644
index 00000000..b52fd2d3
--- /dev/null
+++ b/0.6-dev/tests/strict_image_suite.json
@@ -0,0 +1,341 @@
+{
+ "description": "TBD",
+ "schema": {
+ "id": "schemas/strict_image.schema"
+ },
+ "tests": [
+ {
+ "formerly": "valid_strict/multiscales_example.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "name": "example",
+ "axes": [
+ {
+ "name": "t",
+ "type": "time",
+ "unit": "millisecond"
+ },
+ {
+ "name": "c",
+ "type": "channel"
+ },
+ {
+ "name": "z",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [1.0, 1.0, 0.5, 0.5, 0.5]
+ }
+ ]
+ },
+ {
+ "path": "1",
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [1.0, 1.0, 1.0, 1.0, 1.0]
+ }
+ ]
+ },
+ {
+ "path": "2",
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [1.0, 1.0, 2.0, 2.0, 2.0]
+ }
+ ]
+ }
+ ],
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [0.1, 1.0, 1.0, 1.0, 1.0]
+ }
+ ],
+ "type": "gaussian",
+ "metadata": {
+ "description": "the fields in metadata depend on the downscaling implementation. Here, the parameters passed to the skimage function are given",
+ "method": "skimage.transform.pyramid_gaussian",
+ "version": "0.16.1",
+ "args": "[true]",
+ "kwargs": {
+ "multichannel": true
+ }
+ }
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid_strict/multiscales_transformations.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ],
+ "coordinateTransformations": [
+ {
+ "scale": [10, 10],
+ "type": "scale"
+ }
+ ],
+ "name": "image_with_coordinateTransformations",
+ "type": "foo",
+ "metadata": {
+ "key": "value"
+ }
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid_strict/image_metadata.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "@id": "top",
+ "@type": "ngff:Image",
+ "multiscales": [
+ {
+ "@id": "inner",
+ "name": "example",
+ "datasets": [
+ {
+ "path": "path/to/0",
+ "coordinateTransformations": [
+ {
+ "type": "scale",
+ "scale": [1, 1]
+ }
+ ]
+ }
+ ],
+ "type": "gaussian",
+ "metadata": {
+ "method": "skimage.transform.pyramid_gaussian",
+ "version": "0.16.1",
+ "args": ["true", "false"],
+ "kwargs": {
+ "multichannel": true
+ }
+ },
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid_strict/image.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1],
+ "type": "scale"
+ }
+ ]
+ }
+ ],
+ "name": "simple_image",
+ "type": "foo",
+ "metadata": {
+ "key": "value"
+ }
+ }
+ ]
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "valid_strict/image_omero.json",
+ "description": "TBD",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "multiscales": [
+ {
+ "axes": [
+ {
+ "name": "t",
+ "type": "time"
+ },
+ {
+ "name": "c",
+ "type": "channel"
+ },
+ {
+ "name": "z",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "y",
+ "type": "space",
+ "unit": "micrometer"
+ },
+ {
+ "name": "x",
+ "type": "space",
+ "unit": "micrometer"
+ }
+ ],
+ "datasets": [
+ {
+ "path": "0",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 0.5, 0.13, 0.13],
+ "type": "scale"
+ },
+ {
+ "translation": [0, 9, 0.5, 25.74, 21.58],
+ "type": "translation"
+ }
+ ]
+ },
+ {
+ "path": "1",
+ "coordinateTransformations": [
+ {
+ "scale": [1, 1, 1, 0.26, 0.26],
+ "type": "scale"
+ }
+ ]
+ }
+ ],
+ "name": "image_with_omero_metadata",
+ "type": "foo",
+ "metadata": {
+ "key": "value"
+ }
+ }
+ ],
+ "omero": {
+ "channels": [
+ {
+ "active": true,
+ "coefficient": 1.0,
+ "color": "00FF00",
+ "family": "linear",
+ "inverted": false,
+ "label": "FITC",
+ "window": {
+ "end": 813.0,
+ "max": 870.0,
+ "min": 102.0,
+ "start": 82.0
+ }
+ },
+ {
+ "active": true,
+ "coefficient": 1.0,
+ "color": "FF0000",
+ "family": "linear",
+ "inverted": false,
+ "label": "RD-TR-PE",
+ "window": {
+ "end": 815.0,
+ "max": 441.0,
+ "min": 129.0,
+ "start": 78.0
+ }
+ }
+ ],
+ "id": 1,
+ "rdefs": {
+ "defaultT": 0,
+ "defaultZ": 2,
+ "model": "color"
+ },
+ "version": "0.5-dev"
+ }
+ }
+ },
+ "valid": true
+ }
+ ]
+}
diff --git a/0.6-dev/tests/strict_label_suite.json b/0.6-dev/tests/strict_label_suite.json
new file mode 100644
index 00000000..1b3535c2
--- /dev/null
+++ b/0.6-dev/tests/strict_label_suite.json
@@ -0,0 +1,18 @@
+{
+ "description": "Tests for the strict image-label JSON schema",
+ "schema": {
+ "id": "schemas/strict_label.schema"
+ },
+ "tests": [
+ {
+ "formerly": "image-label/no_colors",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "image-label": {}
+ }
+ },
+ "valid": false
+ }
+ ]
+}
diff --git a/0.6-dev/tests/strict_plate_suite.json b/0.6-dev/tests/strict_plate_suite.json
new file mode 100644
index 00000000..7cea0747
--- /dev/null
+++ b/0.6-dev/tests/strict_plate_suite.json
@@ -0,0 +1,171 @@
+{
+ "description": "Tests for the strict plate JSON schema",
+ "schema": {
+ "id": "schemas/strict_plate.schema"
+ },
+ "tests": [
+ {
+ "formerly": "plate/strict_no_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "name": "test plate",
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "plate/missing_name",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/strict_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "acquisitions": [
+ {
+ "id": 0,
+ "name": "0",
+ "maximumfieldcount": 1
+ }
+ ],
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "name": "test plate",
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "plate/missing_acquisition_name",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "acquisitions": [
+ {
+ "id": 0,
+ "maximumfieldcount": 1
+ }
+ ],
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "name": "test plate",
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ },
+ {
+ "formerly": "plate/missing_acquisition_maximumfieldcount",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "plate": {
+ "acquisitions": [
+ {
+ "id": 0,
+ "name": "0"
+ }
+ ],
+ "columns": [
+ {
+ "name": "A"
+ }
+ ],
+ "name": "test plate",
+ "rows": [
+ {
+ "name": "1"
+ }
+ ],
+ "wells": [
+ {
+ "path": "A/1",
+ "rowIndex": 0,
+ "columnIndex": 0
+ }
+ ]
+ }
+ }
+ },
+ "valid": false
+ }
+ ]
+}
diff --git a/0.6-dev/tests/strict_well_suite.json b/0.6-dev/tests/strict_well_suite.json
new file mode 100644
index 00000000..f56b6c24
--- /dev/null
+++ b/0.6-dev/tests/strict_well_suite.json
@@ -0,0 +1,41 @@
+{
+ "description": "Tests for the strict well JSON schema",
+ "schema": {
+ "id": "schemas/strict_well.schema"
+ },
+ "tests": [
+ {
+ "formerly": "well/strict_no_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "well": {
+ "images": [
+ {
+ "path": "0"
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "plate/strict_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "well": {
+ "images": [
+ {
+ "acquisition": 0,
+ "path": "0"
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ }
+ ]
+}
diff --git a/0.6-dev/tests/test_validation.py b/0.6-dev/tests/test_validation.py
new file mode 100644
index 00000000..c2844f1a
--- /dev/null
+++ b/0.6-dev/tests/test_validation.py
@@ -0,0 +1,130 @@
+import json
+import glob
+import os
+
+from dataclasses import dataclass
+from typing import List
+
+import pytest
+
+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
+
+GENERIC_SCHEMA = schema_store[
+ "https://ngff.openmicroscopy.org/0.5/schemas/ome_zarr.schema"
+]
+
+print(schema_store)
+
+
+@dataclass
+class Suite:
+ schema: dict
+ data: dict
+ valid: bool = True
+
+ def validate(self, validator) -> None:
+ if not self.valid:
+ with pytest.raises(ValidationError):
+ validator.validate(self.data)
+ else:
+ validator.validate(self.data)
+
+ def maybe_validate(self, validator) -> None:
+ if self.valid:
+ validator.validate(self.data)
+
+
+def pytest_generate_tests(metafunc):
+ """
+ Generates tests for the examples/ as well as tests/ subdirectories.
+
+ Examples:
+ These tests evaluate all of the files under the examples/ directory
+ using the configuration in the provided config file in order detect
+ what should be run. It is assumed that all files are valid and complete
+ so that they can be wholly included into the specification. The
+ .config.json file in each directory defines which schema will be used.
+
+ Validation:
+ These test consumes https://github.com/json-schema-org/JSON-Schema-Test-Suite#structure-of-a-test
+ styled JSON tests. Metadata in each test defines which schema is used
+ and whether or not the block is considered valid.
+ """
+ if "suite" in metafunc.fixturenames:
+ suites: List[Schema] = []
+ ids: List[str] = []
+ schema_store = {}
+ for filename in glob.glob("schemas/*.schema"):
+ with open(filename) as o:
+ schema = json.load(o)
+ schema_store[schema["$id"]] = schema
+
+ # Validation
+ for filename in glob.glob("tests/*.json"):
+ with open(filename) as o:
+ suite = json.load(o)
+ schema = suite["schema"]
+ with open(schema["id"]) as f:
+ schema = json.load(f)
+ for test in suite["tests"]:
+ ids.append("validate_" + str(test["formerly"]).split("/")[-1][0:-5])
+ suites.append(Suite(schema, test["data"], test["valid"]))
+
+ # Examples
+ for config_filename in glob.glob("examples/*/.config.json"):
+ with open(config_filename) as o:
+ data = json.load(o)
+ schema = data["schema"]
+ with open(schema) as f:
+ schema = json.load(f)
+ 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)
+ data = data["attributes"] # Only validate the attributes object
+ ids.append("example_" + str(filename).split("/")[-1][0:-5])
+ suites.append(Suite(schema, data, True)) # Assume true
+
+ metafunc.parametrize("suite", suites, ids=ids, indirect=True)
+
+
+@pytest.fixture
+def suite(request):
+ return request.param
+
+
+def test_run(suite):
+ resolver = RefResolver.from_schema(suite.schema, store=schema_store)
+ validator = Validator(suite.schema, resolver=resolver)
+ suite.validate(validator)
+
+
+def test_generic_run(suite):
+ resolver = RefResolver.from_schema(GENERIC_SCHEMA, store=schema_store)
+ validator = Validator(GENERIC_SCHEMA, resolver=resolver)
+ suite.maybe_validate(validator)
+
+
+def test_example_configs():
+ """
+ Test that all example folders have a config file
+ """
+ missing = []
+ for subdir in os.walk("examples"):
+ has_examples = glob.glob(f"{subdir[0]}/*.json")
+ has_config = glob.glob(f"{subdir[0]}/.config.json")
+ if has_examples and not has_config:
+ missing.append(subdir[0])
+ if missing:
+ raise Exception(f"Directories missing configs: {missing}")
diff --git a/0.6-dev/tests/well_suite.json b/0.6-dev/tests/well_suite.json
new file mode 100644
index 00000000..7fbf8ca2
--- /dev/null
+++ b/0.6-dev/tests/well_suite.json
@@ -0,0 +1,80 @@
+{
+ "description": "Tests for the well JSON schema",
+ "schema": {
+ "id": "schemas/well.schema"
+ },
+ "tests": [
+ {
+ "formerly": "well/minimal_no_acquisition",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "well": {
+ "images": [
+ {
+ "path": "0"
+ }
+ ]
+ }
+ }
+ },
+ "valid": true
+ },
+ {
+ "formerly": "well/minimal_acquisitions",
+ "data": {
+ "ome": {
+ "version": "0.5",
+ "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/non_integer_acquisition_id",
+ "data": {
+ "well": {
+ "images": [
+ {
+ "acquisition": "0",
+ "path": "0"
+ }
+ ]
+ }
+ },
+ "valid": false
+ }
+ ]
+}
diff --git a/0.6-dev/tox.ini b/0.6-dev/tox.ini
new file mode 100644
index 00000000..632ca64e
--- /dev/null
+++ b/0.6-dev/tox.ini
@@ -0,0 +1,10 @@
+[tox]
+envlist = v04
+skipsdist = True
+
+[testenv]
+deps =
+ pytest
+ jsonschema
+commands =
+ pytest tests --color=yes --basetemp={envtmpdir} {posargs:-v}
\ No newline at end of file
diff --git a/0.6-dev/transform-details.bs b/0.6-dev/transform-details.bs
new file mode 100644
index 00000000..b2b744c8
--- /dev/null
+++ b/0.6-dev/transform-details.bs
@@ -0,0 +1,106 @@
++Title: Coordinates and Transformations +Shortname: ome-ngff-transformations +Level: 1 +Status: LS-COMMIT +Status: w3c/ED +Group: ome +URL: https://ngff.openmicroscopy.org/latest/ +Repository: https://github.com/ome/ngff +Issue Tracking: Forums https://forum.image.sc/tag/ome-ngff +Logo: http://www.openmicroscopy.org/img/logos/ome-logomark.svg +Local Boilerplate: header no +Local Boilerplate: copyright no +Boilerplate: style-darkmode off +Markup Shorthands: markdown yes +Editor: Josh Moore, Open Microscopy Environment (OME) https://www.openmicroscopy.org +Editor: Sébastien Besson, Open Microscopy Environment (OME) https://www.openmicroscopy.org +Editor: Constantin Pape, European Molecular Biology Laboratory (EMBL) https://www.embl.org/sites/heidelberg/ +Editor: John Bogovic, Hughes Medical Institute Janelia (HHMI) https://www.janelia.org/ +Abstract: This document contains next-generation file format (NGFF) +Abstract: specifications for storing bioimaging data in the cloud. +Abstract: All specifications are submitted to the https://image.sc community for review. +Status Text: The current released version of this specification is +Status Text: will be provided between numbered versions. Data written with these latest changes +Status Text: (an "editor's draft") will not necessarily be supported. ++ +Coordinates and Axes {#coords-axes} +===================== + +OME-NGFF datasets are arrays that hold values. The arrays may be indexed by discrete (integer) +coordinates in order to obtain a corresponding value. If values are desired at continuous (real-valued) +coordinates, then interpolation is required. + +Interpolation {#interp} +--------------------- + +Interpolation is the process of producing values at continuous coordinates from data sampled at discrete +coordinates. "Nearest-neighbor" and "N-Linear" are the two most commonly used interpolation methods. + + +Pixel coordinates {#pix-coords} +--------------------- + +**The pixel center is the origin of the continuous coordinate system.** + +### Top-left convention + +A common alternative convention is for the origin in the continuous space is at the "top-left" of the pixel. +This is not recommended, but can be acheived by explicitly adding a half-pixel translation, for example: + +```json +{ + "name": "center_to_top-left", + "type": "translation", + "translation" : [0.5, 0.5], + "output_space" : "top-left-space" +} +``` + +Coordinate Transformations {#coord-tforms} +===================== + +This document describes background and motivation that is outside the NGFF specification. + + +Direction {#direction} +--------------------- + +Specified coordinate transforms are in the "forward" direction. They represent functions +from *points* in the input space to *points* in the output space. For example, the transformation `"ij2xy"` + + +```json +{ + "name": "ij2xy", + "type": "scale", + "scale": [2, 0.5] + "input_axes" : ["i", "j"] + "output_axes" : ["x", "y"] +} +``` + +representes the function + +``` +x = 2 * i +y = 0.5 * j +``` + + +Recommendations {#recommendations} +===================== + + +"Native" physical space +--------------------- + +Datasets SHOULD define a transformation from array space to their "native physical space." +This transformation SHOULD describe physical pixel spacing and origin only, and therefore SHOULD consist of +`scale` and/or `translation` types only. + +Subsequent reorientation / registration transformations SHOULD use this native space as their `input_space`, +i.e., transformations should be defined in physical coordinates. + +