This commit is contained in:
2013-07-29 15:22:33 +02:00
parent bc0763a22c
commit e64d341a38
6 changed files with 280 additions and 251 deletions
@@ -18,6 +18,8 @@
*/
package ch.psi.fda.aq;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;
@@ -26,6 +28,7 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import ch.psi.jcae.Channel;
import ch.psi.jcae.ChannelDescriptor;
import ch.psi.jcae.ChannelException;
import ch.psi.jcae.ChannelService;
@@ -68,6 +71,19 @@ public class AcquisitionEngineNG {
else if(resourceDescriptors.get(k) instanceof ShellDescriptor){
engine.put(k, new ShellResource());
}
else if(resourceDescriptors.get(k) instanceof ProbeDescriptor){
ProbeDescriptor descriptor = (ProbeDescriptor) resourceDescriptors.get(k);
List<Channel<?>> descriptors = new ArrayList<>();
for(ChannelDescriptor<?> s: descriptor.getSensors()){
try {
descriptors.add(cservice.createChannel(s));
} catch (ChannelException | InterruptedException | TimeoutException e) {
throw new RuntimeException("Unable to create resource for channel: "+s.getName(),e);
}
}
engine.put(k, new ChannelProbeResource(descriptors));
}
else{
throw new RuntimeException("Resource type not supported: "+resourceDescriptors.get(k).getClass().getName());
}
@@ -0,0 +1,58 @@
/**
*
* Copyright 2013 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 <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.aq;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.jcae.Channel;
import ch.psi.jcae.ChannelException;
/**
* @author ebner
*
*/
public class ChannelProbeResource {
private final List<Channel<?>> channels;
public ChannelProbeResource(List<Channel<?>> channels){
this.channels = channels;
}
public void read(){
try{
DataMessage message = new DataMessage();
for(Channel<?> sensor: channels){
// Readout sensor
Object o = sensor.getValue();
// Add sensor data item to message
message.getData().add(o);
}
System.out.println("MESSAGE: "+message);
} catch (InterruptedException | TimeoutException | ChannelException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,37 @@
/**
*
* Copyright 2013 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 <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.aq;
import java.util.ArrayList;
import java.util.List;
import ch.psi.jcae.ChannelDescriptor;
/**
* @author ebner
*
*/
public class ProbeDescriptor {
private List<ChannelDescriptor<?>> sensors = new ArrayList<>();
public List<ChannelDescriptor<?>> getSensors(){
return sensors;
}
}
@@ -28,12 +28,15 @@ import java.util.UUID;
import java.util.logging.Logger;
import ch.psi.fda.model.v1.Action;
import ch.psi.fda.model.v1.ArrayPositioner;
import ch.psi.fda.model.v1.ChannelAction;
import ch.psi.fda.model.v1.Configuration;
import ch.psi.fda.model.v1.ContinuousDimension;
import ch.psi.fda.model.v1.Dimension;
import ch.psi.fda.model.v1.DiscreteStepDimension;
import ch.psi.fda.model.v1.DiscreteStepPositioner;
import ch.psi.fda.model.v1.FunctionPositioner;
import ch.psi.fda.model.v1.LinearPositioner;
import ch.psi.fda.model.v1.Scan;
import ch.psi.fda.model.v1.ScriptAction;
import ch.psi.fda.model.v1.ShellAction;
@@ -48,6 +51,11 @@ import ch.psi.jcae.util.ComparatorREGEX;
*/
public class ScanMapperNG {
// Reserved resource id's
private static final String PROBE_RESOURCE_ID = "probe";
private static final String SHELL_RESOURCE_ID = "shell";
// "logger" is also a special variable as it is bound to the logger of the application!
private static final Logger logger = Logger.getLogger(ScanMapperNG.class.getName());
private static final String INDENT = " ";
@@ -56,9 +64,19 @@ public class ScanMapperNG {
private Set<String> imports = new HashSet<>();
private Map<String, Object> resourceDescriptors = new HashMap<>();
private ProbeDescriptor probeDescriptor = new ProbeDescriptor();
private String indentation = "";
public void map(Configuration configuration) {
// Clear object state
script = new StringBuilder();
imports = new HashSet<>();
resourceDescriptors = new HashMap<>();
probeDescriptor = new ProbeDescriptor();
resourceDescriptors.put(PROBE_RESOURCE_ID, probeDescriptor);
Scan scan = configuration.getScan();
mapActions(scan.getPreAction());
@@ -118,18 +136,88 @@ public class ScanMapperNG {
DiscreteStepDimension d = (DiscreteStepDimension) dimension;
mapActions(d.getPreAction());
// TODO Do mapping
script.append(indentation + "for i in test\n");
List<String> actuators = new ArrayList<>();
for(DiscreteStepPositioner positioner: d.getPositioner()){
Class<?> type = String.class;
switch (positioner.getType()) {
case "Integer":
type = Integer.class;
break;
case "Double":
type = Double.class;
break;
}
String var = getChannelResourceVariable(positioner.getName(), type, false);
actuators.add(var);
// Readback
if(positioner.getReadback()==null){
probeDescriptor.getSensors().add(new ChannelDescriptor<>(type, positioner.getName(), false));
}
else{
// Use readback
probeDescriptor.getSensors().add(new ChannelDescriptor<>(type, positioner.getReadback(), false));
}
// TODO Done resource
if(positioner instanceof LinearPositioner){
LinearPositioner lpositioner = (LinearPositioner) positioner;
}
else if(positioner instanceof ArrayPositioner){
ArrayPositioner apositioner = (ArrayPositioner) positioner;
// Calculate positions
String[] positions = apositioner.getPositions().trim().split(" +");
boolean first = true;
StringBuffer b = new StringBuffer();
b.append("[");
for(String po: positions){
if(first){
first=false;
}
else{
b.append(",");
}
b.append(getPythonValue(po, type));
}
b.append("]");
script.append(indentation + var+"_positions="+b.toString()+"\n");
}
else if(positioner instanceof FunctionPositioner){
FunctionPositioner fpositioner = (FunctionPositioner) positioner;
// TODO take variable mappings into account !
}
}
// Create dimension loop
String v = getUniqueVariableName();
script.append(indentation + "for "+v+"_idx ,"+v+"_pos in enumerate("+actuators.get(0)+"_positions):\n");
indentation = indentation + INDENT;
mapPositioners(d.getPositioner());
// Set all actuators of this dimension
for(String a: actuators){
script.append(indentation + a+".setValue("+a+"_positions["+v+"_idx])\n");
}
// Add all actions executed between actuator and sensors
mapActions(d.getAction());
// TODO map guard and sensors
// Next dimension
// Check whether final dimension reached
if ((index + 1) < dimensions.size()) {
// Map next dimension
mapDimensions(dimensions, (index + 1));
}
else{
// Final dimension reached - readout probe
script.append(indentation + PROBE_RESOURCE_ID+".read()\n");
}
indentation = indentation.replaceFirst(INDENT, ""); // decrease
// indentation
@@ -201,9 +289,9 @@ public class ScanMapperNG {
} else if (action instanceof ShellAction) {
ShellAction saction = (ShellAction) action;
resourceDescriptors.put("shell", new ShellDescriptor());
resourceDescriptors.put(SHELL_RESOURCE_ID, new ShellDescriptor());
// TODO Need to indicate that shell resource is required
script.append(indentation + String.format("shell.execute('%s', %d, %s)\n", saction.getCommand(), saction.getExitValue(), saction.isCheckExitValue()?"True":"False"));
script.append(indentation + String.format(SHELL_RESOURCE_ID+".execute('%s', %d, %s)\n", saction.getCommand(), saction.getExitValue(), saction.isCheckExitValue()?"True":"False"));
} else if (action instanceof ScriptAction) {
ScriptAction saction = (ScriptAction) action;
@@ -212,254 +300,13 @@ public class ScanMapperNG {
// level
String[] lines = saction.getScript().split(System.getProperty("line.separator"));
for (String s : lines) {
script.append(indentation + s);
script.append(indentation + s+"\n");
}
script.append(indentation + "\n");
}
}
}
public void mapPositioners(List<DiscreteStepPositioner> positioners) {
// for (DiscreteStepPositioner p : positioners) {
//
// if (p.getSettlingTime() > stime) {
// stime = p.getSettlingTime();
// }
//
// if (p instanceof LinearPositioner) {
// LinearPositioner lp = (LinearPositioner) p;
// ChannelAccessLinearActuator<?> a;
// if (lp.getType().equals("String")) {
// a = new ChannelAccessLinearActuator<String>(cservice, lp.getName(),
// lp.getDone(), lp.getDoneValue(), lp.getDoneDelay(), lp.getStart(),
// lp.getEnd(), lp.getStepSize(), moveTimeout);
// } else if (lp.getType().equals("Double")) {
// a = new ChannelAccessLinearActuator<Double>(cservice, lp.getName(),
// lp.getDone(), Double.parseDouble(lp.getDoneValue()),
// lp.getDoneDelay(), lp.getStart(), lp.getEnd(),
// lp.getStepSize(), moveTimeout);
// } else {
// // Default
// a = new ChannelAccessLinearActuator<Integer>(cservice, lp.getName(),
// lp.getDone(), Integer.parseInt(lp.getDoneValue()), lp.getDoneDelay(),
// lp.getStart(), lp.getEnd(),
// lp.getStepSize(), moveTimeout);
// }
//
// a.setAsynchronous(lp.isAsynchronous());
// Actor actuator = a;
//
// aLoop.getActors().add(actuator);
//
// // Add a sensor for the readback
// String name = lp.getReadback();
// if (name == null) {
// name = lp.getName();
// }
// ChannelAccessDoubleSensor sensor = new
// ChannelAccessDoubleSensor(cservice, lp.getId(), name);
// aLoop.getSensors().add(sensor);
// } else if (p instanceof FunctionPositioner) {
// FunctionPositioner lp = (FunctionPositioner) p;
//
// // Create function object
// JythonFunction function = mapFunction(lp.getFunction());
//
// // Create actuator
// ChannelAccessFunctionActuator<?> a;
// if (lp.getType().equals("String")) {
// a = new ChannelAccessFunctionActuator<String>(cservice, lp.getName(),
// lp.getDone(), lp.getDoneValue(), lp.getDoneDelay(), function,
// lp.getStart(), lp.getEnd(), lp.getStepSize(),
// moveTimeout);
// } else if (lp.getType().equals("Double")) {
// a = new ChannelAccessFunctionActuator<Double>(cservice, lp.getName(),
// lp.getDone(), Double.parseDouble(lp.getDoneValue()),
// lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(),
// lp.getStepSize(), moveTimeout);
// } else {
// // Default
// a = new ChannelAccessFunctionActuator<Integer>(cservice,
// lp.getName(), lp.getDone(), Integer.parseInt(lp.getDoneValue()),
// lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(),
// lp.getStepSize(), moveTimeout);
// }
//
// a.setAsynchronous(lp.isAsynchronous());
// Actor actuator = a;
//
// aLoop.getActors().add(actuator);
//
// // Add a sensor for the readback
// String name = lp.getReadback();
// if (name == null) {
// name = lp.getName();
// }
// ChannelAccessDoubleSensor sensor = new
// ChannelAccessDoubleSensor(cservice, lp.getId(), name);
// aLoop.getSensors().add(sensor);
// } else if (p instanceof ArrayPositioner) {
// ArrayPositioner ap = (ArrayPositioner) p;
// String[] positions = (ap.getPositions().trim()).split(" +");
// double[] table = new double[positions.length];
// for (int i = 0; i < positions.length; i++) {
// table[i] = Double.parseDouble(positions[i]);
// }
//
// ChannelAccessTableActuator<?> a;
// if (p.getType().equals("String")) {
// a = new ChannelAccessTableActuator<String>(cservice, p.getName(),
// p.getDone(), p.getDoneValue(), p.getDoneDelay(), table, moveTimeout);
// } else if (p.getType().equals("Double")) {
// a = new ChannelAccessTableActuator<Double>(cservice, p.getName(),
// p.getDone(), Double.parseDouble(p.getDoneValue()), p.getDoneDelay(),
// table, moveTimeout);
// } else {
// // Default
// a = new ChannelAccessTableActuator<Integer>(cservice, p.getName(),
// p.getDone(), Integer.parseInt(p.getDoneValue()), p.getDoneDelay(),
// table, moveTimeout);
// }
//
// a.setAsynchronous(p.isAsynchronous());
// Actor actuator = a;
//
// aLoop.getActors().add(actuator);
//
// // Add a sensor for the readback
// String name = ap.getReadback();
// if (name == null) {
// name = ap.getName();
// }
// ChannelAccessDoubleSensor sensor = new
// ChannelAccessDoubleSensor(cservice, ap.getId(), name);
// aLoop.getSensors().add(sensor);
// } else if (p instanceof RegionPositioner) {
// RegionPositioner rp = (RegionPositioner) p;
//
// ComplexActuator actuator = new ComplexActuator();
// /*
// * Regions are translated into a complex actor consisting of a
// * LinearActuator If consecutive regions are overlapping, i.e.
// * end point of region a equals the start point of region b then
// * the start point for the LinearActuator of region b is changes
// * to its next step (start+/-stepSize depending on whether end
// * position of the region is > or < start of the region)
// */
// Region lastRegion = null;
// for (Region r : rp.getRegion()) {
// // Normal region
// if (r.getFunction() == null) {
//
// // Check whether regions are consecutive
// double start = r.getStart();
// if (lastRegion != null && start == lastRegion.getEnd()) { // TODO
// // verify
// // whether
// // double
// // comparison
// // is
// // ok
// if (r.getStart() < r.getEnd()) {
// start = start + r.getStepSize();
// } else {
// start = start - r.getStepSize();
// }
// }
//
// // Create actuator
// ChannelAccessLinearActuator<?> act;
// if (rp.getType().equals("String")) {
// act = new ChannelAccessLinearActuator<String>(cservice, rp.getName(),
// rp.getDone(), rp.getDoneValue(), rp.getDoneDelay(), start,
// r.getEnd(), r.getStepSize(), moveTimeout);
// } else if (rp.getType().equals("Double")) {
// act = new ChannelAccessLinearActuator<Double>(cservice, rp.getName(),
// rp.getDone(), Double.parseDouble(rp.getDoneValue()),
// rp.getDoneDelay(), start, r.getEnd(),
// r.getStepSize(), moveTimeout);
// } else {
// // Default
// act = new ChannelAccessLinearActuator<Integer>(cservice,
// rp.getName(), rp.getDone(), Integer.parseInt(rp.getDoneValue()),
// rp.getDoneDelay(), start, r.getEnd(),
// r.getStepSize(), moveTimeout);
// }
//
// act.setAsynchronous(rp.isAsynchronous());
// Actor a = act;
//
// ComplexActuator ca = new ComplexActuator();
// ca.getActors().add(a);
// ca.getPreActions().addAll(mapActions(r.getPreAction()));
// actuator.getActors().add(ca);
// lastRegion = r;
// } else {
// // Function based region
//
// // Cannot check whether the regions are consecutive as
// // the function
// // used might change the start value to something else
// // [THIS LIMITATION NEEDS TO BE SOMEHOW RESOLVED IN THE
// // NEXT VERSIONS]
// JythonFunction function = mapFunction(r.getFunction());
// ChannelAccessFunctionActuator<?> act;
// if (rp.getType().equals("String")) {
// act = new ChannelAccessFunctionActuator<String>(cservice,
// rp.getName(), rp.getDone(), rp.getDoneValue(), rp.getDoneDelay(),
// function, r.getStart(), r.getEnd(),
// r.getStepSize(), moveTimeout);
// } else if (rp.getType().equals("Double")) {
// act = new ChannelAccessFunctionActuator<Double>(cservice,
// rp.getName(), rp.getDone(), Double.parseDouble(rp.getDoneValue()),
// rp.getDoneDelay(), function, r.getStart(),
// r.getEnd(), r.getStepSize(), moveTimeout);
// } else {
// // Default
// act = new ChannelAccessFunctionActuator<Integer>(cservice,
// rp.getName(), rp.getDone(), Integer.parseInt(rp.getDoneValue()),
// rp.getDoneDelay(), function, r.getStart(),
// r.getEnd(), r.getStepSize(), moveTimeout);
// }
//
// act.setAsynchronous(rp.isAsynchronous());
// Actor a = act;
//
// ComplexActuator ca = new ComplexActuator();
// ca.getActors().add(a);
// ca.getPreActions().addAll(mapActions(r.getPreAction()));
// actuator.getActors().add(ca);
// lastRegion = r;
// }
// }
// aLoop.getActors().add(actuator);
//
// // Add a sensor for the readback
// String name = rp.getReadback();
// if (name == null) {
// name = rp.getName();
// }
// ChannelAccessDoubleSensor sensor = new
// ChannelAccessDoubleSensor(cservice, rp.getId(), name);
// aLoop.getSensors().add(sensor);
// } else if (p instanceof PseudoPositioner) {
// PseudoPositioner pp = (PseudoPositioner) p;
// PseudoActuatorSensor actorSensor = new
// PseudoActuatorSensor(pp.getId(), pp.getCounts());
//
// // Register as actor
// aLoop.getActors().add(actorSensor);
//
// // Register as sensor
// aLoop.getSensors().add(actorSensor);
// } else {
// // Not supported
// logger.warning("Mapping for " + p.getClass().getName() +
// " not available");
// }
// }
}
/**
* Get unique variable names that do not collide with others. (at least have
* an extreme unlikeness to do so)
@@ -25,8 +25,10 @@ import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.model.v1.ArrayPositioner;
import ch.psi.fda.model.v1.ChannelAction;
import ch.psi.fda.model.v1.Configuration;
import ch.psi.fda.model.v1.DiscreteStepDimension;
import ch.psi.fda.model.v1.Scan;
import ch.psi.fda.model.v1.ScriptAction;
import ch.psi.fda.model.v1.ShellAction;
@@ -78,22 +80,34 @@ public class AcquisitionEngineNGTest {
// Wait for value
ca = new ChannelAction();
ca.setChannel(TestChannels.ANALOG_OUT);
ca.setValue("13");
ca.setValue("12"); // use other value than 12 to test
ca.setOperation("wait");
ca.setTimeout(10.0);
ca.setType("Double");
config.getScan().getPreAction().add(ca);
ScriptAction sa = new ScriptAction();
sa.setScript("for i in range(0, 3):\n logger.info('hello %d' %i)\n");
// Add discrete step dimension
DiscreteStepDimension dimension = new DiscreteStepDimension();
ArrayPositioner positioner = new ArrayPositioner();
positioner.setName(TestChannels.ANALOG_OUT);
positioner.setPositions(" 1 2 3 4 5 6 7");
dimension.getPositioner().add(positioner);
dimension.getAction().add(sa);
config.getScan().getDimension().add(dimension);
ShellAction a = new ShellAction();
a.setCommand("echo hello world this is a test");
// a.setExitValue(1);
config.getScan().getPostAction().add(sa);
// config.getScan().getPostAction().add(sa);
config.getScan().getPostAction().add(a);
@@ -106,5 +120,54 @@ public class AcquisitionEngineNGTest {
engine.execute(mapper.getResourceDescriptors(), mapper.getScript());
}
@Test
public void testExecuteDimensionActuators() {
Configuration config = new Configuration();
config.setScan(new Scan());
// Add discrete step dimension
DiscreteStepDimension dimension = new DiscreteStepDimension();
ArrayPositioner positioner = new ArrayPositioner();
positioner.setName(TestChannels.ANALOG_OUT);
// positioner.setReadback(TestChannels.BINARY_OUT);
positioner.setPositions(" 1 2 3 4 5 6 7");
dimension.getPositioner().add(positioner);
positioner = new ArrayPositioner();
positioner.setName(TestChannels.BINARY_OUT);
positioner.setType("Double");
positioner.setPositions(" 10 20 30 40 50 60 70");
dimension.getPositioner().add(positioner);
config.getScan().getDimension().add(dimension);
dimension = new DiscreteStepDimension();
positioner = new ArrayPositioner();
positioner.setName(TestChannels.BINARY_OUT_TWO);
positioner.setType("Double");
// positioner.setReadback(TestChannels.BINARY_OUT);
positioner.setPositions(" 0.1 0.2 0.3 0.4 0.5 0.6 0.7");
dimension.getPositioner().add(positioner);
config.getScan().getDimension().add(dimension);
ScanMapperNG mapper = new ScanMapperNG();
mapper.map(config);
logger.info("Resources to create: "+mapper.getResourceDescriptors());
logger.info("Script to execute: "+mapper.getScript());
long start, end, elapsed;
start = System.currentTimeMillis();
engine.execute(mapper.getResourceDescriptors(), mapper.getScript());
end = System.currentTimeMillis();
elapsed = end-start;
logger.info("Elapsed time: "+elapsed);
}
}
@@ -27,6 +27,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.model.v1.ArrayPositioner;
import ch.psi.fda.model.v1.ChannelAction;
import ch.psi.fda.model.v1.Configuration;
import ch.psi.fda.model.v1.DiscreteStepDimension;
@@ -85,7 +87,13 @@ public class ScanMapperNGTest {
DiscreteStepDimension d = new DiscreteStepDimension();
ArrayPositioner positioner = new ArrayPositioner();
positioner.setName(TestChannels.ANALOG_OUT);
positioner.setPositions(" 1 2 3 4 5 6 7");
d.getPreAction().add(a);
d.getPositioner().add(positioner);
d.getAction().add(sa);
d.getPostAction().add(a);