From b2a67e06fbbacd45e9e9f1c147aaf937b0249d91 Mon Sep 17 00:00:00 2001 From: ebner Date: Mon, 17 Aug 2015 16:12:05 +0200 Subject: [PATCH] removed legacy code for continuous scans --- ch.psi.fda.xscan/pom.xml | 7 +- .../main/java/ch/psi/fda/aq/Acquisition.java | 212 ++-- .../ch/psi/fda/core/TestConfiguration.java | 18 +- .../ch/psi/fda/core/loops/cr/CrlogicLoop.java | 847 --------------- .../fda/core/loops/cr/CrlogicLoopStream.java | 28 +- .../fda/core/loops/cr/ParallelCrlogic.java | 17 +- .../fda/core/loops/otf/DistributedFile.java | 158 --- .../ch/psi/fda/core/loops/otf/OTFLoop.java | 439 -------- .../core/loops/otf/OTFNamedChannelSensor.java | 67 -- .../loops/otf/OTFScalerChannelSensor.java | 67 -- .../psi/fda/core/loops/otf/TemplateOTF.java | 962 ------------------ .../fda/core/loops/DistributedFileTest.java | 142 --- .../ch/psi/fda/core/loops/OTFLoopTest.java | 229 ----- .../core/loops/cr/CrlogicLoopStreamTest.java | 11 - .../core/loops/cr/ParallelCrlogicTest.java | 2 +- 15 files changed, 90 insertions(+), 3116 deletions(-) delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoop.java delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/DistributedFile.java delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFLoop.java delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFNamedChannelSensor.java delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFScalerChannelSensor.java delete mode 100644 ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/TemplateOTF.java delete mode 100644 ch.psi.fda.xscan/src/test/java/ch/psi/fda/core/loops/DistributedFileTest.java delete mode 100644 ch.psi.fda.xscan/src/test/java/ch/psi/fda/core/loops/OTFLoopTest.java diff --git a/ch.psi.fda.xscan/pom.xml b/ch.psi.fda.xscan/pom.xml index bae334d..f21ec4a 100644 --- a/ch.psi.fda.xscan/pom.xml +++ b/ch.psi.fda.xscan/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ch.psi.fda ch.psi.fda.xscan - 2.4.2_zmq + 2.4.7_zmq @@ -30,11 +30,6 @@ jcae 2.4.1 - - jcifs - jcifs - 1.3.17 - org.python jython diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/aq/Acquisition.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/aq/Acquisition.java index f3e3660..72901a3 100644 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/aq/Acquisition.java +++ b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/aq/Acquisition.java @@ -55,15 +55,10 @@ import ch.psi.fda.core.actors.PseudoActuatorSensor; import ch.psi.fda.core.guard.ChannelAccessGuard; import ch.psi.fda.core.guard.ChannelAccessGuardCondition; import ch.psi.fda.core.loops.ActorSensorLoop; -import ch.psi.fda.core.loops.cr.CrlogicLoop; import ch.psi.fda.core.loops.cr.CrlogicLoopStream; import ch.psi.fda.core.loops.cr.CrlogicResource; import ch.psi.fda.core.loops.cr.ParallelCrlogic; import ch.psi.fda.core.loops.cr.ScrlogicLoop; -import ch.psi.fda.core.loops.otf.OTFLoop; -import ch.psi.fda.core.loops.otf.OTFNamedChannelSensor; -import ch.psi.fda.core.loops.otf.OTFScalerChannelSensor; -import ch.psi.fda.core.loops.otf.TemplateOTF; import ch.psi.fda.core.manipulator.JythonManipulation; import ch.psi.fda.core.scripting.JythonGlobalVariable; import ch.psi.fda.core.scripting.JythonParameterMapping; @@ -963,148 +958,77 @@ public class Acquisition { * @param dimension * @return */ - private ActionLoop mapContinuousDimension(ContinuousDimension dimension){ - - ActionLoop aLoop = null; - - if(!configuration.isOtfUseCrlogic()){ - - // USE OTFLOGIC FOR CONTINUOUS "SCANS" - - // Create loop - boolean zigZag = dimension.isZigzag(); // default value is false - - Map macros = new HashMap<>(); - macros.put("PREFIX", configuration.getOtfChannelPrefix()); - TemplateOTF template = new TemplateOTF(); - createTemplateChannels(template, macros); - OTFLoop actionLoop = new OTFLoop(template, configuration.getOtfNfsServer(), configuration.getOtfNfsShare(), configuration.getOtfSmbShare(), zigZag); - - actionLoop.getPreActions().addAll(mapActions(dimension.getPreAction())); - - // Map positioner - ContinuousPositioner p = dimension.getPositioner(); - double backlash = 0; - if(p.getAdditionalBacklash()!=null){ - backlash = p.getAdditionalBacklash(); - } - actionLoop.setActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash); - - // Map sensors - // ATTENTION: the sequence of the mapping depends on the sequence in the schema file ! - int cnt = 0; - for(SimpleScalarDetector detector: dimension.getDetector()){ - if(cnt<8){ // Only up to 8 additional channels supported - actionLoop.getSensors().add(new OTFNamedChannelSensor(detector.getId(), detector.getName())); - } - cnt++; - } - - cnt = 0; - for(ScalerChannel detector: dimension.getScaler()){ - if(cnt<16){ // Only up to 16 scaler channels supported - actionLoop.getSensors().add(new OTFScalerChannelSensor(detector.getId(), detector.getChannel())); - } - cnt++; - } - - Timestamp detector = dimension.getTimestamp(); - if(detector != null){ - actionLoop.getSensors().add(new TimestampSensor(detector.getId())); - } - - actionLoop.getPostActions().addAll(mapActions(dimension.getPostAction())); - - aLoop = actionLoop; - } - else{ - // USE CRLOGIC FOR CONTINUOUS "SCANS" - - boolean hcrOnly = true; - for(SimpleScalarDetector detector: dimension.getDetector()){ - if(detector.isScr()){ - hcrOnly=false; - break; - } - } - - - // BEGIN configure HCRLOGIC - - // Create loop - boolean zigZag = dimension.isZigzag(); // default value is false - - CrlogicLoop actionLoop; - - if(configuration.isUseStream()){ - actionLoop = new CrlogicLoopStream(cservice, configuration.getOtfCrlogicPrefix(), configuration.getStreamIoc(), zigZag); - } - else{ - actionLoop = new CrlogicLoop(cservice, configuration.getOtfCrlogicPrefix(), configuration.getOtfNfsServer(), configuration.getOtfNfsShare(), configuration.getOtfSmbShare(), zigZag); - } - - - actionLoop.setKeepTmpFiles(configuration.isOtfCrlogicKeepTmpFiles()); - - actionLoop.getPreActions().addAll(mapActions(dimension.getPreAction())); - - // Map positioner - ContinuousPositioner p = dimension.getPositioner(); - double backlash = 0; - if(p.getAdditionalBacklash()!=null){ - backlash = p.getAdditionalBacklash(); - } - actionLoop.setActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash); - - // Map sensors - // ATTENTION: the sequence of the mapping depends on the sequence in the schema file ! - for(SimpleScalarDetector detector: dimension.getDetector()){ - if(!detector.isScr()){ - actionLoop.getSensors().add(new CrlogicResource(detector.getId(), detector.getName())); - } - } - - for(ScalerChannel detector: dimension.getScaler()){ - actionLoop.getSensors().add(new CrlogicResource(detector.getId(), "SCALER"+detector.getChannel(), true)); - } - - Timestamp tdetector = dimension.getTimestamp(); - if(tdetector != null){ - actionLoop.getSensors().add(new CrlogicResource(tdetector.getId(), "TIMESTAMP")); - } - - actionLoop.getPostActions().addAll(mapActions(dimension.getPostAction())); - - // END Configure HCRLOGIC - - - if(hcrOnly){ - // There are no additional channels to be read out while taking data via hcrlogic - // Therefore we just register the hcr loop as action loop + private ActionLoop mapContinuousDimension(ContinuousDimension dimension) { - aLoop = actionLoop; + ActionLoop aLoop = null; + + boolean hcrOnly = true; + for (SimpleScalarDetector detector : dimension.getDetector()) { + if (detector.isScr()) { + hcrOnly = false; + break; } - else{ - List> sensors = new ArrayList<>(); - List ids = new ArrayList<>(); - - for(SimpleScalarDetector detector: dimension.getDetector()){ - if(detector.isScr()){ - ids.add(detector.getId()); - sensors.add(createChannel(DoubleTimestamp.class, detector.getName())); - } - } - // Create soft(ware) based crlogic - ScrlogicLoop scrlogic = new ScrlogicLoop(ids, sensors); - - // Create parallel logic - ParallelCrlogic pcrlogic = new ParallelCrlogic(actionLoop, scrlogic); - - aLoop = pcrlogic; - } - } - + + // Create loop + boolean zigZag = dimension.isZigzag(); // default value is false + + CrlogicLoopStream actionLoop = new CrlogicLoopStream(cservice, configuration.getOtfCrlogicPrefix(), configuration.getStreamIoc(), zigZag); + + actionLoop.getPreActions().addAll(mapActions(dimension.getPreAction())); + + // Map positioner + ContinuousPositioner p = dimension.getPositioner(); + double backlash = 0; + if (p.getAdditionalBacklash() != null) { + backlash = p.getAdditionalBacklash(); + } + actionLoop.setActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash); + + // Map sensors + // ATTENTION: the sequence of the mapping depends on the sequence in the + // schema file ! + for (SimpleScalarDetector detector : dimension.getDetector()) { + if (!detector.isScr()) { + actionLoop.getSensors().add(new CrlogicResource(detector.getId(), detector.getName())); + } + } + + for (ScalerChannel detector : dimension.getScaler()) { + actionLoop.getSensors().add(new CrlogicResource(detector.getId(), "SCALER" + detector.getChannel(), true)); + } + + Timestamp tdetector = dimension.getTimestamp(); + if (tdetector != null) { + actionLoop.getSensors().add(new CrlogicResource(tdetector.getId(), "TIMESTAMP")); + } + + actionLoop.getPostActions().addAll(mapActions(dimension.getPostAction())); + + if (hcrOnly) { + // There are no additional channels to be read out while taking data + // via hcrlogic + // Therefore we just register the hcr loop as action loop + + aLoop = actionLoop; + } else { + List> sensors = new ArrayList<>(); + List ids = new ArrayList<>(); + + for (SimpleScalarDetector detector : dimension.getDetector()) { + if (detector.isScr()) { + ids.add(detector.getId()); + sensors.add(createChannel(DoubleTimestamp.class, detector.getName())); + } + } + // Create soft(ware) based crlogic + ScrlogicLoop scrlogic = new ScrlogicLoop(ids, sensors); + + // Create parallel logic + ParallelCrlogic pcrlogic = new ParallelCrlogic(actionLoop, scrlogic); + + aLoop = pcrlogic; + } return aLoop; } diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/TestConfiguration.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/TestConfiguration.java index 1191122..b213fe1 100644 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/TestConfiguration.java +++ b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/TestConfiguration.java @@ -24,9 +24,7 @@ public class TestConfiguration { private final String otfPrefix = "MTEST-HW3-OTFX"; private final String crlogicPrefix = "MTEST-HW3-CRL"; private final String prefixScaler = "MTEST-HW3:JS"; - private final String server = "yoke.psi.ch"; - private final String share = "/usr/nfs"; - private final String smbShare = "smb://test:test@"+server+"/nfs/"; // It is important to have the last slash / ! + private final String server = "MTEST-VME-HW3"; private final String motor1 = "MTEST-HW3:MOT1"; private final String analogIn1 = "MTEST-HW3-AI1:AI_01"; @@ -61,20 +59,6 @@ public class TestConfiguration { return server; } - /** - * @return the share - */ - public String getShare() { - return share; - } - - /** - * @return the smbShare - */ - public String getSmbShare() { - return smbShare; - } - /** * @return the motor1 */ diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoop.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoop.java deleted file mode 100644 index ec51393..0000000 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoop.java +++ /dev/null @@ -1,847 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ - -package ch.psi.fda.core.loops.cr; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; - -import com.google.common.eventbus.EventBus; - -import jcifs.smb.SmbFile; -import ch.psi.fda.core.Action; -import ch.psi.fda.core.ActionLoop; -import ch.psi.fda.messages.DataMessage; -import ch.psi.fda.messages.EndOfStreamMessage; -import ch.psi.fda.messages.Metadata; -import ch.psi.jcae.ChannelException; -import ch.psi.jcae.ChannelService; - -/** - * While using Crlogic the IOC system clock rate should/must be set to 1000 (default 60) - * - * sysClkRateSet 1000 - * - */ -public class CrlogicLoop implements ActionLoop { - - private static final Logger logger = Logger.getLogger(CrlogicLoop.class.getName()); - - /** - * Flag to indicate whether the data of this loop will be grouped - * According to this flag the dataGroup flag in EndOfStream will be set. - */ - private boolean dataGroup = false; - - private boolean keepTmpFiles = false; - - private BlockingQueue readQueue = new LinkedBlockingQueue(); - private volatile boolean stopReadoutThread = false; - private Thread readoutThread; - - /** - * Default timeout (in milliseconds) for wait operations - */ - private long startStopTimeout = 8000; - - /** - * Name of the NFS server to place the data of the OTF logic - */ - private final String server; - /** - * Share on the NFS server to put the OTF data on to - */ - private final String share; - /** - * SMB share to access the data written by the OTF C logic - */ - private final String smbShare; - - /** - * Flag whether the actor of this loop should move in zig zag mode - */ - private final boolean zigZag; - - boolean useReadback; - boolean useEncoder; - - /** - * List of actions that are executed at the beginning of the loop. - */ - private List preActions; - /** - * List of actions that are executed at the end of the loop. - */ - private List postActions; - - /** - * Prefix for the CRLOGIC channels - */ - private String prefix; - - private TemplateCrlogic template; - private TemplateMotor motortemplate; - - /** - * Semaphore to ensure that data is read in correct sequence - */ - private Semaphore semaphore = new Semaphore(1); - - /** - * List of sensors of this loop - */ - private List sensors; - - private List readoutResources; - private Map scalerIndices; - private CrlogicRangeDataFilter crlogicDataFilter; - - - /** - * Abort status - */ - private boolean abort = false; - private boolean abortForce = false; - private Thread executionThread = null; - - private final ChannelService cservice; - - - private String id; - private String name; // name of the motor channel - private String readback; // name of the encoder channel - private double start; - private double end; - private double stepSize; - private double integrationTime; - private double additionalBacklash; - - - private final EventBus eventbus; - private List metadata; - - public CrlogicLoop(ChannelService cservice, String prefix, String server, String share, String smbShare, boolean zigZag){ - eventbus = new EventBus(); - this.cservice = cservice; - this.prefix = prefix; - this.server = server; - this.share = share; - this.smbShare = smbShare; - this.zigZag = zigZag; - - // Initialize lists used by the loop - this.preActions = new ArrayList(); - this.postActions = new ArrayList(); - this.sensors = new ArrayList<>(); - this.readoutResources = new ArrayList(); - this.scalerIndices = new HashMap(); - - this.crlogicDataFilter = new CrlogicRangeDataFilter(); - } - - public void setActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){ - this.id = id; - this.name = name; - this.readback = readback; - this.start = start; - this.end = end; - this.stepSize = stepSize; - this.integrationTime = integrationTime; - this.additionalBacklash = additionalBacklash; - } - - - /** - * Collect data from share - * @param tmpFileName Name of the temporary file - * @throws InterruptedException - * @throws IOException - */ - private void collectData(String tmpDir, String tmpFileName) throws InterruptedException, IOException { - semaphore.acquire(); - - InputStreamReader inreader; - if (tmpDir.startsWith("smb:")) { - SmbFile tmpFile = new SmbFile(tmpDir, tmpFileName); - logger.info("Collect data from " + tmpFile.getCanonicalPath()); - - SmbFile lockfile = new SmbFile(tmpFile.getCanonicalPath() + ".lock"); - - logger.info("Wait until file is written [lock file: " + lockfile.getCanonicalPath() + "]"); - // Wait until file is created - while ((!tmpFile.exists()) || lockfile.exists()) { - try{ - Thread.sleep(100); - } - catch(InterruptedException e){ - abort=true; - } - if(abort){ - // If abort is issued while waiting for data immediately return without - // trying to read the data - return; - } - } - - inreader = new InputStreamReader(tmpFile.getInputStream()); - readData(inreader); - - // Remove temporary file - if(!keepTmpFiles){ - tmpFile.delete(); - } - } - else{ - File tmpFile = new File(tmpDir, tmpFileName); - logger.info("Collect data from " + tmpFile.getCanonicalPath()); - - File lockfile = new File(tmpFile.getCanonicalPath() + ".lock"); - - logger.info("Wait until file is written [lock file: " + lockfile.getCanonicalPath() + "]"); - // Wait until file is created - while ((!tmpFile.exists()) || lockfile.exists()) { - try{ - Thread.sleep(100); - } - catch(InterruptedException e){ - abort=true; - } - if(abort){ - // If abort is issued while waiting for data immediately return without - // trying to read the data - return; - } - } - - inreader = new InputStreamReader(new FileInputStream(tmpFile)); - readData(inreader); - - // Remove temporary file - if(!keepTmpFiles){ - tmpFile.delete(); - } - } - - // Issue end of loop control message - eventbus.post(new EndOfStreamMessage(dataGroup)); - semaphore.release(); - } - - /** - * @param inreader - * @throws IOException - */ - private void readData(InputStreamReader inreader) throws IOException { - BufferedReader in = new BufferedReader(inreader); - String line; - boolean firstline = true; - int linecount=0; - int mcounter=0; - -// boolean wasInRangeBefore = false; - boolean discardAnyway = false; - - while (true) { - line = in.readLine(); - linecount++; - if (line == null) { - break; - } else { - // if(line.matches("^\\[.*")){ - if (line.matches("^ *#.*")) { - // Skip header/comment lines -// logger.info("HEADER: " + line); - } else { - if (firstline) { - firstline = false; - continue; - } - -// logger.info(line); - - // Write into queue - DataMessage message = new DataMessage(metadata); - String[] tokens = line.split("\t"); - boolean use = true; - - for(int i=0;imotorHighLimit || startmotorHighLimit || end0){ - double maxIntegrationTime = stepSize/motorMinSpeed; - if(integrationTime>maxIntegrationTime){ - logger.info("Integration time is too big"); - // Integration time is too big - throw new IllegalArgumentException("Integration time is too big"); - } - } - double motorMaxSpeed = motortemplate.getVelocity().getValue(); - double minIntegrationTime = Math.min( (stepSize/motorMaxSpeed), ((double)minimumTicks/(double)tps) ); - if(integrationTime(); - - // Build up metadata - metadata.add(new Metadata(this.id)); - for(CrlogicResource s: sensors){ - metadata.add(new Metadata(s.getId())); - } - - - stopReadoutThread = false; - // Start readout Thread - readoutThread = new Thread(new Runnable() { - - @Override - public void run() { - while(!stopReadoutThread){ - String file; - try { - file = readQueue.take(); - } catch (InterruptedException e) { - break; - } - // TODO Read file and - try { - collectData(smbShare, file); - } catch (InterruptedException e) { - throw new RuntimeException("Unable to read CRLOGIC raw data file",e); - } catch (IOException e) { - throw new RuntimeException("Unable to read CRLOGIC raw data file",e); - } - - } - - } - }); - readoutThread.start(); - - try{ - // Connect crlogic channels - template = new TemplateCrlogic(); - logger.info("Connect channels"); - Map map = new HashMap<>(); - map.put("PREFIX", prefix); - cservice.createAnnotatedChannels(template, map); - - // Connect motor channels - motortemplate = new TemplateMotor(); - map = new HashMap<>(); - map.put("PREFIX", this.name); - cservice.createAnnotatedChannels(motortemplate, map); - - useReadback = motortemplate.getUseReadback().getValue(); - useEncoder = motortemplate.getUseEncoder().getValue(); - - logger.info("Motor type: "+ TemplateMotor.Type.values()[motortemplate.getType().getValue()]); - logger.info("Motor use readback: "+useReadback); - logger.info("Motor use encoder: "+useEncoder); - - // TODO build up list of readout resources (based on sensors) - readoutResources.clear(); - // first sensor is the actuator - - // Determine mode of motor - if((!useReadback) && (!useEncoder)){ - // Open loop - if(this.readback!=null){ - throw new IllegalArgumentException("Readback not supported if motor is configured in open loop"); - } - else{ - readoutResources.add(this.name); - } - - } - else if(useReadback && (!useEncoder)){ - String readback; - // use readback link - if(this.readback!=null){ - // Use specified readback - readback = this.readback; - } - else{ - // Set resouce to readback link - readback = (motortemplate.getReadbackLink().getValue()); - readback = readback.replaceAll(" +.*", ""); // remove NPP etc at the end - } - - readoutResources.add(readback); - - // Fill readback encoder settings - // Connect to encoder - TemplateEncoder encodertemplate = new TemplateEncoder(); - map = new HashMap<>(); - map.put("PREFIX", readback); - cservice.createAnnotatedChannels(encodertemplate, map); - - // Read encoder settings - if(encodertemplate.getDirection().getValue()==TemplateEncoder.Direction.Positive.ordinal()){ - crlogicDataFilter.setEncoderDirection(1); - } - else{ - crlogicDataFilter.setEncoderDirection(-1); - } - crlogicDataFilter.setEncoderOffset(encodertemplate.getOffset().getValue()); - crlogicDataFilter.setEncoderResolution(encodertemplate.getResolution().getValue()); - - // Disconnect from encoder - cservice.destroyAnnotatedChannels(encodertemplate); - - } - else if (useEncoder && (!useReadback)){ - // use readback link - if(this.readback!=null){ - throw new IllegalArgumentException("Readback not supported if motor is configured to use encoder"); - } - else{ - // Set resouce to readback link - readoutResources.add(this.name+"_ENC"); - } - } - else{ - throw new IllegalArgumentException("Motor configuration not supportet: use readback - "+useReadback+" use encoder - "+useEncoder); - } - - // Fill Motor specific settings - if(motortemplate.getDirection().getValue()==TemplateMotor.Direction.Positive.ordinal()){ - crlogicDataFilter.setMotorDirection(1); - } - else{ - crlogicDataFilter.setMotorDirection(-1); - } - crlogicDataFilter.setMotorEncoderResolution(motortemplate.getEncoderResolution().getValue()); - crlogicDataFilter.setMotorOffset(motortemplate.getOffset().getValue()); - crlogicDataFilter.setMotorReadbackResolution(motortemplate.getReadbackResolution().getValue()); - crlogicDataFilter.setMotorResolution(motortemplate.getMotorResolution().getValue()); - - // Clear all indices - scalerIndices.clear(); - - int c = 1; // We start at 1 because the actuator right now is an implicit sensor - for(CrlogicResource s: sensors){ - readoutResources.add(s.getKey()); - if(s.isDelta()){ - scalerIndices.put(c, new CrlogicDeltaDataFilter()); - } - c++; - } - - // Workaround - somehow one has to add an empty thing to the value otherwise the c logic - // does not pick up the end - readoutResources.add(""); - } - catch(Exception e){ - throw new RuntimeException("Unable to prepare crloop: ",e); - } - } - - @Override - public void cleanup() { - stopReadoutThread = true; - readoutThread.interrupt(); - - try { - cservice.destroyAnnotatedChannels(template); - cservice.destroyAnnotatedChannels(motortemplate); - template = null; - motortemplate = null; - - } catch (Exception e) { - throw new RuntimeException("Unable to destroy CrlogicLoop", e); - } - } - - @Override - public List getPreActions() { - return preActions; - } - - @Override - public List getPostActions() { - return postActions; - } - - @Override - public boolean isDataGroup() { - return dataGroup; - } - - @Override - public void setDataGroup(boolean dataGroup) { - this.dataGroup = dataGroup; - } - - public List getSensors() { - return sensors; - } - - public boolean isKeepTmpFiles() { - return keepTmpFiles; - } - - public void setKeepTmpFiles(boolean keepTmpFiles) { - this.keepTmpFiles = keepTmpFiles; - } - - public EventBus getEventBus(){ - return eventbus; - } -} diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoopStream.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoopStream.java index a2a8194..ea84b5c 100644 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoopStream.java +++ b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/CrlogicLoopStream.java @@ -33,7 +33,6 @@ import java.util.logging.Logger; import org.zeromq.ZMQ; import org.zeromq.ZMQ.Context; import org.zeromq.ZMQ.Socket; -import org.zeromq.ZMQException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.eventbus.EventBus; @@ -52,7 +51,7 @@ import ch.psi.jcae.ChannelService; * sysClkRateSet 1000 * */ -public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { +public class CrlogicLoopStream implements ActionLoop { private static final Logger logger = Logger.getLogger(CrlogicLoopStream.class.getName()); @@ -127,7 +126,6 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { private List metadata; public CrlogicLoopStream(ChannelService cservice, String prefix, String ioc, boolean zigZag){ - super(cservice, prefix, "", "", "", zigZag); eventbus = new EventBus(); this.cservice = cservice; this.prefix = prefix; @@ -476,6 +474,11 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { catch(ChannelException | ExecutionException | TimeoutException e){ throw new RuntimeException("Unable to execute crloop", e); } + finally{ + // Send end of stream message + System.out.println("end of line - "+dataGroup); + eventbus.post(new EndOfStreamMessage(dataGroup)); + } } @Override @@ -491,6 +494,9 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { if(executionThread != null){ executionThread.interrupt(); } + + // Close ZMQ stream to read data from + close(); } @Override @@ -513,6 +519,9 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { @Override public void run() { connect(ioc); + // Clean start of messages - no hanging submessages - although this drops the first message ... + drainHangingSubmessages(); + while(!stopReadoutThread){ receive(); } @@ -641,7 +650,8 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { } } - public void connect(String address) { + + private void connect(String address) { // Clear interrupted state Thread.interrupted(); @@ -652,7 +662,9 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { socket.connect("tcp://"+address+":9999"); } - public void close() { + + + private void close() { logger.info("Closing stream from IOC "+ioc); // Send end of stream message @@ -719,12 +731,6 @@ public class CrlogicLoopStream extends CrlogicLoop implements ActionLoop { return sensors; } - public boolean isKeepTmpFiles() { - return false; - } - - public void setKeepTmpFiles(boolean keepTmpFiles) { - } public EventBus getEventBus(){ return eventbus; diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/ParallelCrlogic.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/ParallelCrlogic.java index 5ab2d5f..a3f2037 100644 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/ParallelCrlogic.java +++ b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/cr/ParallelCrlogic.java @@ -50,7 +50,7 @@ public class ParallelCrlogic implements ActionLoop { */ private boolean dataGroup = false; - private CrlogicLoop crlogic; + private CrlogicLoopStream crlogic; private ScrlogicLoop scrlogic; /** @@ -67,7 +67,7 @@ public class ParallelCrlogic implements ActionLoop { private final EventBus eventbus; - public ParallelCrlogic(CrlogicLoop crlogic, ScrlogicLoop scrlogic){ + public ParallelCrlogic(CrlogicLoopStream crlogic, ScrlogicLoop scrlogic){ if(crlogic==null){ throw new IllegalArgumentException("No Crloop specified"); @@ -165,19 +165,6 @@ public class ParallelCrlogic implements ActionLoop { }}); list.add(f); - -// // Start data merge thread -// logger.info("Start data merge"); -// f = service.submit(new Callable(){ -// @Override -// public Boolean call() throws Exception { -// -// merger.merge(); -// return true; -// }}); -// list.add(f); - - for(Future bf: list){ // Wait for completion of the thread try { diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/DistributedFile.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/DistributedFile.java deleted file mode 100644 index 2c2c384..0000000 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/DistributedFile.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - * - * Copyright 2012 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This code 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 Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ -package ch.psi.fda.core.loops.otf; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; - -import jcifs.smb.SmbFile; - -public class DistributedFile { - - private SmbFile smbfile = null; - private File file = null; - - public DistributedFile(SmbFile file){ - this.smbfile = file; - } - - public DistributedFile(File file){ - this.file = file; - } - - public DistributedFile(String url) throws MalformedURLException{ - if(url.startsWith("smb://")){ - smbfile = new SmbFile(url); - } - else { - file = new File(url); - } - } - - - public String getCanonicalPath() throws IOException{ - if(smbfile!=null){ - return(smbfile.getCanonicalPath()); - } - else{ - return file.getCanonicalPath(); - } - } - - - /** - * @return - * @throws IOException - */ - public boolean exists() throws IOException { - if(smbfile!=null){ - return(smbfile.exists()); - } - else{ - return file.exists(); - } - } - - - /** - * @return - */ - public boolean isDirectory() throws IOException { - if(smbfile!=null){ - return(smbfile.isDirectory()); - } - else{ - return file.isDirectory(); - } - } - - - /** - * @return - */ - public DistributedFile[] listFiles() throws IOException { - if(smbfile!=null){ - SmbFile[] files = smbfile.listFiles(); - DistributedFile[] dfiles = new DistributedFile[files.length]; - for(int i=0;i. - * - */ - -package ch.psi.fda.core.loops.otf; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -import com.google.common.eventbus.EventBus; - -import ch.psi.fda.core.Action; -import ch.psi.fda.core.ActionLoop; -import ch.psi.fda.core.Sensor; -import ch.psi.fda.core.sensors.TimestampSensor; -import ch.psi.fda.messages.DataMessage; -import ch.psi.fda.messages.EndOfStreamMessage; -import ch.psi.fda.messages.Metadata; - -/** - * ActionLoop that is implementing the OTF Scan logic. - * While executing the loop a full OTF scan procedure is executed. - */ -public class OTFLoop implements ActionLoop { - - private static Logger logger = Logger.getLogger(OTFLoop.class.getName()); - - /** - * Flag to indicate whether the data of this loop will be grouped - * According to this flag the dataGroup flag in EndOfStream will be set. - */ - private boolean dataGroup = false; - - /** - * Maximum number of monitored channels - */ - private static final int numberOfMonitoredChannels = 8; - /** - * Maximum number of Scaler channels - */ - private static final int numberOfScalerChannels = 16; - - /** - * Default timeout (in milliseconds) for wait operations - */ - private long timeout = 8000; - - /** - * Name of the NFS server to place the data of the OTF logic - */ - private final String server; - /** - * Share on the NFS server to put the OTF data on to - */ - private final String share; - /** - * SMB share to access the data written by the OTF C logic - */ - private final String smbShare; - - /** - * Flag whether the actor of this loop should move in zig zag mode - */ - private final boolean zigZag; - - /** - * Bean holding all OTF channels and functionality. - */ - private TemplateOTF obean; - - /** - * List of actions that are executed at the beginning of the loop. - */ - private List preActions; - /** - * List of actions that are executed at the end of the loop. - */ - private List postActions; - - /** - * List of sensors of this loop - */ - private List sensors; - - - private List dataIndexes; - - /** - * Execution count of this loop. This count is used to determine the - * file name of the OTF file. - */ - private int executionCount; - - /** - * Flag that indicates that the loop was requested to abort. - */ - private volatile boolean abort = false; - - - private String id; - private String name; // name of the motor channel - private String readback; // name of the encoder channel - private double start; - private double end; - private double stepSize; - private double integrationTime; - private double additionalBacklash; - - private final EventBus eventbus; - private List metadata; - - /** - * @param channelPrefix Prefix of the OTF related records, e.g. MTEST-HW3-OTF - * @param server NFS server the OTF C Logic should put its data to - * @param share Share on NFS server to put the OTF C Logic data - * @param smbShare SMB share to get the data written by the OTF C Logic - * @param zigZag Operate loop in zig zag mode - */ - public OTFLoop(TemplateOTF obean, String server, String share, String smbShare, boolean zigZag){ - - this.eventbus = new EventBus(); - - this.obean = obean; - - // Store loop configuration - this.server = server; - this.share = share; - this.smbShare = smbShare; - this.zigZag = zigZag; - - // Initialize lists used by the loop - this.preActions = new ArrayList(); - this.postActions = new ArrayList(); - this.sensors = new ArrayList(); - } - - public void setActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){ - this.id = id; - this.name = name; - this.readback = readback; - this.start = start; - this.end = end; - this.stepSize = stepSize; - this.integrationTime = integrationTime; - this.additionalBacklash = additionalBacklash; - } - - - @Override - public void execute() throws InterruptedException { - - // Execute pre actions - for(Action action: preActions){ - action.execute(); - } - - // Start scan - obean.start(); - - // Wait for end of scan - obean.waitUntilStopped(); - - // Read data from file - collectData(); - - // Execute post actions - for(Action action: postActions){ - action.execute(); - } - - - // Issue end of loop control message - eventbus.post(new EndOfStreamMessage(dataGroup)); - - // Increase execution count - executionCount++; - } - - @Override - public void abort() { - // Abort otf scan logic - obean.abort(); - - abort=true; - } - - @Override - public void prepare() { - executionCount = 0; - - // Set abort flag to false - abort=false; - - // list with all monitored channels - List monitoredChannels = new ArrayList(); - dataIndexes = new ArrayList(); - dataIndexes.add(1); // The first one is always the readback of the motor - int channelCount =0; - for(Sensor s: sensors){ - if(s instanceof OTFNamedChannelSensor){ - // Monitored channel - OTFNamedChannelSensor so = (OTFNamedChannelSensor) s; - if(channelCount>=numberOfMonitoredChannels){ - throw new IllegalArgumentException("Only up to "+numberOfMonitoredChannels+" channels can be monitored by OTF"); - } - - monitoredChannels.add(so.getName()); - dataIndexes.add(2+numberOfScalerChannels+channelCount); - - - channelCount++; - } - else if (s instanceof OTFScalerChannelSensor){ - OTFScalerChannelSensor so = (OTFScalerChannelSensor) s; - if(so.getIndex()>=numberOfScalerChannels){ - throw new IllegalArgumentException("Scaler index must be between 0<=index<"+numberOfScalerChannels); - } - dataIndexes.add(2+so.getIndex()); // scalers follow directly after the readback - } - else if (s instanceof TimestampSensor){ - dataIndexes.add(2+numberOfScalerChannels+numberOfMonitoredChannels); - } -// else if (s instanceof OTFReadbackSensor){ -// dataIndexes.add(1); -// } - else{ - throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop"); - } - } - - // Set OTF parameters - try{ - obean.resetToDefaults(); - - // Set actor properties - obean.setMotor(this.name); - obean.waitUntilMotorOk(timeout); - - obean.setBegin(this.start); - obean.setEnd(this.end); - obean.setStepSize(this.stepSize); - obean.setIntegrationTime(this.integrationTime); - - // Override encoder if specified - if(this.readback!=null){ - obean.setUseEncoder(true); - obean.setEncoder(this.readback); - obean.waitUntilEncoderOk(timeout); - } - - // Set user backlash - obean.setUserBacklash(this.additionalBacklash); - - - // NFS settings - obean.setNfsServer(server); - obean.setNfsShare(share); - - obean.setFileNameGeneration(true); - obean.setAppendFile(false); - obean.setZigZag(zigZag); // Set ZigZag because there might be iterations - obean.setFileNameFormat("%06d"); // Force an update of the filename/counter by setting file format twice with different values - obean.setFileNameFormat("%06d.txt"); - - - - // Set monitored channels - obean.setMonitoredChannels(monitoredChannels.toArray(new String[monitoredChannels.size()])); - } - catch(Exception e){ - throw new RuntimeException("Unable to set OTF configuration parameters",e); - } - - - // Cleanup temporary directory - try{ - DistributedFile tmpDir = new DistributedFile(smbShare); - if( !tmpDir.exists() || !tmpDir.isDirectory() ){ - throw new RuntimeException("Cannot access OTF temporary directory "+tmpDir.getCanonicalPath()); - } - DistributedFile[] files = tmpDir.listFiles(); - - for(int i=0;i(); - metadata.add(new Metadata(id)); // Id of the readback of the motor - - // Build up data message metadata based on the sensors currently registered. - for(Sensor s: sensors){ - metadata.add(new Metadata(s.getId())); - } - } - - @Override - public void cleanup() { - } - - @Override - public List getPreActions() { - return preActions; - } - - @Override - public List getPostActions() { - return postActions; - } - - /** - * Collect data written by the OTFScan logic - * @param dataSet - * @param tmpFile - */ - private void collectData() { - try{ - final int timestampIndex = 2+numberOfScalerChannels+numberOfMonitoredChannels; - - DistributedFile tmpFile = new DistributedFile(smbShare +"/"+ String.format("%06d.txt", executionCount)); - logger.fine("Collect data from "+tmpFile.getCanonicalPath()); - - DistributedFile lockfile = new DistributedFile(tmpFile.getCanonicalPath() + ".lock"); - - logger.fine("Wait until file is written [lock file: "+lockfile.getCanonicalPath()+"]"); - // Wait until file is created - while ((!tmpFile.exists()) || lockfile.exists()) { - Thread.sleep(500); - if(abort){ - // If abort is issued while waiting for data immediately return without - // trying to read the data - return; - } - } - - logger.fine("Read file " + tmpFile.getCanonicalPath()); - InputStreamReader inreader = tmpFile.getInputStream(); - BufferedReader in = new BufferedReader(inreader); - String line; - boolean firstline = true; - while (true) { - line = in.readLine(); - if (line == null) { - break; - } else { - if(line.matches("^\\[.*")){ - // Skip header lines - } - else{ - if(firstline){ - firstline=false; - continue; - } - - DataMessage message = new DataMessage(metadata); - // Add data to dataset - String[] tokens = line.split("\t"); - - for(Integer i: dataIndexes){ - try{ - if(i == timestampIndex) { - // Calculate time in milliseconds - Double seconds = new Double(tokens[i]); - Double nanoseconds = new Double(tokens[i+1]); - - Double v = seconds*1000+Math.floor(nanoseconds*0.000001); - message.getData().add(v); - } - else { - - message.getData().add(new Double(tokens[i])); - } - } - catch(NumberFormatException e){ - logger.warning("Cannot parse component ["+tokens[i]+"] from source file - will add 0 for this component"); - message.getData().add(new Double(0)); - } - } - eventbus.post(message); - } - } - } - in.close(); - inreader.close(); - } catch(InterruptedException e){ - throw new RuntimeException("An interrupt occured while waiting for the file to show up",e); - } catch (IOException e) { - throw new RuntimeException("An IO Exception occured while reading the OTF data file",e); - } - } - - - public List getSensors() { - return sensors; - } - public boolean isDataGroup() { - return dataGroup; - } - public void setDataGroup(boolean dataGroup) { - this.dataGroup = dataGroup; - } - - /* (non-Javadoc) - * @see ch.psi.fda.core.ActionLoop#getEventBus() - */ - @Override - public EventBus getEventBus() { - return eventbus; - } -} diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFNamedChannelSensor.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFNamedChannelSensor.java deleted file mode 100644 index 8957e06..0000000 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFNamedChannelSensor.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ - -package ch.psi.fda.core.loops.otf; - -import ch.psi.fda.core.Sensor; - -/** - * Sensor to read out a named (Epics) channel. This sensor can only be used within the - * OTFLoop. If it is used in other loops, the read value will always be 0. - */ -public class OTFNamedChannelSensor implements Sensor { - - /** - * Name of the channel - */ - private final String name; - - /** - * Global id of the sensor - */ - private final String id; - - /** - * Constructor - * @param id Global id of the sensor - * @param name Name of the (Epics) channel - */ - public OTFNamedChannelSensor(String id, String name){ - this.id = id; - this.name = name; - } - - @Override - public Object read() { - // Always return 0 if read() method is called. - return 0d; - } - - /** - * @return the name of the channel - */ - public String getName() { - return name; - } - - @Override - public String getId() { - return id; - } -} diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFScalerChannelSensor.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFScalerChannelSensor.java deleted file mode 100644 index 6b62831..0000000 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/OTFScalerChannelSensor.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ - -package ch.psi.fda.core.loops.otf; - -import ch.psi.fda.core.Sensor; - -/** - * Sensor to read out a scaler channel. This sensor can only be used within the - * OTFLoop. If it is used in other loops, the read value will always be 0. - * - */ -public class OTFScalerChannelSensor implements Sensor { - - /** - * Index of the scaler channel. The index starts at 0; - */ - private final int index; - - /** - * Global id of the sensor - */ - private final String id; - - /** - * Constructor - * @param id Global id of the sensor - * @param index Index of the scaler channel. Index starts at 0. - */ - public OTFScalerChannelSensor(String id, int index){ - this.id = id; - this.index = index; - } - - @Override - public Object read() { - return 0d; - } - - /** - * @return the index of the scaler channel - */ - public int getIndex() { - return index; - } - - @Override - public String getId() { - return id; - } -} diff --git a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/TemplateOTF.java b/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/TemplateOTF.java deleted file mode 100644 index cdc4e88..0000000 --- a/ch.psi.fda.xscan/src/main/java/ch/psi/fda/core/loops/otf/TemplateOTF.java +++ /dev/null @@ -1,962 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ - -package ch.psi.fda.core.loops.otf; - -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - -import ch.psi.jcae.annotation.CaChannel; -import ch.psi.jcae.Channel; -import ch.psi.jcae.ChannelException; - -/** - * Bean holding all OTF channels and functionality - */ -public class TemplateOTF { - - public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR }; - public enum Command { NONE, START, STOP }; - - private long timeoutMotorOk = 8000; - private long commandTimeout = 20000; // Maximum time until a command should take effect - - @CaChannel(type=String.class, name ="${PREFIX}:UMOT") - private Channel motor; - - @CaChannel(type=String.class, name="${PREFIX}:MENC") - private Channel encoder; - - @CaChannel(type=Double.class, name="${PREFIX}:UBEG") - private Channel begin; - - @CaChannel(type=Double.class, name="${PREFIX}:UBEG.DRVL") - private Channel beginMin; - - @CaChannel(type=Double.class, name="${PREFIX}:UBEG.DRVH") - private Channel beginMax; - - @CaChannel(type=Double.class, name="${PREFIX}:UEND") - private Channel end; - - @CaChannel(type=Double.class, name="${PREFIX}:UEND.DRVL") - private Channel endMin; - - @CaChannel(type=Double.class, name="${PREFIX}:UEND.DRVH") - private Channel endMax; - - @CaChannel(type=Double.class, name="${PREFIX}:USSIZ") - private Channel stepSize; - - @CaChannel(type=Double.class, name="${PREFIX}:USSIZ.DRVL") - private Channel stepSizeMin; - - @CaChannel(type=Double.class, name="${PREFIX}:UITIM") - private Channel integrationTime; - - @CaChannel(type=Double.class, name="${PREFIX}:UITIM.DRVL") - private Channel integrationTimeMin; - - @CaChannel(type=Double.class, name="${PREFIX}:UITIM.DRVH") - private Channel integrationTimeMax; - - @CaChannel(type=Double.class, name="${PREFIX}:UBCL") - private Channel userBacklash; - - @CaChannel(type=String.class, name="${PREFIX}:NFSSE") - private Channel nfsServer; - - @CaChannel(type=String.class, name="${PREFIX}:NFSSH") - private Channel nfsShare; - - @CaChannel(type=String.class, name="${PREFIX}:DFNAM") - private Channel fileName; - - @CaChannel(type=String.class, name="${PREFIX}:FFORM") - private Channel fileNameFormat; - - @CaChannel(type=Integer.class, name="${PREFIX}:FCNT") - private Channel fileCount; - - @CaChannel(type=Integer.class, name="${PREFIX}:FCNT.B") - private Channel resetFileCounter; - - @CaChannel(type=Boolean.class, name="${PREFIX}:FAPPE") - private Channel appendFile; - - @CaChannel(type=Boolean.class, name="${PREFIX}:FUSE") - private Channel fileNameGeneration; - - @CaChannel(type=Boolean.class, name="${PREFIX}:UZIGZ") - private Channel zigZag; - - @CaChannel(type=Integer.class, name="${PREFIX}:UCOM") - private Channel command; - - @CaChannel(type=Boolean.class, name="${PREFIX}:SCRU", monitor=true) - private Channel scanRunning; - - @CaChannel(type=Boolean.class, name="${PREFIX}:MUENC") - private Channel useEncoder; - - @CaChannel(type=String.class, name={"${PREFIX}:CTM0","${PREFIX}:CTM1","${PREFIX}:CTM2","${PREFIX}:CTM3","${PREFIX}:CTM4","${PREFIX}:CTM5","${PREFIX}:CTM6","${PREFIX}:CTM7"}) - private List> monitoredChannels; - - @CaChannel(type=Boolean.class, name="${PREFIX}:OTF", monitor=true) - private Channel running; - - @CaChannel(type=Integer.class, name="${PREFIX}:USTAT", monitor=true) - private Channel status; - - @CaChannel(type=Boolean.class, name="${PREFIX}:MOK", monitor=true) - private Channel motorOk; - - @CaChannel(type=Boolean.class, name="${PREFIX}:EOK", monitor=true) - private Channel encoderOk; - - @CaChannel(type=String.class, name="${PREFIX}:MSG") - private Channel message; - - /** - * Get the trigger name that can be used by the sscan record to trigger an OTFScan - * @return Name of the trigger that can be used by sscan record - */ - public String getSScanTriggerName(){ - return(running.getName()); - } - - /** - * Start OTF scan - */ - public void start() { - try{ - if(getStatus().equals(Status.INACTIVE)){ - - // Send START command - this.command.setValue(Command.START.ordinal()); - - // Wait until OtF logic is active - this.scanRunning.waitForValue(true, commandTimeout); - } - else{ - throw new RuntimeException("Cannot start scan, status is not INACTIVE.\nThe current status is: "+getStatus()+" . The OTF logic need to be recovered manually [Message: "+getMessage()+"]"); - } - } - catch(Exception e){ - throw new RuntimeException("Unable to start OTF scan.",e); - } - } - - /** - * Abort scan - */ - public void abort() { - try{ - // Send STOP command - this.command.setValue(Command.STOP.ordinal()); - - // Do not wait for put to return - this.running.setValueNoWait(false); - } - catch(Exception e){ - throw new RuntimeException("Unable to abort OTF logic" ,e); - } - } - - /** - * Stop OTF scan - * @throws Exception - */ - public void stop() throws Exception{ - if(!getStatus().equals(Status.INACTIVE) || !getStatus().equals(Status.FAULT)){ - - // Send STOP command - this.command.setValue(Command.STOP.ordinal()); - - // Wait until logic is stopped - status.waitForValue(Status.INACTIVE.ordinal(), commandTimeout); - } - - } - - /** - * Wait until scan has stopped - * @throws InterruptedException - */ - public void waitUntilStopped() throws InterruptedException { - try { - scanRunning.waitForValue(false); // Use of default wait timeout - - // Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception - if(status.getValue() != Status.INACTIVE.ordinal()){ - throw new RuntimeException("OTFSCAN failed with message: "+message.getValue()); - } - - } catch (ExecutionException | ChannelException | TimeoutException e) { - throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e); - } - } - - /** - * Wait until scan has stopped - * @param waitTimeout - * @throws InterruptedException - */ - public void waitUntilStopped(Long waitTimeout) throws InterruptedException { - try { - scanRunning.waitForValue(false, waitTimeout); - - // Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception - if(status.getValue() != Status.INACTIVE.ordinal()){ - throw new RuntimeException("OTFSCAN failed with message: "+message.getValue()); - } - - } catch (ExecutionException | ChannelException | TimeoutException e) { - throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e); - } - - - - } - - /** - * Reset OTFScan records to defaults - * @throws CAException - * @throws InterruptedException - */ - public void resetToDefaults() throws InterruptedException{ - try{ - setMonitoredChannels(new String[]{}); - setMotor(""); - begin.setValue(0d); - end.setValue(0d); - stepSize.setValue(0d); - integrationTime.setValue(0d); - zigZag.setValue(false); - setAppendFile(false); - setFileNameGeneration(true); - setFileName(""); - setFileNameFormat("%06d.txt"); - resetFileCounter(); - - setUserBacklash(0d); - -// setNfsServer(""); -// setNfsShare(""); - - waitUntilMotorNotOk(timeoutMotorOk); - } - catch(ExecutionException | ChannelException e){ - throw new RuntimeException(e); - } - } - - /** - * Get motor of the OTFScan axis - * @return Name of the OTF motor - * @throws CAException - */ - public String getMotor() throws InterruptedException { - try { - return(this.motor.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set motor of the OTFScan axis - * @param motor - * @throws CAException - */ - public void setMotor(String motor) throws InterruptedException { - try{ - this.motor.setValue(motor); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get encoder of the OTFScan axis - * @return Name of the used encoder - * @throws CAException - */ - public String getEncoder() throws InterruptedException { - try{ - return(this.encoder.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set encoder to use of the OTFScan axis - * @param encoder - * @throws CAException - */ - public void setEncoder(String encoder) throws InterruptedException { - try{ - this.encoder.setValue(encoder); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get begin position of the scan - * @return Begin position scan - * @throws CAException - */ - public Double getBegin() throws InterruptedException { - try{ - return(this.begin.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set begin position of scan - * @param begin - * @throws Exception - */ - public void setBegin(Double begin) throws InterruptedException { - try{ - if(begin==null){ - throw new IllegalArgumentException("Begin position must not be null"); - } - - if(begin < beginMin.getValue() || begin > beginMax.getValue()){ - throw new IllegalArgumentException("Cannot set begin value to "+begin+ ". Value is outside range [min: "+beginMin.getValue()+" max: "+beginMax.getValue()+"]"); - } - - this.begin.setValue(begin); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get minimum value of the begin position - * @return Min value for begin - * @throws CAException - */ - public Double getMinBegin() throws InterruptedException { - try{ - return(this.beginMin.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get maximum value of the begin position - * @return Max value for begin - * @throws CAException - */ - public Double getMaxBegin() throws InterruptedException { - try{ - return(this.beginMax.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get end position of the scan - * @return End position scan - * @throws CAException - */ - public Double getEnd() throws InterruptedException { - try{ - return(this.end.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set end positon of scan - * @param end - * @throws CAException - */ - public void setEnd(Double end) throws InterruptedException { - try{ - if(end==null){ - throw new IllegalArgumentException("End position must not be null"); - } - - if(end < endMin.getValue() || end > endMax.getValue()){ - throw new IllegalArgumentException("Cannot set end value to "+end+ ". Value is outside range [min: "+endMin.getValue()+" max: "+endMax.getValue()+"]"); - } - - this.end.setValue(end); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get minimum value of end position - * @return Min value for end - * @throws CAException - */ - public Double getMinEnd() throws InterruptedException { - try{ - return(this.endMin.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - /** - * Get maximum value of end position - * @return Max value for end - * @throws CAException - */ - public Double getMaxEnd() throws InterruptedException { - try{ - return(this.endMax.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get scan step size - * @return Step size - * @throws CAException - */ - public Double getStepSize() throws InterruptedException { - try{ - return(this.stepSize.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set step size of scan - * @param stepSize - * @throws CAException - */ - public void setStepSize(Double stepSize) throws InterruptedException { - try{ - if(integrationTime==null){ - throw new IllegalArgumentException("Step size must not be null"); - } - - // Check if step size is greater than min step size - if(stepSizeMin.getValue() != 0 && stepSize < stepSizeMin.getValue()){ - throw new IllegalArgumentException("Step size value ["+stepSize+"] is less than minimum step size ["+stepSizeMin.getValue()+"]!"); - } - - this.stepSize.setValue(stepSize); - - // TODO WORKAROUND - Wait to "ensure" that step size related fields are updated (i.e. min/max integration time) - Thread.sleep(1); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get minimum integration time - * @return Min value for step size - * @throws CAException - */ - public double getMinStepSize() throws InterruptedException { - try{ - return(this.stepSizeMin.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get scan integration time (time that is spend in one step) - * @return Integration time - * @throws CAException - */ - public Double getIntegrationTime() throws InterruptedException { - try{ - return(this.integrationTime.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set integration time of scan - * @param integrationTime - * @throws CAException - */ - public void setIntegrationTime(Double integrationTime) throws InterruptedException { - try{ - if(integrationTime==null){ - throw new IllegalArgumentException("Integration time must not be null"); - } - - // Check range (if limit is set to 0 then limit is not set) - double min = integrationTimeMin.getValue(); - double max = integrationTimeMax.getValue(); - if(min!= 0 && max!= 0){ - if(integrationTime < min || integrationTime > max){ - throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: "+min+" max: "+max+"]"); - } - } - else { - if(min!= 0 && integrationTimemax){ - throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: - max: "+max+"]"); - } - } - - this.integrationTime.setValue(integrationTime); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get minimum integration time - * @return Min value for integration time - * @throws CAException - */ - public Double getMinIntegrationTime() throws InterruptedException { - try{ - return(this.integrationTimeMin.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - /** - * Get maximum integration time - * @return Max value for integration time - * @throws CAException - */ - public Double getMaxIntegrationTime() throws InterruptedException { - try{ - return(this.integrationTimeMax.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get additional user defined backlash - * @return User backlash - * @throws CAException - */ - public Double getUserBacklash() throws InterruptedException { - try{ - return(this.userBacklash.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set additional user defined backlash - * @param userBacklash - * @throws CAException - */ - public void setUserBacklash(Double userBacklash) throws InterruptedException { - try{ - if(userBacklash==null){ - throw new IllegalArgumentException("User backlash must not be null"); - } - - this.userBacklash.setValue(userBacklash); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the current NFS server the data is written to - * @return Name of NFS server - * @throws CAException - */ - public String getNfsServer() throws InterruptedException { - try{ - return(this.nfsServer.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set name of the NFS server the data is written to - * @param nfsServer - * @throws CAException - */ - public void setNfsServer(String nfsServer) throws InterruptedException { - try{ - this.nfsServer.setValue(nfsServer); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the NFS share the data is written to - * @return Name of NFS share - * @throws CAException - */ - public String getNfsShare() throws InterruptedException { - try{ - return(this.nfsShare.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set name of the NFS share the data is written to - * @param nfsShare - * @throws CAException - */ - public void setNfsShare(String nfsShare) throws InterruptedException { - try{ - this.nfsShare.setValue(nfsShare); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the name of the data file - * @return Name of data file name - * @throws CAException - */ - public String getFileName() throws InterruptedException { - try{ - return(this.fileName.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set name of the data file - * @param filename - * @throws CAException - */ - public void setFileName(String filename) throws InterruptedException { - try{ - this.fileName.setValue(filename); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get File name formate - * @return Get format for file name - * @throws CAException - */ - public String getFileNameFormat() throws InterruptedException { - try{ - return(this.fileNameFormat.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set file name formate of the data file - * @param fileNameFormat - * @throws Exception - */ - public void setFileNameFormat(String fileNameFormat) throws InterruptedException { - try{ - this.fileNameFormat.setValue(fileNameFormat); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get value of the IOC based file name counter - * @return File counter - * @throws CAException - */ - public int getFileCounter() throws InterruptedException { - try{ - return(this.fileCount.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Reset the IOC based file counter - * @throws CAException - */ - public void resetFileCounter() throws InterruptedException { - try{ - this.resetFileCounter.setValue(1); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get if append file option is activated - * @return Append file flag - * @throws CAException - */ - public boolean isAppendFile() throws InterruptedException { - try{ - return(this.appendFile.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set whether to append the specified file if the file exists - * @param append - * @throws CAException - */ - public void setAppendFile(boolean append) throws InterruptedException { - try{ - this.appendFile.setValue(append); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get if file name generation is on or off - * @return File name generation flag - * @throws CAException - */ - public boolean isFileNameGeneration() throws InterruptedException { - try{ - return(this.fileNameGeneration.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set Whether the file name should be generated out of the file name format and the file counter - * @param generation - * @throws CAException - */ - public void setFileNameGeneration(boolean generation) throws InterruptedException { - try{ - this.fileNameGeneration.setValue(generation); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get if ZigZag scan option is on or off - * @return ZigZag flag - * @throws CAException - */ - public boolean isZigZag() throws InterruptedException { - try{ - return(this.zigZag.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set ZigZag scan mode on/off - * @param zigZag ZigZag mode on = true, ZigZag mode off = false - * @throws CAException - */ - public void setZigZag(boolean zigZag) throws InterruptedException { - try{ - this.zigZag.setValue(zigZag); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get whether encoder is used - */ - public boolean isUseEncoder() throws InterruptedException { - try{ - return(this.useEncoder.getValue()); - } catch (TimeoutException | ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Set flag to use encoder - * @throws CAException - */ - public void setUseEncoder(boolean flag) throws InterruptedException { - try{ - this.useEncoder.setValue(flag); - } catch (ChannelException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the channels that are currently monitored by the OTFScan logic - * @return Names of the monitored channels - * @throws CAException - */ - public String[] getMonitoredChannels() throws InterruptedException { - try{ - String[] values = new String[this.monitoredChannels.size()]; - - for(int i=0; imonitoredChannels.size()){ - throw new IllegalArgumentException("Only up to "+monitoredChannels.size()+" monitored channels are supported by OTF"); - } - - for(int i=0; i. - * - */ -package ch.psi.fda.core.loops; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.util.logging.Logger; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import ch.psi.fda.core.TestConfiguration; -import ch.psi.fda.core.loops.otf.DistributedFile; - -public class DistributedFileTest { - - - private static final Logger logger = Logger.getLogger(DistributedFileTest.class.getName()); - - DistributedFile file; - DistributedFile smbfile; - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - file = new DistributedFile("src/test/resources"); - smbfile = new DistributedFile(TestConfiguration.getInstance().getSmbShare()); - } - - /** - * @throws java.lang.Exception - */ - @After - public void tearDown() throws Exception { - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#getCanonicalPath()}. - * @throws IOException - */ - @Test - public void testGetCanonicalPath() throws IOException { - logger.info(file.getCanonicalPath()); - logger.info(smbfile.getCanonicalPath()); - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#exists()}. - * @throws IOException - */ - @Test - public void testExists() throws IOException { - if(!file.exists()){ - fail("Indicating wrong file status (file actually exists)"); - } - if(!smbfile.exists()){ - fail("Indicating wrong file status (file actually exists)"); - } - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#isDirectory()}. - * @throws IOException - */ - @Test - public void testIsDirectory() throws IOException { - if(!file.isDirectory()){ - fail("Indicating wrong file type (file is directory)"); - } - if(!smbfile.isDirectory()){ - fail("Indicating wrong file type (file is directory)"); - } - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#listFiles()}. - */ - @Test - public void testListFiles() { -// fail("Not yet implemented"); - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#getName()}. - */ - @Test - public void testGetName() { - logger.info(file.getName()); - logger.info(smbfile.getName()); - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#isFile()}. - * @throws IOException - */ - @Test - public void testIsFile() throws IOException { - if(file.isFile()){ - fail("Indicating wrong file type (file is directory)"); - } - if(smbfile.isFile()){ - fail("Indicating wrong file type (file is directory)"); - } - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#delete()}. - */ - @Test - public void testDelete() { -// fail("Not yet implemented"); - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.DistributedFile#getInputStream()}. - */ - @Test - public void testGetInputStream() { -// fail("Not yet implemented"); - } - -} diff --git a/ch.psi.fda.xscan/src/test/java/ch/psi/fda/core/loops/OTFLoopTest.java b/ch.psi.fda.xscan/src/test/java/ch/psi/fda/core/loops/OTFLoopTest.java deleted file mode 100644 index 0368c30..0000000 --- a/ch.psi.fda.xscan/src/test/java/ch/psi/fda/core/loops/OTFLoopTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * - * Copyright 2010 Paul Scherrer Institute. All rights reserved. - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - * - */ - -package ch.psi.fda.core.loops; - -import static org.junit.Assert.*; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.google.common.eventbus.Subscribe; - -import ch.psi.fda.core.TestConfiguration; -import ch.psi.fda.core.loops.otf.OTFLoop; -import ch.psi.fda.core.loops.otf.OTFNamedChannelSensor; -import ch.psi.fda.core.loops.otf.OTFScalerChannelSensor; -import ch.psi.fda.core.loops.otf.TemplateOTF; -import ch.psi.fda.core.sensors.TimestampSensor; -import ch.psi.fda.messages.ControlMessage; -import ch.psi.fda.messages.DataMessage; -import ch.psi.fda.messages.Message; -import ch.psi.jcae.Channel; -import ch.psi.jcae.ChannelDescriptor; -import ch.psi.jcae.ChannelException; -import ch.psi.jcae.ChannelService; -import ch.psi.jcae.impl.DefaultChannelService; - -public class OTFLoopTest { - - private static Logger logger = Logger.getLogger(OTFLoopTest.class.getName()); - - private ChannelService cservice; - - - - private static final TestConfiguration configuration = TestConfiguration.getInstance(); - - - private OTFLoop loopZigZag; - private OTFLoop loop; - private Channel statusChannel; - - @Before - public void setUp() throws Exception { - cservice = new DefaultChannelService(); - statusChannel = cservice.createChannel(new ChannelDescriptor<>(Integer.class, configuration.getOtfPrefix()+":USTAT")); - - OTFScalerChannelSensor s2 = new OTFScalerChannelSensor("id1", 0); - OTFScalerChannelSensor s3 = new OTFScalerChannelSensor("id2", 1); - TimestampSensor s4 = new TimestampSensor("id3"); - OTFNamedChannelSensor s5 = new OTFNamedChannelSensor("id4", configuration.getAnalogIn1()); - - Map macros = new HashMap<>(); - macros.put("PREFIX", configuration.getOtfPrefix()); - TemplateOTF template = new TemplateOTF(); - cservice.createAnnotatedChannels(template, macros); - - - // ZigZag loop - loopZigZag = new OTFLoop(template, configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), true); - loopZigZag.setActuator("id0", configuration.getMotor1(), null, 0, 8, 0.5, 0.5, 0); - loopZigZag.getSensors().add(s2); - loopZigZag.getSensors().add(s3); - loopZigZag.getSensors().add(s4); - loopZigZag.getSensors().add(s5); - - - // Normal loop - loop = new OTFLoop(template, configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), false); - loop.setActuator("id0", configuration.getMotor1(), null, 0, 8, 0.5, 0.5, 0); - loop.getSensors().add(s2); - loop.getSensors().add(s3); - loop.getSensors().add(s4); - loop.getSensors().add(s5); - } - - @After - public void tearDown() throws Exception { - cservice.destroy(); - } - - /** - * Test method for {@link ch.psi.fda.core.loops.otf.OTFLoop#execute()}. - * Test ordinary 1D OTF scan - * @throws ExecutionException - * @throws ChannelException - * @throws TimeoutException - * @throws CAException - */ - @Test - public void testExecute() throws InterruptedException, TimeoutException, ChannelException, ExecutionException { - - Object l = new Object(){ - boolean first = true; - @Subscribe - public void onMessage(DataMessage m) { - if(first){ - first = false; - - int numberOfSensors = 5; - if(m.getMetadata().size() != numberOfSensors){ - fail("Loop returned wrong number of components inside the data message metadata"); - } - - boolean fail = false; - for(int x=0;x