-
Notifications
You must be signed in to change notification settings - Fork 9
Replace arrayCoordinateSystem with explanation on how to express dimensionless transforms in pixel coordinates
#118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
201d793
626f756
dc2f68f
193b8df
3ba7903
575345f
7284adb
769f519
1d2c470
6236d70
18d95a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -280,61 +280,6 @@ Here, we refer to any method that obtains values at real-valued coordinates usin | |
| As such, label images may be interpolated using "nearest neighbor" to obtain labels at points along the continuum. | ||
| ``` | ||
|
|
||
| #### Array coordinate systems | ||
|
|
||
| The dimensions of an array do not have an interpretation | ||
| until they are associated with a coordinate system via a coordinate transformation. | ||
| Nevertheless, it can be useful to refer to the "raw" coordinates of the array. | ||
| Some applications might prefer to define points or regions-of-interest in "pixel coordinates" rather than "physical coordinates," for example. | ||
| Indicating that choice explicitly will be important for interoperability. | ||
| This is possible by using **array coordinate systems**. | ||
|
|
||
| Every array has a default coordinate system whose parameters need not be explicitly defined. | ||
| The dimensionality of each array coordinate system equals the dimensionality of its corresponding Zarr array. | ||
| Its name is the path to the array in the container, | ||
| its axes have `"type": "array"`, are unitless, and have default names. | ||
| The i-th axis has `"name": "dim_i"` (these are the same default names used by [xarray](https://docs.xarray.dev/en/stable/user-guide/terminology.html)). | ||
| As with all coordinate systems, the dimension names must be unique and non-null. | ||
|
|
||
| :::{dropdown} Example | ||
| ```json | ||
| { | ||
| "arrayCoordinateSystem" : { | ||
| "name" : "myDataArray", | ||
| "axes" : [ | ||
| {"name": "dim_0", "type": "array"}, | ||
| {"name": "dim_1", "type": "array"}, | ||
| {"name": "dim_2", "type": "array"} | ||
| ] | ||
| } | ||
| } | ||
|
|
||
| ``` | ||
|
|
||
| For example, if 0/zarr.json contains: | ||
| ```json | ||
| { | ||
| "zarr_format": 3, | ||
| "node_type": "array", | ||
| "shape": [4, 3, 5], | ||
| //... | ||
| } | ||
| ``` | ||
|
|
||
| Then `dim_0` has length 4, `dim_1` has length 3, and `dim_2` has length 5. | ||
|
|
||
| ::: | ||
|
|
||
| The axes and their order align with the shape of the corresponding Zarr array, | ||
| and whose data depends on the byte order used to store chunks. | ||
| As described in the [Zarr array metadata](https://zarr.readthedocs.io/en/stable/spec/v3.html#arrays), | ||
| the last dimension of an array in "C" order are stored contiguously on disk or in-memory when directly loaded. | ||
|
|
||
| The name and axes names MAY be customized by including a `arrayCoordinateSystem` field | ||
| in the user-defined attributes of the array whose value is a coordinate system object. | ||
| The length of `axes` MUST be equal to the dimensionality. | ||
| The value of `type` for each object in the axes array MUST equal `"array"`. | ||
|
|
||
| #### Coordinate convention | ||
|
|
||
| **The pixel/voxel center is the origin of the continuous coordinate system.** | ||
|
|
@@ -603,6 +548,99 @@ to do so by estimating the transformations' inverse if they choose to. | |
| ``` | ||
| ::: | ||
|
|
||
| **Transformations in pixel units**: Some applications might prefer to define points, regions-of-interest or transformation parameters | ||
| in "pixel coordinates" rather than "physical coordinates". | ||
jo-mueller marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Because transformations are agnostic to whether they refer to pixel or physical coordinates, | ||
| indicating that choice explicitly will be important for interoperability. | ||
| This can be expressed in the metadata in multiple ways, including: | ||
| - One can embed a transformation defined in pixel units into a `sequence` transformation | ||
| that includes the appropriate scale transformation and its inverse to convert to physical units (see example below). | ||
| - One can define a unitless coordinate system and connect it to the "intrinsic" coordinate system | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a definition of "intrinsic coordinate system somewhere?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm...In #117, I added this further up under the coordinate systems section:
Could add that here as well?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so "intrinsic coordinate system" means "native physical coordinate system"? IMO this is not terribly clear, since both "intrinsic coordinate system" and "native coordinate system" are terms invented in this spec, as far as I can tell. I would encourage reducing the number of different "kinds" of coordinate systems, especially if their differences cannot be strictly defined (i.e., defined well enough for a program to do something useful with). Putting aside the "coordinate system" language for a minute, there is something special about the coordinates an array "starts with" -- without defining these coordinates, you have not defined the input to any of the transforms. So there needs to be some way for an array to declare what coordinates it has, before any transforms are applied. "Array declares its coordinates" is not in principle the same thing as an "intrinsic coordinate system" or "array coordinate system" because ome-zarr could in principle add a convention (like xarray) where the array's coordinates are data that you read from a coordinate array (and so they would not start at (0,0,0), and might have units, etc). I would not close the door on this possibility. So I would not use language that implies that the coordinates an array declares (implicitly, for now, but possibly explicitly later) are somehow categorically different from the coordinates that pop out of transforms. So I don't think you need to talk about pixel units or array units or any of that. The minimal thing is to instruct viewers how to address the coordinates an array starts with. |
||
| with a scale transformation that has the appropriate scale factors to convert to physical units. | ||
|
|
||
| :::{dropdown} Example: Embedded expression | ||
|
|
||
| In the context of [`scene`](#scene-md), one may want to express a transformation between two images in pixel units, | ||
| even though the coordinate systems of the two images are in physical units. | ||
| This can be achieved by embedding the pixel-unit transformation into a `sequence` transformation like this: | ||
|
|
||
| ```json | ||
| { "scene": | ||
| { | ||
| "type": "sequence", | ||
| "input": {"name": "intrinsic", "path": "imageA"}, | ||
| "output": {"name": "intrinsic", "path": "imageB"}, | ||
| "transformations": [ | ||
| { | ||
| "type": "scale", | ||
| "scale": [0.5, 0.5], | ||
| }, | ||
| { | ||
| "type": "translation", | ||
| "translation": [10, 20], | ||
| "name": "translation in pixel units" | ||
| }, | ||
| { | ||
| "type": "scale", | ||
| "scale": [2, 2], | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
| ::: | ||
|
|
||
| :::{dropdown} Example: Unitless coordinate system | ||
|
|
||
| Alternatively, users may choose to define a unitless coordinate system and connect it to the "intrinsic" coordinate system | ||
| with a scale transformation that has the appropriate scale factors to convert to physical units. | ||
| In the context of multiscales metadata, this could look like this: | ||
|
|
||
| ```json | ||
| { | ||
| "multiscales": [ | ||
| { | ||
| "coordinateSystems": [ | ||
| { | ||
| "name": "intrinsic", | ||
| "axes": [{"name": "x", "type": "space", "unit": "micrometer"}, {"name": "y", "type": "space", "unit": "micrometer"}] | ||
| }, | ||
| { | ||
| "name": "array", | ||
| "axes": [{"name": "x", "type": "space"}, {"name": "y", "type": "space"}] | ||
jo-mueller marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| ], | ||
| "datasets": [ | ||
| { | ||
| "path": "s0", | ||
| "coordinateTransformations": [ | ||
| { | ||
| "type": "scale", | ||
| "scale": [0.5, 0.5], | ||
| "input": "s0", | ||
| "output": "intrinsic" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "coordinateTransformations": [ | ||
| { | ||
| "type": "scale", | ||
| "scale": [2.0, 2.0], | ||
| "input": {"name": "intrinsic"}, | ||
| "output": {"name": "pixel"} | ||
jo-mueller marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
| In this case, the `scale` transformation under `coordinateTransformations` | ||
| defines the mapping from the "intrinsic" coordinate system to the unitless "pixel" coordinate system. | ||
| ::: | ||
|
|
||
|
|
||
|
|
||
| #### Matrix transformations | ||
| (matrix-trafo-md)= | ||
|
|
||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.