Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow individual label images to be converted #135

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

<!-- Checks for Size Violations. -->
<!-- See https://checkstyle.org/config_sizes.html -->
<module name="FileLength"/>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
import loci.common.services.ServiceFactory;
import loci.formats.FormatException;
import loci.formats.FormatTools;
import loci.formats.ImageReader;
import loci.formats.MetadataTools;
import loci.formats.codec.CodecOptions;
import loci.formats.meta.IMetadata;
import loci.formats.ome.OMEPyramidStore;
import loci.formats.services.OMEXMLService;
import loci.formats.tiff.IFD;
Expand Down Expand Up @@ -138,6 +140,8 @@ public class PyramidFromDirectoryWriter implements Callable<Void> {
boolean splitBySeries = false;
boolean splitByPlane = false;

String imageFile = null;

private ZarrGroup reader = null;

/** Writer metadata. */
Expand Down Expand Up @@ -352,6 +356,25 @@ public void setSplitSinglePlaneTIFFs(boolean split) {
splitByPlane = split;
}

/**
* Set an alternate file to use for obtaining OME-XML metadata
* If the expected "OME/METADATA.ome.xml" file is not found, then
* the provided file will be read using Bio-Formats.
* This file is expected to be an original image file, with dimensions
* that match the input Zarr.
*
* @param file path to image file
*/
@Option(
names = {"--image-file", "-f"},
description =
"Image file from which read metadata, if METADATA.ome.xml not found",
defaultValue = ""
)
public void setImageFile(String file) {
imageFile = file;
}

/**
* Set the maximum number of workers to use for converting tiles.
* Defaults to 4 or the number of detected CPUs, whichever is smaller.
Expand Down Expand Up @@ -483,6 +506,14 @@ public boolean getSplitSinglePlaneTIFFs() {
return splitByPlane;
}

/**
* @return path to image file from which metadata is read,
* if METADATA.ome.xml not present
*/
public String getImageFile() {
return imageFile;
}

/**
* @return maximum number of worker threads
*/
Expand Down Expand Up @@ -931,6 +962,17 @@ else if (layoutVersion != 3) {
if (omexml != null && Files.exists(omexml)) {
xml = DataTools.readFile(omexml.toString());
}
else if (imageFile != null && !imageFile.isEmpty()) {
try (ImageReader imageReader = new ImageReader()) {
IMetadata srcMetadata = service.createOMEXMLMetadata();
imageReader.setMetadataStore(srcMetadata);
imageReader.setId(imageFile);
xml = service.getOMEXML(srcMetadata);
}
catch (ServiceException e) {
throw new FormatException("Could not get OME-XML from image file", e);
}
}
try {
if (xml != null) {
metadata = (OMEPyramidStore) service.createOMEXMLMetadata(xml);
Expand All @@ -957,8 +999,11 @@ else if (layoutVersion != 3) {

int seriesCount = getSeriesCount();

boolean flatHierarchy = false;
if (seriesCount < 1) {
throw new FormatException("Found no images to convert. Corrupt input?");
LOG.warn("Series missing from hierarchy, assuming single pyramid");
seriesCount = 1;
flatHierarchy = true;
}

if (seriesCount > 1 && legacy) {
Expand Down Expand Up @@ -991,6 +1036,18 @@ else if (layoutVersion != 3) {
PyramidSeries s = new PyramidSeries();
s.index = seriesIndex;
s.path = String.valueOf(s.index);
if (flatHierarchy) {
try {
// if we're skipping the series in the hierarchy,
// check that there is actually an array at the resolution level
ZarrArray.open(inputDirectory.resolve("0"));
s.path = "";
}
catch (IOException e) {
throw new FormatException(
"Could not handle series index " + s.index + ". Corrupt input?");
}
}
series.set(s.index, s);
}
}
Expand All @@ -1004,9 +1061,26 @@ else if (layoutVersion != 3) {
}
findNumberOfResolutions(s);

int x = metadata.getPixelsSizeX(seriesIndex).getNumberValue().intValue();
int y = metadata.getPixelsSizeY(seriesIndex).getNumberValue().intValue();

s.z = metadata.getPixelsSizeZ(seriesIndex).getNumberValue().intValue();
s.c = metadata.getPixelsSizeC(seriesIndex).getNumberValue().intValue();
s.t = metadata.getPixelsSizeT(seriesIndex).getNumberValue().intValue();

// make sure that OME-XML and first resolution array have same dimensions
ZarrGroup imgGroup = getZarrGroup(s.path);
ZarrArray imgArray = imgGroup.openArray("0");
int[] dims = imgArray.getShape();
int[] metadataDims = new int[] {s.t, s.c, s.z, y, x};
for (int d=0; d<dims.length; d++) {
if (dims[d] != metadataDims[d]) {
throw new FormatException("Dimension mismatch: " +
("TZCYX".charAt(d)) + ": Zarr (" + dims[d] + "), OME-XML: (" +
metadataDims[d] + ")");
}
}

s.dimensionOrder =
metadata.getPixelsDimensionOrder(seriesIndex).toString();
s.planeCount = s.z * s.t;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,37 @@ public void testVersionOnly() throws Exception {
new PyramidFromDirectoryWriter(), new String[] {"--version"});
}

/**
* Test conversion of a single multiscales, similar to a label image.
*/
@Test
public void testLabelImage() throws Exception {
input = fake("sizeX", "2000", "sizeY", "1500");
assertBioFormats2Raw();
output = output.resolve("0");
assertTool("-f", input.toString());
iteratePixels();
}

/**
* Test conversion of a single multiscales (similar to label image),
* but intentionally provide incorrect image metadata.
*/
@Test
public void testLabelImageWrongSize() throws Exception {
input = fake("sizeX", "2000", "sizeY", "1500");
assertBioFormats2Raw();
output = output.resolve("0");
try {
assertTool("-f", "test.fake");
}
catch (ExecutionException e) {
// First cause is RuntimeException wrapping the checked FormatException
Assert.assertEquals(
FormatException.class, e.getCause().getCause().getClass());
}
}

private void checkRGBIFDs() throws FormatException, IOException {
try (TiffParser parser = new TiffParser(outputOmeTiff.toString())) {
IFDList mainIFDs = parser.getMainIFDs();
Expand Down
Loading