package uk.ac.diamond.scisoft.analysis.io; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.eclipse.dawnsci.analysis.api.io.ScanFileHolderException; import org.eclipse.january.IMonitor; import org.eclipse.january.MetadataException; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.metadata.AxesMetadata; import org.eclipse.january.metadata.MetadataFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import uk.ac.diamond.scisoft.analysis.io.AbstractFileLoader; import uk.ac.diamond.scisoft.analysis.io.DataHolder; public class XMSOLoader extends AbstractFileLoader { transient protected static final Logger logger = LoggerFactory.getLogger(XMSOLoader.class); public XMSOLoader() { } public XMSOLoader(final String fileName) { setFile(fileName); } @Override public void setFile(String fileName) { super.setFile(fileName); } @Override protected void clearMetadata() { //no metadata in XMSO files } @Override public DataHolder loadFile() throws ScanFileHolderException { return loadFile((IMonitor)null); } /** * Function that loads in the standard XMSO datafile * * @return The package which contains the data that has been loaded * @throws ScanFileHolderException */ @Override public DataHolder loadFile(final IMonitor mon) throws ScanFileHolderException { // first instantiate the return object. final DataHolder result = new DataHolder(); // then try to read the file given Document dom; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { //ignore the dtd dbf.setValidating(false); dbf.setFeature("http://xml.org/sax/features/namespaces", false); dbf.setFeature("http://xml.org/sax/features/validation", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); DocumentBuilder db = dbf.newDocumentBuilder(); dom = db.parse(fileName); //check how many interactions there were XPath xpath = XPathFactory.newInstance().newXPath(); int n_interactions = ((Double)xpath.evaluate("/xmimsim-results/xmimsim-input/general/n_interactions_trajectory", dom, XPathConstants.NUMBER)).intValue(); //check how many children the first channel has. This will let us know if there was transmission (zero-interactions) or not... int nchildren_channel0 = ((NodeList) xpath.evaluate("/xmimsim-results/spectrum_conv/channel[1]/counts", dom, XPathConstants.NODESET)).getLength(); int first_interaction; if (n_interactions == nchildren_channel0) { first_interaction = 1; } else if (nchildren_channel0 == n_interactions+1) { first_interaction = 0; } else { //this should never happen and indicates a corrupt XMSO file throw new ScanFileHolderException("DatLoader.loadFile exception loading " + fileName); } //how many channels are we dealing with int nchannels = ((Double)xpath.evaluate("/xmimsim-results/xmimsim-input/detector/nchannels", dom, XPathConstants.NUMBER)).intValue(); //read the energies double[] energies = new double[nchannels]; NodeList energies_list = ((NodeList) xpath.evaluate("/xmimsim-results/spectrum_conv/channel/energy", dom, XPathConstants.NODESET)); for (int i = 0 ; i < nchannels ; i++) { energies[i] = Double.parseDouble(energies_list.item(i).getFirstChild().getNodeValue()); } Dataset energiesDS = DatasetFactory.createFromObject(energies); energiesDS.setName("Energy (keV)"); result.addDataset("Energy (keV)", energiesDS); //convoluted data for (int interaction = first_interaction ; interaction <= n_interactions ; interaction++) { double[] counts = new double[nchannels]; NodeList counts_list = ((NodeList) xpath.evaluate("/xmimsim-results/spectrum_conv/channel/counts[@interaction_number=\""+ interaction + "\"]", dom, XPathConstants.NODESET)); for (int i = 0 ; i < nchannels ; i++) { counts[i] = Double.parseDouble(counts_list.item(i).getFirstChild().getNodeValue()); } Dataset set = DatasetFactory.createFromObject(counts); // add energies as x-axis try { AxesMetadata amd = MetadataFactory.createMetadata(AxesMetadata.class, 1); amd.setAxis(0, energiesDS); set.addMetadata(amd); } catch (MetadataException e) { logger.error("Could not created AxesMetadata: ", e); } if (interaction == 1) { set.setName("Counts after 1 interaction"); result.addDataset("Counts after 1 interaction", set); } else { set.setName("Counts after " + interaction + " interactions"); result.addDataset("Counts after " + interaction + " interactions", set); } } } catch (Exception e) { logger.error("Exception message: {}", e.getMessage()); throw new ScanFileHolderException("XMSOLoader.loadFile exception loading " + fileName, e); } return result; } }