Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add idr0101 images, one with translation #13

Merged
merged 4 commits into from
Oct 24, 2022

Conversation

will-moore
Copy link
Member

Adds 2 images from ome/napari-ome-zarr#32
This is the first example of coordinateTransforms translate, at the dataset level. Added this to keywords.

@sbesson
Copy link
Member

sbesson commented Oct 13, 2022

Thanks @will-moore. Is this staging anywhere otherwise I believe we should get this merged.

Interestingly what is missing at the moment is the fact the transformation for 13457537.zarr should be considered as relative to the coordinate system of 13457227.zarr.

Two related thoughts:

  • I suspect this sort of relationship should be better captured by the ongoing coordinate systems/transformations proposal in Coordinate systems and new coordinate transformations proposal ome/ngff#138. We should definitely keep idr0101 as an example when entering the evaluation of the specification and its implementations
  • even with the new specification, the fact that the two images are stored in completely separate Zarr datastores (since they are completely separate Image objects in IDR) might be an issue. Possibly wrapping both multiscales within a bioformats2raw.layout group would allow to express this relationship.

@sbesson
Copy link
Member

sbesson commented Oct 13, 2022

See also discussion at ome/ngff#139 (comment)

(omeropy) sbesson@Sebastiens-MacBook-Pro-2 ~ % curl https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457537.zarr/.zattrs
{
    "_creator": {
        "name": "omero-zarr",
        "version": "0.1.dev314+g33e42b1"
    },
    "multiscales": [
        {
            "axes": [
                {
                    "name": "t",
                    "type": "time"
                },
                {
                    "name": "c",
                    "type": "channel"
                },
                {
                    "name": "z",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "y",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "x",
                    "type": "space",
                    "units": "micrometer"
                }
            ],
            "datasets": [
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.108335,
                                0.108335
                            ],
                            "type": "scale"
                        },
                        {
                            "translation": [
                                0,
                                0,
                                1.2,
                                52.109135,
                                60.88427
                            ],
                            "type": "translation"
                        }
                    ],
                    "path": "0"
                },
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.21667,
                                0.21667
                            ],
                            "type": "scale"
                        }
                    ],
                    "path": "1"
                },
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.43334,
                                0.43334
                            ],
                            "type": "scale"
                        }
                    ],
                    "path": "2"
                }
            ],
            "version": "0.4"
        }
    ],
    "omero": {
        "channels": [
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 1",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 2",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 3",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 4",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "0000FF",
                "family": "linear",
                "inverted": false,
                "label": "DAPI",
                "window": {
                    "end": 5000.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FF0000",
                "family": "linear",
                "inverted": false,
                "label": "Hyb probe",
                "window": {
                    "end": 100.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            }
        ],
        "id": 1,
        "rdefs": {
            "defaultT": 0,
            "defaultZ": 9,
            "model": "color"
        },
        "version": "0.4"
    }
}

Echoing Norman's question, I definitely feel that either the translation should be factorized at the multiscales level or defined for each multiscale dataset.

@will-moore
Copy link
Member Author

I don't disagree, but playing devil's advocate... I wonder if this exposes an expectation of the spec that each dataset dict has the same list of coordinateTransformations?
Currently, for v0.4 every one has to have scale, and the only other option is translation, so there's limited scope for divergence. But with v0.5 it will be possible to have lots of different transformations.

Probably in this case, we really should be applying the translation at the multiscales level. In fact, I assume the same is true for most transformations except scale, since it would be unexpected for different resolutions of a pyramid to have different translation or other transformations?

cc @bogovicj

@will-moore
Copy link
Member Author

will-moore commented Oct 13, 2022

@sbesson I've added translation to the other dataasets for https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457537.zarr
Also added https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457539.zarr which instead has coordinateTransformation on the multiscales dict instead of the datasets. Strange that this MUST also have scale in order to be valid, even though I don't want to scale - so I added a no-op scale of 1,1,1,1,1. See https://ome.github.io/ome-ngff-validator/?source=https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457539.zarr

@sbesson
Copy link
Member

sbesson commented Oct 14, 2022

% curl https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457537.zarr/.zattrs
{
    "_creator": {
        "name": "omero-zarr",
        "version": "0.1.dev314+g33e42b1"
    },
    "multiscales": [
        {
            "axes": [
                {
                    "name": "t",
                    "type": "time"
                },
                {
                    "name": "c",
                    "type": "channel"
                },
                {
                    "name": "z",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "y",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "x",
                    "type": "space",
                    "units": "micrometer"
                }
            ],
            "datasets": [
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.108335,
                                0.108335
                            ],
                            "type": "scale"
                        },
                        {
                            "translation": [
                                0,
                                0,
                                1.2,
                                52.109135,
                                60.88427
                            ],
                            "type": "translation"
                        }
                    ],
                    "path": "0"
                },
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.21667,
                                0.21667
                            ],
                            "type": "scale"
                        },
                        {
                            "translation": [
                                0,
                                0,
                                1.2,
                                52.109135,
                                60.88427
                            ],
                            "type": "translation"
                        }
                    ],
                    "path": "1"
                },
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.43334,
                                0.43334
                            ],
                            "type": "scale"
                        },
                        {
                            "translation": [
                                0,
                                0,
                                1.2,
                                52.109135,
                                60.88427
                            ],
                            "type": "translation"
                        }
                    ],
                    "path": "2"
                }
            ],
            "version": "0.4"
        }
    ],
    "omero": {
        "channels": [
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 1",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 2",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 3",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 4",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "0000FF",
                "family": "linear",
                "inverted": false,
                "label": "DAPI",
                "window": {
                    "end": 5000.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FF0000",
                "family": "linear",
                "inverted": false,
                "label": "Hyb probe",
                "window": {
                    "end": 100.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            }
        ],
        "id": 1,
        "rdefs": {
            "defaultT": 0,
            "defaultZ": 9,
            "model": "color"
        },
        "version": "0.4"
    }
}

