diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index 910a6111..c62cd261 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -1199,7 +1199,6 @@ private void saveHCSMetadata(IMetadata meta) throws IOException { Map well = new HashMap(); well.put("path", wellPath); - wells.add(well); List> imageList = new ArrayList>(); @@ -1228,31 +1227,37 @@ private void saveHCSMetadata(IMetadata meta) throws IOException { int column = index.getWellColumnIndex(); int row = index.getWellRowIndex(); - boolean foundColumn = false; - for (Map colMap : columns) { - if (colMap.get("name").equals(String.valueOf(column))) { - foundColumn = true; + int columnIndex = -1; + for (int c=0; c colMap = new HashMap(); colMap.put("name", String.valueOf(column)); + columnIndex = columns.size(); columns.add(colMap); } - boolean foundRow = false; - for (Map rowMap : rows) { - if (rowMap.get("name").equals(String.valueOf(row))) { - foundRow = true; + int rowIndex = -1; + for (int r=0; r rowMap = new HashMap(); rowMap.put("name", String.valueOf(row)); + rowIndex = rows.size(); rows.add(rowMap); } + + well.put("row_index", rowIndex); + well.put("column_index", columnIndex); + wells.add(well); } maxField = (int) Math.max(maxField, index.getFieldIndex()); diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 41089f98..600250bf 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -793,31 +793,15 @@ public void testHCSMetadata() throws IOException { ZarrGroup z = ZarrGroup.open(output); - // check valid group layout - // METADATA.ome.xml, .zattrs (Plate), .zgroup (Plate) and 2 rows - assertEquals(5, Files.list(output).toArray().length); - for (int row=0; row<2; row++) { - Path rowPath = output.resolve(Integer.toString(row)); - // .zgroup (Row) and 3 columns - assertEquals(4, Files.list(rowPath).toArray().length); - for (int col=0; col<3; col++) { - Path colPath = rowPath.resolve(Integer.toString(col)); - ZarrGroup colGroup = ZarrGroup.open(colPath); - // .zattrs (Column/Image), .zgroup (Column/Image) and 2 fields - assertEquals(4, Files.list(colPath).toArray().length); - for (int field=0; field<2; field++) { - // append resolution index - ZarrArray series0 = colGroup.openArray(field + "/0"); - assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getShape()); - assertArrayEquals(new int[] {1, 1, 1, 512, 512}, series0.getChunks()); - } - } - } + int rowCount = 2; + int colCount = 3; + int fieldCount = 2; + checkPlateGroupLayout(output, rowCount, colCount, fieldCount, 512, 512); // check plate/well level metadata Map plate = (Map) z.getAttributes().get("plate"); - assertEquals(2, ((Number) plate.get("field_count")).intValue()); + assertEquals(fieldCount, ((Number) plate.get("field_count")).intValue()); List> acquisitions = (List>) plate.get("acquisitions"); @@ -831,15 +815,8 @@ public void testHCSMetadata() throws IOException { assertEquals(1, acquisitions.size()); assertEquals("0", acquisitions.get(0).get("id")); - assertEquals(2, rows.size()); - for (int row=0; row well = - (Map) wellGroup.getAttributes().get("well"); - List> images = - (List>) well.get("images"); - assertEquals(2, images.size()); - Map field1 = images.get(0); // Field 1 - assertEquals(field1.get("path"), "0"); - assertEquals(0, field1.get("acquisition")); - Map field2 = images.get(1); // Field 2 - assertEquals(field2.get("path"), "1"); - assertEquals(0, field2.get("acquisition")); + checkWell(wellGroup, fieldCount); } } } + /** + * 96 well plate with only well E6. + */ + @Test + public void testSingleWell() throws IOException { + input = getTestFile("E6-only.ome.xml"); + assertTool(); + + ZarrGroup z = ZarrGroup.open(output); + + int rowCount = 8; + int colCount = 12; + int fieldCount = 1; + + // check plate/well level metadata + Map plate = + (Map) z.getAttributes().get("plate"); + assertEquals(fieldCount, ((Number) plate.get("field_count")).intValue()); + + List> acquisitions = + (List>) plate.get("acquisitions"); + List> rows = + (List>) plate.get("rows"); + List> columns = + (List>) plate.get("columns"); + List> wells = + (List>) plate.get("wells"); + + assertEquals(1, acquisitions.size()); + assertEquals("0", acquisitions.get(0).get("id")); + + checkDimension(rows, rowCount); + checkDimension(columns, colCount); + + assertEquals(1, wells.size()); + Map well = wells.get(0); + String wellPath = (String) well.get("path"); + assertEquals("4/5", wellPath); + assertEquals(4, ((Number) well.get("row_index")).intValue()); + assertEquals(5, ((Number) well.get("column_index")).intValue()); + + // check well metadata + ZarrGroup wellGroup = ZarrGroup.open(output.resolve(wellPath)); + checkWell(wellGroup, fieldCount); + } + + /** + * 96 well plate with only wells C4 and H2. + */ + @Test + public void testTwoWells() throws IOException { + input = getTestFile("C4-H2-only.ome.xml"); + assertTool(); + + ZarrGroup z = ZarrGroup.open(output); + + int rowCount = 8; + int colCount = 12; + int fieldCount = 1; + + // check plate/well level metadata + Map plate = + (Map) z.getAttributes().get("plate"); + assertEquals(fieldCount, ((Number) plate.get("field_count")).intValue()); + + List> acquisitions = + (List>) plate.get("acquisitions"); + List> rows = + (List>) plate.get("rows"); + List> columns = + (List>) plate.get("columns"); + List> wells = + (List>) plate.get("wells"); + + assertEquals(1, acquisitions.size()); + assertEquals("0", acquisitions.get(0).get("id")); + + checkDimension(rows, rowCount); + checkDimension(columns, colCount); + + assertEquals(2, wells.size()); + Map well = wells.get(0); + String wellPath = (String) well.get("path"); + assertEquals("2/3", wellPath); + assertEquals(2, ((Number) well.get("row_index")).intValue()); + assertEquals(3, ((Number) well.get("column_index")).intValue()); + ZarrGroup wellGroup = ZarrGroup.open(output.resolve(wellPath)); + checkWell(wellGroup, fieldCount); + + well = wells.get(1); + wellPath = (String) well.get("path"); + assertEquals("7/1", wellPath); + assertEquals(7, ((Number) well.get("row_index")).intValue()); + assertEquals(1, ((Number) well.get("column_index")).intValue()); + wellGroup = ZarrGroup.open(output.resolve(wellPath)); + checkWell(wellGroup, fieldCount); + } + + /** + * 96 well plate with all wells in row F. + */ + @Test + public void testOnePlateRow() throws IOException { + input = getTestFile("row-F-only.ome.xml"); + assertTool(); + + ZarrGroup z = ZarrGroup.open(output); + + int rowCount = 8; + int colCount = 12; + int fieldCount = 1; + + // check plate/well level metadata + Map plate = + (Map) z.getAttributes().get("plate"); + assertEquals(fieldCount, ((Number) plate.get("field_count")).intValue()); + + List> acquisitions = + (List>) plate.get("acquisitions"); + List> rows = + (List>) plate.get("rows"); + List> columns = + (List>) plate.get("columns"); + List> wells = + (List>) plate.get("wells"); + + assertEquals(1, acquisitions.size()); + assertEquals("0", acquisitions.get(0).get("id")); + + checkDimension(rows, rowCount); + checkDimension(columns, colCount); + + assertEquals(colCount, wells.size()); + for (int col=0; col well = wells.get(col); + String wellPath = (String) well.get("path"); + assertEquals("5/" + col, wellPath); + assertEquals(5, ((Number) well.get("row_index")).intValue()); + assertEquals(col, ((Number) well.get("column_index")).intValue()); + ZarrGroup wellGroup = ZarrGroup.open(output.resolve(wellPath)); + checkWell(wellGroup, fieldCount); + } + } + /** * Convert an RGB image. Ensure that the Channels are correctly split. */ @@ -889,7 +1000,6 @@ public void testRGBChannelSeparator() throws Exception { assertEquals(3, pixels.sizeOfChannelList()); } - /** * Check that a root group and attributes are created and populated. */ @@ -914,4 +1024,65 @@ public void testNoRootGroupOption() throws Exception { assertTrue(!Files.exists(output.resolve(".zattrs"))); assertTrue(!Files.exists(output.resolve(".zgroup"))); } + + private void checkPlateGroupLayout(Path root, int rowCount, int colCount, + int fieldCount, int x, int y) + throws IOException + { + // check valid group layout + // METADATA.ome.xml, .zattrs (Plate), .zgroup (Plate) and rows + assertEquals(rowCount + 3, Files.list(root).toArray().length); + for (int row=0; row> dims, int dimCount) + throws IOException + { + assertEquals(dimCount, dims.size()); + for (int dim=0; dim well = + (Map) wellGroup.getAttributes().get("well"); + List> images = + (List>) well.get("images"); + assertEquals(fieldCount, images.size()); + + for (int i=0; i field = images.get(i); + assertEquals(field.get("path"), String.valueOf(i)); + assertEquals(0, field.get("acquisition")); + } + } + + private Path getTestFile(String resourceName) throws IOException { + try { + return Paths.get(this.getClass().getResource(resourceName).toURI()); + } + catch (Exception e) { + throw new IOException(e); + } + } + } diff --git a/src/test/resources/com/glencoesoftware/bioformats2raw/test/C4-H2-only.ome.xml b/src/test/resources/com/glencoesoftware/bioformats2raw/test/C4-H2-only.ome.xml new file mode 100644 index 00000000..c6dd8455 --- /dev/null +++ b/src/test/resources/com/glencoesoftware/bioformats2raw/test/C4-H2-only.ome.xml @@ -0,0 +1,26 @@ + + + +Plate 0 of 1 + + + + + + + +PlateAcquisition 0 of 1 + + + +Image Description 0 + + + +AAAAAA== + +Image Description 1 + + + +AQEBAQ== diff --git a/src/test/resources/com/glencoesoftware/bioformats2raw/test/E6-only.ome.xml b/src/test/resources/com/glencoesoftware/bioformats2raw/test/E6-only.ome.xml new file mode 100644 index 00000000..440f17d7 --- /dev/null +++ b/src/test/resources/com/glencoesoftware/bioformats2raw/test/E6-only.ome.xml @@ -0,0 +1,16 @@ + + + +Plate 0 of 1 + + + + +PlateAcquisition 0 of 1 + + +Image Description 0 + + + +AAAAAA== diff --git a/src/test/resources/com/glencoesoftware/bioformats2raw/test/row-F-only.ome.xml b/src/test/resources/com/glencoesoftware/bioformats2raw/test/row-F-only.ome.xml new file mode 100644 index 00000000..36bc1d7c --- /dev/null +++ b/src/test/resources/com/glencoesoftware/bioformats2raw/test/row-F-only.ome.xml @@ -0,0 +1,126 @@ + + + +Plate 0 of 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PlateAcquisition 0 of 1 + + + + + + + + + + + + + +Image Description 0 + + + +AAAAAA== + +Image Description 1 + + + +AQEBAQ== + +Image Description 2 + + + +AgICAg== + +Image Description 3 + + + +AwMDAw== + +Image Description 4 + + + +BAQEBA== + +Image Description 5 + + + +BQUFBQ== + +Image Description 6 + + + +BgYGBg== + +Image Description 7 + + + +BwcHBw== + +Image Description 8 + + + +CAgICA== + +Image Description 9 + + + +CQkJCQ== + +Image Description 10 + + + +CgoKCg== + +Image Description 11 + + + +CwsLCw==