diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index 53f05ca..7e556dc 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -665,6 +665,39 @@ public void convert() scaleFormatString = "%s/%s/%d/%d"; } + // fileset level metadata + if (!noRootGroup) { + final ZarrGroup root = ZarrGroup.create(getRootPath()); + Map attributes = new HashMap(); + attributes.put("bioformats2raw.layout", LAYOUT); + + root.writeAttributes(attributes); + } + if (!noOMEMeta) { + Path metadataPath = getRootPath().resolve("OME"); + final ZarrGroup root = ZarrGroup.create(metadataPath); + Map attributes = new HashMap(); + + // record the path to each series (multiscales) and the corresponding + // series (OME-XML Image) index + // using the index as the key would mean that the index is stored + // as a string instead of an integer + List groups = new ArrayList(); + for (Integer index : seriesList) { + String resolutionString = String.format( + scaleFormatString, getScaleFormatStringArgs(index, 0)); + String seriesString = ""; + if (resolutionString.indexOf('/') >= 0) { + seriesString = resolutionString.substring(0, + resolutionString.lastIndexOf('/')); + } + groups.add(seriesString); + } + attributes.put("series", groups); + + root.writeAttributes(attributes); + } + for (Integer index : seriesList) { try { write(index); @@ -1215,14 +1248,6 @@ public void saveResolutions(int series) sizeX, tileWidth, sizeY, tileHeight, sizeZ, chunkDepth, imageCount ); - // fileset level metadata - if (!noRootGroup) { - final ZarrGroup root = ZarrGroup.create(getRootPath()); - Map attributes = new HashMap(); - attributes.put("bioformats2raw.layout", LAYOUT); - root.writeAttributes(attributes); - } - // series level metadata setSeriesLevelMetadata(series, resolutions); diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 437f3d5..33a179b 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -210,6 +210,13 @@ public void testAdditionalScaleFormatStringArgs() throws Exception { series0.openArray("0"); series0 = ZarrGroup.open(output.resolve("ghi/999/1").toString()); series0.openArray("0"); + + Path omePath = output.resolve("OME"); + ZarrGroup z = ZarrGroup.open(omePath.toString()); + List groupMap = (List) z.getAttributes().get("series"); + assertEquals(groupMap.size(), 2); + assertEquals(groupMap.get(0), "abc/888/0"); + assertEquals(groupMap.get(1), "ghi/999/1"); } /** @@ -240,6 +247,14 @@ public void testDefaultLayoutIsSetAndIsNested() throws Exception { ZarrGroup z = ZarrGroup.open(output.toString()); Integer layout = (Integer) z.getAttributes().get("bioformats2raw.layout"); + + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 1); + assertEquals(groupMap.get(0), "0"); + ZarrArray series0 = ZarrGroup.open(output.resolve("0")).openArray("0"); // no getter for DimensionSeparator in ZarrArray @@ -428,6 +443,14 @@ public void testMultiSeries() throws Exception { assertTool(); ZarrGroup z = ZarrGroup.open(output.toString()); + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 2); + assertEquals(groupMap.get(0), "0"); + assertEquals(groupMap.get(1), "1"); + // Check series 0 dimensions and special pixels ZarrArray series0 = z.openArray("0/0"); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); @@ -462,6 +485,16 @@ public void testSingleBeginningSeries() throws Exception { assertTool("-s", "0"); ZarrGroup z = ZarrGroup.open(output.toString()); + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 1); + assertEquals(groupMap.get(0), "0"); + + OME ome = getOMEMetadata(); + assertEquals(1, ome.sizeOfImageList()); + // Check series 0 dimensions and special pixels ZarrArray series0 = z.openArray("0/0"); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); @@ -489,6 +522,16 @@ public void testSingleEndSeries() throws Exception { assertTool("-s", "1"); ZarrGroup z = ZarrGroup.open(output.toString()); + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 1); + assertEquals(groupMap.get(0), "0"); + + OME ome = getOMEMetadata(); + assertEquals(1, ome.sizeOfImageList()); + // Check series 1 dimensions and special pixels ZarrArray series0 = z.openArray("0/0"); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); @@ -516,6 +559,16 @@ public void testSingleMiddleSeries() throws Exception { assertTool("-s", "1"); ZarrGroup z = ZarrGroup.open(output.toString()); + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 1); + assertEquals(groupMap.get(0), "0"); + + OME ome = getOMEMetadata(); + assertEquals(1, ome.sizeOfImageList()); + // Check series 1 dimensions and special pixels ZarrArray series0 = z.openArray("0/0"); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); @@ -912,11 +965,21 @@ public void testNoHCSOption() throws Exception { ZarrGroup z = ZarrGroup.open(output); + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 12); + for (int i=0; i<12; i++) { + assertEquals(groupMap.get(i), String.valueOf(i)); + } + // Check dimensions and block size ZarrArray series0 = z.openArray("0/0"); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getChunks()); - assertEquals(12, z.getGroupKeys().size()); + // 12 series + OME group + assertEquals(13, z.getGroupKeys().size()); // Check OME metadata OME ome = getOMEMetadata(); @@ -952,6 +1015,22 @@ public void testHCSMetadata() throws Exception { int rowCount = 2; int colCount = 3; int fieldCount = 2; + + Path omePath = output.resolve("OME"); + ZarrGroup omeGroup = ZarrGroup.open(omePath.toString()); + List groupMap = + (List) omeGroup.getAttributes().get("series"); + assertEquals(groupMap.size(), 12); + int index = 0; + for (int r=0; r> plateMap = new HashMap>(); plateMap.put("A", Arrays.asList("1", "2", "3")); plateMap.put("B", Arrays.asList("1", "2", "3")); @@ -1390,6 +1469,8 @@ public void testNoOmeMetaExportOption() throws Exception { assertTrue(!Files.exists( output.resolve("OME").resolve("METADATA.ome.xml"))); + assertTrue(!Files.exists( + output.resolve("OME").resolve(".zattrs"))); } /**