diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index 4b0fe271..0679ea76 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -21,6 +21,7 @@ jobs: issue-number: ${{ github.event.pull_request.number }} body: | #### Automated Review URLs - * [render latest/index.bs](http://api.csswg.org/bikeshed/?url=https://raw.githubusercontent.com/ome/ngff/${{ github.head.sha }}/latest/index.bs) - * [diff latest modified](https://services.w3.org/htmldiff?doc1=https%3A%2F%2Fngff.openmicroscopy.org%2Flatest%2F&doc2=http%3A%2F%2Fapi.csswg.org%2Fbikeshed%2F%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fome%2Fngff%2F${{ github.head.sha }}%2Flatest%2Findex.bs) + * [Readthedocs](https://ngff--${{ github.event.pull_request.number }}.org.readthedocs.build/) + * [render latest/index.bs](http://api.csswg.org/bikeshed/?url=https://raw.githubusercontent.com/ome/ngff/${{ github.event.pull_request.head.sha }}/latest/index.bs) + * [diff latest modified](https://services.w3.org/htmldiff?doc1=https%3A%2F%2Fngff.openmicroscopy.org%2Flatest%2F&doc2=http%3A%2F%2Fapi.csswg.org%2Fbikeshed%2F%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fome%2Fngff%2F${{ github.event.pull_request.head.sha }}%2Flatest%2Findex.bs) edit-mode: replace diff --git a/.gitignore b/.gitignore index 53de2396..89502188 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ */.DS_Store -**/__pycache__/* \ No newline at end of file +**/__pycache__/* +*/index.html +_build +_bikeshed +.tox +.vscode diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..11ce7bdd --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,13 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.10" + +sphinx: + configuration: conf.py + +python: + install: + - requirements: requirements.txt diff --git a/0.1/index.bs b/0.1/index.bs index b60204f1..52a33115 100644 --- a/0.1/index.bs +++ b/0.1/index.bs @@ -501,8 +501,7 @@ Projects which support reading and/or writing OME-NGFF data include: -Diagram of related projects +Diagram of related projects All implementations prevent an equivalent representation of a dataset which can be downloaded or uploaded freely. An interactive version of this diagram is available from the [OME2020 Workshop](https://downloads.openmicroscopy.org/presentations/2020/Dundee/Workshops/NGFF/zarr_diagram/). diff --git a/0.2/index.bs b/0.2/index.bs index 4e25ad2c..487f91a3 100644 --- a/0.2/index.bs +++ b/0.2/index.bs @@ -559,8 +559,7 @@ Projects which support reading and/or writing OME-NGFF data include: -Diagram of related projects +Diagram of related projects All implementations prevent an equivalent representation of a dataset which can be downloaded or uploaded freely. An interactive version of this diagram is available from the [OME2020 Workshop](https://downloads.openmicroscopy.org/presentations/2020/Dundee/Workshops/NGFF/zarr_diagram/). diff --git a/0.3/index.bs b/0.3/index.bs index 84192b65..47bc2dcf 100644 --- a/0.3/index.bs +++ b/0.3/index.bs @@ -569,8 +569,7 @@ Projects which support reading and/or writing OME-NGFF data include: -Diagram of related projects +Diagram of related projects All implementations prevent an equivalent representation of a dataset which can be downloaded or uploaded freely. An interactive version of this diagram is available from the [OME2020 Workshop](https://downloads.openmicroscopy.org/presentations/2020/Dundee/Workshops/NGFF/zarr_diagram/). diff --git a/0.4/examples/bf2raw/.config.json b/0.4/examples/bf2raw/.config.json new file mode 100644 index 00000000..2525328c --- /dev/null +++ b/0.4/examples/bf2raw/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/bf2raw.schema" +} diff --git a/0.4/examples/bf2raw/image.json b/0.4/examples/bf2raw/image.json new file mode 100644 index 00000000..c5eadb8a --- /dev/null +++ b/0.4/examples/bf2raw/image.json @@ -0,0 +1,3 @@ +{ + "bioformats2raw.layout" : 3 +} \ No newline at end of file diff --git a/0.4/examples/bf2raw/plate.json b/0.4/examples/bf2raw/plate.json new file mode 100644 index 00000000..bd98a16e --- /dev/null +++ b/0.4/examples/bf2raw/plate.json @@ -0,0 +1,22 @@ +{ + "bioformats2raw.layout" : 3, + "plate" : { + "columns" : [ { + "name" : "1" + } ], + "name" : "Plate Name 0", + "wells" : [ { + "path" : "A/1", + "rowIndex" : 0, + "columnIndex" : 0 + } ], + "field_count" : 1, + "rows" : [ { + "name" : "A" + } ], + "acquisitions" : [ { + "id" : 0 + } ], + "version" : "0.4" + } +} diff --git a/0.4/examples/multiscales_strict/multiscales_transformations.json b/0.4/examples/multiscales_strict/multiscales_transformations.json index 82836d0f..0097c47c 100644 --- a/0.4/examples/multiscales_strict/multiscales_transformations.json +++ b/0.4/examples/multiscales_strict/multiscales_transformations.json @@ -5,12 +5,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/0.4/examples/ome/.config.json b/0.4/examples/ome/.config.json new file mode 100644 index 00000000..8a611ccf --- /dev/null +++ b/0.4/examples/ome/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/ome.schema" +} diff --git a/0.4/examples/ome/series-2.json b/0.4/examples/ome/series-2.json new file mode 100644 index 00000000..be7e9ed6 --- /dev/null +++ b/0.4/examples/ome/series-2.json @@ -0,0 +1,3 @@ +{ + "series" : [ "0", "1" ] +} diff --git a/0.4/index.bs b/0.4/index.bs index 18a6656f..a2df9c05 100644 --- a/0.4/index.bs +++ b/0.4/index.bs @@ -99,6 +99,14 @@ The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL “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 commments. However, these are only for clarity purposes and comments MUST NOT be included in JSON objects. @@ -137,7 +145,7 @@ For this example we assume an image with 5 dimensions and axes called `t,c,z,y,x ├── .zgroup # Each image is a Zarr group, or a folder, of other groups and arrays. ├── .zattrs # Group level attributes are stored in the .zattrs file and include │ # "multiscales" and "omero" (see below). In addition, the group level attributes - │ # must also contain "_ARRAY_DIMENSIONS" if this group directly contains multi-scale arrays. + │ # may also contain "_ARRAY_DIMENSIONS" for compatibility with xarray if this group directly contains multi-scale arrays. │ ├── 0 # Each multiscale level is stored as a separate Zarr array, │ ... # which is a folder containing chunk files which compose the array. @@ -240,6 +248,85 @@ keys as specified below for discovering certain types of data, especially images If part of [[#multiscale-md]], the length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. +"bioformats2raw.layout" (transitional) {#bf2raw} +------------------------------------------------ + +[=Transitional=] "bioformats2raw.layout" metadata identifies a group which implicitly describes a series of images. +The need for the collection stems from the common "multi-image file" scenario in microscopy. Parsers like Bio-Formats +define a strict, stable ordering of the images in a single container that can be used to refer to them by other tools. + +In order to capture that information within an OME-NGFF dataset, `bioformats2raw` internally introduced a wrapping layer. +The bioformats2raw layout has been added to v0.4 as a transitional specification to specify filesets that already exist +in the wild. An upcoming NGFF specification will replace this layout with explicit metadata. + +

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
+    ├── .zgroup
+    ├── .zattrs               # Contains "bioformats2raw.layout" metadata
+    ├── OME                   # Special group for containing OME metadata
+    │   ├── .zgroup
+    │   ├── .zattrs           # 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 top-level `.zattrs` 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 `.zattrs` 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 `.zattrs` metadata 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 `` elements as opposed to ``, `` or ``; + - MAY make use of the [minimum specification](https://docs.openmicroscopy.org/ome-model/6.2.2/specifications/minimum.html). + +Additionally, the logic for finding the Zarr group for each image follows the following logic: + +- If "plate" metadata is present, images MUST be located at the defined location. + - Matching "series" metadata (as described next) SHOULD be provided for tools that are unaware of the "plate" specification. +- If the "OME" Zarr group exists, it: + - MAY contain a "series" attribute. If so: + - "series" MUST be a list of string objects, each of which is a path to an image group. + - The order of the paths MUST match the order of the "Image" elements in "OME/METADATA.ome.xml" if provided. +- If the "series" attribute does not exist and no "plate" is present: + - separate "multiscales" images MUST be stored in consecutively numbered groups starting from 0 (i.e. "0/", "1/", "2/", "3/", ...). +- Every "multiscales" group MUST represent exactly one OME-XML "Image" in the same order as either the series index or the group numbers. + +Conforming readers: +- SHOULD make users aware of the presence of more than one image (i.e. SHOULD NOT default to only opening the first image); +- MAY use the "series" attribute in the "OME" group to determine a list of valid groups to display; +- MAY choose to show all images within the collection or offer the user a choice of images, as with HCS plates; +- MAY ignore other groups or arrays under the root of the hierarchy. "coordinateTransformations" metadata {#trafo-md} ------------------------------------- @@ -315,10 +402,10 @@ if not datasets: datasets = [x["path"] for x in multiscales[0]["datasets"]] ``` -"omero" metadata {#omero-md} ----------------------------- +"omero" metadata (transitional) {#omero-md} +------------------------------------------- -Information specific to the channels of an image and how to render it +[=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 @@ -351,6 +438,12 @@ can be found under the "omero" key in the group-level metadata: See https://docs.openmicroscopy.org/omero/5.6.1/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} ------------------------------ @@ -552,8 +645,7 @@ Projects which support reading and/or writing OME-NGFF data include: -Diagram of related projects +Diagram of related projects All implementations prevent an equivalent representation of a dataset which can be downloaded or uploaded freely. An interactive version of this diagram is available from the [OME2020 Workshop](https://downloads.openmicroscopy.org/presentations/2020/Dundee/Workshops/NGFF/zarr_diagram/). @@ -581,6 +673,11 @@ Version History {#history} Description + + 0.4.1 + 2022-09-26 + transitional metadata for image collections ("bioformats2raw.layout") + 0.4.0 2022-02-08 diff --git a/0.4/schemas/bf2raw.schema b/0.4/schemas/bf2raw.schema new file mode 100644 index 00000000..834aee24 --- /dev/null +++ b/0.4/schemas/bf2raw.schema @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/latest/schemas/bf2raw.schema", + "title": "NGFF container produced by bioformats2raw", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "bioformats2raw.layout": { + "description": "The top-level identifier metadata added by bioformats2raw", + "type": "number", + "enum": [3] + } + } +} diff --git a/0.4/schemas/image.schema b/0.4/schemas/image.schema index 59e8e28e..aec5db5f 100644 --- a/0.4/schemas/image.schema +++ b/0.4/schemas/image.schema @@ -124,7 +124,7 @@ "type": "string", "enum": ["space"] }, - "units": { + "unit": { "type": "string" } } diff --git a/0.4/schemas/ome.schema b/0.4/schemas/ome.schema new file mode 100644 index 00000000..bd600a2a --- /dev/null +++ b/0.4/schemas/ome.schema @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/latest/schemas/ome.schema", + "title": "NGFF group produced by bioformats2raw to contain OME metadata", + "description": "JSON from OME-NGFF OME/.zattrs linked to an OME-XML file", + "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 + } + } +} diff --git a/0.4/tests/image_suite.json b/0.4/tests/image_suite.json index f22fa67f..42906985 100644 --- a/0.4/tests/image_suite.json +++ b/0.4/tests/image_suite.json @@ -14,17 +14,17 @@ { "name": "t", "type": "time", - "units": "micrometer" + "unit": "micrometer" }, { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -60,12 +60,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -115,12 +115,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } @@ -138,12 +138,12 @@ { "name": "y", "type": "space", - "units": "micron" + "unit": "micron" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -204,12 +204,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } @@ -231,12 +231,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -270,12 +270,12 @@ { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -344,12 +344,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -382,12 +382,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -476,12 +476,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -530,11 +530,11 @@ "axes": [ { "type": "space", - "units": "micron" + "unit": "micron" }, { "type": "space", - "units": "micron" + "unit": "micron" } ], "datasets": [ @@ -567,7 +567,7 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -641,12 +641,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -679,12 +679,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -725,12 +725,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -754,12 +754,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [], @@ -779,12 +779,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "version": "0.4" @@ -829,12 +829,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -867,12 +867,12 @@ { "name": "y", "type": "invalid", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -905,12 +905,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1032,12 +1032,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1087,12 +1087,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1117,12 +1117,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/0.4/tests/strict_image_suite.json b/0.4/tests/strict_image_suite.json index 22b34c5e..ec6295d3 100644 --- a/0.4/tests/strict_image_suite.json +++ b/0.4/tests/strict_image_suite.json @@ -122,12 +122,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -205,12 +205,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } @@ -228,12 +228,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -279,17 +279,17 @@ { "name": "z", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/README.md b/README.md index 1393bf16..4684d196 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![DOI](https://zenodo.org/badge/313652456.svg)](https://zenodo.org/badge/latestdoi/313652456) + # ome-ngff [Next-generation file format (NGFF) specifications](https://ngff.openmicroscopy.org/latest/) for storing bioimaging data in the cloud. @@ -29,6 +31,26 @@ Commits on GitHub can be viewed using web services from the W3C: * Update changelog at the bottom of `latest/index.bs` * Find references to previous version and _in most cases_, bump to the current version. +## JSON schemas + +For each top-level metadata key of the OME-NGFF specification, JSON schemas are maintained +for each version of the specification and stored under `$VERSION/schemas/` or `latest/schemas/`. +Tests validating these schemas must be implemented to follow principles of the +[JSON schema test suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite) +and stored under `$VERSION/tests/` or `latest/tests/` to allow their execution on each CI build. + +All official example snippets must also be extracted and managed as separate JSON files under +`$VERSION/examples/` or `latest/examples/`, validated by the appropriate schema by adding a +`.config.json` file specifying the JSON schema to use and included in the +specification document using the +[include-code](https://tabatkins.github.io/bikeshed/#including-code) directive. + +The official OME-NGFF JSON schemas are published under +https://ngff.openmicroscopy.org//schemas/.schema using the +[Spec prod](https://github.com/ome/spec-prod) GitHub action. When a new JSON schema is introduced, +this action needs to be reviewed to update the deployment script and allow the publication +of the schema. + # Release process * copy `latest/index.bs` to `$VERSION/index.bs` @@ -43,7 +65,7 @@ Commits on GitHub can be viewed using web services from the W3C: * Version in the citation block including release date * Update https://github.com/ome/spec-prod for the new version -## Citing +# Citing Please see https://ngff.openmicroscopy.org/latest#citing for the latest citation. diff --git a/about/index.md b/about/index.md new file mode 100644 index 00000000..99713ee8 --- /dev/null +++ b/about/index.md @@ -0,0 +1,76 @@ +About +===== + +Bioimaging science is at a crossroads. Currently, the drive to acquire more, +larger, preciser spatial measurements is unfortunately at odds with our ability +to structure and share those measurements with others. During a global pandemic +more than ever, we believe fervently that global, collaborative discovery as +opposed to the post-publication, "data-on-request" mode of operation is the +path forward. Bioimaging data should be shareable via open and commercial cloud +resources without the need to download entire datasets. + +At the moment, that is not the norm. The plethora of data formats produced by +imaging systems are ill-suited to remote sharing. Individual scientists +typically lack the infrastructure they need to host these data themselves. When +they acquire images from elsewhere, time-consuming translations and data +cleaning are needed to interpret findings. Those same costs are multiplied when +gathering data into online repositories where curator time can be the limiting +factor before publication is possible. Without a common effort, each lab or +resource is left building the tools they need and maintaining that +infrastructure often without dedicated funding. + +This document defines a specification for bioimaging data to make it possible +to enable the conversion of proprietary formats into a common, cloud-ready one. +Such next-generation file formats layout data so that individual portions, or +"chunks", of large data are reference-able eliminating the need to download +entire datasets. + + +Why "NGFF"? +----------- + +A short description of what is needed for an imaging format is "a hierarchy +of n-dimensional (dense) arrays with metadata". This combination of features +is certainly provided by `HDF5` +from the [HDF Group](https://www.hdfgroup.org), which a number of +bioimaging formats do use. HDF5 and other larger binary structures, however, +are ill-suited for storage in the cloud where accessing individual chunks +of data by name rather than seeking through a large file is at the heart of +parallelization. + +As a result, a number of formats have been developed more recently which provide +the basic data structure of an HDF5 file, but do so in a more cloud-friendly way. +In the [PyData](https://pydata.org/) community, the Zarr [[zarr]] format was developed +for easily storing collections of [NumPy](https://numpy.org/) arrays. In the +[ImageJ](https://imagej.net/) community, N5 [[n5]] was developed to work around +the limitations of HDF5 ("N5" was originally short for "Not-HDF5"). +Both of these formats permit storing individual chunks of data either locally in +separate files or in cloud-based object stores as separate keys. + +An [updated Zarr version (v3)](https://zarr-specs.readthedocs.io/) +is underway to unify the two similar specifications to provide a single binary +specification. See this [blog post](https://zarr.dev/blog/zep1-update/) for more information. + +In addition to the next-generation file format (NGFF) [specifications](../specifications/index.md), +the pages listed below are intended to provide an overview of external resources available +for working with NGFF data. + +The following pages are intended to provide an overview of the available resources in the NGFF space: + +* [Data Resources](../data/index.md): List of data repositories where OME-Zarr data can be found. +* [Tools](../tools/index.rst): GUIs and libraries that can be used for accessing OME-Zarr formatted data. +* [Publications](../publications/index.md): List of publications referencing OME-NGFF or publishing + datasets in OME-Zarr. + +Additionally, notes and recordings of the past NGFF community calls are available: + +| Call | Date | Presenters | Forum thread | Notes | +|------|------|------------|--------------|-------| +|1| 2020-10-20 | | [image.sc](https://forum.image.sc/t/upcoming-calls-on-next-gen-bioimaging-data-tools-starting-oct-29/43489) | [hackmd](https://hackmd.io/_sftykiGR9mSyUan3l1WmA) | +|2| 2020-12-02 (with I2K)| | [image.sc](https://forum.image.sc/t/next-call-on-next-gen-bioimaging-data-tools-dec-2/45816) | [hackmd](https://hackmd.io/X348vzCaTRSmIpsa3dK-Sg)| +|3| 2021-02-23| |[image.sc](https://forum.image.sc/t/next-call-on-next-gen-bioimaging-data-tools-feb-23/48386)| [hackmd](https://hackmd.io/Ndb5IHRmQn2PCCNBLkG-fQ)| +|4| 2021-06 with Fiji Hackathon| |[image.sc](https://forum.image.sc/t/fiji-hackathon-2021-big-data-days-a/53926)| | | +|5 (0.4/axes)| 2021-09-02| Constantin | [image.sc](https://forum.image.sc/t/next-call-on-next-gen-bioimaging-data-tools-feb-23/48386) | [hackmd](https://hackmd.io/GZ1euZUSRZeqPTJj9WJEtg)| +|6 (0.4/axes)| 2022-01-27| Constantin, Will, Seb| [image.sc](https://forum.image.sc/t/next-call-on-next-gen-bioimaging-data-tools-2022-01-27/60885)| [hackmd](https://hackmd.io/QfiBKHIoTZ-CJSp3q0Wykg)| +|7 (0.5/tables & transforms)| 2022-10-05| Kevin & John| [image.sc](https://forum.image.sc/t/ome-ngff-community-call-transforms-and-tables/71792)| [hackmd](https://hackmd.io/TyfrLiCqRteL0Xfc8HRiOA) | +|8 (Metadata) | 2023-03-15 | Wouter-Michiel | [image.sc](https://forum.image.sc/t/community-call-metadata-in-ome-ngff/77570/10) | [hackmd](https://hackmd.io/BqnK9Wm4QpGYAhYOoaFBQQ) | diff --git a/community/index.md b/community/index.md new file mode 100644 index 00000000..895609d4 --- /dev/null +++ b/community/index.md @@ -0,0 +1,25 @@ +# Community + +## Office Hours + + + +[**Join here!**](https://openmicroscopy-org.zoom.us/j/82526689042?pwd=ZIde7mcvZugQGmJ8Bm9piFo5Tzwdy1.1) + +

