Conversation
Support different axes order and <5d zarrs
| Path output = tmpDir.getRoot().toPath().resolve("output.zarr"); | ||
| assertBioFormats2Raw(input, output); | ||
| if (order != null) { | ||
| assertBioFormats2Raw(input, output, "--dimension-order", order); |
There was a problem hiding this comment.
we probably need to review that strategy
Remove usage of bioformats order argument
|
As a confirmation of the ground truth, I generated a series of test files of various dimensionality using glencoesoftware/bioformats2raw#279 and ome/bioformats#4339 As expected, importing these Zarr datasets into OMERO (Plus) with
|
sbesson
left a comment
There was a problem hiding this comment.
With a build of omero-zarr-pixel-buffer including this PR deployed in OMERO.server (lib/server) as well as the image-region micro-service, all test images imported above now render as expected for all axes variants
In addition, tested the conversion and import of a couple of Zarr datasets generated from real-world examples across different modalities, already used in previous testing
- 384 wells plate (9 fields of view) https://downloads.openmicroscopy.org/images/Cellomics/BBBC017/
- brightfield whole slide image https://downloads.openmicroscopy.org/images/Leica-SCN/openslide/
- fluorescence whole slide image https://downloads.openmicroscopy.org/images/Vectra-QPTIFF/perkinelmer/
- fluorescence 3D image with segmentation https://ftp.ebi.ac.uk/pub/databases/IDR/idr0079-hartmann-lateralline/20200220-ftp/experimentB/03887B26C1/
Zarr datasets were generated with and without --compact and imported into OMERO. The tile loading is consistent between the 5D and reduced dimensionality representation for all samples
Additionally, the 5D and 3D label images both render consistently
From a functional perspective, everything works as expected. The latest version of the code addresses some of the feedback raised in #19 but I'll leave @kkoz @melissalinkert who also has some knowledge of this code to run a round of code review.
From the testing perspective, since #19 (review), @melissalinkert has opened 2 contributions (mentioned previously as glencoesoftware/bioformats2raw#279 and ome/bioformats#4339) to generate sample Zarr datasets of reduced dimensionalities via bioformats2raw which can also be used for unit test. My impression is that this approach covers most of the logic of the TestZarr. Consuming it will require a Bio-Formats and bioformats2raw release. Depending on the timeline, we could integrate this as it is and capture the refactoring of the tests as a follow-up issue to consume the new functionalities?
| } | ||
| if (axesOrder.containsKey(Axis.Z)) { | ||
| offset[axesOrder.get(Axis.Z)] = z; | ||
| } |
There was a problem hiding this comment.
Might be worth condensing lines 566-589, so that for each of the 3 axes there is something like:
if (axesOrder.containsKey(Axis.T)) {
int tIndex = axesOrder.get(Axis.T);
shape[tIndex] = 1;
offset[tIndex] = t;
}
That would reduce the number of axesOrder.containsKey and axesOrder.get calls, which at least can't hurt tile read performance.
| } | ||
| if (axesOrder.containsKey(Axis.Z)) { | ||
| offset[axesOrder.get(Axis.Z)] = z; | ||
| } |
There was a problem hiding this comment.
As above, this could be condensed to a single containsKey(...) check for each axis.
| } | ||
| if (axesOrder.containsKey(Axis.Z)) { | ||
| offset[axesOrder.get(Axis.Z)] = z; | ||
| } |
There was a problem hiding this comment.
Same here as for lines 566-589 and 693-715.
| public TestZarr createImage() throws IOException, InvalidRangeException { | ||
| for (int c = 0; c <= sizeC; c++) { | ||
| if (c == sizeC && sizeC > 0) | ||
| break; |
There was a problem hiding this comment.
Is the idea here to execute once if sizeC is 0, and up to sizeC - 1 otherwise? If so, that might be easier to follow by removing lines 179-180, and using something like this on line 178:
for (int c = 0; c < Math.max(1, sizeC); c++)
| break; | ||
| for (int t = 0; t <= sizeT; t++) { | ||
| if (t == sizeT && sizeT > 0) | ||
| break; |
There was a problem hiding this comment.
Same question as on in the loop over sizeC.
| break; | ||
| for (int z = 0; z <= sizeZ; z++) { | ||
| if (z == sizeZ && sizeZ > 0) | ||
| break; |
There was a problem hiding this comment.
...and same question as for sizeC and sizeT above.
| int fontSize = Math.min(sizeX, sizeY) / 20; // Scale font size based on image dimensions | ||
| g2d.setFont(new Font("Arial", Font.BOLD, fontSize)); | ||
|
|
||
| String planeText = text.replace("<C>", String.valueOf(c)).replace("<T>", String.valueOf(t)).replace("<Z>", String.valueOf(z)); |
There was a problem hiding this comment.
If text were Channel %s, Timepoint %s, Z-plane %s, then this line could be simplified to something like String planeText = String.format(text, c, t, z).
| offset[axesOrder.get(Axis.Z)] = zIndexMap.get(originalZIndex); | ||
| planes = shape[axesOrder.get(Axis.Z)]; | ||
| shape[axesOrder.get(Axis.Z)] = 1; |
There was a problem hiding this comment.
Since these require axesOrder to contain Axis.Z, should they be inside the conditional above?
| * Retrieves the axes metadata of the first multiscale | ||
| * @return See above. | ||
| */ | ||
| public Map<Axis, Integer> getAxesOrder() { |
There was a problem hiding this comment.
I feel like this should either be setAxesOrder and set the member variable from the zarr, or it should check to see if the value has been set and just return axesOrder if it has.
| order.put(Axis.Y, 3); | ||
| order.put(Axis.X, 4); | ||
| } else { | ||
| for (int i=0; i<axesData.size(); i++) { |
There was a problem hiding this comment.
For formatting, do we want spaces between the values and operators here?
There was a problem hiding this comment.
@kkoz should we review whether/how to enforce formatting on this repository as a follow up of this work?
My feeling is that if we go down this route, we should encode the decisions under the form of checkstyle constraints similarly to https://github.com/glencoesoftware/bioformats2raw/blob/97f8a26dd120d854d3e03ab70f1c481b524ff025/config/checkstyle/checkstyle.xml and let Gradle lint the code as part of the build.
There was a problem hiding this comment.
I agree. I was under the impression that there was already an OME style somewhere, but after poking around a bit I couldn't find it. Automatically applying consistent formatting in all repos would definitely be a plus.
There was a problem hiding this comment.
https://ome-contributing.readthedocs.io/en/latest/code-contributions.html would be the most generic guidelines and Bio-Formats has some additional instructions https://bio-formats.readthedocs.io/en/latest/developers/code-formatting.html
For OMERO, there are no written guidelines but https://github.com/ome/openmicroscopy/tree/develop/docs/styles will contain the historical style definition.
| // if no Z downsampling, this is just an identity map | ||
| int fullResZ = fullResolutionArray.getShape()[axesOrder.get(Axis.Z)]; | ||
| int arrayZ = array.getShape()[axesOrder.get(Axis.Z)]; | ||
| for (int z=0; z<fullResZ; z++) { |
There was a problem hiding this comment.
That's true, I've not set any particular formatting style in my IDE, sorry. Happy to use the bioformats2raw one directly!
|
Addressed @kkoz suggestions. Reformatting to the bioformats2raw style rules would introduce a huge amount of changes, make review of this PR impossible. Probably better done in follow-up? |
|
Agreed, let's separate the formatting discussion. On this front, one of the major divergences between the Bio-Formats codebase (incl. bioformats2raw) and the OMERO codebases is the 2 spaces vs 4 spaces indentations. The value of unifying everything to one style would quickly become neglectable compared to the impact of rewriting almost every line ... I would propose to start by reviewing the set of existing and expected rules for each component and try to identify a sensible overlap that we can enforce |
melissalinkert
left a comment
There was a problem hiding this comment.
Minor comment aside, it looks like a couple of the review comments from @kkoz were missed as they were separate from the formatting discussion.
| break; | ||
| for (int c = 0; c <= sizeC; c++) { | ||
| if (c == sizeC && sizeC > 0) | ||
| break; |
There was a problem hiding this comment.
As in TestZarr lines 178-180, this would be easier to follow if using something like for (int t = 0; t < Math.max(sizeT, 1); t++).
sbesson
left a comment
There was a problem hiding this comment.
Retested the last commit against a set of images with XY, XYC, XYZ, XYT, XYZC, XYZT, XYZCT as well as XYZCT dimensions as well as labels with XY, XYC and ZYXCT dimensions. Images and labels are imported correctly with the thumbnails generated and the binary data is correctly read by the viewers.
@melissalinkert and @kkoz can you take a look at the code changes addressing your feedback?

This PR adds support for different axes order and zarrs with less than 5 dimensions.
(Replaces #19)