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

feat: support OmeNgff Metadata #529

Merged
merged 3 commits into from
May 2, 2024
Merged
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
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
<n5-aws-s3.version>4.1.2</n5-aws-s3.version>
<n5-zarr.version>1.3.1</n5-zarr.version>
<n5-imglib2.version>7.0.0</n5-imglib2.version>
<n5-universe.version>1.4.0</n5-universe.version>
<n5-universe.version>1.4.3</n5-universe.version>

<enforcer.skip>true</enforcer.skip>
</properties>
Expand Down Expand Up @@ -632,7 +632,7 @@
<mailingLists>
<mailingList>
<name>ImageJ Forum</name>
<archive>http://forum.imagej.net/</archive>
<archive>https://forum.image.sc/</archive>
</mailingList>
</mailingLists>

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/janelia/saalfeldlab/util/n5/N5Data.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.janelia.saalfeldlab.n5.N5Writer;
import org.janelia.saalfeldlab.n5.imglib2.N5LabelMultisets;
import org.janelia.saalfeldlab.n5.imglib2.N5Utils;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SingleScaleMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SpatialDatasetMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.SpatialMultiscaleMetadata;
import org.janelia.saalfeldlab.paintera.Paintera;
import org.janelia.saalfeldlab.paintera.cache.WeakRefVolatileCache;
Expand Down Expand Up @@ -624,7 +624,7 @@ public static ImagesWithTransform<LabelMultisetType, VolatileLabelMultisetType>[
final SharedQueue queue,
final int priority) throws IOException {

SpatialMultiscaleMetadata<N5SingleScaleMetadata> metadata = metadataState.getMetadata();
SpatialMultiscaleMetadata<N5SpatialDatasetMetadata> metadata = metadataState.getMetadata();
final String[] ssPaths = metadata.getPaths();

LOG.debug("Opening groups {} as multi-scale in {} ", Arrays.toString(ssPaths), metadata.getPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import net.imglib2.realtransform.AffineGet;
import net.imglib2.realtransform.AffineTransform3D;
import org.janelia.saalfeldlab.n5.universe.metadata.N5MultiScaleMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SpatialDatasetMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.SpatialMultiscaleMetadata;

import java.util.function.Predicate;
import java.util.regex.Pattern;

public abstract class N5PainteraDataMultiScaleGroup extends N5MultiScaleMetadata {
public abstract class N5PainteraDataMultiScaleGroup extends SpatialMultiscaleMetadata<N5SpatialDatasetMetadata> {

public static final Predicate<String> SCALE_LEVEL_PREDICATE = Pattern.compile("^s\\d+$").asPredicate();
protected final N5PainteraDataMultiScaleMetadata dataGroup;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package org.janelia.saalfeldlab.util.n5.metadata;

import bdv.util.Affine3DHelpers;
import com.sun.javafx.geom.transform.Affine3D;
import net.imglib2.realtransform.AffineGet;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.realtransform.Scale3D;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.universe.N5TreeNode;
import org.janelia.saalfeldlab.n5.universe.metadata.N5MetadataParser;
import org.janelia.saalfeldlab.n5.universe.metadata.N5MultiScaleMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SingleScaleMetadata;
import org.janelia.saalfeldlab.paintera.state.metadata.SingleScaleMetadataState;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SpatialDatasetMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.SpatialMultiscaleMetadata;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
Expand All @@ -21,14 +17,11 @@
/**
* Metadata Parser for a Paintera Data Multiscale Dataset. Namely, transforms are dependant on group metadata
*/
public class N5PainteraDataMultiScaleMetadata extends N5MultiScaleMetadata {
public class N5PainteraDataMultiScaleMetadata extends SpatialMultiscaleMetadata<N5SpatialDatasetMetadata> {

private AffineTransform3D groupTransform;

public N5PainteraDataMultiScaleMetadata(final String basePath, final N5SingleScaleMetadata[] childrenMetadata, final AffineTransform3D groupTransform) {
public N5PainteraDataMultiScaleMetadata(final String basePath, final N5SpatialDatasetMetadata[] childrenMetadata) {

super(basePath, childrenMetadata);
this.groupTransform = groupTransform;
}
@Override public String unit() {

Expand All @@ -46,7 +39,7 @@ public static class PainteraDataMultiScaleParser implements N5MetadataParser<N5P
final Map<String, N5TreeNode> scaleLevelNodes = new HashMap<>();
for (final N5TreeNode childNode : node.childrenList()) {
if (N5PainteraDataMultiScaleGroup.SCALE_LEVEL_PREDICATE.test(childNode.getNodeName()) && childNode.isDataset()
&& childNode.getMetadata() instanceof N5SingleScaleMetadata) {
&& childNode.getMetadata() instanceof N5SpatialDatasetMetadata) {
scaleLevelNodes.put(childNode.getNodeName(), childNode);
}
}
Expand Down Expand Up @@ -113,7 +106,7 @@ public static class PainteraDataMultiScaleParser implements N5MetadataParser<N5P
);
}

return Optional.of(new N5PainteraDataMultiScaleMetadata(node.getPath(), resolvedChildrenMetadata, transform));
return Optional.of(new N5PainteraDataMultiScaleMetadata(node.getPath(), resolvedChildrenMetadata));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
import org.janelia.saalfeldlab.n5.universe.metadata.N5MetadataParser;
import org.janelia.saalfeldlab.n5.universe.metadata.N5MultiScaleMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SingleScaleMetadata;
import org.janelia.saalfeldlab.n5.universe.metadata.N5SpatialDatasetMetadata;

import java.io.IOException;
import java.util.Optional;

public class N5PainteraLabelMultiScaleGroup extends N5PainteraDataMultiScaleGroup {
Expand Down Expand Up @@ -146,12 +146,16 @@ public static class PainteraLabelMultiScaleParser implements N5MetadataParser<N5
final var finalFragmentSegmentAssignmentGroup = fragmentSegmentAssignment;
final var finalLabelToBlockLookupGroup = labelToBlockLookupGroup;

return Optional.ofNullable(dataGroup).map(dg -> new N5PainteraLabelMultiScaleGroup(
node.getPath(),
dg,
finalUniqueLabelsGroup, finalFragmentSegmentAssignmentGroup, finalLabelToBlockLookupGroup,
maxId, dg.getChildrenMetadata()[0].isLabelMultiset()
));
return Optional.ofNullable(dataGroup).map(dg -> {
final N5SpatialDatasetMetadata firstChild = dg.getChildrenMetadata()[0];
final Boolean isLabelMultiset = firstChild instanceof N5SingleScaleMetadata && ((N5SingleScaleMetadata)firstChild).isLabelMultiset();
return new N5PainteraLabelMultiScaleGroup(
node.getPath(),
dg,
finalUniqueLabelsGroup, finalFragmentSegmentAssignmentGroup, finalLabelToBlockLookupGroup,
maxId, isLabelMultiset
);
});
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/org/janelia/saalfeldlab/paintera/Paintera.kt
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,9 @@ class Paintera : Application() {
internal var debugMode = false

@JvmStatic
val n5Factory = N5FactoryWithCache().apply { cacheAttributes(true) }
val n5Factory = N5FactoryWithCache().apply {
cacheAttributes(true)
}

private val LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ import org.janelia.saalfeldlab.n5.universe.metadata.N5Metadata
import org.janelia.saalfeldlab.n5.universe.metadata.N5SingleScaleMetadata
import org.janelia.saalfeldlab.n5.universe.metadata.N5SpatialDatasetMetadata
import org.janelia.saalfeldlab.n5.universe.metadata.SpatialMultiscaleMetadata
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.NgffSingleScaleAxesMetadata
import org.janelia.saalfeldlab.paintera.Paintera
import org.janelia.saalfeldlab.paintera.state.metadata.MetadataState.Companion.isLabel
import org.janelia.saalfeldlab.paintera.state.metadata.MetadataUtils.Companion.isLabelMultiset
import org.janelia.saalfeldlab.paintera.state.metadata.MetadataUtils.Companion.offset
import org.janelia.saalfeldlab.paintera.state.metadata.MetadataUtils.Companion.resolution
import org.janelia.saalfeldlab.util.n5.ImagesWithTransform
import org.janelia.saalfeldlab.util.n5.N5Data
import org.janelia.saalfeldlab.util.n5.N5Helpers
Expand Down Expand Up @@ -78,20 +82,20 @@ interface MetadataState {

open class SingleScaleMetadataState(
final override var n5ContainerState: N5ContainerState,
final override val metadata: N5SingleScaleMetadata
) :
MetadataState {
override var transform: AffineTransform3D = metadata.spatialTransform3d()
final override val metadata: N5SpatialDatasetMetadata
) : MetadataState {

final override var transform: AffineTransform3D = metadata.spatialTransform3d()
override var isLabelMultiset: Boolean = metadata.isLabelMultiset
override var isLabel: Boolean = isLabel(metadata.attributes.dataType) || metadata.isLabelMultiset
override var datasetAttributes: DatasetAttributes = metadata.attributes
override var minIntensity = metadata.minIntensity()
override var maxIntensity = metadata.maxIntensity()
override var resolution = metadata.pixelResolution!!
override var translation = metadata.offset!!
override var unit = metadata.unit()!!
override var resolution = metadata.resolution
override var translation = metadata.offset
override var unit: String = metadata.unit()
override var reader = n5ContainerState.reader
override val writer :N5Writer?
override val writer: N5Writer?
get() = n5ContainerState.writer

override var group = metadata.path!!
Expand Down Expand Up @@ -129,11 +133,12 @@ open class SingleScaleMetadataState(

open class MultiScaleMetadataState constructor(
override val n5ContainerState: N5ContainerState,
final override val metadata: SpatialMultiscaleMetadata<N5SingleScaleMetadata>
final override val metadata: SpatialMultiscaleMetadata<N5SpatialDatasetMetadata>
) : MetadataState by SingleScaleMetadataState(n5ContainerState, metadata[0]) {

private val highestResMetadata: N5SingleScaleMetadata = metadata[0]
override var transform: AffineTransform3D = metadata.spatialTransform3d()
private val highestResMetadata: N5SpatialDatasetMetadata = metadata[0]
final override var transform: AffineTransform3D = metadata.spatialTransform3d()
final override var isLabelMultiset: Boolean = metadata[0].isLabelMultiset
override var isLabel: Boolean = isLabel(highestResMetadata.attributes.dataType) || isLabelMultiset
override var resolution: DoubleArray = transform.run { doubleArrayOf(get(0, 0), get(1, 1), get(2, 2)) }
override var translation: DoubleArray = transform.translation
Expand Down Expand Up @@ -180,8 +185,7 @@ open class MultiScaleMetadataState constructor(
class PainteraDataMultiscaleMetadataState constructor(
n5ContainerState: N5ContainerState,
var painteraDataMultiscaleMetadata: N5PainteraDataMultiScaleGroup
) :
MultiScaleMetadataState(n5ContainerState, painteraDataMultiscaleMetadata) {
) : MultiScaleMetadataState(n5ContainerState, painteraDataMultiscaleMetadata) {

val dataMetadataState = MultiScaleMetadataState(n5ContainerState, painteraDataMultiscaleMetadata.dataGroupMetadata)

Expand All @@ -207,13 +211,33 @@ operator fun <T> SpatialMultiscaleMetadata<T>.get(index: Int): T where T : N5Spa
class MetadataUtils {

companion object {
val N5SpatialDatasetMetadata.isLabelMultiset
get() = when (this) {
is N5SingleScaleMetadata -> isLabelMultiset
else -> false
}

val N5SpatialDatasetMetadata.resolution: DoubleArray
get() = when (this) {
is N5SingleScaleMetadata -> pixelResolution!!
is NgffSingleScaleAxesMetadata -> scale
else -> DoubleArray(this.spatialTransform().numDimensions()) { 1.0 }
}

val N5SpatialDatasetMetadata.offset
get() = when (this) {
is N5SingleScaleMetadata -> offset!!
is NgffSingleScaleAxesMetadata -> translation!!
else -> DoubleArray(this.spatialTransform().numDimensions()) { 0.0 }
}

@JvmStatic
fun metadataIsValid(metadata: N5Metadata?): Boolean {
/* Valid if we are SpatialMultiscaleMetadata whose children are single scale, or we are SingleScale ourselves. */
return (metadata as? SpatialMultiscaleMetadata<*>)?.let {
it.childrenMetadata[0] is N5SingleScaleMetadata
it.childrenMetadata[0] is N5SpatialDatasetMetadata
} ?: run {
metadata is N5SingleScaleMetadata
metadata is N5SpatialDatasetMetadata
}
}

Expand All @@ -222,16 +246,16 @@ class MetadataUtils {
@Suppress("UNCHECKED_CAST")
return Optional.ofNullable(
(metadata as? N5PainteraDataMultiScaleGroup)?.let { PainteraDataMultiscaleMetadataState(n5ContainerState, it) }
?: (metadata as? SpatialMultiscaleMetadata<N5SingleScaleMetadata>)?.let { MultiScaleMetadataState(n5ContainerState, it) }
?: (metadata as? N5SingleScaleMetadata)?.let { SingleScaleMetadataState(n5ContainerState, it) }
?: (metadata as? SpatialMultiscaleMetadata<N5SpatialDatasetMetadata>)?.let { MultiScaleMetadataState(n5ContainerState, it) }
?: (metadata as? N5SpatialDatasetMetadata)?.let { SingleScaleMetadataState(n5ContainerState, it) }
)
}

@JvmStatic
fun createMetadataState(n5containerAndDataset: String): Optional<MetadataState> {

val reader = with(Paintera.n5Factory) {
openWriterOrNull(n5containerAndDataset) ?: openReaderOrNull(n5containerAndDataset)?: return Optional.empty()
val reader = with(Paintera.n5Factory) {
openWriterOrNull(n5containerAndDataset) ?: openReaderOrNull(n5containerAndDataset) ?: return Optional.empty()
}

val n5ContainerState = N5ContainerState(reader)
Expand All @@ -246,8 +270,8 @@ class MetadataUtils {

@JvmStatic
fun createMetadataState(n5container: String, dataset: String?): Optional<MetadataState> {
val reader = with(Paintera.n5Factory) {
openWriterOrNull(n5container) ?: openReaderOrNull(n5container)?: return Optional.empty()
val reader = with(Paintera.n5Factory) {
openWriterOrNull(n5container) ?: openReaderOrNull(n5container) ?: return Optional.empty()
}

val n5ContainerState = N5ContainerState(reader)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class CreateDataset(private val currentSource: Source<*>?, vararg allSources: So
blockSize.asIntArray(),
resolution.asDoubleArray(),
offset.asDoubleArray(),
scaleLevels.stream().map { it.downsamplingFactors() }.toList().toTypedArray(),
scaleLevels.map { it.downsamplingFactors() }.toTypedArray(),
scaleLevels.stream().mapToInt { it.maxNumEntries() }.toArray()
)

Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/org/janelia/saalfeldlab/util/n5/N5Helpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.janelia.saalfeldlab.n5.hdf5.N5HDF5Reader
import org.janelia.saalfeldlab.n5.universe.N5DatasetDiscoverer
import org.janelia.saalfeldlab.n5.universe.N5TreeNode
import org.janelia.saalfeldlab.n5.universe.metadata.*
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.OmeNgffMetadataParser
import org.janelia.saalfeldlab.paintera.Paintera.Companion.n5Factory
import org.janelia.saalfeldlab.paintera.control.assignment.FragmentSegmentAssignmentOnlyLocal
import org.janelia.saalfeldlab.paintera.control.assignment.FragmentSegmentAssignmentOnlyLocal.NoInitialLutAvailable
Expand All @@ -50,7 +51,6 @@ import org.janelia.saalfeldlab.util.n5.universe.N5ContainerDoesntExist
import org.slf4j.LoggerFactory
import java.io.IOException
import java.lang.invoke.MethodHandles
import java.nio.file.Paths
import java.util.*
import java.util.List
import java.util.concurrent.ExecutorService
Expand Down Expand Up @@ -88,6 +88,7 @@ object N5Helpers {
private val LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())

private val GROUP_PARSERS = List.of<N5MetadataParser<*>>(
OmeNgffMetadataParser(),
PainteraRawMultiScaleParser(),
PainteraLabelMultiScaleParser(),
PainteraDataMultiScaleParser(),
Expand Down
Loading
Loading