and

% curl https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457539.zarr/.zattrs
{
    "_creator": {
        "name": "omero-zarr",
        "version": "0.1.dev314+g33e42b1"
    },
    "multiscales": [
        {
            "axes": [
                {
                    "name": "t",
                    "type": "time"
                },
                {
                    "name": "c",
                    "type": "channel"
                },
                {
                    "name": "z",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "y",
                    "type": "space",
                    "units": "micrometer"
                },
                {
                    "name": "x",
                    "type": "space",
                    "units": "micrometer"
                }
            ],
            "coordinateTransformations": [
                {
                    "scale": [
                        1,
                        1,
                        1,
                        1,
                        1
                    ],
                    "type": "scale"
                },
                {
                    "translation": [
                        0,
                        0,
                        1.2,
                        161.59,
                        176.44
                    ],
                    "type": "translation"
                }
            ],
            "datasets": [
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.108335,
                                0.108335
                            ],
                            "type": "scale"
                        }
                    ],
                    "path": "0"
                },
                {
                    "coordinateTransformations": [
                        {
                            "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.21667,
                                0.21667
                            ],
                            "type": "scale"
                        }
                    ],
                    "path": "1"
                }
            ],
            "version": "0.4"
        }
    ],
    "omero": {
        "channels": [
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 1",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 2",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 3",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FFFFFF",
                "family": "linear",
                "inverted": false,
                "label": "cy 4",
                "window": {
                    "end": 1200.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "0000FF",
                "family": "linear",
                "inverted": false,
                "label": "DAPI",
                "window": {
                    "end": 5000.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            },
            {
                "active": true,
                "coefficient": 1.0,
                "color": "FF0000",
                "family": "linear",
                "inverted": false,
                "label": "Hyb probe",
                "window": {
                    "end": 100.0,
                    "max": 65535.0,
                    "min": 0.0,
                    "start": 0.0
                }
            }
        ],
        "id": 1,
        "rdefs": {
            "defaultT": 0,
            "defaultZ": 9,
            "model": "color"
        },
        "version": "0.4"
    }
}

Thanks @will-moore. Very useful to have representative samples capturing the different variants of the coordinateTransformations defined in the OME-NGFF specification.

Strange that this MUST also have scale in order to be valid, even though I don't want to scale - so I added a no-op scale of 1,1,1,1,1.

Interesting. I had forgotten about this requirement and also confused at first as well. I suspect it comes the from strict semantics in https://ngff.openmicroscopy.org/0.4/#trafo-md that mandates that Each "multiscales" dictionary MAY contain the field "coordinateTransformations", describing transformations that are applied to all resolution levels in the same manner. The transformations MUST follow the same rules about allowed types, order, etc. as in "datasets:coordinateTransformations" and are applied after them..

Rather than using the no-op 1, 1, 1, 1, 1 scale transformation, I could imaging an alternate representation would be to store the scaling of the first resolution in physical units at the multiscales level i.e.

                {
                    "scale": [
                                1.0,
                                1.0,
                                0.4,
                                0.108335,
                                0.108335
                    ],
                    "type": "scale"
                },
                {
                    "translation": [
                        0,
                        0,
                        1.2,
                        161.59,
                        176.44
                    ],
                    "type": "translation"
                }

and then the scale of the different datasets could be simply expressed as 1,1,1,1,1, 1,1,2,2,2, 1,1,1,4,4,4 ...

@bogovicj
Copy link

@will-moore

Probably in this case, we really should be applying the translation at the multiscales level.

I agree - that's also how I would do it. But also think one should be allowed to put the translation in every dataset in the multiscales if that's what they want.

since it would be unexpected for different resolutions of a pyramid to have different translation or other transformations?

One common case where different levels should really have different translations is if the downsampling simply averages adjacent pixels.

Numbers indicate the coordinate of the center of the pixel, then averaging pixels with coordinates 0 and 1 gives a pixel with center 0.5.

| 0.0 | 1.0 | 
|    0.5    |

But with v0.5 it will be possible to have lots of different transformations.

This is also a good point, I'd consider adding the restriction : different multiscale levels must be related to each other only through scale and translation transformations. Other transformations have to happen at the multiscales level. I don't know of anyone doing otherwise.

@will-moore
Copy link
Member Author

@sbesson Fixed https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0101A/13457539.zarr/.zattrs to have datasets scale of 1,1,1,1,1,, 1,1,1,2,2 and apply pixel size scaling at the multiscales level.

Copy link
Member

@sbesson sbesson left a comment

@will-moore
Copy link
Member Author

@sbesson Could you merge this if you're happy with it, thanks.

@sbesson sbesson merged commit c0ab697 into IDR:main Oct 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants