-
Notifications
You must be signed in to change notification settings - Fork 35
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 optional OMERO rendering metadata #160
Add optional OMERO rendering metadata #160
Conversation
This includes introducing min/max calculation so that the channel min/max values are written in each group. See https://ngff.openmicroscopy.org/latest/#omero-md The --no-omero option turns off OMERO metadata population, which also turns off min/max calculation.
a9e555e and ec67911 should fix color and min/max issues mentioned separately by @erindiel. 8ab3ceb adds color picking logic based on https://github.com/ome/omero-renderer/blob/master/src/main/java/omeis/providers/re/ColorsFactory.java. |
In my opinion if we want this to be usable it has to mirror what OMERO would do for default rendering settings exactly. There's probably a discussion with the wider OME-NGFF specification team as to what attributes are explicitly required and which ones are optional but I would drop the following root attributes:
Dropping
The "rules" for how the default rendering settings are populated are loosely defined and have remained pretty static for over 10 years. They are located in
It's going to be very hard to bring this code in without pulling in the OMERO server dependency tree so I would propose we continue with the strategy you've started @melissalinkert: replicate the decisions here in bioformats2raw and add test cases for them. |
...and add more tests.
I think 6693198 addresses all of the open comments here, but if any remaining discrepancies turn up during review they should be easy enough to fix. |
In terms of spec changes, we'll likely want to keep an eye on ome/ngff#78 and update in a future PR once that's finalized. |
The answer might be partial but at least based on the implementation in the OMERO.py gateway:
Taking this image which was exported as OME-NGFF (https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr) as an example
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One suggestion to store the name
at the multiscales level
should OMERO rendering metadata be on by default (better for NGFF imports into OMERO), or off by default (faster for everyone else, consistent with existing behavior)?
Where does the performance hit come from? Assuming we manage to get similar performance metrics, my opinion is that storing this additional metadata in the converted output should become the default. Consumers can then choose whether they use it or not
what should the OMERO id be? it's 0 here, but should it be omitted or user-configurable instead?
I also support not writing omero.id
. In an OMERO export workflow, this can be used to capture some provenance metadata with the ID of the source object ID but that does not apply here.
If some form of identifier was valuable, we might want to look into the uuid proposal
src/main/java/com/glencoesoftware/bioformats2raw/Converter.java
Outdated
Show resolved
Hide resolved
The expected performance hit comes from min/max calculation. While we're reading every tile no matter what, actually unpacking each pixel only happens if min/max calculation is performed, which is only when OMERO metadata is being set. I haven't done any concrete benchmarking there yet, but would be surprised if there isn't a noticeable difference. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor naming thought
src/main/java/com/glencoesoftware/bioformats2raw/Converter.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested the execution of time ./bin/bioformats2raw --omero
vs time ./bin/bioformats2raw --no-omero
for a few modalities from the HEAD of this branch.
Using a sample BBBC017 plate:
./bioformats2raw-0.5.0-SNAPSHOT/bin/bioformats2raw --omero 1922.56s user 2022.15s system 152% cpu 43:09.93 total
./bioformats2raw-0.5.0-SNAPSHOT/bin/bioformats2raw --no-omero 1256.84s user 1576.65s system 195% cpu 24:12.64 total
and the diff between
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/.zattrs no_omero/NIRHTa+001.ome.zarr/.zattrs
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/A/1/.zattrs no_omero/NIRHTa+001.ome.zarr/A/1/.zattrs
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/A/1/0/.zattrs no_omero/NIRHTa+001.ome.zarr/A/1/0/.zattrs
38,85c38
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : "Infinity",
< "max" : "-Infinity",
< "start" : "Infinity",
< "end" : "-Infinity"
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : "Infinity",
< "max" : "-Infinity",
< "start" : "Infinity",
< "end" : "-Infinity"
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : 154.0,
< "max" : 3396.0,
< "start" : 154.0,
< "end" : 3396.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
./bioformats2raw-0.5.0-SNAPSHOT/bin/bioformats2raw --omero 194.89s user 15.59s system 405% cpu 51.870 total
./bioformats2raw-0.5.0-SNAPSHOT/bin/bioformats2raw --no-omero 149.65s user 15.37s system 409% cpu 40.306 total
and
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/LuCa-7color_Scan1.ome.zarr/.zattrs no_omero/LuCa-7color_Scan1.ome.zarr/.zattrs
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/LuCa-7color_Scan1.ome.zarr/0/.zattrs no_omero/LuCa-7color_Scan1.ome.zarr/0/.zattrs
82,155c82
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "DAPI",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "FITC",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FFFF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "CY3",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF8000",
< "coefficient" : 1,
< "active" : false,
< "label" : "Texas Red",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : false,
< "label" : "CY5",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
- using Leica-2.ome.tiff
./bin/bioformats2raw --omero 559.48s user 151.70s system 395% cpu 2:59.84 total
./bin/bioformats2raw --no-omero 475.75s user 147.99s system 402% cpu 2:34.92 total
and
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/Leica-2.ome.zarr/.zattrs no_omero/Leica-2.ome.zarr/.zattrs
(base) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/Leica-2.ome.zarr/0/.zattrs no_omero/Leica-2.ome.zarr/0/.zattrs
64,111c64
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : null,
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
Based on these measurements, the additional overhead due to the bytes unpacking can add an extra 50% on the total conversion time.
In terms of metadata, we should address the writing of "label" : null
and infinite rendering window. I assume the former is simply an extra check of the channel name. I am unsure of where the infinite values come from.
I think getting rid of @kkoz mentioned seeing |
The "known" values from MinMaxCalculator need to be used instead of the "global" values. The "global" values will be null if a MinMaxCalculator instance did not read every plane in the current series. This is pretty much guaranteed to be the case when there are multiple workers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-executed the tests described in #160 (review). The conversion time and the overhead due to the min/max computation was comparable in all cases except for the plate sample where the conversion time is largely identical with/without min/max calculation 👍
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --omero ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff ome-ngff/omero/NIRHTa+001.ome.zarr
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/Users/sbesson/Documents/GitHub/bioformats2raw/bioformats2raw-0.5.0-SNAPSHOT/lib/kryo-4.0.2.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
bioformats2raw --omero ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff 1289.86s user 1574.75s system 200% cpu 23:51.66 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-omero ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff ome-ngff/no_omero/NIRHTa+001.ome.zarr
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/Users/sbesson/Documents/GitHub/bioformats2raw/bioformats2raw-0.5.0-SNAPSHOT/lib/kryo-4.0.2.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
bioformats2raw --no-omero ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff 1240.77s user 1569.51s system 192% cpu 24:17.87 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --omero ome-tiff/public/2016-06/sub-resolutions/Brightfield/Leica-2/Leica-2.ome.tiff ome-ngff/omero/Leica-2.ome.zarr
bioformats2raw --omero ome-ngff/omero/Leica-2.ome.zarr 629.34s user 171.40s system 397% cpu 3:21.46 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-omero ome-tiff/public/2016-06/sub-resolutions/Brightfield/Leica-2/Leica-2.ome.tiff ome-ngff/no_omero/Leica-2.ome.zarr
bioformats2raw --no-omero ome-ngff/no_omero/Leica-2.ome.zarr 534.91s user 178.80s system 399% cpu 2:58.43 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --omero ome-tiff/public/2016-06/sub-resolutions/Fluorescence/LuCa-7color_Scan1.ome.tiff ome-ngff/omero/LuCa-7color_Scan1.ome.zarr
bioformats2raw --omero ome-ngff/omero/LuCa-7color_Scan1.ome.zarr 202.83s user 18.76s system 402% cpu 55.049 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-omero ome-tiff/public/2016-06/sub-resolutions/Fluorescence/LuCa-7color_Scan1.ome.tiff ome-ngff/no_omero/LuCa-7color_Scan1.ome.zarr
bioformats2raw --no-omero ome-ngff/no_omero/LuCa-7color_Scan1.ome.zarr 153.94s user 16.39s system 411% cpu 41.394 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % rm -rf ome-ngff/no_omero/NIRHTa+001.ome.zarr
Looking at the metadata differences, there is no longer null
of +/- Infinity
values and the new rendering window all look sensible. The label
field are set to Channel xxx
by default which is the expectation of the population code:
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/.zattrs no_omero/NIRHTa+001.ome.zarr/.zattrs
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/A/1/.zattrs no_omero/NIRHTa+001.ome.zarr/A/1/.zattrs
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/NIRHTa+001.ome.zarr/A/1/0/.zattrs no_omero/NIRHTa+001.ome.zarr/A/1/0/.zattrs
38,85c38
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 0",
< "window" : {
< "min" : 163.0,
< "max" : 4095.0,
< "start" : 163.0,
< "end" : 4095.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 1",
< "window" : {
< "min" : 104.0,
< "max" : 3563.0,
< "start" : 104.0,
< "end" : 3563.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 2",
< "window" : {
< "min" : 154.0,
< "max" : 3396.0,
< "start" : 154.0,
< "end" : 3396.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff %
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % ls
no_omero omero
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % dif
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/Leica-2.ome.zarr/0/.zattrs no_omero/Leica-2.ome.zarr/0/.zattrs
64,111c64
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 0",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 1",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 2",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/LuCa-7color_Scan1.ome.zarr/.zattrs no_omero/LuCa-7color_Scan1.ome.zarr/.zattrs
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff omero/LuCa-7color_Scan1.ome.zarr/0/.zattrs no_omero/LuCa-7color_Scan1.ome.zarr/0/.zattrs
82,155c82
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "DAPI",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "FITC",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FFFF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "CY3",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF8000",
< "coefficient" : 1,
< "active" : false,
< "label" : "Texas Red",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : false,
< "label" : "CY5",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
The only outstanding issue is the fact channel names do not seem to be generated from the emission wavelength in my environment - see inline comment about test failure
* @param c channel index | ||
* @return channel color | ||
*/ | ||
public static Color getColor(OMEXMLMetadata meta, int series, int c) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside the scope of this PR, assuming this is the same logic as the one implemented in the server components, it would make sense to capture the migration of this logic to Bio-Formats e.g. as a FormatTools
helper or similar. If a new Bio-Formats release included this backwards-compatible API addition, downstream components could be updated to consume it.
e444287 fixes the test failure I was encountering previously. I will carry out a final round of testing of this PR tomorrow morning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-minmax ome-tiff/public/2016-06/sub-resolutions/Brightfield/Leica-2/Leica-2.ome.tiff ome-ngff/no_minmax/Leica-2.ome.zarr
bioformats2raw --no-minmax ome-ngff/no_minmax/Leica-2.ome.zarr 478.98s user 165.74s system 399% cpu 2:41.25 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --minmax ome-tiff/public/2016-06/sub-resolutions/Brightfield/Leica-2/Leica-2.ome.tiff ome-ngff/minmax/Leica-2.ome.zarr
bioformats2raw --minmax ome-ngff/minmax/Leica-2.ome.zarr 580.50s user 153.07s system 402% cpu 3:02.11 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-minmax ome-tiff/public/2016-06/sub-resolutions/Fluorescence/LuCa-7color_Scan1.ome.tiff ome-ngff/no_minmax/LuCa-7color_Scan1.ome.zarr
bioformats2raw --no-minmax ome-ngff/no_minmax/LuCa-7color_Scan1.ome.zarr 158.91s user 16.94s system 397% cpu 44.194 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --minmax ome-tiff/public/2016-06/sub-resolutions/Fluorescence/LuCa-7color_Scan1.ome.tiff ome-ngff/minmax/LuCa-7color_Scan1.ome.zarr
bioformats2raw --minmax ome-ngff/minmax/LuCa-7color_Scan1.ome.zarr 188.75s user 14.79s system 408% cpu 49.829 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --no-minmax ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff ome-ngff/no_minmax/NIRHTa+001.ome.zar
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/Users/sbesson/Documents/GitHub/bioformats2raw/bioformats2raw-0.5.0-SNAPSHOT/lib/kryo-4.0.2.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
bioformats2raw --no-minmax ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff 1245.54s user 1524.63s system 195% cpu 23:34.38 total
(java_dev) sbesson@Sebastiens-MacBook-Pro-2 curated % time bioformats2raw --minmax ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff ome-ngff/minmax/NIRHTa+001.ome.zar
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/Users/sbesson/Documents/GitHub/bioformats2raw/bioformats2raw-0.5.0-SNAPSHOT/lib/kryo-4.0.2.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
bioformats2raw --minmax ome-tiff/BBBC017/single-file/NIRHTa+001.ome.tiff 1245.07s user 1488.08s system 196% cpu 23:12.90 total
and
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/NIRHTa+001.ome.zar/.zattrs no_minmax/NIRHTa+001.ome.zar/.zattrs
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/NIRHTa+001.ome.zar/A/1/.zattrs no_minmax/NIRHTa+001.ome.zar/A/1/.zattrs
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/NIRHTa+001.ome.zar/A/1/0/.zattrs no_minmax/NIRHTa+001.ome.zar/A/1/0/.zattrs
38,85c38
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 0",
< "window" : {
< "min" : 163.0,
< "max" : 4095.0,
< "start" : 163.0,
< "end" : 4095.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 1",
< "window" : {
< "min" : 104.0,
< "max" : 3563.0,
< "start" : 104.0,
< "end" : 3563.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 2",
< "window" : {
< "min" : 154.0,
< "max" : 3396.0,
< "start" : 154.0,
< "end" : 3396.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/LuCa-7color_Scan1.ome.zarr/.zattrs no_minmax/LuCa-7color_Scan1.ome.zarr/.zattrs
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/LuCa-7color_Scan1.ome.zarr/0/.zattrs no_minmax/LuCa-7color_Scan1.ome.zarr/0/.zattrs
82,155c82
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "DAPI",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "FITC",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FFFF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "CY3",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF8000",
< "coefficient" : 1,
< "active" : false,
< "label" : "Texas Red",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : false,
< "label" : "CY5",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/Leica-2.ome.zarr/.zattrs no_minmax/Leica-2.ome.zarr/.zattrs
(aws) sbesson@Sebastiens-MacBook-Pro-2 ome-ngff % diff minmax/Leica-2.ome.zarr/0/.zattrs no_minmax/Leica-2.ome.zarr/0/.zattrs
64,111c64
< } ],
< "omero" : {
< "channels" : [ {
< "color" : "FF0000",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 0",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "00FF00",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 1",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< }, {
< "color" : "0000FF",
< "coefficient" : 1,
< "active" : true,
< "label" : "Channel 2",
< "window" : {
< "min" : 0.0,
< "max" : 255.0,
< "start" : 0.0,
< "end" : 255.0
< },
< "family" : "linear",
< "inverted" : false
< } ],
< "rdefs" : {
< "defaultT" : 0,
< "model" : "color",
< "defaultZ" : 0
< }
< }
---
> } ]
Overall:
- the new unit tests are now reliably passing
- 👍 for allowing a codepath allowing to compute this metadata and store it in the most appropriate location as defined by the current OME-NGFF spec. Obviously, this might need to be revisited as the rendering specification evolves - see the draft proposal
- the min/max computation overhead now feels very reasonable so having the min/max as the default should be acceptable
- the code also ports some of the channel name population logic from OMERO when the metadata is missing from the Channel.Name
The only notable difference with the OMERO channel name code is that this logic falls back to using Channel <index>
as the default while in OMERO, RGB images currently are labelled as 0
, 1
, 2
. I am happy to see this merged in its current form but it would make sense to review the impact of this particular decision in the context of a full conversion+import pipeline.
In addition to the metrics above which are reporting computation time, I minimally tested that the metadata written by the default When using an OME-NGFF dataset created with When using an OME-NGFF dataset created with For reference, this is the viewport of the source OME-TIFF image imported into OMERO with the default settings: |
Note: decision was made at the Formats meeting today to additionally add "transitional" to the |
…to omero-metadata
This includes introducing min/max calculation so that the channel min/max
values are written in each group. See https://ngff.openmicroscopy.org/latest/#omero-md
The
--no-omero
option turns off OMERO metadata population, which also turnsoff min/max calculation.
I wouldn't expect this to be merged as-is, it's just a place to start. A few things that definitely need other opinions:
active
set? is this user-configurable?id
be? it's 0 here, but should it be omitted or user-configurable instead?Color
was set on eachChannel
?start
/end
andmin
/max
in thewindow
?Once we're happy with how this works, I'll add tests before merging.