From 94ec5db18c9bd7e5e87b74081d73d9e95ed637c4 Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Tue, 24 Mar 2026 13:23:30 +0100 Subject: [PATCH 1/4] add unified getOmeroMetadata and getBioformats2rawLayout for all versions --- .../zarrjava/experimental/ome/MultiscaleImage.java | 14 ++++++++++++++ .../experimental/ome/v0_4/MultiscaleImage.java | 4 +++- .../experimental/ome/v0_5/MultiscaleImage.java | 7 +++++-- .../experimental/ome/v0_6/MultiscaleImage.java | 7 +++++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/dev/zarr/zarrjava/experimental/ome/MultiscaleImage.java b/src/main/java/dev/zarr/zarrjava/experimental/ome/MultiscaleImage.java index 3911360f..eb25d178 100644 --- a/src/main/java/dev/zarr/zarrjava/experimental/ome/MultiscaleImage.java +++ b/src/main/java/dev/zarr/zarrjava/experimental/ome/MultiscaleImage.java @@ -3,9 +3,11 @@ import dev.zarr.zarrjava.ZarrException; import dev.zarr.zarrjava.core.Node; import dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry; +import dev.zarr.zarrjava.experimental.ome.metadata.OmeroMetadata; import dev.zarr.zarrjava.store.StoreHandle; import dev.zarr.zarrjava.utils.Utils; +import javax.annotation.Nullable; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -37,6 +39,18 @@ public interface MultiscaleImage { */ int getScaleLevelCount() throws ZarrException; + /** + * Returns the OmeroMetadata if present, or null if not. + */ + @Nullable + OmeroMetadata getOmeroMetadata(); + + /** + * Returns the bioformats2raw.layout property if present, or null if not + */ + @Nullable + Integer getBioformats2rawLayout(); + /** * Returns the axis names of the first multiscale entry. */ diff --git a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_4/MultiscaleImage.java b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_4/MultiscaleImage.java index ae6095c6..9de5b16f 100644 --- a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_4/MultiscaleImage.java +++ b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_4/MultiscaleImage.java @@ -30,7 +30,7 @@ public final class MultiscaleImage extends OmeV2Group implements MultiscalesMeta @Nullable private OmeroMetadata omeroMetadata; @Nullable - private Integer bioformats2rawLayout; + private final Integer bioformats2rawLayout; private MultiscaleImage( @Nonnull StoreHandle storeHandle, @@ -83,6 +83,7 @@ public dev.zarr.zarrjava.store.StoreHandle getStoreHandle() { return this.storeHandle; } + @Override @Nullable public OmeroMetadata getOmeroMetadata() { return omeroMetadata; @@ -93,6 +94,7 @@ public void setOmeroMetadata(@Nullable OmeroMetadata omeroMetadata) throws IOExc persistAttributes(); } + @Override @Nullable public Integer getBioformats2rawLayout() { return bioformats2rawLayout; diff --git a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_5/MultiscaleImage.java b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_5/MultiscaleImage.java index 9623cf5b..3f453758 100644 --- a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_5/MultiscaleImage.java +++ b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_5/MultiscaleImage.java @@ -13,6 +13,7 @@ import dev.zarr.zarrjava.v3.GroupMetadata; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -68,12 +69,14 @@ public MultiscalesEntry getMultiscalesEntry(int i) throws ZarrException { return omeMetadata.multiscales.get(i); } - @javax.annotation.Nullable + @Override + @Nullable public dev.zarr.zarrjava.experimental.ome.metadata.OmeroMetadata getOmeroMetadata() { return omeMetadata.omero; } - @javax.annotation.Nullable + @Override + @Nullable public Integer getBioformats2rawLayout() { return omeMetadata.bioformats2rawLayout; } diff --git a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java index 69b2747b..327f7187 100644 --- a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java +++ b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java @@ -18,6 +18,7 @@ import dev.zarr.zarrjava.v3.GroupMetadata; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -85,12 +86,14 @@ public MultiscalesEntry getMultiscalesEntry(int i) throws ZarrException { return omeMetadata.multiscales.get(i); } - @javax.annotation.Nullable + @Override + @Nullable public dev.zarr.zarrjava.experimental.ome.metadata.OmeroMetadata getOmeroMetadata() { return omeMetadata.omero; } - @javax.annotation.Nullable + @Override + @Nullable public Integer getBioformats2rawLayout() { return omeMetadata.bioformats2rawLayout; } From 94f1f347d4c5527d9a5d64606e65201a03a47cf3 Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Tue, 24 Mar 2026 13:54:43 +0100 Subject: [PATCH 2/4] change type of consolidated_metadata to Object --- src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java b/src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java index 7d3dd85a..56414a2e 100644 --- a/src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java +++ b/src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java @@ -17,7 +17,7 @@ public final class GroupMetadata extends dev.zarr.zarrjava.core.GroupMetadata { @JsonProperty("node_type") public final String nodeType = "group"; @JsonProperty("consolidated_metadata") - public final String consolidatedMetadata = null; + public final Object consolidatedMetadata = null; @Nullable public final Attributes attributes; From a0dd6e337e6ba125140b5c83e23a9b886aa604dd Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Wed, 25 Mar 2026 13:51:50 +0100 Subject: [PATCH 3/4] improve performance on Array.read (less allocation and memory overhead) --- src/main/java/dev/zarr/zarrjava/core/Array.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/zarr/zarrjava/core/Array.java b/src/main/java/dev/zarr/zarrjava/core/Array.java index c1268900..67461483 100644 --- a/src/main/java/dev/zarr/zarrjava/core/Array.java +++ b/src/main/java/dev/zarr/zarrjava/core/Array.java @@ -396,6 +396,10 @@ public ucar.ma2.Array read(final long[] offset, final long[] shape, final boolea final ucar.ma2.Array outputArray = ucar.ma2.Array.factory(metadata.dataType().getMA2DataType(), Utils.toIntArray(shape)); + final Object parsedFillValue = metadata.parsedFillValue(); + if (parsedFillValue != null) { + MultiArrayUtils.fill(outputArray, parsedFillValue); + } Stream chunkStream = Arrays.stream(IndexingUtils.computeChunkCoords(metadata.shape, chunkShape, offset, shape)); if (parallel) { chunkStream = chunkStream.parallel(); @@ -408,17 +412,13 @@ public ucar.ma2.Array read(final long[] offset, final long[] shape, final boolea shape ); - if (chunkIsInArray(chunkCoords)) { - MultiArrayUtils.copyRegion(metadata.allocateFillValueChunk(), - chunkProjection.chunkOffset, outputArray, chunkProjection.outOffset, - chunkProjection.shape - ); - } - final String[] chunkKeys = metadata.chunkKeyEncoding().encodeChunkKey(chunkCoords); final StoreHandle chunkHandle = storeHandle.resolve(chunkKeys); if (codecPipeline.supportsPartialDecode()) { + if (!chunkHandle.exists()) { + return; + } final ucar.ma2.Array chunkArray = codecPipeline.decodePartial(chunkHandle, Utils.toLongArray(chunkProjection.chunkOffset), chunkProjection.shape); MultiArrayUtils.copyRegion(chunkArray, new int[metadata.ndim()], outputArray, From cb2bf1a975862bd2b3022fec3da1fc9e39cc4829 Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Tue, 31 Mar 2026 15:17:35 +0200 Subject: [PATCH 4/4] fix test openSceneExample1AffinePathBetweenInstruments --- .../dev/zarr/zarrjava/experimental/ome/OmeZarrSceneV06Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/dev/zarr/zarrjava/experimental/ome/OmeZarrSceneV06Test.java b/src/test/java/dev/zarr/zarrjava/experimental/ome/OmeZarrSceneV06Test.java index 6ffccbb4..5a28c5c1 100644 --- a/src/test/java/dev/zarr/zarrjava/experimental/ome/OmeZarrSceneV06Test.java +++ b/src/test/java/dev/zarr/zarrjava/experimental/ome/OmeZarrSceneV06Test.java @@ -144,7 +144,7 @@ void createAndReopenScene() throws Exception { void openSceneExample1AffinePathBetweenInstruments() throws Exception { dev.zarr.zarrjava.experimental.ome.v0_6.Scene scene = dev.zarr.zarrjava.experimental.ome.v0_6.Scene.openScene(new FilesystemStore(V06_SCENE_EXAMPLE1).resolve()); - assertEquals(Arrays.asList("sampleA_instrument1", "sampleA_instrument2"), scene.listImageNodes()); + assertEquals(new HashSet<>(Arrays.asList("sampleA_instrument1", "sampleA_instrument2")), new HashSet<>(scene.listImageNodes())); assertEquals(1, scene.getSceneMetadata().coordinateTransformations.size()); dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinateTransformation ct = scene.getSceneMetadata().coordinateTransformations.get(0);