Skip to content

Commit

Permalink
fix(ngff): do not reverse axes for fOrder zarr arrays
Browse files Browse the repository at this point in the history
* add test
  • Loading branch information
bogovicj committed May 3, 2024
1 parent 94c129a commit a3cd67f
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.CoordinateTransformation;
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.CoordinateTransformationAdapter;
import org.janelia.saalfeldlab.n5.zarr.ZarrDatasetAttributes;
import org.janelia.saalfeldlab.n5.zarr.ZarrKeyValueReader;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Expand Down Expand Up @@ -84,7 +85,6 @@ public Optional<OmeNgffMetadata> parseMetadata(final N5Reader n5, final N5TreeNo

final OmeNgffMultiScaleMetadata ms = multiscales[j];

// ms.path = node.getPath();
final String[] paths = ms.getPaths();
final DatasetAttributes[] attrs = new DatasetAttributes[ms.getPaths().length];

Expand All @@ -94,14 +94,20 @@ public Optional<OmeNgffMetadata> parseMetadata(final N5Reader n5, final N5TreeNo
attrs[i] = dsetMeta[i].getAttributes();
}

// final NgffSingleScaleAxesMetadata[] msChildrenMeta = ms.buildChildren(nd, attrs, ms.coordinateTransformations, ms.axes);
// if zarr is used for storage, and arrays are stored in F-order, axes should not be reversed
// reverse Axes if C-order where "row major" == C-order in this context.
boolean reverseAxes = true;
if( n5 instanceof ZarrKeyValueReader)
reverseAxes = cOrder(dsetMeta[0].getAttributes());

final NgffSingleScaleAxesMetadata[] msChildrenMeta = OmeNgffMultiScaleMetadata.buildMetadata(
nd, node.getPath(), ms.datasets, attrs, ms.coordinateTransformations, ms.metadata, ms.axes);

MetadataUtils.updateChildrenMetadata(node, msChildrenMeta, false);

// axes need to be flipped after the child is created
ArrayUtils.reverse(ms.axes);
if (reverseAxes)
ArrayUtils.reverse(ms.axes);

multiscales[j] = new OmeNgffMultiScaleMetadata( ms, msChildrenMeta );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ public void testCoordinateTransformParsing() {
final N5Reader zarr = new N5Factory().openReader(rootF.toString());

final OmeNgffMetadataParser grpParser = new OmeNgffMetadataParser();
test(grpParser.parseMetadata(zarr, setupNode("coordTforms/ss", "s0")),
test(grpParser.parseMetadata(zarr, setupNode(zarr, "coordTforms/ss", "s0")),
new double[]{4, 4},
new double[]{0, 0});

test(grpParser.parseMetadata(zarr, setupNode("coordTforms/st", "s0")),
test(grpParser.parseMetadata(zarr, setupNode(zarr, "coordTforms/st", "s0")),
new double[]{2, 2},
new double[]{10, 10});

test(grpParser.parseMetadata(zarr, setupNode("coordTforms/ts", "s0")),
test(grpParser.parseMetadata(zarr, setupNode(zarr, "coordTforms/ts", "s0")),
new double[]{2, 2},
new double[]{20, 20});

test(grpParser.parseMetadata(zarr, setupNode("coordTforms/tt", "s0")),
test(grpParser.parseMetadata(zarr, setupNode(zarr, "coordTforms/tt", "s0")),
new double[]{1, 1},
new double[]{20, 20});
}
Expand All @@ -61,12 +61,17 @@ private void test(final Optional<OmeNgffMetadata> metaOpt, final double[] expect
assertArrayEquals(expectedTranslation, tform.getTranslationCopy(), EPS);
}

private N5TreeNode setupNode(final String path, final String childPath) {
protected static N5TreeNode setupNode(final N5Reader n5, final String path, final String childPath) {

final String absoluteChildPath = path + "/" + childPath;
final N5TreeNode node = new N5TreeNode(path);
final N5TreeNode child = new N5TreeNode(path + "/" + childPath);
final DatasetAttributes attrs = new DatasetAttributes(new long[]{4, 4}, new int[]{4, 4}, DataType.UINT8, new RawCompression());
child.setMetadata(new N5SingleScaleMetadata(path + "/" + childPath, new AffineTransform3D(),
final N5TreeNode child = new N5TreeNode(absoluteChildPath);

DatasetAttributes attrs = n5.getDatasetAttributes(absoluteChildPath);
if (attrs == null) // add dummy attributes of non are present
attrs = new DatasetAttributes(new long[]{4, 4}, new int[]{4, 4}, DataType.UINT8, new RawCompression());

child.setMetadata(new N5SingleScaleMetadata(absoluteChildPath, new AffineTransform3D(),
new double[]{1, 1}, new double[]{1, 1}, new double[]{0, 0}, "", attrs, false));

node.add(child);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;

import java.net.URI;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Optional;

import org.apache.commons.lang3.ArrayUtils;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.universe.N5Factory;
import org.janelia.saalfeldlab.n5.universe.N5TreeNode;
import org.janelia.saalfeldlab.n5.universe.metadata.axes.Axis;
import org.janelia.saalfeldlab.n5.universe.metadata.axes.AxisUtils;
import org.junit.Test;
Expand Down Expand Up @@ -84,4 +94,36 @@ public void testSpatial3D() {
st5.getRowPackedCopy(), 1e-9);
}

@Test
public void testAxisOrderStorageOrder() {

URI rootF = Paths.get("src", "test", "resources", "metadata.zarr").toUri();
final N5Reader zarr = new N5Factory().openReader(rootF.toString());

final String[] names = new String[]{"c", "x", "y", "z"};

final OmeNgffMetadataParser parser = new OmeNgffMetadataParser();

// no not flip when f-Order
final N5TreeNode fOrderNode = CoordinateTransformParsingTest.setupNode(zarr, "fOrder", "1");
axisOrderTest(parser.parseMetadata(zarr, fOrderNode), names);

// flip when c-Order
ArrayUtils.reverse(names);
final N5TreeNode cOrderNode = CoordinateTransformParsingTest.setupNode(zarr, "cOrder", "1");
axisOrderTest(parser.parseMetadata(zarr, cOrderNode), names);
}

private void axisOrderTest(final Optional<OmeNgffMetadata> metaOpt, final String[] expectedNames) {

assertTrue("ss not parsable", metaOpt.isPresent());

final OmeNgffMetadata meta = metaOpt.get();
assertTrue("no multiscales found", meta.multiscales.length > 0);

final Axis[] axes = meta.multiscales[0].axes;
final String[] names = Arrays.stream(axes).map(a -> a.getName()).toArray(N -> new String[N]);
assertArrayEquals("names don't match", expectedNames, names);
}

}
44 changes: 44 additions & 0 deletions src/test/resources/metadata.zarr/cOrder/.zattrs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"multiscales": [
{
"version": "0.4",
"axes": [
{
"name": "c",
"type": "channel"
},
{
"name": "x",
"type": "space",
"unit": "nanometer"
},
{
"name": "y",
"type": "space",
"unit": "nanometer"
},
{
"name": "z",
"type": "space",
"unit": "nanometer"
}
],
"datasets": [
{
"path": "1",
"coordinateTransformations": [
{
"type": "scale",
"scale": [
1.0,
11.239999771118164,
11.239999771118164,
28.0
]
}
]
}
]
}
]
}
1 change: 1 addition & 0 deletions src/test/resources/metadata.zarr/cOrder/.zgroup
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"zarr_format":2}
16 changes: 16 additions & 0 deletions src/test/resources/metadata.zarr/cOrder/1/.zarray
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"chunks": [ 1, 32, 32, 32 ],
"compressor": {
"blocksize": 0,
"clevel": 3,
"cname": "zstd",
"id": "blosc",
"shuffle": 1
},
"dtype": "|u1",
"fill_value": 0,
"filters": null,
"order": "C",
"shape": [ 1, 4096, 4096, 1536 ],
"zarr_format": 2
}
44 changes: 44 additions & 0 deletions src/test/resources/metadata.zarr/fOrder/.zattrs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"multiscales": [
{
"version": "0.4",
"axes": [
{
"name": "c",
"type": "channel"
},
{
"name": "x",
"type": "space",
"unit": "nanometer"
},
{
"name": "y",
"type": "space",
"unit": "nanometer"
},
{
"name": "z",
"type": "space",
"unit": "nanometer"
}
],
"datasets": [
{
"path": "1",
"coordinateTransformations": [
{
"type": "scale",
"scale": [
1.0,
11.239999771118164,
11.239999771118164,
28.0
]
}
]
}
]
}
]
}
1 change: 1 addition & 0 deletions src/test/resources/metadata.zarr/fOrder/.zgroup
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"zarr_format":2}
16 changes: 16 additions & 0 deletions src/test/resources/metadata.zarr/fOrder/1/.zarray
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"chunks": [ 1, 32, 32, 32 ],
"compressor": {
"blocksize": 0,
"clevel": 3,
"cname": "zstd",
"id": "blosc",
"shuffle": 1
},
"dtype": "|u1",
"fill_value": 0,
"filters": null,
"order": "F",
"shape": [ 1, 4096, 4096, 1536 ],
"zarr_format": 2
}

0 comments on commit a3cd67f

Please sign in to comment.