Skip to content

Commit 53ec195

Browse files
First try at scale transforms
See ome/ngff#57
1 parent 8f430e2 commit 53ec195

File tree

2 files changed

+114
-16
lines changed

2 files changed

+114
-16
lines changed

src/main/java/com/glencoesoftware/bioformats2raw/Converter.java

+76-16
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.nio.file.Path;
2020
import java.nio.file.Paths;
2121
import java.util.ArrayList;
22-
import java.util.Collections;
2322
import java.util.Comparator;
2423
import java.util.HashMap;
2524
import java.util.List;
@@ -56,6 +55,7 @@
5655
import loci.formats.ome.OMEXMLMetadata;
5756
import loci.formats.services.OMEXMLService;
5857
import loci.formats.services.OMEXMLServiceImpl;
58+
import ome.units.quantity.Quantity;
5959
import ome.xml.meta.OMEXMLMetadataRoot;
6060
import ome.xml.model.enums.DimensionOrder;
6161
import ome.xml.model.enums.EnumerationException;
@@ -1506,33 +1506,63 @@ private void setSeriesLevelMetadata(int series, int resolutions)
15061506
multiscale.put("metadata", metadata);
15071507
multiscale.put("version", nested ? "0.2" : "0.1");
15081508
multiscales.add(multiscale);
1509-
List<Map<String, String>> datasets = new ArrayList<Map<String, String>>();
1509+
1510+
IFormatReader v = null;
1511+
IMetadata meta = null;
1512+
String axisOrder = null;
1513+
try {
1514+
v = readers.take();
1515+
meta = (IMetadata) v.getMetadataStore();
1516+
1517+
if (dimensionOrder != null) {
1518+
axisOrder = dimensionOrder.toString();
1519+
}
1520+
else {
1521+
axisOrder = v.getDimensionOrder();
1522+
}
1523+
}
1524+
finally {
1525+
readers.put(v);
1526+
}
1527+
1528+
List<Map<String, Object>> datasets = new ArrayList<Map<String, Object>>();
15101529
for (int r = 0; r < resolutions; r++) {
15111530
resolutionString = String.format(
15121531
scaleFormatString, getScaleFormatStringArgs(series, r));
15131532
String lastPath = resolutionString.substring(
15141533
resolutionString.lastIndexOf('/') + 1);
1515-
datasets.add(Collections.singletonMap("path", lastPath));
1516-
}
1517-
multiscale.put("datasets", datasets);
15181534

