From bd450212b6368e740ea742e3f78f4828d98e115d Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Tue, 30 Jul 2024 13:46:17 -0400 Subject: [PATCH 01/32] wip: start of transforms RFC --- rfc/wip-tform/index.md | 614 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 614 insertions(+) create mode 100644 rfc/wip-tform/index.md diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md new file mode 100644 index 00000000..c04b3e07 --- /dev/null +++ b/rfc/wip-tform/index.md @@ -0,0 +1,614 @@ +# RFC-X Coordinate systems and transformations + +Add named coordinate systems and expand and clarify coordinate transformations. + +## Status + +This RFC is currently in a draft state. + +| Role | Name | GitHub Handle | Institution | Date | Status | +|--------|-----------|---------------|-------------|------------|----------------------------------------| +| Author | John Bogovic | @bogovicj | HHMI Janelia | xxxx-xx-xx | Author; Implemented | +| Author | Luca Marconato | @LucaMarconato | EMBL | xxxx-xx-xx | Author; Implemented | +| Author | Matt McCormick | @thewtex | ITK | xxxx-xx-xx | Author; Implemented? +| Author | Davis Bennett | @d-v-b | | xxxx-xx-xx | Author | + +## Overview + +The RFC begins with a brief overview. This section should be one or two +paragraphs that just explains what the goal of this RFC is going to be, but +without diving too deeply into the "why", "why now", "how", etc. Ensure anyone +opening the document will form a clear understanding of the RFCs intent from +reading this paragraph(s). + +## Background + +This RFC provides first-class support for spatial and coordinate transformations in OME-Zarr, which is vitally important for +neuro and bio-imaging and broader scientific imaging practices to enable: + +1. Reproducibility and Consistency: Supporting spatial transformations explicitly in a file format ensures that transformations + are applied consistently across different platforms and applications. This FAIR capability is a cornerstone of scientific + research, and having standardized formats and tools facilitates verification of results by independent + researchers. +2. Integration with Analysis Workflows: Having spatial transformations as a first-class citizen within file formats allows for + seamless integration with various image analysis workflows. Registration transformations can be used in subsequent image + analysis steps without requiring additional conversion. +3. Efficiency and Accuracy: Storing transformations within the file format avoids the need for re-sampling each time the data is + processed. This reduces sampling errors and preserves the accuracy of subsequent analyses. Standardization enables on-demand + transformation, critical for the massive volumes collected by modern microscopy techniques. +4. Flexibility in Analysis: A file format that natively supports spatial transformations allows researchers to apply, modify, or + reverse transformations as needed for different analysis purposes. This flexibility is critical for tasks such as + longitudinal studies, multi-modal imaging, and comparative analysis across different subjects or experimental conditions. + + +## Proposal + +Below is a slightly abridged proposal (examples are omitted), the full set of changes including all examples +are publicly available on the github pull request TODO link; + + +### "coordinateSystems" metadata {#coord-sys-md} + +A "coordinate system" is a collection of "axes" / dimensions with a name. Every coordinate system: +- MUST contain the field "name". The value MUST be a non-empty string that is unique among `coordinateSystem`s. +- MUST contain the field "axes", whose value is an array of valid "axes" (see below). + + +The order of the `"axes"` list matters and defines the index of each array dimension and coordinates for points in that +coordinate system. For the above example, the `"x"` dimension is the first dimension. The "dimensionality" of a coordinate system +is indicated by the length of its "axes" array. The "volume_micrometers" example coordinate system above is three dimensional (3D). + +The axes of a coordinate system (see below) give information about the types, units, and other properties of the coordinate +system's dimensions. Axis `name`s may contain semantically meaningful information, but can be arbitrary. As a result, two +coordinate systems that have identical axes in the same order may not be "the same" in the sense that measurements at the same +point refer to different physical entities and therefore should not be analyzed jointly. Task that require images, annotations, +regions of interest, etc. SHOULD ensure that they are in the same coordinate system (same name, with identical axes) or can be +transformed to the same coordinate system before doing analysis. See the example below. + + +### "axes" metadata + +"axes" describes the dimensions of a coordinate systems. 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 "array", "space", "time", "channel", "coordinate", or "displacement" but MAY take other values for custom axis types that are not part of this specification yet. +- MAY contain the field "discrete". The value MUST be a boolean, and is `true` if the axis represents a discrete dimension. +- 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. + +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. + +Arrays are often thought of as containing discrete samples along the continuous variable. Axes representing space and time are +usually continuous, meaning they can be indexed by real-valued (floating point) numbers whereas discrete axes may be indexed +only by integers. Arrays are inherently discrete (see Array coordinate systems, below) , but values "in between" discrete +coordinates can be retreived using an *interpolation* method. If an axis is continuous (`"discrete" : false`), it indicates +that indexing with continuous values is meaningful, and that interpolation may be performed along that axis. Interpolation may +be performed jointly across axes with the same `type`, and interpolation should not be performed for discrete axes or jointly +across axes with differing `type`s. Other non-continuous variables and axis types are also usually discrete, such as +`channel`s, `coordinate`s, and `displacement`s. + +Note: The most common methods for interpolation are "nearest neighbor", "linear", "cubic", and "windowed sinc". Here, we refer +to any method that obtains values at real valued coordinates using discrete samples as an "interpolator". As such, label images +may be interpolated using "nearest neighbor" to obtain labels at points along the continuum. + + +### Array coordinate systems + +Every array has a default coordinate system whose parameters need not be explicitly defined. Its name is the path to the array +in the container, its axes have `"type":"array"`, are unitless, and have default "name"s. The ith axis has `"name":"dim_i"` +(these are the same default names used by [xarray](https://docs.xarray.dev/en/stable/user-guide/terminology.html)). + + +The dimensionality of each array coordinate system equals the dimensionality of its corresponding zarr array. The axis with +name `"dim_i"` is the ith element of the `"axes"` list. The axes and their order align with the `shape` +attribute in the zarr array attributes (in `.zarray`), 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/v2.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 `.zattr` metadata 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.** + +It is vital to consistently define relationship between the discrete/array and continuous/interpolated +coordinate systems. A pixel/voxel is the continuous region (rectangle) that corresponds to a single sample +in the discrete array, i.e., the area corresponding to nearest-neighbor (NN) interpolation of that sample. +The center of a 2d pixel corresponding to the origin `(0,0)` in the discrete array is the origin of the continuous coordinate +system `(0.0, 0.0)` (when the transformation is the identity). The continuous rectangle of the pixel is given by the +half-open interval `[-0.5, 0.5) x [-0.5, 0.5)` (i.e., -0.5 is included, +0.5 is excluded). See chapter 4 and figure 4.1 of the ITK Software Guide [[itk]]. + + +### "coordinateTransformations" metadata {#trafo-md} + +"coordinateTransformations" describe the mapping between two coordinate systems (defined by "axes"). +For example, to map an array's discrete coordinate system to its corresponding physical coordinates. +Coordinate transforms are in the "forward" direction. They represent functions from *points* in the +input space to *points* in the output space. + + +- MUST contain the field "type". +- MUST contain any other fields required by the given "type" (see table below). +- MUST contain the field "output", unless part of a `sequence` or `inverseOf` (see details). +- MUST contain the field "input", unless part of a `sequence` or `inverseOf` (see details). +- MAY contain the field "name". Its value MUST be unique across all "name" fields for coordinate transformations. +- Parameter values MUST be compatible with input and output space dimensionality (see details). + + + +
`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[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[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. +
typefieldsdescription +
+ + +Conforming readers: +- MUST parse `identity`, `scale`, `translation` transformations; +- SHOULD parse `mapAxis`, `affine` transformations; +- SHOULD be able to apply transformations to points; +- SHOULD be able to apply transformations to images; + +Coordinate transformations from array to physical coordinates MUST be stored in multiscales ([[#multiscale-md]]), +and MUST be duplicated in the atrributes of the zarr array. Transformations between different images MUST be stored in the +attributes of a parent zarr group. For transformations that store data or parameters in a zarr array, those zarr arrays SHOULD +be stored in a zarr group `"coordinateTransformations"`. + +
+store.zarr                      # Root folder of the zarr store
+│
+├── .zattrs                     # 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
+│       ├── .zattrs
+│       └── .zarray
+│
+├── volume
+│   ├── .zattrs                 # group level attributes (multiscales)
+│   └── 0                       # a group containing the 0th scale
+│       └── image               # a zarr array
+│           ├── .zattrs         # physical coordinate system and transformations here
+│           └── .zarray         # the array attributes
+└── crop
+    ├── .zattrs                 # group level attributes (multiscales)
+    └── 0                       # a group containing the 0th scale
+        └── image               # a zarr array
+            ├── .zattrs         # physical coordinate system and transformations here
+            └── .zarray         # the array attributes
+
+ +### Additional details + +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). + + +Coordinate transformations are functions of *points* in the input space to *points* in the output space. We call this the "forward" direction. +Points are ordered lists of coordinates, where a coordinate is the location/value of that point along its corresponding axis. +The indexes of axis dimensions correspond to indexes into transformation parameter arrays. For example, the scale transformation above +defines the function: + +``` +x = 0.5 * i +y = 1.2 * j +``` + +i.e., the mapping from the first input axis to the first output axis is determined by the first scale parameter. + +When rendering transformed images and interpolating, implementations may need the "inverse" transformation - from the output to +the input coordinate system. Inverse transformations will not be explicitly specified when they can be computed in closed form from the +forward transformation. Inverse transformations used for image rendering may be specified using the `inverseOf` +transformation type, for example: + +```json +{ + "type": "inverseOf", + "transformation" : { + "type": "displacements", + "path": "/path/to/displacements", + } +} +``` + +Implementations SHOULD be able to compute and apply the inverse of some coordinate transformations when they +are computable in closed-form (as the [Transformation types](#transformation-types) section below indicates). If an +operation is requested that requires the inverse of a transformation that can not be inverted in closed-form, +implementations MAY estimate an inverse, or MAY output a warning that the requested operation is unsupported. + + +#### Matrix transformations + +Two transformation types ([affine](#affine) and [rotation](#rotation)) are parametrized by matrices. Matrices are applied to +column vectors that represent points in the input coordinate system. The first (last) axis in a coordinate system is the top +(bottom) entry in the column vector. Matrices may be stored either as row-major flat (one-dimensional) arrays or two-dimensional +arrays, either in json or stored in a zarr array. When stored as a 2D zarr array, the first dimension indexes rows, and the +second dimension indexes columns (e.g., an array of `"shape":[3,4]` has 3 rows and 4 columns). When stored as a 2D json array, +the inner array contains rows (e.g. `[[1,2], [3,4], [5,6]]` has 3 rows and 2 columns). + + +### Transformation types + +Input and output dimensionality may be determined by the value of the "input" and "output" fields, respectively. If the value +of "input" is an array, it's length gives the input dimension, otherwise the length of "axes" for the coordinate +system with the name of the "input" value gives the input dimension. If the value of "input" is an array, it's +length gives the input imension, otherwise it is given by the length of "axes" for the coordinate system with +the name of the "input". If the value of "output" is an array, it's length gives the output dimension, +otherwise it is given by the length of "axes" for the coordinate system with the name of the "output". + +#### identity + +`identity` transformations map input coordinates to output coordinates without modification. The position of +the ith axis of the output coordinate system is set to the position of the ith axis of the input coordinate +system. `identity` transformations are invertible. + + +#### mapAxis + +`mapAxis` transformations describe axis permutations as a mapping of axis names. Transformations MUST include a `mapAxis` field +whose value is an object, all of whose values are strings. If the object contains `"x":"i"`, then the transform sets the value +of the output coordinate for axis "x" to the value of the coordinate of input axis "i" (think `x = i`). For every axis in its output coordinate +system, the `mapAxis` MUST have a corresponding field. For every value of the object there MUST be an axis of the input +coordinate system with that name. Note that the order of the keys could be reversed. + + +#### translation + +`translation` transformations are special cases of affine transformations. When possible, a +translation transformation should be preferred to its equivalent affine. Input and output dimensionality MUST be +identical and MUST equal the the length of the "translation" array (N). `translation` transformations are +invertible. + +
+
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`.
+
+ + +#### scale + +`scale` transformations are special cases of affine transformations. When possible, a scale transformation +SHOULD be preferred to its equivalent affine. Input and output dimensionality MUST be identical and MUST equal +the the length of the "scale" array (N). Values in the `scale` array SHOULD be non-zero; in that case, `scale` +transformations are invertible. + +
+
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`.
+
+ + +#### affine + +`affine`s are [matrix transformations](#matrix-transformations) from N-dimensional inputs to M-dimensional outputs are represented at `(N)x(M+1)` +matrices in homogeneous coordinates. This transformation type is invertible when `N` equals `M`. +The matrix may be stored as a 2D array (inner arrays represent the rows of the matrix) or as a 1D array (row-major). + +
+
path
+
The path to a zarr-array containing the affine parameters. + The array at this path MUST be 1D or 2D. If 1D, its length MUST be `N*(M+1)`. + If 2D its shape must be `N x (M+1)`.
+
affine
+
The affine parameters stored in JSON. The matrix may be stored as a row-major flat array of numbers that MUST be + length `N*(M+1)`, or as 2D nested array where the outer array MUST be length `N` and the inner arrays MUST be length `M+1`.
+
+ + +#### rotation + +`affine`s are [matrix transformations](#matrix-transformations) that are special cases of affine transformations. When possible, a rotation +transformation SHOULD be preferred to its equivalent affine. Input and output dimensionality (N) MUST be identical and greater +than 1. Rotations are stored as `NxN` matrices, see below, and MUST have determinant equal to one, with orthonormal rows and +columns. The matrix may be stored as a 2D array (inner arrays represent the rows of the matrix) or as a 1D array (row-major). +`rotation` transformations are invertible. + +
+
path
+
The path to an array containing the affine parameters. + The array at this path MUST be 1D or 2D. If 1D, its length MUST be `N*N`, + if 2D its shape must be `N x N`.
+
rotation
+
The parameters stored in JSON. The matrix may be stored as a row-major flat array of numbers that MUST be + length `N*N`, or as 2D nested array where the outer array MUST be length `N` and the inner arrays MUST be length `N`.
+
+ + + +#### inverseOf + +An `inverseOf` transformation contains another transformation (often non-linear), and indicates that +transforming points from output to input coordinate systems is possible using the contained transformation. +Transforming points from the input to the output coordinate systems requires the inverse of the contained +transformation (if it exists). + +
+ Software libraries that perform image registration often return the transformation from fixed image + coordinates to moving image coordinates, because this "inverse" transformation is most often required + when rendering the transformed moving image. Results such as this may be enclosed in an `inverseOf` + transformation. This enables the "outer" coordinate transformation to specify the moving image coordinates + as `input` and fixed image coordinates as `output`, a choice that many users and developers find intuitive. +
+ + + +#### sequence + +A `sequence` transformation consists of an ordered array of coordinate transformations, and is invertible if and only if every +coordinate transform in the array is invertible. To apply a sequence transformation to a point in the input coordinate system, +apply the first transformation in the list of transformations. Next, apply the second transformation to the result. Repeat until +every transformation has been applied. The output of the last transformation is the result of the sequence. + +The transformations included in the `transformations` array may omit their `input` and `output` fields under the conditions +outlined below: + +- The `input` and `output` fields MAY be omitted for the following transformation types: + - `identity`, `scale`, `translation`, `rotation`, `affine`, `displacements`, `coordinates` +- The `input` and `output` fields MAY be omitted for `inverseOf` transformations if those fields may be omitted for the + transformation it wraps +- The `input` and `output` fields MAY be omitted for `bijection` transformations if the fields may be omitted for + both its `forward` and `inverse` transformations +- The `input` and `output` fields MAY be omitted for `sequence` transformations if the fields may be omitted for + all transformations in the sequence after flattening the nested sequence lists. +- The `input` and `output` fields MUST be included for transformations of type: `mapAxis`, and `byDimension` (see the note + below), and under all other conditions. + + +
+
transformations
+
A non-empty array of transformations.
+
+ + + +#### coordinates and displacements + +`coordinates` and `displacements` transformations store coordinates or displacements in an array and interpret them as a +transformation. Applying the transformation amounts to looking up the appropriate locations in the array and interpolating +if necessary. + +These transformation types refer to an array at location specified by the `"path"` parameter whose coordinate sytem MUST contain +an axis with type `coordinate` or `displacement` respectively for transformations of type `coordinates` or `displacements`. This +axis MUST be of length equal to the number of axes of the output coordinate system and SHOULD be the last axis (contiguous on +disk when c-order). The coordinate system MUST also contain an axis identical to every axis of its input coordinate system in +the same order. As a consequence, the array will have one dimension more than its input coordinate system. + +The `i`th value of the array along the `coordinate` or `displacement` axis refers to the displacement +or coordinate of `i`th output axis. See the example below. + + +`coordinates` and `displacements` transformations are not invertible in general, but implementations MAY approximate their +inverses. Metadata for these coordinate transforms have the following field: + +
+
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
  • +
+
+ +For both `coordinates` and `displacements`, the array data at referred to by `path` MUST define space and coordinate transform metadata: + +* Every axis name in the `coordinateTransform`'s `input` MUST appear in the coordinate system +* The array dimension corresponding to the `coordinate` or `displacement` axis MUST have length equal to the dimensionality of the `coordinateTransform` `output` +* SHOULD have a `name` identical to the `name` of the corresponding `coordinateTransform`. + +For `coordinates`: + +* coordinateSystem metadata MUST have exactly one axis with `"type" : "coordinate"` +* If a `coordinates`' input space has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. +* the shape of the array along the "coordinate" axis must be exactly `N` + +For `displacements`: + +* coordinateSystem metadata MUST have exactly one axis with `"type" : "displacement"` +* If a `displacements`' input space has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. +* the shape of the array along the "displacement" axis must be exactly `N` +* `input` and `output` MUST have an equal number of dimensions. + + + +#### byDimension {#trafo-byDimension} + +`byDimension` transformations build a high dimensional transformation using lower dimensional transformations +on subsets of dimensions. + +
+
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`. +
+
+ + +#### bijection + +A bijection transformation is an invertible transformation in which both the `forward` and `inverse` transformations +are explicitly defined. Each direction SHOULD be a transformation type that is not closed-form invertible. +Its' input and output spaces MUST have equal dimension. The input and output dimensions for the both the forward +and inverse transformations MUST match bijection's input and output space dimensions. + +`input` and `output` fields MAY be omitted for the `forward` and `inverse` transformations, in which case +the `forward` transformation's `input` and `output` are understood to match the bijection's, and the `inverse` +transformation's `input` (`output`) matches the bijection's `output` (`input`), see the example below. + +Practically, non-invertible transformations have finite extents, so bijection transforms should only be expected +to be correct / consistent for points that fall within those extents. It may not be correct for any point of +appropriate dimensionality. + + +## Requirements (Recommended Header) + +For the problem(s) solved by this RFC, what constrains the possible solutions? +List other RFCs, or standards (ISO, etc.) which are applicable. It is suggested +that the following text SHOULD be used in all RFCs: + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [IETF RFC 2119][IETF RFC 2119] + +## Stakeholders + +People who need to represent the result of image registration algorithms, or any imaging +scientist in need of affine or non-linear transformations. + +This RFC has been discussed in: + +* [This github pull-request](https://github.com/ome/ngff/pull/138) +* These github issues: + * https://github.com/ome/ngff/issues/84 + * https://github.com/ome/ngff/issues/94 + * https://github.com/ome/ngff/issues/101 + * https://github.com/ome/ngff/issues/146 +* Several OME-Zarr community calls ([one example](https://forum.image.sc/t/ome-ngff-community-call-transforms-and-tables/71792) + +## Implementation (Recommended Header) + +Many RFCs have an "implementation" section which details how the implementation +will work. This section should explain the rough specification changes. The +goal is to give an idea to reviewers about the subsystems that require change +and the surface area of those changes. + +This knowledge can result in recommendations for alternate approaches that +perhaps are idiomatic to the project or result in less packages touched. Or, it +may result in the realization that the proposed solution in this RFC is too +complex given the problem. + +For the RFC author, typing out the implementation in a high-level often serves +as "[rubber duck debugging][rubber duck debugging]" and you can catch a lot of +issues or unknown unknowns prior to writing any real code. + +## Drawbacks, risks, alternatives, and unknowns (Recommended Header) + +TODO + +## Abandoned Ideas + +TODO +Considered changing axis-order, preferred this proposal so that backward compatibility will be maintained. + +## Prior art and references + +ITK represents many [types of +transformations](https://itk.org/ITKSoftwareGuide/html/Book2/ITKSoftwareGuide-Book2ch3.html#x26-1170003.9), +and can serialize them to either plain text or to an HDF5 file. This is a practical approach that works +well for software that depend on ITK, the proposed solution encoding transformations will be more +interoperable. + +Displacement fields are typically stored in formats designed for medical imaging (e.g. [Nifti](https://nifti.nimh.nih.gov/)). +While effective, they can only describe one type of non-linear transformation. + +The Saalfeld lab at Janelia developed a [custom +format](https://github.com/saalfeldlab/template-building/wiki/Hdf5-Deformation-fields) for storing affine and displacement field +transformations in HDF5 which is similarly less interoperable thatn would be ideal. + + +## Future possibilities + +Additional transformation types. +* thin-plate spline +* bspline +* velocity fields +* by-coordinate + +## Performance + +TODO +Summary: This proposal adds new features, and has no effect on performance for existing functionality. + +## Backwards Compatibility + +Adds new transformations, but existing transformations (`scale`, `translation`) are backward-compatible. + +Adds coordinate systems, these contain axes which are backward-compatible with the [axis specification for version +0.4](https://ngff.openmicroscopy.org/0.4/#axes-md). This proposal adds new fields to the axis metadata. + + +## Testing + +TODO +Public examples of transformations with expected input/output pairs will be provided. + +## UI/UX + +Implementations SHOULD communicate if it encounters an unsupported transformation (e.g. some software may opt not to support +non-linear transformations), and inform users what action will be taken. The details of this choice should be software / +application dependent, but ignoring the unsupported transformation or falling back to a simpler transformation are likely +to be common choices. + +Implementations MAY choose to communicate if and when an image can be displayed in multiple coordinate systems. Users might +choose between different options, or software could choose a default (e.g. the first listed coordinate system). The +[`multiscales` in version 0.4](https://ngff.openmicroscopy.org/0.4/#multiscale-md) has a similar consideration. + + From 20a0d258cf4d1d6641153219e119c993a6bc4bb4 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Tue, 30 Jul 2024 14:14:36 -0400 Subject: [PATCH 02/32] stage D2 + clean up author table --- rfc/wip-tform/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index c04b3e07..a87e44a3 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -4,14 +4,14 @@ Add named coordinate systems and expand and clarify coordinate transformations. ## Status -This RFC is currently in a draft state. +This RFC is currently in stage D2. | Role | Name | GitHub Handle | Institution | Date | Status | |--------|-----------|---------------|-------------|------------|----------------------------------------| -| Author | John Bogovic | @bogovicj | HHMI Janelia | xxxx-xx-xx | Author; Implemented | -| Author | Luca Marconato | @LucaMarconato | EMBL | xxxx-xx-xx | Author; Implemented | -| Author | Matt McCormick | @thewtex | ITK | xxxx-xx-xx | Author; Implemented? -| Author | Davis Bennett | @d-v-b | | xxxx-xx-xx | Author | +| Author | John Bogovic | @bogovicj | HHMI Janelia | 2024-07-30 | Author; Implemented | +| Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | +| Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented? | +| Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | ## Overview From ce42618e15c7db6843fce28188b785981fb8c090 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Tue, 30 Jul 2024 14:15:10 -0400 Subject: [PATCH 03/32] overview and background --- rfc/wip-tform/index.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index a87e44a3..b49059fe 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -15,16 +15,12 @@ This RFC is currently in stage D2. ## Overview -The RFC begins with a brief overview. This section should be one or two -paragraphs that just explains what the goal of this RFC is going to be, but -without diving too deeply into the "why", "why now", "how", etc. Ensure anyone -opening the document will form a clear understanding of the RFCs intent from -reading this paragraph(s). +This RFC provides first-class support for spatial and coordinate transformations in OME-Zarr. ## Background -This RFC provides first-class support for spatial and coordinate transformations in OME-Zarr, which is vitally important for -neuro and bio-imaging and broader scientific imaging practices to enable: +Coordinate and spatial transformation are vitally important for neuro and bio-imaging and broader scientific imaging practices +to enable: 1. Reproducibility and Consistency: Supporting spatial transformations explicitly in a file format ensures that transformations are applied consistently across different platforms and applications. This FAIR capability is a cornerstone of scientific @@ -40,6 +36,11 @@ neuro and bio-imaging and broader scientific imaging practices to enable: reverse transformations as needed for different analysis purposes. This flexibility is critical for tasks such as longitudinal studies, multi-modal imaging, and comparative analysis across different subjects or experimental conditions. +Toward these goals, this RFC expands the set of transformations in the OME-Zarr spec covering many of the use cases +requested in [this github issue](https://github.com/ome/ngff/issues/84). It also adds "coordinate systems" - named +sets of "axes." Related the relationship of discrete arrays to physical coordinates and the interpretation and motivation for +axis types. + ## Proposal From 5c603a633fd07db4b42ad5d69b0112f6fd134b19 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Tue, 30 Jul 2024 14:15:40 -0400 Subject: [PATCH 04/32] fixes to proposal section * mostly removing irrelevant links and bikeshed stuff --- rfc/wip-tform/index.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index b49059fe..0b6f460f 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -44,11 +44,11 @@ axis types. ## Proposal -Below is a slightly abridged proposal (examples are omitted), the full set of changes including all examples -are publicly available on the github pull request TODO link; +Below is a slightly abridged copy of the proposed changes to the specification (examples are omitted), the full set of changes +including all examples are publicly available on the [github pull request](https://github.com/ome/ngff/pull/138). -### "coordinateSystems" metadata {#coord-sys-md} +### "coordinateSystems" metadata A "coordinate system" is a collection of "axes" / dimensions with a name. Every coordinate system: - MUST contain the field "name". The value MUST be a non-empty string that is unique among `coordinateSystem`s. @@ -78,7 +78,7 @@ transformed to the same coordinate system before doing analysis. See the example - 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. -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. +If part of multiscales metadata, the length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. Arrays are often thought of as containing discrete samples along the continuous variable. Axes representing space and time are usually continuous, meaning they can be indexed by real-valued (floating point) numbers whereas discrete axes may be indexed @@ -123,10 +123,10 @@ coordinate systems. A pixel/voxel is the continuous region (rectangle) that corr in the discrete array, i.e., the area corresponding to nearest-neighbor (NN) interpolation of that sample. The center of a 2d pixel corresponding to the origin `(0,0)` in the discrete array is the origin of the continuous coordinate system `(0.0, 0.0)` (when the transformation is the identity). The continuous rectangle of the pixel is given by the -half-open interval `[-0.5, 0.5) x [-0.5, 0.5)` (i.e., -0.5 is included, +0.5 is excluded). See chapter 4 and figure 4.1 of the ITK Software Guide [[itk]]. +half-open interval `[-0.5, 0.5) x [-0.5, 0.5)` (i.e., -0.5 is included, +0.5 is excluded). See chapter 4 and figure 4.1 of the ITK Software Guide. -### "coordinateTransformations" metadata {#trafo-md} +### "coordinateTransformations" metadata "coordinateTransformations" describe the mapping between two coordinate systems (defined by "axes"). For example, to map an array's discrete coordinate system to its corresponding physical coordinates. @@ -195,7 +195,7 @@ Conforming readers: - SHOULD be able to apply transformations to points; - SHOULD be able to apply transformations to images; -Coordinate transformations from array to physical coordinates MUST be stored in multiscales ([[#multiscale-md]]), +Coordinate transformations from array to physical coordinates MUST be stored in multiscales, and MUST be duplicated in the atrributes of the zarr array. Transformations between different images MUST be stored in the attributes of a parent zarr group. For transformations that store data or parameters in a zarr array, those zarr arrays SHOULD be stored in a zarr group `"coordinateTransformations"`. From 2723c7c9a826cd52c9e35489d9ddb520a0a39295 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 14 Aug 2024 09:13:59 -0400 Subject: [PATCH 05/32] update tform rfc authors --- rfc/wip-tform/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 0b6f460f..08916f69 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -9,9 +9,10 @@ This RFC is currently in stage D2. | Role | Name | GitHub Handle | Institution | Date | Status | |--------|-----------|---------------|-------------|------------|----------------------------------------| | Author | John Bogovic | @bogovicj | HHMI Janelia | 2024-07-30 | Author; Implemented | -| Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | -| Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented? | | Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | +| Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | +| Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented | +| Author | Stephan Saalfeld | @axtimwalde | HHMI JAnelia | 2024-07-30 | Author; Implemented (with JB) | ## Overview From 939cc2c02ba9d7240bb7a0f15906c4b9da5b7e33 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 14 Aug 2024 09:23:23 -0400 Subject: [PATCH 06/32] updates matrix/affine/rotation * store as 2d only --- rfc/wip-tform/index.md | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 08916f69..9810e7d6 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -274,15 +274,14 @@ are computable in closed-form (as the [Transformation types](#transformation-typ operation is requested that requires the inverse of a transformation that can not be inverted in closed-form, implementations MAY estimate an inverse, or MAY output a warning that the requested operation is unsupported. - #### Matrix transformations Two transformation types ([affine](#affine) and [rotation](#rotation)) are parametrized by matrices. Matrices are applied to column vectors that represent points in the input coordinate system. The first (last) axis in a coordinate system is the top -(bottom) entry in the column vector. Matrices may be stored either as row-major flat (one-dimensional) arrays or two-dimensional -arrays, either in json or stored in a zarr array. When stored as a 2D zarr array, the first dimension indexes rows, and the -second dimension indexes columns (e.g., an array of `"shape":[3,4]` has 3 rows and 4 columns). When stored as a 2D json array, -the inner array contains rows (e.g. `[[1,2], [3,4], [5,6]]` has 3 rows and 2 columns). +(bottom) entry in the column vector. Matrices are stored as two-dimensional arrays, either as json or in a zarr array. When +stored as a 2D zarr array, the first dimension indexes rows and the second dimension indexes columns (e.g., an array of +`"shape":[3,4]` has 3 rows and 4 columns). When stored as a 2D json array, the inner array contains rows (e.g. `[[1,2,3], +[4,5,6]]` has 2 rows and 3 columns). ### Transformation types @@ -345,40 +344,36 @@ transformations are invertible. #### affine `affine`s are [matrix transformations](#matrix-transformations) from N-dimensional inputs to M-dimensional outputs are represented at `(N)x(M+1)` -matrices in homogeneous coordinates. This transformation type is invertible when `N` equals `M`. -The matrix may be stored as a 2D array (inner arrays represent the rows of the matrix) or as a 1D array (row-major). +matrices in homogeneous coordinates. This transformation type may be (but is not necessarily) invertible when `N` equals `M`. +The matrix MUST be stored as a 2D array either as json or in a zarr array.
path
The path to a zarr-array containing the affine parameters. - The array at this path MUST be 1D or 2D. If 1D, its length MUST be `N*(M+1)`. - If 2D its shape must be `N x (M+1)`.
+ The array at this path MUST be 2D whose shape MUST be `N x (M+1)`.
affine
-
The affine parameters stored in JSON. The matrix may be stored as a row-major flat array of numbers that MUST be - length `N*(M+1)`, or as 2D nested array where the outer array MUST be length `N` and the inner arrays MUST be length `M+1`.
+
The affine parameters stored in JSON. The matrix MUST be stored as 2D nested array where the outer array MUST be length + `N` and the inner arrays MUST be length `M+1`.
#### rotation -`affine`s are [matrix transformations](#matrix-transformations) that are special cases of affine transformations. When possible, a rotation -transformation SHOULD be preferred to its equivalent affine. Input and output dimensionality (N) MUST be identical and greater -than 1. Rotations are stored as `NxN` matrices, see below, and MUST have determinant equal to one, with orthonormal rows and -columns. The matrix may be stored as a 2D array (inner arrays represent the rows of the matrix) or as a 1D array (row-major). -`rotation` transformations are invertible. +`rotation`s are [matrix transformations](#matrix-transformations) that are special cases of affine transformations. When possible, a rotation +transformation SHOULD be preferred to its equivalent affine. Input and output dimensionality (N) MUST be identical. Rotations +are stored as `NxN` matrices, see below, and MUST have determinant equal to one, with orthonormal rows and columns. The matrix +MUST be stored as a 2D array either as json or in a zarr array. `rotation` transformations are invertible.
path
The path to an array containing the affine parameters. - The array at this path MUST be 1D or 2D. If 1D, its length MUST be `N*N`, - if 2D its shape must be `N x N`.
+ The array at this path MUST be 2D whose shape MUST be `N x N`.
rotation
-
The parameters stored in JSON. The matrix may be stored as a row-major flat array of numbers that MUST be - length `N*N`, or as 2D nested array where the outer array MUST be length `N` and the inner arrays MUST be length `N`.
+
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`.
- #### inverseOf An `inverseOf` transformation contains another transformation (often non-linear), and indicates that From ebe3cd864dc17333be04cf5848c445c9705c8c8b Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 14 Aug 2024 09:57:20 -0400 Subject: [PATCH 07/32] add abandoned ideas section. rm some TODOs --- rfc/wip-tform/index.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 9810e7d6..0d6642d8 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -552,8 +552,19 @@ TODO ## Abandoned Ideas -TODO -Considered changing axis-order, preferred this proposal so that backward compatibility will be maintained. +One consideration was to change (reverse) the order of parameters for transformations to match the convention used by many +libraries. We opted not to make this change for two reasons. First, to maintain backward-compatibility. Second, the convention +used by the libraries generally applies for 2D and 3D spatial transformations, but the specification should be applicable to +transformations of arbitrary dimension and axis type, where there is not a strong convention we are aware of. + +An early consideration was to use axis names to indicate correspondence across different coordinate systems (i.e. if two +coordinate systems both have the "x" axis, then it is "the same" axis. We abandoned this for several reasons. It was +restrictive - it is useful to have many coordinate systems with an "x" axis without requiring that they be "identical." Under our +early idea, every set of spatial axes would need unique names ("x1", "x2", ...), and this seemed burdensome. As well, this +approach would have also made transformations less expclicit and likely would have required more complicated implementaitons. +For example, points in two coordinate systems with re-ordered axis names `["x","y"]` vs `["y","x"]` would need to be +axis-permuted, even if such a permutation was not explicitly specified. + ## Prior art and references @@ -573,16 +584,15 @@ transformations in HDF5 which is similarly less interoperable thatn would be ide ## Future possibilities -Additional transformation types. +Additional transformation types should be added in the future. Top candidates include: * thin-plate spline -* bspline +* b-spline * velocity fields * by-coordinate ## Performance -TODO -Summary: This proposal adds new features, and has no effect on performance for existing functionality. +This proposal adds new features, and has no effect on performance for existing functionality. ## Backwards Compatibility @@ -594,7 +604,6 @@ Adds coordinate systems, these contain axes which are backward-compatible with t ## Testing -TODO Public examples of transformations with expected input/output pairs will be provided. ## UI/UX From e95eaf6b6c4781cb13856f0a74f9b24be5ce862e Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 14 Aug 2024 10:53:10 -0400 Subject: [PATCH 08/32] write "Drawbacks, risks, alternatives, and unknowns" * reorder sections --- rfc/wip-tform/index.md | 48 ++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 0d6642d8..0882ce8f 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -505,16 +505,13 @@ to be correct / consistent for points that fall within those extents. It may not appropriate dimensionality. -## Requirements (Recommended Header) - -For the problem(s) solved by this RFC, what constrains the possible solutions? -List other RFCs, or standards (ISO, etc.) which are applicable. It is suggested -that the following text SHOULD be used in all RFCs: +## Requirements The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [IETF RFC 2119][IETF RFC 2119] + ## Stakeholders People who need to represent the result of image registration algorithms, or any imaging @@ -530,7 +527,7 @@ This RFC has been discussed in: * https://github.com/ome/ngff/issues/146 * Several OME-Zarr community calls ([one example](https://forum.image.sc/t/ome-ngff-community-call-transforms-and-tables/71792) -## Implementation (Recommended Header) +## Implementation Many RFCs have an "implementation" section which details how the implementation will work. This section should explain the rough specification changes. The @@ -546,24 +543,18 @@ For the RFC author, typing out the implementation in a high-level often serves as "[rubber duck debugging][rubber duck debugging]" and you can catch a lot of issues or unknown unknowns prior to writing any real code. -## Drawbacks, risks, alternatives, and unknowns (Recommended Header) +## Drawbacks, risks, alternatives, and unknowns -TODO - -## Abandoned Ideas +Adopting this proposal will add an implementation burden because it adds more transformation types. Though this drawback is +softened by the fact that implementations will be able to choose which transformations to support (e.g., implementations may choose +not to support non-linear transformations). -One consideration was to change (reverse) the order of parameters for transformations to match the convention used by many -libraries. We opted not to make this change for two reasons. First, to maintain backward-compatibility. Second, the convention -used by the libraries generally applies for 2D and 3D spatial transformations, but the specification should be applicable to -transformations of arbitrary dimension and axis type, where there is not a strong convention we are aware of. +An alternative to this proposal would be not to add support transformations directly and instead recommend software use an +existing format (e.g., ITK's). The downside of that is that alternative formats will not integrate well with OME-NGFF as they do +not use JSON or Zarr. -An early consideration was to use axis names to indicate correspondence across different coordinate systems (i.e. if two -coordinate systems both have the "x" axis, then it is "the same" axis. We abandoned this for several reasons. It was -restrictive - it is useful to have many coordinate systems with an "x" axis without requiring that they be "identical." Under our -early idea, every set of spatial axes would need unique names ("x1", "x2", ...), and this seemed burdensome. As well, this -approach would have also made transformations less expclicit and likely would have required more complicated implementaitons. -For example, points in two coordinate systems with re-ordered axis names `["x","y"]` vs `["y","x"]` would need to be -axis-permuted, even if such a permutation was not explicitly specified. +In all, we believe the benefits of this proposal (outlined in the Background section) far outweigh these drawbacks, and will +better promote software interoperability than alternatives. ## Prior art and references @@ -581,6 +572,21 @@ The Saalfeld lab at Janelia developed a [custom format](https://github.com/saalfeldlab/template-building/wiki/Hdf5-Deformation-fields) for storing affine and displacement field transformations in HDF5 which is similarly less interoperable thatn would be ideal. +## Abandoned Ideas + +One consideration was to change (reverse) the order of parameters for transformations to match the convention used by many +libraries. We opted not to make this change for two reasons. First, to maintain backward-compatibility. Second, the convention +used by the libraries generally applies for 2D and 3D spatial transformations, but the specification should be applicable to +transformations of arbitrary dimension and axis type, where there is not a strong convention we are aware of. + +An early consideration was to use axis names to indicate correspondence across different coordinate systems (i.e. if two +coordinate systems both have the "x" axis, then it is "the same" axis. We abandoned this for several reasons. It was +restrictive - it is useful to have many coordinate systems with an "x" axis without requiring that they be "identical." Under our +early idea, every set of spatial axes would need unique names ("x1", "x2", ...), and this seemed burdensome. As well, this +approach would have also made transformations less explicit and likely would have required more complicated implementations. +For example, points in two coordinate systems with re-ordered axis names `["x","y"]` vs `["y","x"]` would need to be +axis-permuted, even if such a permutation was not explicitly specified. + ## Future possibilities From d1a5367a9ce4c394cc0b7071c198648d1d699166 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 14 Aug 2024 16:23:19 -0400 Subject: [PATCH 09/32] request some specific feedback --- rfc/wip-tform/index.md | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 0882ce8f..d7e84216 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -504,6 +504,61 @@ Practically, non-invertible transformations have finite extents, so bijection tr to be correct / consistent for points that fall within those extents. It may not be correct for any point of appropriate dimensionality. +## Specific feedback requested + +We ask the reviewers for one specific piece of feedback. Specifically about whether parameters for transformations should +be written as they are currently in the draft pull request, with named parameters at the "top level" e.g.: + +``` +{ + "type": "affine", + "affine": [[1, 2, 3], [4, 5, 6]], + "input": "ji", + "output": "yx" +} +``` + +or alternatively in a `parameters` field: + +``` +{ + "type": "affine", + "parameters": { + "matrix": [[1, 2, 3], [4, 5, 6]] + }, + "input": "ji", + "output": "yx" +} +``` + +In discussions, some authors preferred the latter because it will make the "top-level" keys for transformation +objects all identical, which could make serialization / validation simpler. One downside is that this change +is breaking for the existing `scale` and `translation` transformations + +``` +{ + "type": "scale", + "scale": [2, 3, 4], + "input": "ji", + "output": "yx" +} +``` + +would change to: + +``` +{ + "type": "scale", + "parameters": { + "scale": [2, 3, 4], + }, + "input": "ji", + "output": "yx" +} +``` + +The authors would be interested to hear perspectives from the reviewers on this matter. + ## Requirements From 9cb6ae4b72dfb2378940906379e8b0f8c6b21b72 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:08:31 -0400 Subject: [PATCH 10/32] Update rfc/wip-tform/index.md typo Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index d7e84216..279be301 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -63,7 +63,7 @@ is indicated by the length of its "axes" array. The "volume_micrometers" example The axes of a coordinate system (see below) give information about the types, units, and other properties of the coordinate system's dimensions. Axis `name`s may contain semantically meaningful information, but can be arbitrary. As a result, two coordinate systems that have identical axes in the same order may not be "the same" in the sense that measurements at the same -point refer to different physical entities and therefore should not be analyzed jointly. Task that require images, annotations, +point refer to different physical entities and therefore should not be analyzed jointly. Tasks that require images, annotations, regions of interest, etc. SHOULD ensure that they are in the same coordinate system (same name, with identical axes) or can be transformed to the same coordinate system before doing analysis. See the example below. From 6c42692e04aa538ba49b77c39773546a98e51d9d Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:08:48 -0400 Subject: [PATCH 11/32] Update rfc/wip-tform/index.md add comma Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 279be301..6e85831a 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -64,7 +64,7 @@ The axes of a coordinate system (see below) give information about the types, un system's dimensions. Axis `name`s may contain semantically meaningful information, but can be arbitrary. As a result, two coordinate systems that have identical axes in the same order may not be "the same" in the sense that measurements at the same point refer to different physical entities and therefore should not be analyzed jointly. Tasks that require images, annotations, -regions of interest, etc. SHOULD ensure that they are in the same coordinate system (same name, with identical axes) or can be +regions of interest, etc., SHOULD ensure that they are in the same coordinate system (same name, with identical axes) or can be transformed to the same coordinate system before doing analysis. See the example below. From df1604004d505955cd0a128137f2bb775c511b98 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:10:10 -0400 Subject: [PATCH 12/32] Update rfc/wip-tform/index.md emphasize axis types are strings Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 6e85831a..c225f00b 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -72,7 +72,7 @@ transformed to the same coordinate system before doing analysis. See the example "axes" describes the dimensions of a coordinate systems. 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 "array", "space", "time", "channel", "coordinate", or "displacement" but MAY take other values for custom axis types that are not part of this specification yet. +- 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. - MAY contain the field "discrete". The value MUST be a boolean, and is `true` if the axis represents a discrete dimension. - 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' From 139264d35cbc49a6dd12024bf859db202426b3e9 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:16:46 -0400 Subject: [PATCH 13/32] Update rfc/wip-tform/index.md rephrase Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index c225f00b..df355448 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -81,7 +81,7 @@ transformed to the same coordinate system before doing analysis. See the example If part of multiscales metadata, the length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. -Arrays are often thought of as containing discrete samples along the continuous variable. Axes representing space and time are +Arrays are often used to store discrete samples from a continuous variable. Axes representing space and time are usually continuous, meaning they can be indexed by real-valued (floating point) numbers whereas discrete axes may be indexed only by integers. Arrays are inherently discrete (see Array coordinate systems, below) , but values "in between" discrete coordinates can be retreived using an *interpolation* method. If an axis is continuous (`"discrete" : false`), it indicates From 9c66c3f81d2d0cf20d357c3d3497b747fe45aff2 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:17:19 -0400 Subject: [PATCH 14/32] Update rfc/wip-tform/index.md spelling Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index df355448..395f390b 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -84,7 +84,7 @@ If part of multiscales metadata, the length of "axes" MUST be equal to the numbe Arrays are often used to store discrete samples from a continuous variable. Axes representing space and time are usually continuous, meaning they can be indexed by real-valued (floating point) numbers whereas discrete axes may be indexed only by integers. Arrays are inherently discrete (see Array coordinate systems, below) , but values "in between" discrete -coordinates can be retreived using an *interpolation* method. If an axis is continuous (`"discrete" : false`), it indicates +coordinates can be retrieved using an *interpolation* method. If an axis is continuous (`"discrete" : false`), it indicates that indexing with continuous values is meaningful, and that interpolation may be performed along that axis. Interpolation may be performed jointly across axes with the same `type`, and interpolation should not be performed for discrete axes or jointly across axes with differing `type`s. Other non-continuous variables and axis types are also usually discrete, such as From 3c3ff8e5fd3923ec1f5c1aa212a3d9150fac4acb Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:17:51 -0400 Subject: [PATCH 15/32] Update rfc/wip-tform/index.md rm zarr2 specific phrasing Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 395f390b..78f1313e 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -110,7 +110,7 @@ the last dimension of an array in "C" order are stored contiguously on disk or i The name and axes names MAY be customized by including a `arrayCoordinateSystem` field in -the `.zattr` metadata of the array whose value is a coordinate system object. The length of +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"`. From 69b6f5737e9e8a3a0268eeb86982fd278c238650 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 13:18:09 -0400 Subject: [PATCH 16/32] Update rfc/wip-tform/index.md spelling Co-authored-by: Davis Bennett --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 78f1313e..1a3797a3 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -197,7 +197,7 @@ Conforming readers: - SHOULD be able to apply transformations to images; Coordinate transformations from array to physical coordinates MUST be stored in multiscales, -and MUST be duplicated in the atrributes of the zarr array. Transformations between different images MUST be stored in the +and MUST be duplicated in the attributes of the zarr array. Transformations between different images MUST be stored in the attributes of a parent zarr group. For transformations that store data or parameters in a zarr array, those zarr arrays SHOULD be stored in a zarr group `"coordinateTransformations"`. From dadff02cde9eb5dd76aa975702d9409a2d190c6e Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 28 Aug 2024 14:48:23 -0400 Subject: [PATCH 17/32] rephrase paragraph on discrete/continuous axes thanks @d-v-b --- rfc/wip-tform/index.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 1a3797a3..04f939aa 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -81,17 +81,15 @@ transformed to the same coordinate system before doing analysis. See the example If part of multiscales metadata, the length of "axes" MUST be equal to the number of dimensions of the arrays that contain the image data. -Arrays are often used to store discrete samples from a continuous variable. Axes representing space and time are -usually continuous, meaning they can be indexed by real-valued (floating point) numbers whereas discrete axes may be indexed -only by integers. Arrays are inherently discrete (see Array coordinate systems, below) , but values "in between" discrete -coordinates can be retrieved using an *interpolation* method. If an axis is continuous (`"discrete" : false`), it indicates -that indexing with continuous values is meaningful, and that interpolation may be performed along that axis. Interpolation may -be performed jointly across axes with the same `type`, and interpolation should not be performed for discrete axes or jointly -across axes with differing `type`s. Other non-continuous variables and axis types are also usually discrete, such as -`channel`s, `coordinate`s, and `displacement`s. +Arrays are inherently discrete (see Array coordinate systems, below) but are often used to store discrete samples of a +continuous variable. The continuous values "in between" discrete samples can be retrieved using an *interpolation* method. If an +axis is continuous (`"discrete" : false`), it indicates that interpolation is well-defined. Axes representing `space` and +`time` are usually continuous. Similarly, joint interpolation across axes is well-defined only for axes of the same `type`. In +contrast, discrete axes (`"discrete" : true`) may be indexed only by integers. Axes of representing a `channel`, `coordinate`, or `displacement` are +usually discrete. Note: The most common methods for interpolation are "nearest neighbor", "linear", "cubic", and "windowed sinc". Here, we refer -to any method that obtains values at real valued coordinates using discrete samples as an "interpolator". As such, label images +to any method that obtains values at real-valued coordinates using discrete samples as an "interpolator". As such, label images may be interpolated using "nearest neighbor" to obtain labels at points along the continuum. From b1e0cc85dfb65ea3c35cc0a960e698ebb4a68dc1 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Fri, 20 Sep 2024 12:02:11 -0400 Subject: [PATCH 18/32] typo and other minor fixes thanks @LucaMarconato --- rfc/wip-tform/index.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 04f939aa..23879e7b 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -12,7 +12,7 @@ This RFC is currently in stage D2. | Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | | Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | | Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented | -| Author | Stephan Saalfeld | @axtimwalde | HHMI JAnelia | 2024-07-30 | Author; Implemented (with JB) | +| Author | Stephan Saalfeld | @axtimwalde | HHMI Janelia | 2024-07-30 | Author; Implemented (with JB) | ## Overview @@ -175,7 +175,7 @@ input space to *points* in the output space. 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. + 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. @@ -232,7 +232,7 @@ corresponding to the name of a coordinate system. The coordinate system's name m 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 +`transformation` of an `inverseOf` transformation. In these two cases input and output could, in some cases, be omitted (see below for details). Transformations in the `transformations` list of a `byDimensions` transformation MUST provide `input` and `output` as arrays @@ -287,8 +287,8 @@ stored as a 2D zarr array, the first dimension indexes rows and the second dimen Input and output dimensionality may be determined by the value of the "input" and "output" fields, respectively. If the value of "input" is an array, it's length gives the input dimension, otherwise the length of "axes" for the coordinate system with the name of the "input" value gives the input dimension. If the value of "input" is an array, it's -length gives the input imension, otherwise it is given by the length of "axes" for the coordinate system with -the name of the "input". If the value of "output" is an array, it's length gives the output dimension, +length gives the input dimension, otherwise it is given by the length of "axes" for the coordinate system with +the name of the "input". If the value of "output" is an array, its length gives the output dimension, otherwise it is given by the length of "axes" for the coordinate system with the name of the "output". #### identity @@ -318,8 +318,8 @@ invertible.
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`.
+
translation
+
The translation parameters stored as a JSON list of numbers. The list MUST have length `N`.
@@ -459,14 +459,14 @@ For both `coordinates` and `displacements`, the array data at referred to by `pa For `coordinates`: -* coordinateSystem metadata MUST have exactly one axis with `"type" : "coordinate"` -* If a `coordinates`' input space has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. +* `coordinateSystem` metadata MUST have exactly one axis with `"type" : "coordinate"` +* If the input coordinate system for a `coordinates` transformation has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. * the shape of the array along the "coordinate" axis must be exactly `N` For `displacements`: -* coordinateSystem metadata MUST have exactly one axis with `"type" : "displacement"` -* If a `displacements`' input space has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. +* `coordinateSystem` metadata MUST have exactly one axis with `"type" : "displacement"` +* If the input coordinate system of a `displacements` transformation has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. * the shape of the array along the "displacement" axis must be exactly `N` * `input` and `output` MUST have an equal number of dimensions. @@ -536,7 +536,7 @@ is breaking for the existing `scale` and `translation` transformations ``` { "type": "scale", - "scale": [2, 3, 4], + "scale": [2, 3], "input": "ji", "output": "yx" } @@ -548,7 +548,7 @@ would change to: { "type": "scale", "parameters": { - "scale": [2, 3, 4], + "scale": [2, 3], }, "input": "ji", "output": "yx" From 77a7db7b4c2b8faff6e002056eb9c1d375765abd Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Mon, 23 Sep 2024 11:46:57 -0400 Subject: [PATCH 19/32] fix affine matrix size, and other small fixes thanks @LucaMarconato --- rfc/wip-tform/index.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 23879e7b..215d1b7b 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -156,7 +156,7 @@ input space to *points* in the output space. 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[number]`,
`"path":str` + 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` @@ -341,17 +341,18 @@ transformations are invertible. #### affine -`affine`s are [matrix transformations](#matrix-transformations) from N-dimensional inputs to M-dimensional outputs are represented at `(N)x(M+1)` -matrices in homogeneous coordinates. This transformation type may be (but is not necessarily) invertible when `N` equals `M`. -The matrix MUST be stored as a 2D array either as json or in a zarr array. +`affine`s are [matrix transformations](#matrix-transformations) from N-dimensional inputs to M-dimensional outputs are +represented as the upper `(M)x(N+1)` sub-matrix of a `(M+1)x(N+1)` matrix in [homogeneous +coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates) (see examples). This transformation type may be (but is not necessarily) +invertible when `N` equals `M`. The matrix MUST be stored as a 2D array either as json or as a zarr array.
path
The path to a zarr-array containing the affine parameters. - The array at this path MUST be 2D whose shape MUST be `N x (M+1)`.
+ 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 - `N` and the inner arrays MUST be length `M+1`.
+ `M` and the inner arrays MUST be length `N+1`.
@@ -391,11 +392,13 @@ transformation (if it exists). #### sequence -A `sequence` transformation consists of an ordered array of coordinate transformations, and is invertible if and only if every +A `sequence` transformation consists of an ordered array of coordinate transformations, and is invertible if every coordinate transform in the array is invertible. To apply a sequence transformation to a point in the input coordinate system, apply the first transformation in the list of transformations. Next, apply the second transformation to the result. Repeat until every transformation has been applied. The output of the last transformation is the result of the sequence. + + The transformations included in the `transformations` array may omit their `input` and `output` fields under the conditions outlined below: @@ -417,7 +420,6 @@ outlined below: - #### coordinates and displacements `coordinates` and `displacements` transformations store coordinates or displacements in an array and interpret them as a @@ -451,7 +453,7 @@ inverses. Metadata for these coordinate transforms have the following field: -For both `coordinates` and `displacements`, the array data at referred to by `path` MUST define space and coordinate transform metadata: +For both `coordinates` and `displacements`, the array data referred to by `path` MUST define space and coordinate transform metadata: * Every axis name in the `coordinateTransform`'s `input` MUST appear in the coordinate system * The array dimension corresponding to the `coordinate` or `displacement` axis MUST have length equal to the dimensionality of the `coordinateTransform` `output` From cae3490cc51a9df30c2ad05c2885a4276fde4bb3 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Mon, 23 Sep 2024 13:21:03 -0400 Subject: [PATCH 20/32] clarify invertibility of sequence --- rfc/wip-tform/index.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 215d1b7b..a62bab88 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -392,12 +392,11 @@ transformation (if it exists). #### sequence -A `sequence` transformation consists of an ordered array of coordinate transformations, and is invertible if every -coordinate transform in the array is invertible. To apply a sequence transformation to a point in the input coordinate system, -apply the first transformation in the list of transformations. Next, apply the second transformation to the result. Repeat until -every transformation has been applied. The output of the last transformation is the result of the sequence. - - +A `sequence` transformation consists of an ordered array of coordinate transformations, and is invertible if every coordinate +transform in the array is invertible (though could be invertible in other cases as well). To apply a sequence transformation +to a point in the input coordinate system, apply the first transformation in the list of transformations. Next, apply the second +transformation to the result. Repeat until every transformation has been applied. The output of the last transformation is the +result of the sequence. The transformations included in the `transformations` array may omit their `input` and `output` fields under the conditions outlined below: From 3659933eb3637f88437e6806c7ae6065544dfe71 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Mon, 23 Sep 2024 13:21:20 -0400 Subject: [PATCH 21/32] add @normanrz as endorser * and clean up table --- rfc/wip-tform/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index a62bab88..a4f2fbcd 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -9,10 +9,11 @@ This RFC is currently in stage D2. | Role | Name | GitHub Handle | Institution | Date | Status | |--------|-----------|---------------|-------------|------------|----------------------------------------| | Author | John Bogovic | @bogovicj | HHMI Janelia | 2024-07-30 | Author; Implemented | -| Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | +| Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | | Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | | Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented | -| Author | Stephan Saalfeld | @axtimwalde | HHMI Janelia | 2024-07-30 | Author; Implemented (with JB) | +| Author | Stephan Saalfeld | @axtimwalde | HHMI Janelia | 2024-07-30 | Author; Implemented (with JB) | +| Endorser | Norman Rzepka | @normanrz | Scalable Minds| 2024-08-22 | | ## Overview From 9c18d4d8e7d776fc157db71c2b3ca62bddd46abf Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 25 Sep 2024 13:46:16 -0400 Subject: [PATCH 22/32] fix spelling --- rfc/wip-tform/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index a4f2fbcd..45500349 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -625,7 +625,7 @@ While effective, they can only describe one type of non-linear transformation. The Saalfeld lab at Janelia developed a [custom format](https://github.com/saalfeldlab/template-building/wiki/Hdf5-Deformation-fields) for storing affine and displacement field -transformations in HDF5 which is similarly less interoperable thatn would be ideal. +transformations in HDF5 which is similarly less interoperable than would be ideal. ## Abandoned Ideas From 8368cae63f2e078c94d5199ba42ea555ecd0b4f3 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 25 Sep 2024 13:46:29 -0400 Subject: [PATCH 23/32] flesh out coordinates + displacements description --- rfc/wip-tform/index.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/rfc/wip-tform/index.md b/rfc/wip-tform/index.md index 45500349..e7b9efd7 100644 --- a/rfc/wip-tform/index.md +++ b/rfc/wip-tform/index.md @@ -422,19 +422,24 @@ outlined below: #### coordinates and displacements -`coordinates` and `displacements` transformations store coordinates or displacements in an array and interpret them as a -transformation. Applying the transformation amounts to looking up the appropriate locations in the array and interpolating -if necessary. +`coordinates` and `displacements` transformations store coordinates or displacements in an array and interpret them as a vector +field that defines a transformation. The arrays must have a dimension corresponding to every axis of the input coordinate +system and one additional dimension to hold components of the vector. Applying the transformation amounts to looking up the +appropriate vector in the array, interpolating if necessary, and treating it either as a position directly (`coordinates`) or a +displacement of the input point (`displacements`). -These transformation types refer to an array at location specified by the `"path"` parameter whose coordinate sytem MUST contain -an axis with type `coordinate` or `displacement` respectively for transformations of type `coordinates` or `displacements`. This -axis MUST be of length equal to the number of axes of the output coordinate system and SHOULD be the last axis (contiguous on -disk when c-order). The coordinate system MUST also contain an axis identical to every axis of its input coordinate system in -the same order. As a consequence, the array will have one dimension more than its input coordinate system. +These transformation types refer to an array at location specified by the `"path"` parameter. The input and output coordinate +systems for these transformations ("input / output coordinate systems") constrain the array size and the coordinate system +metadata for the array ("field coordinate system"). -The `i`th value of the array along the `coordinate` or `displacement` axis refers to the displacement -or coordinate of `i`th output axis. See the example below. +* If the input coordinate system has `N` axes, the array at location path MUST have `N+1` dimensions +* The field coordinate system MUST contain an axis identical to every axis of its input coordinate system in the same order. +* The field coordinate system MUST contain an axis with type `coordinate` or `displacement` respectively for transformations of type `coordinates` or `displacements`. + * This SHOULD be the last axis (contiguous on disk when c-order). +* If the output coordinate system has `M` axes, the length of the array along the `coordinate`/`displacement` dimension MUST be of length `M`. +The `i`th value of the array along the `coordinate` or `displacement` axis refers to the coordinate or displacement +of the `i`th output axis. See the example below. `coordinates` and `displacements` transformations are not invertible in general, but implementations MAY approximate their inverses. Metadata for these coordinate transforms have the following field: @@ -453,27 +458,26 @@ inverses. Metadata for these coordinate transforms have the following field: -For both `coordinates` and `displacements`, the array data referred to by `path` MUST define space and coordinate transform metadata: + +For both `coordinates` and `displacements`, the array data at referred to by `path` MUST define coordinate system and coordinate transform metadata: * Every axis name in the `coordinateTransform`'s `input` MUST appear in the coordinate system -* The array dimension corresponding to the `coordinate` or `displacement` axis MUST have length equal to the dimensionality of the `coordinateTransform` `output` +* The array dimension corresponding to the `coordinate` or `displacement` axis MUST have length equal to the number of dimensions of the `coordinateTransform` `output` +* If the input coordinate system `N` axes, then the array data at `path` MUST have `(N + 1)` dimensions. * SHOULD have a `name` identical to the `name` of the corresponding `coordinateTransform`. For `coordinates`: * `coordinateSystem` metadata MUST have exactly one axis with `"type" : "coordinate"` -* If the input coordinate system for a `coordinates` transformation has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. * the shape of the array along the "coordinate" axis must be exactly `N` For `displacements`: * `coordinateSystem` metadata MUST have exactly one axis with `"type" : "displacement"` -* If the input coordinate system of a `displacements` transformation has dimensionality `N`, then the array data at `path` MUST have dimensionality equal to `(N + 1)`. * the shape of the array along the "displacement" axis must be exactly `N` * `input` and `output` MUST have an equal number of dimensions. - #### byDimension {#trafo-byDimension} `byDimension` transformations build a high dimensional transformation using lower dimensional transformations From 6a02c6aa57aecd3ccaa3a74bb3208eb7a55ef6b0 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 09:40:55 +0200 Subject: [PATCH 24/32] RFC-5: assign number --- rfc/{wip-tform => 5}/index.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rfc/{wip-tform => 5}/index.md (100%) diff --git a/rfc/wip-tform/index.md b/rfc/5/index.md similarity index 100% rename from rfc/wip-tform/index.md rename to rfc/5/index.md From 797925652c35f78584ae34f95671daed34dff41d Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 09:53:39 +0200 Subject: [PATCH 25/32] Minor navigation improvements --- rfc/1/versions/index.md | 2 +- rfc/2/versions/index.md | 2 +- rfc/4/index.md | 1 - rfc/4/versions/index.md | 2 +- rfc/5/comments/index.md | 9 +++++++++ rfc/5/index.md | 11 ++++++++++- rfc/5/responses/index.md | 9 +++++++++ rfc/5/reviews/index.md | 9 +++++++++ rfc/5/versions/index.md | 9 +++++++++ rfc/listing.csv | 4 +++- 10 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 rfc/5/comments/index.md create mode 100644 rfc/5/responses/index.md create mode 100644 rfc/5/reviews/index.md create mode 100644 rfc/5/versions/index.md diff --git a/rfc/1/versions/index.md b/rfc/1/versions/index.md index 3be0622c..0ff8a587 100644 --- a/rfc/1/versions/index.md +++ b/rfc/1/versions/index.md @@ -1,6 +1,6 @@ # Versions -Key versions of the RFC which have been sent for review, etc. +Key versions of RFC-1 which have been sent for review, etc. ```{toctree} :maxdepth: 1 diff --git a/rfc/2/versions/index.md b/rfc/2/versions/index.md index 3be0622c..84cb92f4 100644 --- a/rfc/2/versions/index.md +++ b/rfc/2/versions/index.md @@ -1,6 +1,6 @@ # Versions -Key versions of the RFC which have been sent for review, etc. +Key versions of RFC-2 which have been sent for review, etc. ```{toctree} :maxdepth: 1 diff --git a/rfc/4/index.md b/rfc/4/index.md index 335cab54..6bd892ee 100644 --- a/rfc/4/index.md +++ b/rfc/4/index.md @@ -3,7 +3,6 @@ ```{toctree} :hidden: :maxdepth: 1 -templates/index reviews/index comments/index responses/index diff --git a/rfc/4/versions/index.md b/rfc/4/versions/index.md index 3be0622c..618140ea 100644 --- a/rfc/4/versions/index.md +++ b/rfc/4/versions/index.md @@ -1,6 +1,6 @@ # Versions -Key versions of the RFC which have been sent for review, etc. +Key versions of RFC-4 which have been sent for review, etc. ```{toctree} :maxdepth: 1 diff --git a/rfc/5/comments/index.md b/rfc/5/comments/index.md new file mode 100644 index 00000000..07025b45 --- /dev/null +++ b/rfc/5/comments/index.md @@ -0,0 +1,9 @@ +# Comments + +Additional comments of RFC-5: + +```{toctree} +:maxdepth: 1 +:glob: +*/index +``` diff --git a/rfc/5/index.md b/rfc/5/index.md index e7b9efd7..5f110e3a 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -1,4 +1,13 @@ -# RFC-X Coordinate systems and transformations +# RFC-5 Coordinate systems and transformations + +```{toctree} +:hidden: +:maxdepth: 1 +reviews/index +comments/index +responses/index +versions/index +``` Add named coordinate systems and expand and clarify coordinate transformations. diff --git a/rfc/5/responses/index.md b/rfc/5/responses/index.md new file mode 100644 index 00000000..21b3f300 --- /dev/null +++ b/rfc/5/responses/index.md @@ -0,0 +1,9 @@ +# Responses + +Responses from the authors of RFC-5: + +```{toctree} +:maxdepth: 1 +:glob: +*/index +``` diff --git a/rfc/5/reviews/index.md b/rfc/5/reviews/index.md new file mode 100644 index 00000000..a38a57a6 --- /dev/null +++ b/rfc/5/reviews/index.md @@ -0,0 +1,9 @@ +# Reviews + +Reviews of RFC-5: + +```{toctree} +:maxdepth: 1 +:glob: +*/index +``` diff --git a/rfc/5/versions/index.md b/rfc/5/versions/index.md new file mode 100644 index 00000000..3d07465a --- /dev/null +++ b/rfc/5/versions/index.md @@ -0,0 +1,9 @@ +# Versions + +Key versions of RFC-5 which have been sent for review, etc. + +```{toctree} +:maxdepth: 1 +:glob: +*/index +``` diff --git a/rfc/listing.csv b/rfc/listing.csv index 467b9351..79be88a2 100644 --- a/rfc/listing.csv +++ b/rfc/listing.csv @@ -2,4 +2,6 @@ RFC,Description,Date,Status [0](0/index.md),Original consensus model for decision making,2021,N/A [1](1/index.md),RFC Process,2024,Under review [2](2/index.md),Zarr V3 Support,2024,Accepted -[3](3/index.md),Axis Anatomical Orientation,Under review +3,Remove axis restrictions,Clarifications +[4](4/index.md),Axis Anatomical Orientation,Under review +[5](5/index.md),Coordinate systems and transformations,Under review From 08d6a6196c45463120877ed9b4aca2f4d49da86d Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 09:54:37 +0200 Subject: [PATCH 26/32] Update to long-form status table --- rfc/5/index.md | 60 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/rfc/5/index.md b/rfc/5/index.md index 5f110e3a..7fd4820a 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -13,16 +13,56 @@ Add named coordinate systems and expand and clarify coordinate transformations. ## Status -This RFC is currently in stage D2. - -| Role | Name | GitHub Handle | Institution | Date | Status | -|--------|-----------|---------------|-------------|------------|----------------------------------------| -| Author | John Bogovic | @bogovicj | HHMI Janelia | 2024-07-30 | Author; Implemented | -| Author | Davis Bennett | @d-v-b | | 2024-07-30 | Author; Implemented validation | -| Author | Luca Marconato | @LucaMarconato | EMBL | 2024-07-30 | Author; Implemented | -| Author | Matt McCormick | @thewtex | ITK | 2024-07-30 | Author; Implemented | -| Author | Stephan Saalfeld | @axtimwalde | HHMI Janelia | 2024-07-30 | Author; Implemented (with JB) | -| Endorser | Norman Rzepka | @normanrz | Scalable Minds| 2024-08-22 | | +This RFC is currently in RFC state `R1` (send for review). + +```{list-table} Record +:widths: 8, 20, 20, 20, 15, 10 +:header-rows: 1 +:stub-columns: 1 + +* - Role + - Name + - GitHub Handle + - Institution + - Date + - Status +* - Author + - John Bogovic + - @bogovicj + - HHMI Janelia + - 2024-07-30 + - Implemented +* - Author + - Davis Bennett + - @d-v-b + - + - 2024-07-30 + - Implemented validation +* - Author + - Luca Marconato + - @LucaMarconato + - EMBL + - 2024-07-30 + - Implemented +* - Author + - Matt McCormick + - @thewtex + - ITK + - 2024-07-30 + - Implemented +* - Author + - Stephan Saalfeld + - @axtimwalde + - HHMI Janelia + - 2024-07-30 + - Implemented (with JB) +* - Endorser + - Norman Rzepka + - @normanrz + - Scalable Minds + - 2024-08-22 + - +``` ## Overview From d3e393761e1fb7c8c72867e14f6bb992c5f60574 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 09:59:37 +0200 Subject: [PATCH 27/32] Remove reference to missing example 'above' --- rfc/5/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfc/5/index.md b/rfc/5/index.md index 7fd4820a..3fdffe37 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -107,7 +107,7 @@ A "coordinate system" is a collection of "axes" / dimensions with a name. Every The order of the `"axes"` list matters and defines the index of each array dimension and coordinates for points in that -coordinate system. For the above example, the `"x"` dimension is the first dimension. The "dimensionality" of a coordinate system +coordinate system. The "dimensionality" of a coordinate system is indicated by the length of its "axes" array. The "volume_micrometers" example coordinate system above is three dimensional (3D). The axes of a coordinate system (see below) give information about the types, units, and other properties of the coordinate From 3fb7ac1d2f761740e1fe0d9968535d95ac5049dc Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 10:08:21 +0200 Subject: [PATCH 28/32] Fix markdown for rendering of `` blocks - In HTML sections, replace `` with blocks - Replace div notes with MyST directives --- rfc/5/index.md | 99 +++++++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/rfc/5/index.md b/rfc/5/index.md index 3fdffe37..ff963f52 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -191,46 +191,46 @@ input space to *points* in the output space. - Parameter values MUST be compatible with input and output space dimensionality (see details). - @@ -367,9 +367,9 @@ invertible.
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`.
+ The array at this path MUST be 1D, and its length MUST be N.
translation
-
The translation parameters stored as a JSON list of numbers. The list MUST have length `N`.
+
The translation parameters stored as a JSON list of numbers. The list MUST have length N.
@@ -383,9 +383,9 @@ transformations are invertible.
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`.
+ 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`.
+
The scale parameters stored as a JSON list of numbers. The list MUST have length N.
@@ -399,10 +399,10 @@ invertible when `N` equals `M`. The matrix MUST be stored as a 2D array either
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)`.
+ 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`.
+ M and the inner arrays MUST be length N+1.
@@ -416,10 +416,10 @@ MUST be stored as a 2D array either as json or in a zarr array. `rotation` trans
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`.
+ 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`.
+
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.
@@ -430,14 +430,13 @@ transforming points from output to input coordinate systems is possible using th Transforming points from the input to the output coordinate systems requires the inverse of the contained transformation (if it exists). -
- Software libraries that perform image registration often return the transformation from fixed image - coordinates to moving image coordinates, because this "inverse" transformation is most often required - when rendering the transformed moving image. Results such as this may be enclosed in an `inverseOf` - transformation. This enables the "outer" coordinate transformation to specify the moving image coordinates - as `input` and fixed image coordinates as `output`, a choice that many users and developers find intuitive. -
- +```{note} +Software libraries that perform image registration often return the transformation from fixed image +coordinates to moving image coordinates, because this "inverse" transformation is most often required +when rendering the transformed moving image. Results such as this may be enclosed in an `inverseOf` +transformation. This enables the "outer" coordinate transformation to specify the moving image coordinates +as `input` and fixed image coordinates as `output`, a choice that many users and developers find intuitive. +``` #### sequence @@ -497,7 +496,7 @@ inverses. Metadata for these coordinate transforms have the following field:
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 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:
    @@ -527,7 +526,7 @@ For `displacements`: * `input` and `output` MUST have an equal number of dimensions. -#### byDimension {#trafo-byDimension} +#### byDimension `byDimension` transformations build a high dimensional transformation using lower dimensional transformations on subsets of dimensions. @@ -535,9 +534,9 @@ on subsets of dimensions.
    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`. + 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.
    From b006360058f10e7e3f451892626422058cec31d0 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 10:17:04 +0200 Subject: [PATCH 29/32] Simplify deflist where possible --- conf.py | 1 + rfc/5/index.md | 56 ++++++++++++++++++++------------------------------ 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/conf.py b/conf.py index 5e414675..f18fb755 100644 --- a/conf.py +++ b/conf.py @@ -16,6 +16,7 @@ extensions = ["myst_parser"] source_suffix = [".rst", ".md"] myst_heading_anchors = 5 +myst_enable_extensions = ["deflist"] templates_path = ['_templates'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.git', '.pytest_cache', '**/.pytest_cache', '**/.tox', 'README.md', 'LICENSE.md', 'CONTRIBUTING.md'] diff --git a/rfc/5/index.md b/rfc/5/index.md index ff963f52..7bc7c0af 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -364,13 +364,11 @@ translation transformation should be preferred to its equivalent affine. Input a identical and MUST equal the the length of the "translation" array (N). `translation` transformations are invertible. -
    -
    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.
    -
    translation
    -
    The translation parameters stored as a JSON list of numbers. The list MUST have length N.
    -
    +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`. + +translation +: The translation parameters stored as a JSON list of numbers. The list MUST have length `N`. #### scale @@ -380,13 +378,11 @@ SHOULD be preferred to its equivalent affine. Input and output dimensionality MU the the length of the "scale" array (N). Values in the `scale` array SHOULD be non-zero; in that case, `scale` transformations are invertible. -
    -
    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 +: 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`. #### affine @@ -396,14 +392,11 @@ represented as the upper `(M)x(N+1)` sub-matrix of a `(M+1)x(N+1)` matrix in [ho coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates) (see examples). This transformation type may be (but is not necessarily) invertible when `N` equals `M`. The matrix MUST be stored as a 2D array either as json or as a zarr array. -
    -
    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 +: 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`. #### rotation @@ -413,14 +406,11 @@ transformation SHOULD be preferred to its equivalent affine. Input and output di are stored as `NxN` matrices, see below, and MUST have determinant equal to one, with orthonormal rows and columns. The matrix MUST be stored as a 2D array either as json or in a zarr array. `rotation` transformations are invertible. -
    -
    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 +: 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`. #### inverseOf @@ -462,10 +452,8 @@ outlined below: below), and under all other conditions. -
    -
    transformations
    -
    A non-empty array of transformations.
    -
    +transformations +: A non-empty array of transformations. #### coordinates and displacements From 63976bfafe45225a79510f9c9fc40fa0c0081f78 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 10:18:56 +0200 Subject: [PATCH 30/32] Fix stakeholders links --- rfc/5/index.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/rfc/5/index.md b/rfc/5/index.md index 7bc7c0af..8c97ea06 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -614,13 +614,9 @@ scientist in need of affine or non-linear transformations. This RFC has been discussed in: -* [This github pull-request](https://github.com/ome/ngff/pull/138) -* These github issues: - * https://github.com/ome/ngff/issues/84 - * https://github.com/ome/ngff/issues/94 - * https://github.com/ome/ngff/issues/101 - * https://github.com/ome/ngff/issues/146 -* Several OME-Zarr community calls ([one example](https://forum.image.sc/t/ome-ngff-community-call-transforms-and-tables/71792) +* [PR 138](https://github.com/ome/ngff/pull/138) +* Issues [84](https://github.com/ome/ngff/issues/84), [94](https://github.com/ome/ngff/issues/94), [101](https://github.com/ome/ngff/issues/101), and [146](https://github.com/ome/ngff/issues/146) +* Several OME-Zarr community calls ([one example](https://forum.image.sc/t/ome-ngff-community-call-transforms-and-tables/71792)) ## Implementation From 4d33b87cf158d3df96eab204181f5cbf5929bb00 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 10:20:52 +0200 Subject: [PATCH 31/32] Add changelog --- rfc/5/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rfc/5/index.md b/rfc/5/index.md index 8c97ea06..23b58cfe 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -715,3 +715,8 @@ choose between different options, or software could choose a default (e.g. the f [`multiscales` in version 0.4](https://ngff.openmicroscopy.org/0.4/#multiscale-md) has a similar consideration. +## Changelog + +| Date | Description | Link | +| ---------- | ---------------------------- | ---------------------------------------------------------------------------- | +| 2024-10-08 | RFC number assigned | [https://github.com/ome/ngff/pull/255](https://github.com/ome/ngff/pull/255) | From 67a217a7449523f609689f44075ce7d3a0ddfa54 Mon Sep 17 00:00:00 2001 From: Josh Moore Date: Tue, 8 Oct 2024 10:25:18 +0200 Subject: [PATCH 32/32] Minor index/changelog adjustments --- rfc/5/index.md | 2 +- rfc/listing.csv | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rfc/5/index.md b/rfc/5/index.md index 23b58cfe..b6102e42 100644 --- a/rfc/5/index.md +++ b/rfc/5/index.md @@ -719,4 +719,4 @@ choose between different options, or software could choose a default (e.g. the f | Date | Description | Link | | ---------- | ---------------------------- | ---------------------------------------------------------------------------- | -| 2024-10-08 | RFC number assigned | [https://github.com/ome/ngff/pull/255](https://github.com/ome/ngff/pull/255) | +| 2024-10-08 | RFC assigned and published | [https://github.com/ome/ngff/pull/255](https://github.com/ome/ngff/pull/255) | diff --git a/rfc/listing.csv b/rfc/listing.csv index 79be88a2..c8b2800c 100644 --- a/rfc/listing.csv +++ b/rfc/listing.csv @@ -2,6 +2,6 @@ RFC,Description,Date,Status [0](0/index.md),Original consensus model for decision making,2021,N/A [1](1/index.md),RFC Process,2024,Under review [2](2/index.md),Zarr V3 Support,2024,Accepted -3,Remove axis restrictions,Clarifications -[4](4/index.md),Axis Anatomical Orientation,Under review -[5](5/index.md),Coordinate systems and transformations,Under review +3,Remove axis restrictions,2024, Clarifications +[4](4/index.md),Axis Anatomical Orientation,2024,Under review +[5](5/index.md),Coordinate systems and transformations,2024,Under review
`identity` +
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` +
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[number]`,
`"path":str` +
rotation + one of:
"rotation":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]` +
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` +
displacements + "path":str
"interpolation":str
Displacement field transformation located at (path). -
`coordinates` - `"path":str`
`"interpolation":str` +
coordinates + "path":str
"interpolation":str
Coordinate field transformation located at (path). -
`inverseOf` - `"transform":Transform` +
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` +
bijection + "forward":Transform
"inverse":Transform
Explicitly define an invertible transformation by providing a forward transformation and its inverse. -
`byDimension` - `"transformations":List[Transformation]` +
byDimension + "transformations":List[Transformation] Define a high dimensional transformation using lower dimensional transformations on subsets of dimensions.