Skip to content

Commit

Permalink
Port unit tests from omero-ms-image-region
Browse files Browse the repository at this point in the history
  • Loading branch information
sbesson committed Mar 13, 2024
1 parent a6a4003 commit facdb30
Show file tree
Hide file tree
Showing 4 changed files with 874 additions and 0 deletions.
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ repositories {
maven {
url 'https://artifacts.glencoesoftware.com/artifactory/jzarr-releases/'
}
maven {
url 'https://repo.glencoesoftware.com/repository/bioformats2raw2ometiff/'
}
}

dependencies {
Expand All @@ -36,6 +39,9 @@ dependencies {
implementation 'com.bc.zarr:jzarr:0.3.5'
implementation 'org.lasersonlab:s3fs:2.2.3'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.659'

testImplementation 'info.picocli:picocli:4.7.5'
testImplementation 'com.glencoesoftware:bioformats2raw:0.9.1'
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* Copyright (C) 2021 Glencoe Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.glencoesoftware.omero.ms.core;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;

import com.bc.zarr.ZarrGroup;
import com.glencoesoftware.bioformats2raw.Converter;

import picocli.CommandLine;

public abstract class AbstractZarrPixelBufferTest {

@Rule
public TemporaryFolder tmpDir = new TemporaryFolder();

/**
* Run the bioformats2raw main method and check for success or failure.
*
* @param additionalArgs CLI arguments as needed beyond "input output"
*/
void assertBioFormats2Raw(Path input, Path output, String...additionalArgs)
throws IOException {
List<String> args = new ArrayList<String>(
Arrays.asList(new String[] { "--compression", "null" }));
for (String arg : additionalArgs) {
args.add(arg);
}
args.add(input.toString());
args.add(output.toString());
try {
Converter converter = new Converter();
CommandLine cli = new CommandLine(converter);
cli.execute(args.toArray(new String[]{}));
Assert.assertTrue(Files.exists(output.resolve(".zattrs")));
Assert.assertTrue(Files.exists(
output.resolve("OME").resolve("METADATA.ome.xml")));
} catch (RuntimeException rt) {
throw rt;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

static Path fake(String...args) {
Assert.assertTrue(args.length %2 == 0);
Map<String, String> options = new HashMap<String, String>();
for (int i = 0; i < args.length; i += 2) {
options.put(args[i], args[i+1]);
}
return fake(options);
}

static Path fake(Map<String, String> options) {
return fake(options, null);
}

/**
* Create a Bio-Formats fake INI file to use for testing.
* @param options map of the options to assign as part of the fake filename
* from the allowed keys
* @param series map of the integer series index and options map (same format
* as <code>options</code> to add to the fake INI content
* @see https://docs.openmicroscopy.org/bio-formats/6.4.0/developers/
* generating-test-images.html#key-value-pairs
* @return path to the fake INI file that has been created
*/
static Path fake(Map<String, String> options,
Map<Integer, Map<String, String>> series)
{
return fake(options, series, null);
}

static Path fake(Map<String, String> options,
Map<Integer, Map<String, String>> series,
Map<String, String> originalMetadata)
{
StringBuilder sb = new StringBuilder();
sb.append("image");
if (options != null) {
for (Map.Entry<String, String> kv : options.entrySet()) {
sb.append("&");
sb.append(kv.getKey());
sb.append("=");
sb.append(kv.getValue());
}
}
sb.append("&");
try {
List<String> lines = new ArrayList<String>();
if (originalMetadata != null) {
lines.add("[GlobalMetadata]");
for (String key : originalMetadata.keySet()) {
lines.add(String.format(
"%s=%s", key, originalMetadata.get(key)));
}
}
if (series != null) {
for (int s : series.keySet()) {
Map<String, String> seriesOptions = series.get(s);
lines.add(String.format("[series_%d]", s));
for (String key : seriesOptions.keySet()) {
lines.add(String.format(
"%s=%s", key, seriesOptions.get(key)));
}
}
}
Path ini = Files.createTempFile(sb.toString(), ".fake.ini");
File iniAsFile = ini.toFile();
String iniPath = iniAsFile.getAbsolutePath();
String fakePath = iniPath.substring(0, iniPath.length() - 4);
Path fake = Paths.get(fakePath);
File fakeAsFile = fake.toFile();
Files.write(fake, new byte[]{});
Files.write(ini, lines);
iniAsFile.deleteOnExit();
fakeAsFile.deleteOnExit();
return ini;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public Path writeTestZarr(
int sizeT,
int sizeC,
int sizeZ,
int sizeY,
int sizeX,
String pixelType,
int resolutions) throws IOException {
Path input = fake(
"sizeT", Integer.toString(sizeT),
"sizeC", Integer.toString(sizeC),
"sizeZ", Integer.toString(sizeZ),
"sizeY", Integer.toString(sizeY),
"sizeX", Integer.toString(sizeX),
"pixelType", pixelType,
"resolutions", Integer.toString(resolutions));
Path output = tmpDir.getRoot().toPath().resolve("output.zarr");
assertBioFormats2Raw(input, output);
List<Object> msArray = new ArrayList<>();
Map<String, Object> msData = new HashMap<>();
Map<String, Object> msMetadata = new HashMap<>();
msMetadata.put("method", "loci.common.image.SimpleImageScaler");
msMetadata.put("version", "Bio-Formats 6.5.1");
msData.put("metadata", msMetadata);
msData.put("datasets", getDatasets(resolutions));
msData.put("version", "0.1");
msArray.add(msData);
ZarrGroup z = ZarrGroup.open(output.resolve("0"));
Map<String,Object> attrs = new HashMap<String, Object>();
attrs.put("multiscales", msArray);
z.writeAttributes(attrs);
return output;
}

List<Map<String, String>> getDatasets(int resolutions) {
List<Map<String, String>> datasets = new ArrayList<>();
for (int i = 0; i < resolutions; i++) {
Map<String, String> resObj = new HashMap<>();
resObj.put("path", Integer.toString(i));
datasets.add(resObj);
}
return datasets;
}

}
130 changes: 130 additions & 0 deletions src/test/java/com/glencoesoftware/omero/ms/core/PixelsServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2023 Glencoe Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.glencoesoftware.omero.ms.core;

import java.io.IOException;
import java.io.File;
import java.nio.file.Files;
import java.util.UUID;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import omero.ApiUsageException;
import omero.model.ExternalInfo;
import omero.model.ExternalInfoI;
import omero.model.IObject;
import omero.model.Image;
import omero.model.ImageI;
import omero.model.Mask;
import omero.model.MaskI;
import omero.util.IceMapper;

import static omero.rtypes.rdouble;
import static omero.rtypes.rlong;
import static omero.rtypes.rstring;

public class PixelsServiceTest {

private PixelsService pixelsService;
private String uuid = UUID.randomUUID().toString();
private String imageUri = "/data/ngff/image.zarr";
private String labelUri = imageUri + "/0/labels/" + uuid;
private Image image;
private Mask mask;
private String ENTITY_TYPE = "com.glencoesoftware.ngff:multiscales";
private int ENTITY_ID = 3;

@Before
public void setUp() throws IOException {
File pixelsDir = Files.createTempDirectory("pixels").toFile();
pixelsDir.deleteOnExit();
File memoDir = Files.createTempDirectory("memoizer").toFile();
memoDir.deleteOnExit();
pixelsService = new PixelsService(
pixelsDir.getAbsolutePath(), false, memoDir, 0L, null, null, null, null, 0, 0, 0);
mask = new MaskI();
image = new ImageI();
}

private void addExternalInfo(IObject object, Integer entityId, String entityType, String lsid, String uuid) {
ExternalInfo externalInfo = new ExternalInfoI();
externalInfo.setEntityId(rlong(entityId));
externalInfo.setEntityType(rstring(entityType));
if (lsid != null) {
externalInfo.setLsid(rstring(lsid));
}
if (uuid != null) {
externalInfo.setUuid(rstring(uuid));
}
object.getDetails().setExternalInfo(externalInfo);
}

@Test
public void testDefault() throws ApiUsageException, IOException {
addExternalInfo(mask, ENTITY_ID, ENTITY_TYPE, labelUri, uuid);
Assert.assertEquals(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)), labelUri);

addExternalInfo(image, ENTITY_ID, ENTITY_TYPE, imageUri, uuid);
Assert.assertEquals(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)), imageUri);
}

@Test
public void testGetUriNoExternalInfo() throws ApiUsageException, IOException {
Assert.assertNull(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)));
Assert.assertNull(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)));
}

