/*-
* Copyright 2016 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 uk.ac.diamond.scisoft.analysis.io;
import java.util.Collection;
import java.util.Map;
import javax.vecmath.Matrix3d;
import org.eclipse.dawnsci.analysis.api.diffraction.DetectorProperties;
import org.eclipse.dawnsci.analysis.api.diffraction.DiffractionCrystalEnvironment;
import org.eclipse.dawnsci.analysis.api.io.IDataHolder;
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.IFindInTree;
import org.eclipse.dawnsci.analysis.api.tree.Node;
import org.eclipse.dawnsci.analysis.api.tree.NodeLink;
import org.eclipse.dawnsci.analysis.api.tree.Tree;
import org.eclipse.dawnsci.analysis.api.tree.TreeUtils;
import org.eclipse.january.DatasetException;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetUtils;
import org.eclipse.january.dataset.DoubleDataset;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.ILazyDataset;
import org.eclipse.dawnsci.analysis.api.metadata.IDiffractionMetadata;
/**
* Read DiffractionMetaData from Nexus file written by DAWN/GDA
*/
public class NexusDiffractionCalibrationReader {
public static IDiffractionMetadata getDiffractionMetadataFromNexus(final String filePath, final ILazyDataset parent) throws DatasetException {
return getDiffractionMetadataFromNexus(filePath, parent, null);
}
public static IDiffractionMetadata getDiffractionMetadataFromNexus(final String filePath, final ILazyDataset parent, String datasetName) throws DatasetException {
Tree tree = null;
IDataHolder dh;
try {
dh = LoaderFactory.getData(filePath);
tree = dh.getTree();
} catch (Exception e1) {
return null;
}
if (tree == null) return null;
Map<String, NodeLink> dnl = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), getFinder(parent), true, null);
if (dnl.size() != 1 && datasetName != null){
String s = stripDataName(datasetName);
dnl = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), getFinder(s), true, null);
}
if (dnl.size() != 1 && parent != null) dnl = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), getFinder((ILazyDataset)null), true, null);
if (dnl.size() != 1) return null;
String key = dnl.keySet().iterator().next();
DetectorProperties[] d = NexusTreeUtils.parseDetector("/" + key, tree, 0);
if (d == null || d.length == 0) return trySAXS(dnl.get(key), tree, filePath);
DetectorProperties dp = d[0];
DiffractionCrystalEnvironment dce = tryBeam(tree);
if (dce == null) dce = tryMonochromator(tree);
if (dce == null) return null;
return new DiffractionMetadata(filePath, dp, dce);
}
private static String stripDataName(String dataName) {
String[] split = dataName.split("/");
if (split == null || split.length < 3) return null;
return split[split.length-2];
}
private static IDiffractionMetadata trySAXS(NodeLink detectorLink, Tree tree, String path) throws DatasetException {
DetectorProperties saxs = null;
try {
saxs = NexusTreeUtils.parseSaxsDetector(detectorLink);
} catch (Exception e) {
//TODO warn
}
if (saxs == null) return null;
legacySupport(saxs,detectorLink);
DiffractionCrystalEnvironment dce = tryBeam(tree);
if (dce == null) dce = tryMonochromator(tree);
if (dce == null) return null;
return new DiffractionMetadata(path, saxs, dce);
}
private static DiffractionCrystalEnvironment tryBeam(Tree tree) {
NodeLink nl = findWavelengthNode(tree, NexusTreeUtils.NX_BEAM);
if (nl == null) return null;
DiffractionCrystalEnvironment dce = new DiffractionCrystalEnvironment();
NexusTreeUtils.parseBeam(nl, dce);
return dce.getWavelength() == 0 ? null : dce;
}
private static DiffractionCrystalEnvironment tryMonochromator(Tree tree) {
NodeLink nl = findWavelengthNode(tree, NexusTreeUtils.NX_MONOCHROMATOR);
if (nl == null) return null;
DiffractionCrystalEnvironment dce = new DiffractionCrystalEnvironment();
NexusTreeUtils.parseMonochromator(nl, dce);
return dce.getWavelength() == 0 ? null : dce;
}
private static NodeLink findWavelengthNode(Tree tree, final String nxClass) {
IFindInTree findbeam = new IFindInTree() {
@Override
public boolean found(NodeLink node) {
Node source = node.getDestination();
Attribute attribute = source.getAttribute("NX_class");
if (attribute == null) return false;
String el = attribute.getFirstElement();
if (el == null) return false;
if (el.equals(nxClass)) return true;
return false;
}
};
Map<String, NodeLink> dnl1 = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), findbeam, true, null);
if (dnl1.size() != 1) return null;
String key = dnl1.keySet().iterator().next();
return dnl1.get(key);
}
private static DetectorProperties legacySupport(DetectorProperties dp, NodeLink nl) throws DatasetException {
Node n = nl.getDestination();
if (n instanceof GroupNode) {
GroupNode gn = (GroupNode)n;
if (gn.containsDataNode("detector_orientation")) {
IDataset slice = gn.getDataNode("detector_orientation").getDataset().getSlice();
DoubleDataset dd = (DoubleDataset)DatasetUtils.cast(slice, Dataset.FLOAT64);
double[] bcc = dp.getBeamCentreCoords();
dp.setBeamCentreCoords(new double[]{0,0});
dp.setOrientation(new Matrix3d(dd.getData()));
dp.setBeamCentreCoords(bcc);
}
}
return dp;
}
private static IFindInTree getFinder(final ILazyDataset parent) {
return new IFindInTree() {
@Override
public boolean found(NodeLink node) {
Node dest = node.getDestination();
if (dest instanceof GroupNode) {
GroupNode dgn = (GroupNode)dest;
Attribute attribute = dgn.getAttribute("NX_class");
if (attribute == null) return false;
String el = attribute.getFirstElement();
if (el == null) return false;
if (el.equals("NXdetector")){
if (parent == null) return true;
Collection<String> names = dgn.getNames();
for (String name : names) {
if (dgn.containsDataNode(name)) {
if (dgn.getDataNode(name).getDataset().equals(parent)) return true;
}
}
if (dest instanceof DataNode){
return ((DataNode)dest).getDataset().equals(parent);
}
}
}
return false;
}
};
}
private static IFindInTree getFinder(final String name) {
return new IFindInTree() {
@Override
public boolean found(NodeLink node) {
Node dest = node.getDestination();
if (dest instanceof GroupNode) {
GroupNode dgn = (GroupNode)dest;
Attribute attribute = dgn.getAttribute("NX_class");
if (attribute == null) return false;
String el = attribute.getFirstElement();
if (el == null) return false;
if (el.equals("NXdetector")){
return node.getName().equals(name);
}
}
return false;
}
};
}
public static IDataset getDetectorPixelMaskFromNexus(final String filePath, final ILazyDataset parent) throws Exception {
Tree tree = null;
IDataHolder dh;
try {
dh = LoaderFactory.getData(filePath);
tree = dh.getTree();
} catch (Exception e1) {
return null;
}
Map<String, NodeLink> dnl = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), getFinder(parent), true, null);
if (dnl.size() != 1 && parent != null) dnl = TreeUtils.treeBreadthFirstSearch(tree.getGroupNode(), getFinder((ILazyDataset)null), true, null);
if (dnl.size() != 1) return null;
String key = dnl.keySet().iterator().next();
NodeLink nl = dnl.get(key);
Node n = nl.getDestination();
if (n instanceof GroupNode) {
GroupNode g = (GroupNode)n;
if (g.containsDataNode("pixel_mask")) {
return g.getDataNode("pixel_mask").getDataset().getSlice();
}
}
return null;
}
}