We'll be hosting office hours on Wednesdays, rotating between +APAC/AU/EU- and AMER/AU/EU-friendly times. + +Please join us if you have questions about NGFF and want to learn more about +the OME-Zarr storage format. We'll discuss the specification, the implementations, +what's new in the ecosystem, how you can get involved in the community and +much more.

+ +

Please see the NGFF community calendar for exact +timings:

+ + + +Download the .ics file and add it to your calendar so won't miss any of our meetings! diff --git a/conf.py b/conf.py new file mode 100644 index 00000000..3b941302 --- /dev/null +++ b/conf.py @@ -0,0 +1,79 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'NGFF' +copyright = '2023, NGFF Community' +author = 'NGFF Community' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ["myst_parser"] +source_suffix = [".rst", ".md"] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.git', '.pytest_cache', '**/.pytest_cache', '**/.tox', 'README.md', 'LICENSE.md', 'CONTRIBUTING.md'] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'sphinx_book_theme' + +html_static_path = ['_static'] + +html_css_files = [ + 'https://cdn.datatables.net/v/dt/dt-1.11.5/datatables.min.css', +] + +html_js_files = [ + 'https://cdn.datatables.net/v/dt/dt-1.11.5/datatables.min.js', + 'main.js', +] + +html_extra_path = [ + '_bikeshed', +] + +# #################################### +# Run bikeshed build +# #################################### + +def bikeshed(): + + import glob + import os + import shutil + import subprocess + + for index_file in ["latest/index.bs"] + glob.glob("[0-9]*/index.bs"): + + output_file = index_file.replace("bs", "html") + output_dir = os.path.dirname(output_file) + target_dir = os.path.join("_bikeshed", output_dir) + + run_bikeshed = True + + # Give the loop a chance to skip files if no build is needed/requested + if "BIKESHED" not in os.environ and os.path.exists(output_file): + src_time = os.path.getmtime(index_file) + out_time = os.path.getmtime(output_file) + if src_time < out_time: + print(f"{index_file} unchanged") + run_bikeshed = False + + if run_bikeshed: + subprocess.check_call(f"bikeshed spec {index_file} {output_file}", shell=True) + + if os.path.exists(target_dir): + shutil.rmtree(target_dir) + shutil.copytree(output_dir, target_dir) + +bikeshed() +del bikeshed diff --git a/data/index.md b/data/index.md new file mode 100644 index 00000000..f4cdcec0 --- /dev/null +++ b/data/index.md @@ -0,0 +1,20 @@ +Data Resources +============== + +| Catalog | Hosting | Zarr Files | Size | +| ------------------------------------------------------------------------ | -----------------------------------------------------| ------------ | -------- | +| [BIA Samples](https://bit.ly/bia-ome-ngff-samples) | EBI | 90 | 200 GB | +| [Cell Painting Gallery](https://github.com/broadinstitute/cellpainting-gallery) | AWS Open Data Program | 136 | 20 TB | +| [CZB-Zebrahub](https://zebrahub.ds.czbiohub.org/imaging) | czbiohub | 5 | 1.2 TB | +| [DANDI](https://dandiarchive.org/dandiset/000108) ([identifiers.org][dandi2],[github][dandi3]) | AWS Open Data Program | 3914 | 355 TB | +| [Glencoe](https://glencoesoftware.com/ngff) | Glencoe Software, Inc. | 8 | 165 GB | +| [IDR Samples](https://idr.github.io/ome-ngff-samples/) | EBI | 88 | 3 TB | +| [MoBIE](https://mobie.github.io/specs/ngff.html) | EMBL-HD | 21 | 2 TB | +| [Neural Dynamics](https://registry.opendata.aws/allen-nd-open-data/) | AWS Open Data Program | 90 | 200 TB | +| [Sanger](https://www.sanger.ac.uk/project/ome-zarr/) | Sanger, UK | 10 | 1 TB | +| [SpatialData](https://github.com/scverse/spatialdata-notebooks/tree/main/datasets) | EMBL-HD | 10 | 25 GB | +| [SSBD](https://ssbd.riken.jp/ssbd-ome-ngff-samples) | SSBD | 12 | 196 GB | +| [webKnossos](https://zarr.webknossos.org) | scalableminds GmbH | 69 | 70 TB | + +[dandi2]: https://identifiers.org/DANDI:000108 +[dandi3]: https://github.com/dandisets/000108 diff --git a/index.html b/index.html deleted file mode 100644 index 74f803c4..00000000 --- a/index.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - -

