From dec9c076af9036d4db591b5210f721117e6b8c9f Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Tue, 12 Dec 2023 16:34:28 -0500 Subject: [PATCH 1/5] feat: convenience method for ngff metadata creation --- .../ome/ngff/v04/OmeNgffMetadata.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/main/java/org/janelia/saalfeldlab/n5/universe/metadata/ome/ngff/v04/OmeNgffMetadata.java b/src/main/java/org/janelia/saalfeldlab/n5/universe/metadata/ome/ngff/v04/OmeNgffMetadata.java index 7eb4e6b..55c052e 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/universe/metadata/ome/ngff/v04/OmeNgffMetadata.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/universe/metadata/ome/ngff/v04/OmeNgffMetadata.java @@ -1,6 +1,12 @@ package org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04; import org.janelia.saalfeldlab.n5.universe.metadata.MultiscaleMetadata; +import org.janelia.saalfeldlab.n5.universe.metadata.axes.Axis; +import org.janelia.saalfeldlab.n5.universe.metadata.axes.AxisUtils; +import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.OmeNgffMultiScaleMetadata.OmeNgffDataset; +import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.CoordinateTransformation; +import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.ScaleCoordinateTransformation; +import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.TranslationCoordinateTransformation; public class OmeNgffMetadata extends MultiscaleMetadata { @@ -13,4 +19,56 @@ public OmeNgffMetadata( final String path, final OmeNgffMultiScaleMetadata[] mul this.multiscales = multiscales; } + /** + * Creates an OmeNgffMetadata object for writing. + * See {@link AxisUtils#defaultAxes(String...)} for convenient creation of axes. + * + * @param numDimensions number of dimensions + * @param name a name for this dataset + * @param axes an array of axes (length numDimensions) + * @param scalePaths relative paths to children containing scale level arrays + * @param scales array of absolute resolutions. size: [numScales][numDimensions] + * @param translations array of translations. size: [numScales][numDimensions]. May be null. + * @return OmeNgffMetadata + */ + public static OmeNgffMetadata buildForWriting( final int numDimensions, + final String name, + final Axis[] axes, + final String[] scalePaths, + final double[][] scales, + final double[][] translations) { + + assert scalePaths.length == scales.length; + + if( translations != null ) + assert scalePaths.length == translations.length; + + final int numScales = scalePaths.length; + final String version = "0.4"; + final String type = ""; + final OmeNgffDataset[] datasets = new OmeNgffDataset[numScales]; + for( int i = 0; i < numScales; i++ ) { + + final ScaleCoordinateTransformation s = new ScaleCoordinateTransformation(scales[i]); + TranslationCoordinateTransformation t = null; + if( translations != null && translations[i] != null ) + t = new TranslationCoordinateTransformation(translations[i]); + + datasets[i] = new OmeNgffDataset(); + datasets[i].path = scalePaths[i]; + datasets[i].coordinateTransformations = t == null ? + new CoordinateTransformation[]{ s } : + new CoordinateTransformation[]{ s, t }; + } + + final CoordinateTransformation[] cts = null; + final OmeNgffMultiScaleMetadata ms = new OmeNgffMultiScaleMetadata( + numDimensions, "", name, + type, version, axes, + datasets, null, cts, null); + + + return new OmeNgffMetadata("", new OmeNgffMultiScaleMetadata[]{ ms }); + } + } From 2d7f70b39115175e2bbdddbe053261a4c121c1d8 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Wed, 21 Feb 2024 10:17:00 -0500 Subject: [PATCH 2/5] chore: bump n5-version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a354c6e..b4df038 100644 --- a/pom.xml +++ b/pom.xml @@ -111,7 +111,7 @@ sign,deploy-to-scijava - 3.1.1 + 3.1.3 2.1.0 7.0.0 4.0.2 From 64d8526eceb5b8f71fafeabf1816a238aa1715d2 Mon Sep 17 00:00:00 2001 From: John Bogovic Date: Thu, 22 Feb 2024 10:17:35 -0500 Subject: [PATCH 3/5] test: N5TreeNode.addPath --- .../saalfeldlab/n5/universe/N5TreeNode.java | 2 +- .../n5/universe/N5TreeNodeTest.java | 64 +++++++++++++------ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/janelia/saalfeldlab/n5/universe/N5TreeNode.java b/src/main/java/org/janelia/saalfeldlab/n5/universe/N5TreeNode.java index 81acef3..f4bc1f1 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/universe/N5TreeNode.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/universe/N5TreeNode.java @@ -128,8 +128,8 @@ public N5TreeNode addPath( final String path ) { * @return the node */ public N5TreeNode addPath( final String path, Function constructor ) { - final String normPath = removeLeadingSlash(path); + final String normPath = removeLeadingSlash(path); if( !getPath().isEmpty() && !normPath.startsWith(getPath())) return null; diff --git a/src/test/java/org/janelia/saalfeldlab/n5/universe/N5TreeNodeTest.java b/src/test/java/org/janelia/saalfeldlab/n5/universe/N5TreeNodeTest.java index 38738db..b4da5b3 100644 --- a/src/test/java/org/janelia/saalfeldlab/n5/universe/N5TreeNodeTest.java +++ b/src/test/java/org/janelia/saalfeldlab/n5/universe/N5TreeNodeTest.java @@ -11,8 +11,8 @@ public class N5TreeNodeTest { @Test - public void testStructureEquals() - { + public void testStructureEquals() { + N5TreeNode empty = new N5TreeNode(""); N5TreeNode a = new N5TreeNode("a"); @@ -49,48 +49,74 @@ public void testStructureEquals() } @Test - public void testAddingChildren() - { + public void testAddingChildren() { + final N5TreeNode control = new N5TreeNode(""); final N5TreeNode a = new N5TreeNode("a"); final N5TreeNode b = new N5TreeNode("a/b"); final N5TreeNode c = new N5TreeNode("a/b/c"); final N5TreeNode ant = new N5TreeNode("ant"); final N5TreeNode bat = new N5TreeNode("ant/bat"); - control.add( a ); - a.add( b ); - b.add( c ); + control.add(a); + a.add(b); + b.add(c); final N5TreeNode root = new N5TreeNode(""); root.addPath("a/b/c"); - assertTrue( root.getDescendant("a/b/c").isPresent() ); + assertTrue(root.getDescendant("a/b/c").isPresent()); // make sure the tree has expected structure - assertTrue( root.structureEquals(control)); - assertEquals( 4, N5TreeNode.flattenN5Tree(root).count() ); + assertTrue(root.structureEquals(control)); + assertEquals(4, N5TreeNode.flattenN5Tree(root).count()); root.add(new N5TreeNode("ant")); - assertTrue( root.getDescendant("ant").isPresent() ); - + assertTrue(root.getDescendant("ant").isPresent()); control.add(ant); ant.add(bat); root.addPath("ant/bat"); - assertTrue( root.getDescendant("ant/bat").isPresent() ); + assertTrue(root.getDescendant("ant/bat").isPresent()); // make sure the tree has expected structure - assertTrue( root.structureEquals(control)); - assertEquals( 6, N5TreeNode.flattenN5Tree(root).count() ); + assertTrue(root.structureEquals(control)); + assertEquals(6, N5TreeNode.flattenN5Tree(root).count()); // ensure children can be added from nodes that are not the root final N5TreeNode c0Node = new N5TreeNode("c0"); root.add(c0Node); c0Node.addPath("c0/s0"); - assertTrue( root.getDescendant("c0/s0").isPresent() ); + assertTrue(root.getDescendant("c0/s0").isPresent()); // ensure no new nodes are added when trying to add invalid path - assertEquals( 2, N5TreeNode.flattenN5Tree(c0Node).count() ); - assertNull( c0Node.addPath("x/y/z") ); - assertEquals( 2, N5TreeNode.flattenN5Tree(c0Node).count() ); + assertEquals(2, N5TreeNode.flattenN5Tree(c0Node).count()); + assertNull(c0Node.addPath("x/y/z")); + assertEquals(2, N5TreeNode.flattenN5Tree(c0Node).count()); + } + + @Test + public void testAddPath() { + + final N5TreeNode root = new N5TreeNode(""); + + root.addPath("a"); + assertTrue(root.getDescendant("a").isPresent()); + assertFalse(root.getDescendant("a/b").isPresent()); + + root.removeAllChildren(); + assertFalse(root.getDescendant("a").isPresent()); + assertFalse(root.getDescendant("a/b").isPresent()); + + root.addPath("a/b"); + assertTrue(root.getDescendant("a").isPresent()); + assertTrue(root.getDescendant("a/b").isPresent()); + + // add path to non-root node + final N5TreeNode a = new N5TreeNode("a"); + a.addPath("a/b"); + assertTrue(a.getDescendant("a/b").isPresent()); + + a.addPath("c"); + // not added because the added path is not a child of "a" + assertFalse(a.getDescendant("a/c").isPresent()); } } From 50ceb0ac4eee4031221f5cf9d038c09af550d89c Mon Sep 17 00:00:00 2001 From: Sugawara Ko <36190671+ksugar@users.noreply.github.com> Date: Sat, 24 Feb 2024 23:29:24 +0900 Subject: [PATCH 4/5] fix: support port number in URI (#10) Properly handle a URI with port number. (e.g. locally hosted MinIO server) --- .../java/org/janelia/saalfeldlab/n5/universe/N5Factory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/janelia/saalfeldlab/n5/universe/N5Factory.java b/src/main/java/org/janelia/saalfeldlab/n5/universe/N5Factory.java index 000edd4..e2e2039 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/universe/N5Factory.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/universe/N5Factory.java @@ -234,7 +234,7 @@ private AmazonS3 createS3(final String uri) { // if AmazonS3URI does not like the form of the uri try { final URI buri = new URI(uri); - final URI endpointUrl = new URI(buri.getScheme(), buri.getHost(), null, null); + final URI endpointUrl = new URI(buri.getScheme(), null, buri.getHost(), buri.getPort(), null, null, null); return createS3(getS3Credentials(), new EndpointConfiguration(endpointUrl.toString(), null), null, getS3Bucket(uri)); } catch (final URISyntaxException e1) {} } From 5f3b04317113ce8ffabad891010220995a9f4430 Mon Sep 17 00:00:00 2001 From: Stephan Saalfeld Date: Sat, 24 Feb 2024 09:31:52 -0500 Subject: [PATCH 5/5] Bump to next development cycle Signed-off-by: Stephan Saalfeld --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b4df038..80b1294 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.janelia.saalfeldlab n5-universe - 1.3.2-SNAPSHOT + 1.3.3-SNAPSHOT N5-Universe Utilities spanning all of the N5 repositories