diff --git a/src/main/kotlin/org/janelia/saalfeldlab/util/n5/DatasetDiscovery.kt b/src/main/kotlin/org/janelia/saalfeldlab/util/n5/DatasetDiscovery.kt index 8e6fadcb2..ab0ac0d09 100644 --- a/src/main/kotlin/org/janelia/saalfeldlab/util/n5/DatasetDiscovery.kt +++ b/src/main/kotlin/org/janelia/saalfeldlab/util/n5/DatasetDiscovery.kt @@ -1,7 +1,6 @@ package org.janelia.saalfeldlab.util.n5 import io.github.oshai.kotlinlogging.KotlinLogging -import org.commonmark.internal.util.Parsing import org.janelia.saalfeldlab.n5.N5Reader import org.janelia.saalfeldlab.n5.universe.N5DatasetDiscoverer import org.janelia.saalfeldlab.n5.universe.N5TreeNode @@ -43,9 +42,7 @@ private val LOG = KotlinLogging.logger { } @JvmOverloads internal fun discoverAndParseRecursive(n5Reader: N5Reader, initialGroup: String = "/", callback: (N5TreeNode) -> Unit = {}): N5TreeNode { val discoverer = getDiscoverer(n5Reader) - println("\tParsing ${n5Reader.uri}") return discoverer.discoverAndParseRecursive(initialGroup) { - println("\t\tDiscovered dataset ${it.path} with metadata ${it.metadata}") callback(it) } } \ No newline at end of file diff --git a/src/main/kotlin/org/janelia/saalfeldlab/util/n5/universe/N5FactoryWithCache.kt b/src/main/kotlin/org/janelia/saalfeldlab/util/n5/universe/N5FactoryWithCache.kt index 13571ab20..1507fc718 100644 --- a/src/main/kotlin/org/janelia/saalfeldlab/util/n5/universe/N5FactoryWithCache.kt +++ b/src/main/kotlin/org/janelia/saalfeldlab/util/n5/universe/N5FactoryWithCache.kt @@ -9,6 +9,7 @@ import org.janelia.saalfeldlab.n5.N5Writer import org.janelia.saalfeldlab.n5.hdf5.N5HDF5Reader import org.janelia.saalfeldlab.n5.universe.N5Factory import org.janelia.saalfeldlab.n5.universe.StorageFormat +import org.janelia.saalfeldlab.paintera.serialization.GsonHelpers import java.net.URI class N5FactoryWithCache : N5Factory() { diff --git a/src/test/java/org/janelia/saalfeldlab/util/n5/N5HelpersTest.java b/src/test/java/org/janelia/saalfeldlab/util/n5/N5HelpersTest.java index 396a9e9f9..a90cd236c 100644 --- a/src/test/java/org/janelia/saalfeldlab/util/n5/N5HelpersTest.java +++ b/src/test/java/org/janelia/saalfeldlab/util/n5/N5HelpersTest.java @@ -3,6 +3,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.imglib2.img.cell.CellGrid; +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookup; +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupAdapter; import org.janelia.saalfeldlab.n5.Compression; import org.janelia.saalfeldlab.n5.CompressionAdapter; import org.janelia.saalfeldlab.n5.DataType; @@ -11,12 +13,16 @@ import org.janelia.saalfeldlab.n5.N5Writer; import org.janelia.saalfeldlab.n5.RawCompression; import org.janelia.saalfeldlab.n5.universe.N5TreeNode; +import org.janelia.saalfeldlab.paintera.Paintera; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.invoke.MethodHandles; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Collectors; @@ -49,6 +55,14 @@ private static void assertDatasetAttributesEquals(final DatasetAttributes expect assertEquals(gsonWithCompression.toJson(expected.getCompression()), gsonWithCompression.toJson(actual.getCompression())); } + @BeforeAll + public static void setupN5Factory() { + + final var builder = new GsonBuilder(); + builder.registerTypeHierarchyAdapter(LabelBlockLookup.class, LabelBlockLookupAdapter.getJsonAdapter()); + Paintera.getN5Factory().gsonBuilder(builder); + } + @Test public void testAsCellGrid() { @@ -66,9 +80,10 @@ public void testVolumetricDataGroup() { assertEquals(group + "/" + N5Helpers.PAINTERA_DATA_DATASET, N5Helpers.volumetricDataGroup(group, true)); } - @Test public void testIsMultiscale() throws IOException { + @Test + public void testIsMultiscale(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(!LOG.isDebugEnabled()); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); final String group = "group"; writer.createGroup(group); @@ -91,9 +106,9 @@ public void testVolumetricDataGroup() { } @Test - public void testListAndSortScaleDatasets() throws IOException { + public void testListAndSortScaleDatasets(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(!LOG.isDebugEnabled()); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); final String group = "group"; writer.createGroup(group); writer.setAttribute(group, N5Helpers.MULTI_SCALE_KEY, true); @@ -109,9 +124,9 @@ public void testListAndSortScaleDatasets() throws IOException { } @Test - public void testDiscoverDatasets() throws IOException { + public void testDiscoverDatasets(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(!LOG.isDebugEnabled()); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); final String group = "group"; writer.createGroup(group); writer.setAttribute(group, N5Helpers.MULTI_SCALE_KEY, true); @@ -134,9 +149,9 @@ public void testDiscoverDatasets() throws IOException { } @Test - public void testGetDatasetAttributes() throws IOException { + public void testGetDatasetAttributes(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(!LOG.isDebugEnabled()); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); final DatasetAttributes attributes = new DatasetAttributes(new long[]{1}, new int[]{1}, DataType.UINT8, new GzipCompression()); // single scale diff --git a/src/test/java/org/janelia/saalfeldlab/util/n5/N5TestUtil.java b/src/test/java/org/janelia/saalfeldlab/util/n5/N5TestUtil.java deleted file mode 100644 index 51a7f0f7a..000000000 --- a/src/test/java/org/janelia/saalfeldlab/util/n5/N5TestUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.janelia.saalfeldlab.util.n5; - -import com.google.gson.GsonBuilder; -import com.pivovarit.function.ThrowingRunnable; -import org.apache.commons.io.FileUtils; -import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookup; -import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupAdapter; -import org.janelia.saalfeldlab.n5.DataType; -import org.janelia.saalfeldlab.n5.DatasetAttributes; -import org.janelia.saalfeldlab.n5.N5Writer; -import org.janelia.saalfeldlab.n5.RawCompression; -import org.janelia.saalfeldlab.n5.universe.N5Factory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.nio.file.Files; -import java.nio.file.Path; - -public class N5TestUtil { - - private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public static N5Writer fileSystemWriterAtTmpDir() throws IOException { - - return fileSystemWriterAtTmpDir(true); - } - - public static N5Writer fileSystemWriterAtTmpDir(final boolean deleteOnExit) throws IOException { - - final Path tmp = Files.createTempDirectory(null); - - LOG.debug("Creating temporary N5Writer at {} (delete on exit? {})", tmp, deleteOnExit); - - final File dir = tmp.toFile(); - if (deleteOnExit) { - dir.deleteOnExit(); - Runtime.getRuntime().addShutdownHook(new Thread(ThrowingRunnable.unchecked(() -> FileUtils.deleteDirectory(dir)))); - } - final N5Factory n5Factory = new N5Factory(); - final GsonBuilder builder = new GsonBuilder(); - builder.registerTypeHierarchyAdapter(LabelBlockLookup.class, LabelBlockLookupAdapter.getJsonAdapter()); - n5Factory.gsonBuilder(builder); - return n5Factory.openWriter("n5:file://" + tmp.toAbsolutePath()); - } - - static DatasetAttributes defaultAttributes() { - - return defaultAttributes(DataType.UINT8); - } - - static DatasetAttributes defaultAttributes(DataType t) { - - return new DatasetAttributes(new long[]{1}, new int[]{1}, t, new RawCompression()); - } -} diff --git a/src/test/java/org/janelia/saalfeldlab/util/n5/N5TypesTest.java b/src/test/java/org/janelia/saalfeldlab/util/n5/N5TypesTest.java index 12da80da4..29fb8266d 100644 --- a/src/test/java/org/janelia/saalfeldlab/util/n5/N5TypesTest.java +++ b/src/test/java/org/janelia/saalfeldlab/util/n5/N5TypesTest.java @@ -1,5 +1,6 @@ package org.janelia.saalfeldlab.util.n5; +import com.google.gson.GsonBuilder; import net.imglib2.type.numeric.integer.ByteType; import net.imglib2.type.numeric.integer.IntType; import net.imglib2.type.numeric.integer.LongType; @@ -10,12 +11,19 @@ import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.DoubleType; import net.imglib2.type.numeric.real.FloatType; +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookup; +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupAdapter; import org.janelia.saalfeldlab.n5.DataType; +import org.janelia.saalfeldlab.n5.DatasetAttributes; import org.janelia.saalfeldlab.n5.N5Writer; import org.janelia.saalfeldlab.n5.RawCompression; +import org.janelia.saalfeldlab.paintera.Paintera; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.IOException; +import java.nio.file.Path; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; @@ -27,6 +35,14 @@ public class N5TypesTest { + @BeforeAll + public static void setupN5Factory() { + + final var builder = new GsonBuilder(); + builder.registerTypeHierarchyAdapter(LabelBlockLookup.class, LabelBlockLookupAdapter.getJsonAdapter()); + Paintera.getN5Factory().gsonBuilder(builder); + } + @Test public void testAndLogIsIntegerType() { @@ -48,9 +64,9 @@ public void testAndLogIsIntegerType() { } @Test - public void testIsLabelMultisetType() throws IOException { + public void testIsLabelMultisetType(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); final String noMultisetGroup = "no-multiset-group"; final String multisetGroup = "multiset-group"; @@ -67,10 +83,13 @@ public void testIsLabelMultisetType() throws IOException { final String multisetGroupMultiscale = "multiset-group-multiscale"; writer.createGroup(noMultisetGroupMultiscale); writer.createGroup(multisetGroupMultiscale); - writer.createDataset(noMultisetGroupMultiscale + "/s0", N5TestUtil.defaultAttributes()); - writer.createDataset(noMultisetGroupMultiscale + "/s1", N5TestUtil.defaultAttributes()); - writer.createDataset(multisetGroupMultiscale + "/s0", N5TestUtil.defaultAttributes()); - writer.createDataset(multisetGroupMultiscale + "/s1", N5TestUtil.defaultAttributes()); + + final DatasetAttributes defaultAttributes = new DatasetAttributes(new long[]{1}, new int[]{1}, DataType.UINT8, new RawCompression()); + + writer.createDataset(noMultisetGroupMultiscale + "/s0", defaultAttributes); + writer.createDataset(noMultisetGroupMultiscale + "/s1", defaultAttributes); + writer.createDataset(multisetGroupMultiscale + "/s0", defaultAttributes); + writer.createDataset(multisetGroupMultiscale + "/s1", defaultAttributes); writer.setAttribute(noMultisetGroupMultiscale + "/s0", N5Helpers.LABEL_MULTISETTYPE_KEY, false); writer.setAttribute(multisetGroupMultiscale + "/s0", N5Helpers.LABEL_MULTISETTYPE_KEY, true); assertFalse(N5Types.isLabelMultisetType(writer, noMultisetGroupMultiscale)); @@ -107,9 +126,9 @@ public void testMaxForType() { } @Test - public void testGetDataType() throws IOException { + public void testGetDataType(@TempDir Path tmp) throws IOException { - final N5Writer writer = N5TestUtil.fileSystemWriterAtTmpDir(); + final N5Writer writer = Paintera.getN5Factory().newWriter(tmp.toAbsolutePath().toString()); for (final DataType t : DataType.values()) { writer.createDataset(t.toString(), new long[]{1}, new int[]{1}, t, new RawCompression()); assertEquals(t, N5Types.getDataType(writer, t.toString())); diff --git a/src/test/kotlin/org/janelia/saalfeldlab/paintera/data/n5/CommitCanvasN5Test.kt b/src/test/kotlin/org/janelia/saalfeldlab/paintera/data/n5/CommitCanvasN5Test.kt index 0a0daf4f7..85cd8d46a 100644 --- a/src/test/kotlin/org/janelia/saalfeldlab/paintera/data/n5/CommitCanvasN5Test.kt +++ b/src/test/kotlin/org/janelia/saalfeldlab/paintera/data/n5/CommitCanvasN5Test.kt @@ -1,6 +1,7 @@ package org.janelia.saalfeldlab.paintera.data.n5 import bdv.cache.SharedQueue +import com.google.gson.GsonBuilder import gnu.trove.map.TLongObjectMap import gnu.trove.map.hash.TLongObjectHashMap import gnu.trove.set.TLongSet @@ -20,6 +21,8 @@ import net.imglib2.type.numeric.integer.UnsignedLongType import net.imglib2.util.IntervalIndexer import net.imglib2.util.Intervals import net.imglib2.view.Views +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookup +import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupAdapter import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupKey import org.janelia.saalfeldlab.labels.blocks.n5.LabelBlockLookupFromN5Relative import org.janelia.saalfeldlab.n5.* @@ -27,28 +30,45 @@ import org.janelia.saalfeldlab.n5.imglib2.N5LabelMultisets import org.janelia.saalfeldlab.n5.imglib2.N5Utils import org.janelia.saalfeldlab.n5.universe.metadata.N5Metadata import org.janelia.saalfeldlab.n5.universe.metadata.axes.Axis +import org.janelia.saalfeldlab.paintera.Paintera +import org.janelia.saalfeldlab.paintera.PainteraGateway +import org.janelia.saalfeldlab.paintera.serialization.GsonHelpers import org.janelia.saalfeldlab.paintera.state.metadata.MetadataState import org.janelia.saalfeldlab.paintera.state.metadata.MetadataUtils import org.janelia.saalfeldlab.paintera.state.metadata.MetadataUtils.Companion.createMetadataState import org.janelia.saalfeldlab.paintera.state.metadata.N5ContainerState import org.janelia.saalfeldlab.util.n5.ImagesWithTransform import org.janelia.saalfeldlab.util.n5.N5Helpers -import org.janelia.saalfeldlab.util.n5.N5TestUtil import org.junit.jupiter.api.Assertions.assertArrayEquals import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path import java.util.Random import java.util.stream.IntStream import java.util.stream.Stream +import kotlin.io.path.absolutePathString +@TestInstance(PER_CLASS) class CommitCanvasN5Test { @JvmRecord private data class CanvasAndContainer(val canvas: CachedCellImg, val container: N5ContainerState) + @BeforeAll + fun setupN5Factory() { + + val builder = GsonBuilder() + builder.registerTypeHierarchyAdapter(LabelBlockLookup::class.java, LabelBlockLookupAdapter.getJsonAdapter()); + Paintera.n5Factory.gsonBuilder(builder) + } + @Test - fun testSingleScaleLabelMultisetCommit() = testSingleScale( - getTmpCanvasAndContainer(), + fun testSingleScaleLabelMultisetCommit(@TempDir tmp: Path) = testSingleScale( + getTmpCanvasAndContainer(tmp), "single-scale-label-multisets", DataType.UINT8, { n5, dataset -> N5LabelMultisets.openLabelMultiset(n5, dataset) }, @@ -57,8 +77,8 @@ class CommitCanvasN5Test { ) @Test - fun testMultiScaleScaleLabelMultisetCommit() = testMultiScale( - getTmpCanvasAndContainer(), + fun testMultiScaleScaleLabelMultisetCommit(@TempDir tmp: Path) = testMultiScale( + getTmpCanvasAndContainer(tmp), "multi-scale-label-multisets", DataType.UINT8, { n5, dataset -> N5LabelMultisets.openLabelMultiset(n5, dataset) }, @@ -67,8 +87,8 @@ class CommitCanvasN5Test { ) @Test - fun testPainteraLabelMultisetCommit() = testPainteraData( - getTmpCanvasAndContainer(), + fun testPainteraLabelMultisetCommit(@TempDir tmp: Path) = testPainteraData( + getTmpCanvasAndContainer(tmp), "paintera-label-multisets", DataType.UINT8, { n5, dataset -> N5LabelMultisets.openLabelMultiset(n5, dataset) }, @@ -78,15 +98,16 @@ class CommitCanvasN5Test { ) @Test - fun testSingleScaleUint64Commit() = testSingleScale(getTmpCanvasAndContainer(), + fun testSingleScaleUint64Commit(@TempDir tmp: Path) = testSingleScale( + getTmpCanvasAndContainer(tmp), "single-scale-uint64", DataType.UINT64, { n5, dataset -> N5Utils.open(n5, dataset) }, { c: UnsignedLongType, l: UnsignedLongType -> assertEquals(if (isInvalid(c)) 0 else c.integerLong, l.integerLong) }, HashMap()) @Test - fun testMultiScaleUint64Commit() = testMultiScale( - getTmpCanvasAndContainer(), + fun testMultiScaleUint64Commit(@TempDir tmp: Path) = testMultiScale( + getTmpCanvasAndContainer(tmp), "multi-scale-uint64", DataType.UINT64, { n5, dataset -> N5Utils.open(n5, dataset) }, @@ -94,8 +115,8 @@ class CommitCanvasN5Test { ) @Test - fun testPainteraUint64Commit() = testPainteraData( - getTmpCanvasAndContainer(), + fun testPainteraUint64Commit(@TempDir tmp: Path) = testPainteraData( + getTmpCanvasAndContainer(tmp), "paintera-uint64", DataType.UINT64, { n5, dataset -> N5Utils.open(n5, dataset) }, @@ -129,11 +150,14 @@ class CommitCanvasN5Test { } } - private fun getTmpCanvasAndContainer(): CanvasAndContainer { + private fun getTmpCanvasAndContainer(tmp: Path): CanvasAndContainer { val canvas = newTestCanvas() - val writer = N5TestUtil.fileSystemWriterAtTmpDir(!LOG.isDebugEnabled()) + + val writer = Paintera.n5Factory.newWriter(tmp.absolutePathString()) val container = N5ContainerState(writer) LOG.debug { "Created temporary N5 container $writer" } + + return CanvasAndContainer(canvas, container) } @@ -298,7 +322,7 @@ class CommitCanvasN5Test { ) { val (canvas, container) = canvasAndContainer - val metadataState = createMetadataState(container, dataset) ?: DummyMetadataState(dataset, container) + val metadataState = createMetadataState(container, dataset)!! writeAll(metadataState, canvas)