/*-
* 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.assertTrue;
import static org.junit.Assert.fail;
import java.net.URI;
import org.eclipse.dawnsci.analysis.api.tree.DataNode;
import org.eclipse.dawnsci.analysis.api.tree.GroupNode;
import org.eclipse.dawnsci.nexus.NexusException;
import org.eclipse.dawnsci.nexus.NexusFile;
import org.eclipse.dawnsci.nexus.TestUtils;
import org.eclipse.dawnsci.nexus.test.util.NexusTestUtils;
import org.eclipse.january.DatasetException;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.ILazyDataset;
import org.eclipse.january.dataset.ILazyWriteableDataset;
import org.eclipse.january.dataset.LazyWriteableDataset;
import org.eclipse.january.dataset.Slice;
import org.eclipse.january.dataset.SliceND;
import org.junit.BeforeClass;
import org.junit.Test;
public class NexusFileIntegrationTest {
static String testScratchDirectoryName;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
testScratchDirectoryName = TestUtils.generateDirectorynameFromClassname(NexusFileIntegrationTest.class.getCanonicalName());
TestUtils.makeScratchDirectory(testScratchDirectoryName);
}
@Test
public void testNexusFile() throws Exception {
String name = testScratchDirectoryName + "test.nxs";
NexusFile nf = NexusTestUtils.createNexusFile(name);
GroupNode g = nf.getGroup("/e/a/b", true);
Dataset a = DatasetFactory.createFromObject("world");
a.setName("hello");
nf.addAttribute(g, nf.createAttribute(a));
int[] shape = new int[] {2, 34};
int[] mshape = new int[] {ILazyWriteableDataset.UNLIMITED, 34};
LazyWriteableDataset d = new LazyWriteableDataset("d", Dataset.INT16, shape, mshape, null, null);
nf.createData(g, d);
LazyWriteableDataset e = new LazyWriteableDataset("e", Dataset.FLOAT64, shape, mshape, null, null);
nf.createData(g, e);
a = DatasetFactory.createFromObject(-1.5);
a.setName("value");
nf.addAttribute(g.getDataNode(d.getName()), nf.createAttribute(a));
LazyWriteableDataset t = new LazyWriteableDataset("t", Dataset.STRING, shape, mshape, null, null);
nf.createData(g, t);
a = DatasetFactory.createRange(10, Dataset.FLOAT32).reshape(2, 5);
a.setName("value");
nf.createData("/entry", a, true);
a.iadd(1);
try {
nf.createData("/entry", a, false);
fail("Must not be able to create a dataset on top of an existing one");
} catch (NexusException ex) {
// do nothing
}
nf.close();
SliceND slice = new SliceND(shape, new Slice(2), new Slice(10, 11));
d.setSlice(DatasetFactory.zeros(slice.getShape(), Dataset.INT16).fill(-5), slice);
SliceND eSlice = SliceND.createSlice(e, new int[] {2, 3}, new int[] {4, 34});
e.setSlice(DatasetFactory.zeros(eSlice.getShape(), Dataset.INT16).fill(-9), eSlice);
t.setSlice(DatasetFactory.createFromObject(new String[] {"Hello", "World"}).reshape(2, 1),
SliceND.createSlice(t, new int[] {2, 3}, new int[] {4, 4}));
nf.openToRead();
g = nf.getGroup("/e/a/b", false);
checkGroup(g);
DataNode n = nf.getData("/e/a/b/d");
checkData(n, shape);
n = nf.getData("/e/a/b/e");
checkEData(n, new int[] {4, 34});
n = nf.getData("/e/a/b/t");
checkTextData(n, new int[] {4, 34});
nf.close();
nf.openToWrite(false);
nf.link("/e/a/b", "/f/c");
nf.linkExternal(new URI("nxfile:///./"+name+"#/e/a/b/d"), "/g", false);
nf.close();
nf.openToRead();
g = nf.getGroup("/f/c", false);
checkGroup(g);
n = g.getDataNode("d");
checkData(n, shape);
n = g.getDataNode("t");
checkTextData(n, new int[] {4, 34});
n = nf.getData("/g");
checkData(n, shape);
n = nf.getData("/entry/value");
IDataset b = n.getDataset().getSlice();
assertArrayEquals(new int[] {2, 5}, b.getShape());
assertEquals(Float.class, b.getElementClass());
assertEquals(0.0, b.getDouble(0, 0), 1e-15);
assertEquals(9.0, b.getDouble(1, 4), 1e-15);
nf.close();
}
private void checkGroup(GroupNode g) {
assertTrue(g.containsAttribute("hello"));
assertEquals("world", g.getAttribute("hello").getValue().getString()); // TODO
assertTrue(g.isPopulated() && g.containsDataNode("d"));
}
private void checkData(DataNode n, int[] shape) throws DatasetException {
assertTrue(n.containsAttribute("value"));
assertEquals(-1.5, n.getAttribute("value").getValue().getDouble(), 1e-15);
ILazyDataset b = n.getDataset();
assertTrue(b.getElementClass().equals(Short.class));
assertArrayEquals(shape, b.getShape());
IDataset bs = b.getSlice();
assertEquals(0, bs.getLong(0, 0));
assertEquals(-5, bs.getLong(1, 10));
}
private void checkEData(DataNode n, int[] shape) throws DatasetException {
ILazyDataset b = n.getDataset();
assertTrue(b.getElementClass().equals(Double.class));
assertArrayEquals(shape, b.getShape());
IDataset bs = b.getSlice();
assertEquals(Double.NaN, bs.getDouble(0, 0), 1e-12);
assertEquals(Double.NaN, bs.getDouble(0, 2), 1e-12);
assertEquals(Double.NaN, bs.getDouble(0, 10), 1e-12);
assertEquals(Double.NaN, bs.getDouble(1, 0), 1e-12);
assertEquals(Double.NaN, bs.getDouble(1, 2), 1e-12);
assertEquals(Double.NaN, bs.getDouble(1, 10), 1e-12);
assertEquals(Double.NaN, bs.getDouble(2, 0), 1e-12);
assertEquals(Double.NaN, bs.getDouble(2, 2), 1e-12);
assertEquals(-9, bs.getDouble(2, 10), 1e-12);
}
private void checkTextData(DataNode n, int[] shape) throws DatasetException {
ILazyDataset b = n.getDataset();
assertTrue(b.getElementClass().equals(String.class));
// NAPI is broken wrt strings so skip for time being
assertArrayEquals(shape, b.getShape());
IDataset bs = b.getSlice();
assertEquals("null", bs.getString(0, 0));
assertEquals("Hello", bs.getString(2, 3));
assertEquals("World", bs.getString(3, 3));
}
@Test
public void testLinked() throws Exception {
String d = "testfiles/dawnsci/data/nexus/";
String n = "testlinks.nxs";
NexusFile f = NexusTestUtils.openNexusFileReadOnly(d + n);
// original
int[] shape;
IDataset ds;
shape = new int[] {25, 3};
ds = f.getData("/entry1/to/this/level/d1").getDataset().getSlice();
assertArrayEquals(shape, ds.getShape());
assertEquals(1, ds.getInt(0, 1));
assertEquals(5, ds.getInt(1, 2));
assertEquals(37, ds.getInt(12, 1));
shape = new int[] {2, 5};
ds = f.getData("/d_el").getDataset().getSlice();
assertArrayEquals(shape, ds.getShape());
assertEquals(1., ds.getDouble(0, 1), 1e-8);
assertEquals(9., ds.getDouble(1, 4), 1e-8);
//NAPI mounts to datasets are not valid, so skip
/*
ds = f.getData("/entry1/to/this/level/extdst").getDataset().getSlice();
assertArrayEquals(shape, ds.getShape());
assertEquals(1., ds.getDouble(0, 1), 1e-8);
assertEquals(9., ds.getDouble(1, 4), 1e-8);
*/
// cannot get string attributes written by h5py(!!!)
GroupNode g = f.getGroup("/g_el/lies", false);
assertEquals("ballyho", g.getAttribute("a1").getFirstElement());
}
}