Skip to content
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
27 changes: 9 additions & 18 deletions components/tools/OmeroJava/test/integration/ExporterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,16 +260,13 @@ private Image createSimpleImageToExport() throws Exception {
* Thrown if an error occurred.
*/
private Image createImageWithROIToExport() throws Exception {
//create an import and image
File f = File.createTempFile(RandomStringUtils.random(100, false, true),
"."+ OME_XML);
// Create OME-TIFF file with ROI data
XMLMockObjects xml = new XMLMockObjects();
XMLWriter writer = new XMLWriter();
writer.writeFile(f, xml.createImageWithROI(), true);
File f = mmFactory.createOMETiffFile(xml.createImageWithROI());
List<Pixels> pix = null;
try {
// method tested in ImporterTest
pix = importFile(f, OME_XML);
pix = importFile(f, OME_TIFF);
return pix.get(0).getImage();
} catch (Throwable e) {
throw new Exception("Cannot create image to import", e);
Expand All @@ -286,16 +283,13 @@ private Image createImageWithROIToExport() throws Exception {
* Thrown if an error occurred.
*/
private Image createImageWithAnnotatedDataToExport() throws Exception {
//create an import and image
File f = File.createTempFile(RandomStringUtils.random(100, false, true),
"."+ OME_XML);
// Create OME-TIFF file with annotated acquisition data
XMLMockObjects xml = new XMLMockObjects();
XMLWriter writer = new XMLWriter();
writer.writeFile(f, xml.createImageWithAnnotatedAcquisitionData(), true);
File f = mmFactory.createOMETiffFile(xml.createImageWithAnnotatedAcquisitionData());
List<Pixels> pix = null;
try {
// method tested in ImporterTest
pix = importFile(f, OME_XML);
pix = importFile(f, OME_TIFF);
return pix.get(0).getImage();
} catch (Throwable e) {
throw new Exception("Cannot create image to import", e);
Expand All @@ -312,16 +306,13 @@ private Image createImageWithAnnotatedDataToExport() throws Exception {
* Thrown if an error occurred.
*/
private Image createImageToExport() throws Exception {
//create an import and image
File f = File.createTempFile(RandomStringUtils.random(100, false, true),
"." + OME_XML);
// Create OME-TIFF file with acquisition data
XMLMockObjects xml = new XMLMockObjects();
XMLWriter writer = new XMLWriter();
writer.writeFile(f, xml.createImageWithAcquisitionData(), true);
File f = mmFactory.createOMETiffFile(xml.createImageWithAcquisitionData());
List<Pixels> pix = null;
try {
// method tested in ImporterTest
pix = importFile(f, OME_XML);
pix = importFile(f, OME_TIFF);
return pix.get(0).getImage();
} catch (Throwable e) {
throw new Exception("Cannot create image to import", e);
Expand Down
78 changes: 78 additions & 0 deletions components/tools/OmeroJava/test/integration/ModelMockFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import ome.formats.model.UnitsFactory;
import ome.units.UNITS;
import ome.xml.model.enums.PixelType;
import omero.ServerError;
import omero.api.ITypesPrx;
import omero.model.*;
Expand Down Expand Up @@ -1214,4 +1215,81 @@ public IObject createAnnotationLink(IObject o, Annotation a)
linkMethod.invoke(link, o, a, null); // Last is Ice.Current;
return link;
}

/**
* Creates an OME-TIFF file from OME metadata using Bio-Formats.
* The full OME model is preserved in the embedded OME-XML, including
* ROIs and annotations.
*
* @param ome The OME metadata to convert.
* @return A temporary File containing the OME-TIFF.
* @throws Exception Thrown if an error occurred.
*/
public File createOMETiffFile(ome.xml.model.OME ome) throws Exception {
if (ome == null || ome.sizeOfImageList() == 0) {
throw new IllegalArgumentException("OME metadata must contain at least one Image");
}

// Get dimensions from the first image
ome.xml.model.Pixels pixels = ome.getImage(0).getPixels();
int sizeX = pixels.getSizeX().getValue();
int sizeY = pixels.getSizeY().getValue();
int sizeZ = pixels.getSizeZ().getValue();
int sizeC = pixels.getSizeC().getValue();
int sizeT = pixels.getSizeT().getValue();

PixelType pixelType = pixels.getType();
if (pixelType == null) {
pixelType = PixelType.UINT8;
}

// Step 1: Serialise the full OME model to a temp .ome.xml companion file.
// XMLWriter preserves ROIs, annotations and all other elements.
File xmlFile = File.createTempFile("metadata", ".ome.xml");
xmlFile.deleteOnExit();
new ome.specification.XMLWriter().writeFile(xmlFile, ome, true);

// Step 2: Attach a fresh OMEXMLMetadata store to the reader *before* opening
// the file so that the reader populates it with the complete parsed
// OME-XML (ROIs, annotations, etc.), not just pixel dimensions.
loci.formats.ome.OMEXMLMetadata meta = (loci.formats.ome.OMEXMLMetadata)
loci.formats.MetadataTools.createOMEXMLMetadata();
loci.formats.ImageReader reader = new loci.formats.ImageReader();
reader.setMetadataStore(meta);
reader.setId(xmlFile.getAbsolutePath());

// Step 3: Ensure SamplesPerPixel is set for all channels (required by writer).
for (int c = 0; c < sizeC; c++) {
if (meta.getChannelSamplesPerPixel(0, c) == null) {
meta.setChannelSamplesPerPixel(
new ome.xml.model.primitives.PositiveInteger(1), 0, c);
}
}

// Step 4: Write the OME-TIFF with the fully populated metadata store.
File tiffFile = File.createTempFile("ome_tiff_", ".ome.tiff");
tiffFile.deleteOnExit();

loci.formats.out.OMETiffWriter writer = new loci.formats.out.OMETiffWriter();
writer.setMetadataRetrieve(meta);
writer.setId(tiffFile.getAbsolutePath());

// Step 5: Write synthetic pixel data for each plane.
int bytesPerPixel = loci.formats.FormatTools.getBytesPerPixel(
loci.formats.FormatTools.pixelTypeFromString(pixelType.toString()));
byte[] pixelData = new byte[sizeX * sizeY * bytesPerPixel];
int planeCount = sizeZ * sizeC * sizeT;
for (int plane = 0; plane < planeCount; plane++) {
for (int i = 0; i < pixelData.length; i++) {
pixelData[i] = (byte) ((i + plane) % 256);
}
writer.saveBytes(plane, pixelData);
}

writer.close();
reader.close();
xmlFile.delete();

return tiffFile;
}
}
133 changes: 133 additions & 0 deletions components/tools/OmeroJava/test/integration/ModelMockFactoryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright 2006-2017 University of Dundee. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package integration;

import java.io.File;
import java.util.Iterator;
import java.util.List;

import ome.specification.XMLMockObjects;
import omero.api.IRoiPrx;
import omero.api.RoiOptions;
import omero.api.RoiResult;
import omero.model.Annotation;
import omero.model.BooleanAnnotation;
import omero.model.CommentAnnotation;
import omero.model.Ellipse;
import omero.model.IObject;
import omero.model.ImageAnnotationLink;
import omero.model.Line;
import omero.model.LongAnnotation;
import omero.model.Mask;
import omero.model.Pixels;
import omero.model.Point;
import omero.model.Polyline;
import omero.model.Rectangle;
import omero.model.Roi;
import omero.model.Shape;
import omero.model.TagAnnotation;
import omero.model.TermAnnotation;
import omero.sys.ParametersI;

import org.testng.Assert;
import org.testng.annotations.Test;

/**
* Tests for ModelMockFactory
*/
public class ModelMockFactoryTest extends AbstractServerImportTest {

private static final String OME_TIFF = "ome.tiff";

/**
* Tests that an OME-TIFF created from an image with ROI data can be
* imported and that all expected shapes survive the round-trip.
*/
@Test
public void testCreateOMETiffFileWithROI() throws Throwable {
XMLMockObjects xml = new XMLMockObjects();
File tiffFile = mmFactory.createOMETiffFile(xml.createImageWithROI());
try {
List<Pixels> pixels = importFile(tiffFile, OME_TIFF);
Assert.assertNotNull(pixels);
Assert.assertFalse(pixels.isEmpty());

long imageId = pixels.get(0).getImage().getId().getValue();

IRoiPrx roiSvc = factory.getRoiService();
RoiResult result = roiSvc.findByImage(imageId, new RoiOptions());
Assert.assertNotNull(result);
List<Roi> rois = result.rois;
Assert.assertNotNull(rois);
Assert.assertEquals(rois.size(), XMLMockObjects.SIZE_C.intValue());

Iterator<Roi> roiIter = rois.iterator();
while (roiIter.hasNext()) {
Roi roi = roiIter.next();
List<Shape> shapes = roi.copyShapes();
Assert.assertNotNull(shapes);
Assert.assertEquals(shapes.size(), XMLMockObjects.SHAPES.length);
int count = 0;
for (Shape shape : shapes) {
if (shape instanceof Rectangle || shape instanceof Line
|| shape instanceof Ellipse
|| shape instanceof Polyline || shape instanceof Mask
|| shape instanceof Point) {
count++;
}
}
Assert.assertEquals(count, XMLMockObjects.SHAPES.length);
}
} finally {
if (tiffFile != null && tiffFile.exists()) {
tiffFile.delete();
}
}
}

/**
* Tests that an OME-TIFF created from an annotated image can be imported
* and that all expected annotation types survive the round-trip.
*/
@Test
public void testCreateOMETiffFileWithAnnotations() throws Throwable {
XMLMockObjects xml = new XMLMockObjects();
File tiffFile = mmFactory.createOMETiffFile(xml.createAnnotatedImage());
try {
List<Pixels> pixels = importFile(tiffFile, OME_TIFF);
Assert.assertNotNull(pixels);
Assert.assertFalse(pixels.isEmpty());

long imageId = pixels.get(0).getImage().getId().getValue();

String hql = "select l from ImageAnnotationLink as l "
+ "left outer join fetch l.parent as p "
+ "join fetch l.child "
+ "where p.id = :id";
List<IObject> links = iQuery.findAllByQuery(hql, new ParametersI().addId(imageId));

Assert.assertTrue(links.size() >= XMLMockObjects.ANNOTATIONS.length,
String.format("Expected at least %d annotations, got %d",
XMLMockObjects.ANNOTATIONS.length, links.size()));

int count = 0;
for (IObject obj : links) {
Annotation a = ((ImageAnnotationLink) obj).getChild();
if (a instanceof CommentAnnotation
|| a instanceof TagAnnotation
|| a instanceof TermAnnotation
|| a instanceof BooleanAnnotation
|| a instanceof LongAnnotation) {
count++;
}
}
Assert.assertEquals(count, XMLMockObjects.ANNOTATIONS.length);
} finally {
if (tiffFile != null && tiffFile.exists()) {
tiffFile.delete();
}
}
}
}
Loading
Loading