Initial commit

This commit is contained in:
Gobbo Alexandre
2022-01-17 17:06:13 +01:00
commit e026811933
50 changed files with 13279 additions and 0 deletions

15
bin/psss_panel Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
/opt/gfa/pshell/pshell \
-version=v1_17 \
-py3 \
-m=/opt/gfa/pshell/apps/psss_panel \
-z \
-nbcf=true \
-laf=dark \
-d \
-pini=true \
-clog=WARNING \
-sbar \
$@

13
bin/psss_panel_editor Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
/opt/gfa/pshell/pshell \
-py3 \
-version=v1_17 \
-z \
-nbcf=true \
-laf=dark \
-pini=true \
-setp=/opt/gfa/pshell/apps/psss_panel/config/setup.properties \
-p=PSSS.java \
$@

16
config/devices.properties Executable file
View File

@@ -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

12
config/jcae.properties Executable file
View File

@@ -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

23
config/setup.properties Normal file
View File

@@ -0,0 +1,23 @@
#Tue Jul 06 13:13:12 CEST 2021
scriptPath=/opt/gfa/pshell/apps/psss_panel/script
sessionsPath={outp}/sessions
pluginsPath=/opt/gfa/pshell/apps/psss_panel/plugins
configFileDevices=/opt/gfa/pshell/apps/psss_panel/config/devices.properties
consoleSessionsPath={sessions}/console
libraryPath={script}; {script}/Lib
contextPath={outp}/context
configFilePlugins={config}/plugins.properties
extensionsPath={home}/extensions
configPath={home}/config
configFileSessions={config}/sessions.properties
userSessionsPath={sessions}/user
dataPath={outp}/data
devicesPath=/opt/gfa/pshell/apps/psss_panel/devices
configFileVariables={config}/variables.properties
configFileSettings={config}/settings.properties
wwwPath={home}/www
logPath={outp}/log
imagesPath={outp}/images
configFile={config}/config.properties
scriptType=py
configFileTasks={config}/tasks.properties

25
devices/cam_server.properties Executable file
View File

@@ -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

13
devices/dispatcher.properties Executable file
View File

@@ -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

View File

@@ -0,0 +1,6 @@
#Tue Jun 15 11:03:15 CEST 2021
bins=1000
min=11400.0
max=11200.0
precision=-1
numberOfSamples=10000

6
devices/histo_fwhm.properties Executable file
View File

@@ -0,0 +1,6 @@
#Fri Apr 30 07:45:13 CEST 2021
bins=1000
min=0.0
max=40.0
precision=-1
numberOfSamples=10000

View File

@@ -0,0 +1,4 @@
#Mon May 03 09:21:35 CEST 2021
measures=10
precision=-1
interval=-1

View File

@@ -0,0 +1,4 @@
#Mon May 03 09:21:52 CEST 2021
measures=10
precision=-1
interval=-1

View File

@@ -0,0 +1,5 @@
#Mon May 03 09:15:04 CEST 2021
measures=10
precision=-1
interval=-1
integrate=false

73
nb/PSSS/build.xml Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="PSSS" default="default" basedir=".">
<description>Builds, tests, and runs the project PSSS.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="PSSS-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
build.xml.data.CRC32=cb48e78e
build.xml.script.CRC32=f58963e5
build.xml.stylesheet.CRC32=f85dc8f2@1.97.0.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=cb48e78e
nbproject/build-impl.xml.script.CRC32=1f638965
nbproject/build-impl.xml.stylesheet.CRC32=d549e5cc@1.97.0.48

View File

@@ -0,0 +1,8 @@
compile.on.save=true
do.depend=false
do.jar=true
do.jlink=false
javac.debug=true
javadoc.preview=true
jlink.strip=false
user.properties.file=/afs/psi.ch/user/g/gobbo_a/.netbeans/12.2/build.properties

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
</project-private>

View File

