diff --git a/athos-screens/build.gradle b/athos-screens/build.gradle
index dd6d668..5af5c63 100644
--- a/athos-screens/build.gradle
+++ b/athos-screens/build.gradle
@@ -1 +1,13 @@
description = 'athos-screens'
+ext.mainClass = hasProperty('mainClass') ? mainClass : 'ch.psi.pshell.workbench.App'
+ext.title = 'AthosScreens'
+ext.desc = 'AthosScreens'
+ext.ex_options = 'ch.psi.pshell.screenpanel.Options,ch.psi.athos.Options'
+ext.deploy_type= 'jar'
+
+dependencies {
+ implementation 'ch.psi:pshell-workbench:' + version
+ implementation 'ch.psi:screenpanel:' + version
+ }
+
+createDefaultTasks(project)
\ No newline at end of file
diff --git a/athos-screens/gradle.properties b/athos-screens/gradle.properties
new file mode 100644
index 0000000..083babe
--- /dev/null
+++ b/athos-screens/gradle.properties
@@ -0,0 +1 @@
+action.debug.args=debug --args="-b -d -l -k -n -q -statusbar -persist -console_log=SEVERE -frame_rate=1.1 -p ch.psi.athos.AthosCameras -laf=dark -pipeline_server localhost:8889 -camera_server localhost:8888 ch.psi.jcae.ContextFactory.addressList=localhost:54321"\n
diff --git a/athos-screens/scripts/app_startup b/athos-screens/scripts/app_startup
new file mode 100644
index 0000000..2c3ffc7
--- /dev/null
+++ b/athos-screens/scripts/app_startup
@@ -0,0 +1,7 @@
+#!/bin/sh
+export PSHELL_EX_OPTIONS=${ex_options}
+APP_ARGS_NAME=\$(echo "APP_${app_name}" | tr '[:lower:]' '[:upper:]')_ARGS
+APP_ARGS_NAME=\${APP_ARGS_NAME//-/_}
+
+# Run the JAR with all passed arguments
+exec pshell-workbench -b -d -l -k -n -q -statusbar -persist -console_log=SEVERE -frame_rate=1.1 -p ${jar_file} \${!APP_ARGS_NAME} "\$@"
diff --git a/athos-screens/src/main/java/ch/psi/athos/AthosCameras.form b/athos-screens/src/main/java/ch/psi/athos/AthosCameras.form
new file mode 100644
index 0000000..f55eb07
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/AthosCameras.form
@@ -0,0 +1,454 @@
+
+
+
diff --git a/athos-screens/src/main/java/ch/psi/athos/AthosCameras.java b/athos-screens/src/main/java/ch/psi/athos/AthosCameras.java
new file mode 100644
index 0000000..da4c0ea
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/AthosCameras.java
@@ -0,0 +1,1102 @@
+package ch.psi.athos;
+
+import ch.psi.pshell.bs.StreamValue;
+import ch.psi.pshell.camserver.PipelineSource;
+import ch.psi.pshell.device.Device;
+import ch.psi.pshell.device.DeviceListener;
+import ch.psi.pshell.device.HistogramGenerator;
+import ch.psi.pshell.device.Readable.ReadableArray;
+import ch.psi.pshell.device.Readable.ReadableNumber;
+import ch.psi.pshell.device.ReadableRegister;
+import ch.psi.pshell.device.ReadableRegister.ReadableRegisterArray;
+import ch.psi.pshell.device.ReadableRegister.ReadableRegisterNumber;
+import ch.psi.pshell.epics.ChannelString;
+import ch.psi.pshell.framework.App;
+import ch.psi.pshell.framework.Context;
+import ch.psi.pshell.framework.Panel;
+import ch.psi.pshell.framework.Setup;
+import ch.psi.pshell.imaging.Overlay;
+import ch.psi.pshell.scan.MonitorScan;
+import ch.psi.pshell.screenpanel.CamServerViewer.SourceSelecionMode;
+import ch.psi.pshell.screenpanel.Options;
+import ch.psi.pshell.sequencer.CommandSource;
+import ch.psi.pshell.swing.DataPanel;
+import ch.psi.pshell.swing.DeviceValueChart;
+import ch.psi.pshell.swing.HistogramGeneratorPanel;
+import ch.psi.pshell.swing.SwingUtils;
+import ch.psi.pshell.utils.Arr;
+import ch.psi.pshell.utils.Convert;
+import ch.psi.pshell.utils.State;
+import ch.psi.pshell.utils.Str;
+import ch.psi.pshell.utils.Threading;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.ImageIcon;
+import javax.swing.JDialog;
+import javax.swing.SwingUtilities;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ *
+ */
+public class AthosCameras extends Panel {
+ public static final String ELECTRONS_TYPE = "Electrons";
+
+ final Logger logger;
+
+ PipelineSource imagePipeline;
+ PipelineSource dataPipeline;
+ PipelineSource savePipeline;
+ //String serverUrl = "localhost:
+ Overlay errorOverlay;
+ String imageInstanceName;
+ String dataInstanceName;
+ String cameraName;
+ String persistFile = "{context}/AthosCameras";
+
+ final static String CAMERA_DEVICE_NAME = "AthosCamera";
+ static String pipelineSuffixData = "_acd";
+ static String pipelineSuffixImage = "_aci";
+ static double imageFrameRate = 2.1;
+
+ boolean dataChanged;
+ boolean persisting;
+
+ final DefaultTableModel model;
+
+ Map deviceDialogs = new HashMap<>();
+ Map dataPipelineConfig;
+
+ String remoteData;
+
+ final List fileHistory = new ArrayList<>();
+ final List fileRemHistory = new ArrayList<>();
+
+ ChannelString channelCameraName;
+ HardwarePanel hardwarePanel;
+
+ public AthosCameras() {
+ initComponents();
+ model = (DefaultTableModel) table.getModel();
+ labelRecording.setVisible(false);
+ labelSrvRecording.setVisible(false);
+ buttonOpen.setEnabled(false);
+ buttonSrvOpen.setEnabled(false);
+ if (App.hasArgument("frame_rate")) {
+ imageFrameRate = Double.parseDouble(App.getArgumentValue("frame_rate"));
+ }
+ viewer.setPipelineNameFormat("%s" + pipelineSuffixImage);
+ setPersistedComponents(new Component[]{});
+ remoteData = App.getArgumentValue("remote_data");
+ buttonSrvOpen.setVisible((remoteData != null) && (new File(remoteData)).isDirectory());
+ panelSrvRec.setVisible(remoteData != null);
+ logger = Logger.getLogger(AthosCameras.class.getName());
+ hardwarePanel = new HardwarePanel();
+ viewer.getCustomPanel().add(hardwarePanel);
+ }
+
+ ImageIcon getIcon(String name) {
+ return App.searchIcon(name);
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ try {
+ viewer.applyOptions();
+ viewer.setCameraServerUrl(ch.psi.pshell.framework.Setup.getCameraServer());
+ viewer.setPipelineServerUrl(ch.psi.pshell.framework.Setup.getPipelineServer());
+ viewer.setPersistenceFile(Setup.expandPath(persistFile).toString());
+ viewer.setSidePanelVisible(Options.SIDEBAR.getBool(false));
+ viewer.initialize(SourceSelecionMode.Single);
+
+ if (Options.CAM_NAME.hasValue()) {
+ setCamera(Options.CAM_NAME.getString(null));
+ viewer.setConsoleEnabled(true);
+ }else if (Options.STREAM.hasValue()) {
+ channelCameraName = new ChannelString("Channel Selector", Options.STREAM.getString(null));
+ channelCameraName.setMonitored(true);
+ channelCameraName.addListener(new DeviceListener() {
+ public void onValueChanged(Device device, Object value, Object former) {
+ SwingUtilities.invokeLater(() -> {
+ try {
+ setCamera(String.valueOf(value));
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, null, ex);
+ showException(ex);
+ }
+ });
+ }
+ });
+
+ channelCameraName.initialize();
+ channelCameraName.update();
+ addDevice(channelCameraName);
+ }
+ updateButtons();
+ startTimer(1000);
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, null, ex);
+ showException(ex);
+ }
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ if (state == state.Closing) {
+ try {
+ stopSrvRecording();
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ @Override
+ protected void onTimer() {
+ try {
+ if (hardwarePanel != null) {
+ hardwarePanel.onTimer();
+ }
+ } catch (Exception ex) {
+ logger.log(Level.WARNING, null, ex);
+ }
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ String getImagePipeline() {
+ if (cameraName == null) {
+ return null;
+ }
+ return cameraName + pipelineSuffixImage;
+ }
+
+ String getDataPipeline() {
+ if (cameraName == null) {
+ return null;
+ }
+ return cameraName + pipelineSuffixData;
+ }
+
+ String getDataPipelineInstance() {
+ if (cameraName == null) {
+ return null;
+ }
+ return cameraName + pipelineSuffixData + "1";
+ }
+
+ void setDataFields(List fields) throws IOException {
+ if (cameraName != null) {
+ HashMap config = new HashMap<>();
+ config.put("camera_name", cameraName);
+ config.put("include", fields.toArray(new String[0]));
+ dataPipeline.setInstanceConfig(config);
+ dataPipeline.savePipelineConfig(getDataPipeline(), config);
+ dataChanged = true;
+ }
+ }
+
+ void setCamera(String cameraName) throws IOException, InterruptedException {
+ logger.info("Initializing: " + cameraName);
+
+ boolean changed = !String.valueOf(cameraName).equals(this.cameraName);
+ this.cameraName = cameraName;
+ model.setRowCount(0);
+ updateButtons();
+ if (changed) {
+ if (hardwarePanel != null) {
+ hardwarePanel.setCamera(null);
+ }
+ }
+ if (dataPipeline != null) {
+ dataPipeline.close();
+ dataPipeline = null;
+ }
+ try {
+ stopSrvRecording();
+ } catch (Exception ex) {
+ Logger.getLogger(AthosCameras.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ if (cameraName == null) {
+ return;
+ }
+
+ logger.info("Setting camera: " + cameraName);
+ try {
+
+ String pipelineName = getImagePipeline();
+ logger.info("Creating pipeline: " + pipelineName);
+ HashMap config = new HashMap<>();
+ config.put("camera_name", cameraName);
+ config.put("name", pipelineName);
+ config.put("function", "transparent");
+ config.put("max_frame_rate", imageFrameRate);
+ viewer.setStream(config);
+
+ dataPipeline = new PipelineSource("image", viewer.getPipelineServerUrl());
+ dataPipeline.initialize();
+ dataPipeline.assertInitialized();
+ logger.info("Data pipeline initialization OK");
+
+ pipelineName = getDataPipeline();
+ dataInstanceName = getDataPipelineInstance();
+ if (!dataPipeline.getPipelines().contains(pipelineName)) {
+ logger.info("Creating pipeline: " + pipelineName);
+ dataPipelineConfig = new HashMap<>();
+ dataPipelineConfig.put("camera_name", cameraName);
+ dataPipelineConfig.put("include", new String[]{"x_center_of_mass", "y_center_of_mass",
+ "x_fit_mean", "y_fit_mean"});
+ dataPipelineConfig.put("image_region_of_interest", viewer.getServer().getRoi());
+ //server.createFromConfig(config, pipelineName);
+ dataPipeline.savePipelineConfig(pipelineName, dataPipelineConfig);
+ }
+ dataPipelineConfig = dataPipeline.getConfig(pipelineName);
+ dataPipeline.start(pipelineName, dataInstanceName);
+
+ dataPipeline.getStream().addListener(new DeviceListener() {
+ @Override
+ public void onCacheChanged(Device device, Object value, Object former, long timestamp, boolean arg4) {
+ updateData((StreamValue) value);
+ }
+ });
+
+ if (viewer.getServer()==null){
+ throw new Exception("Pipeline server not instantiated");
+ }
+ viewer.getServer().setConfigChangeListener((cfg) -> {
+ try {
+ if (cfg.containsKey("image_region_of_interest")) {
+ int[] roi = (int[]) cfg.get("image_region_of_interest");
+ if (roi == null) {
+ dataPipeline.resetRoi();
+ } else {
+ dataPipeline.setRoi(roi);
+ }
+ dataPipelineConfig.put("image_region_of_interest", roi);
+ }
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ });
+
+ updateDataPause();
+
+ if (changed) {
+ if (hardwarePanel != null) {
+ boolean electrons = (cameraName!=null) && viewer.getCameraTypes(cameraName).contains(ELECTRONS_TYPE);
+ hardwarePanel.setCamera(cameraName, electrons);
+ }
+ }
+
+ } catch (Exception ex) {
+ showException(ex);
+ } finally {
+ onTimer();
+ }
+ }
+
+ String getDoubleStr(StreamValue sv, String id) {
+ return String.format("%1.4f", sv.getValue(id));
+ }
+
+ void updateData(StreamValue value) {
+ List ids = value.getIdentifiers();
+ List values = value.getValues();
+ if (dataChanged) {
+ //Collections.sort(ids, c);
+ dataChanged = false;
+ }
+ if (model.getRowCount() != ids.size()) {
+ model.setRowCount(ids.size());
+ for (int i = 0; i < ids.size(); i++) {
+ model.setValueAt(ids.get(i), i, 0);
+ }
+ }
+ for (int i = 0; i < values.size(); i++) {
+ Object val = values.get(i);
+ if (val instanceof Double) {
+ val = String.format("%1.4f", val);
+ }
+ model.setValueAt(val, i, 1);
+ }
+ }
+
+ ch.psi.pshell.device.Readable[] getReadables() {
+ ch.psi.pshell.device.Readable[] ret = dataPipeline.getStream().getReadables().toArray(new ch.psi.pshell.device.Readable[0]);
+ String[] ids = dataPipeline.getStream().getIdentifiers().toArray(new String[0]);
+ String[] imageIds = new String[]{"image", "width", "height"};
+ if (Arr.containsAllEqual(ids, imageIds)) {
+ for (ch.psi.pshell.device.Readable r : Arr.copy(ret)) {
+ if (Arr.containsEqual(imageIds, r.getName())) {
+ ret = Arr.remove(ret, r);
+ }
+ }
+ ret = Arr.append(ret, dataPipeline.getDataMatrix());
+ }
+ return ret;
+ }
+
+ MonitorScan recordingScan;
+
+ void startRecording() throws Exception {
+ stopRecording();
+ Context.getInterpreter().startExecution(CommandSource.plugin, null, cameraName, null, false);
+ Context.getInterpreter().setExecutionPar("name", cameraName);
+ Context.getInterpreter().setExecutionPar("open", true);
+ recordingScan = new MonitorScan(dataPipeline.getStream(), getReadables(), -1, -1);
+ Threading.getFuture(() -> recordingScan.start()).handle((ret, t) -> {
+ recordingScan = null;
+ return ret;
+ });
+ String fileName = Context.getInterpreter().getExecutionPars().getPath();
+ logger.info("Start recording: " + fileName);
+ fileHistory.add(fileName);
+ listFile.setModel(new javax.swing.AbstractListModel() {
+ @Override
+ public int getSize() {
+ return fileHistory.size();
+ }
+
+ @Override
+ public String getElementAt(int i) {
+ return fileHistory.get(getSize() - i - 1);
+ }
+ });
+ listFile.setSelectedIndex(0);
+ }
+
+ void stopRecording() throws Exception {
+ if (recordingScan != null) {
+ logger.info("Stop recording");
+ recordingScan.abort();
+ Context.getInterpreter().endExecution();
+ recordingScan = null;
+ }
+ }
+
+ void startSrvRecording() throws Exception {
+ stopSrvRecording();
+ String fileName = Setup.expandPath("{date}_{time}_" + cameraName, System.currentTimeMillis());
+ fileName = Paths.get(remoteData, fileName + ".h5").toString();
+ logger.info("Start server recording: " + fileName);
+
+ HashMap config = (HashMap) ((HashMap) dataPipelineConfig).clone();
+ config.put("mode", "FILE");
+ config.put("file", fileName);
+ config.put("layout", "FLAT");
+ config.put("localtime", false);
+ config.put("change", false);
+ if (App.hasArgument("rlay")) {
+ String[] tokens = App.getArgumentValue("rlay").split("\\|");
+ config.put("layout", tokens[0]);
+ if (tokens.length > 1) {
+ config.put("localtime", Boolean.valueOf(tokens[1]));
+ }
+ if (tokens.length > 2) {
+ config.put("change", Boolean.valueOf(tokens[2]));
+ }
+ }
+ String instanceName = getDataPipeline() + "_save";
+ savePipeline = new PipelineSource("Save Pipeline", viewer.getPipelineServerUrl());
+ savePipeline.createFromConfig(config, instanceName);
+ savePipeline.start(instanceName, true);
+
+ fileRemHistory.add(fileName);
+ listRemFile.setModel(new javax.swing.AbstractListModel() {
+ @Override
+ public int getSize() {
+ return fileRemHistory.size();
+ }
+
+ @Override
+ public String getElementAt(int i) {
+ return fileRemHistory.get(getSize() - i - 1);
+ }
+ });
+ listRemFile.setSelectedIndex(0);
+ }
+
+ void stopSrvRecording() throws Exception {
+ if (savePipeline != null) {
+ logger.info("Stop server recording");
+ savePipeline.stopInstance(getDataPipeline() + "_save");
+ savePipeline.stop();
+ savePipeline = null;
+ }
+ }
+
+ void updateDataPause() throws Exception {
+ dataPipeline.setInstanceConfigValue("pause", buttonDataPause.isSelected());
+ }
+
+ void openFile(boolean server) throws Exception {
+ String filename = server ? listRemFile.getSelectedValue() : listFile.getSelectedValue();
+ DataPanel panel = DataPanel.create(new File(filename));
+ SwingUtils.showDialog(getTopLevel(), filename, new Dimension(600, 400), panel);
+ }
+
+ ReadableRegister geStreamDevice(String field) throws Exception {
+ Object obj = dataPipeline.getValue(field);
+
+ if ((obj != null) && (obj.getClass().isArray() || (obj instanceof Number))) {
+ if (!field.equals("processing_parameters")) {
+ ReadableRegister dev;
+ if (obj.getClass().isArray()) {
+ dev = new ReadableRegisterArray(new ReadableArray() {
+ @Override
+ public Object read() throws IOException, InterruptedException {
+ return Convert.toDouble(dataPipeline.getValue(field));
+ }
+
+ @Override
+ public int getSize() {
+ return Array.getLength(dataPipeline.getValue(field));
+ }
+ });
+ } else {
+ dev = new ReadableRegisterNumber(new ReadableNumber() {
+ @Override
+ public Object read() throws IOException, InterruptedException {
+ return Convert.toDouble(dataPipeline.getValue(field));
+ }
+ });
+ }
+ DeviceListener listener = new DeviceListener() {
+ @Override
+ public void onCacheChanged(Device device, Object value, Object former, long timestamp, boolean valueChange) {
+ if (dev.isClosed()){
+ dataPipeline.getStream().addListener(this);
+ } else {
+ dev.updateAsync();
+ }
+ }
+ };
+
+ dataPipeline.getStream().addListener(listener);
+ return dev;
+ }
+ }
+ return null;
+ }
+
+ void showPlot(String field) throws Exception {
+ String title = cameraName + " " + field;
+ if (deviceDialogs.containsKey(title)) {
+ JDialog dlg = deviceDialogs.get(title);
+ if ((dlg != null) && dlg.isShowing()) {
+ dlg.requestFocus();
+ return;
+ }
+ }
+ DeviceListener listener;
+
+ if (field.equals("processing_parameters")) {
+ Map pars = viewer.getProcessingParameters(dataPipeline.getStream().take());
+ StringBuilder sb = new StringBuilder();
+ for (String key : pars.keySet()) {
+ sb.append(key).append(" = ").append(Str.toString(pars.get(key), 10)).append("\n");
+ }
+ SwingUtils.showMessage(this, "Processing Parameters", sb.toString());
+ } else{
+ Device dev = geStreamDevice(field);
+ if (dev != null) {
+ DeviceValueChart chart = new DeviceValueChart();
+ chart.setAsyncUpdates(true);
+ //dev.setPolling(1000);
+ chart.setDevice(dev);
+ JDialog dlg = SwingUtils.showDialog(AthosCameras.this.getTopLevel(), title, null, chart);
+ dlg.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ try {
+ dev.close();
+ } catch (Exception ex) {
+ AthosCameras.this.showException(ex);
+ }
+ }
+ });
+ deviceDialogs.put(title, dlg);
+ }
+ }
+ }
+
+ void showHistogram(String field) throws Exception {
+ String title = cameraName + " " + field + " histogram";
+ if (deviceDialogs.containsKey(title)) {
+ JDialog dlg = deviceDialogs.get(title);
+ if ((dlg != null) && dlg.isShowing()) {
+ dlg.requestFocus();
+ return;
+ }
+ }
+ ReadableRegister dev = geStreamDevice(field);
+ if (dev != null) {
+ HistogramGenerator hdev = new HistogramGenerator(title, dev, 100, Double.NaN, Double.NaN, 100);
+ hdev.initialize();
+ HistogramGeneratorPanel panel = new HistogramGeneratorPanel();
+ panel.setDevice(hdev);
+ //hdev.setMonitored(true);
+ hdev.setPolling(2000);
+ JDialog dlg = SwingUtils.showDialog(AthosCameras.this.getTopLevel(), title, null, panel);
+ dlg.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ dev.close();
+ }
+ });
+ deviceDialogs.put(title, dlg);
+ }
+ }
+
+ void updateButtons() {
+ boolean serveRec = savePipeline != null;
+ boolean localRec = recordingScan != null;
+ boolean running = cameraName != null;
+
+ buttonReset.setEnabled(running);
+ buttonSrvRec.setEnabled(running);
+ buttonRec.setEnabled(running);
+ buttonSelect.setEnabled(running);
+ buttonPlot.setEnabled((table.getRowCount() > 0) && (table.getSelectedRowCount() == 1));
+ buttonHistogram.setEnabled(buttonPlot.isEnabled());
+
+ buttonOpen.setEnabled(fileHistory.size() > 0);
+ buttonSrvOpen.setEnabled((fileRemHistory.size() > 0)
+ && ((!serveRec) || ((listRemFile.getSelectedIndex() > 0))));
+
+ buttonRec.setSelected(localRec);
+ buttonStop.setEnabled(localRec);
+ labelRecording.setVisible(localRec);
+
+ buttonSrvRec.setSelected(serveRec);
+ buttonSrvStop.setEnabled(serveRec);
+ labelSrvRecording.setVisible(serveRec);
+
+ }
+
+ public static void main(String args[]) throws Exception {
+ args = Arr.append(new String[]{"-l", "-persist", "-q", "-b", "-e", "-g", "-n", "-d", "-laf dark",
+ "-p=ch.psi.athos.AthosCameras",},
+ args);
+ App.main(args);
+ }
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ viewer = new ch.psi.pshell.screenpanel.CamServerViewer();
+ jPanel1 = new javax.swing.JPanel();
+ panelSrvRec = new javax.swing.JPanel();
+ buttonSrvRec = new javax.swing.JToggleButton();
+ buttonSrvStop = new javax.swing.JButton();
+ buttonSrvOpen = new javax.swing.JButton();
+ scrollListRemFile = new javax.swing.JScrollPane();
+ listRemFile = new javax.swing.JList<>();
+ labelSrvRecording = new javax.swing.JLabel();
+ panelData = new javax.swing.JPanel();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ table = new javax.swing.JTable();
+ buttonSelect = new javax.swing.JButton();
+ buttonPlot = new javax.swing.JButton();
+ buttonDataPause = new javax.swing.JToggleButton();
+ buttonReset = new javax.swing.JButton();
+ buttonHistogram = new javax.swing.JButton();
+ panelRec = new javax.swing.JPanel();
+ buttonRec = new javax.swing.JToggleButton();
+ buttonStop = new javax.swing.JButton();
+ buttonOpen = new javax.swing.JButton();
+ scrollListFile = new javax.swing.JScrollPane();
+ listFile = new javax.swing.JList<>();
+ labelRecording = new javax.swing.JLabel();
+
+ viewer.setLocalFit(java.lang.Boolean.TRUE);
+ viewer.setPipelineServerUrl("localhost:8889");
+ viewer.setShowFit(false);
+
+ panelSrvRec.setBorder(javax.swing.BorderFactory.createTitledBorder("Server Data Recording"));
+
+ buttonSrvRec.setIcon(getIcon("Rec"));
+ buttonSrvRec.setToolTipText("Start Data Recording");
+ buttonSrvRec.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonSrvRecActionPerformed(evt);
+ }
+ });
+
+ buttonSrvStop.setIcon(getIcon("Stop"));
+ buttonSrvStop.setEnabled(false);
+ buttonSrvStop.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonSrvStopActionPerformed(evt);
+ }
+ });
+
+ buttonSrvOpen.setText("Open");
+ buttonSrvOpen.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonSrvOpenActionPerformed(evt);
+ }
+ });
+
+ scrollListRemFile.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ scrollListRemFile.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ scrollListRemFile.setSize(new java.awt.Dimension(275, 0));
+ scrollListRemFile.setViewportView(null);
+
+ listRemFile.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ listRemFile.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
+ public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
+ listRemFileValueChanged(evt);
+ }
+ });
+ scrollListRemFile.setViewportView(listRemFile);
+
+ labelSrvRecording.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N
+ labelSrvRecording.setForeground(new java.awt.Color(255, 0, 0));
+ labelSrvRecording.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelSrvRecording.setText("RECORDING");
+
+ javax.swing.GroupLayout panelSrvRecLayout = new javax.swing.GroupLayout(panelSrvRec);
+ panelSrvRec.setLayout(panelSrvRecLayout);
+ panelSrvRecLayout.setHorizontalGroup(
+ panelSrvRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelSrvRecLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelSrvRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelSrvRecLayout.createSequentialGroup()
+ .addComponent(buttonSrvRec)
+ .addGap(0, 0, 0)
+ .addComponent(buttonSrvStop)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE)
+ .addComponent(labelSrvRecording)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
+ .addComponent(buttonSrvOpen))
+ .addComponent(scrollListRemFile, javax.swing.GroupLayout.DEFAULT_SIZE, 336, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+
+ panelSrvRecLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonSrvRec, buttonSrvStop});
+
+ panelSrvRecLayout.setVerticalGroup(
+ panelSrvRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelSrvRecLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelSrvRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(buttonSrvRec)
+ .addComponent(buttonSrvStop)
+ .addComponent(labelSrvRecording, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonSrvOpen))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(scrollListRemFile, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ panelSrvRecLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {buttonSrvOpen, buttonSrvRec, buttonSrvStop});
+
+ panelData.setBorder(javax.swing.BorderFactory.createTitledBorder("Data Fields"));
+
+ table.setModel(new javax.swing.table.DefaultTableModel(
+ new Object [][] {
+
+ },
+ new String [] {
+ "Name", "Value"
+ }
+ ) {
+ Class[] types = new Class [] {
+ java.lang.String.class, java.lang.Object.class
+ };
+ boolean[] canEdit = new boolean [] {
+ false, false
+ };
+
+ public Class getColumnClass(int columnIndex) {
+ return types [columnIndex];
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return canEdit [columnIndex];
+ }
+ });
+ table.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseReleased(java.awt.event.MouseEvent evt) {
+ tableMouseReleased(evt);
+ }
+ });
+ table.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ tableKeyReleased(evt);
+ }
+ });
+ jScrollPane1.setViewportView(table);
+
+ buttonSelect.setText("Select");
+ buttonSelect.setEnabled(false);
+ buttonSelect.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonSelectActionPerformed(evt);
+ }
+ });
+
+ buttonPlot.setText("Plot");
+ buttonPlot.setEnabled(false);
+ buttonPlot.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonPlotActionPerformed(evt);
+ }
+ });
+
+ buttonDataPause.setIcon(getIcon("Pause"));
+ buttonDataPause.setToolTipText("Start Data Recording");
+ buttonDataPause.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonDataPauseActionPerformed(evt);
+ }
+ });
+
+ buttonReset.setIcon(getIcon("Reset"));
+ buttonReset.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonResetActionPerformed(evt);
+ }
+ });
+
+ buttonHistogram.setText("Histo");
+ buttonHistogram.setEnabled(false);
+ buttonHistogram.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonHistogramActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelDataLayout = new javax.swing.GroupLayout(panelData);
+ panelData.setLayout(panelDataLayout);
+ panelDataLayout.setHorizontalGroup(
+ panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelDataLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelDataLayout.createSequentialGroup()
+ .addComponent(buttonReset)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonDataPause)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 12, Short.MAX_VALUE)
+ .addComponent(buttonHistogram)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonPlot))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelDataLayout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(buttonSelect)))
+ .addContainerGap())
+ );
+
+ panelDataLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonHistogram, buttonPlot, buttonSelect});
+
+ panelDataLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonDataPause, buttonReset});
+
+ panelDataLayout.setVerticalGroup(
+ panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelDataLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(buttonDataPause)
+ .addComponent(buttonPlot)
+ .addComponent(buttonReset)
+ .addComponent(buttonHistogram))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 216, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonSelect)
+ .addContainerGap())
+ );
+
+ panelDataLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {buttonDataPause, buttonPlot, buttonReset, buttonSelect});
+
+ panelRec.setBorder(javax.swing.BorderFactory.createTitledBorder("Local Data Recording"));
+
+ buttonRec.setIcon(getIcon("Rec"));
+ buttonRec.setToolTipText("Start Data Recording");
+ buttonRec.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonRecActionPerformed(evt);
+ }
+ });
+
+ buttonStop.setIcon(getIcon("Stop"));
+ buttonStop.setEnabled(false);
+ buttonStop.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStopActionPerformed(evt);
+ }
+ });
+
+ buttonOpen.setText("Open");
+ buttonOpen.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonOpenActionPerformed(evt);
+ }
+ });
+
+ scrollListFile.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ scrollListFile.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ scrollListFile.setViewportView(null);
+
+ listFile.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ listFile.setSize(new java.awt.Dimension(275, 0));
+ scrollListFile.setViewportView(listFile);
+
+ labelRecording.setFont(new java.awt.Font("Lucida Grande", 0, 12)); // NOI18N
+ labelRecording.setForeground(new java.awt.Color(255, 0, 0));
+ labelRecording.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+ labelRecording.setText("RECORDING");
+
+ javax.swing.GroupLayout panelRecLayout = new javax.swing.GroupLayout(panelRec);
+ panelRec.setLayout(panelRecLayout);
+ panelRecLayout.setHorizontalGroup(
+ panelRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelRecLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelRecLayout.createSequentialGroup()
+ .addComponent(scrollListFile, javax.swing.GroupLayout.DEFAULT_SIZE, 336, Short.MAX_VALUE)
+ .addContainerGap())
+ .addGroup(panelRecLayout.createSequentialGroup()
+ .addComponent(buttonRec)
+ .addGap(0, 0, 0)
+ .addComponent(buttonStop)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 22, Short.MAX_VALUE)
+ .addComponent(labelRecording)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 23, Short.MAX_VALUE)
+ .addComponent(buttonOpen))))
+ );
+
+ panelRecLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonRec, buttonStop});
+
+ panelRecLayout.setVerticalGroup(
+ panelRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelRecLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelRecLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(buttonRec)
+ .addComponent(buttonStop)
+ .addComponent(buttonOpen)
+ .addComponent(labelRecording, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(scrollListFile, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ panelRecLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {buttonOpen, buttonRec, buttonStop});
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(0, 0, 0)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(panelRec, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(panelData, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(panelSrvRec, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap())
+ );
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {panelData, panelRec, panelSrvRec});
+
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(panelData, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(panelSrvRec, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(panelRec, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(viewer, javax.swing.GroupLayout.PREFERRED_SIZE, 411, Short.MAX_VALUE)
+ .addGap(0, 0, 0)
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(viewer, javax.swing.GroupLayout.DEFAULT_SIZE, 603, Short.MAX_VALUE)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ }// //GEN-END:initComponents
+
+ private void buttonRecActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRecActionPerformed
+ try {
+ if (buttonRec.isSelected()) {
+ startRecording();
+ } else {
+ stopRecording();
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ updateButtons();
+ }//GEN-LAST:event_buttonRecActionPerformed
+
+ private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed
+ buttonRec.setSelected(false);
+ buttonRecActionPerformed(null);
+ }//GEN-LAST:event_buttonStopActionPerformed
+
+ private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed
+ try {
+ openFile(false);
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonOpenActionPerformed
+
+ private void buttonSelectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSelectActionPerformed
+ try {
+ String instance = getDataPipelineInstance();
+ if (instance != null) {
+ DataSelector dlg = new DataSelector(getTopLevel(), true);
+ dlg.setLocationRelativeTo(getTopLevel());
+ dlg.set(viewer.getPipelineServerUrl(), instance);
+ dlg.setVisible(true);
+ if (dlg.getResult()) {
+ setDataFields(dlg.selected);
+ }
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonSelectActionPerformed
+
+ private void buttonPlotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPlotActionPerformed
+ try {
+ if (table.getSelectedRow() >= 0) {
+ String field = (String) model.getValueAt(table.getSelectedRow(), 0);
+ showPlot(field);
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonPlotActionPerformed
+
+ private void tableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseReleased
+ updateButtons();
+ }//GEN-LAST:event_tableMouseReleased
+
+ private void tableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableKeyReleased
+ updateButtons();
+ }//GEN-LAST:event_tableKeyReleased
+
+ private void buttonSrvRecActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSrvRecActionPerformed
+ try {
+ if (buttonSrvRec.isSelected()) {
+ startSrvRecording();
+ } else {
+ stopSrvRecording();
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ updateButtons();
+ }//GEN-LAST:event_buttonSrvRecActionPerformed
+
+ private void buttonSrvStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSrvStopActionPerformed
+ buttonSrvRec.setSelected(false);
+ buttonSrvRecActionPerformed(null);
+ }//GEN-LAST:event_buttonSrvStopActionPerformed
+
+ private void buttonDataPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDataPauseActionPerformed
+ try {
+ updateDataPause();
+ } catch (Exception ex) {
+ buttonDataPause.setSelected(false);
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonDataPauseActionPerformed
+
+ private void buttonSrvOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSrvOpenActionPerformed
+ try {
+ openFile(true);
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonSrvOpenActionPerformed
+
+ private void buttonResetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResetActionPerformed
+ try {
+ setCamera(cameraName);
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonResetActionPerformed
+
+ private void listRemFileValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listRemFileValueChanged
+ updateButtons();
+ }//GEN-LAST:event_listRemFileValueChanged
+
+ private void buttonHistogramActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonHistogramActionPerformed
+ try {
+ if (table.getSelectedRow() >= 0) {
+ String field = (String) model.getValueAt(table.getSelectedRow(), 0);
+ showHistogram(field);
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ }//GEN-LAST:event_buttonHistogramActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JToggleButton buttonDataPause;
+ private javax.swing.JButton buttonHistogram;
+ private javax.swing.JButton buttonOpen;
+ private javax.swing.JButton buttonPlot;
+ private javax.swing.JToggleButton buttonRec;
+ private javax.swing.JButton buttonReset;
+ private javax.swing.JButton buttonSelect;
+ private javax.swing.JButton buttonSrvOpen;
+ private javax.swing.JToggleButton buttonSrvRec;
+ private javax.swing.JButton buttonSrvStop;
+ private javax.swing.JButton buttonStop;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JLabel labelRecording;
+ private javax.swing.JLabel labelSrvRecording;
+ private javax.swing.JList listFile;
+ private javax.swing.JList listRemFile;
+ private javax.swing.JPanel panelData;
+ private javax.swing.JPanel panelRec;
+ private javax.swing.JPanel panelSrvRec;
+ private javax.swing.JScrollPane scrollListFile;
+ private javax.swing.JScrollPane scrollListRemFile;
+ private javax.swing.JTable table;
+ private ch.psi.pshell.screenpanel.CamServerViewer viewer;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/athos-screens/src/main/java/ch/psi/athos/DataSelector.form b/athos-screens/src/main/java/ch/psi/athos/DataSelector.form
new file mode 100644
index 0000000..40f7bcb
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/DataSelector.form
@@ -0,0 +1,87 @@
+
+
+
diff --git a/athos-screens/src/main/java/ch/psi/athos/DataSelector.java b/athos-screens/src/main/java/ch/psi/athos/DataSelector.java
new file mode 100644
index 0000000..4381584
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/DataSelector.java
@@ -0,0 +1,214 @@
+package ch.psi.athos;
+
+import ch.psi.pshell.camserver.PipelineSource;
+import ch.psi.pshell.swing.StandardDialog;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ *
+ */
+public class DataSelector extends StandardDialog {
+ final DefaultTableModel model;
+ List selected = new ArrayList();
+ /**
+ * Creates new form DataSelector
+ */
+ public DataSelector(java.awt.Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ model = (DefaultTableModel) table.getModel();
+ }
+
+ public void set(String serverUrl, String pipelineName) throws Exception{
+
+ try (PipelineSource server = new PipelineSource("Data pipeline", serverUrl)){
+ server.initialize();
+ Map cfg = server.getInstanceConfig(pipelineName);
+ List include = (List) cfg.get("include");
+ String cameraName = (String) cfg.get("camera_name");
+
+
+ String instanceName = cameraName + AthosCameras.pipelineSuffixData + "info";
+ try{
+ if (!server.getInstances().contains(instanceName)) {
+ HashMap config = new HashMap<>();
+ config.put("camera_name", cameraName);
+ server.createFromConfig(config, instanceName);
+ }
+ server.start(instanceName, true);
+ server.getStream().waitCacheChange(10000);
+ List ids = server.getStream().getIdentifiers();
+ Collections.sort(ids);
+ model.setRowCount(ids.size());
+ for (int i=0; i< ids.size(); i++){
+ model.setValueAt(ids.get(i), i, 0);
+ model.setValueAt(include.contains(ids.get(i)), i, 1);
+ }
+ } finally{
+ server.stop();
+ }
+ }
+ }
+
+ public List getEnabled(){
+ List ret = new ArrayList<>();
+ for (int i=0; i//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new javax.swing.JScrollPane();
+ table = new javax.swing.JTable();
+ buttonCancel = new javax.swing.JButton();
+ buttonOk = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ table.setModel(new javax.swing.table.DefaultTableModel(
+ new Object [][] {
+
+ },
+ new String [] {
+ "Name", "Enable"
+ }
+ ) {
+ Class[] types = new Class [] {
+ java.lang.String.class, java.lang.Boolean.class
+ };
+ boolean[] canEdit = new boolean [] {
+ false, true
+ };
+
+ public Class getColumnClass(int columnIndex) {
+ return types [columnIndex];
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return canEdit [columnIndex];
+ }
+ });
+ jScrollPane1.setViewportView(table);
+
+ buttonCancel.setText("Cancel");
+ buttonCancel.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonCancelActionPerformed(evt);
+ }
+ });
+
+ buttonOk.setText("OK");
+ buttonOk.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonOkActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap(72, Short.MAX_VALUE)
+ .addComponent(buttonCancel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonOk)
+ .addContainerGap(72, Short.MAX_VALUE))
+ );
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonCancel, buttonOk});
+
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(buttonOk)
+ .addComponent(buttonCancel))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
+ this.cancel();
+ }//GEN-LAST:event_buttonCancelActionPerformed
+
+ private void buttonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOkActionPerformed
+ selected.clear();
+ for (int i=0; i< model.getRowCount(); i++){
+ if (Boolean.TRUE.equals(model.getValueAt(i, 1))){
+ selected.add(String.valueOf(model.getValueAt(i, 0)));
+ }
+ }
+ this.accept();
+ }//GEN-LAST:event_buttonOkActionPerformed
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ /* Set the Nimbus look and feel */
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(DataSelector.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(DataSelector.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(DataSelector.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(DataSelector.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+
+ /* Create and display the dialog */
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ DataSelector dialog = new DataSelector(new javax.swing.JFrame(), true);
+ dialog.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ System.exit(0);
+ }
+ });
+ dialog.setVisible(true);
+ }
+ });
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonCancel;
+ private javax.swing.JButton buttonOk;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTable table;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.form b/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.form
new file mode 100644
index 0000000..e99d784
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.form
@@ -0,0 +1,135 @@
+
+
+
diff --git a/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.java b/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.java
new file mode 100644
index 0000000..e9727e1
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/HardwarePanel.java
@@ -0,0 +1,268 @@
+package ch.psi.athos;
+
+import ch.psi.pshell.device.Device;
+import ch.psi.pshell.epics.ChannelInteger;
+import ch.psi.pshell.epics.DiscretePositioner;
+import ch.psi.pshell.swing.SwingUtils;
+import javax.swing.DefaultComboBoxModel;
+
+/**
+ *
+ */
+public class HardwarePanel extends javax.swing.JPanel {
+
+ DiscretePositioner screen;
+ DiscretePositioner filter;
+ Thread devicesInitTask;
+
+ public HardwarePanel() {
+ initComponents();
+ }
+
+ public void onTimer() {
+ for (Device dev : new Device[]{screen, filter}) {
+ if (dev != null) {
+ dev.request();
+ }
+ }
+ }
+
+ String cameraName;
+
+
+ public void setCamera(String cameraName) {
+ setCamera(cameraName, false);
+ }
+
+ public void setCamera(String cameraName, boolean electrons) {
+ this.cameraName = cameraName;
+
+ if ((devicesInitTask != null) && (devicesInitTask.isAlive())) {
+ devicesInitTask.interrupt();
+ }
+ if (screen != null) {
+ screen.close();
+ screen = null;
+ }
+ if (filter != null) {
+ filter.close();
+ filter = null;
+ }
+
+ comboScreen.setModel(new DefaultComboBoxModel());
+ comboScreen.setEnabled(false);
+ comboFilter.setModel(new DefaultComboBoxModel());
+ comboFilter.setEnabled(false);
+ panelFilter.setVisible(electrons);
+ panelScreen.setVisible(electrons);
+
+ if (cameraName!=null){
+ if (electrons) {
+ //Parallelizing initialization
+ devicesInitTask = new Thread(() -> {
+ try {
+ if (cameraName.contains("DSRM")) {
+ screen = new DiscretePositioner("CurrentScreen", cameraName + ":POSITION_SP", cameraName + ":POSITION");
+ } else {
+ screen = new DiscretePositioner("CurrentScreen", cameraName + ":SET_SCREEN1_POS", cameraName + ":GET_SCREEN1_POS");
+ }
+ screen.setMonitored(true);
+ screen.initialize();
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ for (String pos : screen.getPositions()) {
+ model.addElement(pos);
+ }
+ comboScreen.setModel(model);
+ comboScreen.setSelectedItem(screen.read());
+
+ } catch (Exception ex) {
+ comboScreen.setModel(new DefaultComboBoxModel());
+ System.err.println(ex.getMessage());
+ screen = null;
+ }
+ comboScreen.setEnabled(screen != null);
+ valueScreen.setDevice(screen);
+
+ try {
+ filter = new DiscretePositioner("CurrentFilter", cameraName + ":SET_FILTER", cameraName + ":GET_FILTER");
+ filter.setMonitored(true);
+ filter.initialize();
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ for (String pos : filter.getPositions()) {
+ model.addElement(pos);
+ }
+ comboFilter.setModel(model);
+ comboFilter.setSelectedItem(filter.read());
+ } catch (Exception ex) {
+ System.err.println(ex.getMessage());
+ filter = null;
+ }
+ comboFilter.setEnabled(filter != null);
+ valueFilter.setDevice(filter);
+ });
+ devicesInitTask.start();
+ }
+ }
+ }
+
+ public String getCamera() {
+ return cameraName;
+ }
+
+ public String getScreenValue() {
+ return String.valueOf(valueScreen.getLabel().getText());
+ }
+
+ public String getFilterValue() {
+ return String.valueOf(valueFilter.getLabel().getText());
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ panelScreen = new javax.swing.JPanel();
+ valueScreen = new ch.psi.pshell.swing.DeviceValuePanel();
+ comboScreen = new javax.swing.JComboBox();
+ panelFilter = new javax.swing.JPanel();
+ valueFilter = new ch.psi.pshell.swing.DeviceValuePanel();
+ comboFilter = new javax.swing.JComboBox();
+
+ panelScreen.setBorder(javax.swing.BorderFactory.createTitledBorder("Screen"));
+
+ comboScreen.setEnabled(false);
+ comboScreen.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ comboScreenActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelScreenLayout = new javax.swing.GroupLayout(panelScreen);
+ panelScreen.setLayout(panelScreenLayout);
+ panelScreenLayout.setHorizontalGroup(
+ panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelScreenLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(valueScreen, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(comboScreen, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ panelScreenLayout.setVerticalGroup(
+ panelScreenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelScreenLayout.createSequentialGroup()
+ .addGap(4, 4, 4)
+ .addComponent(comboScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(valueScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ panelFilter.setBorder(javax.swing.BorderFactory.createTitledBorder("Filter"));
+
+ comboFilter.setEnabled(false);
+ comboFilter.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ comboFilterActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
+ panelFilter.setLayout(panelFilterLayout);
+ panelFilterLayout.setHorizontalGroup(
+ panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelFilterLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(valueFilter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(comboFilter, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ panelFilterLayout.setVerticalGroup(
+ panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup()
+ .addGap(4, 4, 4)
+ .addComponent(comboFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(valueFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(panelScreen, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(panelFilter, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(panelScreen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+ }// //GEN-END:initComponents
+
+ private void comboScreenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboScreenActionPerformed
+
+ comboScreen.setEnabled(false);
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ChannelInteger setpoint = null;
+ try {
+ int index = comboScreen.getSelectedIndex();
+ if (index >= 0) {
+ if (cameraName.contains("DSRM")) {
+ setpoint = new ChannelInteger(null, cameraName + ":POSITION_SP");
+ } else {
+ setpoint = new ChannelInteger(null, cameraName + ":SET_SCREEN1_POS");
+ }
+ setpoint.initialize();
+ Integer readback = setpoint.read();
+ if ((readback == null) || (setpoint.read() != index)) {
+ setpoint.write(index);
+ }
+ screen.read();
+ }
+ } catch (Exception ex) {
+ SwingUtils.showException(HardwarePanel.this, ex);
+ } finally {
+ comboScreen.setEnabled(true);
+ if (setpoint != null) {
+ setpoint.close();
+ }
+ }
+ }
+ }).start();
+ }//GEN-LAST:event_comboScreenActionPerformed
+
+ private void comboFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboFilterActionPerformed
+ try {
+ String setpoint = (String) comboFilter.getSelectedItem();
+ if (setpoint != null) {
+ if (!setpoint.equals(filter.read())) {
+ filter.write(setpoint);
+ }
+ }
+ } catch (Exception ex) {
+ SwingUtils.showException(HardwarePanel.this, ex);
+ }
+ }//GEN-LAST:event_comboFilterActionPerformed
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JComboBox comboFilter;
+ private javax.swing.JComboBox comboScreen;
+ private javax.swing.JPanel panelFilter;
+ private javax.swing.JPanel panelScreen;
+ private ch.psi.pshell.swing.DeviceValuePanel valueFilter;
+ private ch.psi.pshell.swing.DeviceValuePanel valueScreen;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/athos-screens/src/main/java/ch/psi/athos/Options.java b/athos-screens/src/main/java/ch/psi/athos/Options.java
new file mode 100644
index 0000000..f724b17
--- /dev/null
+++ b/athos-screens/src/main/java/ch/psi/athos/Options.java
@@ -0,0 +1,15 @@
+
+package ch.psi.athos;
+
+import ch.psi.pshell.app.Option;
+
+/**
+ *
+ */
+ public enum Options implements Option {
+ FRAME_RATE;
+
+ public static void add(){
+ FRAME_RATE.add("ft", "Maximum image frame rate");
+ }
+}
diff --git a/build.gradle b/build.gradle
index 4250480..d69b6aa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -10,6 +10,7 @@ allprojects {
ext.release = '1'
ext.jar_suffix = 'fat'
ext.ex_options= ''
+ ext.deploy_type= 'java'
repositories {
mavenLocal()
@@ -85,15 +86,18 @@ subprojects {
def app_release = project.ext.release.toString()
def jar_suffix = project.ext.jar_suffix.toString()
def ex_options = project.ext.ex_options
+ def deploy_type = project.ext.deploy_type
def package_name = project.name
def app_path = '/opt/' + package_name + "/" + app_version
- def jar_file_name = app_name + "-" + app_version + "-" + jar_suffix + ".jar";
+ def jar_file_name = app_name + "-" + app_version + ".jar";
def jar_file_path = app_path + '/lib/' + jar_file_name;
+ def fat_jar_file_name = app_name + "-" + app_version + "-" + jar_suffix + ".jar";
+ def fat_jar_file_path = app_path + '/lib/' + fat_jar_file_name;
def main_class = project.mainClass
def sys_bin ='/usr/local/bin/'
def sys_lib ='/usr/local/lib/'
def bin_file_name = "${app_name}-${app_version}"
- def java_file_name = main_class + ".java"
+ def java_file_name = main_class + ".java"
project.tasks.register("rpm", Rpm) {
doFirst {
@@ -104,6 +108,7 @@ subprojects {
}
}
requires 'pshell-workbench'
+ dependsOn 'jar'
release = app_release
version = app_version
@@ -131,12 +136,19 @@ subprojects {
into app_path
- from ('src/main/java') {
- //print(java_file_name )
- include java_file_name
- into 'lib'
- fileMode 0644
- }
+ if (deploy_type=='java'){
+ from ('src/main/java') {
+ include java_file_name
+ into 'lib'
+ fileMode 0644
+ }
+ } else if (deploy_type=='jar'){
+ from ('build/libs') {
+ include jar_file_name
+ into 'lib'
+ fileMode 0644
+ }
+ }
from('scripts') {
into 'bin'
@@ -148,6 +160,7 @@ subprojects {
"app_name": app_name,
"app_version": app_version,
"jar_file": jar_file_path,
+ "fat_jar_file": fat_jar_file_path,
"java_file": app_path + '/lib/' + main_class + ".java",
"ex_options" :ex_options
])
diff --git a/correlation/bin/correlation b/correlation/bin/correlation
new file mode 100755
index 0000000..7cb7643
--- /dev/null
+++ b/correlation/bin/correlation
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+MY_PATH=$(dirname "$0")
+export PKG=${MY_PATH}/..
+
+#Check if running as e-account
+for i in "$@"
+do
+case $i in
+
+ -pkg=*)
+ export PKG="${i#*=}"
+ ;;
+
+ *) # unknown option
+ ;;
+esac
+done
+
+/opt/gfa/pshell/pshell \
+ -version=default \
+ -py3 \
+ -m=${PKG} \
+ -z \
+ -nbcf=true \
+ -laf=dark \
+ -d \
+ -pini=true \
+ -clog=WARNING \
+ -sbar \
+ $@
diff --git a/correlation/bin/correlation_editor b/correlation/bin/correlation_editor
new file mode 100755
index 0000000..b1e7a4e
--- /dev/null
+++ b/correlation/bin/correlation_editor
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+MY_PATH=$(dirname "$0")
+export PKG=${MY_PATH}/..
+
+#Check if running as e-account
+for i in "$@"
+do
+case $i in
+
+ -pkg=*)
+ export PKG="${i#*=}"
+ ;;
+
+ *) # unknown option
+ ;;
+esac
+done
+
+
+/opt/gfa/pshell/pshell \
+ -version=default \
+ -z \
+ -py3 \
+ -nbcf=true \
+ -laf=dark \
+ -pini=true \
+ -plgp=${PKG}/plugins \
+ -scpt=${PKG}/script \
+ -devp=${PKG}/devices \
+ $@
diff --git a/correlation/build.gradle b/correlation/build.gradle
new file mode 100644
index 0000000..c78565a
--- /dev/null
+++ b/correlation/build.gradle
@@ -0,0 +1,11 @@
+description = 'correlation'
+ext.mainClass = hasProperty('mainClass') ? mainClass : 'ch.psi.pshell.workbench.App'
+ext.title = 'Correlation'
+ext.desc = 'Correlation'
+ext.deploy_type= 'pkg'
+
+dependencies {
+ implementation 'ch.psi:pshell-workbench:' + version
+ }
+
+createDefaultTasks(project)
diff --git a/correlation/config/devices.properties b/correlation/config/devices.properties
new file mode 100755
index 0000000..b0992e6
--- /dev/null
+++ b/correlation/config/devices.properties
@@ -0,0 +1,2 @@
+dispatcher=ch.psi.pshell.bs.Dispatcher|https://dispatcher-api.psi.ch/sf|||
+cam_server=ch.psi.pshell.bs.PipelineServer|sf-daqsync-01:8889|||
diff --git a/correlation/config/jcae.properties b/correlation/config/jcae.properties
new file mode 100755
index 0000000..3c929d9
--- /dev/null
+++ b/correlation/config/jcae.properties
@@ -0,0 +1,12 @@
+#Mon Feb 22 20:35:07 CET 2021
+ch.psi.jcae.ContextFactory.addressList=
+ch.psi.jcae.ContextFactory.serverPort=
+ch.psi.jcae.ContextFactory.maxArrayBytes=50000000
+ch.psi.jcae.ChannelFactory.retries=1
+ch.psi.jcae.ChannelFactory.timeout=1000
+ch.psi.jcae.impl.DefaultChannelService.retries=1
+ch.psi.jcae.impl.DefaultChannelService.timeout=1000
+ch.psi.jcae.ContextFactory.autoAddressList=true
+ch.psi.jcae.ContextFactory.useShellVariables=true
+ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false
+ch.psi.jcae.ContextFactory.maxSendArrayBytes=1000000
diff --git a/correlation/devices/cam_server.properties b/correlation/devices/cam_server.properties
new file mode 100755
index 0000000..f49f624
--- /dev/null
+++ b/correlation/devices/cam_server.properties
@@ -0,0 +1,25 @@
+#Mon Aug 21 16:04:52 CEST 2023
+spatialCalOffsetY=-26.131980971800004
+spatialCalOffsetX=-40.21857787259174
+colormapLogarithmic=false
+scale=1.0
+grayscale=false
+spatialCalScaleX=-13.784314431779372
+spatialCalScaleY=-13.784313995826063
+colormapMax=255.0
+rescaleOffset=0.0
+roiWidth=-1
+colormap=Temperature
+invert=false
+colormapMin=0.0
+rotationCrop=false
+rotation=0.0
+rescaleFactor=1.0
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+flipHorizontally=false
+colormapAutomatic=true
+roiY=0
+roiX=0
+transpose=false
diff --git a/correlation/devices/dispatcher.properties b/correlation/devices/dispatcher.properties
new file mode 100755
index 0000000..db3e719
--- /dev/null
+++ b/correlation/devices/dispatcher.properties
@@ -0,0 +1,14 @@
+#Wed May 31 12:25:22 CEST 2023
+byteBufferAllocator=false
+disableCompression=false
+dropIncomplete=false
+headerReservingAllocator=false
+keepListeningOnStop=false
+mappingIncomplete=fill_null
+parallelHandlerProcessing=true
+sendAwaitFirstMessage=false
+sendBuildChannelConfig=at_startup
+sendStrategy=complete_all
+sendSyncTimeout=0
+socketType=DEFAULT
+validationInconsistency=keep_as_is
diff --git a/correlation/plugins/Correlation.form b/correlation/plugins/Correlation.form
new file mode 100644
index 0000000..6402672
--- /dev/null
+++ b/correlation/plugins/Correlation.form
@@ -0,0 +1,331 @@
+
+
+
diff --git a/correlation/plugins/Correlation.java b/correlation/plugins/Correlation.java
new file mode 100644
index 0000000..d7234bc
--- /dev/null
+++ b/correlation/plugins/Correlation.java
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
+ */
+
+import ch.psi.pshell.plot.Plot;
+import ch.psi.pshell.swing.ChannelSelector;
+import ch.psi.pshell.ui.App;
+import ch.psi.pshell.ui.Panel;
+import ch.psi.utils.State;
+import ch.psi.utils.Chrono;
+import ch.psi.utils.swing.SwingUtils;
+import ch.psi.utils.swing.SwingUtils.OptionResult;
+import ch.psi.utils.swing.SwingUtils.OptionType;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.HashMap;
+import java.util.List;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+/**
+ *
+ */
+public class Correlation extends Panel {
+
+ public Correlation() {
+ initComponents();
+ this.setPersistedComponents(new Component[]{textDevX, textDevY, spinnerInterval, spinnerWindow, comboTypeX, comboTypeY});
+ plot.getAxis(Plot.AxisId.X).setLabel(null);
+ plot.getAxis(Plot.AxisId.Y).setLabel(null);
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ if (runCount==0){
+ super.onInitialize(runCount);
+ if (App.hasArgument("dx")) {
+ textDevX.setText(App.getArgumentValue("dx"));
+ }
+ if (App.hasArgument("dy")) {
+ textDevY.setText(App.getArgumentValue("dy"));
+ }
+ try{
+ if (App.hasArgument("dxtype")) {
+ comboTypeX.setSelectedIndex(Integer.valueOf(App.getArgumentValue("dxtype")));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("dytype")) {
+ comboTypeY.setSelectedIndex(Integer.valueOf(App.getArgumentValue("dytype")));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("interval")) {
+ spinnerInterval.setValue(Double.valueOf(App.getArgumentValue("interval")));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("window")) {
+ spinnerWindow.setValue(Integer.valueOf(App.getArgumentValue("window")));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("align")) {
+ checkAlign.setSelected(App.getBoolArgumentValue("align"));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("linear")) {
+ checkLinear.setSelected(App.getBoolArgumentValue("linear"));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ try{
+ if (App.hasArgument("quadratic")) {
+ checkQuadratic.setSelected(App.getBoolArgumentValue("quadratic"));
+ }
+ } catch (Exception ex){
+ System.err.println(ex.getMessage());
+ }
+ }
+ this.startTimer(100, 10);
+ comboTypeXActionPerformed(null);
+ comboTypeYActionPerformed(null);
+ }
+
+ @Override
+ protected void onTimer(){
+ if (isRunning()){
+ updateResults();
+ }
+ }
+
+ //DecimalFormat formatter = new DecimalFormat("0.##E0");
+ void updateResults(){
+ try{
+ textCorrelation.setText(String.format("%1.4f", Double.valueOf((Double)getContext().getInterpreterVariable("corr"))));
+ } catch (Exception ex){
+ textCorrelation.setText("");
+ }
+
+ if (checkLinear.isSelected()){
+ try{
+ List pars = (List)getContext().getInterpreterVariable("pars_lin");
+ //textLinear.setText(String.format("%1.3fx%+1.3f", (Double)(pars.get(1)), (Double)(pars.get(0))));
+ textLinear.setText(String.format("%1.6gx%+1.6g",pars.get(1), pars.get(0)));
+ } catch (Exception ex){
+ textLinear.setText("");
+ }
+ }
+
+ if (checkQuadratic.isSelected()){
+ try{
+ List pars = (List)getContext().getInterpreterVariable("pars_quad");
+ //textQuadratic.setText(String.format("%1.2fx\u00B2 %+1.2fx%+1.2f", (Double)(pars.get(0)), (Double)(pars.get(1)), (Double)(pars.get(0))));
+ textQuadratic.setText(String.format("%1.3gx\u00B2%+1.3gx%+1.3g", pars.get(0), pars.get(1), pars.get(0)));
+ //textQuadratic.setText(formatter.format(pars.get(2))+ formatter.format(pars.get(1)) + formatter.format(pars.get(0)));
+
+ } catch (Exception ex){
+ textQuadratic.setText("");
+ }
+ try{
+ String peak = (String)getContext().getInterpreterVariable("pos_peak");
+ if (peak!=null){
+ textPeak.setText(peak + " (max)");
+ } else {
+ peak = (String)getContext().getInterpreterVariable("neg_peak");
+ if (peak!=null){
+ textPeak.setText(peak + " (min)");
+ } else {
+ textPeak.setText("");
+ }
+ }
+
+ } catch (Exception ex){
+ textPeak.setText("");
+ }
+ }
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ buttonStart.setEnabled((state==State.Ready) || (state==State.Busy));
+ if (isRunning()){
+ if (state==State.Ready){
+ buttonStart.setText("Start");
+ }
+ } else {
+ if (state==State.Busy){
+ buttonStart.setText("Stop");
+ buttonElog.setEnabled(true);
+ }
+ }
+ textDevX.setEnabled(state==State.Ready);
+ textDevY.setEnabled(state==State.Ready);
+ spinnerInterval.setEnabled(state==State.Ready);
+ spinnerWindow.setEnabled(state==State.Ready);
+ comboTypeX.setEnabled(state==State.Ready);
+ comboTypeY.setEnabled(state==State.Ready);
+ checkLinear.setEnabled(state==State.Ready);
+ checkQuadratic.setEnabled(state==State.Ready);
+
+ if ((former==State.Initializing) && (state == State.Ready)){
+ if (App.hasArgument("start")) {
+ buttonStartActionPerformed(null);
+ }
+ }
+
+ }
+
+ boolean isRunning(){
+ return buttonStart.getText().equals("Stop");
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ void elog(String logbook, String title, String message, String[] attachments) throws Exception {
+ String domain = "";
+ String category = "Info";
+ String entry = "";
+ StringBuffer cmd = new StringBuffer();
+
+ cmd.append("G_CS_ELOG_add -l \"").append(logbook).append("\" ");
+ cmd.append("-a \"Author=ScreenPanel\" ");
+ cmd.append("-a \"Type=pshell\" ");
+ cmd.append("-a \"Entry=").append(entry).append("\" ");
+ cmd.append("-a \"Title=").append(title).append("\" ");
+ cmd.append("-a \"Category=").append(category).append("\" ");
+ cmd.append("-a \"Domain=").append(domain).append("\" ");
+ for (String attachment : attachments) {
+ cmd.append("-f \"").append(attachment).append("\" ");
+ }
+ cmd.append("-n 1 ");
+ cmd.append("\"").append(message).append("\" ");
+ System.out.println(cmd.toString());
+
+ final Process process = Runtime.getRuntime().exec(new String[]{"bash", "-c", cmd.toString()});
+ new Thread(() -> {
+ try {
+ process.waitFor();
+ int bytes = process.getInputStream().available();
+ byte[] arr = new byte[bytes];
+ process.getInputStream().read(arr, 0, bytes);
+ System.out.println(new String(arr));
+ bytes = process.getErrorStream().available();
+ arr = new byte[bytes];
+ process.getErrorStream().read(arr, 0, bytes);
+ System.err.println(new String(arr));
+ } catch (Exception ex) {
+ System.err.println(ex);
+ }
+ }).start();
+ }
+
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ plot = new ch.psi.pshell.plot.LinePlotJFree();
+ jPanel1 = new javax.swing.JPanel();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel2 = new javax.swing.JLabel();
+ jLabel3 = new javax.swing.JLabel();
+ spinnerInterval = new javax.swing.JSpinner();
+ jLabel4 = new javax.swing.JLabel();
+ spinnerWindow = new javax.swing.JSpinner();
+ buttonStart = new javax.swing.JButton();
+ jLabel5 = new javax.swing.JLabel();
+ textCorrelation = new javax.swing.JTextField();
+ jLabel6 = new javax.swing.JLabel();
+ textLinear = new javax.swing.JTextField();
+ jLabel7 = new javax.swing.JLabel();
+ textQuadratic = new javax.swing.JTextField();
+ checkLinear = new javax.swing.JCheckBox();
+ checkQuadratic = new javax.swing.JCheckBox();
+ comboTypeX = new javax.swing.JComboBox();
+ comboTypeY = new javax.swing.JComboBox();
+ textDevX = new ch.psi.pshell.swing.ChannelSelector();
+ textDevY = new ch.psi.pshell.swing.ChannelSelector();
+ buttonElog = new javax.swing.JButton();
+ jLabel8 = new javax.swing.JLabel();
+ textPeak = new javax.swing.JTextField();
+ checkAlign = new javax.swing.JCheckBox();
+
+ plot.setTitle("");
+
+ jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel1.setText("X device:");
+
+ jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel2.setText("Y device:");
+
+ jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel3.setText("Interval (s):");
+
+ spinnerInterval.setModel(new javax.swing.SpinnerNumberModel(0.1d, 0.001d, null, 1.0d));
+
+ jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel4.setText("Window size:");
+
+ spinnerWindow.setModel(new javax.swing.SpinnerNumberModel(50, 3, null, 1));
+
+ buttonStart.setText("Start");
+ buttonStart.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStartActionPerformed(evt);
+ }
+ });
+
+ jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ jLabel5.setText("Correlation:");
+
+ textCorrelation.setEditable(false);
+ textCorrelation.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+
+ jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ jLabel6.setText("Liner fit:");
+
+ textLinear.setEditable(false);
+ textLinear.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+
+ jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ jLabel7.setText("Quadratric fit:");
+
+ textQuadratic.setEditable(false);
+ textQuadratic.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+
+ checkLinear.setSelected(true);
+ checkLinear.setText("Linear fit");
+
+ checkQuadratic.setText("Quadratic fit");
+
+ comboTypeX.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Channel", "Stream", "Camera" }));
+ comboTypeX.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ comboTypeXActionPerformed(evt);
+ }
+ });
+
+ comboTypeY.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Channel", "Stream", "Camera" }));
+ comboTypeY.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ comboTypeYActionPerformed(evt);
+ }
+ });
+
+ textDevX.setHistorySize(20);
+ textDevX.setName("Correlation_textDevX"); // NOI18N
+
+ textDevY.setHistorySize(20);
+ textDevY.setName("Correlation_textDevY"); // NOI18N
+
+ buttonElog.setText("ELOG");
+ buttonElog.setEnabled(false);
+ buttonElog.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonElogActionPerformed(evt);
+ }
+ });
+
+ jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
+ jLabel8.setText("Peak:");
+
+ textPeak.setEditable(false);
+ textPeak.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+
+ checkAlign.setText("Align Camera Streams");
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel8, javax.swing.GroupLayout.Alignment.TRAILING))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(checkAlign)
+ .addComponent(comboTypeY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(comboTypeX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(textCorrelation, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
+ .addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(spinnerWindow, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(textLinear, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
+ .addComponent(checkLinear)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addComponent(textPeak, javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(textQuadratic, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)))
+ .addGap(0, 70, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(textDevX, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
+ .addComponent(checkQuadratic)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonElog))
+ .addComponent(textDevY, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())))
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonStart, javax.swing.GroupLayout.PREFERRED_SIZE, 189, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, Short.MAX_VALUE))
+ );
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3, jLabel4});
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerInterval, spinnerWindow});
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel5, jLabel6, jLabel7});
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {textCorrelation, textLinear, textQuadratic});
+
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1)
+ .addComponent(textDevX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(comboTypeX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel2)
+ .addComponent(textDevY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(5, 5, 5)
+ .addComponent(comboTypeY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel4)
+ .addComponent(spinnerWindow, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(checkAlign)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(checkLinear)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(checkQuadratic)
+ .addComponent(buttonElog))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(textCorrelation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel5))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(jLabel6)
+ .addComponent(textLinear, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(jLabel7)
+ .addComponent(textQuadratic, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(jLabel8)
+ .addComponent(textPeak, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(18, 18, Short.MAX_VALUE)
+ .addComponent(buttonStart)
+ .addGap(33, 33, 33))
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addContainerGap())))
+ );
+ }// //GEN-END:initComponents
+
+ private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed
+ try {
+ if (isRunning()){
+ //abort();
+ //Stooping smootly so displayed variables get updated.
+ getContext().setInterpreterVariable("stop_exec", true);
+ Chrono chrono = new Chrono();
+ while (!chrono.isTimeout(500)){
+ if (!Boolean.TRUE.equals(getContext().getInterpreterVariable("stop_exec"))){
+ break;
+ }
+ Thread.sleep(1);
+ }
+ if (Boolean.TRUE.equals(getContext().getInterpreterVariable("stop_exec"))){
+ System.out.println("Timeout stopping script - aborting...");
+ abort();
+ }
+ updateResults();
+ //buttonStart.setText("Start");
+ } else {
+ textCorrelation.setText("");
+ textLinear.setText("");
+ textQuadratic.setText("");
+ textPeak.setText("");
+ HashMap args = new HashMap();
+ args.put("dx", textDevX.getText());
+ args.put("dy", textDevY.getText());
+ args.put("interval", spinnerInterval.getValue());
+ args.put("window", spinnerWindow.getValue());
+ args.put("dxtype", comboTypeX.getSelectedIndex());
+ args.put("dytype", comboTypeY.getSelectedIndex());
+ args.put("linear_fit", checkLinear.isSelected());
+ args.put("quadratic_fit", checkQuadratic.isSelected());
+ args.put("merge_camera_stream", checkAlign.isSelected());
+
+ args.put("p", plot);
+ runAsync("correlation", args).handle((ok, ex) -> {
+ if (ex != null) {
+ ex.printStackTrace();
+ }
+ return ok;
+ });
+ ///buttonStart.setText("Stop");
+ }
+
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStartActionPerformed
+
+ private void comboTypeXActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboTypeXActionPerformed
+ if (comboTypeX.getSelectedIndex()==0){
+ //textDevX.configure(ChannelSelector.Type.Epics, "http://epics-boot-info.psi.ch", "swissfel", 5000);
+ textDevX.configure(ChannelSelector.Type.IocInfo,"http://iocinfo.psi.ch/api/v2", "swissfel", 5000);
+ } else if (comboTypeX.getSelectedIndex()==1){
+ textDevX.configure(ChannelSelector.Type.DataAPI, "https://data-api.psi.ch/sf", "sf-databuffer", 5000);
+ } else if (comboTypeX.getSelectedIndex()==2){
+ textDevX.configure(ChannelSelector.Type.Camera, "sf-daqsync-01:8889", null, 5000);
+ }
+ }//GEN-LAST:event_comboTypeXActionPerformed
+
+ private void comboTypeYActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboTypeYActionPerformed
+ if (comboTypeY.getSelectedIndex()==0){
+ textDevY.configure(ChannelSelector.Type.IocInfo,"http://iocinfo.psi.ch/api/v2", "swissfel", 5000);
+ } else if (comboTypeY.getSelectedIndex()==1){
+ textDevY.configure(ChannelSelector.Type.DataAPI, "https://data-api.psi.ch/sf", "sf-databuffer", 5000);
+ } else if (comboTypeY.getSelectedIndex()==2){
+ textDevY.configure(ChannelSelector.Type.Camera, "sf-daqsync-01:8889", null, 5000);
+ }
+ }//GEN-LAST:event_comboTypeYActionPerformed
+
+ private void buttonElogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonElogActionPerformed
+ try{
+ String snapshotFile = getContext().getSetup().expandPath("{context}/correlation_plot.png");
+ plot.saveSnapshot(snapshotFile, "png");
+ JPanel panel = new JPanel();
+ GridBagLayout layout = new GridBagLayout();
+ layout.columnWidths = new int[]{0, 180}; //Minimum width
+ layout.rowHeights = new int[]{30, 30, 30}; //Minimum height
+ panel.setLayout(layout);
+ JComboBox comboLogbook = new JComboBox(new String[]{"SwissFEL commissioning data", "SwissFEL commissioning"});
+ JTextField textComment = new JTextField();
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ panel.add(new JLabel("Logbook:"), c);
+ c.gridy = 1;
+ panel.add(new JLabel("Comment:"), c);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridx = 1;
+ panel.add(textComment, c);
+ c.gridy = 0;
+ panel.add(comboLogbook, c);
+
+ if (SwingUtils.showOption(getTopLevel(), "ELOG", panel, OptionType.OkCancel) == OptionResult.Yes) {
+ StringBuilder message = new StringBuilder();
+ message.append("Device X: ").append(String.valueOf(textDevX.getText())).append("\n");
+ message.append("Device Y: ").append(String.valueOf(textDevY.getText())).append("\n");
+ message.append("Interval: ").append(String.valueOf(spinnerInterval.getValue())).append("\n");
+ message.append("Samples: ").append(String.valueOf(spinnerWindow.getValue())).append("\n");
+ message.append("Correlation: ").append(textCorrelation.getText()).append("\n");
+ message.append("Linear fit: ").append(textLinear.getText()).append("\n");
+ message.append("Quadratic fit: ").append(textQuadratic.getText()).append("\n");
+ message.append("Peak: ").append(textPeak.getText()).append("\n");
+ message.append("Comment: ").append(textComment.getText()).append("\n");
+ elog((String) comboLogbook.getSelectedItem(), "Correlation Panel Snapshot", message.toString(), new String[]{snapshotFile});
+ }
+ }catch (Exception ex){
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonElogActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonElog;
+ private javax.swing.JButton buttonStart;
+ private javax.swing.JCheckBox checkAlign;
+ private javax.swing.JCheckBox checkLinear;
+ private javax.swing.JCheckBox checkQuadratic;
+ private javax.swing.JComboBox comboTypeX;
+ private javax.swing.JComboBox comboTypeY;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel4;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JLabel jLabel6;
+ private javax.swing.JLabel jLabel7;
+ private javax.swing.JLabel jLabel8;
+ private javax.swing.JPanel jPanel1;
+ private ch.psi.pshell.plot.LinePlotJFree plot;
+ private javax.swing.JSpinner spinnerInterval;
+ private javax.swing.JSpinner spinnerWindow;
+ private javax.swing.JTextField textCorrelation;
+ private ch.psi.pshell.swing.ChannelSelector textDevX;
+ private ch.psi.pshell.swing.ChannelSelector textDevY;
+ private javax.swing.JTextField textLinear;
+ private javax.swing.JTextField textPeak;
+ private javax.swing.JTextField textQuadratic;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/correlation/script/correlation.py b/correlation/script/correlation.py
new file mode 100755
index 0000000..9614189
--- /dev/null
+++ b/correlation/script/correlation.py
@@ -0,0 +1,252 @@
+import math
+import sys, traceback
+from mathutils import fit_polynomial, PolynomialFunction, calculate_peaks
+from plotutils import plot_line, plot_function
+from ch.psi.pshell.swing.Shell import getColorStdout
+import org.apache.commons.math3.stat.correlation.PearsonsCorrelation as PearsonsCorrelation
+try:
+ import ch.psi.pshell.bs.StreamMerger as StreamMerger
+except:
+ merge_camera_stream = False
+
+TYPE_CHANNEL = 0
+TYPE_STREAM = 1
+TYPE_CAMERA= 2
+
+INVOKE_PLOT_UPDATES = True
+
+if get_exec_pars().source == CommandSource.ui:
+ #dx = "SINEG01-DICT215:B1_CHARGE" ; dxtype = TYPE_CHANNEL
+ dx=get_beam_ok_channel(1) ; dxtype = TYPE_STREAM
+ #dx = "SLG-LCAM-C042 x_rms" ; dxtype = TYPE_CAMERA
+
+ #dy = "SINDI01-RLLE-STA:SLAVE1-DLTIMER" ; dytype = TYPE_CHANNEL
+ dy = "SATES31-CAMS187-RIXS1_sp intensity" ; dytype = TYPE_CAMERA
+ #dy=get_beam_ok_channel(2) ; dytype = TYPE_STREAM
+
+ interval = 0.01
+ window = 40
+ p = plot(None)[0]
+ linear_fit = True
+ quadratic_fit = True
+ merge_camera_stream = True
+print dx, dxtype
+print dy, dytype
+
+corr = None
+pars_lin = None
+pars_quad = None
+pos_peak = None
+neg_peak = None
+stop_exec = None
+
+
+bs = TYPE_STREAM in [dxtype, dytype]
+
+for s in p.getAllSeries():
+ p.removeSeries(s)
+
+_stream = None
+_camname = None
+
+instances = []
+
+def _get_device(d, type):
+ global _stream, _camname
+ egu = None
+ if isinstance(d, basestring):
+ name = d.strip()
+ d = None
+ try:
+ d = get_device(name)
+ if d is None:
+ d = eval(name)
+ #print name
+ if d is not None:
+ if not isinstance(r, Device):
+ d = None
+ else:
+ try:
+ egu = d.unit
+ except:
+ pass
+ except:
+ pass
+ if d is None:
+ offset = 0
+ if type==TYPE_STREAM:
+ if " " in name:
+ tokens = name.split(" ")
+ name = tokens[0]
+ offset = int(tokens[1])
+ if _stream == None:
+ _stream = Stream("corr_stream", dispatcher)
+ instances.append(_stream)
+ #d = _stream.addScalar(name, name, int(interval*100), offset)
+ _stream.addScalar(name, name, int(interval*100), offset)
+ d=name
+ elif type==TYPE_CHANNEL:
+ d = Channel(name)
+ d.set_monitored(True)
+ elif type==TYPE_CAMERA:
+ tokens = name.split(" ")
+ _camname = tokens[0]
+ field = tokens[1]
+ return field, ""
+ else:
+ raise Exception("Invalid type: " + str(type))
+ if not isinstance(d, basestring):
+ instances.append(d)
+ try:
+ if type==TYPE_CHANNEL:
+ egu = caget(name+".EGU",'s')
+ except:
+ pass
+ else:
+ try:
+ egu = d.unit
+ except:
+ pass
+ return d, egu
+
+dx, egux = _get_device(dx, dxtype)
+dy, eguy = _get_device(dy, dytype)
+
+p.getAxis(p.AxisId.X).setLabel(egux)
+p.getAxis(p.AxisId.Y).setLabel(eguy)
+
+merge = False
+try:
+ if _stream != None:
+ _stream.initialize()
+ _stream.start(True)
+ if _camname != None:
+ shared = _camname.endswith("_sp")
+ print "Camera: " , _camname, " shared: ", shared
+ cam_server.start(_camname, shared )
+
+ cam_server.stream.waitCacheChange(10000);
+ _camera_stream = cam_server.stream
+
+ if merge_camera_stream:
+ merge = ((dxtype==TYPE_CAMERA) and (dytype == TYPE_STREAM)) or ((dxtype==TYPE_STREAM) and (dytype == TYPE_CAMERA))
+ if merge:
+ print "Merging dispatcher and camera streams"
+ _merger = StreamMerger("stream", _stream, cam_server.stream)
+ _merger.monitored=True
+ _merger.start()
+ _camera_stream.setBufferCapacity(500)
+ _stream.setBufferCapacity(500)
+ instances.append(_merger)
+ _merger.waitCacheChange(5000)
+ #print _merger.readables
+ _camera_stream=_merger
+ _stream = _merger
+
+ if dxtype==TYPE_CAMERA:
+ dx=_camera_stream.getChild(dx)
+ if dytype==TYPE_CAMERA:
+ dy=_camera_stream.getChild(dy)
+
+ if dxtype==TYPE_STREAM:
+ dx=_stream.getChild(dx)
+ if dytype==TYPE_STREAM:
+ dy=_stream.getChild(dy)
+
+ p.addSeries(LinePlotSeries("Data"))
+ sd=p.getSeries(0)
+ sd.setLinesVisible(False)
+ sd.setPointSize(4)
+
+ if get_exec_pars().source == CommandSource.ui:
+ if globals().has_key("marker"):
+ p.removeMarker(marker)
+ if globals().has_key("peak_marker"):
+ p.removeMarker(peak_marker)
+ marker=None
+ peak_marker=None
+
+ while(True):
+ #Sample and plot data
+ if bs == True:
+ _stream.waitCacheChange(10000)
+ #bsdata = list(_stream.take().values())
+ x=dx.read()
+ y=dy.read()
+
+ def update():
+ global marker, peak_marker, corr, pars_lin, pars_quad, pos_peak, neg_peak, stop_exec
+ sd.appendData(x, y)
+ if len(sd.x) > window:
+ #Remove First Element
+ sd.token.remove(0)
+ ax = sd.x
+ ay = sd.y
+ if len(ax)>2:
+ x1, x2 = min(ax), max(ax)
+ res = (x2-x1)/100
+ if x1!=x2:
+ #Display correlation
+ corr= PearsonsCorrelation().correlation(to_array(ax,'d'), to_array(ay,'d'))
+ s = "Correlation=" + str(round(corr,4))
+ #print s
+ if get_exec_pars().source == CommandSource.ui:
+ if marker is not None:
+ p.removeMarker(marker)
+ marker = p.addMarker(x2+res, p.AxisId.X, s, p.getBackground())
+ marker.setLabelPaint(getColorStdout())
+ if linear_fit:
+ #Calculate, print and plot linear fit
+ pars_lin = (a0,a1) = fit_polynomial(ay, ax, 1)
+ #print "Fit lin a1:" , a1, " a0:",a0
+ y1 = poly(x1, pars_lin)
+ y2 = poly(x2, pars_lin)
+ plot_line(p, x1, y1, x2, y2, width = 2, color = Color.BLUE, name = "Fit Linear")
+ if quadratic_fit:
+ #Calculate, print and plot quadratic fit
+ pars_quad = (a0,a1,a2) = fit_polynomial(ay, ax, 2)
+ #print "Fit quad a2:" , a2, "a1:" , a1, " a0:",a0
+ fitted_quad_function = PolynomialFunction(pars_quad)
+ ax = frange(x1, x2, res, True)
+ plot_function(p, fitted_quad_function, "Fit Quadratic", ax, color=Color.GREEN)
+
+ peak = None
+ peaks = calculate_peaks(fitted_quad_function, x1, x2, positive=True)
+ if len(peaks)>0:
+ peak = peaks[0]
+ pos_peak = str(round(peak,4))
+ peak_str = "Positive peak: " + pos_peak
+ else:
+ peaks = calculate_peaks(fitted_quad_function, x1, x2, positive=False)
+ if len(peaks)>0:
+ peak = peaks[0]
+ neg_peak = str(round(peak,4))
+ peak_str = "Negative peak: " + neg_peak
+ else:
+ pos_peak = neg_peak = None
+ if get_exec_pars().source == CommandSource.ui:
+ if peak_marker is not None:
+ p.removeMarker(peak_marker)
+ if peak is not None:
+ peak_marker = p.addMarker(peak, p.AxisId.X, peak_str, Color(0,128,0))
+ if INVOKE_PLOT_UPDATES:
+ invoke(update, False)
+ else:
+ update()
+
+ if stop_exec == True:
+ stop_exec = False
+ break
+ if bs != True:
+ time.sleep(interval)
+except KeyboardInterrupt:
+ pass
+finally:
+ for dev in instances:
+ try:
+ dev.close()
+ except:
+ pass
+ if _camname != None:
+ cam_server.stop()
+
diff --git a/persplot/build.gradle b/persplot/build.gradle
new file mode 100644
index 0000000..3203913
--- /dev/null
+++ b/persplot/build.gradle
@@ -0,0 +1,10 @@
+description = 'persplot'
+ext.mainClass = hasProperty('mainClass') ? mainClass : 'ch.psi.pshell.workbench.App'
+ext.title = 'PersPlot'
+ext.desc = 'PersPlot'
+
+dependencies {
+ implementation 'ch.psi:pshell-workbench:' + version
+ }
+
+createDefaultTasks(project)
\ No newline at end of file
diff --git a/persplot/gradle.properties b/persplot/gradle.properties
new file mode 100644
index 0000000..2d1f6ef
--- /dev/null
+++ b/persplot/gradle.properties
@@ -0,0 +1 @@
+action.debug.args=debug --args="-b -d -l -k -n -q -console_log=SEVERE -p PersistencePlot -laf=dark -epics_config ch.psi.jcae.ContextFactory.addressList=localhost:54321"
diff --git a/persplot/persplot b/persplot/persplot
new file mode 100755
index 0000000..dca670a
--- /dev/null
+++ b/persplot/persplot
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+
+/opt/gfa/pshell/pshell \
+ -z -sbar -clog=INFO -d -q -n \
+ -p=/opt/gfa/pshell/apps/persplot/PersistencePlot.java \
+ -laf=dark \
+ -last \
+ ${1+"$@"}
+
+~
diff --git a/persplot/scripts/app_startup b/persplot/scripts/app_startup
new file mode 100644
index 0000000..7985300
--- /dev/null
+++ b/persplot/scripts/app_startup
@@ -0,0 +1,6 @@
+#!/bin/sh
+APP_ARGS_NAME=\$(echo "APP_${app_name}" | tr '[:lower:]' '[:upper:]')_ARGS
+APP_ARGS_NAME=\${APP_ARGS_NAME//-/_}
+
+# Run the JAR with all passed arguments
+exec pshell-workbench -b -d -l -k -n -q -console_log=SEVERE -p ${java_file} \${!APP_ARGS_NAME} "\$@"
diff --git a/persplot/src/main/java/PersistencePlot.form b/persplot/src/main/java/PersistencePlot.form
new file mode 100644
index 0000000..925caa6
--- /dev/null
+++ b/persplot/src/main/java/PersistencePlot.form
@@ -0,0 +1,82 @@
+
+
+
diff --git a/persplot/src/main/java/PersistencePlot.java b/persplot/src/main/java/PersistencePlot.java
new file mode 100644
index 0000000..8f045dc
--- /dev/null
+++ b/persplot/src/main/java/PersistencePlot.java
@@ -0,0 +1,279 @@
+import ch.psi.pshell.device.Device;
+import ch.psi.pshell.device.DeviceListener;
+import static ch.psi.pshell.device.Record.SIZE_VALID;
+import static ch.psi.pshell.device.Record.UNDEFINED_PRECISION;
+import ch.psi.pshell.epics.ChannelDoubleArray;
+import ch.psi.pshell.framework.App;
+import ch.psi.pshell.framework.Panel;
+import ch.psi.pshell.plot.LinePlotSeries;
+import ch.psi.pshell.plot.Plot;
+import ch.psi.pshell.swing.ChannelSelector;
+import ch.psi.pshell.utils.State;
+import java.awt.Color;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.SwingUtilities;
+
+/**
+ *
+ */
+public class PersistencePlot extends Panel{
+ ChannelDoubleArray channel;
+ LinePlotSeries series;
+ LinePlotSeries seriesMax;
+ LinePlotSeries seriesMin;
+ boolean started;
+ double[] max;
+ double[] min;
+ double[] last;
+ boolean permanent;
+
+
+ public PersistencePlot() {
+ initComponents();
+ plot.setTitle(null);
+ plot.getAxis(Plot.AxisId.X).setLabel(null);
+ plot.getAxis(Plot.AxisId.Y).setLabel(null);
+ plot.setLegendVisible(true);
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ channelSelector.configure(ChannelSelector.Type.Epics, "http://epics-boot-info.psi.ch", "sls", 3000);
+ if (App.hasArgument("channel")){
+ channelSelector.setText(App.getArgumentValue("channel"));
+ }
+ if (App.hasArgument("start")){
+ buttonStartActionPerformed(null);
+ }
+ startTimer(500);
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ updateButtons();
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ final Object lock = new Object();
+ volatile boolean updated;
+
+ @Override
+ protected void onTimer() {
+ if (started){
+ synchronized(lock){
+ if (updated){
+ series.setData(last);
+ seriesMax.setData(max);
+ seriesMin.setData(min);
+ if (permanent){
+ //LinePlotSeries series = new LinePlotSeries("", Color.RED.darker().darker());
+ //plot.addSeries(series);
+ //series.setPointsVisible(false);
+ }
+ updated = false;
+ }
+ }
+ }
+ }
+
+ void updateButtons(){
+ boolean initialized = getState().isInitialized();
+ buttonStart.setEnabled(initialized && !started);
+ buttonStop.setEnabled(initialized && started);
+ channelSelector.setEnabled(initialized && !started);
+ }
+
+ final DeviceListener deviceListener = new DeviceListener() {
+ @Override
+ public void onCacheChanged(Device device, Object value, Object former, long timestamp, boolean valueChange) {
+ try{
+ onData((double[]) value);
+ } catch (Exception ex){
+ Logger.getLogger(PersistencePlot.class.getName()).log(Level.WARNING, null, ex);
+ }
+ }
+ };
+
+ void onData(double[] data){
+ if (data.length!=last.length){
+ stop();
+ showMessage("Error", "Waveforme size changed: stopping plot");
+ }
+
+ synchronized(lock){
+ for (int i=0; i< data.length;i++){
+ double value = data[i];
+ if (value>max[i]){
+ max[i]=value;
+ }
+ if (value{
+ channel.close();
+ });
+ }
+ }
+ }
+ } finally{
+ started = false;
+ updateButtons();
+ }
+ }
+
+ void clear(){
+ try {
+ plot.clear();
+ } catch (Exception ex) {
+ Logger.getLogger(PersistencePlot.class.getName()).log(Level.WARNING, null, ex);
+ }
+ }
+
+
+
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ plot = new ch.psi.pshell.plot.LinePlotJFree();
+ channelSelector = new ch.psi.pshell.swing.ChannelSelector();
+ buttonStart = new javax.swing.JButton();
+ buttonStop = new javax.swing.JButton();
+ jLabel1 = new javax.swing.JLabel();
+
+ channelSelector.setHistorySize(20);
+ channelSelector.setName("Correlation_textDevX"); // NOI18N
+
+ buttonStart.setText("Start");
+ buttonStart.setEnabled(false);
+ buttonStart.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStartActionPerformed(evt);
+ }
+ });
+
+ buttonStop.setText("Stop");
+ buttonStop.setEnabled(false);
+ buttonStop.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStopActionPerformed(evt);
+ }
+ });
+
+ jLabel1.setText("Channel:");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(plot, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 508, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(channelSelector, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(18, 18, 18)
+ .addComponent(buttonStart)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonStop)
+ .addContainerGap())
+ );
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonStart, buttonStop});
+
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(jLabel1)
+ .addComponent(channelSelector, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(buttonStart)
+ .addComponent(buttonStop))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed
+ try{
+ //setChannel( "ALIRF-A1-KLYDCP10:REF-POWER");
+ start(channelSelector.getText());
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStartActionPerformed
+
+ private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed
+ try{
+ stop();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStopActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonStart;
+ private javax.swing.JButton buttonStop;
+ private ch.psi.pshell.swing.ChannelSelector channelSelector;
+ private javax.swing.JLabel jLabel1;
+ private ch.psi.pshell.plot.LinePlotJFree plot;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/psss-panel/assembly/bin/psss_panel b/psss-panel/assembly/bin/psss_panel
new file mode 100755
index 0000000..7cb7643
--- /dev/null
+++ b/psss-panel/assembly/bin/psss_panel
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+MY_PATH=$(dirname "$0")
+export PKG=${MY_PATH}/..
+
+#Check if running as e-account
+for i in "$@"
+do
+case $i in
+
+ -pkg=*)
+ export PKG="${i#*=}"
+ ;;
+
+ *) # unknown option
+ ;;
+esac
+done
+
+/opt/gfa/pshell/pshell \
+ -version=default \
+ -py3 \
+ -m=${PKG} \
+ -z \
+ -nbcf=true \
+ -laf=dark \
+ -d \
+ -pini=true \
+ -clog=WARNING \
+ -sbar \
+ $@
diff --git a/psss-panel/assembly/bin/psss_panel_editor b/psss-panel/assembly/bin/psss_panel_editor
new file mode 100755
index 0000000..ca5c5d9
--- /dev/null
+++ b/psss-panel/assembly/bin/psss_panel_editor
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+MY_PATH=$(dirname "$0")
+export PKG=${MY_PATH}/..
+
+#Check if running as e-account
+for i in "$@"
+do
+case $i in
+
+ -pkg=*)
+ export PKG="${i#*=}"
+ ;;
+
+ *) # unknown option
+ ;;
+esac
+done
+
+
+/opt/gfa/pshell/pshell \
+ -version=default \
+ -z \
+ -py3 \
+ -nbcf=true \
+ -laf=dark \
+ -pini=true \
+ -plgp=${PKG}/plugins \
+ -scpt=${PKG}/script \
+ -devp=${PKG}/devices \
+ -pool=${PKG}/config/devices.properties \
+ -p=Correlation.java \
+ $@
diff --git a/psss-panel/assembly/config/devices.properties b/psss-panel/assembly/config/devices.properties
new file mode 100755
index 0000000..1a9eafc
--- /dev/null
+++ b/psss-panel/assembly/config/devices.properties
@@ -0,0 +1,16 @@
+psss_fwhm_avg=ch.psi.pshell.epics.ChannelDouble|SARFE10-PSSS059:REL-E-SPREAD|||true
+dispatcher=ch.psi.pshell.bs.Dispatcher|https://dispatcher-api.psi.ch/sf|||
+cam_server=ch.psi.pshell.bs.PipelineServer|sf-daqsync-01:8889|||
+energy_machine=ch.psi.pshell.epics.ChannelDouble|SARFE10-PBPG050:ENERGY|||true
+psss_energy=ch.psi.pshell.epics.ChannelDouble|SARFE10-PSSS059:ENERGY|||true
+psss_spectrum_x=ch.psi.pshell.epics.ChannelDoubleArray|SARFE10-PSSS059:SPECTRUM_X -1 -3|||true
+psss_spectrum_y=ch.psi.pshell.epics.ChannelDoubleArray|SARFE10-PSSS059:SPECTRUM_Y -1 -3|||true
+psss_center=ch.psi.pshell.epics.ChannelDouble|SARFE10-PSSS059:SPECTRUM_CENTER|||true
+psss_fwhm=ch.psi.pshell.epics.ChannelDouble|SARFE10-PSSS059:SPECTRUM_FWHM|||true
+psss_roi_min=ch.psi.pshell.epics.ChannelInteger|SARFE10-PSSS059:SPC_ROI_YMIN|||true
+psss_roi_max=ch.psi.pshell.epics.ChannelInteger|SARFE10-PSSS059:SPC_ROI_YMAX|||true
+histo_center=ch.psi.pshell.device.HistogramGenerator|psss_center|||true
+histo_fwhm=ch.psi.pshell.device.HistogramGenerator|psss_fwhm|||true
+psss_spectrum_y_average=ch.psi.pshell.device.ArrayAverager|psss_spectrum_y|||true
+psss_center_average=ch.psi.pshell.device.Averager|psss_center|||true
+psss_fwhm_average=ch.psi.pshell.device.Averager|psss_fwhm|||true
diff --git a/psss-panel/assembly/config/jcae.properties b/psss-panel/assembly/config/jcae.properties
new file mode 100755
index 0000000..0e02d88
--- /dev/null
+++ b/psss-panel/assembly/config/jcae.properties
@@ -0,0 +1,12 @@
+#Mon Feb 22 20:35:07 CET 2021
+ch.psi.jcae.ContextFactory.addressList=
+ch.psi.jcae.ContextFactory.serverPort=
+ch.psi.jcae.ContextFactory.maxArrayBytes=50000000
+ch.psi.jcae.ChannelFactory.retries=1
+ch.psi.jcae.ChannelFactory.timeout=1250
+ch.psi.jcae.impl.DefaultChannelService.retries=4
+ch.psi.jcae.impl.DefaultChannelService.timeout=1000
+ch.psi.jcae.ContextFactory.autoAddressList=true
+ch.psi.jcae.ContextFactory.useShellVariables=true
+ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false
+ch.psi.jcae.ContextFactory.maxSendArrayBytes=1000000
diff --git a/psss-panel/assembly/devices/cam_server.properties b/psss-panel/assembly/devices/cam_server.properties
new file mode 100755
index 0000000..7f7cedb
--- /dev/null
+++ b/psss-panel/assembly/devices/cam_server.properties
@@ -0,0 +1,25 @@
+#Mon Jan 17 16:00:40 CET 2022
+spatialCalOffsetY=-50.02549719530852
+spatialCalOffsetX=-50.01953888237593
+colormapLogarithmic=false
+scale=1.0
+grayscale=false
+spatialCalScaleX=-1.0
+spatialCalScaleY=-1.0
+colormapMax=255.0
+rescaleOffset=0.0
+roiWidth=-1
+colormap=Temperature
+invert=false
+colormapMin=0.0
+rotationCrop=false
+rotation=0.0
+rescaleFactor=1.0
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+flipHorizontally=false
+colormapAutomatic=true
+roiY=0
+roiX=0
+transpose=false
diff --git a/psss-panel/assembly/devices/dispatcher.properties b/psss-panel/assembly/devices/dispatcher.properties
new file mode 100755
index 0000000..9891517
--- /dev/null
+++ b/psss-panel/assembly/devices/dispatcher.properties
@@ -0,0 +1,13 @@
+#Wed Jun 03 18:45:57 CEST 2020
+sendStrategy=complete_all
+dropIncomplete=false
+keepListeningOnStop=false
+disableCompression=false
+parallelHandlerProcessing=true
+sendBuildChannelConfig=at_startup
+sendAwaitFirstMessage=false
+socketType=DEFAULT
+validationInconsistency=keep_as_is
+byteBufferAllocator=false
+mappingIncomplete=fill_null
+sendSyncTimeout=0
diff --git a/psss-panel/assembly/devices/histo_center.properties b/psss-panel/assembly/devices/histo_center.properties
new file mode 100755
index 0000000..dfccc99
--- /dev/null
+++ b/psss-panel/assembly/devices/histo_center.properties
@@ -0,0 +1,6 @@
+#Tue Jun 15 11:03:15 CEST 2021
+bins=1000
+min=11400.0
+max=11200.0
+precision=-1
+numberOfSamples=10000
diff --git a/psss-panel/assembly/devices/histo_fwhm.properties b/psss-panel/assembly/devices/histo_fwhm.properties
new file mode 100755
index 0000000..da35091
--- /dev/null
+++ b/psss-panel/assembly/devices/histo_fwhm.properties
@@ -0,0 +1,6 @@
+#Fri Apr 30 07:45:13 CEST 2021
+bins=1000
+min=0.0
+max=40.0
+precision=-1
+numberOfSamples=10000
diff --git a/psss-panel/assembly/devices/psss_center_average.properties b/psss-panel/assembly/devices/psss_center_average.properties
new file mode 100755
index 0000000..6a20991
--- /dev/null
+++ b/psss-panel/assembly/devices/psss_center_average.properties
@@ -0,0 +1,4 @@
+#Mon May 03 09:21:35 CEST 2021
+measures=10
+precision=-1
+interval=-1
diff --git a/psss-panel/assembly/devices/psss_fwhm_average.properties b/psss-panel/assembly/devices/psss_fwhm_average.properties
new file mode 100755
index 0000000..6aeec64
--- /dev/null
+++ b/psss-panel/assembly/devices/psss_fwhm_average.properties
@@ -0,0 +1,4 @@
+#Mon May 03 09:21:52 CEST 2021
+measures=10
+precision=-1
+interval=-1
diff --git a/psss-panel/assembly/devices/psss_spectrum_y_average.properties b/psss-panel/assembly/devices/psss_spectrum_y_average.properties
new file mode 100755
index 0000000..2c2e72a
--- /dev/null
+++ b/psss-panel/assembly/devices/psss_spectrum_y_average.properties
@@ -0,0 +1,5 @@
+#Mon May 03 09:15:04 CEST 2021
+measures=10
+precision=-1
+interval=-1
+integrate=false
diff --git a/psss-panel/assembly/plugins/PSSS.form b/psss-panel/assembly/plugins/PSSS.form
new file mode 100755
index 0000000..cab1b86
--- /dev/null
+++ b/psss-panel/assembly/plugins/PSSS.form
@@ -0,0 +1,715 @@
+
+
+
diff --git a/psss-panel/assembly/plugins/PSSS.java b/psss-panel/assembly/plugins/PSSS.java
new file mode 100755
index 0000000..e652bf2
--- /dev/null
+++ b/psss-panel/assembly/plugins/PSSS.java
@@ -0,0 +1,760 @@
+import ch.psi.pshell.bs.PipelineServer;
+import ch.psi.pshell.core.Context;
+import ch.psi.pshell.epics.ChannelDouble;
+import ch.psi.pshell.imaging.RendererMode;
+import ch.psi.pshell.plot.Plot;
+import ch.psi.pshell.plot.LinePlotJFree;
+import ch.psi.pshell.ui.Panel;
+import ch.psi.utils.Convert;
+import ch.psi.utils.State;
+import ch.psi.utils.Str;
+import java.awt.CardLayout;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+
+/**
+ *
+ */
+public class PSSS extends Panel {
+
+ final String CAMERA_NAME = "SARFE10-PSSS059";
+ PipelineServer pipelineServer;
+ volatile boolean updatingPlot;
+ volatile boolean updatingImage;
+
+ public PSSS() {
+ initComponents();
+ plot.getAxis(Plot.AxisId.X).setLabel(null);
+ plot.getAxis(Plot.AxisId.Y).setLabel(null);
+ renderer.setMode(RendererMode.Stretch);
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ startTimer(1000);
+
+ try {
+ setGlobalVar("PSSS_PLOT", plot);
+ setGlobalVar("HISTORY_PLOT", history);
+ setGlobalVar("PSSS_RENDERER", renderer);
+
+ pipelineServer = (PipelineServer) getDevice("cam_server");
+ ((LinePlotJFree)histogramGeneratorPanelCenter.getPlot()).setLegendVisible(true);
+ ((LinePlotJFree)histogramGeneratorFwhm.getPlot()).setLegendVisible(true);
+ histogramGeneratorPanelCenter.getPlot().getAxis(Plot.AxisId.Y).setRange(0, 100);
+ histogramGeneratorFwhm.getPlot().getAxis(Plot.AxisId.Y).setRange(0, 100);
+ //setImageEnabled(true);
+ tabStateChanged(null);
+
+ spinnerAverage.setValue(( (Number) eval("get_psss_averaging()", true)).intValue());
+
+ try{
+ Double energy = (((ChannelDouble)getDevice("energy_machine")).take(-1));
+ energy=Convert.roundDouble(energy, 0);
+ spFromEn.setValue(energy-150);
+ spToEn.setValue(energy+150);
+ } catch (Exception ex) {
+ getLogger().warning("Error reading energy_machine");
+ }
+
+
+ } catch (Exception ex) {
+ getLogger().log(Level.WARNING, null, ex);
+ }
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ this.btStartCr.setEnabled(state == State.Ready);
+ this.btStartEn.setEnabled(state == State.Ready);
+ this.btStartCam.setEnabled(state == State.Ready);
+ radioEnergyScan.setEnabled(state == State.Ready);
+ radioCrystalScan.setEnabled(state == State.Ready);
+ radioCameraScan.setEnabled(state == State.Ready);
+ this.btAbort.setEnabled(state.isRunning());
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+ @Override
+ public void onTimer() {
+ try {
+ if (!updatingPlot){
+ updatingPlot = true;
+ //evalAsync("plot_psss(PSSS_PLOT, HISTORY_PLOT, " + spinnerAverage.getValue() + ")", true).handle((ret,ex)->{
+ evalAsync("plot_psss(PSSS_PLOT, HISTORY_PLOT)", true).handle((ret,ex)->{
+ updatingPlot = false;
+ return ret;
+ });
+ }
+ if (isImageEnabled()){
+ if (!updatingImage){
+ updatingImage = true;
+ evalAsync("update_psss_image(PSSS_RENDERER)", true).handle((ret,ex)->{
+ updatingImage = false;
+ return ret;
+ });
+ }
+ }
+ } catch (Exception ex) {
+ getLogger().log(Level.WARNING, null, ex);
+ }
+ }
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ void setImageEnabled(boolean enabled){
+ try{
+ imageEnabled = enabled;
+ evalAsync("enable_psss_image(" + Str.capitalizeFirst(String.valueOf(enabled)) + ", PSSS_RENDERER)", true);
+ } catch (Exception ex) {
+ getLogger().log(Level.WARNING, null, ex);
+ }
+ }
+ volatile boolean imageEnabled;
+
+ boolean isImageEnabled(){
+ return imageEnabled;
+ }
+
+
+ void runScan(String name, Map args){
+ try {
+ args.put("PLOT", plotScan);
+ this.runAsync(name, args).handle((ret,ex)->{
+ if (ex!=null){
+ if (!getContext().isAborted()){
+ showException((Exception)ex);
+ }
+ }
+ return ret;
+ });
+ } catch (Context.ContextStateException ex) {
+ showException(ex);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ buttonGroup1 = new javax.swing.ButtonGroup();
+ tab = new javax.swing.JTabbedPane();
+ jPanel1 = new javax.swing.JPanel();
+ plot = new ch.psi.pshell.plot.LinePlotJFree();
+ history = new ch.psi.pshell.plot.TimePlotJFree();
+ jLabel1 = new javax.swing.JLabel();
+ spinnerAverage = new javax.swing.JSpinner();
+ histogramGeneratorPanelCenter = new ch.psi.pshell.swing.HistogramGeneratorPanel();
+ histogramGeneratorFwhm = new ch.psi.pshell.swing.HistogramGeneratorPanel();
+ jPanel4 = new javax.swing.JPanel();
+ renderer = new ch.psi.pshell.imaging.Renderer();
+ jPanel3 = new javax.swing.JPanel();
+ jPanel2 = new javax.swing.JPanel();
+ btAbort = new javax.swing.JButton();
+ radioEnergyScan = new javax.swing.JRadioButton();
+ radioCameraScan = new javax.swing.JRadioButton();
+ radioCrystalScan = new javax.swing.JRadioButton();
+ jPanel5 = new javax.swing.JPanel();
+ panelScan = new javax.swing.JPanel();
+ panelEnergyScan = new javax.swing.JPanel();
+ spFromEn = new javax.swing.JSpinner();
+ jLabel6 = new javax.swing.JLabel();
+ jLabel7 = new javax.swing.JLabel();
+ spToEn = new javax.swing.JSpinner();
+ spStepsEn = new javax.swing.JSpinner();
+ jLabel8 = new javax.swing.JLabel();
+ jLabel9 = new javax.swing.JLabel();
+ spShotsEn = new javax.swing.JSpinner();
+ btStartEn = new javax.swing.JButton();
+ panelCameraScan = new javax.swing.JPanel();
+ jLabel10 = new javax.swing.JLabel();
+ spFromCam = new javax.swing.JSpinner();
+ jLabel11 = new javax.swing.JLabel();
+ spToCam = new javax.swing.JSpinner();
+ jLabel12 = new javax.swing.JLabel();
+ spStepsCam = new javax.swing.JSpinner();
+ jLabel13 = new javax.swing.JLabel();
+ spShotsCam = new javax.swing.JSpinner();
+ btStartCam = new javax.swing.JButton();
+ panelCrystalScan = new javax.swing.JPanel();
+ jLabel2 = new javax.swing.JLabel();
+ spFromCr = new javax.swing.JSpinner();
+ jLabel3 = new javax.swing.JLabel();
+ spToCr = new javax.swing.JSpinner();
+ jLabel4 = new javax.swing.JLabel();
+ spStepsCr = new javax.swing.JSpinner();
+ jLabel5 = new javax.swing.JLabel();
+ spShotsCr = new javax.swing.JSpinner();
+ btStartCr = new javax.swing.JButton();
+ plotScan = new ch.psi.pshell.plot.LinePlotJFree();
+
+ tab.addChangeListener(new javax.swing.event.ChangeListener() {
+ public void stateChanged(javax.swing.event.ChangeEvent evt) {
+ tabStateChanged(evt);
+ }
+ });
+
+ plot.setTitle("");
+
+ jLabel1.setText("Average:");
+
+ spinnerAverage.setModel(new javax.swing.SpinnerNumberModel(1, 1, 100, 1));
+ spinnerAverage.addChangeListener(new javax.swing.event.ChangeListener() {
+ public void stateChanged(javax.swing.event.ChangeEvent evt) {
+ spinnerAverageStateChanged(evt);
+ }
+ });
+
+ histogramGeneratorPanelCenter.setDeviceName("histo_center");
+
+ histogramGeneratorFwhm.setDeviceName("histo_fwhm");
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spinnerAverage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(history, javax.swing.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE)
+ .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(12, 12, 12)
+ .addComponent(histogramGeneratorFwhm, javax.swing.GroupLayout.PREFERRED_SIZE, 372, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(histogramGeneratorPanelCenter, javax.swing.GroupLayout.PREFERRED_SIZE, 372, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(0, 0, 0))
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(spinnerAverage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(6, 6, 6)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(histogramGeneratorPanelCenter, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE)
+ .addComponent(plot, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(history, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE)
+ .addComponent(histogramGeneratorFwhm, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)))
+ );
+
+ tab.addTab("Spectrum", jPanel1);
+
+ javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
+ jPanel4.setLayout(jPanel4Layout);
+ jPanel4Layout.setHorizontalGroup(
+ jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 843, Short.MAX_VALUE)
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, 843, Short.MAX_VALUE))
+ );
+ jPanel4Layout.setVerticalGroup(
+ jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 432, Short.MAX_VALUE)
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE))
+ );
+
+ tab.addTab("Camera", jPanel4);
+
+ btAbort.setText("Abort");
+ btAbort.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btAbortActionPerformed(evt);
+ }
+ });
+
+ buttonGroup1.add(radioEnergyScan);
+ radioEnergyScan.setSelected(true);
+ radioEnergyScan.setText("Energy Scan");
+ radioEnergyScan.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ radioEnergyScanActionPerformed(evt);
+ }
+ });
+
+ buttonGroup1.add(radioCameraScan);
+ radioCameraScan.setText("Camera Scan");
+ radioCameraScan.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ radioCameraScanActionPerformed(evt);
+ }
+ });
+
+ buttonGroup1.add(radioCrystalScan);
+ radioCrystalScan.setText("Crystal Height Scan");
+ radioCrystalScan.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ radioCrystalScanActionPerformed(evt);
+ }
+ });
+
+ panelScan.setLayout(new java.awt.CardLayout());
+
+ spFromEn.setModel(new javax.swing.SpinnerNumberModel(7200.0d, 1.0d, 20000.0d, 10.0d));
+
+ jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel6.setText("Range From:");
+
+ jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel7.setText("Range To:");
+
+ spToEn.setModel(new javax.swing.SpinnerNumberModel(7340.0d, 1.0d, 20000.0d, 10.0d));
+
+ spStepsEn.setModel(new javax.swing.SpinnerNumberModel(20, 1, 1000, 1));
+
+ jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel8.setText("Steps:");
+
+ jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel9.setText("Num Shots:");
+
+ spShotsEn.setModel(new javax.swing.SpinnerNumberModel(100, 1, 1000, 1));
+
+ btStartEn.setText("Start Energy Scan");
+ btStartEn.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btStartEnActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelEnergyScanLayout = new javax.swing.GroupLayout(panelEnergyScan);
+ panelEnergyScan.setLayout(panelEnergyScanLayout);
+ panelEnergyScanLayout.setHorizontalGroup(
+ panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addComponent(jLabel7)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spToEn, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addComponent(jLabel6)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spFromEn, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addComponent(jLabel8)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spStepsEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addComponent(jLabel9)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spShotsEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap())
+ .addComponent(btStartEn, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+
+ panelEnergyScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel6, jLabel7, jLabel8, jLabel9});
+
+ panelEnergyScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spFromEn, spShotsEn, spStepsEn, spToEn});
+
+ panelEnergyScanLayout.setVerticalGroup(
+ panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelEnergyScanLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel6)
+ .addComponent(spFromEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel7)
+ .addComponent(spToEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel8)
+ .addComponent(spStepsEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelEnergyScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel9)
+ .addComponent(spShotsEn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(btStartEn)
+ .addContainerGap())
+ );
+
+ panelScan.add(panelEnergyScan, "energy");
+
+ jLabel10.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel10.setText("Range From:");
+
+ spFromCam.setModel(new javax.swing.SpinnerNumberModel(-17.0d, -30.0d, 30.0d, 1.0d));
+
+ jLabel11.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel11.setText("Range To:");
+
+ spToCam.setModel(new javax.swing.SpinnerNumberModel(-11.0d, -30.0d, 30.0d, 1.0d));
+
+ jLabel12.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel12.setText("Steps:");
+
+ spStepsCam.setModel(new javax.swing.SpinnerNumberModel(20, 1, 1000, 1));
+
+ jLabel13.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel13.setText("Num Shots:");
+
+ spShotsCam.setModel(new javax.swing.SpinnerNumberModel(100, 1, 1000, 1));
+
+ btStartCam.setText("Start Camera Scan");
+ btStartCam.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btStartCamActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelCameraScanLayout = new javax.swing.GroupLayout(panelCameraScan);
+ panelCameraScan.setLayout(panelCameraScanLayout);
+ panelCameraScanLayout.setHorizontalGroup(
+ panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addComponent(jLabel11)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spToCam, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addComponent(jLabel10)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spFromCam, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addComponent(jLabel12)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spStepsCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addComponent(jLabel13)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spShotsCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(btStartCam, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+
+ panelCameraScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel10, jLabel11, jLabel12, jLabel13});
+
+ panelCameraScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spFromCam, spShotsCam, spStepsCam, spToCam});
+
+ panelCameraScanLayout.setVerticalGroup(
+ panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCameraScanLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel10)
+ .addComponent(spFromCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel11)
+ .addComponent(spToCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel12)
+ .addComponent(spStepsCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCameraScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel13)
+ .addComponent(spShotsCam, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(btStartCam)
+ .addContainerGap())
+ );
+
+ panelScan.add(panelCameraScan, "camera");
+
+ jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel2.setText("Range From:");
+
+ spFromCr.setModel(new javax.swing.SpinnerNumberModel(-0.8d, -10.0d, 10.0d, 0.1d));
+
+ jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel3.setText("Range To:");
+
+ spToCr.setModel(new javax.swing.SpinnerNumberModel(-1.7d, -10.0d, 10.0d, 0.1d));
+
+ jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel4.setText("Steps:");
+
+ spStepsCr.setModel(new javax.swing.SpinnerNumberModel(20, 1, 1000, 1));
+
+ jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel5.setText("Num Shots:");
+
+ spShotsCr.setModel(new javax.swing.SpinnerNumberModel(100, 1, 1000, 1));
+
+ btStartCr.setText("Start Crystal Height Scan");
+ btStartCr.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btStartCrActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout panelCrystalScanLayout = new javax.swing.GroupLayout(panelCrystalScan);
+ panelCrystalScan.setLayout(panelCrystalScanLayout);
+ panelCrystalScanLayout.setHorizontalGroup(
+ panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addComponent(jLabel3)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spToCr, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addComponent(jLabel2)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spFromCr, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addComponent(jLabel4)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spStepsCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addComponent(jLabel5)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(spShotsCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(btStartCr, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+
+ panelCrystalScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel2, jLabel3, jLabel4, jLabel5});
+
+ panelCrystalScanLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spFromCr, spShotsCr, spStepsCr, spToCr});
+
+ panelCrystalScanLayout.setVerticalGroup(
+ panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(panelCrystalScanLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel2)
+ .addComponent(spFromCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(spToCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel4)
+ .addComponent(spStepsCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(panelCrystalScanLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel5)
+ .addComponent(spShotsCr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(btStartCr)
+ .addContainerGap())
+ );
+
+ panelScan.add(panelCrystalScan, "crystal");
+
+ javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
+ jPanel5.setLayout(jPanel5Layout);
+ jPanel5Layout.setHorizontalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel5Layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(panelScan, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0)))
+ );
+ jPanel5Layout.setVerticalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel5Layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(panelScan, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(0, 0, 0)))
+ );
+
+ javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+ jPanel2.setLayout(jPanel2Layout);
+ jPanel2Layout.setHorizontalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addGap(12, 12, 12)
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(radioCrystalScan)
+ .addComponent(radioCameraScan)
+ .addComponent(radioEnergyScan)
+ .addComponent(btAbort, javax.swing.GroupLayout.DEFAULT_SIZE, 213, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ jPanel2Layout.setVerticalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
+ .addGap(20, 20, 20)
+ .addComponent(radioEnergyScan)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(radioCameraScan)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(radioCrystalScan)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(btAbort)
+ .addContainerGap())
+ );
+
+ plotScan.setTitle("");
+
+ javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
+ jPanel3.setLayout(jPanel3Layout);
+ jPanel3Layout.setHorizontalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0)
+ .addComponent(plotScan, javax.swing.GroupLayout.DEFAULT_SIZE, 614, Short.MAX_VALUE))
+ );
+ jPanel3Layout.setVerticalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(plotScan, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE)
+ );
+
+ tab.addTab("Alignment", jPanel3);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(tab)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(tab, javax.swing.GroupLayout.Alignment.TRAILING)
+ );
+ }// //GEN-END:initComponents
+
+ private void tabStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabStateChanged
+ setImageEnabled(tab.getSelectedIndex()==1);
+ }//GEN-LAST:event_tabStateChanged
+
+ private void btAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btAbortActionPerformed
+ try {
+ abort();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_btAbortActionPerformed
+
+ private void btStartCrActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btStartCrActionPerformed
+ Map args = new HashMap();
+ args.put("RANGE_FROM", spFromCr.getValue());
+ args.put("RANGE_TO", spToCr.getValue());
+ args.put("STEPS", spStepsCr.getValue());
+ args.put("NUM_SHOTS", spShotsCr.getValue());
+ runScan("psss/CrystalHeightScan",args);
+ }//GEN-LAST:event_btStartCrActionPerformed
+
+ private void btStartCamActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btStartCamActionPerformed
+ Map args = new HashMap();
+ args.put("RANGE_FROM", spFromCam.getValue());
+ args.put("RANGE_TO", spToCam.getValue());
+ args.put("STEPS", spStepsCam.getValue());
+ args.put("NUM_SHOTS", spShotsCam.getValue());
+ runScan("psss/CameraScan",args);
+ }//GEN-LAST:event_btStartCamActionPerformed
+
+ private void btStartEnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btStartEnActionPerformed
+ Map args = new HashMap();
+ args.put("RANGE_OFF", null);
+ args.put("RANGE_FROM", spFromEn.getValue());
+ args.put("RANGE_TO", spToEn.getValue());
+ args.put("STEPS", spStepsEn.getValue());
+ args.put("NUM_SHOTS", spShotsEn.getValue());
+ runScan("psss/EnergyScan",args);
+ }//GEN-LAST:event_btStartEnActionPerformed
+
+ private void radioEnergyScanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioEnergyScanActionPerformed
+ ((CardLayout)panelScan.getLayout()).show(panelScan, "energy");
+ }//GEN-LAST:event_radioEnergyScanActionPerformed
+
+ private void radioCameraScanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioCameraScanActionPerformed
+ ((CardLayout)panelScan.getLayout()).show(panelScan, "camera");
+ }//GEN-LAST:event_radioCameraScanActionPerformed
+
+ private void radioCrystalScanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioCrystalScanActionPerformed
+ ((CardLayout)panelScan.getLayout()).show(panelScan, "crystal");
+ }//GEN-LAST:event_radioCrystalScanActionPerformed
+
+ private void spinnerAverageStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerAverageStateChanged
+ try {
+ eval("set_psss_averaging(" + spinnerAverage.getValue() + ")", true);
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_spinnerAverageStateChanged
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton btAbort;
+ private javax.swing.JButton btStartCam;
+ private javax.swing.JButton btStartCr;
+ private javax.swing.JButton btStartEn;
+ private javax.swing.ButtonGroup buttonGroup1;
+ private ch.psi.pshell.swing.HistogramGeneratorPanel histogramGeneratorFwhm;
+ private ch.psi.pshell.swing.HistogramGeneratorPanel histogramGeneratorPanelCenter;
+ private ch.psi.pshell.plot.TimePlotJFree history;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel10;
+ private javax.swing.JLabel jLabel11;
+ private javax.swing.JLabel jLabel12;
+ private javax.swing.JLabel jLabel13;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel4;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JLabel jLabel6;
+ private javax.swing.JLabel jLabel7;
+ private javax.swing.JLabel jLabel8;
+ private javax.swing.JLabel jLabel9;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPanel jPanel2;
+ private javax.swing.JPanel jPanel3;
+ private javax.swing.JPanel jPanel4;
+ private javax.swing.JPanel jPanel5;
+ private javax.swing.JPanel panelCameraScan;
+ private javax.swing.JPanel panelCrystalScan;
+ private javax.swing.JPanel panelEnergyScan;
+ private javax.swing.JPanel panelScan;
+ private ch.psi.pshell.plot.LinePlotJFree plot;
+ private ch.psi.pshell.plot.LinePlotJFree plotScan;
+ private javax.swing.JRadioButton radioCameraScan;
+ private javax.swing.JRadioButton radioCrystalScan;
+ private javax.swing.JRadioButton radioEnergyScan;
+ private ch.psi.pshell.imaging.Renderer renderer;
+ private javax.swing.JSpinner spFromCam;
+ private javax.swing.JSpinner spFromCr;
+ private javax.swing.JSpinner spFromEn;
+ private javax.swing.JSpinner spShotsCam;
+ private javax.swing.JSpinner spShotsCr;
+ private javax.swing.JSpinner spShotsEn;
+ private javax.swing.JSpinner spStepsCam;
+ private javax.swing.JSpinner spStepsCr;
+ private javax.swing.JSpinner spStepsEn;
+ private javax.swing.JSpinner spToCam;
+ private javax.swing.JSpinner spToCr;
+ private javax.swing.JSpinner spToEn;
+ private javax.swing.JSpinner spinnerAverage;
+ private javax.swing.JTabbedPane tab;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/psss-panel/assembly/script/cpython/psss.py b/psss-panel/assembly/script/cpython/psss.py
new file mode 100755
index 0000000..e5ce177
--- /dev/null
+++ b/psss-panel/assembly/script/cpython/psss.py
@@ -0,0 +1,45 @@
+import numpy as np
+from scipy.optimize import curve_fit
+import sys
+
+
+def gaus(x, a, x0, sigma, offset):
+ return offset + a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))
+
+#Return [amp, mean_val, sigma, offset]
+def fit_energy(e_from, e_to, steps, num_shots, data):
+ energy_range = np.linspace(e_from, e_to, steps)
+ energy_range_fit = np.linspace(energy_range[0], energy_range[-1], len(energy_range)*10)
+ centre_line_out = data[:,:,int(data.shape[2]/2)].mean(axis=1)
+ try:
+ popt,pcov = curve_fit(gaus,energy_range,centre_line_out,p0=[1,energy_range[np.argmax(centre_line_out)],energy_range.mean()*1e-3,1e3*num_shots])
+ except:
+ raise Exception('Fit failed: spectrum might not be near scan range center \n' + str(sys.exc_info()[1]))
+ #print('Fit failed: spectrum might not be near scan range center')
+ #return None
+ max_ind = np.argmax(centre_line_out)
+ max_photon_energy=energy_range[max_ind]
+ print(max_photon_energy)
+ return popt, centre_line_out
+
+
+#Return [amp, mean_val, sigma, offset]
+def fit_crystal_height(xstal_from, xstal_to, steps, data):
+ xstal_range = np.linspace(xstal_from, xstal_to, steps)
+ projection = data.mean(axis=1).mean(axis=1)
+ offset = np.mean(projection[0:100])
+ signal_centre = xstal_range[np.argmax(projection)]
+ xstal_range_fit = np.linspace(xstal_range[0], xstal_range[-1], len(xstal_range)*10)
+ try:
+ popt,pcov = curve_fit(gaus,xstal_range,projection,p0=[100,signal_centre,-0.2,offset])
+ except:
+ raise Exception('Fit failed: spectrum might not be near scan range center \n' + str(sys.exc_info()[1]))
+ #print('Fit failed: spectrum might not be near scan range center')
+ #return None
+ return popt, projection
+
+
+def get_signal_centre(data, data_range):
+ projection = data.mean(axis=1).mean(axis=1)
+ signal_centre = data_range[np.argmax(projection)]
+ return signal_centre, projection
diff --git a/psss-panel/assembly/script/cpython/psss_plot.py b/psss-panel/assembly/script/cpython/psss_plot.py
new file mode 100755
index 0000000..27080e2
--- /dev/null
+++ b/psss-panel/assembly/script/cpython/psss_plot.py
@@ -0,0 +1,32 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+def gaus(x, a, x0, sigma, offset):
+ return offset + a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))
+
+def plot_energy(E_from, E_to, steps, Scan_spec, popt, measured_offset):
+ Energy_range = np.linspace(E_from, E_to, steps)
+ centre_line_out = Scan_spec[:,:,int(Scan_spec.shape[2]/2)].mean(axis=1)
+ Energy_range_fit = np.linspace(Energy_range[0], Energy_range[-1], len(Energy_range)*10)
+
+
+ plt.figure(figsize=[10,5])
+ plt.subplot(121)
+ plt.title('PSSS scan of set photon energy')
+ plt.pcolormesh(np.arange(0,Scan_spec.shape[2]), Energy_range, Scan_spec.mean(axis=1),cmap='CMRmap')
+ plt.vlines(int(Scan_spec.shape[2]/2), Energy_range[0], Energy_range[-1],linestyles='--', colors='orange')
+ plt.xlim([0,Scan_spec.shape[2]])
+ plt.xlabel('Camera pixel')
+ plt.ylabel('Set PSSS energy [eV] \n SARFE10-PSSS059:ENERGY')
+
+ plt.subplot(122)
+ plt.title('At camera centre pixel %1i \nCalibrated energy = %.1f [eV]\n Offset from machine = %.1f [eV]'%(int(Scan_spec.shape[2]/2),popt[1],measured_offset))
+ plt.plot(centre_line_out,Energy_range,linewidth = 2, color = 'orange',label ='measured')
+ try:
+ plt.plot(gaus(Energy_range_fit,*popt),Energy_range_fit,'r:',label='fit')
+ except:
+ pass
+ plt.xticks([])
+ plt.legend()
+ plt.grid(True)
\ No newline at end of file
diff --git a/psss-panel/assembly/script/cpython/wrapper.py b/psss-panel/assembly/script/cpython/wrapper.py
new file mode 100755
index 0000000..5aa4031
--- /dev/null
+++ b/psss-panel/assembly/script/cpython/wrapper.py
@@ -0,0 +1,36 @@
+from jeputils import *
+
+RELOAD_CPYTHON = not App.isDetached()
+
+def fit_energy(e_from, e_to, steps, num_shots, data):
+ data = to_array(data, 'd')
+ dims = [len(data), len(data[0]), len(data[0][0])]
+ data = Convert.flatten(data)
+ arr = to_npa(data, dims)
+ popt, centre_line_out = call_jep("cpython/psss", "fit_energy", [e_from, e_to, steps, num_shots, arr], reload=RELOAD_CPYTHON)
+ return popt.getData(), centre_line_out.getData()
+
+def fit_crystal_height(xstal_from, xstal_to, steps, data):
+ data = to_array(data, 'd')
+ dims = [len(data), len(data[0]), len(data[0][0])]
+ data = Convert.flatten(data)
+ arr = to_npa(data, dims)
+ popt, projection = call_jep("cpython/psss", "fit_crystal_height", [xstal_from, xstal_to, steps, arr], reload=RELOAD_CPYTHON)
+ return popt.getData(), projection.getData()
+
+def get_signal_centre(data, data_range):
+ data = to_array(data, 'd')
+ dims = [len(data), len(data[0]), len(data[0][0])]
+ data = Convert.flatten(data)
+ arr = to_npa(data, dims)
+ data_range = to_npa(to_array(data_range, 'd'))
+ signal_centre, projection = call_jep("cpython/psss", "get_signal_centre", [arr, data_range], reload=RELOAD_CPYTHON)
+ return signal_centre, projection.getData()
+
+def plot_energy(e_from, e_to, steps, data, popt, measured_offset):
+ data = to_array(data, 'd')
+ dims = [len(data), len(data[0]), len(data[0][0])]
+ data = Convert.flatten(data)
+ arr = to_npa(data, dims)
+ ret = call_jep("cpython/psss_plot", "plot_energy", [e_from, e_to, steps, arr, popt, measured_offset], reload=RELOAD_CPYTHON)
+ return ret
diff --git a/psss-panel/assembly/script/local.py b/psss-panel/assembly/script/local.py
new file mode 100755
index 0000000..6ce8712
--- /dev/null
+++ b/psss-panel/assembly/script/local.py
@@ -0,0 +1,184 @@
+###################################################################################################
+# Deployment specific global definitions - executed after startup.py
+###################################################################################################
+
+from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list
+from mathutils import fit_polynomial,fit_gaussian, fit_harmonic, calculate_peaks, fit_gaussian_offset
+from mathutils import PolynomialFunction, Gaussian, HarmonicOscillator, GaussianOffset
+from plotutils import plot_function, plot_data
+
+import java.awt.Color as Color
+run("psss/psss")
+
+###################################################################################################
+# DRY RUN
+###################################################################################################
+
+def set_dry_run(value):
+ global dry_run
+ dry_run = value
+
+def is_dry_run():
+ if "dry_run" in globals():
+ return True if dry_run else False
+ return False
+
+
+###################################################################################################
+# Machine utilities
+###################################################################################################
+
+def is_laser_on():
+ return (caget ("SIN-TIMAST-TMA:Beam-Las-Delay-Sel",'d') == 0 )
+
+def is_timing_ok():
+ return caget("SIN-TIMAST-TMA:SOS-COUNT-CHECK") == 0
+
+def get_repetition_rate():
+ return caget("SIN-TIMAST-TMA:Evt-15-Freq-I")
+
+
+###################################################################################################
+# Shortcut to maths utilities
+###################################################################################################
+
+def gfit(ydata, xdata = None):
+ """
+ Gaussian fit
+ """
+ if xdata is None:
+ xdata = frange(0, len(ydata), 1)
+ #ydata = to_list(ydata)
+ #xdata = to_list(xdata)
+ max_y= max(ydata)
+ index_max = ydata.index(max_y)
+ max_x= xdata[index_max]
+ print "Max index:" + str(index_max),
+ print " x:" + str(max_x),
+ print " y:" + str(max_y)
+ gaussians = fit_gaussians(ydata, xdata, [index_max,])
+ (norm, mean, sigma) = gaussians[0]
+ p = plot([ydata],["data"],[xdata], title="Fit" )[0]
+ fitted_gaussian_function = Gaussian(norm, mean, sigma)
+ scale_x = [float(min(xdata)), float(max(xdata)) ]
+ points = max((len(xdata)+1), 100)
+ resolution = (scale_x[1]-scale_x[0]) / points
+ fit_y = []
+ fit_x = frange(scale_x[0],scale_x[1],resolution, True)
+ for x in fit_x:
+ fit_y.append(fitted_gaussian_function.value(x))
+ p.addSeries(LinePlotSeries("fit"))
+ p.getSeries(1).setData(fit_x, fit_y)
+
+ if abs(mean - xdata[index_max]) < ((scale_x[0] + scale_x[1])/2):
+ print "Mean -> " + str(mean)
+ p.addMarker(mean, None, "Mean="+str(round(norm,2)), Color.MAGENTA.darker())
+ return (norm, mean, sigma)
+ else:
+ p.addMarker(max_x, None, "Max="+str(round(max_x,2)), Color.GRAY)
+ print "Invalid gaussian fit: " + str(mean)
+ return (None, None, None)
+
+
+def hfit(ydata, xdata = None):
+ """
+ Harmonic fit
+ """
+ if xdata is None:
+ xdata = frange(0, len(ydata), 1)
+
+ max_y= max(ydata)
+ index_max = ydata.index(max_y)
+ max_x= xdata[index_max]
+
+ start,end = min(xdata), max(xdata)
+ (amplitude, angular_frequency, phase) = fit_harmonic(ydata, xdata)
+ fitted_harmonic_function = HarmonicOscillator(amplitude, angular_frequency, phase)
+
+ print "amplitude = ", amplitude
+ print "angular frequency = ", angular_frequency
+ print "phase = ", phase
+
+ f = angular_frequency/ (2* math.pi)
+ print "frequency = ", f
+
+ resolution = 4.00 # 1.00
+ fit_y = []
+ for x in frange(start,end,resolution, True):
+ fit_y.append(fitted_harmonic_function.value(x))
+ fit_x = frange(start, end+resolution, resolution)
+
+ p = plot(ydata,"data", xdata, title="HFit")[0]
+ p.addSeries(LinePlotSeries("fit"))
+ p.getSeries(1).setData(fit_x, fit_y)
+
+ #m = (phase + math.pi)/ angular_frequency
+ m = -phase / angular_frequency
+ if (m