diff --git a/plugins/AthosCameras.form b/plugins/AthosCameras.form
new file mode 100644
index 0000000..edacaa3
--- /dev/null
+++ b/plugins/AthosCameras.form
@@ -0,0 +1,90 @@
+
+
+
diff --git a/plugins/AthosCameras.java b/plugins/AthosCameras.java
new file mode 100644
index 0000000..56760af
--- /dev/null
+++ b/plugins/AthosCameras.java
@@ -0,0 +1,201 @@
+import ch.psi.pshell.bs.PipelineServer;
+import ch.psi.pshell.imaging.ColormapSource;
+import ch.psi.pshell.imaging.Overlay;
+import ch.psi.pshell.imaging.Overlays;
+import ch.psi.pshell.ui.App;
+import ch.psi.pshell.ui.Panel;
+import ch.psi.utils.State;
+import java.awt.Font;
+import java.awt.Point;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ */
+public class AthosCameras extends Panel {
+
+ PipelineServer server;
+ ColormapSource camera;
+ String serverUrl;
+ Overlay errorOverlay;
+ String instanceName;
+ String cameraName;
+
+ final String CAMERA_DEVICE_NAME = "AthosCamera";
+ String pipelineSuffix = "_sp";
+
+ public AthosCameras() {
+ initComponents();
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ if (App.hasArgument("cam")) {
+ try {
+ setCamera(App.getArgumentValue("cam"));
+ } catch (Exception ex) {
+ Logger.getLogger(AthosCameras.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+
+ @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() {
+ }
+
+
+ PipelineServer newServer() throws IOException {
+ if (serverUrl != null) {
+ System.out.println("Connecting to server: " + serverUrl);
+ server = new PipelineServer(CAMERA_DEVICE_NAME, serverUrl);
+ } else {
+ System.out.println("Connecting to server");
+ server = new PipelineServer(CAMERA_DEVICE_NAME);
+ }
+ return server;
+ }
+
+ void setCamera(String cameraName) throws IOException, InterruptedException {
+ System.out.println("Initializing: " + cameraName);
+ renderer.setDevice(null);
+ renderer.setShowReticle(false);
+ renderer.clear();
+ renderer.resetZoom();
+
+ boolean changed = !String.valueOf(cameraName).equals(this.cameraName);
+ this.cameraName = cameraName;
+
+
+ if (cameraName == null) {
+ return;
+ }
+
+ System.out.println("Setting camera: " + cameraName );
+ try{
+ camera = newServer();
+ camera.getConfig().flipHorizontally = false;
+ camera.getConfig().flipVertically = false;
+ camera.getConfig().rotation = 0.0;
+ camera.getConfig().roiX = 0;
+ camera.getConfig().roiY = 0;
+ camera.getConfig().roiWidth = -1;
+ camera.getConfig().roiHeight = -1;
+ camera.initialize();
+ camera.assertInitialized();
+ System.out.println("Camera initialization OK");
+
+ String pipelineName = cameraName + pipelineSuffix;
+ instanceName = cameraName + pipelineSuffix + "1";
+ if (!server.getPipelines().contains(pipelineName)) {
+ System.out.println("Creating pipeline: " + pipelineName);
+ HashMap config = new HashMap<>();
+ config.put("camera_name", cameraName);
+ //server.createFromConfig(config, pipelineName);
+ server.savePipelineConfig(pipelineName, config);
+ }
+ server.start(pipelineName, instanceName);
+
+ camera.getConfig().save();
+ renderer.setDevice(camera);
+ renderer.setAutoScroll(true);
+ renderer.setSource(camera);
+ } catch (Exception ex) {
+ showException(ex);
+ renderer.clearOverlays();
+ if (renderer.getDevice() == null) {
+ //renderer.setZoom(1.0);
+ //renderer.setMode(RendererMode.Zoom);
+ errorOverlay = new Overlays.Text(renderer.getPenErrorText(), ex.toString(), new Font("Verdana", Font.PLAIN, 12), new Point(20, 20));
+ errorOverlay.setFixed(true);
+ errorOverlay.setAnchor(Overlay.ANCHOR_VIEWPORT_TOP_LEFT);
+ renderer.addOverlay(errorOverlay);
+ }
+ } finally {
+ //checkReticle();
+ onTimer();
+ }
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ renderer = new ch.psi.pshell.imaging.Renderer();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel2 = new javax.swing.JLabel();
+ edit_y_center_of_mass = new javax.swing.JTextField();
+ edit_x_center_of_mass = new javax.swing.JTextField();
+
+ jLabel1.setText("x_center_of_mass:");
+
+ jLabel2.setText("y_center_of_mass:");
+
+ edit_y_center_of_mass.setEditable(false);
+
+ edit_x_center_of_mass.setEditable(false);
+
+ 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(503, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jLabel2)
+ .addComponent(jLabel1))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(edit_y_center_of_mass, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(edit_x_center_of_mass, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(72, 72, 72))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(renderer, javax.swing.GroupLayout.PREFERRED_SIZE, 462, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(361, Short.MAX_VALUE)))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(132, 132, 132)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1)
+ .addComponent(edit_x_center_of_mass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel2)
+ .addComponent(edit_y_center_of_mass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(303, Short.MAX_VALUE))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(renderer, javax.swing.GroupLayout.DEFAULT_SIZE, 481, Short.MAX_VALUE)
+ .addContainerGap()))
+ );
+ }// //GEN-END:initComponents
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField edit_x_center_of_mass;
+ private javax.swing.JTextField edit_y_center_of_mass;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private ch.psi.pshell.imaging.Renderer renderer;
+ // End of variables declaration//GEN-END:variables
+}