Initial commit

This commit is contained in:
gac-x09la
2021-08-27 14:25:04 +02:00
commit c1c747c22f
8 changed files with 3896 additions and 0 deletions

411
src/Scienta.java Normal file
View File

@@ -0,0 +1,411 @@
import ch.psi.jcae.ChannelException;
import ch.psi.pshell.device.AccessType;
import ch.psi.pshell.device.ArrayCalibration;
import ch.psi.pshell.device.CameraImageDescriptor;
import ch.psi.pshell.device.MatrixCalibration;
import ch.psi.pshell.device.Device;
import ch.psi.pshell.device.DeviceAdapter;
import ch.psi.pshell.device.DeviceListener;
import ch.psi.pshell.device.Readable.ReadableCalibratedArray;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import ch.psi.pshell.epics.*;
import ch.psi.utils.State;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
/**
* Implementation of Scienta spectrometer analyser.
*/
public class Scienta extends AreaDetector {
final ChannelInteger acquire;
final ChannelInteger slices;
final ChannelDouble lowEnergy, centerEnergy, highEnergy, stepSize, energyWidth;
final GenericArray data;
final ChannelInteger totalSteps, currentStep;
final ChannelString lensMode, acquisitionMode, passEnergy;
final ChannelInteger numSlices;
final Stats[] stats;
final String channelCtrl;
public Scienta(final String name, final String channelPrefix) {
this(name, channelPrefix + ":cam1", channelPrefix + ":image1");
}
public Scienta(String name, String channelCtrl, String channelData) {
super(name, channelCtrl, channelData);
this.channelCtrl = channelCtrl;
acquire = new ChannelInteger(name + " aquire", channelCtrl + ":Acquire", false);
slices = new ChannelInteger(name + " slices", channelCtrl + ":SLICES", false);
//frames = new ChannelInteger(name + " frames", channelCtrl + ":FRAMES", false);
lowEnergy = new ChannelDouble(name + " low energy", channelCtrl + ":LOW_ENERGY", 3, false);
centerEnergy = new ChannelDouble(name + " center energy", channelCtrl + ":CENTRE_ENERGY", 3, false);
highEnergy = new ChannelDouble(name + " high energy", channelCtrl + ":HIGH_ENERGY", 3, false);
stepSize = new ChannelDouble(name + " step size", channelCtrl + ":STEP_SIZE", 3, false);
energyWidth = new ChannelDouble(name + " energy width", channelCtrl + ":ENERGY_WIDTH_RBV", 3, false);
energyWidth.setAccessType(AccessType.Read);
passEnergy = new ChannelString(name + " pass energy", channelCtrl + ":PASS_ENERGY", false);
lensMode = new ChannelString(name + " lens mode", channelCtrl + ":LENS_MODE", false);
acquisitionMode = new ChannelString(name + " lens mode", channelCtrl + ":ACQ_MODE", false);
numSlices = new ChannelInteger(name + " num slices", channelCtrl + ":SLICES_RBV", false);
numSlices.setAccessType(AccessType.Read);
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);
addChildren(new Device[]{acquire, slices,
lowEnergy, centerEnergy, highEnergy, stepSize, energyWidth,
data,
totalSteps, currentStep,
passEnergy, lensMode, acquisitionMode,
numSlices
});
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 doUpdate() throws IOException, InterruptedException {
super.doUpdate();
acquire.update();
slices.update();
lowEnergy.update();
centerEnergy.update();
highEnergy.update();
energyWidth.update();
stepSize.update();
totalSteps.update();
currentStep.update();
passEnergy.update();
lensMode.update();
acquisitionMode.update();
//channelBegin.update();
//channelEnd.update();
///sliceBegin.update();
//sliceEnd.update();
}
@Override
protected void doSetMonitored(boolean value) {
super.doSetMonitored(value);
acquire.setMonitored(value);
slices.setMonitored(value);
lowEnergy.setMonitored(value);
centerEnergy.setMonitored(value);
highEnergy.setMonitored(value);
energyWidth.setMonitored(value);
stepSize.setMonitored(value);
totalSteps.setMonitored(value);
currentStep.setMonitored(value);
passEnergy.setMonitored(value);
lensMode.setMonitored(value);
acquisitionMode.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 enum AcquisitionMode {
Fixed,
Swept_Energy,
Swept_ThetaY,
Swept_Energy_ThetaY
}
public void setAcquisitionMode(AcquisitionMode mode) throws IOException, InterruptedException {
acquisitionMode.write(String.valueOf(mode).replaceAll("_", " "));
}
public AcquisitionMode getAcquisitionMode() throws IOException, InterruptedException {
String val = acquisitionMode.getValue();
return (AcquisitionMode) convertCtrlEnum(val, AcquisitionMode.class);
}
public enum EnergyMode {
Binding,
Kinetic
}
public void setEnergyMode(EnergyMode mode) throws IOException, InterruptedException {
writeCtrlEnum("ENERGY_MODE", String.valueOf(mode));
}
public EnergyMode getEnergyMode() throws IOException, InterruptedException {
return (EnergyMode) readCtrlEnum("ENERGY_MODE", EnergyMode.class);
}
public enum LensMode {
A14_01,
A14_08,
A30_01,
A30_08,
A7_08,
DA14_01,
DA14_08,
DA30_01,
DA30_08,
DA7_08,
Transmission,
Transmission_XPS
}
public void setLensMode(LensMode mode) throws IOException, InterruptedException {
//writeCtrlEnum("LENS_MODE", String.valueOf(mode));
lensMode.write(mode.equals(LensMode.Transmission_XPS) ? "Transmission XPS" : String.valueOf(mode));
}
public LensMode getLensMode() throws IOException, InterruptedException {
//return (LensMode) readCtrlEnum("LENS_MODE", LensMode.class);
String val = lensMode.getValue();
return convertCtrlEnum(val, LensMode.class);
}
public enum DetectorMode {
Pulse,
ADC
}
public void setDetectorMode(DetectorMode mode) throws IOException, InterruptedException {
writeCtrlEnum("DETECTOR_MODE", String.valueOf(mode));
}
public DetectorMode getDetectorMode() throws IOException, InterruptedException {
return (DetectorMode) readCtrlEnum("DETECTOR_MODE", DetectorMode.class);
}
public enum ElementSet {
High_Pass_XPS,
Low_Pass_UPS
}
public void setElementSet(ElementSet mode) throws IOException, InterruptedException {
throw new IOException("Read-only value");
//writeCtrlEnum("ELEMENT_SET", String.valueOf(mode));
}
public ElementSet getElementSet() throws IOException, InterruptedException {
return readCtrl("ELEMENT_SET_RBV", String.class).equals("High Pass (XPS)") ? ElementSet.High_Pass_XPS : ElementSet.Low_Pass_UPS;
}
public static final int[] PASS_ENERGY_VALUES = new int[]{1, 2, 5, 10, 20};
public void setPassEnergy(int energy) throws IOException, InterruptedException {
//writeCtrl("PASS_ENERGY", String.valueOf(energy));
passEnergy.write(String.valueOf(energy));
}
public int getPassEnergy() throws IOException, InterruptedException {
//String ret = (String) readCtrl("PASS_ENERGY", String.class);
String ret = passEnergy.getValue();
try {
return Integer.valueOf(ret);
} catch (Exception ex) {
throw new DeviceInvalidParameterException("Pass Energy", ret);
}
}
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 ChannelInteger getSlices() {
return slices;
}
public ChannelDouble getLowEnergy() {
return lowEnergy;
}
public ChannelDouble getCenterEnergy() {
return centerEnergy;
}
public ChannelDouble getHighEnergy() {
return highEnergy;
}
public ChannelDouble getStepSize() {
return stepSize;
}
public ChannelDouble getEnergyWidth() {
return energyWidth;
}
public List<Double> getChannelRange() throws IOException, InterruptedException {
ArrayList<Double> ret = new ArrayList<>();
switch (getAcquisitionMode()) {
case Fixed:
double eCenter = centerEnergy.getValue();
int ePass = getPassEnergy();
double xe = 0.04464;
double xn = 0.04464;
ret.add(eCenter - xe * ePass);
ret.add(eCenter + xn * ePass);
break;
default:
ret.add(lowEnergy.getValue());
ret.add(highEnergy.getValue());
break;
}
return ret;
}
public List<Double> getSliceRange() throws IOException, InterruptedException {
ArrayList<Double> ret = new ArrayList<>();
//ret.add(sliceBegin.getValue());
//ret.add(sliceEnd.getValue());
try {
switch (getLensMode()) {
//TODO:
/*
case Angular45:
ret.add(-28.148);
ret.add(27.649);
break;
case Angular60:
ret.add(-34.736);
ret.add(34.119);
break;
*/
case Transmission:
default:
ret.add(-2.332);
ret.add(2.291);
break;
}
} catch (Exception ex) {
ret.add(Double.NaN);
ret.add(Double.NaN);
}
return ret;
}
public ChannelInteger getNumSlices() {
return numSlices;
}
public ChannelInteger getTotalSteps() {
return totalSteps;
}
public ChannelInteger getCurrentStep() {
return currentStep;
}
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());
}
@Override
public Double read() throws IOException, InterruptedException {
assertInitialized();
waitReady(10000);
return super.read();
}
public int getUID() throws IOException, InterruptedException {
return uid.getValue();
}
}
}