/* * Copyright (c) 2012 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.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.dawnsci.analysis.api.io.ScanFileHolderException; import org.eclipse.january.IMonitor; import org.eclipse.january.dataset.Dataset; import org.eclipse.january.dataset.DatasetFactory; import org.eclipse.january.dataset.FloatDataset; import org.eclipse.january.dataset.ILazyDataset; import org.eclipse.january.dataset.IntegerDataset; import org.eclipse.january.metadata.Metadata; /** * This class should be used to load ESRF datafiles created by the Pilatus detector system * into the ScanFileHolder object. This has not been tested on general ESRF datafiles. * <p> * <b>Note</b>: the header data from this loader is left as strings */ public class PilatusEdfLoader extends AbstractFileLoader { private Map<String, String> textMetadata = new HashMap<String, String>(); public static final String DATA_NAME = "EDF"; /** * @param fileName */ public PilatusEdfLoader(String fileName) { this.fileName = fileName; } @Override protected void clearMetadata() { metadata = null; textMetadata.clear(); } @Override public DataHolder loadFile() throws ScanFileHolderException { return loadFile(null); } @Override public DataHolder loadFile(IMonitor mon) throws ScanFileHolderException { ILazyDataset data = null; final DataHolder output = new DataHolder(); File f = null; FileInputStream fi = null; BufferedReader br = null; try { f = new File(fileName); fi = new FileInputStream(f); br = new BufferedReader(new FileReader(f)); String line = br.readLine(); if (line == null) throw new ScanFileHolderException("No lines found"); // If the first line is not a { then we fail this loader. if (!line.trim().startsWith("{")) throw new ScanFileHolderException("EDF File should start with {"); if (line.contains("{")) { // Read the meta data int index = readMetaData(br, line.length()+1, mon); // Now read the data int[] shape = new int[] { Integer.parseInt(textMetadata.get("Dim_2")), Integer.parseInt(textMetadata.get("Dim_1"))}; String dataType = textMetadata.get("DataType"); if (loadLazily) { // This does not provide support for 64-bit datatypes, which may be present in EDF files. data = createLazyDataset(DEF_IMAGE_NAME, DATA_NAME, dataType.equals("Float") ? Dataset.FLOAT32 : Dataset.INT32, shape, new PilatusEdfLoader(fileName)); } else { boolean le = "LowByteFirst".equals(textMetadata.get("ByteOrder")); boolean signed = dataType.startsWith("Signed"); // this EDF loader supports only a subset of all possible datatypes // an exception will be thrown when an unsupported datatype is encountered if (dataType.equals("Float") || dataType.equals("FloatValue")) { data = DatasetFactory.zeros(FloatDataset.class, shape); if (le) { Utils.readLeFloat(fi, (FloatDataset) data, index); } else { Utils.readBeFloat(fi, (FloatDataset) data, index); } } else if (dataType.contains("Short")) { // 16 bit integers data = DatasetFactory.zeros(IntegerDataset.class, shape); if (le) Utils.readLeShort(fi, (IntegerDataset) data, index, signed); else Utils.readBeShort(fi, (IntegerDataset) data, index, signed); } else if (dataType.contains("Long") || dataType.contains("Integer")) { // 32 bit integers, signed ONLY if (!signed) { throw new ScanFileHolderException("32-bit unsigned integers are currently not supported"); } data = DatasetFactory.zeros(IntegerDataset.class, shape); if (le) Utils.readLeInt(fi, (IntegerDataset) data, index); else Utils.readBeInt(fi, (IntegerDataset) data, index); } else { // unsupported data type exception // expect this when datatype is byte, 64-bit integer or 64-bit float throw new ScanFileHolderException("Unknown EDF datatype " + dataType); } data.setName(DEF_IMAGE_NAME); } } } catch (Exception e) { throw new ScanFileHolderException("File failed to load " + fileName, e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { // do nothing } } if (fi != null) { try { fi.close(); } catch (IOException ex) { // do nothing } fi = null; } } if (data != null) { output.addDataset(DATA_NAME, data); if (loadMetadata) { createMetadata(); data.setMetadata(metadata); output.setMetadata(metadata); } } return output; } private void createMetadata() { metadata = new Metadata(); metadata.initialize(textMetadata); metadata.setFilePath(fileName); metadata.addDataInfo(DATA_NAME, Integer.parseInt(textMetadata.get("Dim_2")), Integer.parseInt(textMetadata.get("Dim_1"))); } private int readMetaData(final BufferedReader br, int index, final IMonitor mon) throws Exception { textMetadata.clear(); while (true) { if (!monitorIncrement(mon)) { throw new ScanFileHolderException("Loader cancelled during reading!"); } String line = br.readLine(); if (line == null) { throw new ScanFileHolderException("No closing brace found"); } index += line.length()+1; if (line.contains("}")) { break; } String[] keyvalue = line.split("="); if (keyvalue.length == 1) { textMetadata.put(keyvalue[0].trim(), ""); } else { int len = (keyvalue[1].endsWith(";")) ? keyvalue[1].length()-1 : keyvalue[1].length(); String value = keyvalue[1].substring(0, len); textMetadata.put(keyvalue[0].trim(), value.trim()); } } return index; } }