1519-
String axisOrder = null;
1520-
if (dimensionOrder != null) {
1521-
axisOrder = dimensionOrder.toString();
1522-
}
1523-
else {
1524-
IFormatReader reader = readers.take();
1525-
try {
1526-
axisOrder = reader.getDimensionOrder();
1527-
}
1528-
finally {
1529-
readers.put(reader);
1535+
List<Map<String, Object>> transforms =
1536+
new ArrayList<Map<String, Object>>();
1537+
Map<String, Object> scale = new HashMap<String, Object>();
1538+
scale.put("type", "scale");
1539+
List<Double> axisValues = new ArrayList<Double>();
1540+
List<Integer> axisIndices = new ArrayList<Integer>();
1541+
for (int i=axisOrder.length()-1; i>=0; i--) {
1542+
Quantity axisScale = getScale(meta, series, axisOrder, i);
1543+
if (axisScale != null) {
1544+
// TODO: does this need to be recalculated for r > 0?
1545+
axisValues.add(axisScale.value().doubleValue());
1546+
axisIndices.add(axisOrder.length() - i - 1);
1547+
}
15301548
}
1549+
scale.put("scale", axisValues);
1550+
scale.put("axisIndices", axisIndices);
1551+
1552+
transforms.add(scale);
1553+
1554+
Map<String, Object> dataset = new HashMap<String, Object>();
1555+
dataset.put("path", lastPath);
1556+
dataset.put("transformations", transforms);
1557+
datasets.add(dataset);
15311558
}
1559+
multiscale.put("datasets", datasets);
1560+
15321561
List<Map<String, String>> axes = new ArrayList<Map<String, String>>();
15331562
for (int i=axisOrder.length()-1; i>=0; i--) {
15341563
String axis = axisOrder.substring(i, i + 1).toLowerCase();
15351564
String type = "space";
1565+
Quantity scale = getScale(meta, series, axisOrder, i);
15361566
if (axis.equals("t")) {
15371567
type = "time";
15381568
}
@@ -1542,6 +1572,9 @@ else if (axis.equals("c")) {
15421572
Map<String, String> thisAxis = new HashMap<String, String>();
15431573
thisAxis.put("name", axis);
15441574
thisAxis.put("type", type);
1575+
if (scale != null) {
1576+
thisAxis.put("unit", scale.unit().getSymbol());
1577+
}
15451578
axes.add(thisAxis);
15461579
}
15471580
multiscale.put("axes", axes);
@@ -1555,6 +1588,33 @@ else if (axis.equals("c")) {
15551588
LOGGER.debug(" finished writing subgroup attributes");
15561589
}
15571590

1591+
private Quantity getScale(
1592+
IMetadata meta, int series, String axisOrder, int axis)
1593+
{
1594+
if (meta == null) {
1595+
return null;
1596+
}
1597+
int seriesIndex = seriesList.indexOf(series);
1598+
1599+
if (seriesIndex < 0 || seriesIndex >= meta.getImageCount()) {
1600+
return null;
1601+
}
1602+
1603+
String axisChar = axisOrder.substring(axis, axis + 1).toLowerCase();
1604+
switch (axisChar.charAt(0)) {
1605+
case 'x':
1606+
return meta.getPixelsPhysicalSizeX(seriesIndex);
1607+
case 'y':
1608+
return meta.getPixelsPhysicalSizeY(seriesIndex);
1609+
case 'z':
1610+
return meta.getPixelsPhysicalSizeZ(seriesIndex);
1611+
case 't':
1612+
return meta.getPixelsTimeIncrement(seriesIndex);
1613+
default:
1614+
return null;
1615+
}
1616+
}
1617+
15581618
/**
15591619
* Takes exception from asynchronous execution and re-throw known exception
15601620
* types. If the end is reached with no known exception detected, either the

src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java

+38
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,44 @@ public void testSetOriginalDimensionOrder() throws Exception {
320320
checkAxes(axes, "TZCYX");
321321
}
322322

323+
/**
324+
* Test that physical sizes are saved in axes/transformations metadata.
325+
*/
326+
@Test
327+
public void testPhysicalSizes() throws Exception {
328+
input = fake("physicalSizeX", "1.0mm",
329+
"physicalSizeY", "0.5mm",
330+
"physicalSizeZ", "2cm");
331+
assertTool();
332+
333+
ZarrGroup z = ZarrGroup.open(output.resolve("0").toString());
334+
List<Map<String, Object>> multiscales = (List<Map<String, Object>>)
335+
z.getAttributes().get("multiscales");
336+
assertEquals(1, multiscales.size());
337+
Map<String, Object> multiscale = multiscales.get(0);
338+
List<Map<String, Object>> axes =
339+
(List<Map<String, Object>>) multiscale.get("axes");
340+
checkAxes(axes, "TCZYX");
341+
342+
List<Map<String, Object>> datasets =
343+
(List<Map<String, Object>>) multiscale.get("datasets");
344+
assertEquals(2, datasets.size());
345+
346+
for (Map<String, Object> dataset : datasets) {
347+
List<Map<String, Object>> transforms =
348+
(List<Map<String, Object>>) dataset.get("transformations");
349+
assertEquals(1, transforms.size());
350+
Map<String, Object> scale = transforms.get(0);
351+
assertEquals("scale", scale.get("type"));
352+
List<Integer> axisIndices = (List<Integer>) scale.get("axisIndices");
353+
List<Double> axisValues = (List<Double>) scale.get("scale");
354+
355+
assertEquals(axisIndices.size(), axisValues.size());
356+
assertEquals(axisIndices, Arrays.asList(new Integer[] {2, 3, 4}));
357+
assertEquals(axisValues, Arrays.asList(new Double[] {2.0, 0.5, 1.0}));
358+
}
359+
}
360+
323361
/**
324362
* Test using a different tile size from the default (1024).
325363
*/

0 commit comments

Comments
 (0)