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