Java tutorial
/*- * Copyright 2011 Diamond Light Source Ltd. * * This file is part of GDA. * * GDA is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License version 3 as published by the Free * Software Foundation. * * GDA is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along * with GDA. If not, see <http://www.gnu.org/licenses/>. */ package gda.device.detector.pco; import gda.configuration.properties.LocalProperties; import gda.data.NumTracker; import gda.data.PathConstructor; import gda.data.fileregistrar.FileRegistrarHelper; import gda.device.Detector; import gda.device.DeviceException; import gda.device.detector.DetectorBase; import gda.device.detector.IPCOControllerV17; import gda.device.detector.IPCODetector; import gda.device.detector.NXDetectorData; import gda.device.detector.areadetector.v17.ADBase; import gda.device.detector.areadetector.v17.NDFile; import gda.jython.InterfaceProvider; import gda.scan.ScanInformation; import gda.util.Sleep; import gov.aps.jca.TimeoutException; import java.io.File; import java.io.IOException; import java.util.Vector; import org.eclipse.dawnsci.analysis.api.dataset.IDataset; import org.eclipse.dawnsci.analysis.api.io.IDataHolder; import org.eclipse.dawnsci.analysis.api.io.IFileLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import uk.ac.diamond.scisoft.analysis.SDAPlotter; import uk.ac.diamond.scisoft.analysis.io.LoaderFactory; import uk.ac.diamond.scisoft.analysis.io.TIFFImageLoader; import uk.ac.gda.devices.pco.LiveModeUtil; /** * Separating out the detector from the controller - Part of GDA-4231 area detector stuff to get all detectors aligned * to EPICS V1.7 * * @author rsr31645 */ public class PCODetector extends DetectorBase implements InitializingBean, IPCODetector { private boolean isWindowsIoc = true; public final String GDA_FILE_TRANSFER_SCRIPT = "gda.file.transfer.script"; private String description; private String detectorID; private String detectorType; private IPCOControllerV17 controller; private File scanSaveFolder; private String localFilePath; // parameter required by Tomography reconstruction software private String projectionFolderName = "projections"; // private String numTrackerTag; private Windows2LinuxFilePath localDataStoreWindows2LinuxFilePath; private Windows2LinuxFilePath nonLocalDataStoreWindows2LinuxFilePath; private Windows2LinuxFilePath demandRawDataStoreWindows2LinuxFileName; private String darkFileNameRoot; private int numberOfDarkImages; private String faltFileNameRoot; private int numberOfFlatImages; private static final Logger logger = LoggerFactory.getLogger(PCODetector.class); private boolean saveLocal = false; private boolean hdfFormat = true; // default is HDF format private String plotName; private long aquisitionStartTime; private int pauseTime; private boolean externalTriggered = false; private boolean isPreviewing = false; private boolean scanRunning; private boolean firstcall; public PCODetector() { setLocal(true); // do not use CORBA, use RMI } public void preview(double acquireTime) throws Exception { ADBase areaDetector = controller.getAreaDetector(); // stop the camera first controller.stop(); // then change to preview parameters controller.setImageMode(2); areaDetector.setAcquireTime(acquireTime); // make sure all file savers disabled controller.disableTiffSaver(); controller.disableHdfSaver(); // TODO start external MJEP GUI on client? controller.acquire(); isPreviewing = true; } private void stopPreview() throws Exception { controller.stop(); isPreviewing = false; } /** * @return Returns the hdfFormat. */ @Override public boolean isHdfFormat() { return hdfFormat; } @Override public void collectData() throws DeviceException { // TODO sleep needed to give time for camera readout as detector has no READOUT status if (!isExternalTriggered()) { // software data collection try { controller.acquire(); // aquisitionStartTime = System.currentTimeMillis(); } catch (Exception e1) { logger.error("{} acquire failed", getName()); throw new DeviceException(getName() + " acquire request failed.", e1); } } else { // make sure that the new time is at least the acquisition Time plus the pause long nextStartTime = (long) (aquisitionStartTime + pauseTime + (collectionTime * 1000.0)); long currentTime = System.currentTimeMillis(); // InterfaceProvider.getTerminalPrinter().print(String.format("%d, %d", nextStartTime, currentTime)); // wait for the correct amount of time, and then start if (nextStartTime > currentTime) { try { Thread.sleep(nextStartTime - currentTime); } catch (InterruptedException e) { throw new DeviceException("Failed to cause Thread.sleep", e); } } // triggered data collection try { controller.trigger(); aquisitionStartTime = System.currentTimeMillis(); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; if (e instanceof DeviceException) throw (DeviceException) e; throw new DeviceException("Failed to make PCO camera trigger", e); } } } public boolean isExternalTriggered() { return this.externalTriggered; } @Override public void setExternalTriggered(boolean externalTriggered) { this.externalTriggered = externalTriggered; } /** * @param hdfFormat * The hdfFormat to set. */ @Override public void setHdfFormat(boolean hdfFormat) { this.hdfFormat = hdfFormat; } @Override public int getStatus() { if (isExternalTriggered()) { if (firstcall) { firstcall = false; try { if (controller.getTiff().getNumCaptured_RBV() == 0) { return Detector.BUSY; } } catch (Exception e) { logger.error("getNumCaptured_RBV() failed at getStatus()", e); } return Detector.IDLE; } // this to make sure motors can be moved at detector readout time if (System.currentTimeMillis() < (aquisitionStartTime + (collectionTime * 1000))) { return Detector.BUSY; } return Detector.IDLE; } int status = controller.getAreaDetector().getStatus(); // get camera acquire state return status; } @Override public Object readout() throws DeviceException { String output = ""; NXDetectorData dataTree = new NXDetectorData(); try { if (hdfFormat) { print("Frames collected: " + controller.getHdf().getFile().getNumCaptured_RBV()); if (controller.getHdf().getFile().getNumCapture_RBV() == controller.getHdf().getFile() .getNumCaptured_RBV()) { // when capturing completed int totalmillis = 120 * 1000; // 2 minutes timeout int grain = 25; long timer = 0, timer0 = System.currentTimeMillis(); while (isWriterBusy() && timer - timer0 < totalmillis) { Thread.sleep(grain); timer = System.currentTimeMillis(); } if (timer - timer0 >= totalmillis) { throw new TimeoutException( "It takes too long to write out data from EPICS Area Detector HDF buffer."); } if (scanRunning) { output = getFilePath(controller.getHDFFileName()); dataTree.addScanFileLink(getName(), "nxfile://" + output + "#entry/instrument/detector/data"); } } } else { // do not want to wait EPICS AD full file name update before collect next image - to support NDArray // buffering String fileTemplate = "File template not set"; String fileName = "File name not set"; int fileNumber = -1; if (controller.getTiff() != null) { if (controller.getTiff().getFileTemplate() != null) { fileTemplate = controller.getTiff().getFileTemplate().trim(); } fileName = controller.getTiff().getFileName(); fileNumber = controller.getTiff().getFileNumber(); } output = String.format(fileTemplate, scanSaveFolder.getAbsolutePath(), fileName, fileNumber); if (scanRunning) { dataTree.addScanFileLink(getName(), "nxfile://" + output + "#entry/instrument/detector/data"); } } } catch (Exception e) { throw new DeviceException("readout failed to add scan file link to NeXus data file.", e); } return output; // dataTree; } /** * method to print message to the Jython Terminal console. * * @param msg */ private void print(String msg) { if (InterfaceProvider.getTerminalPrinter() != null) { InterfaceProvider.getTerminalPrinter().print(msg); } } @Override public void setCollectionTime(double collectionTime) throws DeviceException { try { // TODO beamline reported sometime exposure need to be set twice to succeed if (LiveModeUtil.isLiveMode()) { if (controller.isArmed()) { controller.disarmCamera(); } } ADBase areaDetector = controller.getAreaDetector(); areaDetector.setAcquireTime(collectionTime); this.collectionTime = collectionTime; } catch (Exception e) { logger.error("{} failed to set exposure time to {}.", getName(), collectionTime); throw new DeviceException(getName() + " failed to set exposure time to " + collectionTime, e); } } public void setCollectionTime(Object... collectspec) throws DeviceException { this.collectionTime = Double.parseDouble(collectspec[0].toString()); int numImagesPerPoint = Integer.parseInt(collectspec[1].toString()); int totalNumImages = Integer.parseInt(collectspec[2].toString()); try { if (LiveModeUtil.isLiveMode()) { if (controller.isArmed()) { controller.disarmCamera(); } } ADBase areaDetector = controller.getAreaDetector(); areaDetector.setAcquireTime(collectionTime); controller.setNumImages(numImagesPerPoint); if (numImagesPerPoint > 1) { controller.setImageMode(1); // multiple image per data point } controller.getHdf().getFile().setNumCapture(totalNumImages); } catch (Exception e) { logger.error("{} failed to set exposure time {}.", getName(), collectionTime); throw new DeviceException(getName() + " failed to set exposure time", e); } } // Methods for the Scannable interface @Override public void atScanStart() throws DeviceException { logger.debug("scan start"); if (isPreviewing) { // gda in preview try { stopPreview(); } catch (Exception e) { throw new DeviceException("Failed to stop preview", e); } } try { pauseTime = controller.getReadoutTime(); boolean firstTime = true; // ensure detector buffer writer completed before proceed while (isWriterBusy()) { if (firstTime) { logger.warn( "{}: buffer is still writing out data to disk from previous collection. please wait...", getName()); print("the file writer in EPICS Area detector is busy. Please release it to proceed or abort this scan instead"); firstTime = false; } Sleep.sleep(100); } controller.makeDetectorReadyForCollection(); // this will leave camera disarmed if (hdfFormat) { controller.getHdf().getFile().getPluginBase().enableCallbacks(); controller.getTiff().getPluginBase().disableCallbacks(); controller.getHdf().stopCapture(); controller.getHdf().getFile().getPluginBase().setDroppedArrays(0); controller.getHdf().getFile().getPluginBase().setArrayCounter(0); } else { controller.getHdf().getFile().getPluginBase().disableCallbacks(); controller.getTiff().getPluginBase().enableCallbacks(); controller.getTiff().stopCapture(); controller.getTiff().getPluginBase().setDroppedArrays(0); controller.getTiff().getPluginBase().setArrayCounter(0); controller.getTiff().setFileNumber(0); } setScanNumberAlreadyIncremented(true); // scan number is increamented by scan class before atScanStart // called. // must set file path and file name before starting capturing -EPICS required this initialiseFilePath(); setFileName(); ScanInformation scaninfo = InterfaceProvider.getCurrentScanInformationHolder() .getCurrentScanInformation(); if (hdfFormat) { controller.setScanDimensions(scaninfo.getDimensions()); controller.startRecording(); } else { controller.getTiff().setNumCapture(totalNumberImages2Collect(scaninfo.getDimensions())); controller.getTiff().startCapture(); } scanRunning = true; controller.armCamera(); Sleep.sleep(3000); firstcall = true; aquisitionStartTime = System.currentTimeMillis(); } catch (Exception e) { logger.error("atScanStart failed with error:", e); throw new DeviceException("atScanStart failed with error:", e); } } private int totalNumberImages2Collect(int[] dimensions) { int total = 1; for (int i = 0; i < dimensions.length; i++) { total *= dimensions[i]; } return total; } @Override public void atScanEnd() throws DeviceException { setScanNumberAlreadyIncremented(true); scanRunning = false; if (hdfFormat) { int num; try { if ((num = controller.getHdf().getFile().getPluginBase().getDroppedArrays_RBV()) != 0) { controller.getHdf().stopCapture(); throw new DeviceException("Buffer reports dropped array number: " + num); } } catch (Exception e) { logger.error("Failed to get Dropped Array parameter from HDF plugin.", e); throw new DeviceException("Failed to get Dropped Array parameter from HDF plugin.", e); } long starttimer = System.currentTimeMillis(); long timer = 0; try { while (controller.getHdf().getCapture_RBV() == 1 && timer < starttimer + 10 * getCollectionTime() * 1000) { Sleep.sleep(50); timer = System.currentTimeMillis(); // if (controller.getHdf().getNumCaptured_RBV() + // controller.getHdf().getPluginBase().getDroppedArrays_RBV()== // controller.getHdf().getPluginBase().getArrayCounter_RBV()) { // controller.getHdf().stopCapture(); // } } } catch (Exception e) { logger.error("Failed to getCapture_RBV() from HDF plugin.", e); throw new DeviceException("Failed to getCapture_RBV() from HDF plugin.", e); } if (timer >= starttimer + 10 * getCollectionTime() * 1000) { try { controller.getHdf().stopCapture(); } catch (Exception e) { logger.error("failed to stop capture on HDF plugin", e); throw new DeviceException("failed to stop capture on HDF plugin", e); } throw new DeviceException("TimeoutException: It takes to long to collect the last frame"); } try { FileRegistrarHelper.registerFile(getFilePath(controller.getHDFFileName())); } catch (Exception e) { logger.error("failed to getHDFFileName() in HDF plugin", e); throw new DeviceException("failed to getHDFFileName() in HDF plugin", e); } try { controller.endRecording(); } catch (Exception e) { logger.error("failed to endRecording() in HDF plugin", e); throw new DeviceException("failed to endRecording() in HDF plugin", e); } } else { int num; try { num = controller.getTiff().getPluginBase().getDroppedArrays_RBV(); } catch (Exception e1) { logger.error("Failed to get Dropped Array parameter from Tiff plugin.", e1); throw new DeviceException("Failed to get Dropped Array parameter from Tiff plugin.", e1); } if (num != 0) { try { controller.getTiff().stopCapture(); } catch (Exception e) { logger.error("Failed to stop capture in Tiff plugin.", e); throw new DeviceException("Failed to stop capture in Tiff plugin.", e); } throw new DeviceException(getName() + ": reports dropped array number: " + num); } long starttimer = System.currentTimeMillis(); long timer = 0; try { while (controller.getTiff().getCapture_RBV() == 1 && timer < starttimer + 10 * getCollectionTime() * 1000) { Sleep.sleep((int) getCollectionTime() / 10); timer = System.currentTimeMillis(); // if (controller.getTiff().getNumCaptured_RBV() + // controller.getTiff().getPluginBase().getDroppedArrays_RBV()== // controller.getTiff().getPluginBase().getArrayCounter_RBV()) { // controller.getTiff().stopCapture(); // } } } catch (Exception e) { logger.error("Failed to getCapture_RBV() in Tiff plugin.", e); throw new DeviceException("Failed to getCapture_RBV() in Tiff plugin.", e); } // if (timer>=starttimer+10*getCollectionTime()*1000){ // try { // controller.getTiff().stopCapture(); // } catch (Exception e) { // logger.error("Failed to stop capture in Tiff plugin.", e); // throw new DeviceException("Failed to stop capture in Tiff plugin.", e); // } // throw new DeviceException("TimeoutException: It takes to long to collect the last frame"); // } } try { controller.disarmCamera(); } catch (Exception e) { logger.error("Failed to disarmCamera() in Tiff plugin.", e); throw new DeviceException("Failed to disarmCamera() in Tiff plugin.", e); } if (saveLocal) { try { while (isWriterBusy()) { Sleep.sleep(100); } } catch (Exception e) { logger.error("check buffer writting state failed", e); throw new DeviceException("check buffer writting state failed", e); } transferFiles(); } } @Override public void atPointStart() throws DeviceException { if (!hdfFormat) { try { // Tiff file save must make capture ready for capturing in Stream mode at each point // controller.getTiff().setNumCapture(1); // controller.getTiff().startCapture(); } catch (Exception e) { logger.error("Failed to start Capturing.", e); throw new DeviceException(getName() + ": Failed to start Capturing."); } } } private void initialiseFilePath() throws IOException, Exception { scanSaveFolder = createMainFileStructure(); // this statement rely on GDA file tracker increment properly // already setFilePath(scanSaveFolder); //Initialise the file template NDFile fullFrameSaver; if (hdfFormat) { fullFrameSaver = controller.getHdf().getFile(); } else { fullFrameSaver = controller.getTiff(); } fullFrameSaver.setFileTemplate(fullFrameSaver.getInitialFileTemplate()); } private void setFileName() throws IOException, Exception { NDFile fullFrameSaver; if (hdfFormat) { fullFrameSaver = controller.getHdf().getFile(); } else { fullFrameSaver = controller.getTiff(); } fullFrameSaver.setFileName(fullFrameSaver.getInitialFileName()); } @Override public void stop() throws DeviceException { super.stop(); try { controller.stop(); setScanNumberAlreadyIncremented(false); } catch (Exception e) { logger.error("PCO Detector failed to stop", e); throw new DeviceException("PCO Detector failed to stop", e); } if (saveLocal) { transferFiles(); } } @Override public void resetAll() throws Exception { controller.resetAll(); } public void setFormat(String format) { LocalProperties.set(LocalProperties.GDA_DATA_SCAN_DATAWRITER_DATAFORMAT, format); } public void setNexusFormat() { LocalProperties.set(LocalProperties.GDA_DATA_SCAN_DATAWRITER_DATAFORMAT, "NexusDataWriter"); } /** * manage the file path mapping between Windows (where the EPICS IOC is running) and Linux (Where data is to be * stored). * * @param filePath * @throws Exception */ @Override public void setFilePath(File filePath) throws Exception { String filePathString = null; if (saveLocal) { filePathString = filePath.getAbsolutePath().replace( getLocalDataStoreWindows2LinuxFilePath().getLinuxPath(), getLocalDataStoreWindows2LinuxFilePath().getWindowsPath()); } else { filePathString = filePath.getAbsolutePath().replace( getNonLocalDataStoreWindows2LinuxFilePath().getLinuxPath(), getNonLocalDataStoreWindows2LinuxFilePath().getWindowsPath()); } if (hdfFormat) { controller.getHdf().getFile().setFilePath(filePathString); } else { controller.getTiff().setFilePath(filePathString); } } public String getFilePath(String filePath) { String filePathString = null; if (saveLocal) { filePathString = filePath.replace(getLocalDataStoreWindows2LinuxFilePath().getWindowsPath(), getLocalDataStoreWindows2LinuxFilePath().getLinuxPath()); } else { filePathString = filePath.replace(getNonLocalDataStoreWindows2LinuxFilePath().getWindowsPath(), getNonLocalDataStoreWindows2LinuxFilePath().getLinuxPath()); } return filePathString; } File metadataFile; Vector<String> imageFiles = new Vector<String>(); private boolean scanNumberAlreadyIncremented = false; public boolean isScanNumberAlreadyIncremented() { return scanNumberAlreadyIncremented; } public void setScanNumberAlreadyIncremented(boolean scanNumberAlreadyIncremented) { this.scanNumberAlreadyIncremented = scanNumberAlreadyIncremented; } private long filenumber = -1; private boolean isWindowsIocSet = false; /** * processes after collected data: <li>Archival of data collected</li> <li>Display the last image</li> */ public void afterCollection() { FileRegistrarHelper.registerFiles(imageFiles); // TODO call stop? // stop(); // Ensure GDA reset cache detector status as stop is not called after fast collection or callback failed. if (getStatus() != Detector.IDLE) { controller.getAreaDetector().setStatus(Detector.IDLE); } else { if (hdfFormat) { controller.getHdf().getFile().setStatus(Detector.IDLE); } else { controller.getTiff().setStatus(Detector.IDLE); } } print("collection completed."); } /** * processing to be done before starting acquire data from detector - create data storage parameters and metadata * file * * @throws Exception * @throws IOException * @throws DeviceException */ public void beforeCollection() throws Exception, IOException, DeviceException { // as outside of any scan we need to increment file number here. NumTracker nt = new NumTracker(LocalProperties.get(LocalProperties.GDA_BEAMLINE_NAME)); if (!isScanNumberAlreadyIncremented()) { filenumber = nt.getCurrentFileNumber() + 1; } else { filenumber = nt.getCurrentFileNumber(); } // set file path must be done before start capture initialiseFilePath(); print("Saving data in directory: " + scanSaveFolder.getAbsolutePath()); } /** * collect specified number of dark images - users must ensure the shutter is closed before call this method * * @param numberOfDarks * @throws Exception */ @Override public void collectDarkSet(int numberOfDarks) throws Exception { logger.info("{} starts to collect {} dark images, please wait...", getName(), numberOfDarks); beforeCollection(); if (hdfFormat) { // set file name must be done before start capture controller.getHdf().setFileName(getDarkFileNameRoot()); controller.getHdf().setNumExtraDims(0); controller.getHdf().setNumCapture(numberOfDarks); controller.getHdf().getFile().startCapture(); } else { // set file name must be done before start capture controller.getTiff().setFileName(getDarkFileNameRoot()); controller.getTiff().setFileNumber(0); controller.getTiff().setNumCapture(numberOfDarks); controller.getTiff().startCapture(); } // capture the appropriate number of images controller.setNumImages(numberOfDarks); controller.setImageMode(1); if (isExternalTriggered()) { setExternalTriggered(false); } collectData(); print("starting collect " + numberOfDarks + " dark images. Please wait ......"); // wait for the collection to be complete while (getStatus() == Detector.BUSY) { Sleep.sleep(100); } if (hdfFormat) { imageFiles.add(getFilePath(controller.getHdf().getFile().getFullFileName_RBV())); } else { String formatter = controller.getTiff().getFileTemplate().trim(); String filename = controller.getTiff().getFileName(); for (int i = 0; i < numberOfDarks; i++) { imageFiles .add(getFilePath(String.format(formatter, scanSaveFolder.getAbsolutePath(), filename, i))); } } afterCollection(); } /** * collect the dark image set - users must ensure the shutter is closed and number of images is set in EPICS * * @throws Exception */ @Override public void collectDarkSet() throws Exception { int numberOfDarkImages = controller.getNumImages(); collectDarkSet(numberOfDarkImages); } /** * collect specified numbers of flat images, users must ensure the shutter is open and sample is outside from the * field of view. * * @param numberOfFlats * - number of flat images for each flat set * @param flatSet * - the set number * @throws Exception */ @Override public void collectFlatSet(int numberOfFlats, int flatSet) throws Exception { logger.info("{} starts to collect {} flat images, please wait...", getName(), numberOfFlats); beforeCollection(); if (hdfFormat) { controller.getHdf().setFileName(getFlatFileNameRoot()); controller.getHdf().setNumExtraDims(0); controller.getHdf().setNumCapture(numberOfFlats); controller.getHdf().getFile().startCapture(); } else { controller.getTiff().setFileName(String.format("%s_%03d", getFlatFileNameRoot(), flatSet)); controller.getTiff().setFileNumber(0); controller.getTiff().setNumCapture(numberOfFlats); controller.getTiff().startCapture(); } // capture the appropriate number of images controller.setNumImages(numberOfFlats); controller.setImageMode(1); if (isExternalTriggered()) { setExternalTriggered(false); } collectData(); print("starting collect " + numberOfFlats + " flat images. Please wait ......"); // wait for the collection to be complete while (getStatus() == Detector.BUSY) { Sleep.sleep(100); } if (hdfFormat) { imageFiles.add(getFilePath(controller.getHdf().getFile().getFullFileName_RBV())); } else { String formatter = controller.getTiff().getFileTemplate().trim(); String filename = controller.getTiff().getFileName(); for (int i = 0; i < numberOfFlats; i++) { imageFiles .add(getFilePath(String.format(formatter, scanSaveFolder.getAbsolutePath(), filename, i))); } } afterCollection(); } /** * collect specified numbers of flat images, users must ensure the shutter is open and sample is outside from the * field of view and set the number of flat images required in EPICS. * * @throws Exception */ public void collectFlatSet(int flatSet) throws Exception { int numberOfFlats = controller.getNumImages(); collectFlatSet(numberOfFlats, flatSet); } public void resetFileNumber() throws Exception { if (hdfFormat) { controller.getHdf().setFileNumber(0); } else { controller.getTiff().setFileNumber(0); } setScanNumberAlreadyIncremented(false); } /** * plot image to the PCOPlot view. * * @param imageFileName */ @Override public void plotImage(final String imageFileName) { // Plot the last image collected from file Thread plot = new Thread(new Runnable() { boolean plotted = false; int trycounter = 0; double starttime = System.currentTimeMillis(); double time = 0.0, timeout = 15000.0; double fileexisttime; private boolean firsttime = true; @Override public void run() { while (!plotted && time < timeout) { if ((new File(imageFileName)).exists()) { if (firsttime) { fileexisttime = System.currentTimeMillis(); firsttime = false; } try { IFileLoader loader = LoaderFactory.getLoader(TIFFImageLoader.class, imageFileName); IDataHolder dataHolder = loader.loadFile(); IDataset dataset = dataHolder.getDataset(0); if (dataset != null) { dataset.clearMetadata(null); SDAPlotter.imagePlot(getPlotName(), dataset); // SDAPlotter.imagePlot(getPlotName(), imageFileName); } plotted = true; } catch (Exception e) { trycounter++; logger.error("Plot data {} try {} failed", imageFileName, trycounter); plotted = false; } print("Time elasped since plotting request: " + (System.currentTimeMillis() - starttime)); logger.debug("Time elasped since plotting request: {}", (System.currentTimeMillis() - starttime)); print("Time elasped since file first appears: " + (System.currentTimeMillis() - fileexisttime)); logger.debug("Time elasped since file first appears: {}", (System.currentTimeMillis() - fileexisttime)); } else { // logger.debug("wait for data file {} to plot.", imageFileName); } time = (System.currentTimeMillis() - starttime); } } }, "plotpcoimage"); plot.start(); } // Helper methods for dealing with the file system. @Override public File createMainFileStructure() throws IOException { // set up the filename which will be the base directory for data to be saved to File path = new File(PathConstructor.createFromDefaultProperty()); NumTracker nt = new NumTracker(LocalProperties.GDA_BEAMLINE_NAME); String filenumber; if (!isScanNumberAlreadyIncremented()) { // for non-scan use filenumber = Long.toString(this.filenumber); } else { // for scan which already increments the file number filenumber = Long.toString(nt.getCurrentFileNumber()); } File scanFolder = new File(path, filenumber); // Make the directory if required. if (!scanFolder.isDirectory()) { // create the directory scanFolder.mkdir(); } if (hdfFormat) { // HDF to save both h5 and nxs data in scanNumber folder return scanFolder; } // tiff to save image in projections folder under scanNumber folder File projectionsFolder = new File(scanFolder, projectionFolderName); if (!projectionsFolder.isDirectory()) { // create the directory required for Tomography reconstruction software projectionsFolder.mkdir(); } return projectionsFolder; } @Override public boolean isBusy() { return getStatus() == Detector.BUSY; } private void transferFiles() throws DeviceException { try { // copy the files off Runtime rt = Runtime.getRuntime(); String script = LocalProperties.get(GDA_FILE_TRANSFER_SCRIPT, null); if (script == null) { logger.warn("property '{}' is not defined.", GDA_FILE_TRANSFER_SCRIPT); return; } Process p = rt.exec(String.format("%s %s", script, scanSaveFolder.getAbsolutePath())); InterfaceProvider.getTerminalPrinter().print("Start to copy data to Central Storage"); // TODO this should be in a monitoring loop p.waitFor(); } catch (Exception e) { throw new DeviceException("Failed to run pco.transferFiles.", e); } } @Override public boolean isWriterBusy() throws Exception { if (hdfFormat) { return controller.getHdf().getFile().getWriteFile_RBV() == 1; // get buffer writer state from HDF } return controller.getTiff().getWriteFile_RBV() == 1; // get buffer writer state from tif } @Override public boolean createsOwnFiles() throws DeviceException { return true; } @Override public void afterPropertiesSet() throws Exception { if (description == null) { throw new IllegalArgumentException("'description' is required"); } if (detectorID == null) { throw new IllegalArgumentException("'detectorID' is required"); } if (detectorType == null) { throw new IllegalArgumentException("'detectorType' is required"); } if (controller == null) { throw new IllegalArgumentException("'pcoController' needs to be set"); } } public void setController(IPCOControllerV17 controller) { this.controller = controller; } @Override public IPCOControllerV17 getController() { return controller; } @Override public String getDescription() throws DeviceException { return description; } public void setDescription(String description) { this.description = description; } @Override public String getDetectorID() throws DeviceException { return detectorID; } public void setDetectorID(String detectorID) { this.detectorID = detectorID; } @Override public String getDetectorType() throws DeviceException { return detectorType; } public void setDetectorType(String detectorType) { this.detectorType = detectorType; } public void setLocalFilePath(String localFilePath) { this.localFilePath = localFilePath; } @Override public String getLocalFilePath() { return localFilePath; } @Override public String getProjectionFolderName() { return projectionFolderName; } public void setProjectionFolderName(String projectionFoldername) { this.projectionFolderName = projectionFoldername; } public void setDarkFileNameRoot(String darkFileNameRoot) { this.darkFileNameRoot = darkFileNameRoot; } @Override public String getDarkFileNameRoot() { return darkFileNameRoot; } public void setFlatFileNameRoot(String faltFileNameRoot) { this.faltFileNameRoot = faltFileNameRoot; } @Override public String getFlatFileNameRoot() { return faltFileNameRoot; } public void setNumberOfDarkImages(int numberOfDarkImages) { this.numberOfDarkImages = numberOfDarkImages; } @Override public int getNumberOfDarkImages() { return numberOfDarkImages; } public void setNumberOfFlatImages(int numberOfFlatImages) { this.numberOfFlatImages = numberOfFlatImages; } @Override public int getNumberOfFlatImages() { return numberOfFlatImages; } static class Windows2LinuxFilePath { private String windowsPath; private String linuxPath; public String getWindowsPath() { return windowsPath; } public void setWindowsPath(String windowsPath) { this.windowsPath = windowsPath; } public void setLinuxPath(String linuxPath) { this.linuxPath = linuxPath; } public String getLinuxPath() { return linuxPath; } /** * @param fileName * @return the linux file name for a given windows file name respective to the location of the datastore. */ public String getFilePathString(String fileName) { String filePathString = fileName.replace(windowsPath, linuxPath); return filePathString; } } public Windows2LinuxFilePath getLocalDataStoreWindows2LinuxFilePath() { return localDataStoreWindows2LinuxFilePath; } public void setLocalDataStoreWindows2LinuxFileName(Windows2LinuxFilePath localDataStoreWindows2LinuxFilePath) { this.localDataStoreWindows2LinuxFilePath = localDataStoreWindows2LinuxFilePath; } public Windows2LinuxFilePath getNonLocalDataStoreWindows2LinuxFilePath() { return nonLocalDataStoreWindows2LinuxFilePath; } public void setNonLocalDataStoreWindows2LinuxFileName( Windows2LinuxFilePath nonLocalDataStoreWindows2LinuxFilePath) { this.nonLocalDataStoreWindows2LinuxFilePath = nonLocalDataStoreWindows2LinuxFilePath; } public void setPlotName(String plotName) { this.plotName = plotName; } @Override public String getPlotName() { return plotName; } public String getFullFilename() throws Exception { if (isHdfFormat()) { return controller.getHdf().getFullFileName_RBV(); } return controller.getTiff().getFullFileName_RBV(); } public void setNumImages(int num) throws Exception { controller.setNumImages(num); } public void setNumCapture(int num) throws Exception { if (hdfFormat) { controller.getHdf().getFile().setNumCapture(num); } else { controller.getTiff().setNumCapture(num); } } /** * Acquire and wait till the acquisition is complete. * * @throws Exception */ @Override public void acquireSynchronously() throws Exception { controller.getAreaDetector().startAcquiringSynchronously(); if (hdfFormat) { while (controller.getHdf().getStatus() != Detector.IDLE) { Sleep.sleep(100); } } else { while (controller.getTiff().getStatus() != Detector.IDLE) { Sleep.sleep(100); } } } @Override public void stopCapture() throws Exception { if (hdfFormat) { controller.getHdf().stopCapture(); } else { controller.getTiff().stopCapture(); } } public void setWindowsIoc(boolean isWindowsIoc) { this.isWindowsIoc = isWindowsIoc; isWindowsIocSet = true; } public boolean isWindowsIoc() { if (isWindowsIocSet) { return isWindowsIoc; } // Only the live mode is windows return LiveModeUtil.isLiveMode(); } /** * @return Returns the demandRawDataStoreWindows2LinuxFileName. */ public Windows2LinuxFilePath getDemandRawDataStoreWindows2LinuxFileName() { return demandRawDataStoreWindows2LinuxFileName; } /** * s * * @param demandRawDataStoreWindows2LinuxFileName * The demandRawDataStoreWindows2LinuxFileName to set. */ public void setDemandRawDataStoreWindows2LinuxFileName( Windows2LinuxFilePath demandRawDataStoreWindows2LinuxFileName) { this.demandRawDataStoreWindows2LinuxFileName = demandRawDataStoreWindows2LinuxFileName; } @Override public String getTiffImageFileName() throws Exception { if (isWindowsIoc()) { return controller.getTiffFullFileName().replaceAll( demandRawDataStoreWindows2LinuxFileName.getWindowsPath(), demandRawDataStoreWindows2LinuxFileName.getLinuxPath()); } return controller.getTiffFullFileName(); } @Override public void setTiffFilePathBasedOnIocOS(String demandRawFilePath) throws Exception { if (isWindowsIoc()) { String replacedWindowsPath = demandRawFilePath.replaceAll( demandRawDataStoreWindows2LinuxFileName.getLinuxPath(), demandRawDataStoreWindows2LinuxFileName.getWindowsPath()); controller.getTiff().setFilePath(replacedWindowsPath); } else { controller.getTiff().setFilePath(demandRawFilePath); } } @Override public void setADCMode(int mode) throws Exception { // The ADC mode is available only the actual PCO IOC and not the simulation if (LiveModeUtil.isLiveMode()) { controller.setADCMode(mode); } } public void setSaveLocal(boolean saveLocal) { this.saveLocal = saveLocal; } public boolean isSaveLocal() { return saveLocal; } public void setTriggerPV(String triggerPV) { controller.setTriggerPV(triggerPV); } public String getTriggerPV() { return controller.getTriggerPV(); } public void setTimestampMode(int timestampMode) throws Exception { controller.setTimestampMode(timestampMode); } }