@@ -0,0 +1,99 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=PSSS
application.vendor=gobbo_a
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.modulepath=\
${run.modulepath}
debug.test.classpath=\
${run.test.classpath}
debug.test.modulepath=\
${run.test.modulepath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/PSSS.jar
dist.javadoc.dir=${dist.dir}/javadoc
dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/PSSS
endorsed.classpath=
excludes=
file.reference.pshell-latest.jar=../../../../head/pshell-latest.jar
file.reference.psss_panel-plugins=../../plugins
file.reference.psss_panel-script=../../script
includes=**/*.java
jar.compress=false
javac.classpath=\
${file.reference.pshell-latest.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.external.vm=true
javac.modulepath=
javac.processormodulepath=
javac.processorpath=\
${javac.classpath}
javac.source=11
javac.target=11
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.modulepath=\
${javac.modulepath}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.html5=false
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
# The jlink additional root modules to resolve
jlink.additionalmodules=
# The jlink additional command line parameters
jlink.additionalparam=
jlink.launcher=true
jlink.launcher.name=PSSS
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=true
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.modulepath=\
${javac.modulepath}
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
run.test.modulepath=\
${javac.test.modulepath}
source.encoding=UTF-8
src.plugins.dir=${file.reference.psss_panel-plugins}
src.script.dir=${file.reference.psss_panel-script}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>PSSS</name>
<source-roots>
<root id="src.plugins.dir" name="Plugins"/>
<root id="src.script.dir" name="Scripts"/>
</source-roots>
<test-roots/>
</data>
</configuration>
</project>

BIN
plugins/PSSS$1.class Normal file

Binary file not shown.

BIN
plugins/PSSS$2.class Normal file

Binary file not shown.

BIN
plugins/PSSS$3.class Normal file

Binary file not shown.

BIN
plugins/PSSS$4.class Normal file

Binary file not shown.

BIN
plugins/PSSS$5.class Normal file

Binary file not shown.

BIN
plugins/PSSS$6.class Normal file

Binary file not shown.

BIN
plugins/PSSS$7.class Normal file

Binary file not shown.

BIN
plugins/PSSS$8.class Normal file

Binary file not shown.

BIN
plugins/PSSS$9.class Normal file

Binary file not shown.

BIN
plugins/PSSS.class Normal file

Binary file not shown.

715
plugins/PSSS.form Executable file
View File

@@ -0,0 +1,715 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tab" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tab" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JTabbedPane" name="tab">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabStateChanged"/>
</Events>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Spectrum">
<Property name="tabTitle" type="java.lang.String" value="Spectrum"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spinnerAverage" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="history" alignment="0" pref="453" max="32767" attributes="0"/>
<Component id="plot" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="12" pref="12" max="-2" attributes="0"/>
<Component id="histogramGeneratorFwhm" min="-2" pref="372" max="-2" attributes="0"/>
</Group>
<Component id="histogramGeneratorPanelCenter" alignment="0" min="-2" pref="372" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spinnerAverage" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="histogramGeneratorPanelCenter" alignment="0" pref="194" max="32767" attributes="0"/>
<Component id="plot" alignment="0" pref="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="history" pref="194" max="32767" attributes="0"/>
<Component id="histogramGeneratorFwhm" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="ch.psi.pshell.plot.LinePlotJFree" name="plot">
<Properties>
<Property name="title" type="java.lang.String" value=""/>
</Properties>
</Component>
<Component class="ch.psi.pshell.plot.TimePlotJFree" name="history">
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value="Average:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spinnerAverage">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="1" maximum="100" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerAverageStateChanged"/>
</Events>
</Component>
<Component class="ch.psi.pshell.swing.HistogramGeneratorPanel" name="histogramGeneratorPanelCenter">
<Properties>
<Property name="deviceName" type="java.lang.String" value="histo_center"/>
</Properties>
</Component>
<Component class="ch.psi.pshell.swing.HistogramGeneratorPanel" name="histogramGeneratorFwhm">
<Properties>
<Property name="deviceName" type="java.lang.String" value="histo_fwhm"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel4">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Camera">
<Property name="tabTitle" type="java.lang.String" value="Camera"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="843" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="renderer" alignment="0" pref="843" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="432" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Component id="renderer" alignment="0" pref="432" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="ch.psi.pshell.imaging.Renderer" name="renderer">
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel3">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
<JTabbedPaneConstraints tabName="Alignment">
<Property name="tabTitle" type="java.lang.String" value="Alignment"/>
</JTabbedPaneConstraints>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jPanel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="plotScan" pref="614" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel2" max="32767" attributes="0"/>
<Component id="plotScan" pref="432" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jPanel5" alignment="0" max="32767" attributes="0"/>
<Component id="radioCrystalScan" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="radioCameraScan" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="radioEnergyScan" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="btAbort" alignment="0" pref="213" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
<Component id="radioEnergyScan" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="radioCameraScan" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="radioCrystalScan" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jPanel5" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="btAbort" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btAbort">
<Properties>
<Property name="text" type="java.lang.String" value="Abort"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btAbortActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="radioEnergyScan">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup1"/>
</Property>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Energy Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="radioEnergyScanActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="radioCameraScan">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup1"/>
</Property>
<Property name="text" type="java.lang.String" value="Camera Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="radioCameraScanActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="radioCrystalScan">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup1"/>
</Property>
<Property name="text" type="java.lang.String" value="Crystal Height Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="radioCrystalScanActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JPanel" name="jPanel5">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="panelScan" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="panelScan" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelScan">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="panelEnergyScan">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="energy"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel7" linkSize="7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spToEn" linkSize="8" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel6" linkSize="7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spFromEn" linkSize="8" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel8" linkSize="7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spStepsEn" linkSize="8" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel9" linkSize="7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spShotsEn" linkSize="8" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="btStartEn" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spFromEn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spToEn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spStepsEn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spShotsEn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="btStartEn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JSpinner" name="spFromEn">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="7200.0" maximum="20000.0" minimum="1.0" numberType="java.lang.Double" stepSize="10.0" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range From:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range To:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spToEn">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="7340.0" maximum="20000.0" minimum="1.0" numberType="java.lang.Double" stepSize="10.0" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spStepsEn">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="20" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel8">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Steps:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel9">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Num Shots:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spShotsEn">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="100" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btStartEn">
<Properties>
<Property name="text" type="java.lang.String" value="Start Energy Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btStartEnActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelCameraScan">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="camera"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel11" linkSize="10" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spToCam" linkSize="11" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel10" linkSize="10" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spFromCam" linkSize="11" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel12" linkSize="10" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spStepsCam" linkSize="11" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel13" linkSize="10" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spShotsCam" linkSize="11" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Component id="btStartCam" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel10" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spFromCam" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spToCam" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel12" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spStepsCam" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel13" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spShotsCam" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="btStartCam" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel10">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range From:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spFromCam">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="-17.0" maximum="30.0" minimum="-30.0" numberType="java.lang.Double" stepSize="1.0" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel11">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range To:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spToCam">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="-11.0" maximum="30.0" minimum="-30.0" numberType="java.lang.Double" stepSize="1.0" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel12">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Steps:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spStepsCam">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="20" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel13">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Num Shots:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spShotsCam">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="100" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btStartCam">
<Properties>
<Property name="text" type="java.lang.String" value="Start Camera Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btStartCamActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelCrystalScan">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="crystal"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel3" linkSize="6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spToCr" linkSize="9" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel2" linkSize="6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spFromCr" linkSize="9" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jLabel4" linkSize="6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spStepsCr" linkSize="9" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jLabel5" linkSize="6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spShotsCr" linkSize="9" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Component id="btStartCr" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spFromCr" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spToCr" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spStepsCr" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spShotsCr" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="btStartCr" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range From:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spFromCr">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="-0.8" maximum="10.0" minimum="-10.0" numberType="java.lang.Double" stepSize="0.1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Range To:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spToCr">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="-1.7" maximum="10.0" minimum="-10.0" numberType="java.lang.Double" stepSize="0.1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Steps:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spStepsCr">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="20" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" value="Num Shots:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spShotsCr">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="100" maximum="1000" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btStartCr">
<Properties>
<Property name="text" type="java.lang.String" value="Start Crystal Height Scan"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btStartCrActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Component class="ch.psi.pshell.plot.LinePlotJFree" name="plotScan">
<Properties>
<Property name="title" type="java.lang.String" value=""/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

760
plugins/PSSS.java Executable file
View File

@@ -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().log(Level.WARNING, null, ex);
}
} 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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)
);
}// </editor-fold>//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
}

View File

@@ -0,0 +1,587 @@
from builtin_utils import *
import ch.psi.utils.Threading as Threading
import ch.psi.utils.State as State
import ch.psi.utils.Convert as Convert
import ch.psi.utils.Str as Str
import ch.psi.utils.Sys as Sys
import ch.psi.utils.Arr as Arr
import ch.psi.utils.IO as IO
import ch.psi.utils.Chrono as Chrono
import ch.psi.utils.Folder as Folder
import ch.psi.utils.Histogram as Histogram
import ch.psi.utils.History as History
import ch.psi.utils.Condition as Condition
import ch.psi.utils.ArrayProperties as ArrayProperties
import ch.psi.utils.Audio as Audio
import ch.psi.utils.BitMask as BitMask
import ch.psi.utils.Config as Config
import ch.psi.utils.Inventory as Inventory
import ch.psi.utils.DataAPI as DataAPI
import ch.psi.utils.DispatcherAPI as DispatcherAPI
import ch.psi.utils.EpicsBootInfoAPI as EpicsBootInfoAPI
import ch.psi.utils.Mail as Mail
import ch.psi.utils.Posix as Posix
import ch.psi.utils.ProcessFactory as ProcessFactory
import ch.psi.utils.Range as Range
import ch.psi.utils.Reflection as Reflection
import ch.psi.utils.Serializer as Serializer
import ch.psi.utils.Windows as Windows
import ch.psi.utils.NumberComparator as NumberComparator
import ch.psi.pshell.core.CommandSource as CommandSource
import ch.psi.pshell.core.ContextAdapter as ContextListener
import ch.psi.pshell.core.Context
import ch.psi.pshell.core.InlineDevice as InlineDevice
import ch.psi.pshell.data.DataSlice as DataSlice
import ch.psi.pshell.data.PlotDescriptor as PlotDescriptor
import ch.psi.pshell.data.Table as Table
import ch.psi.pshell.data.Provider as Provider
import ch.psi.pshell.data.ProviderHDF5 as ProviderHDF5
import ch.psi.pshell.data.ProviderText as ProviderText
import ch.psi.pshell.data.ProviderCSV as ProviderCSV
import ch.psi.pshell.data.ProviderFDA as ProviderFDA
import ch.psi.pshell.data.Converter as DataConverter
import ch.psi.pshell.data.Layout as Layout
import ch.psi.pshell.data.LayoutBase as LayoutBase
import ch.psi.pshell.data.LayoutDefault as LayoutDefault
import ch.psi.pshell.data.LayoutTable as LayoutTable
import ch.psi.pshell.data.LayoutFDA as LayoutFDA
import ch.psi.pshell.data.LayoutSF as LayoutSF
import ch.psi.pshell.device.Device as Device
import ch.psi.pshell.device.DeviceBase as DeviceBase
import ch.psi.pshell.device.GenericDevice as GenericDevice
import ch.psi.pshell.device.DeviceConfig as DeviceConfig
import ch.psi.pshell.device.PositionerConfig as PositionerConfig
import ch.psi.pshell.device.RegisterConfig as RegisterConfig
import ch.psi.pshell.device.ReadonlyProcessVariableConfig as ReadonlyProcessVariableConfig
import ch.psi.pshell.device.ProcessVariableConfig as ProcessVariableConfig
import ch.psi.pshell.device.MotorConfig as MotorConfig
import ch.psi.pshell.device.Register as Register
import ch.psi.pshell.device.RegisterBase as RegisterBase
import ch.psi.pshell.device.ProcessVariableBase as ProcessVariableBase
import ch.psi.pshell.device.ControlledVariableBase as ControlledVariableBase
import ch.psi.pshell.device.PositionerBase as PositionerBase
import ch.psi.pshell.device.MasterPositioner as MasterPositioner
import ch.psi.pshell.device.MotorBase as MotorBase
import ch.psi.pshell.device.DiscretePositionerBase as DiscretePositionerBase
import ch.psi.pshell.device.MotorGroupBase as MotorGroupBase
import ch.psi.pshell.device.MotorGroupDiscretePositioner as MotorGroupDiscretePositioner
import ch.psi.pshell.device.ReadonlyRegisterBase as ReadonlyRegisterBase
import ch.psi.pshell.device.ReadonlyAsyncRegisterBase as ReadonlyAsyncRegisterBase
import ch.psi.pshell.device.Register as Register
import ch.psi.pshell.device.Register.RegisterArray as RegisterArray
import ch.psi.pshell.device.Register.RegisterNumber as RegisterNumber
import ch.psi.pshell.device.Register.RegisterBoolean as RegisterBoolean
import ch.psi.pshell.device.RegisterCache as RegisterCache
import ch.psi.pshell.device.ReadonlyRegister.ReadonlyRegisterArray as ReadonlyRegisterArray
import ch.psi.pshell.device.ReadonlyRegister.ReadonlyRegisterMatrix as ReadonlyRegisterMatrix
import ch.psi.pshell.device.DummyPositioner as DummyPositioner
import ch.psi.pshell.device.DummyMotor as DummyMotor
import ch.psi.pshell.device.DummyRegister as DummyRegister
import ch.psi.pshell.device.Timestamp as Timestamp
import ch.psi.pshell.device.Interlock as Interlock
import ch.psi.pshell.device.Readable as Readable
import ch.psi.pshell.device.Readable.ReadableArray as ReadableArray
import ch.psi.pshell.device.Readable.ReadableMatrix as ReadableMatrix
import ch.psi.pshell.device.Readable.ReadableCalibratedArray as ReadableCalibratedArray
import ch.psi.pshell.device.Readable.ReadableCalibratedMatrix as ReadableCalibratedMatrix
import ch.psi.pshell.device.ArrayCalibration as ArrayCalibration
import ch.psi.pshell.device.MatrixCalibration as MatrixCalibration
import ch.psi.pshell.device.Writable as Writable
import ch.psi.pshell.device.Writable.WritableArray as WritableArray
import ch.psi.pshell.device.Stoppable as Stoppable
import ch.psi.pshell.device.Averager as Averager
import ch.psi.pshell.device.ArrayAverager as ArrayAverager
import ch.psi.pshell.device.Delta as Delta
import ch.psi.pshell.device.DeviceAdapter as DeviceListener
import ch.psi.pshell.device.ReadbackDeviceAdapter as ReadbackDeviceListener
import ch.psi.pshell.device.MotorAdapter as MotorListener
import ch.psi.pshell.device.MoveMode as MoveMode
import ch.psi.pshell.device.SettlingCondition as SettlingCondition
import ch.psi.pshell.device.HistogramGenerator as HistogramGenerator
import ch.psi.pshell.epics.Epics as Epics
import ch.psi.pshell.epics.EpicsScan as EpicsScan
import ch.psi.pshell.epics.ChannelSettlingCondition as ChannelSettlingCondition
import ch.psi.pshell.epics.AreaDetector as AreaDetector
import ch.psi.pshell.epics.BinaryPositioner as BinaryPositioner
import ch.psi.pshell.epics.ChannelByte as ChannelByte
import ch.psi.pshell.epics.ChannelByteArray as ChannelByteArray
import ch.psi.pshell.epics.ChannelByteMatrix as ChannelByteMatrix
import ch.psi.pshell.epics.ChannelDouble as ChannelDouble
import ch.psi.pshell.epics.ChannelDoubleArray as ChannelDoubleArray
import ch.psi.pshell.epics.ChannelDoubleMatrix as ChannelDoubleMatrix
import ch.psi.pshell.epics.ChannelFloat as ChannelFloat
import ch.psi.pshell.epics.ChannelFloatArray as ChannelFloatArray
import ch.psi.pshell.epics.ChannelFloatMatrix as ChannelFloatMatrix
import ch.psi.pshell.epics.ChannelInteger as ChannelInteger
import ch.psi.pshell.epics.ChannelIntegerArray as ChannelIntegerArray
import ch.psi.pshell.epics.ChannelIntegerMatrix as ChannelIntegerMatrix
import ch.psi.pshell.epics.ChannelShort as ChannelShort
import ch.psi.pshell.epics.ChannelShortArray as ChannelShortArray
import ch.psi.pshell.epics.ChannelShortMatrix as ChannelShortMatrix
import ch.psi.pshell.epics.ChannelString as ChannelString
import ch.psi.pshell.epics.ControlledVariable as ControlledVariable
import ch.psi.pshell.epics.DiscretePositioner as DiscretePositioner
import ch.psi.pshell.epics.GenericChannel as GenericChannel
import ch.psi.pshell.epics.GenericArray as GenericArray
import ch.psi.pshell.epics.GenericMatrix as GenericMatrix
import ch.psi.pshell.epics.Manipulator as Manipulator
import ch.psi.pshell.epics.Motor as EpicsMotor
import ch.psi.pshell.epics.Positioner as Positioner
import ch.psi.pshell.epics.ProcessVariable as ProcessVariable
import ch.psi.pshell.epics.ReadonlyProcessVariable as ReadonlyProcessVariable
import ch.psi.pshell.epics.Scaler as Scaler
import ch.psi.pshell.epics.Scienta as Scienta
import ch.psi.pshell.epics.Slit as Slit
import ch.psi.pshell.epics.AreaDetectorSource as AreaDetectorSource
import ch.psi.pshell.epics.ArraySource as ArraySource
import ch.psi.pshell.epics.ByteArraySource as ByteArraySource
import ch.psi.pshell.epics.PsiCamera as PsiCamera
import ch.psi.pshell.epics.CAS as CAS
import ch.psi.pshell.serial.SerialPortDevice as SerialPortDevice
import ch.psi.pshell.serial.TcpDevice as TcpDevice
import ch.psi.pshell.serial.UdpDevice as UdpDevice
import ch.psi.pshell.serial.SerialPortDeviceConfig as SerialPortDeviceConfig
import ch.psi.pshell.serial.SocketDeviceConfig as SocketDeviceConfig
import ch.psi.pshell.modbus.ModbusTCP as ModbusTCP
import ch.psi.pshell.modbus.ModbusUDP as ModbusUDP
import ch.psi.pshell.modbus.ModbusSerial as ModbusSerial
import ch.psi.pshell.modbus.AnalogInput as ModbusAI
import ch.psi.pshell.modbus.AnalogInputArray as ModbusMAI
import ch.psi.pshell.modbus.AnalogOutput as ModbusAO
import ch.psi.pshell.modbus.AnalogOutputArray as ModbusMAO
import ch.psi.pshell.modbus.DigitalInput as ModbusDO
import ch.psi.pshell.modbus.DigitalInputArray as ModbusMDI
import ch.psi.pshell.modbus.DigitalOutput as ModbusDO
import ch.psi.pshell.modbus.DigitalOutputArray as ModbusMDO
import ch.psi.pshell.modbus.Register as ModbusReg
import ch.psi.pshell.modbus.ReadonlyProcessVariable as ModbusROPV
import ch.psi.pshell.modbus.ProcessVariable as ModbusPV
import ch.psi.pshell.modbus.ControlledVariable as ModbusCB
import ch.psi.pshell.modbus.ModbusDeviceConfig as ModbusDeviceConfig
import ch.psi.pshell.imaging.Source as Source
import ch.psi.pshell.imaging.SourceBase as SourceBase
import ch.psi.pshell.imaging.DirectSource as DirectSource
import ch.psi.pshell.imaging.RegisterArraySource as RegisterArraySource
import ch.psi.pshell.imaging.RegisterMatrixSource as RegisterMatrixSource
import ch.psi.pshell.imaging.ImageListener as ImageListener
import ch.psi.pshell.imaging.ImageMeasurement as ImageMeasurement
import ch.psi.pshell.imaging.CameraSource as CameraSource
import ch.psi.pshell.imaging.ColormapAdapter as ColormapAdapter
import ch.psi.pshell.imaging.FileSource as FileSource
import ch.psi.pshell.imaging.MjpegSource as MjpegSource
import ch.psi.pshell.imaging.Webcam as Webcam
import ch.psi.pshell.imaging.Filter as Filter
import ch.psi.pshell.imaging.Utils as ImagingUtils
import ch.psi.pshell.imaging.Overlay as Overlay
import ch.psi.pshell.imaging.Overlays as Overlays
import ch.psi.pshell.imaging.Pen as Pen
import ch.psi.pshell.imaging.Data as Data
import ch.psi.pshell.imaging.Colormap as Colormap
import ch.psi.pshell.imaging.Renderer as Renderer
import ch.psi.pshell.plot.Plot as Plot
import ch.psi.pshell.plot.Plot.AxisId as AxisId
import ch.psi.pshell.plot.LinePlot.Style as LinePlotStyle
import ch.psi.pshell.plot.RangeSelectionPlot as RangeSelectionPlot
import ch.psi.pshell.plot.RangeSelectionPlot.RangeSelectionPlotListener as RangeSelectionPlotListener
import ch.psi.pshell.plot.LinePlot as LinePlot
import ch.psi.pshell.plot.MatrixPlot as MatrixPlot
import ch.psi.pshell.plot.TimePlot as TimePlot
import ch.psi.pshell.plot.SlicePlot as SlicePlot
import ch.psi.pshell.plot.LinePlotJFree as LinePlotJFree
import ch.psi.pshell.plot.MatrixPlotJFree as MatrixPlotJFree
import ch.psi.pshell.plot.TimePlotJFree as TimePlotJFree
import ch.psi.pshell.plot.SlicePlotDefault as SlicePlotDefault
import ch.psi.pshell.plot.LinePlotSeries as LinePlotSeries
import ch.psi.pshell.plot.LinePlotErrorSeries as LinePlotErrorSeries
import ch.psi.pshell.plot.MatrixPlotSeries as MatrixPlotSeries
import ch.psi.pshell.plot.TimePlotSeries as TimePlotSeries
import ch.psi.pshell.plot.SlicePlotSeries as SlicePlotSeries
import ch.psi.pshell.scan.ScanBase as ScanBase
import ch.psi.pshell.scan.LineScan
import ch.psi.pshell.scan.ContinuousScan
import ch.psi.pshell.scan.AreaScan
import ch.psi.pshell.scan.VectorScan
import ch.psi.pshell.scan.ManualScan
import ch.psi.pshell.scan.HardwareScan
import ch.psi.pshell.scan.RegionScan
import ch.psi.pshell.scan.TimeScan
import ch.psi.pshell.scan.MonitorScan
import ch.psi.pshell.scan.BinarySearch
import ch.psi.pshell.scan.HillClimbingSearch
import ch.psi.pshell.scan.ScanResult
import ch.psi.pshell.scan.Otf as Otf
import ch.psi.pshell.scan.ScanCallbacks as ScanCallbacks
import ch.psi.pshell.crlogic.CrlogicPositioner as CrlogicPositioner
import ch.psi.pshell.crlogic.CrlogicSensor as CrlogicSensor
import ch.psi.pshell.scan.ScanAbortedException as ScanAbortedException
import ch.psi.pshell.bs.BsScan
import ch.psi.pshell.bs.Stream as Stream
import ch.psi.pshell.bs.Provider as Provider
import ch.psi.pshell.bs.Dispatcher as Dispatcher
import ch.psi.pshell.bs.Scalar as Scalar
import ch.psi.pshell.bs.Waveform as Waveform
import ch.psi.pshell.bs.Matrix as Matrix
import ch.psi.pshell.bs.StreamCamera as StreamCamera
import ch.psi.pshell.bs.CameraServer as CameraServer
import ch.psi.pshell.bs.PipelineServer as PipelineServer
import ch.psi.pshell.bs.ProviderConfig as ProviderConfig
import ch.psi.pshell.bs.StreamConfig as StreamConfig
import ch.psi.pshell.bs.ScalarConfig as ScalarConfig
import ch.psi.pshell.bs.WaveformConfig as WaveformConfig
import ch.psi.pshell.bs.MatrixConfig as MatrixConfig
import ch.psi.pshell.detector.DetectorConfig as DetectorConfig
import ch.psi.pshell.ui.App as App
import ch.psi.pshell.scripting.ViewPreference as Preference
import ch.psi.pshell.scripting.ScriptUtils as ScriptUtils
import ch.psi.pshell.scripting.ScriptType as ScriptType
from ch.psi.pshell.device.Record import *
from javax.swing.SwingUtilities import invokeLater, invokeAndWait
import org.jfree.ui.RectangleAnchor as RectangleAnchor
import org.jfree.ui.TextAnchor as TextAnchor
def string_to_obj(o):
if is_string(o):
o=str(o)
if "://" in o:
return InlineDevice(o)
ret = get_context().getInterpreterVariable(o)
if ret is None:
try:
return get_context().scriptManager.evalBackground(o).result
except:
return None
return ret
elif is_list(o):
ret = []
for i in o:
ret.append(string_to_obj(i))
return ret
return o
def json_to_obj(o):
if is_string(o):
import json
return json.loads(o)
elif is_list(o):
ret = []
for i in o:
ret.append(json_to_obj(i))
return ret
return o
###################################################################################################
#Scan classes
###################################################################################################
def __no_args(f):
ret = f.func_code.co_argcount
return (ret-1) if type(f)==PyMethod else ret
def __before_readout(scan, pos):
try:
if scan.before_read != None:
args = __no_args(scan.before_read)
if args==0: scan.before_read()
elif args==1: scan.before_read(pos.tolist())
elif args==2: scan.before_read(pos.tolist(), scan)
except AttributeError:
pass
def __after_readout(scan, record):
try:
if scan.after_read != None:
args = __no_args(scan.after_read)
if args==0: scan.after_read()
elif args==1: scan.after_read(record)
elif args==2: scan.after_read(record, scan)
except AttributeError:
pass
def __before_pass(scan, num_pass):
try:
if scan.before_pass != None:
args = __no_args(scan.before_pass)
if args==0:scan.before_pass()
elif args==1:scan.before_pass(num_pass)
elif args==2:scan.before_pass(num_pass, scan)
except AttributeError:
pass
def __after_pass(scan, num_pass):
try:
if scan.after_pass != None:
args = __no_args(scan.after_pass)
if args==0:scan.after_pass()
elif args==1:scan.after_pass(num_pass)
elif args==2:scan.after_pass(num_pass, scan)
except AttributeError:
pass
def __before_region(scan, num_region):
try:
if scan.before_region != None:
args = __no_args(scan.before_region)
if args==0:scan.before_region()
elif args==1:scan.before_region(num_region)
elif args==2:scan.before_region(num_region, scan)
except AttributeError:
pass
class LineScan(ch.psi.pshell.scan.LineScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class AreaScan(ch.psi.pshell.scan.AreaScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class RegionScan(ch.psi.pshell.scan.RegionScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
def onBeforeRegion(self, num): __before_region(self,num)
class VectorScan(ch.psi.pshell.scan.VectorScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class ContinuousScan(ch.psi.pshell.scan.ContinuousScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class TimeScan(ch.psi.pshell.scan.TimeScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class MonitorScan(ch.psi.pshell.scan.MonitorScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class BsScan(ch.psi.pshell.bs.BsScan):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def onBeforePass(self, num): __before_pass(self, num)
def onAfterPass(self, num): __after_pass(self, num)
class ManualScan (ch.psi.pshell.scan.ManualScan):
def __init__(self, writables, readables, start = None, end = None, steps = None, relative = False, dimensions = None, **pars):
ch.psi.pshell.scan.ManualScan.__init__(self, writables, readables, start, end, steps, relative)
self._dimensions = dimensions
processScanPars(self, pars)
def append(self,setpoints, positions, values, timestamps=None):
ch.psi.pshell.scan.ManualScan.append(self, to_array(setpoints), to_array(positions), to_array(values), None if (timestamps is None) else to_array(timestamps))
def getDimensions(self):
if self._dimensions == None:
return ch.psi.pshell.scan.ManualScan.getDimensions(self)
else:
return self._dimensions
class BinarySearch(ch.psi.pshell.scan.BinarySearch):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
class HillClimbingSearch(ch.psi.pshell.scan.HillClimbingSearch):
def onBeforeReadout(self, pos): __before_readout(self, pos)
def onAfterReadout(self, rec): __after_readout(self, rec)
def processScanPars(scan, pars):
scan.before_read = pars.pop("before_read",None)
scan.after_read = pars.pop("after_read",None)
scan.before_pass = pars.pop("before_pass",None)
scan.after_pass = pars.pop("after_pass",None)
scan.before_region= pars.pop("before_region",None)
scan.setPlotTitle(pars.pop("title",None))
scan.setHidden(pars.pop("hidden",False))
scan.setSettleTimeout (pars.pop("settle_timeout",ScanBase.getScansSettleTimeout()))
scan.setUseWritableReadback (pars.pop("use_readback",ScanBase.getScansUseWritableReadback()))
scan.setInitialMove(pars.pop("initial_move",ScanBase.getScansTriggerInitialMove()))
scan.setParallelPositioning(pars.pop("parallel_positioning",ScanBase.getScansParallelPositioning()))
scan.setAbortOnReadableError(pars.pop("abort_on_error",ScanBase.getAbortScansOnReadableError()))
scan.setRestorePosition (pars.pop("restore_position",ScanBase.getRestorePositionOnRelativeScans()))
scan.setCheckPositions(pars.pop("check_positions",ScanBase.getScansCheckPositions()))
scan.setMonitors(to_list(string_to_obj(pars.pop("monitors",None))))
scan.setSnaps(to_list(string_to_obj(pars.pop("snaps",None))))
scan.setDiags(to_list(string_to_obj(pars.pop("diags",None))))
scan.setMeta(pars.pop("meta",None))
get_context().setCommandPars(scan, pars)
###################################################################################################
#Simple EPICS Channel abstraction
###################################################################################################
def create_channel(name, type=None, size=None):
return Epics.newChannel(name, Epics.getChannelType(type), size)
#Not using finalizer: closing channels in garbage collection generate errors
class Channel(java.beans.PropertyChangeListener, Writable, Readable, DeviceBase):
def __init__(self, channel_name, type = None, size = None, callback=None, alias = None, monitored=None, name = None):
""" Create an object that encapsulates an Epics PV connection.
Args:
channel_name(str):name of the channel
type(str, optional): type of PV. By default gets the PV standard field type.
Scalar values: 'b', 'i', 'l', 'd', 's'.
Array values: '[b', '[i,', '[l', '[d', '[s'.
size(int, optional): the size of the channel
callback(function, optional): The monitor callback.
alias(str): name to be used on scans.
"""
super(DeviceBase, self).__init__(name if (name is not None) else channel_name.replace(":","_").replace(".","_"))
self.channel = create_channel(channel_name, type, size)
self.callback = callback
self._alias = alias
if monitored is not None:self.setMonitored(monitored)
self.initialize()
def get_channel_name(self):
"""Return the name of the channel.
"""
return self.channel.name
def get_size(self):
"""Return the size of the channel.
"""
return self.channel.size
def set_size(self, size):
"""Set the size of the channel.
"""
self.channel.size = size
def is_connected(self):
"""Return True if channel is connected.
"""
return self.channel.connected
def doSetMonitored(self, value):
self.channel.monitored = value
if (value):
self.channel.addPropertyChangeListener(self)
else:
self.channel.removePropertyChangeListener(self)
def is_monitored(self):
"""Return True if channel is monitored
"""
return self.channel.monitored
def set_monitored(self, value):
"""Set a channel monitor to trigger the callback function defined in the constructor.
"""
self.setMonitored(value)
def propertyChange(self, pce):
if pce.getPropertyName() == "value":
value=pce.getNewValue()
self.setCache(value, None)
if self.callback is not None:
self.callback(value)
def put(self, value, timeout=None):
"""Write to channel and wait value change. In the case of a timeout throws a TimeoutException.
Args:
value(obj): value to be written
timeout(float, optional): timeout in seconds. If none waits forever.
"""
if (timeout==None):
self.channel.setValue(value)
else:
self.channel.setValueAsync(value).get(int(timeout*1000), java.util.concurrent.TimeUnit.MILLISECONDS)
self.setCache(value, None)
def putq(self, value):
"""Write to channel and don't wait.
"""
self.channel.setValueNoWait(value)
def get(self, force = False):
"""Get channel value.
"""
ret = self.channel.getValue(force)
self.setCache(ret, None)
return ret
def wait_for_value(self, value, timeout=None, comparator=None):
"""Wait channel to reach a value, using a given comparator. In the case of a timeout throws a TimeoutException.
Args:
value(obj): value to be verified.
timeout(float, optional): timeout in seconds. If None waits forever.
comparator (java.util.Comparator, optional). If None, uses Object.equals.
"""
if comparator is None:
if timeout is None:
self.channel.waitForValue(value)
else:
self.channel.waitForValue(value, int(timeout*1000))
self.setCache(value, None)
else:
if timeout is None:
self.channel.waitForValue(value, comparator)
else:
self.channel.waitForValue(value, comparator, int(timeout*1000))
def doUpdate(self):
self.get()
def close(self):
"""Close the channel.
"""
Epics.closeChannel(self.channel)
def setAlias(self, alias):
self._alias = alias
def getAlias(self):
return self._alias if self._alias else self.getName()
def write(self, value):
self.put(value)
def read(self):
return self.get()
def __enter__(self):
return self
def __exit__(self, *args):
self.close()

File diff suppressed because it is too large Load Diff

174
script/Lib/builtin_utils.py Normal file
View File

@@ -0,0 +1,174 @@
import sys
import time
import math
import os.path
from operator import add, mul, sub, truediv
from time import sleep
from array import array
import jarray
import java.lang.Class as Class
import java.lang.Object as Object
import java.lang.System as System
import java.beans.PropertyChangeListener
import java.util.concurrent.Callable
import java.util.List
import java.util.ArrayList
import java.lang.reflect.Array
import java.lang.Thread
import java.awt.image.BufferedImage as BufferedImage
import java.awt.Color as Color
import java.awt.Point as Point
import java.awt.Dimension as Dimension
import java.awt.Rectangle as Rectangle
import java.awt.Font as Font
import org.python.core.PyArray as PyArray
import org.python.core.PyFunction as PyFunction
import org.python.core.PyMethod as PyMethod
import org.python.core.PyGenerator as PyGenerator
import java.lang.Boolean
import java.lang.Integer
import java.lang.Float
import java.lang.Double
import java.lang.Short
import java.lang.Byte
import java.lang.Long
import java.lang.String
import ch.psi.pshell.core.Context
import ch.psi.pshell.scripting.ScriptUtils as ScriptUtils
import ch.psi.utils.Convert as Convert
import ch.psi.utils.Arr as Arr
###################################################################################################
#Type conversion and checking
###################################################################################################
def to_array(obj, type = None, primitive = True):
"""Convert Python list to Java array.
Args:
obj(list): Original data.
type(str): array type 'b' = byte, 'h' = short, 'i' = int, 'l' = long, 'f' = float, 'd' = double,
'c' = char, 'z' = boolean, 's' = String, 'o' = Object
Returns:
Java array.
"""
if obj is None:
return None
if type is None:
type = 'o'
enforceArrayType=False
else:
enforceArrayType=True
if type[0] == '[':
type = type[1:]
element_type = ScriptUtils.getPrimitiveType(type) if primitive else ScriptUtils.getType(type)
def convert_1d_array(obj):
try:
if primitive:
#If primitive, first try converting with jarray.array
return jarray.array(obj,type)
except:
pass
if type == 'c':
ret = java.lang.reflect.Array.newInstance(element_type,len(obj))
for i in range(len(obj)): ret[i] = chr(obj[i])
return ret
if type == 'z':
ret = java.lang.reflect.Array.newInstance(element_type,len(obj))
for i in range(len(obj)):
ret[i]= True if obj[i] else False
return ret
if type == 'o':
ret = java.lang.reflect.Array.newInstance(element_type,len(obj))
for i in range(len(obj)):
ret[i]= obj[i]
return ret
if type == "s":
return Convert.toStringArray(obj)
if primitive:
ret = Convert.toPrimitiveArray(obj, element_type)
else:
ret = java.lang.reflect.Array.newInstance(element_type,len(obj))
for i in range(len(obj)): ret[i] = Convert.toType(obj[i],element_type)
return ret
if isinstance(obj,PyArray):
if enforceArrayType:
if Arr.getComponentType(obj) != element_type:
rank = Arr.getRank(obj)
if (rank== 1):
obj=convert_1d_array(obj)
elif (rank>1):
pars, aux = [element_type], obj
for i in range(rank):
pars.append(len(aux))
aux = aux[0]
ret = java.lang.reflect.Array.newInstance(*pars)
for i in range(len(obj)):
ret[i]=to_array(obj[i], type)
obj = ret
elif is_list(obj):
if type=='o':
ret = java.lang.reflect.Array.newInstance(element_type, len(obj))
for i in range (len(obj)):
if is_list(obj[i]) or isinstance(obj[i],PyArray):
ret[i] = to_array(obj[i],type)
else:
ret[i] = obj[i]
obj=ret
elif len(obj)>0 and (is_list(obj[0]) or isinstance(obj[0],PyArray)):
pars, aux = [element_type], obj
while len(aux)>0 and (is_list(aux[0]) or isinstance(aux[0],PyArray)):
pars.append(len(aux))
aux = aux[0]
pars.append(0)
ret = java.lang.reflect.Array.newInstance(*pars)
for i in range(len(obj)):
ret[i]=to_array(obj[i], type)
obj=ret
else:
obj= convert_1d_array(obj)
return obj
def to_list(obj):
"""Convert an object into a Python List.
Args:
obj(tuple or array or List): Original data.
Returns:
List.
"""
if obj is None:
return None
if isinstance(obj,tuple) or isinstance(obj,java.util.List) :
return list(obj)
#if isinstance(obj,PyArray):
# return obj.tolist()
if not isinstance(obj,list):
return [obj,]
return obj
def is_list(obj):
return isinstance(obj,tuple) or isinstance(obj,list) or isinstance (obj, java.util.List)
def is_string(obj):
return (type(obj) is str) or (type(obj) is unicode)
def is_interpreter_thread():
return java.lang.Thread.currentThread().name == "MainThread"
###################################################################################################
#Access to context singleton
###################################################################################################
def get_context():
return ch.psi.pshell.core.Context.getInstance()

1032
script/Lib/diffutils.py Normal file

File diff suppressed because it is too large Load Diff

782
script/Lib/ijutils.py Normal file
View File

@@ -0,0 +1,782 @@
####################################################################################################
# Facade to ImageJ functionality
####################################################################################################
#More information on:
# Image: https://imagej.nih.gov/ij/docs/guide/146-28.html#toc-Section-28
# Process: https://imagej.nih.gov/ij/docs/guide/146-29.html#toc-Section-29
# Analyze: https://imagej.nih.gov/ij/docs/guide/146-30.html#toc-Section-30
import ch.psi.utils.Convert as Convert
import ch.psi.pshell.imaging.Utils as ImagingUtils
from startup import get_context, expand_path, is_string
import java.awt.image.BufferedImage as BufferedImage
import jarray
import os
import ij.IJ as IJ
import ij.ImageJ as ImageJ
import ij.WindowManager as WindowManager
import ij.ImagePlus as ImagePlus
import ij.ImageStack as ImageStack
import ij.Prefs as Prefs
import ij.io.FileSaver as FileSaver
import ij.io.Opener as Opener
from ij.gui import Roi
import ij.process.ImageProcessor as ImageProcessor
import ij.process.ByteProcessor as ByteProcessor
import ij.process.ShortProcessor as ShortProcessor
import ij.process.ColorProcessor as ColorProcessor
import ij.process.FloatProcessor as FloatProcessor
import ij.process.ImageConverter as ImageConverter
import ij.process.AutoThresholder as AutoThresholder
import ij.process.LUT as LUT
import ij.measure.Measurements as Measurements
import ij.measure.ResultsTable as ResultsTable
import ij.plugin.filter.Analyzer as Analyzer
import ij.plugin.filter.GaussianBlur as GaussianBlur
import ij.plugin.filter.Filters as Filters
import ij.plugin.filter.FFTFilter as FFTFilter
import ij.plugin.filter.BackgroundSubtracter as BackgroundSubtracter
import ij.plugin.filter.EDM as EDM
import ij.plugin.filter.Shadows as Shadows
import ij.plugin.filter.UnsharpMask as UnsharpMask
import ij.plugin.filter.MaximumFinder as MaximumFinder
import ij.plugin.filter.EDM as EDM
import ij.plugin.filter.Shadows as Shadows
import ij.plugin.filter.UnsharpMask as UnsharpMask
import ij.plugin.filter.RankFilters as RankFilters
import ij.plugin.filter.Convolver as Convolver
import ij.plugin.filter.ParticleAnalyzer as ParticleAnalyzer
import ij.plugin.ContrastEnhancer as ContrastEnhancer
import ij.plugin.Thresholder as Thresholder
import ij.plugin.ImageCalculator as ImageCalculator
import ij.plugin.FFT as FFT
import ij.plugin.Concatenator as Concatenator
#ImageJ customizations
import ch.psi.pshell.imaging.ij.FFTMath as FFTMath
import ch.psi.pshell.imaging.ij.FFTFilter as FFTFilter
import ch.psi.pshell.imaging.ij.Binary as Binary
import ch.psi.pshell.imaging.ij.Slicer as Slicer
#This eliminates the error messages due to the bug on ij.gui.ImageWindow row 555 (ij is null)
if not "_image_j" in globals().keys():
_image_j = ImageJ(None, ImageJ.NO_SHOW)
###################################################################################################
#Image creation, copying & saving
###################################################################################################
def load_image(image, title = None):
"""
image: file name or BufferedImage
"""
if is_string(image):
try:
file = expand_path(image)
except:
pass
try:
image = ImagingUtils.newImage(file)
except:
#try loading from assembly
image = get_context().setup.getAssemblyImage(image)
if title is None:
title = os.path.basename(file)
return ImagePlus("img" if title is None else title, image)
def load_array(array, width=None, height=None, title = "img"):
"""
array: 1d array if width and height defined , or else 2d array to be flattened.
"""
#2D
if (width==None) and (height==None):
if array.typecode == '[B': proc = ByteProcessor(len(array[0]), len(array), Convert.flatten(array))
elif array.typecode == '[S': proc = ShortProcessor(len(array[0]), len(array), Convert.flatten(array), None)
elif array.typecode in ['[I','[F', '[D']: proc = FloatProcessor(len(array[0]), len(array), Convert.flatten(array))
else: raise Exception("Invalid array type")
#1D
else:
if (len(array) > width*height):
array = array[:(width*height)]
if array.typecode == 'b': proc = ByteProcessor(width, height, array)
elif array.typecode == 'h': proc = ShortProcessor(width, height, array, None)
elif array.typecode in ['i','f','d']: proc = FloatProcessor(width, height, array)
else: raise Exception("Invalid array type")
return ImagePlus(title, proc)
def save_image(ip, path=None, format = None, metadata={}):
"""
Saves image or stack
If parameters omitted, saves image again in same location, with same format.
"""
fs = FileSaver(ip)
info = ""
for key,val in metadata.items():
info = info + ("\n" if len(info)>0 else "") + str(key) + ": " + str(val)
ip.setProperty("Info", info)
if path == None: fs.save()
else:
try:
path = expandPath(path)
except:
pass
if format == "bmp": fs.saveAsBmp(path)
elif format == "fits": fs.saveAsFits(path)
elif format == "gif": fs.saveAsGif(path)
elif format == "jpeg": fs.saveAsJpeg(path)
elif format == "lut": fs.saveAsLut(path)
elif format == "pgm": fs.saveAsPgm(path)
elif format == "png": fs.saveAsPng(path)
elif format == "raw" and ip.getImageStackSize()>1: fs.saveAsRawStack(path)
elif format == "raw": fs.saveAsRaw(path)
elif format == "txt": fs.saveAsText(path)
elif format == "tiff" and ip.getImageStackSize()>1: fs.saveAsTiffStack(path)
elif format == "tiff": fs.saveAsTiff(path)
elif format == "zip": fs.saveAsZip(path)
def open_image(path, index=1):
"""
Open file using ij.io,Opener
"""
try:
path = expand_path(path)
except:
pass
opener = Opener()
return opener.openImage(path, index)
def new_image(width, height, image_type="byte", title = "img", fill_color = None):
"""
type = "byte", "short", "color" or "float"
"""
if image_type == "byte": p=ByteProcessor(width, height)
elif image_type == "short": p=ShortProcessor(width, height)
elif image_type == "color": p=ColorProcessor(width, height)
elif image_type == "float": p=FloatProcessor(width, height)
else: raise Exception("Invalid image type " + str(image_type))
ret = ImagePlus(title, p)
if fill_color is not None:
p.setColor(fill_color)
p.resetRoi()
p.fill()
return ret
def get_ip_array(ip):
"""
Returns data array of ImagePlus
"""
if type(ip.getProcessor()) == FloatProcessor:
return ip.getProcessor().getFloatArray()
else:
return ip.getProcessor().getIntArray()
def sub_image(ip, x, y, width, height):
"""
Returns new ImagePlus
"""
ip.setRoi(x, y, width, height)
p=ip.getProcessor().crop()
return ImagePlus(ip.getTitle() + " subimage", p)
def copy_image(ip):
return ip.duplicate()
def copy_image_to(ip_source, ip_dest, x, y):
ip_source.deleteRoi()
ip_source.copy()
ip_dest.setRoi(x, y, ip_source.getWidth(), ip_source.getHeight())
ip_dest.paste()
ip_dest.changes = False
ip_dest.deleteRoi()
def pad_image(ip, left=0, right=0, top=0, bottom=0, fill_color = None):
p=ip.getProcessor()
width = p.getWidth() + left + right
height = p.getHeight() + top + bottom
image_type = get_image_type(ip)
ret = new_image(width, height, image_type, ip.getTitle() + " padded", fill_color)
ip.deleteRoi()
ip.copy()
ret.setRoi(left, top, p.getWidth(), p.getHeight())
ret.paste()
ret.changes = False
ret.deleteRoi()
return ret
def get_image_type(ip):
"""
Returns: "byte", "short", "color" or "float"
"""
p=ip.getProcessor()
if type(p) == ShortProcessor: return "short"
elif type(p) == ColorProcessor: return "color"
elif type(p) == FloatProcessor: return "float"
return "byte"
###################################################################################################
#Image measurements
###################################################################################################
def get_measurement(ip, measurement):
"""
Return image measurement:
"Area", "Mean", "StdDev", "Mode", "Min", "Max", "X", "Y", "XM", "YM", "Perim.", "BX", "BY",
"Width", "Height", "Major", "Minor", "Angle", "Circ.", "Feret", "IntDen", "Median", "Skew",
"Kurt", "%Area", "RawIntDen", "Ch", "Slice", "Frame", "FeretX", "FeretY", "FeretAngle",
"MinFeret", "AR", "Round", "Solidity", "MinThr" or "MaxThr"
"""
return IJ.getValue(ip,measurement)
###################################################################################################
#Image type conversion
###################################################################################################
def grayscale(ip, do_scaling=None, in_place=True):
ip = ip if in_place else ip.duplicate()
ic = ImageConverter(ip)
if do_scaling is not None:
ic.setDoScaling(do_scaling)
ic.convertToGray8()
return ip
def get_channel(ip, channel):
"""
Return a channel from a color image as a new ImagePlus.
channel: "red", "green","blue", "alpha", "brightness",
"""
proc = ip.getProcessor()
if channel == "red": ret = proc.getChannel(1, None)
elif channel == "green": ret = proc.getChannel(2, None)
elif channel == "blue": ret = proc.getChannel(3, None)
elif channel == "alpha": ret = proc.getChannel(4, None)
elif channel == "brightness": ret = proc.getBrightness()
else: raise Exception("Invalid channel " + str(channel))
return ImagePlus(ip.getTitle() + " channel: " + channel, ret)
###################################################################################################
#Thresholder
###################################################################################################
def threshold(ip, min_threshold, max_threshold, in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().setThreshold(min_threshold, max_threshold, ImageProcessor.NO_LUT_UPDATE)
WindowManager.setTempCurrentImage(ip)
Thresholder().run("mask")
return ip
def auto_threshold(ip, dark_background = False, method = AutoThresholder.getMethods()[0], in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().setAutoThreshold(method, dark_background , ImageProcessor.NO_LUT_UPDATE)
WindowManager.setTempCurrentImage(ip)
thresholder=Thresholder().run("mask")
return ip
###################################################################################################
#Binary functions
###################################################################################################
def binary_op(ip, op, dark_background=False, iterations=1, count=1, in_place=True):
"""
op = "erode","dilate", "open","close", "outline", "fill holes", "skeletonize"
"""
ip = ip if in_place else ip.duplicate()
binary = Binary(count, iterations, dark_background )
binary.setup(op, ip)
binary.run(ip.getProcessor())
return ip
def binary_erode(ip, dark_background=False, iterations=1, count=1, in_place=True):
return binary_op(ip, "erode", dark_background, iterations, count, in_place)
def binary_dilate(ip, dark_background=False, iterations=1, count=1, in_place=True):
return binary_op(ip, "dilate", dark_background, iterations, count, in_place)
def binary_open(ip, dark_background=False, iterations=1, count=1, in_place=True):
return binary_op(ip, "open", dark_background, iterations, count, in_place)
def binary_close(ip, dark_background=False, iterations=1, count=1, in_place=True):
return binary_op(ip, "close", dark_background, iterations, count)
def binary_outline(ip, dark_background=False, in_place=True):
return binary_op(ip, "outline", dark_background, in_place=in_place)
def binary_fill_holes(ip, dark_background=False, in_place=True):
return binary_op(ip, "fill holes", dark_background, in_place=in_place)
def binary_skeletonize(ip, dark_background=False, in_place=True):
return binary_op(ip, "skeletonize", dark_background, in_place=in_place)
def analyse_particles(ip, min_size, max_size, fill_holes = True, exclude_edges = True, extra_measurements = 0, \
print_table = False, output_image = "outlines", minCirc = 0.0, maxCirc = 1.0):
"""
Returns: tuple (ResultsTable results_table, ImagePlus output_image)
output_image = "outlines", "overlay_outlines", "masks", "overlay_masks", "roi_masks" or None
extra_measurements = mask with Measurements.CENTROID, PERIMETER, RECT, MIN_MAX, ELLIPSE, CIRCULARITY, AREA_FRACTION, INTEGRATED_DENSITY, INVERT_Y, FERET, KURTOSIS, MEDIAN, MODE, SKEWNESS, STD_DEV
Measurements is a mask of flags: https://imagej.nih.gov/ij/developer/api/ij/measure/Measurements.html.
Returned ResultsTable hold public fields: https://imagej.nih.gov/ij/developer/api/ij/measure/ResultsTable.html
"""
rt = ResultsTable()
show_summary = False
options = ParticleAnalyzer.SHOW_RESULTS | ParticleAnalyzer.CLEAR_WORKSHEET
"""
ParticleAnalyzer.SHOW_ROI_MASKS | \
#ParticleAnalyzer.RECORD_STARTS | \
#ParticleAnalyzer.ADD_TO_MANAGER | \
#ParticleAnalyzer.FOUR_CONNECTED | \
#ParticleAnalyzer.IN_SITU_SHOW | \
#ParticleAnalyzer.SHOW_NONE | \
"""
if show_summary: options = options | ParticleAnalyzer.DISPLAY_SUMMARY
if output_image == "outlines": options = options | ParticleAnalyzer.SHOW_OUTLINES
elif output_image == "overlay_outlines": options = options | ParticleAnalyzer.SHOW_OVERLAY_OUTLINES
elif output_image == "masks": options = options | ParticleAnalyzer.SHOW_MASKS
elif output_image == "overlay_masks": options = options | ParticleAnalyzer.SHOW_OVERLAY_MASKS
elif output_image == "roi_masks": options = options | ParticleAnalyzer.SHOW_ROI_MASKS
#ParticleAnalyzer.SHOW_ROI_MASKS
if exclude_edges: options = options | ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES
if fill_holes: options = options | ParticleAnalyzer.INCLUDE_HOLES
measurements = Measurements.AREA | Measurements.MEAN | Measurements.CENTER_OF_MASS | Measurements.RECT
pa = ParticleAnalyzer(options, measurements, rt, min_size, max_size, minCirc, maxCirc)
pa.setHideOutputImage(True)
pa.setResultsTable(rt)
if pa.analyze(ip):
if print_table:
print rt.getColumnHeadings()
for row in range (rt.counter):
print rt.getRowAsString(row)
return (rt, pa.getOutputImage())
###################################################################################################
#Image operators
###################################################################################################
def op_image(ip1, ip2, op, float_result=False, in_place=True):
"""
op = "add","subtract", "multiply","divide", "and", "or", "xor", "min", "max", "average", "difference" or "copy"
"""
ip1 = ip1 if in_place else ip1.duplicate()
ic = ImageCalculator()
pars = op
if float_result:
op = op + " float"
ic.run(pars, ip1, ip2)
return ip1
def op_const(ip, op, val, in_place=True):
"""
op = "add","subtract", "multiply","divide", "and", "or", "xor", "min", "max", "gamma", "set" or "log", "exp", "sqr", "sqrt","abs"
"""
ip = ip if in_place else ip.duplicate()
pr = ip.getProcessor()
if op == 'add': pr.add(val)
elif op == 'sub': pr.subtract(val)
elif op == 'multiply': pr.multiply(val)
elif op == 'divide' and val!=0: pr.multiply(1.0/val)
elif op == 'and': pr.and(val)
elif op == 'or': pr.or(val)
elif op == 'xor': pr.xor(val)
elif op == 'min': pr.min(val);pr.resetMinAndMax()
elif op == 'max': pr.max(val);pr.resetMinAndMax()
elif op == 'gamma' and 0.05 < val < 5.0: pr.gamma(val)
elif op == 'set': pr.set(val)
elif op == 'log': pr.log()
elif op == 'exp': pr.exp()
elif op == 'sqr': pr.sqr()
elif op == 'sqrt': pr.sqrt()
elif op == 'abs': pr.abs();pr.resetMinAndMax()
else: raise Exception("Invalid operation " + str(op))
return ip
def op_fft(ip1, ip2, op, do_inverse = True) :
"""
Images must have same sizes, and multiple of 2 height and width.
op = "correlate" (complex conjugate multiply), "convolve" (Fourier domain multiply), "deconvolve" (Fourier domain divide)
"""
if op == "correlate": op_index = 0
elif op == "convolve": op_index = 1
elif op == "deconvolve": op_index = 2
else: raise Exception("Invalid operation " + str(op))
return FFTMath().doMath(ip1, ip2, op_index, do_inverse)
def op_rank(ip, op, kernel_radius =1 , dark_outliers = False ,threshold = 50, in_place=True):
"""
op = "mean", "min", "max", "variance", "median", "close_maxima", "open_maxima", "remove_outliers", "remove_nan", "despeckle"
"""
if op == "mean": filter_type = RankFilters.MEAN
elif op == "min": filter_type = RankFilters.MIN
elif op == "max": filter_type = RankFilters.MAX
elif op == "variance": filter_type = RankFilters.VARIANCE
elif op == "median": filter_type = RankFilters.MEDIAN
elif op == "close_maxima": filter_type = RankFilters.CLOSE
elif op == "open_maxima": filter_type = RankFilters.OPEN
elif op == "remove_outliers": filter_type = RankFilters.OUTLIERS
elif op == "remove_nan": filter_type = RankFilters.REMOVE_NAN
elif op == "despeckle": filter_type, kernel_radius = RankFilters.MEDIAN, 1
else: raise Exception("Invalid operation " + str(op))
ip = ip if in_place else ip.duplicate()
RankFilters().rank(ip.getProcessor(), kernel_radius, filter_type, RankFilters.DARK_OUTLIERS if dark_outliers else RankFilters.BRIGHT_OUTLIERS ,threshold)
return ip
def op_edm(ip, op="edm", dark_background=False, in_place=True):
"""
Euclidian distance map & derived operations
op ="edm", "watershed","points", "voronoi"
"""
ip = ip if in_place else ip.duplicate()
pr = ip.getProcessor()
edm=EDM()
Prefs.blackBackground=dark_background
if op=="edm":
#pr.setPixels(0, edm.makeFloatEDM(pr, 0, False));
#pr.resetMinAndMax();
if dark_background:
pr.invert()
edm.toEDM(pr)
else:
edm.setup(op, ip)
edm.run(pr)
return ip
def watershed(ip, dark_background=False, in_place=True):
return op_edm(ip, "watershed", dark_background, in_place)
def ultimate_points(ip, dark_background=False, in_place=True):
return op_edm(ip, "points", dark_background, in_place)
def veronoi(ip, dark_background=False, in_place=True):
return op_edm(ip, "voronoi", dark_background, in_place)
def edm(ip, dark_background=False, in_place=True):
return op_edm(ip, "edm", dark_background, in_place)
def op_filter(ip, op, in_place=True):
"""
This is redundant as just calls processor methods.
op ="invert", "smooth", "sharpen", "edge", "add"
"""
ip = ip if in_place else ip.duplicate()
f = Filters()
f.setup(op, ip )
f.run(ip.getProcessor())
return ip
###################################################################################################
#Other operations
###################################################################################################
def gaussian_blur(ip, sigma_x=3.0, sigma_y=3.0, accuracy = 0.01, in_place=True):
ip = ip if in_place else ip.duplicate()
GaussianBlur().blurGaussian(ip.getProcessor(), sigma_x, sigma_y, accuracy)
return ip
def find_maxima(ip, tolerance=25, threshold = ImageProcessor.NO_THRESHOLD, output_type=MaximumFinder.IN_TOLERANCE, exclude_on_edges = False, is_edm = False):
"""
Returns new ImagePlus
tolerance: maxima are accepted only if protruding more than this value from the ridge to a higher maximum
threshhold: minimum height of a maximum (uncalibrated);
output_type = SINGLE_POINTS, IN_TOLERANCE or SEGMENTED. No output image is created for output types POINT_SELECTION, LIST and COUNT.
"""
byte_processor = MaximumFinder().findMaxima(ip.getProcessor(), tolerance, threshold, output_type, exclude_on_edges, is_edm)
return ImagePlus(ip.getTitle() + " maxima", byte_processor)
def get_maxima_points(ip, tolerance=25, exclude_on_edges = False):
polygon = MaximumFinder().getMaxima(ip.getProcessor(), tolerance, exclude_on_edges)
return (polygon.xpoints, polygon.ypoints)
def enhance_contrast(ip, equalize_histo = True, saturated_pixels = 0.5, normalize = False, stack_histo = False, in_place=True):
ip = ip if in_place else ip.duplicate()
ce = ContrastEnhancer()
if equalize_histo:
ce.equalize(ip.getProcessor());
else:
ce.stretchHistogram(ip.getProcessor(), saturated_pixels)
if normalize:
ip.getProcessor().setMinAndMax(0,1.0 if (ip.getProcessor().getBitDepth()==32) else ip.getProcessor().maxValue())
return ip
def shadows(ip, op, in_place=True):
"""
op ="north","northeast", "east", "southeast","south", "southwest", "west","northwest"
"""
ip = ip if in_place else ip.duplicate()
shadows= Shadows()
shadows.setup(op, ip)
shadows.run(ip.getProcessor())
return ip
def unsharp_mask(ip, sigma, weight, in_place=True):
"""
Float processor
"""
ip = ip if in_place else ip.duplicate()
ip.getProcessor().snapshot()
unsharp=UnsharpMask()
USmask.setup(" ", ip)
USmask.sharpenFloat( ip.getProcessor(),sigma, weight)
return ip
def subtract_background(ip, radius = 50, create_background=False, dark_background=False, use_paraboloid =True, do_presmooth = True, correctCorners = True, rgb_brightness=False, in_place=True):
ip = ip if in_place else ip.duplicate()
if rgb_brightness:
BackgroundSubtracter().rollingBallBrightnessBackground(ip.getProcessor(), radius, create_background,not dark_background, use_paraboloid, do_presmooth, correctCorners)
else:
BackgroundSubtracter().rollingBallBackground(ip.getProcessor(), radius, create_background, not dark_background, use_paraboloid, do_presmooth, correctCorners)
return ip
###################################################################################################
#FFT
###################################################################################################
def image_fft(ip, show = True):
WindowManager.setTempCurrentImage(ip)
fft = FFT()
fft.run("fft")
#TODO: how to avoid it to be created?
#ret = ImagePlus("FHT of " + ip.getTitle(), WindowManager.getCurrentImage().getProcessor())
ret = WindowManager.getCurrentImage()
if not show:
WindowManager.getCurrentImage().hide()
return ret
def image_ffti(ip, show = True):
WindowManager.setTempCurrentImage(ip)
fft = FFT()
fft.run("inverse")
#WindowManager.getCurrentImage().hide()
#TODO: how to avoid it to be created?
#ret = WindowManager.getCurrentImage()
#WindowManager.getCurrentImage().hide()
#ret = ImagePlus(ip.getTitle() + " ffti", WindowManager.getCurrentImage().getProcessor())
ret = WindowManager.getCurrentImage()
if not show:
WindowManager.getCurrentImage().hide()
return ret
def bandpass_filter(ip, small_dia_px, large_dia_px, suppress_stripes = 0, stripes_tolerance_direction = 5.0, autoscale_after_filtering = False, saturate_if_autoscale = False, display_filter = False, in_place=True):
"""
suppress_stripes = 0 for none, 1 for horizontal, 2 for vertical
"""
ip = ip if in_place else ip.duplicate()
filter= FFTFilter();
FFTFilter.filterLargeDia = large_dia_px
FFTFilter.filterSmallDia = small_dia_px
FFTFilter.choiceIndex = suppress_stripes
FFTFilter.toleranceDia = stripes_tolerance_direction
FFTFilter.doScalingDia = autoscale_after_filtering
FFTFilter.saturateDia = saturate_if_autoscale
FFTFilter.displayFilter =display_filter
filter.setup(None, ip);
filter.run(ip.getProcessor())
return ip
###################################################################################################
#Convolution
###################################################################################################
KERNEL_BLUR = [[0.1111, 0.1111, 0.1111], [0.1111, 0.1111, 0.1111], [0.1111, 0.1111, 0.1111]]
KERNEL_SHARPEN = [[0.0, -0.75, 0.0], [-0.75, 4.0, -0.75], [0.0, -0.75, 0.0]]
KERNEL_SHARPEN_2 = [[-1.0, -1.0, -1.0], [-1.0, 9.0, -1.0], [-1.0, -1.0, -1.0]]
KERNEL_LIGHT = [[0.1, 0.1, 0.1], [0.1, 1.0, 0.1],[0.1, 0.1, 0.1]]
KERNEL_DARK = [[0.01, 0.01, 0.01],[0.01, 0.5, 0.01],[0.01, 0.01, 0.01]]
KERNEL_EDGE_DETECT = [[0.0, -0.75, 0.0], [-0.75, 3.0, -0.75], [0.0, -0.75, 0.0]]
KERNEL_EDGE_DETECT_2 = [[-0.5, -0.5, -0.5], [-0.5, 4.0, -0.5], [-0.5, -0.5, -0.5]]
KERNEL_DIFFERENTIAL_EDGE_DETECT = [[-1.0, 0.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, -1.0]]
KERNEL_PREWITT = [[-2.0, -1.0, 0.0], [-1.0, 0.0, 1.0 ], [0.0, 1.0, 2.0]]
KERNEL_SOBEL = [[2.0, 2.0, 0.0], [2.0, 0.0, -2.0 ], [0.0, -2.0, -2.0]]
def convolve(ip, kernel, in_place=True):
"""
kernel: list of lists
"""
ip = ip if in_place else ip.duplicate()
kernel_width = len(kernel)
kernel_height= len(kernel[0])
kernel = [item for row in kernel for item in row]
#Convolver().convolve(ip.getProcessor(), kernel, kernel_width, kernel_height)
ip.getProcessor().convolve(kernel, kernel_width, kernel_height)
return ip
###################################################################################################
#Shortcut to ImageProcessor methods
###################################################################################################
def invert(ip, in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().invert()
return ip
def smooth(ip, in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().smooth()
return ip
def sharpen(ip, in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().sharpen()
return ip
def edges(ip, in_place=True): #Sobel
ip = ip if in_place else ip.duplicate()
ip.getProcessor().findEdges()
return ip
def noise(ip, sigma = 25.0, in_place=True):
ip = ip if in_place else ip.duplicate()
ip.getProcessor().noise(sigma)
return ip
def remap(ip, min=None, max=None, in_place=True):
ip = ip if in_place else ip.duplicate()
if min is None or max is None:
stats = get_statistics(ip, Measurements.MIN_MAX)
if min is None: min = stats.min
if max is None: max = stats.max
ip.getProcessor().setMinAndMax(min, max)
return ip
def set_lut(ip, r, g, b):
"""
r,g and b are lists of 256 integers
"""
r = [x if x<128 else x-256 for x in r]
g = [x if x<128 else x-256 for x in g]
b = [x if x<128 else x-256 for x in b]
ip.setLut(LUT(jarray.array(r,'b'),jarray.array(g,'b'),jarray.array(b,'b')))
def resize(ip, width, height):
"""
Returns new ImagePlus
"""
p = ip.getProcessor().resize(width, height)
return ImagePlus(ip.getTitle() + " resized", p)
def binning(ip, factor):
p=ip.getProcessor().bin(factor)
return ImagePlus(ip.getTitle() + " resized", p)
def get_histogram(ip, hist_min = 0, hist_max = 0, hist_bins = 256, roi=None):
"""
hist_min, hist_max, hist_bins used only for float images (otherwise fixed to 0,255,256)
roi is list [x,y,w,h]
"""
if roi == None: ip.deleteRoi()
else: ip.setRoi(roi[0],roi[1],roi[2],roi[3])
image_statistics = ip.getStatistics(0, hist_bins, hist_min, hist_max)
return image_statistics.getHistogram()
def get_array(ip):
return ip.getProcessor().getIntArray()
def get_line(ip, x1, y1, x2, y2):
return ip.getProcessor().getLine(x1, y1, x2, y2)
def get_pixel_range(ip):
return (ip.getProcessor().getMin(), ip.getProcessor().getMax())
def get_num_channels(ip):
return ip.getProcessor().getNChannels()
def is_binary(ip):
return ip.getProcessor().isBinary()
def get_pixel(ip, x, y):
return ip.getProcessor().getPixel(x,y)
def get_pixel_array(ip, x, y):
a = [0]*get_num_channels(ip)
return ip.getProcessor().getPixel(x,y,a)
def get_pixels(ip):
return ip.getProcessor().getPixels()
def get_width(ip):
return ip.getProcessor().getWidth()
def get_height(ip):
return ip.getProcessor().getHeight()
def get_row(ip, y):
a = [0]*get_width(ip)
array = jarray.array(a,'i')
ip.getProcessor().getRow(0, y, array, get_width(ip))
return array
def get_col(ip, x):
a = [0]*get_height(ip)
array = jarray.array(a,'i')
ip.getProcessor().getColumn(x, 0, array, get_height(ip))
return array
def get_statistics(ip, measurements = None):
"""
Measurements is a mask of flags: https://imagej.nih.gov/ij/developer/api/ij/measure/Measurements.html.
Statistics object hold public fields: https://imagej.nih.gov/ij/developer/api/ij/process/ImageStatistics.html
"""
if measurements is None:
return ip.getStatistics()
else:
return ip.getStatistics(measurements)
###################################################################################################
#Image stack functions
###################################################################################################
def create_stack(ip_list, duplicate=True, title = None):
stack = Concatenator().concatenate(ip_list, duplicate)
if title is not None:
stack.setTitle(title)
return stack
def open_stack(path_list, title=None):
"""
Open list of files as a stack using ij.io,Opener
"""
ip_list = []
for path in path_list:
ip_list.append(open_image(path))
return create_stack(ip_list, duplicate=False, title = "stack" if title is None else title)
def reslice(stack, start_at = "Top", vertically = True, flip = True, output_pixel_spacing=1.0, avoid_interpolation = True, title = None):
ss = Slicer()
ss.rotate = vertically
ss.startAt = start_at
ss.flip = flip
ss.nointerpolate = avoid_interpolation
ss.outputZSpacing = output_pixel_spacing
stack = ss.reslice(stack)
if title is not None:
stack.setTitle(title)
return stack
###############################################################################
# ImagePlus list operations
###############################################################################
def integrate_ips(ips, as_float=True):
"""
Integrate list if ImagePlus with the same size.
"""
aux = None
for i in range(len(ips)):
if i==0:
img_type = "float" if as_float else "short"
aux = new_image(ips[i].width, ips[i].height, image_type=img_type, title = "sum", fill_color = None)
op_image(aux, ips[i], "add", float_result=as_float, in_place=True)
return aux
def average_ips (ips, roi=None, as_float=True):
"""
Average list if ImagePlus with the same size.
"""
aux = integrate_ips(ips, as_float)
op_const(aux, "divide", float(len(ips)), in_place=True)
return aux

239
script/Lib/jeputils.py Normal file
View File

@@ -0,0 +1,239 @@
###################################################################################################
# Facade to JEP: Embedded Python
###################################################################################################
#Matplotlib won't work out of the box because it's default backend (Qt) uses signals, which only works in
#the main thread. Ideally should find a fix, in order to mark the running thread as the main.
#As a workaround, one can use the Tk backend:
#
#import matplotlib
#matplotlib.use('TkAgg')
#In principle just add JEP jar and library to the extensions folder.
#
#Alternatively on Linux:
# Python 2:
# - Add <python home>/lib/python3.X/site-packages/jep to LD_LIBRARY_PATH
# - Add <python home>/lib/python3.X/site-packages/jep/jep-X.X.X.jar to the class path
#
#Python3:
# - Add JEP library folder to LD_LIBRARY_PATH
# - If using OpenJDK, add also python <python home>/lib folder to LD_LIBRARY_PATH
# - Set LD_PRELOAD=<python home>/lib/libpython3.5m.so
import sys
import os
import jep.Jep
import jep.SharedInterpreter
import jep.NDArray
import java.lang.Thread
import org.python.core.PyArray as PyArray
import java.lang.String as String
import java.util.List
import java.util.Map
import java.util.HashMap
import ch.psi.pshell.scripting.ScriptUtils as ScriptUtils
from startup import to_array, get_context, _get_caller, Convert, Arr
__jep = {}
def __get_jep():
t = java.lang.Thread.currentThread()
if not t in __jep:
init_jep()
return __jep[t]
def __close_jep():
t = java.lang.Thread.currentThread()
if t in __jep:
__jep[t].close()
def init_jep():
#TODO: Should do it but generates errors
#__close_jep()
j = jep.SharedInterpreter()
#Faster, but statements must be complete
j.setInteractive(False)
__jep[java.lang.Thread.currentThread()] = j
j.eval("import sys")
#sys.argv is not present in JEP and may be needed for certain modules (as Tkinter)
j.eval("sys.argv = ['PShell']");
#Add standard script path to python path
j.eval("sys.path.append('" + get_context().setup.getScriptPath() + "')")
#Redirect stdout
j.eval("class JepStdout:\n" +
" def write(self, str):\n" +
" self.str += str\n" +
" def clear(self):\n" +
" self.str = ''\n" +
" def flush(self):\n" +
" pass\n")
j.eval("sys.stdout=JepStdout()");
j.eval("sys.stderr=JepStdout()");
j.eval("sys.stdout.clear()")
j.eval("sys.stderr.clear()")
#Import reload on Python 3
j.eval("try:\n" +
" reload # Python 2.7\n" +
"except NameError:\n" +
" try:\n" +
" from importlib import reload # Python 3.4+\n" +
" except ImportError:\n" +
" from imp import reload # Python 3.0 - 3.3\n")
def __print_stdout():
j=__get_jep()
output = None
err = None
try:
output = j.getValue("sys.stdout.str")
err = j.getValue("sys.stderr.str")
j.eval("sys.stdout.clear()")
j.eval("sys.stderr.clear()")
except:
pass
if (output is not None) and len(output)>0:
print output
if (err is not None) and len(err)>0:
print >> sys.stderr, err
def run_jep(script_name, vars = {}):
global __jep
script = get_context().scriptManager.library.resolveFile(script_name)
if script is None :
script= os.path.abspath(script_name)
j=__get_jep()
for v in vars:
j.set(v, vars[v])
try:
j.runScript(script)
finally:
__print_stdout()
def eval_jep(line):
j=__get_jep()
try:
j.eval(line)
finally:
__print_stdout()
def set_jep(var, value):
j=__get_jep()
j.set(var, value)
def get_jep(var):
j=__get_jep()
return j.getValue(var)
def call_jep(module, function, args = [], kwargs = {}, reload=False):
j=__get_jep()
if "/" in module:
script = get_context().scriptManager.library.resolveFile(module)
if "\\" in script:
#Windows paths
module_path = script[0:script.rfind("\\")]
module = script[script.rfind("\\")+1:]
else:
#Linux paths
module_path = script[0:script.rfind("/")]
module = script[script.rfind("/")+1:]
eval_jep("import sys")
eval_jep("sys.path.append('" + module_path + "')")
if module.endswith(".py"):
module = module[0:-3]
f = module+"_" + function+"_"+str(j.hashCode())
try:
if reload:
eval_jep("import " + module)
eval_jep("_=reload(" + module+")")
eval_jep("from " + module + " import " + function + " as " + f)
if (kwargs is not None) and (len(kwargs)>0):
#invoke with kwargs only available in JEP>3.8
hm=java.util.HashMap()
hm.update(kwargs)
#The only way to get the overloaded method...
m = j.getClass().getMethod("invoke", [String, ScriptUtils.getType("[o"), java.util.Map])
ret = m.invoke(j, [f, to_array(args,'o'), hm])
else:
ret = j.invoke(f, args)
finally:
__print_stdout()
return ret
#Converts pythonlist or Java array to numpy array
def to_npa(data, dimensions = None, type = None):
if (not isinstance(data, PyArray)) or (type is not None):
data = to_array(data,'d' if type is None else type)
return jep.NDArray(data, dimensions)
#recursivelly converts all NumPy arrays to Java arrys
def rec_from_npa(obj):
if isinstance(obj, jep.NDArray):
ret = obj.data
if len(obj.dimensions)>1:
ret=Convert.reshape(ret, obj.dimensions)
return ret
if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list):
ret=[]
for i in range(len(obj)):
ret.append(rec_from_npa(obj[i]))
if isinstance(obj,tuple):
return type(ret)
return ret
if isinstance(obj, java.util.Map) or isinstance(obj,dict):
ret = {} if isinstance(obj,dict) else java.util.HashMap()
for k in obj.keys():
ret[k] = rec_from_npa(obj[k])
return ret
return obj
#recursivelly converts all Java arrays to NumPy arrys
def rec_to_npa(obj):
if isinstance(obj, PyArray):
dimensions = Arr.getShape(obj)
if len(dimensions)>1:
obj = Convert.flatten(obj)
return to_npa(obj, dimensions = dimensions)
if isinstance(obj, java.util.List) or isinstance(obj,tuple) or isinstance(obj,list):
ret=[]
for i in range(len(obj)):
ret.append(rec_to_npa(obj[i]))
if isinstance(obj,tuple):
return tuple(ret)
return ret
if isinstance(obj, java.util.Map) or isinstance(obj,dict):
ret = {} if isinstance(obj,dict) else java.util.HashMap()
for k in obj.keys():
ret[k] = rec_to_npa(obj[k])
return ret
return obj
def call_py(module, function, reload_function, *args, **kwargs):
"""
Calls a CPython function recursively crecursively converting Java arrays in arguments to NumPy,
and NumPy arrays in return values to Java arrays.
"""
ret = call_jep(module, function, rec_to_npa(args), rec_to_npa(kwargs), reload=reload_function)
return rec_from_npa(ret)
def import_py(module, function):
"""
Adds a CPython function to globals, creating a wrapper call to JEP, with
recurvive convertion of Java arrays in arguments to NumPy arrays,
and NumPy arrays in return values to Java arrays.
"""
def jep_wrapper(*args, **kwargs):
reload_function = jep_wrapper.reload
jep_wrapper.reload = False
return call_py(module, function, reload_function, *args, **kwargs)
jep_wrapper.reload=True
_get_caller().f_globals[function] = jep_wrapper

681
script/Lib/mathutils.py Normal file
View File

@@ -0,0 +1,681 @@
###################################################################################################
# Facade to Apache Commons Math
###################################################################################################
import sys
import math
import operator
import java.util.List
import java.lang.reflect.Array
import java.lang.Class as Class
import jarray
import org.python.core.PyArray as PyArray
import ch.psi.utils.Convert as Convert
import org.apache.commons.math3.util.FastMath as FastMath
import org.apache.commons.math3.util.Pair as Pair
import org.apache.commons.math3.complex.Complex as Complex
import org.apache.commons.math3.analysis.DifferentiableUnivariateFunction as DifferentiableUnivariateFunction
import org.apache.commons.math3.analysis.function.Gaussian as Gaussian
import org.apache.commons.math3.analysis.function.HarmonicOscillator as HarmonicOscillator
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure as DerivativeStructure
import org.apache.commons.math3.analysis.differentiation.FiniteDifferencesDifferentiator as FiniteDifferencesDifferentiator
import org.apache.commons.math3.analysis.integration.SimpsonIntegrator as SimpsonIntegrator
import org.apache.commons.math3.analysis.integration.TrapezoidIntegrator as TrapezoidIntegrator
import org.apache.commons.math3.analysis.integration.RombergIntegrator as RombergIntegrator
import org.apache.commons.math3.analysis.integration.MidPointIntegrator as MidPointIntegrator
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction as PolynomialFunction
import org.apache.commons.math3.analysis.polynomials.PolynomialFunctionLagrangeForm as PolynomialFunctionLagrangeForm
import org.apache.commons.math3.analysis.solvers.LaguerreSolver as LaguerreSolver
import org.apache.commons.math3.analysis.UnivariateFunction as UnivariateFunction
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator as SplineInterpolator
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator as LinearInterpolator
import org.apache.commons.math3.analysis.interpolation.NevilleInterpolator as NevilleInterpolator
import org.apache.commons.math3.analysis.interpolation.LoessInterpolator as LoessInterpolator
import org.apache.commons.math3.analysis.interpolation.DividedDifferenceInterpolator as DividedDifferenceInterpolator
import org.apache.commons.math3.analysis.interpolation.AkimaSplineInterpolator as AkimaSplineInterpolator
import org.apache.commons.math3.fitting.GaussianCurveFitter as GaussianCurveFitter
import org.apache.commons.math3.fitting.PolynomialCurveFitter as PolynomialCurveFitter
import org.apache.commons.math3.fitting.HarmonicCurveFitter as HarmonicCurveFitter
import org.apache.commons.math3.fitting.WeightedObservedPoint as WeightedObservedPoint
import org.apache.commons.math3.fitting.leastsquares.MultivariateJacobianFunction as MultivariateJacobianFunction
import org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder as LeastSquaresBuilder
import org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer as LevenbergMarquardtOptimizer
import org.apache.commons.math3.fitting.leastsquares.GaussNewtonOptimizer as GaussNewtonOptimizer
import org.apache.commons.math3.stat.regression.SimpleRegression as SimpleRegression
import org.apache.commons.math3.transform.FastFourierTransformer as FastFourierTransformer
import org.apache.commons.math3.transform.DftNormalization as DftNormalization
import org.apache.commons.math3.transform.TransformType as TransformType
import org.apache.commons.math3.linear.ArrayRealVector as ArrayRealVector
import org.apache.commons.math3.linear.Array2DRowRealMatrix as Array2DRowRealMatrix
import org.apache.commons.math3.linear.MatrixUtils as MatrixUtils
###################################################################################################
#Derivative and interpolation
###################################################################################################
def get_values(f, xdata):
"""Return list of values of a function
Args:
f(UnivariateFunction): function
xdata(float array or list): Domain values
Returns:
List of doubles
"""
v = []
for x in xdata:
v.append(f.value(x))
return v
def interpolate(data, xdata = None, interpolation_type = "linear"):
"""Interpolate data array or list to a UnivariateFunction
Args:
data(float array or list): The values to interpolate
xdata(float array or list, optional): Domain values
interpolation_type(str , optional): "linear", "cubic", "akima", "neville", "loess", "newton"
Returns:
UnivariateDifferentiableFunction object
"""
if xdata is None:
from startup import frange
xdata = frange(0, len(data), 1.0)
else:
#X must be ordered
xy = sorted(zip(xdata,data), key=operator.itemgetter(0))
xdata, data = zip(*xy)
if len(data) != len(xdata) or len(data)<2:
raise Exception("Dimension mismatch")
if interpolation_type == "cubic":
i = SplineInterpolator()
elif interpolation_type == "linear":
i = LinearInterpolator()
elif interpolation_type == "akima":
i = AkimaSplineInterpolator()
elif interpolation_type == "neville":
i = NevilleInterpolator()
elif interpolation_type == "loess":
i = LoessInterpolator()
elif interpolation_type == "newton":
i = DividedDifferenceInterpolator()
else:
raise Exception("Invalid interpolation type")
from startup import to_array
return i.interpolate(to_array(xdata,'d'), to_array(data,'d'))
def deriv(f, xdata = None, interpolation_type = "linear"):
"""Calculate derivative of UnivariateFunction, array or list.
Args:
f(UnivariateFunction or array): The function object. If array it is interpolated.
xdata(float array or list, optional): Domain values to process.
interpolation_type(str , optional): "linear", "cubic", "akima", "neville", "loess", "newton"
Returns:
List with the derivative values for xdata
"""
if not isinstance(f,UnivariateFunction):
if xdata is None:
from startup import frange
xdata = frange(0, len(f), 1.0)
f = interpolate(f, xdata, interpolation_type)
if xdata is None:
if isinstance(f,DifferentiableUnivariateFunction):
return f.derivative()
raise Exception("Domain range not defined")
d = []
for x in xdata:
xds = DerivativeStructure(1, 2, 0, x)
yds = f.value(xds)
d.append( yds.getPartialDerivative(1))
return d
def integrate(f, range = None, xdata = None, interpolation_type = "linear", integrator_type = "simpson"):
"""Integrate UnivariateFunction, array or list in an interval.
Args:
f(UnivariateFunction or array): The function object. If array it is interpolated.
range(list, optional): integration range ([min, max]).
xdata(float array or list, optional): disregarded if f is UnivariateFunction.
interpolation_type(str , optional): "linear", "cubic", "akima", "neville", "loess", "newton"
integrator_type(str , optional): "simpson", "trapezoid", "romberg" or "midpoint"
Returns:
Integrated value (Float)
"""
if not isinstance(f, UnivariateFunction):
from startup import frange
if xdata is None:
xdata = frange(0, len(f), 1.0)
if range is None:
range = xdata
f = interpolate(f, xdata, interpolation_type)
if range is None:
raise Exception("Domain range not defined")
d = []
if integrator_type == "simpson":
integrator = SimpsonIntegrator()
elif integrator_type == "trapezoid":
integrator = TrapezoidIntegrator()
elif integrator_type == "romberg":
integrator = RombergIntegrator()
elif integrator_type == "midpoint":
integrator = MidPointIntegrator()
raise Exception("Invalid integrator type")
lower = min(range)
upper = max(range)
return integrator.integrate(MAX_EVALUATIONS, f, lower, upper)
def trapz(y, xdata=None):
"""Integrate an array or list using the composite trapezoidal rule.
Args:
y(array or list)
xdata(float array or list, optional)
"""
return integrate(y, range = None, xdata = xdata, interpolation_type = "linear", integrator_type = "trapezoid")
###################################################################################################
#Fitting and peak search
###################################################################################################
try:
MAX_FLOAT = sys.float_info.max
except: # Python 2.5
MAX_FLOAT = 1.7976931348623157e+308
MAX_ITERATIONS = 1000
MAX_EVALUATIONS = 1000000
def calculate_peaks(function, start_value, end_value = MAX_FLOAT, positive=True):
"""Calculate peaks of a DifferentiableUnivariateFunction in a given range by finding the roots of the derivative
Args:
function(DifferentiableUnivariateFunction): The function object.
start_value(float): start of range
end_value(float, optional): end of range
positive (boolean, optional): True for searching positive peaks, False for negative.
Returns:
List of peaks in the interval
"""
derivative = function.derivative()
derivative2 = derivative.derivative()
ret = []
solver = LaguerreSolver()
for complex in solver.solveAllComplex(derivative.coefficients, start_value):
r = complex.real
if start_value < r < end_value:
if (positive and (derivative2.value(r) < 0)) or ( (not positive) and (derivative2.value(r) > 0)):
ret.append(r)
return ret
def estimate_peak_indexes(data, xdata = None, threshold = None, min_peak_distance = None, positive = True):
"""Estimation of peaks in an array by ordering local maxima according to given criteria.
Args:
data(float array or list)
xdata(float array or list, optional): if not None must have the same length as data.
threshold(float, optional): if specified filter peaks below this value
min_peak_distance(float, optional): if specified defines minimum distance between two peaks.
if xdata == None, it represents index counts, otherwise in xdata units.
positive (boolean, optional): True for searching positive peaks, False for negative.
Returns:
List of peaks indexes.
"""
peaks = []
indexes = sorted(range(len(data)),key=lambda x:data[x])
if positive:
indexes = reversed(indexes)
for index in indexes:
first = (index == 0)
last = (index == (len(data)-1))
val=data[index]
prev = float('NaN') if first else data[index-1]
next = float('NaN') if last else data[index+1]
if threshold is not None:
if (positive and (val<threshold)) or ((not positive) and (val>threshold)):
break
if ( positive and (first or val>prev ) and (last or val>=next ) ) or (
(not positive) and (first or val<prev ) and (last or val<=next ) ):
append = True
if min_peak_distance is not None:
for peak in peaks:
if ((xdata is None) and (abs(peak-index) < min_peak_distance)) or (
(xdata is not None) and (abs(xdata[peak]-xdata[index]) < min_peak_distance)):
append = False
break
if append:
peaks.append(index)
return peaks
def _assert_valid_for_fit(y,x):
if len(y)<2 or ((x is not None) and (len(x)>len(y))):
raise Exception("Invalid data for fit")
def fit_gaussians(y, x, peak_indexes):
"""Fits data on multiple gaussians on the given peak indexes.
Args:
x(float array or list)
y(float array or list)
peak_indexes(list of int)
Returns:
List of tuples of gaussian parameters: (normalization, mean, sigma)
"""
_assert_valid_for_fit(y,x)
ret = []
minimum = min(y)
for peak in peak_indexes:
#Copy data
data = y[:]
#Remover data from other peaks
for p in peak_indexes:
limit = int(round((p+peak)/2))
if (p > peak):
data[limit : len(y)] =[minimum] * (len(y)-limit)
elif (p < peak):
data[0:limit] = [minimum] *limit
#Build fit point list
values = create_fit_point_list(data, x)
maximum = max(data)
gaussian_fitter = GaussianCurveFitter.create().withStartPoint([(maximum-minimum)/2,x[peak],1.0]).withMaxIterations(MAX_ITERATIONS)
#Fit return parameters: (normalization, mean, sigma)
try:
ret.append(gaussian_fitter.fit(values).tolist())
except:
ret.append(None) #Fitting error
return ret
def create_fit_point_list(y, x, weights = None):
values = []
for i in sorted(range(len(x)),key=lambda v:x[v]): #Creating list ordered by x, needed for gauss fit
if weights is None:
values.append(WeightedObservedPoint(1.0, x[i], y[i]))
else:
values.append(WeightedObservedPoint(weights[i], x[i], y[i]))
return values
def fit_polynomial(y, x, order, start_point = None, weights = None):
"""Fits data into a polynomial.
Args:
x(float array or list): observed points x
y(float array or list): observed points y
order(int): if start_point is provided order parameter is disregarded - set to len(start_point)-1.
start_point(optional tuple of float): initial parameters (a0, a1, a2, ...)
weights(optional float array or list): weight for each observed point
Returns:
Tuples of polynomial parameters: (a0, a1, a2, ...)
"""
_assert_valid_for_fit(y,x)
fit_point_list = create_fit_point_list(y, x, weights)
if start_point is None:
polynomial_fitter = PolynomialCurveFitter.create(order).withMaxIterations(MAX_ITERATIONS)
else:
polynomial_fitter = PolynomialCurveFitter.create(0).withStartPoint(start_point).withMaxIterations(MAX_ITERATIONS)
try:
return polynomial_fitter.fit(fit_point_list).tolist()
except:
raise Exception("Fitting failure")
def fit_gaussian(y, x, start_point = None, weights = None):
"""Fits data into a gaussian.
Args:
x(float array or list): observed points x
y(float array or list): observed points y
start_point(optional tuple of float): initial parameters (normalization, mean, sigma)
If None, use a custom initial estimation.
Set to "default" to force Commons.Math the default (GaussianCurveFitter.ParameterGuesser).
weights(optional float array or list): weight for each observed point
Returns:
Tuples of gaussian parameters: (normalization, mean, sigma)
"""
_assert_valid_for_fit(y,x)
fit_point_list = create_fit_point_list(y, x, weights)
#If start point not provided, start on peak
if start_point is None:
maximum, minimum = max(y), min(y)
norm = maximum - minimum
mean = x[y.index(maximum)]
sigma = trapz([v-minimum for v in y], x) / (norm*math.sqrt(2*math.pi))
start_point = (norm, mean, sigma)
elif start_point == "simple":
start_point = [(max(y)-min(y))/2, x[y.index(max(y))], 1.0]
elif start_point == "default":
start_point = GaussianCurveFitter.ParameterGuesser(fit_point_list).guess().tolist()
gaussian_fitter = GaussianCurveFitter.create().withStartPoint(start_point).withMaxIterations(MAX_ITERATIONS)
try:
return gaussian_fitter.fit(fit_point_list).tolist() # (normalization, mean, sigma)
except:
raise Exception("Fitting failure")
def fit_harmonic(y, x, start_point = None, weights = None):
"""Fits data into an harmonic.
Args:
x(float array or list): observed points x
y(float array or list): observed points y
start_point(optional tuple of float): initial parameters (amplitude, angular_frequency, phase)
weights(optional float array or list): weight for each observed point
Returns:
Tuples of harmonic parameters: (amplitude, angular_frequency, phase)
"""
_assert_valid_for_fit(y,x)
fit_point_list = create_fit_point_list(y, x, weights)
if start_point is None:
harmonic_fitter = HarmonicCurveFitter.create().withMaxIterations(MAX_ITERATIONS)
else:
harmonic_fitter = HarmonicCurveFitter.create().withStartPoint(start_point).withMaxIterations(MAX_ITERATIONS)
try:
return harmonic_fitter.fit(fit_point_list).tolist() # (amplitude, angular_frequency, phase)
except:
raise Exception("Fitting failure")
def fit_gaussian_offset(y, x, start_point = None, weights = None):
"""Fits data into a gaussian with offset (constant background).
f(x) = a + b * exp(-(pow((x - c), 2) / (2 * pow(d, 2))))
Args:
x(float array or list): observed points x
y(float array or list): observed points y
start_point(optional tuple of float): initial parameters (normalization, mean, sigma)
weights(optional float array or list): weight for each observed point
Returns:
Tuples of gaussian parameters: (offset, normalization, mean, sigma)
"""
# For normalised gauss curve sigma=1/(amp*sqrt(2*pi))
if start_point is None:
off = min(y) # good enough starting point for offset
com = x[y.index(max(y))]
amp = max(y) - off
sigma = trapz([v-off for v in y], x) / (amp*math.sqrt(2*math.pi))
start_point = [off, amp, com , sigma]
class Model(MultivariateJacobianFunction):
def value(self, variables):
value = ArrayRealVector(len(x))
jacobian = Array2DRowRealMatrix(len(x), 4)
for i in range(len(x)):
(a,b,c,d) = (variables.getEntry(0), variables.getEntry(1), variables.getEntry(2), variables.getEntry(3))
v = math.exp(-(math.pow((x[i] - c), 2) / (2 * math.pow(d, 2))))
model = a + b * v
value.setEntry(i, model)
jacobian.setEntry(i, 0, 1) # derivative with respect to p0 = a
jacobian.setEntry(i, 1, v) # derivative with respect to p1 = b
v2 = b*v*((x[i] - c)/math.pow(d, 2))
jacobian.setEntry(i, 2, v2) # derivative with respect to p2 = c
jacobian.setEntry(i, 3, v2*(x[i] - c)/d ) # derivative with respect to p3 = d
return Pair(value, jacobian)
model = Model()
target = [v for v in y] #the target is to have all points at the positios
(parameters, residuals, rms, evals, iters) = optimize_least_squares(model, target, start_point, weights)
return parameters
def fit_gaussian_linear(y, x, start_point = None, weights = None):
"""Fits data into a gaussian with linear background.
f(x) = a * x + b + c * exp(-(pow((x - d), 2) / (2 * pow(e, 2))))
Args:
x(float array or list): observed points x
y(float array or list): observed points y
start_point(optional tuple of float): initial parameters (normalization, mean, sigma)
weights(optional float array or list): weight for each observed point
Returns:
Tuples of gaussian parameters: (a, b, normalization, mean, sigma)
"""
# For normalised gauss curve sigma=1/(amp*sqrt(2*pi))
if start_point is None:
off = min(y) # good enough starting point for offset
com = x[y.index(max(y))]
amp = max(y) - off
sigma = trapz([v-off for v in y], x) / (amp*math.sqrt(2*math.pi))
start_point = [0, off, amp, com, sigma]
class Model(MultivariateJacobianFunction):
def value(self, variables):
value = ArrayRealVector(len(x))
jacobian = Array2DRowRealMatrix(len(x), 5)
for i in range(len(x)):
(a,b,c,d,e) = (variables.getEntry(0), variables.getEntry(1), variables.getEntry(2), variables.getEntry(3), variables.getEntry(4))
v = math.exp(-(math.pow((x[i] - d), 2) / (2 * math.pow(e, 2))))
model = a*x[i] + b + c * v
value.setEntry(i, model)
jacobian.setEntry(i, 0, x[i]) # derivative with respect to p0 = a
jacobian.setEntry(i, 1, 1) # derivative with respect to p1 = b
jacobian.setEntry(i, 2, v) # derivative with respect to p2 = c
v2 = c*v*((x[i] - d)/math.pow(e, 2))
jacobian.setEntry(i, 3, v2) # derivative with respect to p3 = d
jacobian.setEntry(i, 4, v2*(x[i] - d)/e ) # derivative with respect to p4 = e
return Pair(value, jacobian)
model = Model()
target = [v for v in y] #the target is to have all points at the positios
(parameters, residuals, rms, evals, iters) = optimize_least_squares(model, target, start_point, weights)
return parameters
def fit_gaussian_exp_bkg(y, x, start_point = None, weights = None):
"""Fits data into a gaussian with exponential background.
f(x) = a * math.exp(-(x/b)) + c * exp(-(pow((x - d), 2) / (2 * pow(e, 2))))
Args:
x(float array or list): observed points x
y(float array or list): observed points y
start_point(optional tuple of float): initial parameters (normalization, mean, sigma)
weights(optional float array or list): weight for each observed point
Returns:
Tuples of gaussian parameters: (a,b , normalization, mean, sigma)
"""
# For normalised gauss curve sigma=1/(amp*sqrt(2*pi))
if start_point is None:
off = min(y) # good enough starting point for offset
com = x[len(x)/2]
#com = 11.9
amp = max(y) - off
sigma = trapz([v-off for v in y], x) / (amp*math.sqrt(2*math.pi))
start_point = [1, 1, amp, com, sigma]
class Model(MultivariateJacobianFunction):
def value(self, variables):
value = ArrayRealVector(len(x))
jacobian = Array2DRowRealMatrix(len(x), 5)
for i in range(len(x)):
(a,b,c,d,e) = (variables.getEntry(0), variables.getEntry(1), variables.getEntry(2), variables.getEntry(3), variables.getEntry(4))
v = math.exp(-(math.pow((x[i] - d), 2) / (2 * math.pow(e, 2))))
bkg=math.exp(-(x[i]/b))
model = a*bkg + c * v
value.setEntry(i, model)
jacobian.setEntry(i, 0, bkg) # derivative with respect to p0 = a
jacobian.setEntry(i, 1, a*x[i]*bkg/math.pow(b, 2)) # derivative with respect to p1 = b
jacobian.setEntry(i, 2, v) # derivative with respect to p2 = c
v2 = c*v*((x[i] - d)/math.pow(e, 2))
jacobian.setEntry(i, 3, v2) # derivative with respect to p3 = d
jacobian.setEntry(i, 4, v2*(x[i] - d)/e ) # derivative with respect to p4 = e
return Pair(value, jacobian)
model = Model()
target = [v for v in y] #the target is to have all points at the positios
(parameters, residuals, rms, evals, iters) = optimize_least_squares(model, target, start_point, weights)
return parameters
###################################################################################################
#Functions
###################################################################################################
class GaussianOffset(UnivariateFunction):
def __init__(self, offset, normalization, mean_value, sigma):
self.gaussian = Gaussian(normalization, mean_value, sigma)
self.offset = offset
def value(self,x):
return self.gaussian.value(x) + self.offset
class GaussianLinear(UnivariateFunction):
def __init__(self, a,b, normalization, mean_value, sigma):
self.gaussian = Gaussian(normalization, mean_value, sigma)
self.a = a
self.b = b
def value(self,x):
return self.gaussian.value(x) + self.a * x + self.b
class GaussianExpBkg(UnivariateFunction):
def __init__(self, a, b, normalization, mean_value, sigma):
self.gaussian = Gaussian(normalization, mean_value, sigma)
self.a = a
self.b = b
def value(self,x):
return self.gaussian.value(x) + self.a * math.exp(-(x/self.b))
###################################################################################################
#Least squares
###################################################################################################
def optimize_least_squares(model, target, initial, weights):
"""Fits a parametric model to a set of observed values by minimizing a cost function.
Args:
model(MultivariateJacobianFunction): observed points x
target(float array or list): observed data
initial(optional tuple of float): initial guess
weights(optional float array or list): weight for each observed point
Returns:
Tuples of harmonic parameters: (amplitude, angular_frequency, phase)
"""
if isinstance(weights,tuple) or isinstance(weights,list):
weights = MatrixUtils.createRealDiagonalMatrix(weights)
problem = LeastSquaresBuilder().start(initial).model(model).target(target).lazyEvaluation(False).maxEvaluations(MAX_EVALUATIONS).maxIterations(MAX_ITERATIONS).weight(weights).build()
optimizer = LevenbergMarquardtOptimizer()
optimum = optimizer.optimize(problem)
parameters=optimum.getPoint().toArray().tolist()
residuals = optimum.getResiduals().toArray().tolist()
rms = optimum.getRMS()
evals = optimum.getEvaluations()
iters = optimum.getIterations()
return (parameters, residuals, rms, evals, iters)
###################################################################################################
#FFT
###################################################################################################
def is_power(num, base):
if base<=1: return num == 1
power = int (math.log (num, base) + 0.5)
return base ** power == num
def pad_to_power_of_two(data):
if is_power(len(data),2):
return data
pad =(1 << len(data).bit_length()) - len(data)
elem = complex(0,0) if type(data[0]) is complex else [0.0,]
return data + elem * pad
def get_real(values):
"""Returns real part of a complex numbers vector.
Args:
values: List of complex.
Returns:
List of float
"""
ret = []
for c in values:
ret.append(c.real)
return ret
def get_imag(values):
"""Returns imaginary part of a complex numbers vector.
Args:
values: List of complex.
Returns:
List of float
"""
ret = []
for c in values:
ret.append(c.imag)
return ret
def get_modulus(values):
"""Returns the modulus of a complex numbers vector.
Args:
values: List of complex.
Returns:
List of float
"""
ret = []
for c in values:
ret.append(math.hypot(c.imag,c.real))
return ret
def get_phase(values):
"""Returns the phase of a complex numbers vector.
Args:
values: List of complex.
Returns:
List of float
"""
ret = []
for c in values:
ret.append(math.atan(c.imag/c.real))
return ret
def fft(f):
"""Calculates the Fast Fourrier Transform of a vector, padding to the next power of 2 elements.
Args:
values(): List of float or complex
Returns:
List of complex
"""
f = pad_to_power_of_two(f)
if type(f[0]) is complex:
aux = []
for c in f:
aux.append(Complex(c.real, c.imag))
f = aux
fftt = FastFourierTransformer(DftNormalization.STANDARD)
ret = []
for c in fftt.transform(f,TransformType.FORWARD ):
ret.append(complex(c.getReal(),c.getImaginary()))
return ret
def ffti(f):
"""Calculates the Inverse Fast Fourrier Transform of a vector, padding to the next power of 2 elements.
Args:
values(): List of float or complex
Returns:
List of complex
"""
f = pad_to_power_of_two(f)
if type(f[0]) is complex:
aux = []
for c in f:
aux.append(Complex(c.real, c.imag))
f = aux
fftt = FastFourierTransformer(DftNormalization.STANDARD)
ret = []
for c in fftt.transform(f,TransformType.INVERSE ):
ret.append(complex(c.getReal(),c.getImaginary()))
return ret

119
script/Lib/plotutils.py Normal file
View File

@@ -0,0 +1,119 @@
###################################################################################################
# Plot utilities
###################################################################################################
import ch.psi.pshell.plot.LinePlotSeries as LinePlotSeries
import ch.psi.pshell.plot.LinePlotErrorSeries as LinePlotErrorSeries
import math
from startup import frange, to_array
def plot_function(plot, function, name, range, show_points = True, show_lines = True, color = None):
"""Plots a function to a plot.
Args:
plot(LinePlot)
function(UnivariateFunction): Gaussian, PolynomialFunction, HarmonicOscillator...
name(str): name of the series
range(list or array of floats): x values to plot
Returns:
Tuples of harmonic parameters: (amplitude, angular_frequency, phase)
"""
if plot.style.isError():
s = LinePlotErrorSeries(name, color)
else:
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setPointsVisible(show_points)
s.setLinesVisible(show_lines)
for x in range:
s.appendData(x, function.value(x))
return s
def plot_data(plot, data, name, xdata = None, error = None, show_points = True, show_lines = True, color = None):
"""Plots a subscriptable object to a plot.
Args:
plot(LinePlot)
data(subscriptable): Y data
name(str): name of the series
xdata(subscriptable): X data
error(subscriptable): Error data (only for error plots)
Returns:
Tuples of harmonic parameters: (amplitude, angular_frequency, phase)
"""
if plot.style.isError():
s = LinePlotErrorSeries(name, color)
else:
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setPointsVisible(show_points)
s.setLinesVisible(show_lines)
if xdata is None:
xdata = range(len(data))
xdata = to_array(xdata, 'd')
data = to_array(data, 'd')
if plot.style.isError():
error = to_array(error, 'd')
s.setData(xdata, data, error)
else:
s.setData(xdata, data)
return s
def plot_point(plot, x, y, size = 3, color = None, name = "Point"):
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setPointSize(size)
s.appendData(x, y)
return s
def plot_line(plot, x1, y1, x2, y2, width = 1, color = None, name = "Line"):
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setLineWidth(width)
s.setPointsVisible(False)
s.appendData(x1, y1)
s.appendData(x2, y2)
return s
def plot_cross(plot, x, y, size = 1.0, width = 1, color = None, name = "Cross"):
size = float(size)
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setLineWidth(width)
s.setPointsVisible(False)
s.appendData(float('nan'), float('nan'))
s.appendData(x-size/2, y)
s.appendData(x+size/2, y)
s.appendData(float('nan'), float('nan'))
s.appendData(x, y-size/2)
s.appendData(x, y+size/2)
return s
def plot_rectangle(plot, x1, y1, x2, y2, width = 1, color = None, name = "Rectangle"):
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setLineWidth(width)
s.setPointsVisible(False)
s.appendData(x1, y1)
s.appendData(x1, y2)
s.appendData(x2, y2)
s.appendData(x2, y1)
s.appendData(x1, y1)
return s
def plot_circle(plot, cx, cy, radius, width = 1, color = None, name = "Circle"):
s = LinePlotSeries(name, color)
plot.addSeries(s)
s.setLineWidth(width)
s.setPointsVisible(False)
res=float(radius) / 100.0
epson = 1e-12
for xp in frange (cx+radius-epson , cx-radius+epson , -res):
yp = math.sqrt(math.pow(radius, 2) - math.pow(xp - cx, 2)) + cy
s.appendData(xp, yp)
for xp in frange (cx-radius+epson , cx+radius-epson, res):
yp = -math.sqrt(math.pow(radius, 2) - math.pow(xp - cx, 2)) + cy
s.appendData(xp, yp)
if s.getCount()>0:
s.appendData(s.getX()[0], s.getY()[0])
return s

149
script/Lib/rsync.py Normal file
View File

@@ -0,0 +1,149 @@
####################################################################################################
# Utilities for synchronizing folders with rsync
# On RH7 (not SL6)
# Change permission of the account, otherwise SSH keys are not accepted:
# ~/.ssh from drwxr-S--- to drwx----
# ~ : from drwxrws--- to drwxr-s---
####################################################################################################
import sys
import os
import os.path
import shutil
import ch.psi.utils.Sys
from startup import exec_cmd, log
RSYNC_GENERATE_USER_KEY = True
XTERM = "/opt/X11/bin/xterm" if ch.psi.utils.Sys.getOSFamily().name()=="Mac" else "xterm"
def rsync(src, dest, key):
#cmd = 'rsync -e "ssh -i ' + key + ' -o LogLevel=quiet" --chmod=ug=rwx --verbose --modify-window=1 --times --recursive ' + src + ' ' + dest
#ret = exec_cmd(cmd)
cmd = 'rsync -e "ssh -i ' + key + '" --chmod=ug=rwx --verbose --modify-window=1 --times --recursive ' + src + ' ' + dest
ret = exec_cmd(cmd, False)
lines = ret.split("\n")
lines = filter(lambda x: x != "", lines)
if len(lines)<3:
print "Invalid return from rsync:\n", ret
raise Exception ("Invalid format")
#files = lines[1:-2]
files = []
head,tail=os.path.split(src)
for l in lines:
f = os.path.join(head,l)
if os.path.exists(f):
files.append(f)
try:
stats = lines[-2].replace(",", "").replace(".", "")
stats = [int(s) for s in stats.split() if s.isdigit()]
bytes_sent, bytes_received = stats[0], stats[1]
except:
print "Invalid statistics from rsync:\n", ret
bytes_sent, bytes_received = None, None
return files, bytes_sent, bytes_received
def sync_user_data(user, src, dest, host= "localhost", remove_local_folder=False, remove_local_files=False, do_log=True, do_print=True):
try:
if do_log:
log("Start synchronizing %s to %s:%s" % (src, user, dest), False )
key = os.path.expanduser("~/.ssh/" + ("ke" if RSYNC_GENERATE_USER_KEY else "id_rsa"))
if not os.path.isfile(key):
raise Exception ("Invalid key file")
dest = "'" + dest.replace(" ", "\ ") + "'"
dest = user + "@" + host + ":" + dest
files, bytes_sent, bytes_received = rsync(src,dest,key)
msg = "Transferred " + str(bytes_sent) + " bytes to " + user + ": "
for f in files:
msg = msg + "\n" + f
if do_log:
log(msg, False)
if do_print:
print msg
if remove_local_folder:
if do_log:
log("Removing folder: " + src)
shutil.rmtree(src)
elif remove_local_files:
for f in files:
if not os.path.samefile(f, src):
if os.path.isfile(f):
if do_log:
log("Removing file: " + f)
os.remove(f)
elif os.path.isdir(f):
if do_log:
log("Removing folder: " + f)
shutil.rmtree(f)
except:
msg = "Error transferring user data to " + user + ": " + str(sys.exc_info()[1])
if do_log:
log(msg, False)
if do_print:
print >> sys.stderr, msg
return msg
def remove_user_key(do_print=True):
cmd = "rm ~/.ssh/ke;"
cmd = cmd + "rm ~/.ssh/ke.pub"
ret = exec_cmd(cmd, False)
if do_print:
if not ret.strip():
ret = "Success removing ssh keys"
print ret
def reset_user_key(do_print=True):
remove_user_key(do_print)
cmd = "ssh-keygen -N '' -f ~/.ssh/ke -t rsa;"
ret = exec_cmd(cmd)
if do_print:
print ret
def authorize_user(user, aux_file = os.path.expanduser("~/.rsync.tmp"), fix_permissions=True, do_print=True):
if (os.path.isfile(aux_file)):
os.remove(aux_file)
with open(aux_file, "w") as fh:
fh.write("Cannot access file: " + aux_file)
os.chmod(aux_file, 0o777)
success_msg = 'Success transfering authorization key for: ' + user
cmd = 'echo Authorizing: ' + user + ";"
cmd = cmd + 'echo Invalid user or password > ' + aux_file + ";"
cmd = cmd + "export PK_SUCCESS=FAILURE;"
if RSYNC_GENERATE_USER_KEY:
reset_user_key(do_print)
cmd = cmd + "export PK=`cat ~/.ssh/ke.pub`;"
else:
cmd = cmd + "export PK=`cat ~/.ssh/id_rsa.pub`;"
cmd = cmd + 'su - ' + user + ' bash -c "'
cmd = cmd + 'echo $PK >> .ssh/authorized_keys;'
#cmd = cmd + 'sort .ssh/authorized_keys | uniq > .ssh/authorized_keys.uniq;'
#cmd = cmd + 'mv .ssh/authorized_keys.uniq .ssh/authorized_keys;'
if fix_permissions:
cmd = cmd + 'chmod g-w ~' + ";"
cmd = cmd + 'echo ' + success_msg + ";"
cmd = cmd + 'echo ' + success_msg + " > " + aux_file + ";"
cmd = cmd + '"'
#xterm_options = '-hold -T "Authentication" -into 44040199' #Get Winfow ID with 'wmctrl -lp'
xterm_options = '-T "Authentication" -fa monaco -fs 14 -bg black -fg green -geometry 80x15+400+100'
try:
ret = exec_cmd(XTERM + " " + xterm_options + " -e '" + cmd + "'")
with open (aux_file, "r") as myfile:
ret=myfile.read()
#;if [ "$depth" -eq "1" ]; then echo ' + success_msg + '; fi')
if not success_msg in ret:
raise Exception (ret)
except:
if RSYNC_GENERATE_USER_KEY:
remove_user_key(do_print)
raise Exception ("Error authenticating user: " + str(sys.exc_info()[1]))
finally:
if (os.path.isfile(aux_file)):
os.remove(aux_file)
return ret
def is_authorized():
key = os.path.expanduser("~/.ssh/" + ("ke" if RSYNC_GENERATE_USER_KEY else "id_rsa"))
return os.path.isfile(key)

348
script/Lib/sessions.py Normal file
View File

@@ -0,0 +1,348 @@
from startup import get_context, set_exec_pars
import ch.psi.utils.SciCat as SciCat
import java.lang.Boolean
def _sm():
return get_context().sessionManager
def session_start(name, metadata=None):
""" Starts new session. If a session os open, completes it first.
Args:
name(str): Session name.
metadata(dict): Map of initial metadata parameters
If None(Default) use the default metadata definition.
Returns:
session id (int)
"""
set_exec_pars(open=False)
return _sm().start(name, metadata)
def session_complete():
""" Completes current session, if started.
"""
set_exec_pars(open=False)
return _sm().stop()
def session_pause():
""" Pauses current session, if started.
"""
return _sm().pause()
def session_resume():
""" Resumes current session, if paused.
"""
return _sm().resume()
def session_cancel():
""" Cancels current session, if started and empty (no generated data).
"""
return _sm().cancel()
def session_restart(id):
""" Reopens a completed if not yet archived and if belongs to the same user.
Args:
id(int): Session id.
"""
return _sm().restart(id)
def session_move(origin, files, dest):
""" Moves a list of run files (relative to root) to another session.
Sessions must not be archived and belong to the same user.
Args:
origin(int): Origin session id.
files(list): file names
dest(int): Destination session id.
"""
return _sm().move(origin, files, dest)
def session_detach(name, id, files):
""" Detaches a list of run files (relative to root) to a new session.
Session must not be archived and belong to the same user.
Args:
name(str): Name of new session.
id(int): Session id.
files(list): file names
Returns:
New session id (int)
"""
return _sm().detach(name, id, files)
def session_create(name, files, metadata=None, root=None):
""" Create a session from existing data files.
Args:
name(str): Name of new session.
files(list): file names relative to root
metadata(dict): Map of initial metadata parameters
If None(Default) use the default metadata definition.
root(str): data root path. If None(Default) uses default data path.
Returns:
New session id (int)
"""
return _sm().create(name, files, metadata, root)
def session_id():
""" Returns current session id (0 if no session is started).
Returns:
session id (int)
"""
return _sm().getCurrentSession()
def session_name():
""" Returns current session name ("unknown" if no session is started)
Returns:
session name(str)
"""
return _sm().getCurrentName()
def session_started():
""" Returns true if a session is started.
Returns:
bool
"""
return _sm().isStarted()
def session_paused():
""" Returns true if current session is paused.
Returns:
bool
"""
return _sm().isPaused()
def session_add_file(path):
""" Adds additional file to session, if started.
Args:
path(str): Relative to data path or absolute.
"""
return _sm().addAdditionalFile(path)
def session_ids():
""" Returns list of completed sessions.
Returns:
list of int
"""
return _sm().getIDs()
def session_get_name(id=None):
""" Return the name of a session.
Args:
id(int): Session id. Default (None) is the current session.
Returns:
session name (str)
"""
return _sm().getName() if id is None else _sm().getName(id)
def session_get_state(id=None):
""" Returns the session state
Args:
id(int): Session id. Default (None) is the current session.
Returns:
session state (str)
"""
return _sm().getState() if id is None else _sm().getState(id)
def session_get_start(id=None):
""" Returns the start timestamp of a session.
Args:
id(int): Session id. Default (None) is the current session.
Returns:
long
"""
return _sm().getStart() if id is None else _sm().getStart(id)
def session_get_stop(id):
""" Returns the stop timestamp of a completed session.
Args:
id(int): Session id.
Returns:
Timestamp (long)
"""
return _sm().getStop(id)
def session_get_root(id=None):
""" Returns the root data path of a session.
Args:
id(int): Session id. Default (None) is the current session.
Returns:
str
"""
return _sm().getRoot() if id is None else _sm().getRoot(id)
def session_get_info(id=None):
""" Returns the session information.
Args:
id(int): Session id. Default (None) is the current session.
Returns:
session info (dict)
"""
return _sm().getInfo() if id is None else _sm().getInfo(id)
def session_get_metadata(id=None):
""" Returns a session info metadata.
Args:
id(int): Session id. Default (None) is the current session.
Returns:
session metadata (dict)
"""
return _sm().getMetadata() if id is None else _sm().getMetadata(id)
def session_set_metadata(key, value,id=None):
""" Set session metadata entry.
Args:
key(str): Metadata key
value(obj): Metadata value
id(int): Session id. Default (None) is the current session.
"""
return _sm().setMetadata(key, value) if id is None else _sm().setMetadata(id,key, value)
def session_get_metadata_keys():
""" Return the default metadata definition for samples.
Returns:
list of map entries
"""
return [str(e.key) for e in _sm().getMetadataDefinition()]
def session_get_metadata_type(key):
""" Return the metadata type for a given key:
String, Integer, Double, Boolean, List or Map.
Args:
key(str): Metadata key.
Returns:
str
"""
return str(_sm().getMetadataType(key))
def session_get_metadata_default(key):
""" Return the metadata default value for a given key.
Args:
key(str): Metadata key.
Returns:
Object
"""
return _sm().getMetadataDefault(key)
def session_get_runs(id=None, relative=True):
""" Return the runs of a session.
Args:
id(int): Session id. Default (None) is the current session.
relative(bool): if True use relative file names (for files under the data root path)
Returns:
List of dicts
"""
return _sm().getRuns(java.lang.Boolean(relative)) if id is None else _sm().getRuns(id, relative)
def session_set_run_enabled(enabled, id=None, index=-1):
""" Enable or disable a run.
Args:
enabled(bool): true for enabling, false for disabling
id(int): Session id. Default (None) is the current session.
index: Index of the run. Default (-1) for the last run.
Returns:
Object
"""
return _sm().setRunEnabled(index, enabled) if id is None else _sm().setRunEnabled(id, index, enabled)
def session_get_additional_files(id=None, relative=True):
""" Return additional files of a session.
Args:
id(int): Session id. Default (None) is the current session.
relative(bool): if True use relative file names (for files under the data root path)
Returns:
List of str
"""
return _sm().getAdditionalFiles(java.lang.Boolean(relative)) if id is None else _sm().getAdditionalFiles(id, relative)
def session_get_file_list(id=None, relative=True):
""" Return complete list of data files of a session.
Args:
id(int): Session id. Default (None) is the current session.
relative(bool): if True use relative file names (for files under the data root path)
Returns:
List of str
"""
return _sm().getFileList(java.lang.Boolean(relative)) if id is None else _sm().getFileList(id, relative)
def session_create_zip(file_name, id=None, preserve_folder_structure=True):
""" Create ZIP file with session contents
Args:
file_name(str): name of the zip file
id(int): Session id. Default (None) is the current session.
preserve_folder_structure: if False all data files are added to the root of the file.
if True the folder structure under data root is preserved.
"""
return _sm().createZipFile(file_name, preserve_folder_structure) if id is None else _sm().createZipFile(id, file_name, preserve_folder_structure)
def session_ingest_scicat(id, matadata={}):
""" Ingest a completed session to SciCat
Args:
id(int): Session id.
matadata(dict): session metadata
Returns:
Tuple (Dataset Name, Dataset ID) in case of success. Otherwise throws an exception.
"""
sciCat= SciCat()
result = sciCat.ingest(id, matadata)
print result.output
if not result.success:
raise Exception ("Error ingesting session " + str(id))
return result.datasetName, result.datasetId

207
script/Lib/startup.py Normal file
View File

@@ -0,0 +1,207 @@
###################################################################################################
# Global definitions and built-in functions
###################################################################################################
from builtin_utils import *
from builtin_classes import *
from builtin_functions import *
###################################################################################################
#Default empty callbacks
###################################################################################################
def on_command_started(info): pass
def on_command_finished(info): pass
def on_session_started(id): pass
def on_session_finished(id): pass
def on_change_data_path(path): pass
###################################################################################################
#Help and access to function documentation
###################################################################################################
def _getBuiltinFunctions(filter = None):
ret = []
for name in globals().keys():
val = globals()[name]
if type(val) is PyFunction:
if filter is None or filter in name:
#Only "public" documented functions
if not name.startswith('_') and (val.__doc__ is not None):
ret.append(val)
return to_array(ret)
def _getBuiltinFunctionNames(filter = None):
ret = []
for function in _getBuiltinFunctions(filter):
ret.append(function.func_name)
return to_array(ret)
def _getFunctionDoc(function):
if is_string(function):
if function not in globals():
return
function = globals()[function]
if type(function) is PyFunction and '__doc__' in dir(function):
ac = function.func_code.co_argcount
var = function.func_code.co_varnames
args = list(var)[:ac]
defs = function.func_defaults
if defs is not None:
for i in range (len(defs)):
index = len(args) - len(defs) + i
args[index] = args[index] + " = " + str(defs[i])
flags = function.func_code.co_flags
if flags & 4 > 0:
args.append('*' + var[ac])
ac=ac+1
if flags & 8 > 0:
args.append('**' + var[ac])
d = function.func_doc
return function.func_name+ "(" + ", ".join(args) + ")" + "\n\n" + (d if (d is not None) else "")
def help(object = None):
"""
Print help message for function or object (if available).
Args:
object (any, optional): function or object to get help.
If null prints a list of the builtin functions.
Returns:
None
"""
if object is None:
print "Built-in functions:"
for f in _getBuiltinFunctionNames():
print "\t" + f
else:
if type(object) is PyFunction:
print _getFunctionDoc(object)
elif '__doc__' in dir(object):
#The default doc is now shown
import org.python.core.BuiltinDocs.object_doc
if object.__doc__ != org.python.core.BuiltinDocs.object_doc:
print object.__doc__
###################################################################################################
#Variable injection
###################################################################################################
def _get_caller():
#Not doing inspect.currentframe().f_back because inspect is slow to load
return sys._getframe(1).f_back if hasattr(sys, "_getframe") else None
def inject():
"""Restore initial globals: re-inject devices and startup variables to the interpreter.
Args:
None
Returns:
None
"""
if __name__ == "__main__":
get_context().injectVars()
else:
_get_caller().f_globals.update(get_context().scriptManager.injections)
###################################################################################################
#Script evaluation and return values
###################################################################################################
def run(script_name, args = None, locals = None):
"""Run script: can be absolute path, relative, or short name to be search in the path.
Args:
args(Dict ot List): Sets sys.argv (if list) or gobal variables(if dict) to the script.
locals(Dict): If not none sets the locals()for the runing script.
If locals is used then script definitions will not go to global namespace.
Returns:
The script return value (if set with set_return)
"""
script = get_context().scriptManager.library.resolveFile(script_name)
if script is not None and os.path.isfile(script):
info = get_context().startScriptExecution(script_name, args)
try:
set_return(None)
if args is not None:
if isinstance(args,list) or isinstance(args,tuple):
sys.argv = list(args)
globals()["args"] = sys.argv
else:
for arg in args.keys():
globals()[arg] = args[arg]
if (locals is None):
execfile(script, globals())
else:
execfile(script, globals(), locals)
ret = get_return()
get_context().finishScriptExecution(info, ret)
return ret
except Exception, ex:
get_context().finishScriptExecution(info, ex)
raise ex
raise IOError("Invalid script: " + str(script_name))
def abort():
"""Abort the execution of ongoing task. It can be called from the script to quit.
Args:
None
Returns:
None
"""
fork(get_context().abort) #Cannot be on script execution thread
while True: sleep(10.0)
def set_return(value):
"""Sets the script return value. This value is returned by the "run" function.
Args:
value(Object): script return value.
Returns:
None
"""
#In Jython, the output of last statement is not returned when running a file
if __name__ == "__main__":
global __THREAD_EXEC_RESULT__
if is_interpreter_thread():
global _
_=value
__THREAD_EXEC_RESULT__[java.lang.Thread.currentThread()]=value #Used when running file
else:
#if startup is imported, cannot set global
caller = _get_caller()
if is_interpreter_thread():
caller.f_globals["_"]=value
if not "__THREAD_EXEC_RESULT__" in caller.f_globals.keys():
caller.f_globals["__THREAD_EXEC_RESULT__"] = {}
caller.f_globals["__THREAD_EXEC_RESULT__"][java.lang.Thread.currentThread()]=value
return value #Used when parsing file
def get_return():
if __name__ == "__main__":
global __THREAD_EXEC_RESULT__
return __THREAD_EXEC_RESULT__[java.lang.Thread.currentThread()]
else:
return _get_caller().f_globals["__THREAD_EXEC_RESULT__"][java.lang.Thread.currentThread()]
###################################################################################################
#Executed on startup
###################################################################################################
if __name__ == "__main__":
ca_channel_path=os.path.join(get_context().setup.getStandardLibraryPath(), "epics")
sys.path.append(ca_channel_path)
#This is to destroy previous context of _ca (it is not shared with PShell)
if run_count > 0:
if sys.modules.has_key("_ca"):
print
import _ca
_ca.initialize()

2836
script/Lib/startup_c.py Normal file

File diff suppressed because it is too large Load Diff

191
script/Lib/statsutils.py Normal file
View File

@@ -0,0 +1,191 @@
###################################################################################################
# Utilities for generating reports from command statistics files
###################################################################################################
#CsvJdbc JAR file must be downloaded to extensions folder:
#http://central.maven.org/maven2/net/sourceforge/csvjdbc/csvjdbc/1.0.34/csvjdbc-1.0.34.jar
import java.sql.DriverManager as DriverManager
import java.sql.ResultSet as ResultSet
import java.util.Properties as Properties
import java.lang.Class as Class
import os
from startup import get_context, expand_path
import ch.psi.pshell.core.CommandManager.CommandStatisticsFileRange as CommandStatisticsFileRange
stmt = None
STAT_COLUMN_NAMES = ["Command","Args","Source","Start","End","Background","Result","Return"]
def get_stats_connection():
global stmt
Class.forName("org.relique.jdbc.csv.CsvDriver");
db = os.path.abspath(expand_path("{home}/statistics"))
props = Properties()
props.put("fileExtension", ".csv")
props.put("separator", ";")
props.put("timestampFormat", "dd/MM/yy HH:mm:ss.SSS")
props.put("indexedFiles", "true");
props.put("columnTypes", "String,String,String,Timestamp,Timestamp,Boolean,String,String");
fileRange = get_context().commandManager.commandStatisticsConfig.fileRange
if fileRange==CommandStatisticsFileRange.Daily:
props.put("fileTailPattern", "(\\d+)_(\\d+)_(\\d+)");
props.put("fileTailParts", "Year,Month,Day");
elif fileRange==CommandStatisticsFileRange.Monthly:
props.put("fileTailPattern", "(\\d+)_(\\d+)"); #props.put("fileTailPattern", "-(\\d+)_(\\d+)");
props.put("fileTailParts", "Year,Month");
elif fileRange==CommandStatisticsFileRange.Yearly:
props.put("fileTailPattern", "(\\d+)");
props.put("fileTailParts", "Year");
conn = DriverManager.getConnection("jdbc:relique:csv:" + db, props);
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
return conn
def _get_count(sql):
ret = 0
results = stmt.executeQuery("SELECT COUNT(*) AS count FROM . WHERE " + sql)
if results.first():
ret = results.getInt("count")
return ret
def _add_sql_time(sql, start, end):
if start:
if len(start)==8:
start = start + " 00:00:00.000"
sql = sql + " AND Start>='" + start + "'"
if end:
if len(end)==8:
end = end + " 00:00:00.000"
sql = sql + " AND (\"End\"<'" + end + "')"
return sql
def get_count(command= "%%", start = None, end = None, result= "%%"):
sql = "Command LIKE '"+ command +"' AND Result LIKE '"+ result +"'"
sql = _add_sql_time(sql, start, end)
return _get_count(sql)
def get_return_count(command= "%%", start = None, end = None, ret= "%%"):
sql = "Command LIKE '"+ command +"' AND Return = '"+ ret +"'"
sql = _add_sql_time(sql, start, end)
return _get_count(sql)
def get_cmd_stats(command = "%", start = None, end = None):
s = get_count(command, start, end, "success")
a = get_count(command, start, end, "abort")
e = get_count(command, start, end, "error")
return (s,a,e)
def get_errors(command = "%", start = None, end = None):
sql = "SELECT Return, Count(Return) as count FROM . WHERE Command LIKE '"+ command +"' AND Result='error'"
sql = _add_sql_time(sql, start, end)
sql = sql + " GROUP BY Return ORDER BY count DESC"
results = stmt.executeQuery(sql)
ret = []
while results.next():
ret.append((results.getInt("count"), results.getString("Return")))
return ret
def get_cmd_records(command = "%", start = None, end = None, result= "%%"):
sql = "SELECT * FROM . WHERE Command LIKE '"+ command +"' AND Result LIKE '"+ result +"'"
sql = _add_sql_time(sql, start, end)
results = stmt.executeQuery(sql)
ret = []
while results.next():
rec={}
for col in STAT_COLUMN_NAMES:
rec[col]= results.getString(col)
ret.append(rec)
return ret
def get_commands(commands =None, start = None, end = None):
ret = []
if (commands is None) or (len(commands)==0):
sql = "SELECT * FROM . WHERE Command != ''"
sql = _add_sql_time(sql, start, end)
sql = sql + " GROUP BY Command"
results = stmt.executeQuery(sql)
while results.next():
cmd = results.getString("Command")
if cmd and not " " in cmd:
ret.append(cmd)
else:
for cmd in commands:
if get_count(cmd, start, end) >0 :
ret.append(cmd)
return ret
def print_cmd_stats(command = "%", start = None, end = None):
print "-----------------------------------------------------------"
print "Statistics from ", start , " to ", end
(s,a,e) = get_cmd_stats(command, start, end)
t=s+a+e #get_count(command, start, end, "%")
print "Command: " , command , " Records: ", t
if t>0:
print "%-10s %7.2f%% - %d" % ("Success", (float(s)/t) * 100, s)
print "%-10s %7.2f%% - %d" % ("Abort", (float(a)/t) * 100, a)
print "%-10s %7.2f%% - %d" % ("Error", (float(e)/t) * 100, e)
print "\nErrors:"
print "%5s %s" % ("Count", "Error")
errors = get_errors(command, start, end)
for error in errors:
print "%5d %s" % (error[0], error[1])
print "-----------------------------------------------------------"
def print_cmd_records(command = "%", start = None, end = None, result= "%%"):
print "-----------------------------------------------------------"
print "Records from ", start , " to ", end
info = get_cmd_records(command, start, end, result)
print "Command: " , command , " Result: ", result, " Records: ", len(info)
for col in STAT_COLUMN_NAMES:
print col+ "; " ,
print
for cmd in info:
s = ""
for col in STAT_COLUMN_NAMES:
s = s + cmd[col]+ "; "
print s
print "-----------------------------------------------------------"
def print_stats(commands = None, start = None, end = None):
print "-----------------------------------------------------------"
print "Statistics from ", start , " to ", end
print "%-20s %-5s %8s %8s %8s" % ("Command", "Total", "Success", "Abort", "Error")
cmds = get_commands(commands)
for cmd in cmds:
(s,a,e) = get_cmd_stats(cmd, start, end)
t=s+a+e
if t>0:
print "%-20s %-5d %7.2f%% %7.2f%% %7.2f%%" % (cmd, t, (float(s)/t) * 100, (float(a)/t) * 100, (float(e)/t) * 100)
else:
print "%-20s %-5d" % (cmd, t)
print "-----------------------------------------------------------"
if __name__=='__main__':
conn = get_stats_connection()
#Print stats of all commands, with no time range
print_stats()
cmds = ["%scan1%", "%scan2%"]
start= "01/03/19"
end= "01/04/19"
#Print stats all commands containing 'scan1' and 'scan2' in the month 03.2019
print_stats(cmds, start, end)
#Print individual statistics, including error count, for commands containing 'scan1' and 'scan2'
for cmd in cmds:
print_cmd_stats (cmd, start, end)
#Print all records for commands containing 'scan1'
print_cmd_records("%scan1%%", start, end, "error")
conn.close()

7
script/local.py Executable file
View File

@@ -0,0 +1,7 @@
###################################################################################################
# Deployment specific global definitions - executed after startup.py
###################################################################################################
run("psss/psss")

73
script/psss/CameraScan.py Executable file
View File

@@ -0,0 +1,73 @@
#Scan the PSSS camera position
#Purpose:
#To set or confirm the camera is positioned with the measured spectrum in the centre of the spectral integration window
#If running from editor
if get_exec_pars().source == CommandSource.ui:
#User inputs - define travel range of camera
RANGE_FROM = -17
RANGE_TO = -11
STEPS = 20
NUM_SHOTS= 10 #100
PLOT=None
p = plot(None, title="Data")[0] if (PLOT is None) else PLOT
p.clear()
p.removeMarker(None)
p.setLegendVisible(True)
p.addSeries(LinePlotSeries("PSSS Spectrum Average"))
run("cpython/wrapper")
if not is_dry_run():
cam_x=Channel("SARFE10-PSSS059:MOTOR_X5.VAL", name="cam_x")
else:
cam_x=DummyRegister("cam_x")
av = create_averager(psss_spectrum_y, NUM_SHOTS, interval=-1, name="spectrum_average")
av_samples = av.samples
av_samples.alias = "spectrum_samples"
#Scan and take data
def after_read(record, scan):
p.getSeries(0).setData(psss_spectrum_x.take(), record[av])
p.setTitle("Cam X = %1.3f" %(record[cam_x]))
r = lscan(cam_x, (av, av_samples), RANGE_FROM, RANGE_TO, STEPS, latency=0.0, after_read = after_read, save=False)
average, samples, cam_range = r.getReadable(0), r.getReadable(1), r.getPositions(0)
signal_centre, projection = get_signal_centre(samples, cam_range)
#Set max position
cam_x.write(signal_centre)
cam_x.close()
"""
plt.figure(figsize=[10,5])
plt.subplot(121)
plt.title('PSSS scan of camera position')
plt.pcolormesh(np.arange(0,Scan_spec.shape[2]), Cam_range, Scan_spec.mean(axis=1),cmap='CMRmap')
plt.xlim([0,Scan_spec.shape[2]])
plt.xlabel('Camera pixel dispersive direction')
plt.ylabel('Set PSSS cam_x _pos [mm] \n'+PSSS_cam_x_PV_name[0:-4])
plt.subplot(122)
plt.plot(projection,Cam_range,linewidth = 2, color = 'orange',label ='projected signal')
plt.title('Spectrum centred at %.1f [mm] (from signal max) \n trace should have hard edges'%signal_centre)
plt.xticks([])
plt.legend()
plt.grid(True)
"""
#PLOT.clear()
#plot_data(PLOT, projection, "Data", xdata=cam_range, show_points = True, color=Color.BLUE)
#p,pars = plot_gauss_fit(cam_range, projection, gauss_pars=None, p=PLOT, title = "Data")
p.clear()
p.setTitle("")
plot_data(p, projection, "Projection", xdata=cam_range, show_points = True, color=Color.BLUE)
p.addMarker(signal_centre, None, "Signal Centre=" + str(round(signal_centre,2)), Color.LIGHT_GRAY)
set_return(signal_centre)

View File

@@ -0,0 +1,81 @@
###############################################################################
#Scan the PSSS crystal height
#Purpose:
#The PSSS signal level is very sensitive to the crystal height. This script will scan the height and set the position to the maximum signal
if get_exec_pars().source == CommandSource.ui:
#User inputs - define travel range of camera
RANGE_FROM = -0.8
RANGE_TO = -1.7
STEPS = 10 #20
NUM_SHOTS= 10 # 100
PLOT=None
p = plot(None, title="Data")[0] if (PLOT is None) else PLOT
p.clear()
p.removeMarker(None)
p.setLegendVisible(True)
p.addSeries(LinePlotSeries("PSSS Spectrum Average"))
run("cpython/wrapper")
#Setup and functions setup¶
if not is_dry_run():
xstal_height=Channel("SARFE10-PSSS059:MOTOR_Y3.VAL", name="xstal_height")
else:
xstal_height=DummyRegister("xstal_height")
av = create_averager(psss_spectrum_y, NUM_SHOTS, interval=-1, name="spectrum_average")
av_samples = av.samples
av_samples.alias = "spectrum_samples"
#Scan and take data
def after_read(record, scan):
p.getSeries(0).setData(psss_spectrum_x.take(), record[av])
p.setTitle("Xtal Height = %1.3f" %(record[xstal_height]))
r = lscan(xstal_height, (av, av_samples), RANGE_FROM, RANGE_TO, STEPS, latency=2.0, after_read = after_read, save=False)
#User inputs - define travel range of crystal
#It is unlikely these values need to be changed
average, samples, xstal_range = r.getReadable(0), r.getReadable(1), r.getPositions(0)
#return maxium position
[amp, mean_val, sigma, offset], projection = fit_crystal_height(RANGE_FROM, RANGE_TO, STEPS+1, samples)
print(mean_val)
if not (RANGE_FROM < mean_val < RANGE_TO or RANGE_TO < mean_val < RANGE_FROM):
raise Exception ("Invalid fit mean: " + str(mean_val))
#Set max position
#Cell below will push the maximum position to the xstal height
xstal_height.write(mean_val)
xstal_height.close()
#Plots
"""
plt.figure(figsize=[10,5])
plt.subplot(121)
plt.title('PSSS scan of crystal height')
plt.pcolormesh(energy_axis, xstal_range, Scan_spec.mean(axis=1),cmap='CMRmap')
plt.xlim([energy_axis[0],energy_axis[-1]])
plt.ylim([xstal_range[0], xstal_range[-1]])
plt.xlabel('PSSS energy axis')
plt.ylabel('Set crystal position [mm] \n'+PSSS_xstal_height_name[0:-4])
plt.subplot(122)
plt.plot(projection,xstal_range,linewidth = 2, color = 'orange',label ='projected signal')
plt.plot(gaus(xstal_range_fit,*popt),xstal_range_fit,'r:',label='fit')
plt.ylim([xstal_range[0], xstal_range[-1]])
plt.title('Signal max at %.3f [mm] (from fit)'%popt[1])
plt.xticks([])
plt.legend()
plt.grid(True)
"""
p.clear()
p.setTitle("")
plot_gauss_fit(xstal_range, projection, gauss_pars=(offset, amp, mean_val, sigma), p=p, title = "Data")
set_return(mean_val)

101
script/psss/EnergyScan.py Executable file
View File

@@ -0,0 +1,101 @@
###############################################################################
#Scan the PSSS photon energy
#Purpose: To find and centre the PSSS photon energy so the measured spectrum is centred on the camera chip
#PARAMETERS
#User inputs - define energy range to scan below by running the appropiate cell
#Below is for a large scan range assuming offset from machine upto $\pm$ 300 eV
#If running from editor
if get_exec_pars().source == CommandSource.ui:
RANGE_OFF = None
RANGE_FROM = 11100
RANGE_TO = 11300
STEPS = 5 #60
NUM_SHOTS= 10 #100
PLOT=None
p = plot(None, title="Data")[0] if (PLOT is None) else PLOT
p.clear()
p.removeMarker(None)
p.setLegendVisible(True)
p.addSeries(LinePlotSeries("PSSS Spectrum Average"))
if RANGE_OFF is not None:
RANGE_FROM = energy_machine.read()-RANGE_OFF
RANGE_TO = energy_machine.read()+RANGE_OFF
run("cpython/wrapper")
#Scan and take data
class PSSS_energy(Writable):
def write(self, value):
if not is_dry_run():
psss_energy.write(value)
exec_cpython("/ioc/modules/qt/PSSS_motion.py", args = ["-m1", "SARFE10-PSSS059"])
# python / ioc / modules / qt / PSSS_motion.py - m1 SARFE10 - PSSS059
time.sleep(1)
print(value)
en = PSSS_energy()
en.alias = "energy"
av = create_averager(psss_spectrum_y, NUM_SHOTS, interval=-1, name="spectrum_average")
av_samples = av.samples
av_samples.alias = "spectrum_samples"
def after_read(record, scan):
p.getSeries(0).setData(psss_spectrum_x.take(), record[av])
p.setTitle("Energy = %1.3f" %(record[en]))
r = lscan(en, (av, av_samples), RANGE_FROM, RANGE_TO, STEPS, latency=0.0, after_read = after_read, save=False )
average, samples, energy_range = r.getReadable(0), r.getReadable(1), r.getPositions(0)
[amp, mean_val, sigma, offset],centre_line_out = fit_energy(RANGE_FROM, RANGE_TO, STEPS+1, NUM_SHOTS, samples)
if not (RANGE_FROM < mean_val < RANGE_TO or RANGE_TO < mean_val < RANGE_FROM):
raise Exception ("Invalid fit mean: " + str(mean_val))
measured_offset = energy_machine.read() - mean_val
#Set fitted energy
print "measured offset", measured_offset
en.write(mean_val)
#Plot
"""
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')
plt.plot(gaus(Energy_range_fit,*popt),Energy_range_fit,'r:',label='fit')
plt.xticks([])
plt.legend()
plt.grid(True)
"""
p.clear()
p.setTitle("")
plot_gauss_fit(energy_range, centre_line_out, gauss_pars=(offset, amp, mean_val, sigma), p=PLOT, title = "Data")
set_return(mean_val)

188
script/psss/psss.py Executable file
View File

@@ -0,0 +1,188 @@
import org.jfree.ui.RectangleAnchor as RectangleAnchor
import org.jfree.ui.TextAnchor as TextAnchor
import ch.psi.pshell.imaging.Overlay as Overlay
import ch.psi.pshell.plot.RangeSelectionPlot as RangeSelectionPlot
from collections import deque
PSSS_CAMERA_NAME = "SARFE10-PSSS059";
def integrate_arrays(arrays):
if arrays is None or (len(arrays)==0):
return None
ret = arrays[0]
for a in arrays[1:]:
ret=arradd(ret, a)
return ret
def average_arrays(arrays):
ret = integrate_arrays(arrays)
if ret is not None:
s=len(arrays)
ret = [x/s for x in ret]
return ret
def get_psss_data(average=1):
ax,ay,ac,af=[],[],[],[]
x = psss_spectrum_x.take()
for i in range(average):
y = psss_spectrum_y.take()
center,fwhm = psss_center.take(), psss_fwhm.take()
if average==1:
return x,y,center,fwhm
#ax.append(x)
ay.append(y)
ac.append(center)
af.append(fwhm)
if i < (average-1):
psss_spectrum_y.waitCacheChange(2000)
#psss_center.waitCacheChange(1)
#psss_fwhm.waitCacheChange(1)
#x=average_arrays(ax)
y=average_arrays(ay)
center=mean(ac)
fwhm=mean(af)
return x,y,center,fwhm
def plot_psss(p, h=None, average = None):
"""
if len(p.getMarkers())==0:
m1=p.addMarker(0,None,"",Color.WHITE)
m2=p.addMarker(0,None,"",Color.WHITE)
m2.setLabelAnchor(RectangleAnchor.TOP)
else:
m1,m2 = p.getMarkers()
"""
#Manipulate axis (use PSSS_PLOT for the global object):
#p.getAxis(LinePlot.AxisId.X).
# Setup queues
if p.getNumberOfSeries()==0:
center_queue = deque(maxlen=100)
fwhm_queue = deque(maxlen=100)
# Setup figures
if p.getNumberOfSeries()==0:
p.addSeries(LinePlotSeries("spectrum"))
p.addSeries(LinePlotSeries("average"))
p.setLegendVisible(True)
p.getAxis(LinePlot.AxisId.X)
p.getAxis(LinePlot.AxisId.X).setLabel("Energy [eV]")
p.getAxis(LinePlot.AxisId.Y).setLabel("Sum counts")
if len(p.getMarkers())==0:
paint = RangeSelectionPlot().getSelectionColor() #p.chart.getBackgroundPaint()
m=p.addIntervalMarker(0,0, None,"", paint)
m.setLabelAnchor(RectangleAnchor.BOTTOM)
m.alpha=0.2
m.setLabelPaint(Color.WHITE)
else:
m = p.getMarkers()[0]
x,y, = psss_spectrum_x.take(), psss_spectrum_y.take()
# update spectral plot
if (x is None) or (y is None):
p.getSeries(0).clear()
else:
p.getSeries(0).setData(x,y)
if (x is None) or (y is None):
p.getSeries(0).clear()
else:
p.getSeries(0).setData(x,y)
if average is not None:
print "Average: ", average
x,y, center,fwhm = get_psss_data(average)
else:
y = psss_spectrum_y_average.take()
center = psss_center_average.take()
fwhm = psss_fwhm_average.take()
if (x is None) or (y is None):
p.getSeries(1).clear()
else:
p.getSeries(1).setData(x,y)
if (center!= None) and (fwhm!=None):
center=center.doubleValue()
fwhm=fwhm.doubleValue()
m.startValue, m.endValue = center - fwhm/2, center + fwhm/2
m.label = str(center)
if h:
if h.getNumberOfSeries()==0:
h.addSeries(TimePlotSeries("centre"))
h.addSeries(TimePlotSeries("Energy spread SS",2))
h.addSeries(TimePlotSeries("Energy spread cum avg",2))
h.setLegendVisible(True)
h.setTimeAxisLabel("")
h.getAxis(Timeplot.AxisId.Y1).setLabel("Central energy [eV]")
per_mil = (fwhm/center)*1e3
per_mil_avg = psss_fwhm_avg.take()
h.getSeries(0).appendData(center)
h.getSeries(1).appendData(per_mil)
h.getSeries(2).appendData(per_mil_avg)
return center,fwhm
ovmin, ovmax, ovavg = None, None, None
def update_psss_image(renderer):
global ovmin, ovmax
#if ovmin: ovmin.update(Point(0,psss_roi_min.take()))
#if ovmax: ovmax.update(Point(0,psss_roi_max.take()))
width=psss_spectrum_x.size
if ovmin: ovmin.update(Point(0,psss_roi_min.take()), Point(width, psss_roi_min.take()))
if ovmax: ovmax.update(Point(0,psss_roi_max.take()), Point(width, psss_roi_max.take()))
try:
data = renderer.data
av = "%1.2f" %(data.integrate(False)/data.width/data.height)
except:
av = ""
if ovavg: ovavg.update(av)
def enable_psss_image(enabled, renderer):
global ovmin, ovmax, ovavg
try:
if (enabled):
#Start or connect to ScreenPanel pipeline
renderer.setDevice(cam_server)
renderer.setProfile(renderer.Profile.Both)
renderer.setShowProfileLimits(False)
#Changing colormap
#print Colormap.values() #Check values
cam_server.config.colormap=Colormap.Temperature
cam_server.start(PSSS_CAMERA_NAME + "_sp", PSSS_CAMERA_NAME + "_sp1")
#ovmin, ovmax= Overlays.Crosshairs(renderer.getPenMarker(), Dimension(-1,1)), \
# Overlays.Crosshairs(renderer.getPenMarker(), Dimension(-1,1))
ovmin, ovmax= Overlays.Line(renderer.getPenMarker()), Overlays.Line(renderer.getPenMarker())
ovavg = Overlays.Text(Pen(java.awt.Color.GREEN.darker()), "", \
java.awt.Font("Verdana", java.awt.Font.PLAIN, 12), java.awt.Point(-50,20))
ovavg.fixed=True
ovavg.anchor=Overlay.ANCHOR_IMAGE_TOP_RIGHT
renderer.addOverlays([ovmin, ovmax, ovavg])
update_psss_image(renderer)
else:
ovmin, ovmax, ovavg = None, None, None
renderer.setDevice(None)
renderer.clearOverlays()
cam_server.stop()
except:
log(sys.exc_info()[1])
def get_psss_averaging():
return psss_spectrum_y_average.config.measures
def set_psss_averaging(measures):
psss_spectrum_y_average.config.measures=measures
psss_center_average.config.measures=measures
psss_fwhm_average.config.measures=measures