Files
x09la/src/Scienta.java
gac-x09la f62fa8b58e
2022-04-25 14:25:30 +02:00

542 lines
20 KiB
Java

import ch.psi.pshell.device.AccessType;
import ch.psi.pshell.device.CameraImageDescriptor;
import ch.psi.pshell.device.MatrixCalibration;
import ch.psi.pshell.device.Device;
import ch.psi.pshell.device.Writable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ch.psi.pshell.epics.*;
import ch.psi.utils.Arr;
/**
* Implementation of Scienta spectrometer analyser.
*/
public class Scienta extends AreaDetector {
final ChannelInteger acquire;
final ChannelInteger energyCount, ThetaYCount, ThetaXCount;
final ChannelDouble energyWidth, ThetaYWidth, lowThetaX, highThetaX, stepSizeThetaX, ThetaXWidth;
final ControlledVariable lowEnergy, centerEnergy, highEnergy, stepSize, lowThetaY, centerThetaY, highThetaY, stepSizeThetaY, centerThetaX;
final ControlledVariable excitationEnergy;
final GenericArray data;
final ChannelInteger totalSteps, currentStep, exposuresComplete;
final DiscretePositioner lensMode, acquisitionMode, energyMode, detectorMode, elementSet, passEnergy;
final ChannelString estTime, detectorState;
final ChannelByteArray status;
final ChannelInteger slices, slicesReadback, channels, channelsReadback;
final Stats[] stats;
final String channelCtrl;
final Device[] monitoredChildren;
final boolean test;
final ChannelDouble exposureDev;
public Scienta(final String name, final String channelPrefix, boolean test) {
this(name, channelPrefix + ":cam1", channelPrefix + ":image1", test);
}
public Scienta(String name, String channelCtrl, String channelData, boolean test) {
super(name, channelCtrl, channelData);
this.test=test;
this.channelCtrl = channelCtrl;
acquire = new ChannelInteger(name + " aquire", channelCtrl + ":Acquire", false);
lowEnergy = new ControlledVariable(name + " low energy", channelCtrl + ":LOW_ENERGY", channelCtrl + ":LOW_ENERGY_RBV", false);
centerEnergy = new ControlledVariable(name + " center energy", channelCtrl + ":CENTRE_ENERGY", channelCtrl + ":CENTRE_ENERGY_RBV", false);
highEnergy = new ControlledVariable(name + " high energy", channelCtrl + ":HIGH_ENERGY", channelCtrl + ":HIGH_ENERGY_RBV", false);
stepSize = new ControlledVariable(name + " step size", channelCtrl + ":STEP_SIZE", channelCtrl + ":STEP_SIZE_RBV", false);
energyWidth = new ChannelDouble(name + " energy width", channelCtrl + ":ENERGY_WIDTH_RBV", 3, false);
energyWidth.setAccessType(AccessType.Read);
energyCount = new ChannelInteger(name + " energy count", channelCtrl + ":COUNT_RBV", false);
energyCount.setAccessType(AccessType.Read);
exposureDev = new ChannelDouble(name + " exposure time", channelCtrl + ":AcquireTime", 3, false);
lowThetaY = new ControlledVariable(name + " low Theta Y", channelCtrl + ":LOW_THETA_Y", channelCtrl + ":LOW_THETA_Y_RBV", false);
centerThetaY = new ControlledVariable(name + " center Theta Y", channelCtrl + ":CENTRE_THETA_Y", channelCtrl + ":CENTRE_THETA_Y_RBV", false);
highThetaY = new ControlledVariable(name + " high Theta Y", channelCtrl + ":HIGH_THETA_Y", channelCtrl + ":HIGH_THETA_Y_RBV", false);
stepSizeThetaY = new ControlledVariable(name + " Theta Y step size", channelCtrl + ":THETA_Y_STEP_SIZE", channelCtrl + ":THETA_Y_STEP_SIZE_RBV", false);
ThetaYWidth = new ChannelDouble(name + " Theta Y width", channelCtrl + ":THETA_Y_WIDTH_RBV", 3, false);
ThetaYWidth.setAccessType(AccessType.Read);
ThetaYCount = new ChannelInteger(name + " Theta Y count", channelCtrl + ":THETA_Y_COUNT_RBV", false);
ThetaYCount.setAccessType(AccessType.Read);
lowThetaX = new ChannelDouble(name + " low Theta X", channelCtrl + ":LOW_SLICE_RBV", 3, false);
lowThetaX.setAccessType(AccessType.Read);
centerThetaX = new ControlledVariable(name + " center Theta X", channelCtrl + ":CENTRE_SLICE", channelCtrl + ":CENTRE_SLICE_RBV", false);
highThetaX = new ChannelDouble(name + " high Theta X", channelCtrl + ":HIGH_SLICE_RBV", 3, false);
highThetaX.setAccessType(AccessType.Read);
stepSizeThetaX = new ChannelDouble(name + " Theta X step size", channelCtrl + ":SLICE_STEP_SIZE_RBV", 3, false);
stepSizeThetaX.setAccessType(AccessType.Read);
ThetaXWidth = new ChannelDouble(name + " ThetaX width", channelCtrl + ":SLICE_WIDTH_RBV", 3, false);
ThetaXWidth.setAccessType(AccessType.Read);
ThetaXCount = new ChannelInteger(name + " Theta count", channelCtrl + ":SLICE_COUNT_RBV", false);
ThetaXCount.setAccessType(AccessType.Read);
passEnergy = new DiscretePositioner(name + " pass energy", channelCtrl + ":PASS_ENERGY", channelCtrl + ":PASS_ENERGY_RBV");
lensMode = new DiscretePositioner(name + " lens mode", channelCtrl + ":LENS_MODE", channelCtrl + ":LENS_MODE_RBV");
acquisitionMode = new DiscretePositioner(name + " acquisition mode", channelCtrl + ":ACQ_MODE", channelCtrl + ":ACQ_MODE_RBV");
energyMode = new DiscretePositioner(name + " energy mode", channelCtrl + ":ENERGY_MODE", channelCtrl + ":ENERGY_MODE_RBV");
detectorMode = new DiscretePositioner(name + " detector mode", channelCtrl + ":DETECTOR_MODE", channelCtrl + ":DETECTOR_MODE_RBV");
elementSet = new DiscretePositioner(name + " element set", channelCtrl + ":ELEMENT_SET_RBV", channelCtrl + ":ELEMENT_SET_RBV");
elementSet.setAccessType(AccessType.Read);
slices = new ChannelInteger(name + " slices", channelCtrl + ":SLICES", false);
slicesReadback = new ChannelInteger(name + " slices rbv", channelCtrl + ":SLICES_RBV", false);
slicesReadback.setAccessType(AccessType.Read);
channels = new ChannelInteger(name + " channels", channelCtrl + ":CHANNELS", false);
channelsReadback = new ChannelInteger(name + " channels rbv", channelCtrl + ":CHANNELS_RBV", false);
channelsReadback.setAccessType(AccessType.Read);
excitationEnergy = new ControlledVariable(name + " excitation energy", channelCtrl + ":EXCITATION_ENERGY", channelCtrl + ":EXCITATION_ENERGY_RBV", false);
data = new GenericArray(name + " data", channelData + ":ArrayData", SIZE_MAX, false); //If nullable on invalidd value, read blocks on Scienta.
data.setAutoResolveType(false);
totalSteps = new ChannelInteger(name + " total steps", channelCtrl + ":STEPS_RBV", false);
totalSteps.setAccessType(AccessType.Read);
currentStep = new ChannelInteger(name + " current step", channelCtrl + ":STEPS_COUNTER_RBV", false);
currentStep.setAccessType(AccessType.Read);
exposuresComplete = new ChannelInteger(name + " exp complete", channelCtrl + ":NumExposuresCounter_RBV", false);
exposuresComplete.setAccessType(AccessType.Read);
estTime = new ChannelString(name + " estimated time", channelCtrl + ":ETA_STR", false);
estTime.setAccessType(AccessType.Read);
detectorState= new ChannelString(name + " detector state", channelCtrl + ":DetectorState_RBV", false);
detectorState.setAccessType(AccessType.Read);
status= new ChannelByteArray(name + " status", channelCtrl + ":StatusMessage_RBV", -1, false){
protected void onReadout(Object value){
this.setCache((value==null)?"":new String((byte[])value));
}
//protected Object convertFromRead(byte[] value){
// return (value==null) ? "" : new String((byte[])value);
//}
};
status.setAccessType(AccessType.Read);
monitoredChildren = new Device[]{acquire,
lowEnergy,centerEnergy,highEnergy,energyWidth,energyCount,
lowThetaY, centerThetaY, highThetaY, stepSizeThetaY, ThetaYWidth,ThetaYCount,
lowThetaX, centerThetaX, highThetaX, stepSizeThetaX, ThetaXWidth,ThetaXCount,
stepSize,totalSteps,currentStep, exposuresComplete, passEnergy,
lensMode, acquisitionMode, energyMode, detectorMode, elementSet,
slices, slicesReadback, channels, channelsReadback, excitationEnergy,
exposureDev, estTime, detectorState, status
};
addChildren(monitoredChildren);
addChildren(new Device[]{
data,
});
stats = new Stats[5];
stats[0] = new Stats("CountsR1", 1);
stats[1] = new Stats("CountsR2", 2);
stats[2] = new Stats("CountsR3", 3);
stats[3] = new Stats("CountsR4", 4);
stats[4] = new Stats("Counts", 5);
addChildren(stats);
}
@Override
protected void doStart() throws IOException, InterruptedException {
acquire.write(1);
}
@Override
protected void doSetSimulated() {
super.doSetSimulated();
setCache(passEnergy, "2");
setCache(lensMode, "Transmission");
setCache(acquisitionMode, "Fixed");
setCache(energyMode, "Binding");
setCache(detectorMode, "ADC");
setCache(elementSet, "High_Pass_XPS");
}
@Override
protected void doInitialize() throws IOException, InterruptedException {
super.doInitialize();
}
@Override
protected void doUpdate() throws IOException, InterruptedException {
super.doUpdate();
for (Device dev : monitoredChildren){
dev.update();
}
}
@Override
protected void doSetMonitored(boolean value) {
super.doSetMonitored(value);
for (Device dev : monitoredChildren){
dev.setMonitored(value);
}
}
@Override
protected CameraImageDescriptor doReadImageDescriptor() throws IOException, InterruptedException {
CameraImageDescriptor ret = super.doReadImageDescriptor();
List<Double> channelRange = getChannelRange();
List<Double> sliceRange = getSliceRange();
Double cb = channelRange.get(0);
Double ce = channelRange.get(1);
Double sb = sliceRange.get(0);
Double se = sliceRange.get(1);
if ((cb == null) || (ce == null) || (sb == null) || (se == null) || (ret.width == 0) || (ret.height == 0)) {
ret.calibration = null;
} else {
double scaleX = (ce - cb) / Math.max(ret.width - 1, 1);
double offsetX = cb;
double scaleY = (se - sb) / Math.max(ret.height - 1, 1);
double offsetY = sb;
ret.calibration = new MatrixCalibration(scaleX, scaleY, offsetX, offsetY);
}
return ret;
}
//Modes
public void setAcquisitionMode(String mode) throws IOException, InterruptedException { //acquisitionMode.write(String.valueOf(mode).replaceAll("_", " "));
acquisitionMode.write(mode);
}
public String getAcquisitionMode() throws IOException, InterruptedException {
return acquisitionMode.getValue();
}
public void setEnergyMode(String mode) throws IOException, InterruptedException {
energyMode.write(mode);
}
public String getEnergyMode() throws IOException, InterruptedException {
return energyMode.getValue();
}
public void setLensMode(String mode) throws IOException, InterruptedException {
lensMode.write(mode);
}
public String getLensMode() throws IOException, InterruptedException {
return lensMode.getValue();
}
public String[] getLensModes() throws IOException, InterruptedException {
return lensMode.getPositions();
}
public void setDetectorMode(String mode) throws IOException, InterruptedException {
detectorMode.write(mode);
}
public String getDetectorMode() throws IOException, InterruptedException {
return detectorMode.getValue();
}
public void setElementSet(String mode) throws IOException, InterruptedException {
throw new IOException("Read-only value");
}
public String getElementSet() throws IOException, InterruptedException {
return elementSet.getValue();
}
public void setPassEnergy(int energy) throws IOException, InterruptedException {
setPassEnergy(String.valueOf(energy));
}
public void setPassEnergy(String energy) throws IOException, InterruptedException {
passEnergy.write(energy);
}
public String getPassEnergy() throws IOException, InterruptedException {
return passEnergy.getValue();
}
public DiscretePositioner getPassEnergyDev(){
return passEnergy;
}
public DiscretePositioner getElementSetDev(){
return elementSet;
}
public DiscretePositioner getDetectorModeDev(){
return detectorMode;
}
public DiscretePositioner getLensModeDev(){
return lensMode;
}
public DiscretePositioner getAcquisitionModeDev(){
return acquisitionMode;
}
public DiscretePositioner getEnergyModeDev(){
return energyMode;
}
public Writable getRangeDev(){
return (Writable) (Object value) -> {
Integer[] range = (Integer[]) value;
int[] roi = getROI();
if ((range[0]!=null) && (range[1]!=null)){
int from = Math.min(range[0], range[1]);
int to = Math.max(range[0], range[1]);
roi[0]=from;
roi[2]=(to-from);
}
if ((range[2]!=null) && (range[3]!=null)){
int from = Math.min(range[2], range[3]);
int to = Math.max(range[2], range[3]);
roi[1]=from;
roi[3]=(to-from);
}
setROI(roi);
};
}
public void zeroSupplies() throws IOException, InterruptedException {
writeCtrl("ZERO_SUPPLIES", 1);
}
//Progress
//Disconnected operations
public double getProgress() {
Double cur = currentStep.take().doubleValue();
Double total = totalSteps.take().doubleValue();
if ((cur == null) || (total == null) || (total == 0)) {
return 0.0;
}
return cur / total;
}
//Direct register access
public ChannelInteger getAcquire() {
return acquire;
}
public ControlledVariable getLowEnergy() {
return lowEnergy;
}
public ControlledVariable getCenterEnergy() {
return centerEnergy;
}
public ControlledVariable getHighEnergy() {
return highEnergy;
}
public ControlledVariable getEnergyStepSize() {
return stepSize;
}
public ChannelDouble getEnergyWidth() {
return energyWidth;
}
public ChannelInteger getEnergyCount() {
return energyCount;
}
public ChannelDouble getExposureDev() {
return exposureDev;
}
public ControlledVariable getLowThetaY() {
return lowThetaY;
}
public ControlledVariable getCenterThetaY() {
return centerThetaY;
}
public ControlledVariable getHighThetaY() {
return highThetaY;
}
public ControlledVariable getThetaYStepSize() {
return stepSizeThetaY;
}
public ChannelDouble getThetaYWidth() {
return ThetaYWidth;
}
public ChannelInteger getThetaYCount() {
return ThetaYCount;
}
public ChannelDouble getLowThetaX() {
return lowThetaX;
}
public ControlledVariable getCenterThetaX() {
return centerThetaX;
}
public ChannelDouble getHighThetaX() {
return highThetaX;
}
public ChannelDouble getThetaXStepSize() {
return stepSizeThetaX;
}
public ChannelDouble getThetaXWidth() {
return ThetaXWidth;
}
public ChannelInteger getThetaXCount() {
return ThetaXCount;
}
public ChannelString getEstTime() {
return estTime;
}
public ChannelString getDetectorState() {
return detectorState;
}
public ChannelByteArray getStatus() {
return status;
}
public ChannelInteger getSlices() {
return slices;
}
public ChannelInteger getSlicesReadback() {
return slicesReadback;
}
public ChannelInteger getChannels() {
return channels;
}
public ChannelInteger getChannelsReadback() {
return channelsReadback;
}
public ChannelInteger getTotalSteps() {
return totalSteps;
}
public ChannelInteger getCurrentStep() {
return currentStep;
}
public ChannelInteger getExposuresComplete() {
return exposuresComplete;
}
public ControlledVariable getExcitationEnergy() {
return excitationEnergy;
}
public List<Double> getChannelRange() throws IOException, InterruptedException {
ArrayList<Double> ret = new ArrayList<>();
try {
if (isSimulated()){
ret.add(100.0);
ret.add(200.0);
} else {
ret.add(lowEnergy.getReadback().getValue());
ret.add(highEnergy.getReadback().getValue());
}
} catch (Exception ex) {
ret.add(Double.NaN);
ret.add(Double.NaN);
}
return ret;
}
public List<Double> getSliceRange() throws IOException, InterruptedException {
ArrayList<Double> ret = new ArrayList<>();
try {
if (isSimulated()){
ret.add(200.0);
ret.add(400.0);
} else {
String lens=getLensMode();
if (lens.startsWith("D")){
ret.add(lowThetaY.getReadback().getValue());
ret.add(highThetaY.getReadback().getValue());
} else {
ret.add(lowThetaX.getValue());
ret.add(highThetaX.getValue());
}
}
} catch (Exception ex) {
ret.add(Double.NaN);
ret.add(Double.NaN);
}
return ret;
}
public Integer readNumExposures() throws IOException, InterruptedException{
return (Integer) readCtrl("NumExposures_RBV", Integer.class);
}
public Double readAcqTime() throws IOException, InterruptedException{
return (Double) readCtrl("AcquireTime_RBV", Double.class);
}
public Stats[] getStats() {
return stats;
}
public class Stats extends ChannelDouble {
final int index;
final ChannelInteger uid;
Stats(String name, int index) {
super(name, channelCtrl.split(":")[0] + ":Stats" + index + ":Total_RBV", 3, false);
this.index = index;
uid = new ChannelInteger(name + " uid", channelCtrl.split(":")[0] + ":Stats" + index + ":UniqueId_RBV", false);
//setParent(Scienta.this);
addChild(uid);
}
@Override
public boolean isReady() throws IOException, InterruptedException {
Integer imageCounter = getImageCounter().getValue();
if (imageCounter == null) {
return false;
}
/*
Integer id = uid.take();
if ((id == null) || (!imageCounter.equals(id))) {
uid.update();
}
return imageCounter.equals(uid.take());
*/
return true;
}
@Override
public Double read() throws IOException, InterruptedException {
assertInitialized();
waitReady(10000);
return super.read();
}
public int getUID() throws IOException, InterruptedException {
return uid.getValue();
}
}
}