/*- * Copyright 2015 Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.dawnsci.nexus.file; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.net.URI; import java.util.Arrays; import org.eclipse.dawnsci.analysis.api.tree.Attribute; import org.eclipse.dawnsci.analysis.api.tree.DataNode; import org.eclipse.dawnsci.analysis.api.tree.GroupNode; import org.eclipse.dawnsci.analysis.api.tree.SymbolicNode; import org.eclipse.dawnsci.analysis.tree.impl.DataNodeImpl; import org.eclipse.dawnsci.analysis.tree.impl.GroupNodeImpl; import org.eclipse.dawnsci.analysis.tree.impl.SymbolicNodeImpl; import org.eclipse.dawnsci.nexus.NexusException; import org.eclipse.dawnsci.nexus.NexusFile; import org.eclipse.dawnsci.nexus.NexusUtils; import org.eclipse.dawnsci.nexus.TestUtils; import org.eclipse.dawnsci.nexus.test.util.NexusTestUtils; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.DatasetUtils; import org.eclipse.january.dataset.IDataset; import org.eclipse.january.dataset.ILazyWriteableDataset; import org.eclipse.january.dataset.LazyWriteableDataset; import org.eclipse.january.dataset.Random; import org.eclipse.january.dataset.SliceND; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class NexusFileTest { private static String testScratchDirectoryName; private static String FILE_NAME; private static String FILE2_NAME; private NexusFile nf; /** * Creates an empty directory for use by test code. * * @throws Exception if setup fails */ @BeforeClass public static void setUpBeforeClass() throws Exception { testScratchDirectoryName = TestUtils.generateDirectorynameFromClassname(NexusFileTest.class.getCanonicalName()); TestUtils.makeScratchDirectory(testScratchDirectoryName); (new File(testScratchDirectoryName + "origin/")).mkdirs(); (new File(testScratchDirectoryName + "linked/")).mkdirs(); FILE_NAME = testScratchDirectoryName + "test.nxs"; FILE2_NAME = testScratchDirectoryName + "ext-test.nxs"; } @Before public void setUp() throws Exception { nf = NexusTestUtils.createNexusFile(FILE_NAME); } @After public void tearDown() throws Exception { nf.close(); nf = null; } @Test public void testOpenToRead() throws Exception { // create a group and close the file nf.getGroup("/a/b/c", true); nf.close(); // open the file to read and test that the created group is present nf.openToRead(); assertNotNull(nf.getGroup("/a/b/c", false)); } @Test(expected = NexusException.class) public void testOpenToReadTryWrite() throws Exception { // create a group and close the file nf.getGroup("/a/b/c", true); nf.close(); // open the file to read only, and try writing to it, exception should be thrown nf.openToRead(); nf.getGroup("/e/f/g", true); } @Test public void testOpenToWrite() throws Exception { // create a group and close the file nf.getGroup("/a/b/c", true); nf.close(); // open the file to write and check the previously written group is still there nf.openToWrite(false); assertNotNull(nf.getGroup("/a/b/c", false)); // write a new group (would throw an exception if file wasn't writable) nf.getGroup("/e/f/g", true); } @Test public void testCreateAndOpenToWrite() throws Exception { // create a group and close the file nf.getGroup("/a/b/c", true); nf.close(); // create and open the file to write - overwrites the old file nf.createAndOpenToWrite(); try { // try getting the previously created group, should not exist // as createAndOpenToWrite overwrites the old file nf.getGroup("/a/b/c", false); fail("Group should not exist as old file should have been overwritten"); } catch (NexusException e) { // fall through } // try writing a new group nf.getGroup("/e/f/g", true); assertNotNull(nf.getGroup("/e/f/g", false)); } @Test public void testGetPath() throws Exception { final String path = "/a/b/c/"; GroupNode groupNode = nf.getGroup(path, true); assertEquals(path, nf.getPath(groupNode)); } @Test public void testGetGroup() throws Exception { // create a new group GroupNode group = nf.getGroup("/a/b/c", true); assertNotNull(group); // test that the group is a child of its expected parent group GroupNode childGroup = nf.getGroup("/a/b/c", false); GroupNode parentGroup = nf.getGroup("/a/b", false); assertEquals(1, parentGroup.getNames().size()); assertTrue(parentGroup.getNames().contains("c")); assertSame(childGroup, parentGroup.getGroupNode("c")); } @Test(expected = NexusException.class) public void testGetGroupNoCreate() throws Exception { nf.getGroup("/a/b/c/d", false); } @Test public void testGetGroupOfClass() throws Exception { // create a new group of class Nxtext final String className = "NXtext"; GroupNode parentGroup = nf.getGroup("/a/b", true); GroupNode group = nf.getGroup(parentGroup, "c", className, true); assertEquals(className, group.getAttribute("NX_class").getFirstElement()); assertEquals(1, parentGroup.getNames().size()); assertTrue(parentGroup.getNames().contains("c")); } @Test public void testGetRootNode() throws Exception { nf.getGroup("/a/b", true); GroupNode root = nf.getGroup("/", false); assertNotNull(root); assertTrue(root.containsGroupNode("a")); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); root = nf.getGroup("/", false); assertNotNull(root); assertTrue(root.containsGroupNode("a")); } @Test public void testGroupProperties() throws Exception { //Test that the properties on a retrieved node match expectations without having traversed to children nf.getGroup("/a/b/c", true); nf.getGroup("/a/b/x", true); IDataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("d"); nf.createData("/a/b", dataset, false); IDataset attr = DatasetFactory.createFromObject(new int[] {1, 2, 3}); IDataset attr2 = DatasetFactory.createFromObject(new int[] {4, 5}); attr.setName("SomeAttribute"); attr2.setName("Another Attribute"); nf.addAttribute("/a/b", nf.createAttribute(attr)); nf.addAttribute("/a/b/c", nf.createAttribute(attr2)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); GroupNode group = nf.getGroup("/a/b", false); assertTrue(group.containsGroupNode("c")); assertTrue(group.containsGroupNode("x")); assertTrue(group.containsDataNode("d")); assertEquals(group.getDataNode("d").getDataset().getSlice(), dataset); assertTrue(group.containsAttribute("SomeAttribute")); assertEquals(attr, group.getAttribute("SomeAttribute").getValue()); assertTrue(group.getGroupNode("c").containsAttribute("Another Attribute")); assertEquals(attr2, group.getGroupNode("c").getAttribute("Another Attribute").getValue()); //Make sure group has no other children String[] childNames = group.getNames().toArray(new String[] {}); //we could use assertTrue(childNames.contains(...)) but this gives a much better diagnostic on failure Arrays.sort(childNames); assertArrayEquals(childNames, new String[] {"c", "d", "x"}); } @Test public void testDataNodeProperties() throws Exception { IDataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("d"); nf.createData("/a/b", dataset, true); IDataset attr = DatasetFactory.createFromObject(new int[] {12, 3}); attr.setName("SomeAttribute"); nf.addAttribute("/a/b/d", nf.createAttribute(attr)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode dataNode = nf.getData("/a/b/d"); assertNotNull(dataNode); assertEquals(dataset, dataNode.getDataset().getSlice()); Attribute foundAttr = dataNode.getAttribute("SomeAttribute"); assertNotNull(foundAttr); assertEquals(attr, foundAttr.getValue()); } @Test public void testCreateDataPathLazyDataset() throws Exception { int[] shape = { 5, 5 }; ILazyWriteableDataset dataset = new LazyWriteableDataset("data", Dataset.INT32, shape, shape, null, null); DataNode dataNode = nf.createData("/a/b/c", dataset, true); assertNotNull(dataNode); assertSame(dataset, dataNode.getDataset()); GroupNode parentGroup = nf.getGroup("/a/b/c", false); assertSame(dataNode, parentGroup.getDataNode("data")); } @Test public void testCreateDataGroupNodeLazyDataset() throws Exception { GroupNode parentGroup = nf.getGroup("/a/b/c", true); int[] shape = { 5, 5 }; ILazyWriteableDataset dataset = new LazyWriteableDataset("data", Dataset.INT32, shape, shape, null, null); DataNode dataNode = nf.createData(parentGroup, dataset); assertNotNull(dataNode); assertSame(dataset, dataNode.getDataset()); assertSame(dataNode, parentGroup.getDataNode("data")); } @Test public void testCreateDataPathDataset() throws Exception { Dataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("data"); DataNode dataNode = nf.createData("/a/b/c", dataset, true); assertNotNull(dataNode); assertSame(dataset, dataNode.getDataset()); GroupNode parentGroup = nf.getGroup("/a/b/c", false); assertSame(dataNode, parentGroup.getDataNode("data")); } @Test public void testCreateDataGroupNodeDataset() throws Exception { GroupNode parentGroup = nf.getGroup("/a/b/c", true); Dataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("data"); DataNode dataNode = nf.createData(parentGroup, dataset); assertNotNull(dataNode); assertSame(dataset, dataNode.getDataset()); assertSame(dataNode, parentGroup.getDataNode("data")); } @Test public void testGetDataWithAugmentedPath() throws Exception { GroupNode parentNode = nf.getGroup("/entry1:NXentry/instrument:NXinstrument/detector:NXdetector", true); IDataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("data"); nf.createData(parentNode, dataset); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); GroupNode readNode = nf.getGroup("/entry1/instrument/detector", false); assertTrue(readNode.containsDataNode("data")); DataNode readDataNode = nf.getData("/entry1:NXentry/instrument:NXinstrument/detector:NXdetector/data"); assertSame(readNode.getDataNode("data"), readDataNode); IDataset readData = readDataNode.getDataset().getSlice(); assertEquals(dataset, readData); } @Test public void testAddAttributeNode() throws Exception { Dataset attribDataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); attribDataset.setName("testAttribute"); GroupNode node = nf.getGroup("/a/b/c", true); Attribute attribute = nf.createAttribute(attribDataset); assertNotNull(attribute); nf.addAttribute(node, attribute); assertNotNull(node.getAttribute("testAttribute")); assertSame(attribute, node.getAttribute("testAttribute")); } @Test public void testAddAttributePath() throws Exception { Dataset attribDataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); attribDataset.setName("testAttribute"); Dataset attrib2Dataset = DatasetFactory.createRange(6, Dataset.INT64).reshape(3, 2); attrib2Dataset.setName("testAttribute2"); GroupNode node = nf.getGroup("/a/b/c", true); Attribute attribute = nf.createAttribute(attribDataset); assertNotNull(attribute); nf.addAttribute(node, attribute); Attribute attribute2 = nf.createAttribute(attrib2Dataset); assertNotNull(attribute2); nf.addAttribute(node, attribute2); assertNotNull(node.getAttribute("testAttribute")); assertSame(attribute, node.getAttribute("testAttribute")); assertNotNull(node.getAttribute("testAttribute2")); assertSame(attribute2, node.getAttribute("testAttribute2")); } @Test public void testReadbackDoubleArrayAttribute() throws Exception { GroupNode group = nf.getGroup("/a/b", true); IDataset attrData = DatasetFactory.createRange(12.0, Dataset.FLOAT64).reshape(3, 4); attrData.setName("attribute"); nf.addAttribute(group, nf.createAttribute(attrData)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); group = nf.getGroup("/a/b", false); Attribute attr = group.getAttribute("attribute"); assertNotNull(attr); IDataset readData = attr.getValue(); assertNotNull(readData); assertEquals(attrData, readData); } @Test public void testReadbackStringAttribute() throws Exception { GroupNode group = nf.getGroup("/a/b", true); IDataset attrString = DatasetFactory.createFromObject("SomeÅttributeString"); attrString.setName("test"); nf.addAttribute(group, nf.createAttribute(attrString)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); group = nf.getGroup("/a/b", false); Attribute attr = group.getAttribute("test"); assertNotNull(attr); if (attrString.getRank() == 0) { // TODO //Hack around the current ambiguity between scalar datasets (rank 0) and single element arrays // attrString.resize(new int[] {1}); } assertEquals(attrString, attr.getValue()); } @Test public void testReadbackStringArrayAttribute() throws Exception { GroupNode group = nf.getGroup("/a/b", true); IDataset attrString = DatasetFactory.createFromObject(new String[] {"A String", "String1", "SomeÅttributeString", "String2"}).reshape(2,2); attrString.setName("test"); nf.addAttribute(group, nf.createAttribute(attrString)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); group = nf.getGroup("/a/b", false); Attribute attr = group.getAttribute("test"); assertNotNull(attr); assertEquals(attrString, attr.getValue()); } @Test public void testOverwritingAttribute() throws Exception { GroupNode group = nf.getGroup("/a", true); IDataset attr = DatasetFactory.createFromObject(new int[] {1, 2}); attr.setName("test"); nf.addAttribute(group, nf.createAttribute(attr)); IDataset attr2 = DatasetFactory.createFromObject(new int[] {3, 4, 5}); attr2.setName("test"); nf.addAttribute(group, nf.createAttribute(attr2)); nf.close(); nf = NexusTestUtils.openNexusFile(FILE_NAME); group = nf.getGroup("/a", true); assertTrue(group.containsAttribute("test")); assertEquals(attr2, group.getAttribute("test").getValue()); IDataset attr3 = DatasetFactory.createFromObject(new String[] {"test attribute"}); attr3.setName("test"); nf.addAttribute(group, nf.createAttribute(attr3)); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); group = nf.getGroup("/a", true); assertTrue(group.containsAttribute("test")); assertEquals(attr3, group.getAttribute("test").getValue()); } @Test public void testLink() throws Exception { nf.getGroup("/a/b/c/d", true); nf.link("/a/b/c", "/f/g"); GroupNode linkedGroup = nf.getGroup("/f/g", false); assertNotNull(linkedGroup); assertNotNull(linkedGroup.getGroupNode("d")); } @Test public void testHardLinkDataset() throws Exception { IDataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("data"); nf.createData("/a/", dataset, true); nf.link("/a/data", "/x/data"); DataNode dataNode = nf.getData("/a/data"); DataNode linkedNode = nf.getData("/x/data"); assertSame(linkedNode, nf.getData("/a/data")); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); dataNode = nf.getData("/a/data"); linkedNode = nf.getData("/x/data"); assertNotNull(linkedNode); assertNotNull(linkedNode.getDataset().getSlice()); assertSame(dataNode, linkedNode); } @Test public void testTargetAttributeAfterLink() throws Exception { nf.getGroup("/a/", true); nf.getGroup("/x/y", true); nf.link("/x/y", "/a/b"); GroupNode b = nf.getGroup("/a/b", false); assertTrue(b.containsAttribute("target")); IDataset attrData = b.getAttribute("target").getValue(); IDataset expected = DatasetFactory.createFromObject("/x/y"); expected.setName("target"); assertEquals(expected, attrData); } @Test public void testLinkExternal() throws Exception { try (NexusFile extFile = NexusTestUtils.createNexusFile(FILE2_NAME)) { extFile.getGroup("/d/e/f/g", true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#/d/e"), "/a/b/c", true); GroupNode groupC = nf.getGroup("/a/b/c", false); GroupNode groupF = nf.getGroup(groupC, "f", null, false); GroupNode groupG = nf.getGroup(groupF, "g", null, false); assertNotNull(groupG); assertSame(groupG, nf.getGroup("/a/b/c/f/g", false)); } @Test public void testLinkExternalNonExistent() throws Exception { nf.linkExternal(new URI("nxfile://NOT_REAL.nxs#/d/e"), "/a/b/c", true); nf.getGroup("/a/b", false); } @Test public void testLinkExternalUnderRoot() throws Exception { try (NexusFile extFile = NexusTestUtils.createNexusFile(FILE2_NAME)) { extFile.getGroup("/d", true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#/d"), "/a", true); assertNotNull(nf.getGroup("/a", false)); } @Test public void testLinkExternalUseSourceName() throws Exception { try (NexusFile extFile = NexusTestUtils.createNexusFile(FILE2_NAME)) { extFile.getGroup("/e/f/g", true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#e"), "/a/b/c/d/", true); GroupNode groupD = nf.getGroup("/a/b/c/d", false); GroupNode groupE = nf.getGroup(groupD, "e", null, false); assertNotNull(groupE); } @Test public void testLinkExternalDatasetUseGivenName() throws Exception { IDataset externalData = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); externalData.setName("data"); try (NexusFile ef = NexusTestUtils.createNexusFile(FILE2_NAME)) { ef.createData("/a/b/c", externalData, true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#a/b/c/data"), "/x/y/linkedData", false); DataNode dataNode = nf.getData("/x/y/linkedData"); IDataset linkedData = dataNode.getDataset().getSlice(); assertNotNull(linkedData); assertEquals(externalData, linkedData); } @Test public void testLinkExternalDatasetUseSourceName() throws Exception { IDataset externalData = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); externalData.setName("data"); try (NexusFile ef = NexusTestUtils.createNexusFile(FILE2_NAME)) { ef.createData("/a/b/c", externalData, true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#a/b/c/data"), "/x/y/", false); DataNode dataNode = nf.getData("/x/y/data"); IDataset linkedData = dataNode.getDataset().getSlice(); assertNotNull(linkedData); assertEquals(externalData, linkedData); } @Test public void testLinkExternalSameFile() throws Exception { //"soft link" implementation nf.getGroup("/a/b/c", true); nf.linkExternal(new URI("#/a/b"), "/x", true); GroupNode groupXC = nf.getGroup("/x/c", false); GroupNode groupABC = nf.getGroup("/a/b/c", false); assertNotNull(groupXC); assertSame(groupXC, groupABC); } @Test public void testSoftLinkDataset() throws Exception { IDataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("data"); nf.createData("/a/", dataset, true); nf.linkExternal(new URI("#/a/data"), "/x/", false); DataNode dataNode = nf.getData("/a/data"); DataNode linkedDataNode = nf.getData("/x/data"); assertSame(dataNode, linkedDataNode); } @Test public void testRelativeExternalLink() throws Exception { IDataset externalData = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); externalData.setName("data"); try (NexusFile ef = NexusTestUtils.createNexusFile(FILE2_NAME)) { ef.createData("/a/b/c", externalData, true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME.replaceFirst(testScratchDirectoryName, "") + "#a/b/c/data"), "/x/y/", false); DataNode dataNode = nf.getData("/x/y/data"); IDataset linkedData = dataNode.getDataset().getSlice(); assertNotNull(linkedData); assertEquals(externalData, linkedData); } @Test public void testRelativeExternalLinkPopulateGroup() throws Exception { IDataset externalData = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); externalData.setName("data"); try (NexusFile ef = NexusTestUtils.createNexusFile(FILE2_NAME)) { ef.createData("/a/b/c", externalData, true); } nf.linkExternal(new URI("nxfile://" + FILE2_NAME.replaceFirst(testScratchDirectoryName, "") + "#a/b/c/data"), "/x/y/", false); GroupNode group = nf.getGroup("/x/y", true); assertTrue(group.getNodeNameIterator().hasNext()); DataNode dataNode = group.getDataNode("data"); assertNotNull(dataNode); IDataset linkedData = dataNode.getDataset().getSlice(); assertNotNull(linkedData); assertEquals(externalData, linkedData); } @Test public void testIsPathValid() throws Exception { nf.getGroup("/a/b/c", true); assertTrue(nf.isPathValid("/a/b/c")); assertFalse(nf.isPathValid("/a/b/c/d")); } @Test public void testWritingSimpleStringArray() throws Exception { GroupNode g = nf.getGroup("/entry1:NXentry", true); NexusUtils.write(nf, g, "stringarray", new String[] {"String", "String Å"}); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode d = nf.getData("/entry1/stringarray"); IDataset ds = d.getDataset().getSlice(); int[] shape = ds.getShape(); assertArrayEquals(new int[] {2}, shape); } @Test public void testWriteSimpleString() throws Exception { GroupNode g = nf.getGroup("/note:NXnote", true); NexusUtils.write(nf, g, "somestring", "MyString"); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode d = nf.getData("/note/somestring"); IDataset ds = d.getDataset().getSlice(); int[] shape = ds.getShape(); assertArrayEquals(new int[] {}, shape); assertEquals("MyString", ds.getString()); } @Test public void testLazyWriteStringArray() throws Exception { int nPoints = 10; GroupNode g = nf.getGroup("/test:NXnote", true); ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("stringarray", Dataset.STRING, new int[] {ILazyWriteableDataset.UNLIMITED}, null, null); nf.createData(g, lazy); nf.close(); for (int i = 0; i < nPoints; i++) { lazy.setSlice(null, DatasetFactory.createFromObject("file" + i), SliceND.createSlice(lazy, new int[] {i}, new int[] {i+1})); } nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode d = nf.getData("/test/stringarray"); IDataset ds = d.getDataset().getSlice(); int[] shape = ds.getShape(); assertArrayEquals(new int[] {nPoints}, shape); for (int i = 0; i < nPoints; i++) { assertEquals("file" + i, ds.getString(i)); } } @Test public void testLazyWrite2DInt32Array() throws Exception { GroupNode g = nf.getGroup("/test:NXnote", true); ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("intarray", Dataset.INT32, new int[] {ILazyWriteableDataset.UNLIMITED, 10}, null, null); nf.createData(g, lazy); lazy.setSlice(null, DatasetFactory.createFromObject(new int[] {-1, -1, -1, -1}).reshape(2, 2), new int[] {0, 0}, new int[] {2, 2}, null); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode node = nf.getData("/test/intarray"); Dataset data = DatasetUtils.convertToDataset(node.getDataset().getSlice(new int[] {0, 0}, new int[] {2, 2}, new int[] {1, 1})); assertArrayEquals(new int[] {-1, -1, -1, -1}, (int[]) data.getBuffer()); } @Test public void testLazyWrite2DDoubleArray() throws Exception { GroupNode g = nf.getGroup("/test:NXnote", true); ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("doublearray", Dataset.FLOAT64, new int[] {ILazyWriteableDataset.UNLIMITED, 10}, null, null); nf.createData(g, lazy); lazy.setSlice(null, DatasetFactory.createFromObject(new double[] {1, 2, 3, 4}).reshape(2, 2), new int[] {0, 0}, new int[] {2, 2}, null); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode node = nf.getData("/test/doublearray"); Dataset data = DatasetUtils.convertToDataset(node.getDataset().getSlice(new int[] {0, 0}, new int[] {2, 2}, new int[] {1, 1})); assertArrayEquals(new double[] {1, 2, 3, 4}, (double[]) data.getBuffer(), 1e-12); } @Test public void testLazyRelativeWriteSpeed() throws Exception { ILazyWriteableDataset lazy3 = createLazyDouble(3); ILazyWriteableDataset lazy4 = createLazyDouble(4); ILazyWriteableDataset lazy5 = createLazyDouble(5); ILazyWriteableDataset lazy8 = createLazyDouble(8); nf.close(); IDataset image = Random.rand(1024,1024); long diff3 = checkWrite(lazy3, image); long diff4 = checkWrite(lazy4, image); long diff5 = checkWrite(lazy5, image); long diff8 = checkWrite(lazy8, image); long perf = Math.max(20,diff3*2); assertTrue(diff4<perf); // Might not be with default chunking. assertTrue(diff5<perf); // Might not be with default chunking. assertTrue(diff8<perf); // Might not be with default chunking. } private long checkWrite(ILazyWriteableDataset lazy, IDataset image) throws Exception { int size = lazy.getShape().length; int[] start = new int[size]; int[] end = new int[size]; for (int i = 0; i < size; i++) { start[i]=0; end[i]=1; } end[end.length-2] = 1024; end[end.length-1] = 1024; long before = System.currentTimeMillis(); lazy.setSlice(null, image, start, end, null); long after = System.currentTimeMillis(); long diff = after-before; System.out.println("Writing 1 image in "+size+"D stack took: "+diff+" ms"); return diff; } private ILazyWriteableDataset createLazyDouble(int size) throws NexusException { GroupNode group = nf.getGroup("/test_"+size+"D:NXnote", true); int[] max = new int[size]; int[]chunk = new int[size]; for (int i = 0; i < size-2; i++) { max[i]=ILazyWriteableDataset.UNLIMITED; chunk[i]=1; } max[max.length-2] = 1024; max[max.length-1] = 1024; chunk[max.length-2] = 1024; chunk[max.length-1] = 1024; final ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("doublearray", Dataset.FLOAT64, max, null, chunk); nf.createData(group, lazy); return lazy; } @Test public void testLazyWrite2DStringArray() throws Exception { GroupNode g = nf.getGroup("/test:NXnote", true); ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("stringarray", Dataset.STRING, new int[] {2, 10}, new int[] {ILazyWriteableDataset.UNLIMITED, 10}, null); nf.createData(g, lazy); lazy.setSlice(null, DatasetFactory.createFromObject(new String[] {"Value1", "Value2"}).reshape(2, 1), new int[] {2, 0}, new int[] {4, 1}, null); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode node = nf.getData("/test/stringarray"); IDataset data = node.getDataset().getSlice(); assertEquals("Value1", data.getString(2, 0)); } @Test public void testLazyDatasetMaxShape() throws Exception { int[] maxShape = new int[] {ILazyWriteableDataset.UNLIMITED, 10, 100}; ILazyWriteableDataset lazyData = NexusUtils.createLazyWriteableDataset("data", Dataset.INT32, new int[] {10, 10, 10}, maxShape, null); nf.createData("/a/", lazyData, true); nf.close(); nf = NexusTestUtils.openNexusFile(FILE_NAME); ILazyWriteableDataset readData = nf.getData("/a/data").getWriteableDataset(); assertNotNull(readData); assertArrayEquals(maxShape, readData.getMaxShape()); } @Test public void testWriteAfterHardLink() throws Exception { //Have had bugs where writing created a "new" dataset, leaving previously //hard linked nodes un-updated ILazyWriteableDataset lazyData = NexusUtils.createLazyWriteableDataset("c", Dataset.INT32, new int[] {ILazyWriteableDataset.UNLIMITED}, null, null); GroupNode g = nf.getGroup("/a/b", true); nf.createData(g, lazyData); nf.link("/a/b/c", "/x/"); lazyData.setSlice(null, DatasetFactory.createFromObject(1), new int[] {0}, new int[] {1}, null); assertSame(nf.getData("/a/b/c").getDataset(), nf.getData("/x/c").getDataset()); nf.flush(); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); assertEquals(nf.getData("/a/b/c").getDataset(), nf.getData("/x/c").getDataset()); } @Test public void testNxClassGroup() throws Exception { GroupNode g = nf.getGroup("/entry1:NXentry/note:NXnote", true); GroupNode e = nf.getGroup("/entry1", false); Attribute gAttr = g.getAttribute("NX_class"); Attribute eAttr = e.getAttribute("NX_class"); assertNotNull(gAttr); assertArrayEquals(gAttr.getValue().getShape(), new int[] {}); assertEquals(gAttr.getFirstElement(), "NXnote"); assertNotNull(eAttr); assertArrayEquals(eAttr.getValue().getShape(), new int[] {}); assertEquals(eAttr.getFirstElement(), "NXentry"); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); g = nf.getGroup("/entry1:NXentry/note:NXnote", true); e = nf.getGroup("/entry1", false); gAttr = g.getAttribute("NX_class"); eAttr = e.getAttribute("NX_class"); assertNotNull(gAttr); assertArrayEquals(gAttr.getValue().getShape(), new int[] {}); assertEquals(gAttr.getFirstElement(), "NXnote"); assertNotNull(eAttr); assertArrayEquals(eAttr.getValue().getShape(), new int[] {}); assertEquals(eAttr.getFirstElement(), "NXentry"); } @Test public void testRelativeNapiMountToGroup() throws Exception { GroupNode g = nf.getGroup("/e/g", true); Dataset mountData = DatasetFactory.createFromObject(new String[] {"nxfile://" + FILE2_NAME.replaceFirst(testScratchDirectoryName, "") + "#x/y"}); mountData.setName("napimount"); nf.addAttribute( g, nf.createAttribute(mountData) ); nf.close(); nf = NexusTestUtils.createNexusFile(FILE2_NAME); nf.getGroup("/x/y/z", true); nf.close(); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); g = nf.getGroup("/e/g", false); assertTrue(g.containsGroupNode("z")); assertNotNull(nf.getGroup("/e/g/z/", false)); nf.close(); } @Test public void testRelativeNapiMountToDataset() throws Exception { GroupNode g = nf.getGroup("/e/g", true); Dataset mountData = DatasetFactory.createFromObject(new String[] {"nxfile://" + FILE2_NAME.replaceFirst(testScratchDirectoryName, "") + "#x/y/z"}); mountData.setName("napimount"); nf.addAttribute( g, nf.createAttribute(mountData) ); nf.close(); Dataset dummyData = DatasetFactory.createFromObject(new int[] {0, 1, 2}); dummyData.setName("z"); try (NexusFile extFile = NexusTestUtils.createNexusFile(FILE2_NAME)) { extFile.createData(extFile.getGroup("/x/y", true), dummyData); } try (NexusFile oFile = NexusTestUtils.openNexusFileReadOnly(FILE_NAME)) { g = oFile.getGroup("/e", false); assertFalse(g.containsDataNode("g")); // NAPI mount from group to dataset not supported oFile.getData("/e/g"); fail("NAPI mount from group to dataset not supported"); } catch (IllegalArgumentException e) { // throws this } } @Test public void testAbsoluteNapiMountToGroup() throws Exception { try (NexusFile origin = NexusTestUtils.createNexusFile(testScratchDirectoryName + "origin/test.nxs"); NexusFile linked = NexusTestUtils.createNexusFile(testScratchDirectoryName + "linked/linked.nxs")) { GroupNode g = origin.getGroup("/a/b", true); linked.getGroup("/x/y/z", true); Dataset mountData = DatasetFactory.createFromObject(new String[] {"nxfile://" + testScratchDirectoryName + "linked/linked.nxs#x/y/"}); mountData.setName("napimount"); origin.addAttribute( g, nf.createAttribute(mountData) ); } try (NexusFile origin = NexusTestUtils.openNexusFileReadOnly(testScratchDirectoryName + "origin/test.nxs")) { GroupNode g = origin.getGroup("/a/b", false); GroupNode g2 = origin.getGroup("/a/b/z", false); assertNotNull(g2); assertNotNull(g); assertTrue(g.containsGroupNode("z")); assertSame(g.getGroupNode("z"), g2); } } @Test public void testAbsoluteNapiMountToDataset() throws Exception { Dataset dummyData = DatasetFactory.createFromObject(new int[] {0, 1, 2}); dummyData.setName("z"); try (NexusFile origin = NexusTestUtils.createNexusFile(testScratchDirectoryName + "origin/test.nxs"); NexusFile linked = NexusTestUtils.createNexusFile(testScratchDirectoryName + "linked/linked.nxs")) { GroupNode g = origin.getGroup("/a/b/d", true); Dataset mountData = DatasetFactory.createFromObject(new String[] {"nxfile://" + testScratchDirectoryName + "linked/linked.nxs#x/y/z"}); mountData.setName("napimount"); origin.addAttribute(g, origin.createAttribute(mountData)); GroupNode l = linked.getGroup("/x/y/", true); linked.createData(l, dummyData); } try (NexusFile origin = NexusTestUtils.openNexusFileReadOnly(testScratchDirectoryName + "origin/test.nxs")) { GroupNode group = origin.getGroup("/a/b", false); assertFalse(group.containsDataNode("d")); origin.getData(group, "d"); fail("NAPI mount from group to dataset not supported"); } catch (IllegalArgumentException e) { // throws this } } @Test public void testNapiMountToGroupThenDataset() throws Exception { Dataset dummyData = DatasetFactory.createFromObject(new int[] {0, 1, 2}); dummyData.setName("z"); try (NexusFile origin = NexusTestUtils.createNexusFile(testScratchDirectoryName + "origin/test.nxs"); NexusFile linked = NexusTestUtils.createNexusFile(testScratchDirectoryName + "linked/linked.nxs")) { GroupNode g = origin.getGroup("/a/b/d", true); Dataset mountData = DatasetFactory.createFromObject(new String[] {"nxfile://" + testScratchDirectoryName + "linked/linked.nxs#w/x"}); mountData.setName("napimount"); origin.addAttribute(g, origin.createAttribute(mountData)); GroupNode l = linked.getGroup("/w/x/y/", true); linked.createData(l, dummyData); } try (NexusFile origin = NexusTestUtils.openNexusFileReadOnly(testScratchDirectoryName + "origin/test.nxs")) { DataNode dataNode = origin.getData("/a/b/d/y/z"); assertNotNull(dataNode); GroupNode groupNode = origin.getGroup("/a/b/d/y", false); assertNotNull(groupNode); assertTrue(groupNode.containsDataNode("z")); assertSame(groupNode.getDataNode("z"), dataNode); IDataset readData = dataNode.getDataset().getSlice(); assertNotNull(readData); assertEquals(dummyData, readData); } } @Test public void testCreateCompressedDataDeflate() throws Exception { //Not a very elegant test int[] chunking = new int[] {200, 200}; ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("d", Dataset.FLOAT64, new int[] {ILazyWriteableDataset.UNLIMITED, 1000}, null, null); lazy.setChunking(chunking); nf.createData("/a", lazy, true); lazy.setSlice(null, DatasetFactory.createRange(1, 1000000, Dataset.FLOAT64).reshape(1000, 1000), new int[] {0, 0}, new int[] {1000, 1000}, null); nf.close(); try (NexusFile cf = NexusTestUtils.createNexusFile(FILE2_NAME)) { lazy = NexusUtils.createLazyWriteableDataset("d", Dataset.FLOAT64, new int[] {ILazyWriteableDataset.UNLIMITED, 1000}, null, null); lazy.setChunking(chunking); cf.createData("/a", lazy, NexusFile.COMPRESSION_LZW_L1, true); lazy.setSlice(null, DatasetFactory.createRange(1, 1000000, Dataset.FLOAT64).reshape(1000, 1000), new int[] {0, 0}, new int[] {1000, 1000}, null); } File uncompressed = new File(FILE_NAME); File compressed = new File(FILE2_NAME); assertTrue(compressed.length() < uncompressed.length()); } @Test public void testChunking() throws Exception { int[] chunking = new int[] {1, 256, 256}; ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("data", Dataset.FLOAT64, new int[] {1 ,100, 100}, new int[] {ILazyWriteableDataset.UNLIMITED, 1024, 1024}, null); lazy.setChunking(chunking); nf.createData("/a/", lazy, true); assertArrayEquals(chunking, lazy.getChunking()); lazy.setSlice(null, DatasetFactory.createRange(1, 1024 * 1024 * 8, Dataset.FLOAT64).reshape(8, 1024, 1024), new int[] {0, 0, 0}, new int[] {8, 1024, 1024}, null); nf.close(); nf = NexusTestUtils.openNexusFile(FILE_NAME); ILazyWriteableDataset readData = nf.getData("/a/data").getWriteableDataset(); assertNotNull(readData); assertArrayEquals(chunking, readData.getChunking()); } @Test public void testDefaultChunking() throws Exception { ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("data", Dataset.FLOAT64, new int[] {1 ,100, 100}, new int[] {ILazyWriteableDataset.UNLIMITED, 1000, 1000}, null); nf.createData("/a", lazy, true); int[] newChunking = lazy.getChunking(); assertNotNull(newChunking); assertTrue(newChunking[0] >= 1); assertTrue(newChunking[1] >= 32); assertTrue(newChunking[2] >= 32); //our chunks should be at *least* 16kb on this sort of dataset assertTrue(newChunking[0] * newChunking[1] * newChunking[2] * 8 >= 16 * 1024); //we should not exceed 1MB either assertTrue(newChunking[0] * newChunking[1] * newChunking[2] * 8 <= 1024 * 1024); //should favour the last axis assertTrue(newChunking[2] >= newChunking[1] && newChunking[2] >= newChunking[0]); } @Test public void testSensibleChunkingOverride() throws Exception { int[] originalChunking = new int[] {1, 1, 1}; ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("data", Dataset.FLOAT64, new int[] {1 ,100, 100}, new int[] {ILazyWriteableDataset.UNLIMITED, 1000, 1000}, null); lazy.setChunking(originalChunking); nf.createData("/a", lazy, true); int[] newChunking = lazy.getChunking(); assertFalse(Arrays.equals(originalChunking, newChunking)); assertTrue(newChunking[0] >= 1); assertTrue(newChunking[1] >= 32); assertTrue(newChunking[2] >= 32); assertTrue(newChunking[0] * newChunking[1] * newChunking[2] * 8 >= 16 * 1024); assertTrue(newChunking[0] * newChunking[1] * newChunking[2] * 8 <= 1024 * 1024); assertTrue(newChunking[2] >= newChunking[1] && newChunking[2] >= newChunking[0]); } @Test public void testAddGroupNode() throws Exception { GroupNode groupNode = new GroupNodeImpl("/base/g".hashCode()); DataNode dataNode = new DataNodeImpl("/base/g/d".hashCode()); Dataset dataset = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); dataset.setName("d"); dataNode.setDataset(dataset); groupNode.addDataNode(dataset.getName(), dataNode); GroupNode base = nf.getGroup("/base", true); nf.addNode(base, "g", groupNode); GroupNode readG = nf.getGroup("/base/g", false); assertNotNull(readG); assertTrue(readG.containsDataNode("d")); DataNode readDataNode = readG.getDataNode("d"); assertNotNull(readDataNode); assertSame(readDataNode, nf.getData("/base/g/d")); IDataset readData = readDataNode.getDataset().getSlice(); assertEquals(dataset, readData); assertFalse(dataset == readData); // we probably shouldn't be referencing the same object } @Test public void testUpdateNodes() throws Exception { nf.getGroup("/a/b/c", true); Dataset attrData = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); attrData.setName("atr"); Attribute attr = nf.createAttribute(attrData); GroupNode base = nf.getGroup("/a", false); GroupNode b = new GroupNodeImpl("/a/b".hashCode()); b.addAttribute(attr); GroupNode x = new GroupNodeImpl("/a/b/x".hashCode()); b.addGroupNode("x", x); nf.addNode(base, "b", b); assertNotNull(nf.getGroup("/a/b/x", false)); GroupNode readB = nf.getGroup("/a/b", false); assertTrue(readB.containsAttribute("atr")); Attribute readAttr = readB.getAttribute("atr"); assertEquals(attrData, readAttr.getValue()); } @Test public void testAddLazyDataNode() throws Exception { GroupNode g = new GroupNodeImpl("/base/g".hashCode()); DataNode lazyDataNode = new DataNodeImpl("/base/g/intarray".hashCode()); ILazyWriteableDataset lazy = NexusUtils.createLazyWriteableDataset("intarray", Dataset.INT32, new int[] { ILazyWriteableDataset.UNLIMITED, 10 }, null, null); lazyDataNode.setDataset(lazy); g.addDataNode("intarray", lazyDataNode); GroupNode base = nf.getGroup("/base", true); nf.addNode(base, "g", g); DataNode readNode = nf.getData("/base/g/intarray"); assertNotNull(readNode); assertSame(lazy, readNode.getDataset()); nf.close(); nf = null; lazy.setSlice(null, DatasetFactory.createFromObject(new int[] { -1, -1, -1, -1 }).reshape(2, 2), new int[] { 0, 0 }, new int[] { 2, 2 }, null); nf = NexusTestUtils.openNexusFileReadOnly(FILE_NAME); DataNode node = nf.getData("/base/g/intarray"); Dataset data = DatasetUtils.convertToDataset(node.getDataset().getSlice(new int[] { 0, 0 }, new int[] { 2, 2 }, new int[] { 1, 1 })); assertArrayEquals(new int[] { -1, -1, -1, -1 }, (int[]) data.getBuffer()); } @Test public void testAddNodeWithHardlinks() throws Exception { GroupNode g = new GroupNodeImpl("/base/g".hashCode()); GroupNode h = new GroupNodeImpl("/base/g/h".hashCode()); g.addGroupNode("h", h); // /base/g/i = hardlink to /base/g/h g.addGroupNode("i", h); GroupNode j = new GroupNodeImpl("/base/g/j".hashCode()); g.addGroupNode("j", j); GroupNode k = new GroupNodeImpl("/base/g/h/k".hashCode()); h.addGroupNode("k", k); // /base/g/h/k/l hardlink to /base/g/j k.addGroupNode("l", j); GroupNode base = nf.getGroup("/base", true); nf.addNode(base, "g", g); GroupNode readH = nf.getGroup("/base/g/h", false); GroupNode readI = nf.getGroup("/base/g/i", false); assertNotNull(readH); assertSame(readH, readI); GroupNode readL = nf.getGroup("/base/g/h/k/l", false); GroupNode readJ = nf.getGroup("/base/g/j", false); assertNotNull(readL); assertSame(readJ, readL); assertFalse(readH == readL); nf.close(); nf = NexusTestUtils.openNexusFile(FILE_NAME); readH = nf.getGroup("/base/g/h", false); readI = nf.getGroup("/base/g/i", false); assertNotNull(readH); assertSame(readH, readI); readL = nf.getGroup("/base/g/h/k/l", false); readJ = nf.getGroup("/base/g/j", false); assertNotNull(readL); assertSame(readJ, readL); assertFalse(readH == readL); } @Test public void testLazyWriteFromReadbackNode() throws Exception { nf.close(); IDataset ods = DatasetFactory.createFromObject(new int[] {10, 20, 30}); try (NexusFile nf2 = NexusTestUtils.createNexusFile(FILE_NAME)) { ILazyWriteableDataset lds = new LazyWriteableDataset("data", Dataset.INT32, new int[] {0}, new int[] {ILazyWriteableDataset.UNLIMITED}, new int[] {3}, null); nf2.createData("/test/", lds, true); nf2.flush(); } try (NexusFile nf = NexusTestUtils.openNexusFile((FILE_NAME))) { ILazyWriteableDataset lds = nf.getData("/test/data").getWriteableDataset(); lds.setSlice(null, ods, new int[] {0}, new int[] {3}, null); } } @Test public void testExternalLinkToDelayedFile() throws Exception { File f2 = new File(FILE2_NAME); if (f2.exists()) { if (!f2.delete()) { throw new Exception("Could not delete previous external file"); } } IDataset data = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); data.setName("d"); nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#a/"), "/x", true); nf.linkExternal(new URI("nxfile://" + FILE2_NAME + "#g/d"), "/l/d", false); assertTrue(nf.isPathValid("/x")); assertTrue(nf.isPathValid("/l/d")); try { nf.getGroup("/x", false); fail("Should not be able to traverse external link node when external file does not exist"); } catch (Exception e) { } try { nf.getData("/l/d"); fail("Should not be able to open external data node when external file does not exist"); } catch (Exception e) { } try (NexusFile ef = NexusTestUtils.createNexusFile(FILE2_NAME)) { ef.getGroup("/a/b", true); ef.getGroup("/a/c", true); ef.createData("/g", data, true); } GroupNode x = nf.getGroup("/x", false); assertNotNull(x); assertTrue(x.containsGroupNode("b")); assertTrue(x.containsGroupNode("c")); DataNode d = nf.getData("/l/d"); assertNotNull(d); assertEquals(data, d.getDataset().getSlice()); } @Test public void testAddExternalLinkNode() throws Exception { IDataset data = DatasetFactory.createRange(10.0, Dataset.FLOAT64).reshape(2, 5); data.setName("data"); try (NexusFile nf2 = NexusTestUtils.createNexusFile(FILE2_NAME)) { nf2.getGroup("/ext/group/a", true); nf2.createData("/ext", data, true); } GroupNode g = new GroupNodeImpl("/g".hashCode()); SymbolicNode ed = new SymbolicNodeImpl("/g/ed".hashCode(), new URI(FILE2_NAME), null, "/ext/data"); SymbolicNode eg = new SymbolicNodeImpl("/g/eg".hashCode(), new URI(FILE2_NAME), null, "/ext/group/"); g.addNode("ed", ed); g.addNode("eg", eg); nf.addNode("/g", g); nf.close(); nf.openToRead(); GroupNode readG = nf.getGroup("/g", false); assertTrue(readG.containsGroupNode("eg")); assertTrue(readG.containsDataNode("ed")); GroupNode readEg = nf.getGroup("/g/eg", false);; assertTrue(readEg.containsGroupNode("a")); assertEquals(data, nf.getData(readG, "ed").getDataset().getSlice()); } @Test public void testHardLinkWithExistingTargetAttribute() throws Exception { // test that creating a hard link does not overwrite an already set "target" attribute IDataset target = DatasetFactory.createFromObject("/g/d"); target.setName("target"); GroupNode h = nf.getGroup("/g/h/", true); Attribute t = nf.createAttribute(target); nf.addAttribute(h, t); nf.link("/g/h", "/g/d"); // would normally set target to /g/h GroupNode d = nf.getGroup("/g/d", false); IDataset readBack = d.getAttribute("target").getValue(); if (readBack.getRank() == 0) { // TODO // readBack.resize(new int[] {1}); } assertEquals(target, readBack.getSlice()); nf.close(); nf.openToRead(); d = nf.getGroup("/g/d", false); readBack = d.getAttribute("target").getValue(); if (readBack.getRank() == 0) { // TODO // readBack.resize(new int[] {1}); } assertEquals(target, readBack.getSlice()); } }