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