Skip to content

Commit c87373f

Browse files
authored
Merge pull request qupath#1964 from Rylern/pyramidal-zarr-writer
Pyramidal zarr writer
2 parents 4f8e95f + 434fc92 commit c87373f

14 files changed

Lines changed: 2320 additions & 506 deletions

qupath-extension-bioformats/src/main/java/qupath/lib/images/writers/ome/ConvertCommand.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,7 @@ public void run() {
290290
).toArray());
291291
}
292292

293-
try (OMEZarrWriter writer = builder.build(outputFile.getAbsolutePath())) {
294-
writer.writeImage();
295-
}
293+
builder.build(outputFile.getAbsolutePath()).writeImage();
296294
}
297295
}
298296
long duration = System.currentTimeMillis() - startTime;

qupath-extension-bioformats/src/main/java/qupath/lib/images/writers/ome/zarr/OMEXMLCreator.java

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,30 @@
1414
import ome.xml.model.enums.PixelType;
1515
import ome.xml.model.primitives.Color;
1616
import ome.xml.model.primitives.PositiveInteger;
17-
import org.slf4j.Logger;
18-
import org.slf4j.LoggerFactory;
1917
import org.w3c.dom.Document;
2018
import org.w3c.dom.Element;
2119
import qupath.lib.common.ColorTools;
2220
import qupath.lib.images.servers.ImageChannel;
2321
import qupath.lib.images.servers.ImageServerMetadata;
2422

2523
import javax.xml.parsers.DocumentBuilderFactory;
24+
import javax.xml.parsers.ParserConfigurationException;
25+
import javax.xml.transform.OutputKeys;
26+
import javax.xml.transform.Transformer;
27+
import javax.xml.transform.TransformerException;
2628
import javax.xml.transform.TransformerFactory;
2729
import javax.xml.transform.dom.DOMSource;
2830
import javax.xml.transform.stream.StreamResult;
2931
import java.io.ByteArrayOutputStream;
30-
import java.io.OutputStreamWriter;
32+
import java.io.IOException;
3133
import java.nio.charset.StandardCharsets;
32-
import java.util.Optional;
3334

3435
/**
3536
* Create the content of an OME XML file as described by the
3637
* <a href="http://www.openmicroscopy.org/Schemas/OME/2016-06/">Open Microscopy Environment OME Schema</a>.
3738
*/
3839
class OMEXMLCreator {
3940

40-
private static final Logger logger = LoggerFactory.getLogger(OMEXMLCreator.class);
4141
private static final String NAMESPACE_ATTRIBUTE = "xmlns";
4242
private static final String NAMESPACE = "http://www.openmicroscopy.org/Schemas/OME/2016-06";
4343
private static final String INSTRUMENT_ID = "Instrument:0";
@@ -46,18 +46,23 @@ class OMEXMLCreator {
4646
private static final String PIXELS_ID = "Pixels:0";
4747

4848
private OMEXMLCreator() {
49-
throw new RuntimeException("This class is not instantiable.");
49+
throw new AssertionError("This class is not instantiable.");
5050
}
5151

5252
/**
5353
* Create the content of an OME XML file that corresponds to the June 2016 Open Microscopy Environment OME Schema
5454
* applied to the provided metadata.
5555
*
5656
* @param metadata the metadata of the image
57-
* @return a text representing the provided metadata according the June 2016 Open Microscopy Environment OME Schema,
58-
* or an empty optional if the creation failed
57+
* @return a byte array representing a text encoded with {@link StandardCharsets#UTF_8} describing the provided metadata according the June 2016
58+
* Open Microscopy Environment OME Schema
59+
* @throws ParserConfigurationException if the XML document cannot be created
60+
* @throws org.w3c.dom.DOMException if an error occurs while creating the XML content
61+
* @throws IOException if an error occurs while converting the XML content to a byte array
62+
* @throws TransformerException if an error occurs while converting the XML content to a byte array
63+
* @throws IllegalArgumentException if the provided metadata contains an unexpected entry (e.g. no channels)
5964
*/
60-
public static Optional<String> create(ImageServerMetadata metadata) {
65+
public static byte[] create(ImageServerMetadata metadata) throws ParserConfigurationException, IOException, TransformerException {
6166
OME ome = new OME();
6267

6368
Instrument instrument = Double.isNaN(metadata.getMagnification()) ? null : createInstrument(metadata.getMagnification());
@@ -66,22 +71,21 @@ public static Optional<String> create(ImageServerMetadata metadata) {
6671
}
6772
ome.addImage(createImage(metadata, instrument));
6873

69-
try {
70-
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
71-
Element root = ome.asXMLElement(document);
72-
root.setAttribute(NAMESPACE_ATTRIBUTE, NAMESPACE);
73-
document.appendChild(root);
74-
75-
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
76-
TransformerFactory.newInstance().newTransformer().transform(
77-
new DOMSource(document),
78-
new StreamResult(new OutputStreamWriter(os, StandardCharsets.UTF_8))
79-
);
80-
return Optional.ofNullable(os.toString(StandardCharsets.UTF_8));
81-
}
82-
} catch (Exception e) {
83-
logger.error("Error while creating OME XML content", e);
84-
return Optional.empty();
74+
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
75+
Element root = ome.asXMLElement(document);
76+
root.setAttribute(NAMESPACE_ATTRIBUTE, NAMESPACE);
77+
document.appendChild(root);
78+
79+
try (
80+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
81+
) {
82+
Transformer transformer = TransformerFactory.newInstance().newTransformer();
83+
transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
84+
transformer.transform(
85+
new DOMSource(document),
86+
new StreamResult(outputStream)
87+
);
88+
return outputStream.toByteArray();
8589
}
8690
}
8791

qupath-extension-bioformats/src/main/java/qupath/lib/images/writers/ome/zarr/OMEZarrAttributesCreator.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,12 @@ private List<Map<String, Object>> getAxes() {
100100
}
101101

102102
private List<Map<String, Object>> getDatasets() {
103-
return IntStream.range(0, metadata.getPreferredDownsamplesArray().length)
103+
double[] downsamples = metadata.getPreferredDownsamplesArray();
104+
105+
return IntStream.range(0, downsamples.length)
104106
.mapToObj(level -> Map.of(
105-
"path", "s" + level,
106-
"coordinateTransformations", List.of(getCoordinateTransformation((float) metadata.getPreferredDownsamplesArray()[level]))
107+
"path", String.valueOf(level),
108+
"coordinateTransformations", List.of(getCoordinateTransformation((float) downsamples[level]))
107109
))
108110
.toList();
109111
}

qupath-extension-bioformats/src/main/java/qupath/lib/images/writers/ome/zarr/OMEZarrImageWriter.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,11 @@ public Class<BufferedImage> getImageClass() {
7373

7474
@Override
7575
public void writeImage(ImageServer<BufferedImage> server, RegionRequest region, String pathOutput) throws IOException {
76-
try (
77-
OMEZarrWriter writer = new OMEZarrWriter.Builder(server)
78-
.region(region)
79-
.build(pathOutput)
80-
) {
81-
writer.writeImage();
76+
try {
77+
new OMEZarrWriter.Builder(server)
78+
.region(region)
79+
.build(pathOutput)
80+
.writeImage();
8281
} catch (InterruptedException e) {
8382
logger.debug("Zarr image writing to {} interrupted", pathOutput, e);
8483
Thread.currentThread().interrupt();

0 commit comments

Comments
 (0)