diff --git a/config/config.properties b/config/config.properties
index cb0b55c..93db32f 100644
--- a/config/config.properties
+++ b/config/config.properties
@@ -1,4 +1,4 @@
-#Mon Apr 19 14:03:50 CEST 2021
+#Thu Aug 26 11:06:44 CEST 2021
autoSaveScanData=true
simulation=false
logDaysToLive=7
@@ -27,7 +27,7 @@ serverEnabled=false
dataScanReleaseRecords=false
depthDimension=0
dataScanPreserveTypes=true
-logLevel=Fine
+logLevel=Info
dataScanFlushRecords=false
logPath={logs}/{date}_{time}
dataLayout=default
diff --git a/config/devices.properties b/config/devices.properties
new file mode 100644
index 0000000..a39e4cc
--- /dev/null
+++ b/config/devices.properties
@@ -0,0 +1,22 @@
+scienta=Scienta|X09LA-SCIENTA|||true
+current=ch.psi.pshell.epics.ChannelDouble|ARIDI-PCT:CURRENT 6|Read||true
+keithley10=ch.psi.pshell.epics.ChannelDouble|X09LA-KEI10:READOUT|Read||true
+keithley11=ch.psi.pshell.epics.ChannelDouble|X09LA-KEI11:READOUT|Read||true
+trx=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:TRX|||true
+try=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:TRY|||true
+trz=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:TRZ|||true
+phi=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:PHI|||true
+tht=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:THT|||true
+tlt=ch.psi.pshell.epics.Motor|X09LA-ES1-MA:TLT|||true
+manip=ch.psi.pshell.device.MotorGroupBase|trx try trz phi tht tlt|||true
+id_mode=ch.psi.pshell.epics.DiscretePositioner|X09LA-ID:MODE|||true
+id_status=ch.psi.pshell.epics.ChannelString|X09LA-ID:OFFS-MNTR|Read||true
+shutter=ch.psi.pshell.epics.DiscretePositioner|X09LA-SIS:OPEN|||true
+energy=ch.psi.pshell.epics.Positioner|X09LA-PHS:E_SP X09LA-PGM:rbkenergy|||true
+image=ch.psi.pshell.imaging.CameraSource|scienta|||true
+cam1=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.82/axis-cgi/mjpg/video.cgi?camera=1||-200|
+cam2=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.82/axis-cgi/mjpg/video.cgi?camera=2||-200|
+cam3=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.82/axis-cgi/mjpg/video.cgi?camera=3||-200|
+cam4=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.82/axis-cgi/mjpg/video.cgi?camera=4||-200|
+cam5=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.84/axis-cgi/mjpg/video.cgi||-200|
+cam6=ch.psi.pshell.imaging.MjpegSource|http://129.129.117.85/axis-cgi/mjpg/video.cgi||-200|
diff --git a/config/jcae.properties b/config/jcae.properties
new file mode 100644
index 0000000..8af012c
--- /dev/null
+++ b/config/jcae.properties
@@ -0,0 +1,12 @@
+#Fri Aug 27 09:00:46 CEST 2021
+ch.psi.jcae.ContextFactory.addressList=
+ch.psi.jcae.ContextFactory.serverPort=
+ch.psi.jcae.ContextFactory.maxArrayBytes=20000000
+ch.psi.jcae.ContextFactory.maxSendArrayBytes=10000000
+ch.psi.jcae.ChannelFactory.retries=2
+ch.psi.jcae.ChannelFactory.timeout=1500
+ch.psi.jcae.impl.DefaultChannelService.retries=1
+ch.psi.jcae.impl.DefaultChannelService.timeout=2000
+ch.psi.jcae.ContextFactory.autoAddressList=false
+ch.psi.jcae.ContextFactory.useShellVariables=true
+ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false
diff --git a/config/variables.properties b/config/variables.properties
index 82d0237..2cea9f8 100644
--- a/config/variables.properties
+++ b/config/variables.properties
@@ -1,2 +1,4 @@
-#Mon Apr 19 13:45:17 CEST 2021
-DaySequentialNumber=0
+#Mon Aug 30 18:03:14 CEST 2021
+LastRunDate=210830
+DaySequentialNumber=8
+FileSequentialNumber=10
diff --git a/devices/DummyEnergy.properties b/devices/DummyEnergy.properties
new file mode 100644
index 0000000..91a7a0f
--- /dev/null
+++ b/devices/DummyEnergy.properties
@@ -0,0 +1,10 @@
+#Mon Aug 30 16:57:31 CEST 2021
+minValue=NaN
+unit=null
+offset=0.0
+maxValue=NaN
+rotation=false
+precision=-1
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/Time.properties b/devices/Time.properties
new file mode 100644
index 0000000..c594351
--- /dev/null
+++ b/devices/Time.properties
@@ -0,0 +1,10 @@
+#Wed Apr 21 11:41:05 CEST 2021
+minValue=NaN
+unit=null
+offset=0.0
+maxValue=NaN
+rotation=false
+precision=-1
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/cam1.properties b/devices/cam1.properties
new file mode 100644
index 0000000..cdf4009
--- /dev/null
+++ b/devices/cam1.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:07:41 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/cam2.properties b/devices/cam2.properties
new file mode 100644
index 0000000..add9a51
--- /dev/null
+++ b/devices/cam2.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:09:37 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/cam3.properties b/devices/cam3.properties
new file mode 100644
index 0000000..add9a51
--- /dev/null
+++ b/devices/cam3.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:09:37 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/cam4.properties b/devices/cam4.properties
new file mode 100644
index 0000000..e8a01c5
--- /dev/null
+++ b/devices/cam4.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:15:02 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/cam5.properties b/devices/cam5.properties
new file mode 100644
index 0000000..cbb0771
--- /dev/null
+++ b/devices/cam5.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:18:30 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/cam6.properties b/devices/cam6.properties
new file mode 100644
index 0000000..cbb0771
--- /dev/null
+++ b/devices/cam6.properties
@@ -0,0 +1,20 @@
+#Wed Apr 21 10:18:30 CEST 2021
+spatialCalOffsetY=NaN
+invert=false
+spatialCalOffsetX=NaN
+rotation=0.0
+rotationCrop=false
+scale=1.0
+rescaleFactor=1.0
+grayscale=false
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+flipHorizontally=false
+roiY=0
+roiX=0
+rescaleOffset=0.0
+transpose=false
+roiWidth=-1
diff --git a/devices/dp1.properties b/devices/dp1.properties
new file mode 100644
index 0000000..76570b9
--- /dev/null
+++ b/devices/dp1.properties
@@ -0,0 +1,11 @@
+#Wed Apr 21 11:31:22 CEST 2021
+motor7=null
+motor8=null
+motor5=null
+motor6=null
+precision=-1
+positions=Park|Ready|Out|Clear
+motor3=null
+motor4=null
+motor1=0.0|4.0|8.0|0.0
+motor2=0.0|5.0|3.0|NaN
diff --git a/devices/energy.properties b/devices/energy.properties
new file mode 100644
index 0000000..e2a15e4
--- /dev/null
+++ b/devices/energy.properties
@@ -0,0 +1,10 @@
+#Wed Apr 21 09:48:12 CEST 2021
+offset=0.0
+maxValue=350.0
+rotation=false
+precision=3
+scale=1.0
+resolution=0.01
+minValue=19.5
+unit=eV
+sign_bit=0
diff --git a/devices/image.properties b/devices/image.properties
new file mode 100644
index 0000000..bf29fad
--- /dev/null
+++ b/devices/image.properties
@@ -0,0 +1,25 @@
+#Mon Aug 30 16:46:12 CEST 2021
+spatialCalOffsetY=NaN
+spatialCalOffsetX=NaN
+colormapLogarithmic=false
+scale=1.0
+grayscale=false
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+colormapMax=NaN
+rescaleOffset=0.0
+roiWidth=-1
+colormap=Grayscale
+invert=false
+colormapMin=NaN
+rotation=0.0
+rotationCrop=false
+rescaleFactor=1.0
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+flipHorizontally=false
+colormapAutomatic=true
+roiY=0
+roiX=0
+transpose=false
diff --git a/devices/m1.properties b/devices/m1.properties
new file mode 100644
index 0000000..fd1741f
--- /dev/null
+++ b/devices/m1.properties
@@ -0,0 +1,16 @@
+#Wed Apr 21 11:31:22 CEST 2021
+offset=0.0
+maxValue=10.0
+rotation=false
+precision=2
+scale=1.0
+estbilizationDelay=0
+maxSpeed=10.0
+resolution=NaN
+startRetries=1
+minValue=-10.0
+unit=mm
+defaultSpeed=1.0
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.1
diff --git a/devices/m2.properties b/devices/m2.properties
new file mode 100644
index 0000000..fd1741f
--- /dev/null
+++ b/devices/m2.properties
@@ -0,0 +1,16 @@
+#Wed Apr 21 11:31:22 CEST 2021
+offset=0.0
+maxValue=10.0
+rotation=false
+precision=2
+scale=1.0
+estbilizationDelay=0
+maxSpeed=10.0
+resolution=NaN
+startRetries=1
+minValue=-10.0
+unit=mm
+defaultSpeed=1.0
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.1
diff --git a/devices/p1.properties b/devices/p1.properties
new file mode 100644
index 0000000..a4b2c0c
--- /dev/null
+++ b/devices/p1.properties
@@ -0,0 +1,10 @@
+#Wed Apr 21 11:31:22 CEST 2021
+minValue=0.0
+unit=mm
+offset=0.0
+maxValue=1000.0
+rotation=false
+precision=-1
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/phi.properties b/devices/phi.properties
new file mode 100644
index 0000000..38150ad
--- /dev/null
+++ b/devices/phi.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:29 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.1
+minValue=-90.0
+defaultSpeed=17.0
+sign_bit=0
+monitorByPosition=false
+minSpeed=17.0
+offset=0.0
+maxValue=110.0
+rotation=false
+maxSpeed=20.0
+homingType=None
+startRetries=1
+unit=deg
+hasEnable=true
diff --git a/devices/scienta Theta Y step size.properties b/devices/scienta Theta Y step size.properties
new file mode 100644
index 0000000..a19ab0d
--- /dev/null
+++ b/devices/scienta Theta Y step size.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 11:34:39 CEST 2021
+minValue=NaN
+unit=
+offset=0.0
+maxValue=NaN
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta center Theta X.properties b/devices/scienta center Theta X.properties
new file mode 100644
index 0000000..cb39e62
--- /dev/null
+++ b/devices/scienta center Theta X.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 16:06:28 CEST 2021
+minValue=0.0
+unit=
+offset=0.0
+maxValue=0.0
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta center Theta Y.properties b/devices/scienta center Theta Y.properties
new file mode 100644
index 0000000..a19ab0d
--- /dev/null
+++ b/devices/scienta center Theta Y.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 11:34:39 CEST 2021
+minValue=NaN
+unit=
+offset=0.0
+maxValue=NaN
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta center energy.properties b/devices/scienta center energy.properties
new file mode 100644
index 0000000..1739b63
--- /dev/null
+++ b/devices/scienta center energy.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 10:57:12 CEST 2021
+minValue=0.0
+unit=
+offset=0.0
+maxValue=2000.0
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta excitation energy.properties b/devices/scienta excitation energy.properties
new file mode 100644
index 0000000..3f135c6
--- /dev/null
+++ b/devices/scienta excitation energy.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 12:16:20 CEST 2021
+minValue=0.0
+unit=
+offset=0.0
+maxValue=0.0
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta high Theta Y.properties b/devices/scienta high Theta Y.properties
new file mode 100644
index 0000000..a19ab0d
--- /dev/null
+++ b/devices/scienta high Theta Y.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 11:34:39 CEST 2021
+minValue=NaN
+unit=
+offset=0.0
+maxValue=NaN
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta high energy.properties b/devices/scienta high energy.properties
new file mode 100644
index 0000000..1739b63
--- /dev/null
+++ b/devices/scienta high energy.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 10:57:12 CEST 2021
+minValue=0.0
+unit=
+offset=0.0
+maxValue=2000.0
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta low Theta Y.properties b/devices/scienta low Theta Y.properties
new file mode 100644
index 0000000..a19ab0d
--- /dev/null
+++ b/devices/scienta low Theta Y.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 11:34:39 CEST 2021
+minValue=NaN
+unit=
+offset=0.0
+maxValue=NaN
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta low energy.properties b/devices/scienta low energy.properties
new file mode 100644
index 0000000..1739b63
--- /dev/null
+++ b/devices/scienta low energy.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 10:57:12 CEST 2021
+minValue=0.0
+unit=
+offset=0.0
+maxValue=2000.0
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/scienta step size.properties b/devices/scienta step size.properties
new file mode 100644
index 0000000..a33ca1b
--- /dev/null
+++ b/devices/scienta step size.properties
@@ -0,0 +1,9 @@
+#Mon Aug 30 10:16:07 CEST 2021
+minValue=NaN
+unit=
+offset=0.0
+maxValue=NaN
+precision=3
+sign_bit=0
+scale=1.0
+resolution=NaN
diff --git a/devices/src1.properties b/devices/src1.properties
new file mode 100644
index 0000000..18fa36d
--- /dev/null
+++ b/devices/src1.properties
@@ -0,0 +1,25 @@
+#Wed Apr 21 13:36:49 CEST 2021
+spatialCalOffsetY=NaN
+spatialCalOffsetX=NaN
+colormapLogarithmic=false
+scale=1.0
+grayscale=false
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+colormapMax=NaN
+rescaleOffset=0.0
+roiWidth=-1
+colormap=Temperature
+invert=false
+colormapMin=NaN
+rotation=0.0
+rotationCrop=false
+rescaleFactor=1.0
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+flipHorizontally=false
+colormapAutomatic=true
+roiY=0
+roiX=0
+transpose=false
diff --git a/devices/src2.properties b/devices/src2.properties
new file mode 100644
index 0000000..2e63610
--- /dev/null
+++ b/devices/src2.properties
@@ -0,0 +1,25 @@
+#Wed Apr 21 13:36:49 CEST 2021
+spatialCalOffsetY=NaN
+spatialCalOffsetX=NaN
+colormapLogarithmic=false
+scale=1.0
+grayscale=false
+spatialCalScaleX=NaN
+spatialCalScaleY=NaN
+colormapMax=NaN
+rescaleOffset=0.0
+roiWidth=-1
+colormap=Grayscale
+invert=false
+colormapMin=NaN
+rotation=0.0
+rotationCrop=false
+rescaleFactor=1.0
+spatialCalUnits=mm
+flipVertically=false
+roiHeight=-1
+flipHorizontally=false
+colormapAutomatic=true
+roiY=0
+roiX=0
+transpose=false
diff --git a/devices/tht.properties b/devices/tht.properties
new file mode 100644
index 0000000..05d4ff3
--- /dev/null
+++ b/devices/tht.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:36 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.05
+minValue=-95.0
+defaultSpeed=2.5
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.5
+offset=0.0
+maxValue=185.0
+rotation=false
+maxSpeed=5.0
+homingType=None
+startRetries=1
+unit=deg
+hasEnable=true
diff --git a/devices/tlt.properties b/devices/tlt.properties
new file mode 100644
index 0000000..412c3a4
--- /dev/null
+++ b/devices/tlt.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:40 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.1
+minValue=-100.0
+defaultSpeed=20.0
+sign_bit=0
+monitorByPosition=false
+minSpeed=17.0
+offset=0.0
+maxValue=100.0
+rotation=false
+maxSpeed=20.0
+homingType=None
+startRetries=1
+unit=deg
+hasEnable=true
diff --git a/devices/trx.properties b/devices/trx.properties
new file mode 100644
index 0000000..b3fe9d4
--- /dev/null
+++ b/devices/trx.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:04 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.005
+minValue=-7.0
+defaultSpeed=0.8
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.6
+offset=0.0
+maxValue=7.0
+rotation=false
+maxSpeed=5.0
+homingType=None
+startRetries=1
+unit=mm
+hasEnable=true
diff --git a/devices/try.properties b/devices/try.properties
new file mode 100644
index 0000000..b020c24
--- /dev/null
+++ b/devices/try.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:10 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.005
+minValue=-6.8896
+defaultSpeed=0.8
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.6
+offset=0.0
+maxValue=2.7204000000000006
+rotation=false
+maxSpeed=5.0
+homingType=None
+startRetries=1
+unit=mm
+hasEnable=true
diff --git a/devices/trz.properties b/devices/trz.properties
new file mode 100644
index 0000000..aed917c
--- /dev/null
+++ b/devices/trz.properties
@@ -0,0 +1,18 @@
+#Wed Apr 21 09:23:23 CEST 2021
+precision=4
+scale=1.0
+estbilizationDelay=0
+resolution=0.005
+minValue=-10.0
+defaultSpeed=2.0
+sign_bit=0
+monitorByPosition=false
+minSpeed=0.5
+offset=0.0
+maxValue=600.0
+rotation=false
+maxSpeed=8.0
+homingType=None
+startRetries=1
+unit=mm
+hasEnable=true
diff --git a/plugins/EnergyScan.form b/plugins/EnergyScan.form
new file mode 100644
index 0000000..7886cd9
--- /dev/null
+++ b/plugins/EnergyScan.form
@@ -0,0 +1,293 @@
+
+
+
diff --git a/plugins/EnergyScan.java b/plugins/EnergyScan.java
new file mode 100644
index 0000000..e244864
--- /dev/null
+++ b/plugins/EnergyScan.java
@@ -0,0 +1,522 @@
+
+import ch.psi.pshell.core.JsonSerializer;
+import ch.psi.pshell.epics.Positioner;
+import ch.psi.pshell.ui.PanelProcessor;
+import ch.psi.utils.IO;
+import ch.psi.utils.State;
+import ch.psi.utils.swing.SwingUtils;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ *
+ */
+public class EnergyScan extends PanelProcessor {
+
+ final DefaultTableModel model;
+ Positioner energy;
+ File currentFile;
+ public static final String FILE_EXTENSION = "ens";
+
+ public EnergyScan() {
+ initComponents();
+ model = (DefaultTableModel) table.getModel();
+ }
+
+ @Override
+ public String getType() {
+ return "Energy Scan";
+ }
+
+ @Override
+ public boolean createMenuNew() {
+ return true;
+ }
+
+ @Override
+ public boolean createFilePanel() {
+ return true;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Energy scan definition file (*." + FILE_EXTENSION + ")";
+ }
+
+ @Override
+ public String[] getExtensions() {
+ return new String[]{FILE_EXTENSION};
+ }
+
+ @Override
+ public String getHomePath() {
+ return "{home}/parameters";
+ }
+
+ //Overridable callbacks
+ @Override
+ public void onInitialize(int runCount) {
+ energy = (Positioner) getDevice("energy");
+ }
+
+ @Override
+ public void onStateChange(State state, State former) {
+ buttonStart.setEnabled(state == State.Ready);
+ buttonAbort.setEnabled(state.isProcessing());
+ buttonScienta.setEnabled(state.isInitialized());
+ updateSeq();
+ }
+
+ void updateSeq() {
+ try {
+ textFileId.setText(String.valueOf(getContext().getFileSequentialNumber()));
+ } catch (Exception ex) {
+ textFileId.setText("");
+ }
+ }
+
+ @Override
+ public void onExecutedFile(String fileName, Object result) {
+ }
+
+ //Callback to perform update - in event thread
+ @Override
+ protected void doUpdate() {
+ }
+
+ void checkValues() {
+ if (model.getRowCount() == 0) {
+ throw new IllegalArgumentException();
+ }
+ Positioner energy = (Positioner) getDevice("energy");
+ for (int i = 0; i < model.getRowCount(); i++) {
+ Double start = (Double) model.getValueAt(i, 0);
+ Double stop = (Double) model.getValueAt(i, 1);
+ Double step = (Double) model.getValueAt(i, 2);
+ if (Double.isNaN(start) || Double.isNaN(stop) || Double.isNaN(step)
+ || (start >= stop) || (step < 0)
+ || (start < energy.getMinValue())
+ || (stop > energy.getMaxValue())) {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+
+ String getScanName() {
+ String name = textName.getText().trim();
+ return name.isEmpty() ? null : name;
+ }
+
+ @Override
+ public void execute() throws Exception {
+ checkValues();
+ String lastOutput = getContext().getDataManager().getLastOutput();
+
+ HashMap args = new HashMap();
+ ArrayList regions = new ArrayList();
+ for (int i = 0; i < model.getRowCount(); i++) {
+ ArrayList region = new ArrayList();
+ region.add(model.getValueAt(i, 0));
+ region.add(model.getValueAt(i, 1));
+ region.add(model.getValueAt(i, 2));
+ regions.add(region);
+ }
+ args.put("FILE", null);
+ args.put("NAME", getScanName());
+ args.put("REGIONS", regions);
+ this.runAsync("templates/EnergyScan", args).handle((ret, ex) -> {
+ if (ex != null) {
+ }
+ if (checkAutoSaveArgs.isSelected()) {
+ //Save scan attributes
+ String output = getContext().getDataManager().getLastOutput();
+ if ((output != null) && !output.isEmpty() && !output.equals(lastOutput)) {
+ try {
+ saveAs(output + "." + FILE_EXTENSION);
+ } catch (IOException e) {
+ Logger.getLogger(EnergyScan.class.getName()).log(Level.WARNING, null, e);
+ }
+ }
+ }
+ return ret;
+ });
+ }
+
+ @Override
+ public void saveAs(String fileName) throws IOException {
+ currentFile = new File(fileName);
+ ArrayList data = new ArrayList();
+ data.add(new Object[][]{new Object[]{textName.getText()}});
+ data.add(model.getDataVector());
+ String json = JsonSerializer.encode(data, true);
+ Files.write(currentFile.toPath(), json.getBytes());
+ }
+
+ @Override
+ public void open(String fileName) throws IOException {
+ if (fileName==null){
+ currentFile = null;
+ textName.setText("");
+ model.setRowCount(0);
+ } else {
+ Path path = Paths.get(fileName);
+ String json = new String(Files.readAllBytes(path));
+ currentFile = path.toFile();
+ Object[][][] vector = (Object[][][]) JsonSerializer.decode(json, Object[][][].class);
+ textName.setText(String.valueOf(vector[0][0][0]));
+ model.setDataVector(vector[1], SwingUtils.getTableColumnNames(table));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane2 = new javax.swing.JScrollPane();
+ jEditorPane1 = new javax.swing.JEditorPane();
+ buttonStart = new javax.swing.JButton();
+ buttonAbort = new javax.swing.JButton();
+ checkAutoSaveArgs = new javax.swing.JCheckBox();
+ buttonScienta = new javax.swing.JButton();
+ jPanel2 = new javax.swing.JPanel();
+ textName = new javax.swing.JTextField();
+ jPanel1 = new javax.swing.JPanel();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ table = new javax.swing.JTable();
+ buttonAdd = new javax.swing.JButton();
+ buttonDelete = new javax.swing.JButton();
+ jLabel1 = new javax.swing.JLabel();
+ buttonOpen = new javax.swing.JButton();
+ buttonSave = new javax.swing.JButton();
+ jLabel2 = new javax.swing.JLabel();
+ textFileId = new javax.swing.JTextField();
+ buttonResetId = new javax.swing.JButton();
+
+ jScrollPane2.setViewportView(jEditorPane1);
+
+ buttonStart.setText("Start");
+ buttonStart.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonStartActionPerformed(evt);
+ }
+ });
+
+ buttonAbort.setText("Abort");
+ buttonAbort.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonAbortActionPerformed(evt);
+ }
+ });
+
+ checkAutoSaveArgs.setText("Auto save parameters");
+
+ buttonScienta.setText("Scienta Panel");
+ buttonScienta.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonScientaActionPerformed(evt);
+ }
+ });
+
+ jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Parameters"));
+
+ jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Regions"));
+
+ table.setModel(new javax.swing.table.DefaultTableModel(
+ new Object [][] {
+
+ },
+ new String [] {
+ "Start", "End", "Step"
+ }
+ ) {
+ Class[] types = new Class [] {
+ java.lang.Double.class, java.lang.Double.class, java.lang.Double.class
+ };
+
+ public Class getColumnClass(int columnIndex) {
+ return types [columnIndex];
+ }
+ });
+ jScrollPane1.setViewportView(table);
+
+ buttonAdd.setText("Add");
+ buttonAdd.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonAddActionPerformed(evt);
+ }
+ });
+
+ buttonDelete.setText("Delete");
+ buttonDelete.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonDeleteActionPerformed(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(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addComponent(buttonAdd)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonDelete)
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+
+ jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonAdd, buttonDelete});
+
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 103, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(buttonAdd)
+ .addComponent(buttonDelete))
+ .addContainerGap())
+ );
+
+ jLabel1.setText("Name:");
+
+ buttonOpen.setText("Open");
+ buttonOpen.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonOpenActionPerformed(evt);
+ }
+ });
+
+ buttonSave.setText("Save");
+ buttonSave.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonSaveActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+ jPanel2.setLayout(jPanel2Layout);
+ jPanel2Layout.setHorizontalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(textName)
+ .addGap(18, 18, 18)
+ .addComponent(buttonOpen)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(buttonSave)))
+ .addContainerGap())
+ );
+ jPanel2Layout.setVerticalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(textName)
+ .addComponent(buttonOpen)
+ .addComponent(buttonSave)
+ .addComponent(jLabel1))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(12, 12, 12))
+ );
+
+ jLabel2.setText("File ID:");
+
+ textFileId.setEditable(false);
+ textFileId.setHorizontalAlignment(javax.swing.JTextField.CENTER);
+
+ buttonResetId.setText("Reset");
+ buttonResetId.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ buttonResetIdActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(buttonStart, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(33, 33, 33)
+ .addComponent(buttonAbort)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(checkAutoSaveArgs)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jLabel2)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(textFileId, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(buttonScienta)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonResetId)))
+ .addContainerGap())))
+ );
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonAbort, buttonStart});
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonResetId, textFileId});
+
+ layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonScienta, checkAutoSaveArgs});
+
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(7, 7, 7)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(checkAutoSaveArgs)
+ .addComponent(jLabel2)
+ .addComponent(textFileId, 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(buttonScienta)
+ .addComponent(buttonResetId))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(buttonStart)
+ .addComponent(buttonAbort))
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed
+ try {
+ execute();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonStartActionPerformed
+
+ private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed
+ try {
+ abort();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonAbortActionPerformed
+
+ private void buttonAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAddActionPerformed
+ try {
+ //model.addRow(new Object[]{energy.getMinValue(), energy.getMaxValue(), 10.0});
+ model.addRow(new Object[]{500.0, 1000.0, 100.0});
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonAddActionPerformed
+
+ private void buttonDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDeleteActionPerformed
+ try {
+ if ((model.getRowCount() > 0) && (table.getSelectedRow() >= 0)) {
+ model.removeRow(table.getSelectedRow());
+ }
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonDeleteActionPerformed
+
+ private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed
+ try {
+ open();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonOpenActionPerformed
+
+ private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed
+ try {
+ JFileChooser chooser = new JFileChooser(getContext().getSetup().expandPath(getHomePath()));
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(getDescription(), getExtensions());
+ chooser.setFileFilter(filter);
+ try {
+ if (currentFile != null) {
+ chooser.setSelectedFile(currentFile);
+ } else if (getScanName() != null) {
+ File file = Paths.get(chooser.getCurrentDirectory().getAbsolutePath(), getScanName()).toFile();
+ chooser.setSelectedFile(file);
+ }
+ } catch (Exception ex) {
+ this.showException(ex);
+ }
+ int rVal = chooser.showSaveDialog(this);
+ if (rVal == JFileChooser.APPROVE_OPTION) {
+ String fileName = chooser.getSelectedFile().getAbsolutePath();
+ if (IO.getExtension(chooser.getSelectedFile().getAbsolutePath()).isEmpty()) {
+ fileName += "." + FILE_EXTENSION;
+ }
+ saveAs(fileName);
+ }
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonSaveActionPerformed
+
+ private void buttonScientaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScientaActionPerformed
+ try {
+ this.showDevicePanel("scienta");
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonScientaActionPerformed
+
+ private void buttonResetIdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResetIdActionPerformed
+ try {
+ this.getContext().setFileSequentialNumber(0);
+ updateSeq();
+ } catch (Exception ex) {
+ showException(ex);
+ }
+ }//GEN-LAST:event_buttonResetIdActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton buttonAbort;
+ private javax.swing.JButton buttonAdd;
+ private javax.swing.JButton buttonDelete;
+ private javax.swing.JButton buttonOpen;
+ private javax.swing.JButton buttonResetId;
+ private javax.swing.JButton buttonSave;
+ private javax.swing.JButton buttonScienta;
+ private javax.swing.JButton buttonStart;
+ private javax.swing.JCheckBox checkAutoSaveArgs;
+ private javax.swing.JEditorPane jEditorPane1;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPanel jPanel2;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JTable table;
+ private javax.swing.JTextField textFileId;
+ private javax.swing.JTextField textName;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/plugins/NewJPanel.form b/plugins/NewJPanel.form
new file mode 100644
index 0000000..c638b68
--- /dev/null
+++ b/plugins/NewJPanel.form
@@ -0,0 +1,28 @@
+
+
+
diff --git a/plugins/NewJPanel.java b/plugins/NewJPanel.java
new file mode 100644
index 0000000..d05e096
--- /dev/null
+++ b/plugins/NewJPanel.java
@@ -0,0 +1,44 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ *
+ * @author gac-x09la
+ */
+public class NewJPanel extends javax.swing.JPanel {
+
+ /**
+ * Creates new form NewJPanel
+ */
+ public NewJPanel() {
+ initComponents();
+ }
+
+ /**
+ * 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() {
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 400, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 300, Short.MAX_VALUE)
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/script/local.py b/script/local.py
index 9dc8b0d..e169993 100644
--- a/script/local.py
+++ b/script/local.py
@@ -2,3 +2,179 @@
# Deployment specific global definitions - executed after startup.py
###################################################################################################
+
+
+###################################################################################################
+# Device initialization
+###################################################################################################
+
+
+#scienta.getDataArray().setMonitored(True)
+
+class AcquisitionMode(Readable.ReadableString):
+ def read(self):
+ return str(scienta.getAcquisitionMode())
+_acquisition_mode=AcquisitionMode()
+
+class EnergyMode(Readable.ReadableString):
+ def read(self):
+ return str(scienta.getEnergyMode())
+_energy_mode=EnergyMode()
+
+class LensMode(Readable.ReadableString):
+ def read(self):
+ return str(scienta.getLensMode())
+_lens_mode=LensMode()
+
+class DetectorMode(Readable.ReadableString):
+ def read(self):
+ return str(scienta.getDetectorMode())
+_detector_mode=DetectorMode()
+
+class PassEnergy(Readable):
+ def read(self):
+ return scienta.getPassEnergy()
+_pass_energy=PassEnergy()
+
+class ElementSet(Readable.ReadableString):
+ def read(self):
+ return str(scienta.getElementSet())
+_element_set=ElementSet()
+
+
+###################################################################################################
+# Handlig diagnostics
+###################################################################################################
+
+diag_channels = []
+
+diag_channels.append(scienta.lowEnergy.readback)
+diag_channels.append(scienta.centerEnergy.readback)
+diag_channels.append(scienta.highEnergy.readback)
+diag_channels.append(scienta.energyStepSize.readback)
+diag_channels.append(scienta.energyWidth)
+diag_channels.append(scienta.energyCount)
+diag_channels.append(scienta.lowThetaY.readback)
+diag_channels.append(scienta.centerThetaY.readback)
+diag_channels.append(scienta.highThetaY.readback)
+diag_channels.append(scienta.thetaYStepSize.readback)
+diag_channels.append(scienta.thetaYWidth)
+diag_channels.append(scienta.thetaYCount)
+diag_channels.append(scienta.lowThetaX)
+diag_channels.append(scienta.centerThetaX.readback)
+diag_channels.append(scienta.highThetaX)
+diag_channels.append(scienta.thetaXStepSize)
+diag_channels.append(scienta.thetaXWidth)
+diag_channels.append(scienta.thetaXCount)
+diag_channels.append(scienta.slicesReadback)
+diag_channels.append(scienta.channelsReadback)
+diag_channels.append(scienta.excitationEnergy)
+
+diag_channels.append(_acquisition_mode)
+diag_channels.append(_energy_mode)
+diag_channels.append(_lens_mode)
+diag_channels.append(_detector_mode)
+diag_channels.append(_pass_energy)
+diag_channels.append(_element_set)
+
+
+diag_channels = sorted(diag_channels, key=lambda channel: channel.name)
+
+def get_diag_name(diag):
+ return ch.psi.utils.Str.toTitleCase(diag.getName()).replace(" ", "").replace("Readback", "")
+
+def print_diag():
+ for f in diag_channels:
+ print "%-25s %s" % (get_diag_name(f) , str(f.read()))
+
+def create_diag_datasets(parent = None):
+ if parent is None:
+ parent = get_exec_pars().group
+ group = parent + "attrs/"
+ for f in diag_channels:
+ create_dataset(group+get_diag_name(f) , 's' if (issubclass(type(f), Readable.ReadableString)) else 'd')
+
+def append_diag_datasets(parent = None):
+ if parent is None:
+ parent = get_exec_pars().group
+ group = parent + "attrs/"
+ for f in diag_channels:
+ try:
+ x = f.read()
+ if x is None:
+ x = '' if (type(f) is ch.psi.pshell.epics.ChannelString) else float('nan')
+ append_dataset(group+get_diag_name(f), x)
+ except:
+ log("Error sampling " + str(get_diag_name(f)) + ": " + str(sys.exc_info()[1]))
+
+
+def handle_diagnostics(rec):
+ #if beam_ok:
+ if get_exec_pars().save:
+ #Saving only once the diag data
+ if rec.index == 0:
+ create_diag_datasets()
+ append_diag_datasets()
+
+
+
+def trigger_scienta():
+ """
+ Trigger new acquisition
+ """
+ scienta.start()
+ scienta.waitNewImage(-1)
+
+
+def dummy_trigger_scienta():
+ """
+ Trigger detector to update the array sizes and calibration
+ """
+ iterations = scienta.getIterations()
+ scienta.setIterations(1)
+ try:
+ trigger_scienta()
+ finally:
+ scienta.setIterations(iterations)
+
+
+###################################################################################################
+# Utilities
+###################################################################################################
+
+def fit(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)
diff --git a/script/queues/test.que b/script/queues/test.que
new file mode 100644
index 0000000..117ac67
--- /dev/null
+++ b/script/queues/test.que
@@ -0,0 +1 @@
+[ [ [ true, "/sls/X09LA/data/X09LA/pshell/home/parameters/Test1.ens", "", "Resume", "" ], [ true, "templates/EnergyScan.py", "\"FILE\":\"\", \"REGIONS\":[[523.0,527.0,2.0],[527.0,535.0,4.0],[535.0,558.0,2.0]], \"NAME\":\"tst\"", "Resume", "" ] ] ]
\ No newline at end of file
diff --git a/script/templates/EnergyScan.py b/script/templates/EnergyScan.py
new file mode 100644
index 0000000..131ecec
--- /dev/null
+++ b/script/templates/EnergyScan.py
@@ -0,0 +1,43 @@
+if get_exec_pars().debug:
+ print "Setting debug parameters"
+ REGIONS = [[523.0, 527.0, 2.0], [527.0, 535.0, 4.0], [535.0, 558.0, 2.0]]
+ NAME = None
+ FILE = None
+
+if FILE:
+ FILE = get_context().setup.expandPath("{home}/parameters/" + FILE)
+ import json
+ with open(FILE) as json_file:
+ cfg = json.load(json_file)
+ NAME , REGIONS= cfg[0][0][0], cfg[1]
+ print "FILE: ", FILE
+print "NAME: ", NAME
+print "REGIONS: ", REGIONS
+
+IOC_AUTO_SAVE = False
+DUMMY_TRIGGER = True #Trigger detector to update the array sizes and calibration
+
+set_device_alias(scienta.getSpectrum(), "spectrum")
+set_device_alias(scienta.getDataMatrix(), "image")
+set_device_alias(scienta.stats[0], "sum")
+
+sensors=[i0, scienta.stats[0], scienta.getSpectrum()] #), scienta.getDataMatrix()]
+
+def trigger(position, scan):
+ scienta.start()
+ scienta.waitNewImage(-1)
+
+
+if DUMMY_TRIGGER:
+ trigger(None, None)
+
+
+if IOC_AUTO_SAVE:
+ capture.write(1)
+
+try:
+ rscan(energy, sensors, REGIONS, latency = 0.0, before_read=trigger, after_read=after_readout, name = NAME)
+finally:
+ if IOC_AUTO_SAVE:
+ capture.write(0)
+ scienta.zeroSupplies()
diff --git a/script/test/TestScan.py b/script/test/TestScan.py
new file mode 100644
index 0000000..e0cfe61
--- /dev/null
+++ b/script/test/TestScan.py
@@ -0,0 +1,13 @@
+
+en = DummyPositioner("DummyEnergy")
+add_device(en, True)
+
+set_device_alias(scienta.getDataMatrix(), "image")
+set_device_alias(scienta.stats[0], "sum")
+
+sensors=[current, scienta.stats[0], scienta.getDataMatrix()]
+
+try:
+ lscan(en, sensors, 0, 10, 4, latency = 0.0, before_read=trigger_scienta, after_read=handle_diagnostics, save=True)
+finally:
+ scienta.zeroSupplies()