@Test
public void testGetUriNoUuid() throws ApiUsageException, IOException {
addExternalInfo(mask, ENTITY_ID, ENTITY_TYPE, labelUri, null);
Assert.assertEquals(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)), labelUri);

addExternalInfo(image, ENTITY_ID, ENTITY_TYPE, imageUri, null);
Assert.assertEquals(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)), imageUri);
}

@Test
public void testGetUriNoLsid() throws ApiUsageException, IOException {
addExternalInfo(mask, ENTITY_ID, ENTITY_TYPE, null, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)));

addExternalInfo(image, ENTITY_ID, ENTITY_TYPE, null, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)));
}

@Test
public void testGetUriWrongEntityType() throws ApiUsageException, IOException {
addExternalInfo(mask, ENTITY_ID, "multiscales", labelUri, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)));

addExternalInfo(image, ENTITY_ID, "multiscales", imageUri, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)));
}

@Test
public void testGetUriWrongEntityId() throws ApiUsageException, IOException {
addExternalInfo(mask, 1, ENTITY_TYPE, labelUri, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.roi.Mask) new IceMapper().reverse(mask)));

addExternalInfo(image, 1, ENTITY_TYPE, imageUri, uuid);
Assert.assertNull(pixelsService.getUri((ome.model.core.Image) new IceMapper().reverse(image)));
}
}
Loading

0 comments on commit facdb30

Please sign in to comment.