If you are not redirected in five seconds, click here.

- diff --git a/index.rst b/index.rst new file mode 100644 index 00000000..ded27a68 --- /dev/null +++ b/index.rst @@ -0,0 +1,28 @@ +.. NGFF documentation master file, created by + sphinx-quickstart on Tue Mar 14 08:54:12 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Next-generation file formats (NGFF) +=================================== + +OME-NGFF is an imaging format specification being developed by the bioimaging community to +address issues of scalability and interoperability. +Please see the :doc:`about/index` section for an introduction. +The OME-NGFF specification is detailed under :doc:`specifications/index`. +Various Image viewers and other software for working with NGFF data +are listed on the :doc:`tools/index` page. +Sample NGFF datasets provided by the community can be found under :doc:`data/index`. + +.. toctree:: + :maxdepth: 2 + + about/index + community/index + data/index + publications/index + specifications/index + tools/index + +.. raw:: html + diff --git a/latest/examples/bf2raw/.config.json b/latest/examples/bf2raw/.config.json new file mode 100644 index 00000000..2525328c --- /dev/null +++ b/latest/examples/bf2raw/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/bf2raw.schema" +} diff --git a/latest/examples/bf2raw/image.json b/latest/examples/bf2raw/image.json new file mode 100644 index 00000000..c5eadb8a --- /dev/null +++ b/latest/examples/bf2raw/image.json @@ -0,0 +1,3 @@ +{ + "bioformats2raw.layout" : 3 +} \ No newline at end of file diff --git a/latest/examples/bf2raw/plate.json b/latest/examples/bf2raw/plate.json new file mode 100644 index 00000000..bd98a16e --- /dev/null +++ b/latest/examples/bf2raw/plate.json @@ -0,0 +1,22 @@ +{ + "bioformats2raw.layout" : 3, + "plate" : { + "columns" : [ { + "name" : "1" + } ], + "name" : "Plate Name 0", + "wells" : [ { + "path" : "A/1", + "rowIndex" : 0, + "columnIndex" : 0 + } ], + "field_count" : 1, + "rows" : [ { + "name" : "A" + } ], + "acquisitions" : [ { + "id" : 0 + } ], + "version" : "0.4" + } +} diff --git a/latest/examples/label_strict/colors_properties.json b/latest/examples/label_strict/colors_properties.json index 7f1d6f20..c96820e1 100644 --- a/latest/examples/label_strict/colors_properties.json +++ b/latest/examples/label_strict/colors_properties.json @@ -3,23 +3,25 @@ "version": "0.5-dev", "colors": [ { - "label-value": 1, - "rgba": [255, 255, 255, 255] + "label-value": 0, + "rgba": [0, 0, 128, 128] }, { - "label-value": 4, - "rgba": [0, 255, 255, 128] + "label-value": 1, + "rgba": [0, 128, 0, 128] } ], "properties": [ { - "label-value": 1, + "label-value": 0, "area (pixels)": 1200, - "class": "foo" + "class": "intercellular space" }, { - "label-value": 4, - "area (pixels)": 1650 + "label-value": 1, + "area (pixels)": 1650, + "class": "cell", + "cell type": "neuron" } ], "source": { diff --git a/latest/examples/multiscales_strict/multiscales_transformations.json b/latest/examples/multiscales_strict/multiscales_transformations.json index c99040c2..80dbedab 100644 --- a/latest/examples/multiscales_strict/multiscales_transformations.json +++ b/latest/examples/multiscales_strict/multiscales_transformations.json @@ -5,12 +5,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/latest/examples/ome/.config.json b/latest/examples/ome/.config.json new file mode 100644 index 00000000..8a611ccf --- /dev/null +++ b/latest/examples/ome/.config.json @@ -0,0 +1,3 @@ +{ + "schema": "schemas/ome.schema" +} diff --git a/latest/examples/ome/series-2.json b/latest/examples/ome/series-2.json new file mode 100644 index 00000000..be7e9ed6 --- /dev/null +++ b/latest/examples/ome/series-2.json @@ -0,0 +1,3 @@ +{ + "series" : [ "0", "1" ] +} diff --git a/latest/header.include b/latest/header.include index 28305fe4..e98bf6fe 100644 --- a/latest/header.include +++ b/latest/header.include @@ -11,7 +11,7 @@
- OME logo (6 circles in a hexagon) diff --git a/latest/index.bs b/latest/index.bs index 0ec5b1f1..498bcac7 100644 --- a/latest/index.bs +++ b/latest/index.bs @@ -26,60 +26,6 @@ Status Text: will be provided between numbered versions. Data written with these Status Text: (an "editor's draft") will not necessarily be supported. -Introduction {#intro} -===================== - -Bioimaging science is at a crossroads. Currently, the drive to acquire more, -larger, preciser spatial measurements is unfortunately at odds with our ability -to structure and share those measurements with others. During a global pandemic -more than ever, we believe fervently that global, collaborative discovery as -opposed to the post-publication, "data-on-request" mode of operation is the -path forward. Bioimaging data should be shareable via open and commercial cloud -resources without the need to download entire datasets. - -At the moment, that is not the norm. The plethora of data formats produced by -imaging systems are ill-suited to remote sharing. Individual scientists -typically lack the infrastructure they need to host these data themselves. When -they acquire images from elsewhere, time-consuming translations and data -cleaning are needed to interpret findings. Those same costs are multiplied when -gathering data into online repositories where curator time can be the limiting -factor before publication is possible. Without a common effort, each lab or -resource is left building the tools they need and maintaining that -infrastructure often without dedicated funding. - -This document defines a specification for bioimaging data to make it possible -to enable the conversion of proprietary formats into a common, cloud-ready one. -Such next-generation file formats layout data so that individual portions, or -"chunks", of large data are reference-able eliminating the need to download -entire datasets. - - -Why "NGFF"? {#why-ngff} -------------------------------------------------------------------------------------------------- - -A short description of what is needed for an imaging format is "a hierarchy -of n-dimensional (dense) arrays with metadata". This combination of features -is certainly provided by HDF5 -from the HDF Group, which a number of -bioimaging formats do use. HDF5 and other larger binary structures, however, -are ill-suited for storage in the cloud where accessing individual chunks -of data by name rather than seeking through a large file is at the heart of -parallelization. - -As a result, a number of formats have been developed more recently which provide -the basic data structure of an HDF5 file, but do so in a more cloud-friendly way. -In the [PyData](https://pydata.org/) community, the Zarr [[zarr]] format was developed -for easily storing collections of [NumPy](https://numpy.org/) arrays. In the -[ImageJ](https://imagej.net/) community, N5 [[n5]] was developed to work around -the limitations of HDF5 ("N5" was originally short for "Not-HDF5"). -Both of these formats permit storing individual chunks of data either locally in -separate files or in cloud-based object stores as separate keys. - -A [current effort](https://zarr-specs.readthedocs.io/en/core-protocol-v3.0-dev/protocol/core/v3.0.html) -is underway to unify the two similar specifications to provide a single binary -specification. The editor's draft will soon be entering a [request for comments (RFC)](https://github.com/zarr-developers/zarr-specs/issues/101) phase with the goal of having a first version early in 2021. As that -process comes to an end, this document will be updated. - OME-NGFF {#ome-ngff} -------------------- @@ -101,6 +47,14 @@ The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL “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 commments. However, these are only for clarity purposes and comments MUST NOT be included in JSON objects. @@ -139,7 +93,7 @@ For this example we assume an image with 5 dimensions and axes called `t,c,z,y,x ├── .zgroup # Each image is a Zarr group, or a folder, of other groups and arrays. ├── .zattrs # Group level attributes are stored in the .zattrs file and include │ # "multiscales" and "omero" (see below). In addition, the group level attributes - │ # must also contain "_ARRAY_DIMENSIONS" if this group directly contains multi-scale arrays. + │ # may also contain "_ARRAY_DIMENSIONS" for compatibility with xarray if this group directly contains multi-scale arrays. │ ├── 0 # Each multiscale level is stored as a separate Zarr array, │ ... # which is a folder containing chunk files which compose the array. @@ -242,9 +196,89 @@ keys as specified below for discovering certain types of data, especially images If part of [[#multiscale-md]], the length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. +"bioformats2raw.layout" (transitional) {#bf2raw} +------------------------------------------------ + +[=Transitional=] "bioformats2raw.layout" metadata identifies a group which implicitly describes a series of images. +The need for the collection stems from the common "multi-image file" scenario in microscopy. Parsers like Bio-Formats +define a strict, stable ordering of the images in a single container that can be used to refer to them by other tools. + +In order to capture that information within an OME-NGFF dataset, `bioformats2raw` internally introduced a wrapping layer. +The bioformats2raw layout has been added to v0.4 as a transitional specification to specify filesets that already exist +in the wild. An upcoming NGFF specification will replace this layout with explicit metadata. + +

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
+    ├── .zgroup
+    ├── .zattrs               # Contains "bioformats2raw.layout" metadata
+    ├── OME                   # Special group for containing OME metadata
+    │   ├── .zgroup
+    │   ├── .zattrs           # 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 top-level `.zattrs` 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 `.zattrs` 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 `.zattrs` metadata 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 `` elements as opposed to ``, `` or ``; + - MAY make use of the [minimum specification](https://docs.openmicroscopy.org/ome-model/6.2.2/specifications/minimum.html). + +Additionally, the logic for finding the Zarr group for each image follows the following logic: + +- If "plate" metadata is present, images MUST be located at the defined location. + - Matching "series" metadata (as described next) SHOULD be provided for tools that are unaware of the "plate" specification. +- If the "OME" Zarr group exists, it: + - MAY contain a "series" attribute. If so: + - "series" MUST be a list of string objects, each of which is a path to an image group. + - The order of the paths MUST match the order of the "Image" elements in "OME/METADATA.ome.xml" if provided. +- If the "series" attribute does not exist and no "plate" is present: + - separate "multiscales" images MUST be stored in consecutively numbered groups starting from 0 (i.e. "0/", "1/", "2/", "3/", ...). +- Every "multiscales" group MUST represent exactly one OME-XML "Image" in the same order as either the series index or the group numbers. + +Conforming readers: +- SHOULD make users aware of the presence of more than one image (i.e. SHOULD NOT default to only opening the first image); +- MAY use the "series" attribute in the "OME" group to determine a list of valid groups to display; +- MAY choose to show all images within the collection or offer the user a choice of images, as with HCS plates; +- MAY ignore other groups or arrays under the root of the hierarchy. + "coordinateTransformations" metadata {#trafo-md} -------------------------------------- +------------------------------------------------ "coordinateTransformations" describe a series of transformations that map between two coordinate spaces (defined by "axes"). For example, to map a discrete data space of an array to the corresponding physical space. @@ -292,7 +326,7 @@ Each "multiscales" dictionary MAY contain the field "coordinateTransformations", The transformations MUST follow the same rules about allowed types, order, etc. as in "datasets:coordinateTransformations" and are applied after them. They can for example be used to specify the `scale` for a dimension that is the same for all resolutions. -Each "multiscales" dictionary SHOULD contain the field "name". It SHOULD contain the field "version", which indicates the version of the multiscale metadata of this image (current version is [NGFFVERSION]). +Each "multiscales" dictionary SHOULD contain the field "name". It MUST contain the field "version", which indicates the version of the multiscale metadata of this image (current version is [NGFFVERSION]). Each "multiscales" dictionary SHOULD contain the field "type", which gives the type of downscaling method used to generate the multiscale image pyramid. It SHOULD contain the field "metadata", which contains a dictionary with additional information about the downscaling method. @@ -317,10 +351,10 @@ if not datasets: datasets = [x["path"] for x in multiscales[0]["datasets"]] ``` -"omero" metadata {#omero-md} ----------------------------- +"omero" metadata (transitional) {#omero-md} +------------------------------------------- -Information specific to the channels of an image and how to render it +[=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 @@ -356,59 +390,65 @@ for more information. "labels" metadata {#labels-md} ------------------------------ -The special group "labels" found under an image Zarr contains the key `labels` containing -the paths to label objects which can be found underneath the group: +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 `.zattrs` 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 { "labels": [ - "orphaned/0" + "cell_space_segmentation" ] } ``` -Unlisted groups MAY be labels. +The `.zattrs` 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. -"image-label" metadata {#label-md} ----------------------------------- +In addition to the `multiscales` key, the JSON object in this image-level `.zattrs` 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-NGFF `image-label` schema. -Groups containing the `image-label` dictionary represent an image segmentation -in which each unique pixel value represents a separate segmented object. -`image-label` groups MUST also contain `multiscales` metadata and the two -"datasets" series MUST have the same number of entries. +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. -The `image-label` dictionary SHOULD contain a `colors` key whose value MUST be a -list of JSON objects describing the unique label values. Each color object MUST -contain the `label-value` key whose value MUST be an integer specifying the -pixel value for that label. It MAY contain an `rgba` key whose value MUST be an array -of four integers between 0 and 255 `[uint8, uint8, uint8, uint8]` specifying the label -color as RGBA. All the values under the `label-value` key MUST be unique. Clients -who choose to not throw an error SHOULD ignore all except the _last_ entry. +Next, the `image-label` object MAY contain the following keys: a `properties` key, and a `source` key. -Some implementations MAY represent overlapping labels by using a specially assigned -value, for example the highest integer available in the pixel range. +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 `image-label` dictionary MAY contain a `properties` key whose value MUST be a -list of JSON objects which also describes the unique label values. Each property object -MUST contain the `label-value` key whose value MUST be an integer specifying the pixel -value for that label. Additionally, an arbitrary number of key-value pairs -MAY be present for each label value denoting associated metadata. Not all label -values must share the same key-value pairs within the properties list. +The 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. -The `image-label` dictionary MAY contain a `source` key whose value MUST be a JSON -object containing information on the image the label is associated with. If included, -it MAY include a key `image` whose value MUST be a string specifying the relative -path to a Zarr image group. The default value is "../../" since most labels are stored -under a subgroup named "labels/" (see above). - -The `image-label` dictionary SHOULD contain a `version` key whose value MUST be a string -specifying the version of the image-label specification. +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} ---------------------------- @@ -452,7 +492,7 @@ contain only alphanumeric characters, MUST be case-sensitive, and MUST NOT be a 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 SHOULD contain a `version` key whose value MUST be a string specifying the +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 @@ -552,10 +592,12 @@ Projects which support reading and/or writing OME-NGFF data include:
[vizarr](https://github.com/hms-dbmi/vizarr/)
A minimal, purely client-side program for viewing Zarr-based images with Viv & ImJoy.
+
[ITKIOOMEZarrNGFF](https://github.com/InsightSoftwareConsortium/ITKIOOMEZarrNGFF/)
+
ITK IO for images stored in OME-NGFF format.
+ -Diagram of related projects +Diagram of related projects All implementations prevent an equivalent representation of a dataset which can be downloaded or uploaded freely. An interactive version of this diagram is available from the [OME2020 Workshop](https://downloads.openmicroscopy.org/presentations/2020/Dundee/Workshops/NGFF/zarr_diagram/). @@ -583,6 +625,16 @@ Version History {#history} Description + + 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 diff --git a/latest/schemas/bf2raw.schema b/latest/schemas/bf2raw.schema new file mode 100644 index 00000000..834aee24 --- /dev/null +++ b/latest/schemas/bf2raw.schema @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/latest/schemas/bf2raw.schema", + "title": "NGFF container produced by bioformats2raw", + "description": "JSON from OME-NGFF .zattrs", + "type": "object", + "properties": { + "bioformats2raw.layout": { + "description": "The top-level identifier metadata added by bioformats2raw", + "type": "number", + "enum": [3] + } + } +} diff --git a/latest/schemas/image.schema b/latest/schemas/image.schema index 3926c4f4..cf2b477f 100644 --- a/latest/schemas/image.schema +++ b/latest/schemas/image.schema @@ -44,7 +44,7 @@ } }, "required": [ - "datasets", "axes" + "datasets", "axes", "version" ] }, "minItems": 1, @@ -93,11 +93,7 @@ "active": { "type": "boolean" } - }, - "required": [ - "window", - "color" - ] + } } } }, @@ -124,7 +120,7 @@ "type": "string", "enum": ["space"] }, - "units": { + "unit": { "type": "string" } } diff --git a/latest/schemas/ome.schema b/latest/schemas/ome.schema new file mode 100644 index 00000000..bd600a2a --- /dev/null +++ b/latest/schemas/ome.schema @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ngff.openmicroscopy.org/latest/schemas/ome.schema", + "title": "NGFF group produced by bioformats2raw to contain OME metadata", + "description": "JSON from OME-NGFF OME/.zattrs linked to an OME-XML file", + "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 + } + } +} diff --git a/latest/schemas/plate.schema b/latest/schemas/plate.schema index 099f5bb4..1b7ed532 100644 --- a/latest/schemas/plate.schema +++ b/latest/schemas/plate.schema @@ -133,7 +133,7 @@ } }, "required": [ - "columns", "rows", "wells" + "columns", "rows", "wells", "version" ] } } diff --git a/latest/tests/image_suite.json b/latest/tests/image_suite.json index 39cb73d5..bec52214 100644 --- a/latest/tests/image_suite.json +++ b/latest/tests/image_suite.json @@ -14,17 +14,17 @@ { "name": "t", "type": "time", - "units": "micrometer" + "unit": "micrometer" }, { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -60,12 +60,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -90,7 +90,7 @@ "valid": true }, { - "formerly": "valid/missing_version.json", + "formerly": "invalid/missing_version.json", "description": "TBD", "data": { "@type": "ngff:Image", @@ -115,18 +115,18 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } ] }, - "valid": true + "valid": false }, { "formerly": "valid/invalid_axis_units.json", @@ -138,12 +138,12 @@ { "name": "y", "type": "space", - "units": "micron" + "unit": "micron" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -204,12 +204,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } @@ -231,12 +231,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -270,12 +270,12 @@ { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -344,12 +344,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -382,12 +382,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -476,12 +476,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -530,11 +530,11 @@ "axes": [ { "type": "space", - "units": "micron" + "unit": "micron" }, { "type": "space", - "units": "micron" + "unit": "micron" } ], "datasets": [ @@ -567,7 +567,7 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -641,12 +641,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -679,12 +679,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -725,12 +725,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -754,12 +754,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [], @@ -779,12 +779,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "version": "0.5-dev" @@ -829,12 +829,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -857,6 +857,43 @@ }, "valid": false }, + { + "formerly": "invalid/missing_version.json", + "description": "TBD", + "data": { + "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_axis_type.json", "description": "TBD", @@ -867,12 +904,12 @@ { "name": "y", "type": "invalid", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -905,12 +942,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1032,12 +1069,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1087,12 +1124,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -1117,12 +1154,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/latest/tests/plate_suite.json b/latest/tests/plate_suite.json index c19ad60e..876d7c45 100644 --- a/latest/tests/plate_suite.json +++ b/latest/tests/plate_suite.json @@ -8,6 +8,7 @@ "formerly": "plate/minimal_no_acquisitions", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -33,6 +34,7 @@ "formerly": "plate/minimal_acquisitions", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0 @@ -63,6 +65,7 @@ "formerly": "plate/missing_rows", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -83,6 +86,7 @@ "formerly": "plate/empty_rows", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -104,6 +108,7 @@ "formerly": "plate/duplicate_rows", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -131,6 +136,7 @@ { "formerly": "plate/missing_columns", "data": { + "version": "0.5-dev", "plate": { "rows": [ { @@ -152,6 +158,7 @@ "formerly": "plate/empty_columns", "data": { "plate": { + "version": "0.5-dev", "columns": [], "rows": [ { @@ -173,6 +180,7 @@ "formerly": "plate/duplicate_columns", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -201,6 +209,7 @@ "formerly": "plate/missing_wells", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -219,6 +228,7 @@ "formerly": "plate/empty_wells", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -238,6 +248,7 @@ "formerly": "plate/duplicate_rows", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -271,6 +282,7 @@ "formerly": "plate/missing_column_name", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "concentration": 10 @@ -296,6 +308,7 @@ "formerly": "plate/missing_row_name", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -321,6 +334,7 @@ "formerly": "plate/missing_well_path", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -345,6 +359,7 @@ "formerly": "plate/missing_well_rowIndex", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -369,6 +384,7 @@ "formerly": "plate/missing_well_columnIndex", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -393,6 +409,7 @@ "formerly": "plate/well_1group", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -417,6 +434,7 @@ "formerly": "plate/well_3groups", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -441,6 +459,7 @@ "formerly": "plate/invalid_version", "data": { "plate": { + "version": "foo", "columns": [ { "name": "A" @@ -457,8 +476,32 @@ "rowIndex": 0, "columnIndex": 0 } + ] + } + }, + "valid": false + }, + { + "formerly": "plate/missing_version", + "data": { + "plate": { + "columns": [ + { + "name": "A" + } ], - "version": "foo" + "rows": [ + { + "name": "1" + } + ], + "wells": [ + { + "path": "A/1", + "rowIndex": 0, + "columnIndex": 0 + } + ] } }, "valid": false @@ -467,6 +510,7 @@ "formerly": "plate/non_alphanumeric_column", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A-1" @@ -492,6 +536,7 @@ "formerly": "plate/non_alphanumeric_row", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" @@ -517,6 +562,7 @@ "formerly": "plate/missing_acquisition_id", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "maximumfieldcount": 1 @@ -547,6 +593,7 @@ "formerly": "plate/non_integer_acquisition_id", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": "0" @@ -577,6 +624,7 @@ "formerly": "plate/negative_acquisition_id", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": -1 @@ -607,6 +655,7 @@ "formerly": "plate/non_integer_acquisition_maximumfieldcount", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -638,6 +687,7 @@ "formerly": "plate/acquisition_zero_maximumfieldcount", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -669,6 +719,7 @@ "formerly": "plate/acquisition_noninteger_starttime", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -700,6 +751,7 @@ "formerly": "plate/acquisition_negative_starttime", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -731,6 +783,7 @@ "formerly": "plate/acquisition_noninteger_endtime", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -762,6 +815,7 @@ "formerly": "plate/negative_endtime", "data": { "plate": { + "version": "0.5-dev", "acquisitions": [ { "id": 0, @@ -793,6 +847,7 @@ "formerly": "plate/zero_field_count", "data": { "plate": { + "version": "0.5-dev", "columns": [ { "name": "A" diff --git a/latest/tests/strict_image_suite.json b/latest/tests/strict_image_suite.json index b8aeebe1..7bff90ca 100644 --- a/latest/tests/strict_image_suite.json +++ b/latest/tests/strict_image_suite.json @@ -122,12 +122,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -205,12 +205,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ] } @@ -228,12 +228,12 @@ { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ @@ -279,17 +279,17 @@ { "name": "z", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "y", "type": "space", - "units": "micrometer" + "unit": "micrometer" }, { "name": "x", "type": "space", - "units": "micrometer" + "unit": "micrometer" } ], "datasets": [ diff --git a/latest/tests/test_validation.py b/latest/tests/test_validation.py index 9e441fad..8c13b113 100644 --- a/latest/tests/test_validation.py +++ b/latest/tests/test_validation.py @@ -89,3 +89,17 @@ def test_run(suite): resolver = RefResolver.from_schema(suite.schema, store=schema_store) validator = Validator(suite.schema, resolver=resolver) suite.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/make.bat b/make.bat new file mode 100644 index 00000000..954237b9 --- /dev/null +++ b/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/publications/index.md b/publications/index.md new file mode 100644 index 00000000..f3e872fd --- /dev/null +++ b/publications/index.md @@ -0,0 +1,5 @@ +Publications +============ + +* [OME-NGFF: a next-generation file format for expanding bioimaging data-access strategies](https://www.nature.com/articles/s41592-021-01326-w) 29th November 2021 +* [OME-Zarr: a cloud-optimized bioimaging file format with international community support](https://link.springer.com/article/10.1007/s00418-023-02209-1) 10th July 2023 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..e43d0c22 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +bikeshed +myst-parser +sphinx-book-theme diff --git a/specifications/index.md b/specifications/index.md new file mode 100644 index 00000000..a40e0708 --- /dev/null +++ b/specifications/index.md @@ -0,0 +1,16 @@ +Specifications +============== + +The current released version of the OME-NGFF specification is 0.4. + +The latest version is still undergoing changes and is not yet released. + +Version history: + + diff --git a/tools/index.md b/tools/index.md new file mode 100644 index 00000000..b3b0d5d0 --- /dev/null +++ b/tools/index.md @@ -0,0 +1,158 @@ +# Tools + +A list of tools and libraries with OME-Zarr support. These are developed by various members of the OME-NGFF community. If you think your tool/library should be listed here, please [open a pull request](https://github.com/ome/ngff). + +In addition to this collection, an evaluation of selected tools/libraries is available on . + + +## Image viewers with OME-Zarr support + +### AGAVE + + +A desktop application for viewing multichannel volume data. + + +### ITKWidgets + + +A Python interface for visualization on the web platform to interactively generate insights into multidimensional images, point sets, and geometry. + + +### MoBIE/BDV + + +A Fiji plugin for exploring and sharing big multi-modal image and associated tabular data. + + +### napari + + +A fast, interactive, multi-dimensional image viewer for Python that supports OME-Zarr with the [napari-ome-zarr](https://github.com/ome/napari-ome-zarr) plugin. + + +### Neuroglancer + + +A WebGL-based viewer for volumetric data. + + +### Viv (Avivator, Vizarr, Vitessce, ...) + + +A WebGL-powered toolkit for interactive visualization of high-resolution, multiplexed bioimaging datasets. + +The viv toolkit is used by the [Avivator](https://avivator.gehlenborglab.org), [Vizarr](https://github.com/hms-dbmi/vizarr) and [Vitessce](http://vitessce.io) image viewers, among others. + + + + +### WEBKNOSSOS + + +An open-source tool for annotating and exploring large 3D image datasets. + + +### AICS Image Viewer + + +A browser-based volume viewer built with React and WebGL (Three.js). + + +## Tools for converting image files to OME-Zarr + +### bioformats2raw + + +Java application to convert image file formats, including .mrxs, to an intermediate Zarr structure compatible with the OME-NGFF specification. + + +### NGFF-Converter + + +A GUI application for conversion of bioimage formats into OME-NGFF (Next-Generation File Format) or OME-TIFF. + + +### stack_to_multiscale_ngff + + +A tool for converting multi-terabyte stacks of images into a multiscale OME-NGFF Zarr. + + +## Libraries for reading/writing OME-Zarr files + +Various libraries for reading/writing OME-Zarr files in Python were evaluated as part of the BioVisionCenter "Next generation bioimage analysis workflows hackathon" 2023 in Zurich, Switzerland: https://github.com/jwindhager/ome-ngff-readers-writers/. + + +### AICSImageIO + + +Image Reading, Metadata Conversion, and Image Writing for Microscopy Images in pure Python. + + +### bfio + + +A Python interface to Bioformats using jpype for direct access to the library. + + +### Bio-Formats + + +A standalone Java library for reading and writing life sciences image file formats. + + +### ngff-zarr + + +A lean and kind Open Microscopy Environment (OME) Next Generation File Format (NGFF) Zarr implementation. + + +### multiscale-spatial-image + + +Generate a multiscale, chunked, multi-dimensional spatial image data structure that can serialized to OME-NGFF. + + +### ome-zarr-py + + +A Python library for reading and writing multi-resolution images stored as Zarr filesets, according to the OME NGFF spec. + + +### ITKIOOMEZarrNGFF + + +An ITK external module for IO of images stored in Zarr-backed OME-NGFF file format. + + +## Other tools and libraries + +### Fractal + + +A framework to process high content screening data at scale and to prepare it for interactive visualization. + + +### Nyxus + + +A scalable library for calculating features from intensity-label image data. + + +### ome-ngff-validator + + +Web page for validating OME-NGFF files. + + +### SpatialData + + +An open and universal framework for processing spatial omics data. + + +### tensorstore + + +Library for reading and writing large multi-dimensional arrays (e.g., Zarr).