/* * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. */ import java.io.File; import java.io.IOException; import java.nio.file.Paths; import javax.swing.DefaultComboBoxModel; import ch.psi.pshell.ui.Panel; import ch.psi.pshell.imaging.ImageListener; import ch.psi.utils.State; import ch.psi.utils.IO; import ch.psi.utils.swing.SwingUtils; import ch.psi.utils.swing.ConfigDialog; import ch.psi.utils.swing.StandardDialog; import ch.psi.utils.swing.TextEditor; import ch.psi.pshell.epics.PsiCamera; import ch.psi.pshell.core.JsonSerializer; import ch.psi.pshell.device.Device; import ch.psi.pshell.epics.ArraySource; import ch.psi.pshell.epics.ChannelDouble; import ch.psi.pshell.epics.ChannelDoubleArray; import ch.psi.pshell.epics.ChannelInteger; import ch.psi.pshell.epics.ChannelIntegerArray; import ch.psi.pshell.ui.App; import ch.psi.pshell.imaging.Data; import ch.psi.utils.swing.Editor.EditorDialog; import java.awt.Component; import java.awt.Dimension; import java.awt.Frame; import java.awt.image.BufferedImage; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE; /** * */ public class Cameras extends Panel { public Cameras() { initComponents(); renderer.setPersistenceFile(Paths.get(getController().getSetup().getContextPath(), "Renderer_Cameras.bin")); setPersistedComponents(new Component[]{checkCamtool}); comboCameras.setEnabled(false); } final String configFolder = "/afs/psi.ch/intranet/SF/Applications/config/camtool"; File[] cameraConfigFiles = new File[0]; ArraySource camera; String cameraName; String cameraConfigJson; CameraConfig config; //Overridable callbacks @Override public void onInitialize(int runCount) { comboCameras.setEnabled(false); cameraConfigFiles = IO.listFiles(configFolder, new String[]{"json"}); Arrays.sort(cameraConfigFiles, (a, b) -> a.compareTo(b)); DefaultComboBoxModel model = new DefaultComboBoxModel(); for (File file : cameraConfigFiles) { String prefix = IO.getPrefix(file); if (!prefix.startsWith("#")) { model.addElement(prefix); } } comboCameras.setModel(model); comboCameras.setEnabled(true); comboCameras.setSelectedItem(-1); if (model.getSize() > 0) { try { //setCamera((String)comboCameras.getSelectedItem()); if (App.hasArgument("cam")) { comboCameras.setSelectedItem(App.getArgumentValue("cam")); } } catch (Exception ex) { ex.printStackTrace(); } } startTimer(1000); } @Override public void onStateChange(State state, State former) { } @Override public void onExecutedFile(String fileName, Object result) { } //Callback to perform update - in event thread @Override protected void doUpdate() { } public static class CameraConfig { public HashMap kwargs; public ArrayList args; public ArrayList links; public String type; public HashMap state; public CameraConfig image_source; public HashMap subcomponents; public ArrayList getCalibration() { return (ArrayList) state.get("calibration"); } public Double getCalibrationHeight() { return (Double) state.get("calibration_height"); } public Double getCalibrationWidth() { return (Double) state.get("calibration_width"); } public Double getCalibrationHorizontalAngle() { return (Double) state.get("calibration_horizontal_angle"); } public Double getCalibrationVerticalAngle() { return (Double) state.get("calibration_vertical_angle"); } public Boolean getMirrorX() { return (Boolean) state.get("mirror_x"); } public Boolean getMirrorY() { return (Boolean) state.get("mirror_y"); } public Integer getRotate() { return (Integer) state.get("rotate"); } public ArrayList getOrigin() { return (ArrayList) state.get("origin"); } public ArrayList getRoi() { return (ArrayList) state.get("roi"); } public Boolean getRoiEnable() { if ((state.get("roi_enable") == null) || (state.get("roi") == null)) { return false; } return (Boolean) state.get("roi_enable"); } public ArrayList getUnitSize() { return (ArrayList) state.get("unit_size"); } public Integer getRun() { return (Integer) state.get("run"); } } void setCamera(String cameraName) throws IOException, InterruptedException { System.out.println("Setting camera: " + cameraName); if (camera != null) { camera.close(); camera = null; renderer.setDevice(null); renderer.clear(); } try { Path configFile = Paths.get(configFolder, cameraName + ".json"); cameraConfigJson = new String(Files.readAllBytes(configFile)); this.cameraName = cameraName; //SwingUtils.showMessage(null, "", json); try { if (checkCamtool.isSelected()) { camera = new Camtool("CurrentCamera", cameraName, false, true); } else { camera = new PsiCamera("CurrentCamera", cameraName); config = (CameraConfig) JsonSerializer.decode(cameraConfigJson, CameraConfig.class); camera.getConfig().flipHorizontally = config.getMirrorX(); camera.getConfig().flipVertically = config.getMirrorY(); camera.getConfig().rotation = config.getRotate(); camera.getConfig().rotationCrop = true; camera.getConfig().roiX = config.getRoiEnable() ? config.getRoi().get(0) : 0; camera.getConfig().roiY = config.getRoiEnable() ? config.getRoi().get(1) : 0; camera.getConfig().roiWidth = config.getRoiEnable() ? config.getRoi().get(2) : -1; camera.getConfig().roiHeight = config.getRoiEnable() ? config.getRoi().get(3) : -1; //camera.getConfig().spatialCalOffsetX = (config.getOrigin()!=null) ? config.getOrigin().get(0) : Double.NaN; //camera.getConfig().spatialCalOffsetY = (config.getOrigin()!=null) ? config.getOrigin().get(1) : Double.NaN; //camera.getConfig().spatialCalScaleX = (config.getUnitSize()!=null) && (config.getOrigin().get(0)!=0) ? 1.0/(config.getOrigin().get(0)*1000) : Double.NaN; //camera.getConfig().spatialCalScaleY= (config.getUnitSize()!=null) && (config.getOrigin().get(1)!=0) ? 1.0/(config.getOrigin().get(1)*1000) : Double.NaN; ArrayList calibration = config.getCalibration(); if ((calibration != null) && (calibration.size() != 4)) { calibration = null; } camera.getConfig().spatialCalOffsetX = (calibration != null) ? -calibration.get(2) : Double.NaN; camera.getConfig().spatialCalOffsetY = (calibration != null) ? -calibration.get(3) : Double.NaN; camera.getConfig().spatialCalScaleX = (calibration != null) && (calibration.get(0) != 0) ? 1.0 / (calibration.get(0)) : Double.NaN; camera.getConfig().spatialCalScaleY = (calibration != null) && (calibration.get(1) != 0) ? 1.0 / (calibration.get(1)) : Double.NaN; } } catch (Exception ex) { config = null; showException(ex); } camera.initialize(); if (camera instanceof Camtool){ double[] origin = ((Camtool)camera).origin.read(); camera.getConfig().spatialCalOffsetX = origin[0]; camera.getConfig().spatialCalOffsetY = origin[1]; } camera.getConfig().save(); camera.setPolling(-500); //camera.setMonitored(true); renderer.setDevice(camera); renderer.setShowReticle(true); renderer.setAutoScroll(true); camera.addListener(new ImageListener() { @Override public void onImage(Object o, BufferedImage bi, Data data) { if (renderer.getReticle() != null) { if (bi == null) { return; } renderer.getReticle().setSize(new Dimension(bi.getWidth(), bi.getHeight())); } camera.removeListener(this); } @Override public void onError(Object o, Exception excptn) { } }); } finally { onTimer(); } } @Override protected void onTimer() { textState.setText((camera == null) ? "" : camera.getState().toString()); buttonConfig.setEnabled(camera != null); } ///////// public class Camtool extends ArraySource { final String prefix; final String dataPrefix; final boolean latch; final public ChannelInteger channelRun; final public ChannelInteger channelLatch; final public ChannelDouble channelTimestamp; final public ChannelDoubleArray origin; final public ChannelDouble posX, posY; final public ChannelDoubleArray profileX, profileY; final public ChannelIntegerArray shape; final public ChannelInteger bgEnable, bgCapture, bgCaptureRemain; //final public CamToolPosX posMeanX; //final public CamToolPosY posMeanY; //final public CamToolVarX posVarX; //final public CamToolVarY posVarY; public Camtool(String name, String prefix) { this(name, prefix, false, true); } public Camtool(String name, String prefix, boolean latch, boolean roi) { super(name, prefix + (latch ? ":latch" : ":pipeline") + (roi ? ".roi.output" : ".image")); this.prefix = prefix + ":"; this.latch = latch; dataPrefix = this.prefix + (latch ? "latch" : "pipeline") + "."; channelRun = new ChannelInteger(name + " run", this.prefix + "camera.run"); channelLatch = new ChannelInteger(name + " latch", this.prefix + "latch.capture"); channelTimestamp = new ChannelDouble(name + " timestamp", dataPrefix + "timestamp"); channelTimestamp.setMonitored(true); //posX = new ChannelDouble(name + " com x", dataPrefix + "x_stats.com"); //posY = new ChannelDouble(name + " com y", dataPrefix + "y_stats.com"); posX = new ChannelDouble(name + " com x", dataPrefix + "x_stats.com_egu"); posY = new ChannelDouble(name + " com y", dataPrefix + "y_stats.com_egu"); profileX = new ChannelDoubleArray(name + " profile x", dataPrefix + "profile.x"); profileY = new ChannelDoubleArray(name + " profile y", dataPrefix + "profile.y"); shape = new ChannelIntegerArray(name + " shape", dataPrefix + (roi ? "roi.output.shape" : "image.shape")); origin = new ChannelDoubleArray(name + " origin X", roi ? (dataPrefix + "roi.origin_out") : (prefix+"origin")); bgEnable = new ChannelInteger(name + " bg enable", this.prefix + "pipeline.bg.enabled"); bgCapture = new ChannelInteger(name + " bg capture", this.prefix + "pipeline.bg.capture"); bgCaptureRemain = new ChannelInteger(name + " bg capture remain", this.prefix + "pipeline.bg.capture_remain"); //posMeanX = new CamToolPosX(); //posMeanY = new CamToolPosY(); //posVarX = new CamToolVarX(); //posVarY = new CamToolVarY(); } @Override public void doSetMonitored(boolean value) { super.doSetMonitored(value); getDevice().setMonitored(value); } @Override public void doUpdate() throws IOException, InterruptedException { super.doUpdate(); getDevice().update(); } void safeInitialize(Device dev, int timeout) throws IOException, InterruptedException{ for (int retries = 0; retries < 10; retries ++){ try{ dev.initialize(); break; } catch (IOException ex){ if (retries==9){ throw ex; } Thread.sleep(timeout / 10); } } } @Override protected void doInitialize() throws IOException, InterruptedException { try { safeInitialize (channelRun,3000); channelLatch.initialize(); if (latch){ start(); latch(); } safeInitialize (channelTimestamp,2000); posX.initialize(); posY.initialize(); profileX.initialize(); profileY.initialize(); shape.initialize(); origin.initialize(); bgEnable.initialize(); bgCapture.initialize(); bgCaptureRemain.initialize(); int[] s = shape.read(); getConfig().imageHeight = s[0]; getConfig().imageWidth = s[1]; getConfig().save(); getDevice().setSize(s[0] * s[1]); super.doInitialize(); } catch (InterruptedException ex) { throw ex; } catch (Exception ex) { throw new IOException(ex); } } int numImages = 1; public int getNumImages() { return numImages; } public void setNumImages(int value) { numImages = value; } double grabTimeout = 3.0; public double getGrabTimeout() { return grabTimeout; } public void setGrabTimeou(double value) { grabTimeout = value; } public void capture() throws IOException, InterruptedException { } public void start() throws IOException, InterruptedException { channelRun.write(-1); } public void stop() throws IOException, InterruptedException { channelRun.write(0); } public void grabSingle() throws IOException, InterruptedException { channelRun.write(1); } public void latch() throws IOException, InterruptedException { System.out.println("LATCH"); channelLatch.write(1); System.out.println("Ret:" + channelLatch.read()); } public void enableBackground(boolean value) throws IOException, InterruptedException { bgEnable.write(value ? 1 : 0); } public void captureBackground(int images) throws IOException, InterruptedException { start(); bgCapture.write(images); Thread.sleep(200); while (bgCaptureRemain.read() > 0) { Thread.sleep(10); } } } //////// @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { renderer = new ch.psi.pshell.imaging.Renderer(); jLabel1 = new javax.swing.JLabel(); comboCameras = new javax.swing.JComboBox(); jLabel2 = new javax.swing.JLabel(); textState = new javax.swing.JTextField(); buttonConfig = new javax.swing.JButton(); buttonSetup = new javax.swing.JButton(); checkCamtool = new javax.swing.JCheckBox(); jLabel1.setText("Camera:"); comboCameras.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { comboCamerasActionPerformed(evt); } }); jLabel2.setText("State:"); textState.setEditable(false); textState.setHorizontalAlignment(javax.swing.JTextField.CENTER); textState.setDisabledTextColor(new java.awt.Color(0, 0, 0)); textState.setEnabled(false); buttonConfig.setText("Config"); buttonConfig.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonConfigActionPerformed(evt); } }); buttonSetup.setText("Setup"); buttonSetup.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonSetupActionPerformed(evt); } }); checkCamtool.setSelected(true); checkCamtool.setText("Camtool"); 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() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(checkCamtool) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(comboCameras, 0, 218, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonConfig) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonSetup) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(textState, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonConfig, buttonSetup}); 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.BASELINE) .addComponent(jLabel1) .addComponent(comboCameras, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel2) .addComponent(textState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(buttonConfig) .addComponent(buttonSetup) .addComponent(checkCamtool)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE) .addGap(6, 6, 6)) ); layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {comboCameras, textState}); }// //GEN-END:initComponents private void comboCamerasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboCamerasActionPerformed try { comboCameras.setEnabled(false); new Thread(new Runnable() { @Override public void run() { try{ setCamera((String) comboCameras.getSelectedItem()); } catch(Exception ex){ ex.printStackTrace(); } finally{ comboCameras.setEnabled(true); } } }).start(); } catch (Exception ex) { showException(ex); } }//GEN-LAST:event_comboCamerasActionPerformed private void buttonConfigActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonConfigActionPerformed try { if (camera != null) { TextEditor editor = new TextEditor(); editor.setText(cameraConfigJson); editor.setReadOnly(true); editor.setTitle(cameraName); EditorDialog dlg = editor.getDialog(getTopLevel(), false); dlg.setSize(480, 640); dlg.setVisible(true); SwingUtils.centerComponent(this, dlg); } } catch (Exception ex) { showException(ex); } }//GEN-LAST:event_buttonConfigActionPerformed private void buttonSetupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSetupActionPerformed try { if (camera != null) { this.showDeviceConfigDialog(camera, false); } } catch (Exception ex) { showException(ex); } }//GEN-LAST:event_buttonSetupActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonConfig; private javax.swing.JButton buttonSetup; private javax.swing.JCheckBox checkCamtool; private javax.swing.JComboBox comboCameras; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private ch.psi.pshell.imaging.Renderer renderer; private javax.swing.JTextField textState; // End of variables declaration//GEN-END:variables }