diff --git a/plugins/Correlation.form b/plugins/Correlation.form
new file mode 100644
index 0000000..241ea9b
--- /dev/null
+++ b/plugins/Correlation.form
@@ -0,0 +1,170 @@
+
+
+
diff --git a/plugins/Correlation.java b/plugins/Correlation.java
new file mode 100644
index 0000000..c9dad7b
--- /dev/null
+++ b/plugins/Correlation.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
+ */
+
+import ch.psi.pshell.ui.Panel;
+import ch.psi.utils.State;
+import java.awt.Component;
+import java.util.HashMap;
+
+/**
+ *
+ */
+public class Correlation extends Panel {
+
+ public Correlation() {
+ initComponents();
+ this.setPersistedComponents(new Component[]{textDevX, textDevY, spinnerInterval, spinnerWindow});
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ buttonStart.setEnabled(state==State.Ready);
+ buttonStop.setEnabled(state==State.Busy);
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ @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();
+ textDevX = new javax.swing.JTextField();
+ textDevY = new javax.swing.JTextField();
+ 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();
+ buttonStop = new javax.swing.JButton();
+
+ 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(Double.valueOf(0.1d), Double.valueOf(0.001d), null, Double.valueOf(1.0d)));
+
+ jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ jLabel4.setText("Window size:");
+
+ spinnerWindow.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(50), Integer.valueOf(3), null, Integer.valueOf(1)));
+
+ buttonStart.setText("Start");
+ buttonStart.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStartActionPerformed(evt);
+ }
+ });
+
+ buttonStop.setText("Stop");
+ buttonStop.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStopActionPerformed(evt);
+ }
+ });
+
+ 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(jLabel1)
+ .addComponent(jLabel2)
+ .addComponent(jLabel3)
+ .addComponent(jLabel4))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(textDevX, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(textDevY, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .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))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(buttonStart, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonStop, javax.swing.GroupLayout.PREFERRED_SIZE, 142, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 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.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .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)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel2)
+ .addComponent(textDevY, 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(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, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonStart)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonStop)
+ .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)
+ .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, 363, Short.MAX_VALUE)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, 499, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStopActionPerformed
+ try {
+ abort();
+ } catch (InterruptedException ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStopActionPerformed
+
+ private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed
+ try {
+ 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("p", plot);
+ runAsync("Correlation/Correlation", args);
+
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStartActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonStart;
+ private javax.swing.JButton buttonStop;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel4;
+ 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 textDevX;
+ private javax.swing.JTextField textDevY;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/script/Devices/BpmStats.py b/script/Devices/BpmStats.py
new file mode 100644
index 0000000..73c16f7
--- /dev/null
+++ b/script/Devices/BpmStats.py
@@ -0,0 +1,83 @@
+from startup import *
+from ijutils import *
+from ch.psi.pshell.imaging.Overlays import *
+import ch.psi.pshell.imaging.Pen as Pen
+import java.awt.Color as Color
+import random
+
+
+
+class BpmStats(DeviceBase):
+ def __init__(self, name, prefix, read_interval = 0.1):
+ DeviceBase.__init__(self, name)
+ self.read_interval = read_interval
+ self.prefix = prefix
+ self.bpm_x = Channel(prefix + ":X1", type = 'd', alias = name + " x")
+ self.bpm_y = Channel(prefix + ":Y1", type = 'd', alias = name + " y")
+ self.com_x_samples, self.com_y_samples = [], []
+ class ComX(Readable):
+ def read(self):
+ if len(self.image_stats.com_x_samples)==0: return None
+ return mean(self.image_stats.com_x_samples)
+ self.com_x_mean = ComX(); self.com_x_mean.image_stats = self
+ class ComY(Readable):
+ def read(self):
+ if len(self.image_stats.com_y_samples)==0: return None
+ return mean(self.image_stats.com_y_samples)
+ self.com_y_mean = ComY(); self.com_y_mean.image_stats = self
+ class ComXVar(Readable):
+ def read(self):
+ if len(self.image_stats.com_x_samples)==0: return None
+ return stdev(self.image_stats.com_x_samples)
+ self.com_x_stdev = ComXVar(); self.com_x_stdev.image_stats = self
+ class ComXVar(Readable):
+ def read(self):
+ if len(self.image_stats.com_y_samples)==0: return None
+ return stdev(self.image_stats.com_y_samples)
+ self.com_y_stdev = ComXVar(); self.com_y_stdev.image_stats = self
+ set_device_alias(self.com_x_mean, name + " x mean")
+ set_device_alias(self.com_y_mean, name + " y mean")
+ set_device_alias(self.com_x_stdev, name + " x stdev")
+ set_device_alias(self.com_y_stdev, name + " y stdev")
+ self.num_images = 1
+ self.initialize()
+
+
+ def doUpdate(self):
+ self.com_x_samples, self.com_y_samples = [], []
+ for i in range(self.num_images):
+ time.sleep(self.read_interval)
+ cx = self.bpm_x.read()
+ cy = self.bpm_y.read()
+ print "centroid ",[cx,cy]
+ self.com_x_samples.append(cx)
+ self.com_y_samples.append(cy)
+
+ def setNumberOfImages(self, value):
+ self.num_images = value
+
+ def enableBackground(self, value):
+ pass
+
+ def captureBackground(self, images):
+ pass
+
+ def doClose(self):
+ pass
+
+ def start(self):
+ pass
+
+ def stop(self):
+ pass
+
+
+
+if __name__ == "__builtin__":
+ add_device(BpmStats("bpm_com", "SINEG01-DBPM340"), True)
+ bpm_com.setNumberOfImages(5)
+ for i in range (10):
+ bpm_com.update()
+ print bpm_com.take(), bpm_com.com_x_mean.read(), bpm_com.com_y_mean.read()
+ time.sleep(1)
+
diff --git a/script/Devices/ImageStats.py b/script/Devices/ImageStats.py
new file mode 100644
index 0000000..bd33223
--- /dev/null
+++ b/script/Devices/ImageStats.py
@@ -0,0 +1,137 @@
+from startup import *
+from ijutils import *
+from ch.psi.pshell.imaging.Overlays import *
+import ch.psi.pshell.imaging.Pen as Pen
+import java.awt.Color as Color
+import random
+
+
+def get_centroid(source):
+ bi = source.getImage()
+ if bi is None:
+ return None
+ op = show_panel(bi, "Original")
+ ip = load_image(bi)
+ plot(get_histogram(ip), title = "Histogram")
+ grayscale(ip)
+ invert(ip)
+ gaussian_blur(ip)
+ auto_threshold(ip)
+
+ #binary_erode(ip)
+ show_panel(ip.getBufferedImage(), "Image")
+ (results,output_img)=analyse_particles(ip, 2000,20000, exclude_edges=False, print_table=True)
+ op.clearOverlays()
+ show_panel(output_img.getBufferedImage(), "Outlines")
+ if results.size()>0:
+ centroid = (results.getValue("XM",0), results.getValue("YM",0))
+ ov = Crosshairs(Pen(Color.ORANGE), java.awt.Point(int(centroid[0]),int(centroid[1])), java.awt.Dimension(15,15))
+ op.addOverlay(ov)
+ return centroid
+
+
+
+
+import ch.psi.pshell.imaging.Filter as Filter
+
+class SimulatedSource(Filter):
+ def process(self, img, data):
+ self.img=img
+ if img is None:
+ return None
+ ip = load_image(img)
+ pad_h = int((random.random()-0.5) * 500)
+ pad_v = int((random.random()-0.5) * 500)
+ #print "Pad = " , (pad_h, pad_v)
+ ip = pad_image(ip, -pad_h, pad_h, pad_v, -pad_v, fill_color = Color.BLACK)
+ return ip.getBufferedImage()
+ #return img
+
+ def waitNext(self, timeout):
+ self.pushImage(self.process(self.img, None))
+
+
+
+class ImageStats(DeviceBase):
+ def __init__(self, name, source):
+ DeviceBase.__init__(self, name)
+ self.source = source
+ self.com_x_samples, self.com_y_samples = [], []
+ class ComX(Readable):
+ def read(self):
+ if len(self.image_stats.com_x_samples)==0: return None
+ return mean(self.image_stats.com_x_samples)
+ self.com_x_mean = ComX(); self.com_x_mean.image_stats = self
+ class ComY(Readable):
+ def read(self):
+ if len(self.image_stats.com_y_samples)==0: return None
+ return mean(self.image_stats.com_y_samples)
+ self.com_y_mean = ComY(); self.com_y_mean.image_stats = self
+ class ComXVar(Readable):
+ def read(self):
+ if len(self.image_stats.com_x_samples)==0: return None
+ return stdev(self.image_stats.com_x_samples)
+ self.com_x_stdev = ComXVar(); self.com_x_stdev.image_stats = self
+ class ComXVar(Readable):
+ def read(self):
+ if len(self.image_stats.com_y_samples)==0: return None
+ return stdev(self.image_stats.com_y_samples)
+ self.com_y_stdev = ComXVar(); self.com_y_stdev.image_stats = self
+ set_device_alias(self.com_x_mean, name + " com x mean")
+ set_device_alias(self.com_y_mean, name + " com y mean")
+ set_device_alias(self.com_x_stdev, name + " com x stdev")
+ set_device_alias(self.com_y_stdev, name + " com y stdev")
+ self.bg_en = False
+ self.num_images = 1
+ self.initialize()
+
+
+ def doUpdate(self):
+ self.com_x_samples, self.com_y_samples = [], []
+ for i in range(self.num_images):
+ if type(self.source) is not ch.psi.pshell.imaging.FileSource:
+ self.source.waitNext(3000)
+ centroid = get_centroid(self.source)
+ print "cent ", centroid
+ if centroid is not None:
+ self.com_x_samples.append(centroid[0])
+ self.com_y_samples.append(centroid[1])
+
+ def setNumberOfImages(self, value):
+ self.num_images = value
+
+ def enableBackground(self, value):
+ self.bg_en = value
+
+ def captureBackground(self, images):
+ self.doInitialize()
+
+ def doClose(self):
+ pass
+
+ def start(self):
+ pass
+
+ def stop(self):
+ pass
+
+
+def get_simulated_source(img):
+ simulated_source = SimulatedSource()
+ simulated_source.img=None
+ simulated_source.initialize()
+ img.addListener(simulated_source)
+ show_panel(simulated_source)
+ return simulated_source
+
+if __name__ == "__builtin__":
+ simulated_source = get_simulated_source(image)
+ print get_centroid(simulated_source)
+
+ add_device(ImageStats("image_stats", simulated_source), True)
+ image_stats.enableBackground(False)
+ for i in range (10):
+ image_stats.update()
+ print image_stats.take(), image_stats.com_x_mean.read(), image_stats.com_y_mean.read()
+ time.sleep(1)
+