155 Commits
zmq ... master

Author SHA1 Message Date
d1e8913dd4 new version 2016-03-21 15:55:40 +01:00
c5d845e7ff added simulated epics server for testing 2016-03-21 15:47:04 +01:00
5f836e7856 merged core into project 2016-03-17 08:52:34 +01:00
8c13c1c85d updated gradle build 2016-03-17 08:22:19 +01:00
e1ff42d464 merged xscan into project 2016-03-17 08:17:05 +01:00
b014dd6afd merged fdaq code 2016-03-16 15:09:26 +01:00
e412ae7092 merged cdump code which this project 2016-03-16 13:29:02 +01:00
e63d2e3052 Updated readme to remember that there are 2 more properties in the fda.properties file for CRLOGIC 2015-08-21 08:53:10 +02:00
09ead2eb64 updated version 2015-08-20 08:38:51 +02:00
166e8d325a increased xscan version 2015-08-19 09:51:40 +02:00
03ac83adf6 cleanup properties and compiler warnings 2015-08-18 11:44:57 +02:00
edf3672317 updated build number and removed pom 2015-08-18 11:27:49 +02:00
10f0fcdde2 moved files to top level 2015-08-14 13:26:17 +02:00
19d2b28f25 removed eclipse specific settings 2015-08-14 13:21:34 +02:00
ac04a730a3 fixed javadoc problems and migrated to gradle 2015-08-14 13:20:48 +02:00
87ed988dfe updated zmq 2015-08-13 14:44:02 +02:00
fb21986493 updated version 2015-08-13 14:36:50 +02:00
1601fbcbfd origin crlogic 2015-05-11 13:36:17 +02:00
c25a80ddfb new version 2014-10-10 13:54:34 +02:00
ba630a44e1 new version 2014-10-10 11:07:34 +02:00
5316773104 Added title font property to plots. 2014-09-09 09:18:29 +02:00
38b60f3f5e Added title font property to plots. 2014-09-09 09:17:58 +02:00
31d37c7c45 Fixed bug in chained manipulations 2014-09-04 09:16:31 +02:00
366a7f2a74 Added visualization to Fdaq 2014-08-29 16:51:59 +02:00
e5cc3126ab Added visualization to Fdaq 2014-08-29 16:28:06 +02:00
45505b511d Added item count to LinePlotSeries & Subsampling to visualizer 2014-08-29 16:15:50 +02:00
e21b3d64ee Several bug fixes and small improvements 2014-08-28 14:25:18 +02:00
1a294a1a75 Fixed bugs on MatrixPlotArray 7 LinePlotArray 2014-08-22 09:26:16 +02:00
fb5b2ff257 Upgraded xscan code 2014-08-19 13:16:01 +02:00
8d9fba4be6 updated pom to require source level 1.8 2014-08-13 08:15:45 +02:00
065ed130a6 Adapting to plot v2: Abstraction of graphs & new implementations: JZY3D, JavaFX, JFreeChart 2014-08-12 16:41:58 +02:00
074ac2caff Update version in release notes 2014-08-07 14:38:35 +02:00
f2e3bf23e8 Added an release notes file 2014-08-07 14:28:07 +02:00
f39822ec74 updated referenced library 2014-07-28 16:29:25 +02:00
5038912472 updated pom deploy url 2014-07-28 12:38:34 +02:00
8ab87b8332 Updated version ... 2014-07-28 11:13:23 +02:00
8f698e82ba upgraded xscan version 2014-05-12 11:40:15 +02:00
58e92684ad Updated version 2014-05-12 11:17:19 +02:00
5a6396cfb7 Added initial administration web page. 2014-05-09 09:29:41 +02:00
57ecb121b2 improved return values ... 2014-05-06 16:14:21 +02:00
3ce7282214 Improved logging 2014-05-06 13:50:50 +02:00
16d18288b6 improved termination of the execution container 2014-05-06 13:15:51 +02:00
76ce595f87 removed author comment 2014-04-30 07:51:53 +02:00
486d11db2b Finished cleanup 2014-04-30 07:45:16 +02:00
fa2416492e Refactored test packages 2014-04-30 07:34:31 +02:00
db097eba8f added new startup script 2014-04-30 07:29:33 +02:00
838f6fd385 moved classes to ui package 2014-04-30 07:28:14 +02:00
1c9eca2a1c handle end of stream correctly 2014-04-30 07:27:43 +02:00
f30aa6495f refactored classes 2014-04-30 07:17:06 +02:00
a15356190d moved classes 2014-04-30 07:07:33 +02:00
88f4dd2b19 cleaned up configuraiton management and startup scripts 2014-04-30 07:00:25 +02:00
9f4c6c0356 re-organized some stuff ... 2014-04-29 11:44:10 +02:00
84fb119932 cleaned up cleanup procedure 2014-04-29 11:26:22 +02:00
311eae3cbc changes ... 2014-04-29 11:06:21 +02:00
9529d7f088 Renamed classes to better represent what they are doing 2014-04-29 10:34:26 +02:00
e597b5cd12 stuff 2014-04-28 16:06:10 +02:00
8ab6f7965b moved to correct package 2014-04-28 13:57:40 +02:00
4bb984cc1c Removed lots of stuff from the project 2014-04-28 13:56:52 +02:00
b64f31e778 some more cleanups and fixes
-- however still lots of bugs in there !
2014-04-28 11:46:36 +02:00
43a8347924 added gitignore file 2014-04-25 12:44:22 +02:00
f520ff4337 removed xmlscan based classes and imported ch.psi.fda.xscan library
instead
2014-04-25 12:39:49 +02:00
5995b2ed5c use of edescriptor also for the server/client setup of FDA 2014-04-22 08:43:14 +02:00
e20cab4874 Fixed viewer 2014-04-16 08:43:58 +02:00
576d7eb048 Refactored visualizer to support vdescriptor 2014-04-16 08:34:24 +02:00
21f86d7d69 Updated provider to also generate a vdescriptor 2014-04-14 13:14:45 +02:00
aa1681aaf3 Cleaned messed up stuff 2014-04-11 16:15:38 +02:00
da182adcd2 updated edescriptor thingi 2014-04-11 15:47:09 +02:00
8d1bd4e816 moved certain rest related classes 2014-04-10 15:23:15 +02:00
07d6b47885 added injection and fixed shutdown problems 2014-04-10 15:19:39 +02:00
87781b8f06 Added new abstraction layer 2014-04-10 14:11:40 +02:00
28bd7c40d8 removed unused option 2014-04-09 16:27:54 +02:00
dcd394b586 updated readme formatting 2014-04-08 10:11:02 +02:00
76c40ccf28 Made zmq port configureable
Updated Readme.md file
2014-04-08 10:09:05 +02:00
8522d46813 renamed fda script to server and added script to startup the viewer 2014-04-07 15:11:01 +02:00
1077ec8ab3 Added flag to generate serializable model classes (xjb.xjb)
Improved viewer to update/change the plots whenever a new scan starts...
Therefore the visualization configuration is always send before any of
the scan data is sent.
2014-04-07 11:02:40 +02:00
da0e0eab79 Updated to latest fdaq 2014-01-22 13:38:35 +01:00
ac54407e34 upgraded to latest fdaq version 2014-01-22 11:29:23 +01:00
b0d4ef9d8b Made home variable visible 2014-01-21 08:41:07 +01:00
f8ee1bd666 updated readme 2014-01-20 13:30:45 +01:00
8d37cdbeca created all in one jar for gui application. 2014-01-20 13:12:25 +01:00
fbe03b7ade Added tracking id for isActive call 2014-01-20 11:12:20 +01:00
d866fa0eda fixed rest documentation 2014-01-15 16:09:39 +01:00
2b0877c65d Documented fda rest api 2014-01-15 16:08:06 +01:00
d7f1b15927 new package version
FDA-106
FDA-1
2014-01-15 14:31:28 +01:00
35a4949907 Rest server now also takes ch.psi.fda.home variable into account
FDA-106
2014-01-15 13:38:03 +01:00
30355deacc removed setting of java.util.logging.config.file inside this class as
this has no effect!
2014-01-15 13:37:07 +01:00
eb0aa9a1b6 Cleaned up configuration mess 2014-01-15 13:14:56 +01:00
b447ec12d7 FDA-1
Added function to wait for the termination of a request
2014-01-15 11:04:24 +01:00
ae78b8c7a7 Removed unnecessary queue in AcquisitionEngine 2014-01-15 10:15:00 +01:00
c9ff7ccf2c tests ... 2014-01-15 09:05:51 +01:00
c01995675e decreased log level for logging complete message send out by the zmq
streamer
2014-01-14 13:47:05 +01:00
e4885d11e1 added startup scripts: FDA-106
created assembly descriptor for build
Renamed RestServer to FdaServer
2014-01-14 11:39:10 +01:00
407aff2e24 Upgrade fdaq and cdump code dependencies ... 2014-01-14 11:08:59 +01:00
9d6ae89f13 Added TODO comment for reminding that filtering is not yet done 2014-01-09 09:17:27 +01:00
fafea6dc69 FDA-103
Created first version of Cdump REST service
2014-01-09 09:10:25 +01:00
3e841c7596 FDA-102 2014-01-09 08:35:50 +01:00
542379545b Added (singleton) fdaq engine class to be able to unregister the zmq
streamer and to avoid having more than one thing driving the fdaq box
...
2014-01-08 16:30:59 +01:00
4d0f329e72 removed class because of no time to fully implement it ...
will add it later .
2014-01-08 16:11:40 +01:00
488fa5c908 FDA-102
moved request object to rest.model package
2014-01-08 16:10:12 +01:00
d550e59254 Implemented FDAQ REST API and started to with Cdump 2014-01-08 09:58:26 +01:00
685ac0cd2d renamed ScanService to FDAService 2013-12-20 15:25:09 +01:00
9476f9b57c cleaned comments 2013-12-20 14:35:37 +01:00
8888172ede Renamed class RestClient to ControlClient 2013-12-20 14:31:44 +01:00
e324987c8e FDA-1
Improved client - Now multiple clients can submit scans and only the one
submitted the scan will receive the data as well as can abor the scan.
2013-12-20 14:28:32 +01:00
76e9ea1bed FDA-1
Improved server and client
2013-12-20 13:43:16 +01:00
244001fd99 First working (messy) version of client/server split
FDA-1
2013-12-20 08:54:55 +01:00
55faaa2aa3 FDA-1
Improved rest server
2013-12-19 11:23:56 +01:00
ab0d1654c1 fixed pom for artifact upload 2013-12-18 11:09:47 +01:00
726cf9c0ff fixed pom 2013-12-17 15:31:54 +01:00
03c7d84b05 Renamed serializer classes (removed Data prefix)
Moved SerializerTXT to core project
2013-12-17 15:20:53 +01:00
54fb16a0e9 Renamed package from core.messages to messages 2013-12-17 15:18:09 +01:00
f96b85f6d0 Renamed test case 2013-12-17 15:16:44 +01:00
696893ba16 Renamed unnecessary interface DataSerializer
moved messages package into own project
2013-12-17 15:11:38 +01:00
d84ce43676 Update readme 2013-12-17 14:56:59 +01:00
e625185b6d Updated version to 2.0.x
Added Readme.md file - Starting of development documentation
2013-11-27 11:44:48 +01:00
a40573d320 Cleaned up injects, added ZMQ streaming and viewer 2013-11-27 09:55:14 +01:00
70089581c4 First version with asynchronous execution 2013-10-24 10:03:23 +02:00
08cbd0bad0 got first working version of REST server 2013-10-24 08:38:33 +02:00
f4d5102ea3 Implemented REST API and server for executing scans 2013-10-23 15:16:49 +02:00
e483f90837 remove comments 2013-10-23 11:55:41 +02:00
795b269bd0 minor changes 2013-10-21 13:21:01 +02:00
3cb7458e64 removed comment 2013-10-21 12:40:04 +02:00
51d7b36219 Probably fixed CRLOGIC thing as such ... 2013-10-21 11:49:29 +02:00
67e7f9a6c8 fixed scrlogic 2013-10-21 10:59:11 +02:00
491812ddeb fixed otf code 2013-10-21 09:45:06 +02:00
40cc7f6a31 fixed stuff for the new data transfer format 2013-10-21 08:41:22 +02:00
9386f42d06 Somehow works better than before 2013-10-17 08:59:33 +02:00
855535134e Got Visualization work 2013-10-17 07:55:49 +02:00
e2921ff1f4 fixed lots of stuff regarding new message format ... 2013-10-17 07:35:28 +02:00
36cd4335ab Preparation for reworking messaging format 2013-10-16 11:30:38 +02:00
d92534ec37 Removed unnecessary function parameter 2013-10-16 10:54:47 +02:00
ca871ad478 some cleanup in CRLOGIC 2013-10-15 16:13:08 +02:00
b65764ac57 removed injection classes/libraries as not needed 2013-10-15 15:55:47 +02:00
63e681c3bb update version and added configuration for single jar 2013-10-15 15:53:41 +02:00
48cda75405 removed unecessary JythonGlobalVariableDictionary class 2013-10-15 09:40:14 +02:00
4b615d29a6 Cleanup and restructuring notification agent 2013-10-15 08:44:18 +02:00
d8f1e2d8f1 see commit before 2013-10-15 08:26:03 +02:00
768ea9f254 Cleanup Crlogic code 2013-10-14 16:42:00 +02:00
2cba6e7991 Cleanup OTF scan 2013-10-14 16:10:54 +02:00
cb6ec74859 cleanup ... 2013-10-14 13:21:25 +02:00
36f717c8bf more cleanup 2013-10-14 13:06:50 +02:00
716eeba98b cleanup comments 2013-10-14 12:57:21 +02:00
c1c8170f36 Restructuring code 2013-10-14 12:54:57 +02:00
c8031db1fd Cleanup ChannelAccessCondition* classes 2013-10-14 11:31:29 +02:00
a2d9216e84 Removed destroy() method from actuator and action interface 2013-10-14 11:06:55 +02:00
57eca36d27 Cleaned up code
Removed lots of duplicated code, merged classes, etc.
2013-10-14 10:34:40 +02:00
809caa3ed1 Fixed tests 2013-10-09 11:23:34 +02:00
3532f95acb Renamed template files 2013-10-09 09:23:37 +02:00
5d2c2b94d6 Fixed remaining broken tests 2013-10-09 09:15:59 +02:00
2520573d12 Exchanged Channel Access library with latest version
Fixing of the code is still going on!
2013-10-08 16:36:17 +02:00
97ab9fa5b2 Removed unnecessary dependency 2013-10-04 14:39:15 +02:00
debc54a28a do not execute the test case 2013-10-04 14:12:52 +02:00
55ed5ac764 Upgraded mail libraries to latest version 2013-10-04 14:12:18 +02:00
84c86b8d9f cleanup comments 2013-10-04 13:37:03 +02:00
b38654056b minor comments cleanup 2013-10-04 13:22:38 +02:00
363 changed files with 20840 additions and 21205 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
/bin
/target
/build
.gradle
.settings
.project
.classpath
/schema/

165
Readme.md Normal file
View File

@@ -0,0 +1,165 @@
# Overview
This package holds the core functionality of FDA.
# Usage
use -Djava.util.logging.config.file=logging.properties` to configure logging
## Server
The FDA server is started as follows:
```
./bin/server -h
usage: fda
-h Help
-p <arg> Server port (default: 8080)
-s <arg> Server address (default: localhost)
```
Start new scan:
```
curl -X PUT -d @scan1d.xml -H 'Content-Type:application/xml' http://localhost:8080/fda/scan
```
## Viewer
```
./bin/viewer -h
usage: viewer
-h Help
-p <arg> Server port (default: 10000)
-s <arg> Server address (default: localhost)
```
# Development
When checking out the project from the repository there is the `target/generated-sources/xjc` folder missing.
After checking out the project execute `mvn compile` to create the folder and the required classes.
To build project use `mvn clean install`.
To upload the latest version to the central artifact repository use `mvn clean deploy`.
Create Zip file via `mvn clean compile assembly:assembly`
To use the FDA libary in an other project (like the GUI project) use:
```
<dependency>
<groupId>ch.psi</groupId>
<artifactId>fda</artifactId>
<version>x.x.x</version>
</dependency>
```
## REST
FDA offers a rest service to execute scans. There are 3 distinct service for fda scan, fdaq and cdump.
### FDA Service
Submit scan
```
PUT fda/{trackingId}
Content-Type: application/xml
<configuration>
...
</configuration>
204 - Success
```
Stop/cancel scan
```
DELETE fda/{trackingId}
204 - Success
```
Stop all scans
```
DELETE fda
204 - Success
```
Check if scan is running
```
GET fda/{trackingId}/running
200 - true/false
```
Wait for scan done (blocks until scan is done)
```
GET fda/{trackingId}/done
204 - Success
```
# Notes
## Upgrade FDA 1.x to 2.x
In existing fda.properties file the following property need to be added: `ch.psi.fda.aq.data.dir=../data`
## Upgrade FDA 2.6.1
There are 2 new properties for crlogic:
```
ch.psi.fda.aq.crlogic.ioc=X05LA-VME-ES2
ch.psi.fda.aq.crlogic.prefix=X05LA-ES2-CRL
```
# FDAQ
## Overview
This software is used to readout the FDAQ box developed at X10SA.
On The FDAQ box there are 2 socket servers, one for retrieving the data and one for resetting the socket
server for data retrieval.
The fdaq code provides exactly 2 functionalities. It can query on the data socket for data (need to specifying how many data point to read),
and it can send a reset request on the reset channel.
## Usage
To acquire data into a file use:
```
java -jar ch.psi.fda.fdaq-<version>.jar <file>
```
You can terminate the acquisition with *CTRL+C*. If you submit 2 consequtive *CTRL+C* the program will terminate immediately (and data might be lost);
This will take the default connections settings:
* Hostname: mchip015.psi.ch
* Port: 2233
* Kill Port: 2234
* Number Of Elements: Integer.MAX_VALUE/2
If you need to specify different settings create a property files with following content:
```
ch.psi.fda.fdaq.hostname=myhost
ch.psi.fda.fdaq.port=1234
ch.psi.fda.fdaq.killPort=4321
```
Use `-Dch.psi.fda.fdaq.config.file=<file>` to use this property file as base configuration.
## Development
A standalone jar can be build via `mvn clean compile assembly:single`.
To upload the latest version to the artifact repository use ` mvn clean compile deploy`.
## Notes
Trigger port is `Trigger In 1`. For testing apply a 1kHz signal.

92
build.gradle Normal file
View File

@@ -0,0 +1,92 @@
apply plugin: 'java'
apply plugin: 'eclipse'
sourceCompatibility = 1.7
version = '3.0.0'
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.github.jacobono:gradle-jaxb-plugin:1.3.5"
}
}
apply plugin: "com.github.jacobono.jaxb"
repositories {
mavenCentral()
maven { url "http://artifacts.psi.ch/artifactory/libs-releases" }
maven { url "http://artifacts.psi.ch/artifactory/libs-snapshots" }
}
dependencies {
compile 'ch.psi:jcae:2.4.1'
compile 'com.google.inject:guice:3.0'
compile 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:2.5.1'
compile 'org.glassfish.jersey.media:jersey-media-sse:2.5.1'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.5.1'
compile 'org.zeromq:jeromq:0.3.4'
compile 'org.apache.commons:cli:1.2'
// For reading/writing Matlab files
compile 'com.jmatio:jmatio:0.2u2psi1'
// Library for reading/writing XDR Format (MDA)
compile 'org.freehep:freehep-xdr:2.0.4'
compile 'ch.psi:plot:2.1-SNAPSHOT'
compile 'com.google.guava:guava:>15.0'
compile 'com.sun.mail:javax.mail:1.5.0'
compile 'javax.inject:javax.inject:1'
compile 'org.python:jython:2.5.3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7-b41'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.7-b41'
jaxb 'javax.xml.bind:jaxb-api:2.2.7'
testCompile 'junit:junit:4.+'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
/*
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
*/
artifacts {
archives sourcesJar
//archives javadocJar
}
jaxb{
xsdDir = "src/main/resources"
xjc {
generatePackage = "ch.psi.fda.model.v1"
}
}
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "http://artifacts.psi.ch/artifactory/libs-snapshots-local"){
authentication(userName: "upload", password: "{DESede}eWKHxAtQ2Dc=")
}
pom.groupId = 'ch.psi'
pom.artifactId = 'fda'
}
}
}

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/xjc"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1 +0,0 @@
/target

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ch.psi.fda</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,3 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8

View File

@@ -1,5 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

View File

@@ -1,5 +0,0 @@
#Tue Oct 18 15:52:42 CEST 2011
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@@ -1,223 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.psi</groupId>
<artifactId>fda</artifactId>
<version>1.1.40</version>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>ch.psi</groupId>
<artifactId>jcae</artifactId>
<version>1.0.30</version>
</dependency>
<!-- Plotting library -->
<dependency>
<groupId>ch.psi</groupId>
<artifactId>plot</artifactId>
<version>1.1.30</version>
</dependency>
<!-- Java SMB/CIFS library -->
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
<!-- JAXB implementation -->
<!-- <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId>
<version>2.2.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId> <version>2.2.1</version> </dependency> -->
<!-- Jython Library -->
<dependency>
<groupId>org.python</groupId>
<artifactId>jython</artifactId>
<version>2.5.3</version>
</dependency>
<!-- CLI Libraries -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>cli</artifactId>
<version>1.2</version>
</dependency>
<!-- Library to Read Matlab Files -->
<dependency>
<groupId>com.jmatio</groupId>
<artifactId>jmatio</artifactId>
<version>0.2u2psi1</version>
</dependency>
<!-- Mail Libraries -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
<!-- Library for reading/writing XDR Format (MDA) -->
<dependency>
<groupId>org.freehep</groupId>
<artifactId>freehep-xdr</artifactId>
<version>2.0.4</version>
</dependency>
<!-- JUnit test library -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- Generate Javadoc Jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Generate Source Jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Schema generation -->
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>ch.psi.fda.model.v1</generatePackage>
</configuration>
</plugin>
<!-- Schema Documentation Generation -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>transform</phase>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<configuration>
<transformationSets>
<transformationSet>
<!-- <outputDir>target</outputDir> -->
<dir>src/main/resources</dir>
<stylesheet>src/main/documentation/xs3p.xsl</stylesheet>
<fileMappers>
<fileMapper
implementation="org.codehaus.plexus.components.io.filemappers.RegExpFileMapper">
<pattern>\.xsd$</pattern>
<replacement>.html</replacement>
</fileMapper>
</fileMappers>
</transformationSet>
</transformationSets>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.jvnet.jaxb2.maven2
</groupId>
<artifactId>
maven-jaxb2-plugin
</artifactId>
<versionRange>
[0.8.0,)
</versionRange>
<goals>
<goal>generate</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<distributionManagement>
<snapshotRepository>
<id>i.snapshots</id>
<name>Artifactory Snapshots</name>
<url>http://yoke/artifactory/libs-snapshots-local</url>
</snapshotRepository>
<repository>
<id>i.releases</id>
<name>Atrifactory Releases</name>
<url>http://yoke/artifactory/libs-releases-local</url>
</repository>
</distributionManagement>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
package ch.psi.fda.aq;
import gov.aps.jca.CAException;
import ch.psi.jcae.ChannelBeanFactory;
import com.google.inject.AbstractModule;
public class AcquisitionModule extends AbstractModule {
@Override
protected void configure() {
try {
bind(ChannelBeanFactory.class).toInstance(ChannelBeanFactory.getFactory());
} catch (CAException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,155 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.aq;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;
import com.google.common.eventbus.EventBus;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* Collector class that is collecting and merging data from different Queues.
* @author ebner
*
*/
public class Collector implements Runnable{
// Get Logger
private static Logger logger = Logger.getLogger(Collector.class.getName());
/**
* List of queues and their metadata this collector is responsible to readout.
* The logic is as follows:
* Read out the last queue until the first queue in the list has the EndOfLoopMessage.
*/
private List<DataQueue> queues;
/**
* Outgoing queue of this collector
*/
private EventBus bus;
/**
* Constructor
*/
public Collector(EventBus b){
queues = new ArrayList<DataQueue>();
this.bus = b;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if(queues.size()>0){
try{
readQueue(0, null);
}
catch(InterruptedException e){
// Readout aborted through interrupt
}
}
else{
// No queue registered for reading
}
bus.post(new EndOfStreamMessage());
logger.info("END");
}
private void readQueue(int index, DataMessage m) throws InterruptedException{
BlockingQueue<Message> q = queues.get(index).getQueue();
// Read Message
Message message = q.take();
while(message instanceof DataMessage){
// Create new data message
DataMessage dm = new DataMessage();
if(m!=null){
dm.getData().addAll(m.getData());
}
dm.getData().addAll(((DataMessage)message).getData());
if(index<(queues.size()-1)){
readQueue(index+1, dm);
}
else{
// Write message to outgoing queue
bus.post(dm);
}
// Read next message
message = q.take();
}
if(message instanceof EndOfStreamMessage){
// Translate EndOfStream to StreamDelimiter message
StreamDelimiterMessage ddm = new StreamDelimiterMessage(queues.size()-1-index, ((EndOfStreamMessage)message).isIflag());
// Write message to outgoing queue
bus.post(ddm);
}
}
/**
* @return the queues
*/
public List<DataQueue> getQueues() {
return queues;
}
/**
* Get the outgoing data metadata
*/
public DataMessageMetadata getMetadata(){
DataMessageMetadata dataMessageMetadata = new DataMessageMetadata();
// Generate new combined metadata and add dimension information to the components
int nq = queues.size();
for(int i=0;i<nq;i++){
DataQueue q = queues.get(i);
for(ComponentMetadata cm: q.getDataMessageMetadata().getComponents()){
// The dimension number is the number of queues minus the index of the current queue minus 1 (because dimension index starts at 0)
dataMessageMetadata.getComponents().add(new ComponentMetadata(cm.getId(), nq-i-1));
}
}
return(dataMessageMetadata);
}
}

View File

@@ -1,87 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core;
/**
* Singleton object for holing the core engine configuration
*
* @author ebner
*/
public class EngineConfiguration {
/**
* Flag to indicate whether the engine should fail if there is an error while reading out a sensor.
*/
private boolean failOnSensorError = true;
/**
* Flag to indicate whether the set value of the actor should be verified after the set operation.
* Having this flag on true will enable detecting for example that a motor hit the end switch or
* did not move correctly.
*/
private boolean checkActorSet = true;
/**
* Singleton instance
*/
private final static EngineConfiguration instance = new EngineConfiguration();
private EngineConfiguration(){
}
/**
* Get singleton instance of this class
* @return Engine configuration
*/
public static EngineConfiguration getInstance(){
return instance;
}
/**
* @return the failOnSensorError
*/
public boolean isFailOnSensorError() {
return failOnSensorError;
}
/**
* @param failOnSensorError the failOnSensorError to set
*/
public void setFailOnSensorError(boolean failOnSensorError) {
this.failOnSensorError = failOnSensorError;
}
/**
* @return the checkActorSet
*/
public boolean isCheckActorSet() {
return checkActorSet;
}
/**
* @param checkActorSet the checkActorSet to set
*/
public void setCheckActorSet(boolean checkActorSet) {
this.checkActorSet = checkActorSet;
}
}

View File

@@ -1,156 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.actions;
import java.util.Comparator;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.Action;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Condition a channnel needs to match
* Only accepts channels of type Integer
*
* @author ebner
*
*/
public class ChannelAccessConditionAnd implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionAnd.class.getName());
/**
* Channel to set
*/
private final ChannelBean<Integer> channel;
/**
* Value to wait for
*/
private final Integer expectedValue;
private final Long timeout;
private volatile boolean abort = false;
private volatile Thread waitT = null;
/**
* Constructor
* @param channelName Name of the channel to set the value
* @param expectedValue Value to wait for
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
*
* @throws IllegalArgumentException Unable to initialize channel,
* Timeout specified is not >=0
*/
@SuppressWarnings("unchecked")
public ChannelAccessConditionAnd(String channelName, Integer expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<Integer>) ChannelBeanFactory.getFactory().createChannelBean( (Class<Integer>) expectedValue.getClass(), channelName, false);
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
}
this.expectedValue = expectedValue;
if(timeout==null){
this.timeout = channel.getWaitTimeout();
}
else{
this.timeout = timeout;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#execute()
*/
/**
* @throws InterruptedException
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
*/
@Override
public void execute() throws InterruptedException {
abort=false;
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
try{
waitT = Thread.currentThread();
channel.waitForValue(expectedValue, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
int one = o1;
int two = o2;
if((one & two) != 0){
return 0;
}
return 1;
}
}
, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
} catch (CAException e) {
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
} catch(InterruptedException e){
if(!abort){
throw e;
}
}
finally{
waitT=null;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
abort=true;
if(waitT!=null){
waitT.interrupt();
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy action channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,156 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.actions;
import java.util.Comparator;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.Action;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Or condition of a channel
* Only supports Integer values and channel
*
* @author ebner
*
*/
public class ChannelAccessConditionOr implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionOr.class.getName());
/**
* Channel to set
*/
private final ChannelBean<Integer> channel;
/**
* Value to wait for
*/
private final Integer expectedValue;
private final Long timeout;
private volatile boolean abort = false;
private volatile Thread waitT = null;
/**
* Constructor
* @param channelName Name of the channel to set the value
* @param expectedValue Value to wait for
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
*
* @throws IllegalArgumentException Unable to initialize channel,
* Timeout specified is not >=0
*/
@SuppressWarnings("unchecked")
public ChannelAccessConditionOr(String channelName, Integer expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<Integer>) ChannelBeanFactory.getFactory().createChannelBean( (Class<Integer>) expectedValue.getClass(), channelName, false);
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
}
this.expectedValue = expectedValue;
if(timeout==null){
this.timeout = channel.getWaitTimeout();
}
else{
this.timeout = timeout;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#execute()
*/
/**
* @throws InterruptedException
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
*/
@Override
public void execute() throws InterruptedException {
abort=false;
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
try{
waitT = Thread.currentThread();
channel.waitForValue(expectedValue, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
int one = o1;
int two = o2;
if((one | two) != 0){
return 0;
}
return 1;
}
}
, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
} catch (CAException e) {
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
} catch(InterruptedException e){
if(!abort){
throw e;
}
}
finally{
waitT=null;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
abort=true;
if(waitT!=null){
waitT.interrupt();
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy action channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,149 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.actions;
import java.util.Comparator;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.Action;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Regex condition
* Only supports String value/channel.
* @author ebner
*
*/
public class ChannelAccessConditionRegex implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionRegex.class.getName());
/**
* Channel to set
*/
private final ChannelBean<String> channel;
/**
* Value to wait for
*/
private final String expectedValue;
private final Long timeout;
private volatile boolean abort = false;
private volatile Thread waitT = null;
/**
* Constructor
* @param channelName Name of the channel to set the value
* @param expectedValue Value to wait for
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
*
* @throws IllegalArgumentException Unable to initialize channel,
* Timeout specified is not >=0
*/
@SuppressWarnings("unchecked")
public ChannelAccessConditionRegex(String channelName, String expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<String>) ChannelBeanFactory.getFactory().createChannelBean( (Class<String>) expectedValue.getClass(), channelName, false);
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
}
this.expectedValue = expectedValue;
if(timeout==null){
this.timeout = channel.getWaitTimeout();
}
else{
this.timeout = timeout;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#execute()
*/
/**
* @throws InterruptedException
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
*/
@Override
public void execute() throws InterruptedException {
abort=false;
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
try{
waitT = Thread.currentThread();
channel.waitForValue(expectedValue, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.matches(o2) ? 0:1;
}
}, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
} catch (CAException e) {
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
} catch(InterruptedException e){
if(!abort){
throw e;
}
}
finally{
waitT=null;
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
abort=true;
if(waitT!=null){
waitT.interrupt();
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy action channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,188 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.actors;
import ch.psi.fda.core.Actor;
/**
* Special actuator for the OTFLoop. This type of actor must not be used in any other
* type of loop than OTFLoop. If it is used it will, depending on the loop, immediately stop the loop
* as it no single step.
* @author ebner
*
*/
public class OTFActuator implements Actor {
/**
* Name of the motor channel
*/
private final String name;
/**
* Channel name of the encoder;
*/
private final String readback;
private double start;
private double end;
private final double stepSize;
private final double integrationTime;
private final String id;
/**
* Additional backlash for the motor
*/
private final double additionalBacklash;
public OTFActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){
this.id = id;
this.name = name;
this.readback = readback;
this.start = start;
this.end = end;
this.stepSize = stepSize;
this.integrationTime = integrationTime;
this.additionalBacklash = additionalBacklash;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#set()
*/
@Override
public void set() {
// Do nothing
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#hasNext()
*/
@Override
public boolean hasNext() {
return false;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the readback
*/
public String getReadback() {
return readback;
}
/**
* @return the start
*/
public double getStart() {
return start;
}
/**
* @return the end
*/
public double getEnd() {
return end;
}
/**
* @return the stepSize
*/
public double getStepSize() {
return stepSize;
}
/**
* @return the integrationTime
*/
public double getIntegrationTime() {
return integrationTime;
}
/**
* @return the additionalBacklash
*/
public double getAdditionalBacklash() {
return additionalBacklash;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#init()
*/
@Override
public void init() {
// Not implemented
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#reverse()
*/
@Override
public void reverse() {
// Not implemented
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#reset()
*/
@Override
public void reset() {
// Not implemented
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Actor#destroy()
*/
@Override
public void destroy() {
// Nothing to be done
}
/**
* @param start the start to set
*/
public void setStart(double start) {
this.start = start;
}
/**
* @param end the end to set
*/
public void setEnd(double end) {
this.end = end;
}
}

View File

@@ -1,96 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.guard;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Channel and condition that need to be met.
* @author ebner
*
*/
public class ChannelAccessGuardCondition {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessGuardCondition.class.getName());
/**
* Channel name
*/
private final ChannelBean<?> channel;
/**
* Value of the channel to meet condition
*/
private final Object value;
/**
* Constructor
* @param channel Name of the channel that contributes to a guard
* @param value
*/
public ChannelAccessGuardCondition(String channel, Object value){
try {
this.channel = ChannelBeanFactory.getFactory().createChannelBean(value.getClass(), channel, true);
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channel+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize actuator channel [name:"+channel+"]",e);
}
this.value = value;
}
/**
* @return the channel
*/
public ChannelBean<?> getChannel() {
return channel;
}
/**
* @return the value
*/
public Object getValue() {
return value;
}
/**
* Destroy guard condition.
* Can be used for the cleanup of used resources of the guard condition (e.g. to close connections, ...) if
* this cannot be done automatically by the GarbageCollector.
*
* After calling this method the guard condition must not be used any more!
*/
public void destroy(){
// Destroy channel
try {
logger.finest("Destroy guard condition channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,162 +0,0 @@
/**
*
* Copyright 2012 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import jcifs.smb.SmbFile;
/**
* @author ebner
*
*/
public class DistributedFile {
private SmbFile smbfile = null;
private File file = null;
public DistributedFile(SmbFile file){
this.smbfile = file;
}
public DistributedFile(File file){
this.file = file;
}
public DistributedFile(String url) throws MalformedURLException{
if(url.startsWith("smb://")){
smbfile = new SmbFile(url);
}
else {
file = new File(url);
}
}
public String getCanonicalPath() throws IOException{
if(smbfile!=null){
return(smbfile.getCanonicalPath());
}
else{
return file.getCanonicalPath();
}
}
/**
* @return
* @throws IOException
*/
public boolean exists() throws IOException {
if(smbfile!=null){
return(smbfile.exists());
}
else{
return file.exists();
}
}
/**
* @return
*/
public boolean isDirectory() throws IOException {
if(smbfile!=null){
return(smbfile.isDirectory());
}
else{
return file.isDirectory();
}
}
/**
* @return
*/
public DistributedFile[] listFiles() throws IOException {
if(smbfile!=null){
SmbFile[] files = smbfile.listFiles();
DistributedFile[] dfiles = new DistributedFile[files.length];
for(int i=0;i<files.length;i++){
dfiles[i] = new DistributedFile(files[i]);
}
return(dfiles);
}
else{
File[] files = file.listFiles();
DistributedFile[] dfiles = new DistributedFile[files.length];
for(int i=0;i<files.length;i++){
dfiles[i] = new DistributedFile(files[i]);
}
return(dfiles);
}
}
/**
* @return
*/
public String getName() {
if(smbfile!=null){
return(smbfile.getName());
}
else{
return file.getName();
}
}
/**
* @return
*/
public boolean isFile() throws IOException {
if(smbfile!=null){
return(smbfile.isFile());
}
else{
return file.isFile();
}
}
/**
*
*/
public void delete() throws IOException {
if(smbfile!=null){
smbfile.delete();
}
else{
file.delete();
}
}
/**
* @return
*/
public InputStreamReader getInputStream() throws IOException {
if(smbfile!=null){
return(new InputStreamReader(smbfile.getInputStream()));
}
else{
return new FileReader(file);
}
}
}

View File

@@ -1,770 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops;
import gov.aps.jca.CAException;
import java.util.List;
import ch.psi.jcae.annotation.CaChannel;
import ch.psi.jcae.ChannelBean;
/**
* Bean holding all OTF channels and functionality
* @author ebner
*
*/
public class OTFBean {
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
public enum Command { NONE, START, STOP };
private long timeoutMotorOk = 8000;
private long commandTimeout = 20000; // Maximum time until a command should take effect
@CaChannel(type=String.class, name =":UMOT")
private ChannelBean<String> motor;
@CaChannel(type=String.class, name=":MENC")
private ChannelBean<String> encoder;
@CaChannel(type=Double.class, name=":UBEG")
private ChannelBean<Double> begin;
@CaChannel(type=Double.class, name=":UBEG.DRVL")
private ChannelBean<Double> beginMin;
@CaChannel(type=Double.class, name=":UBEG.DRVH")
private ChannelBean<Double> beginMax;
@CaChannel(type=Double.class, name=":UEND")
private ChannelBean<Double> end;
@CaChannel(type=Double.class, name=":UEND.DRVL")
private ChannelBean<Double> endMin;
@CaChannel(type=Double.class, name=":UEND.DRVH")
private ChannelBean<Double> endMax;
@CaChannel(type=Double.class, name=":USSIZ")
private ChannelBean<Double> stepSize;
@CaChannel(type=Double.class, name=":USSIZ.DRVL")
private ChannelBean<Double> stepSizeMin;
@CaChannel(type=Double.class, name=":UITIM")
private ChannelBean<Double> integrationTime;
@CaChannel(type=Double.class, name=":UITIM.DRVL")
private ChannelBean<Double> integrationTimeMin;
@CaChannel(type=Double.class, name=":UITIM.DRVH")
private ChannelBean<Double> integrationTimeMax;
@CaChannel(type=Double.class, name=":UBCL")
private ChannelBean<Double> userBacklash;
@CaChannel(type=String.class, name=":NFSSE")
private ChannelBean<String> nfsServer;
@CaChannel(type=String.class, name=":NFSSH")
private ChannelBean<String> nfsShare;
@CaChannel(type=String.class, name=":DFNAM")
private ChannelBean<String> fileName;
@CaChannel(type=String.class, name=":FFORM")
private ChannelBean<String> fileNameFormat;
@CaChannel(type=Integer.class, name=":FCNT")
private ChannelBean<Integer> fileCount;
@CaChannel(type=Integer.class, name=":FCNT.B")
private ChannelBean<Integer> resetFileCounter;
@CaChannel(type=Boolean.class, name=":FAPPE")
private ChannelBean<Boolean> appendFile;
@CaChannel(type=Boolean.class, name=":FUSE")
private ChannelBean<Boolean> fileNameGeneration;
@CaChannel(type=Boolean.class, name=":UZIGZ")
private ChannelBean<Boolean> zigZag;
@CaChannel(type=Integer.class, name=":UCOM")
private ChannelBean<Integer> command;
@CaChannel(type=Boolean.class, name=":SCRU", monitor=true)
private ChannelBean<Boolean> scanRunning;
@CaChannel(type=Boolean.class, name=":MUENC")
private ChannelBean<Boolean> useEncoder;
@CaChannel(type=String.class, name={":CTM0",":CTM1",":CTM2",":CTM3",":CTM4",":CTM5",":CTM6",":CTM7"})
private List<ChannelBean<String>> monitoredChannels;
@CaChannel(type=Boolean.class, name=":OTF", monitor=true)
private ChannelBean<Boolean> running;
@CaChannel(type=Integer.class, name=":USTAT", monitor=true)
private ChannelBean<Integer> status;
@CaChannel(type=Boolean.class, name=":MOK", monitor=true)
private ChannelBean<Boolean> motorOk;
@CaChannel(type=Boolean.class, name=":EOK", monitor=true)
private ChannelBean<Boolean> encoderOk;
@CaChannel(type=String.class, name=":MSG")
private ChannelBean<String> message;
/**
* Get the trigger name that can be used by the sscan record to trigger an OTFScan
* @return Name of the trigger that can be used by sscan record
*/
public String getSScanTriggerName(){
return(running.getName());
}
/**
* Start OTF scan
*/
public void start() {
try{
if(getStatus().equals(Status.INACTIVE)){
// Send START command
this.command.setValue(Command.START.ordinal());
// Wait until OtF logic is active
this.scanRunning.waitForValue(true, commandTimeout);
}
else{
throw new RuntimeException("Cannot start scan, status is not INACTIVE.\nThe current status is: "+getStatus()+" . The OTF logic need to be recovered manually [Message: "+getMessage()+"]");
}
}
catch(Exception e){
throw new RuntimeException("Unable to start OTF scan.",e);
}
}
/**
* Abort scan
*/
public void abort() {
try{
// Send STOP command
this.command.setValue(Command.STOP.ordinal());
// Do not wait for put to return
this.running.setValueNoWait(false);
}
catch(Exception e){
throw new RuntimeException("Unable to abort OTF logic" ,e);
}
}
/**
* Stop OTF scan
* @throws Exception
*/
public void stop() throws Exception{
if(!getStatus().equals(Status.INACTIVE) || !getStatus().equals(Status.FAULT)){
// Send STOP command
this.command.setValue(Command.STOP.ordinal());
// Wait until logic is stopped
status.waitForValue(Status.INACTIVE.ordinal(), commandTimeout);
}
}
/**
* Wait until scan has stopped
* @throws InterruptedException
*/
public void waitUntilStopped() throws InterruptedException {
try {
scanRunning.waitForValue(false); // Use of default wait timeout
// Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception
if(status.getValue() != Status.INACTIVE.ordinal()){
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
}
} catch (CAException e) {
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
}
}
/**
* Wait until scan has stopped
* @param waitTimeout
* @throws InterruptedException
*/
public void waitUntilStopped(Long waitTimeout) throws InterruptedException {
try {
scanRunning.waitForValue(false, waitTimeout);
// Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception
if(status.getValue() != Status.INACTIVE.ordinal()){
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
}
} catch (CAException e) {
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
}
}
/**
* Reset OTFScan records to defaults
* @throws CAException
* @throws InterruptedException
*/
public void resetToDefaults() throws CAException, InterruptedException{
setMonitoredChannels(new String[]{});
setMotor("");
begin.setValue(0d);
end.setValue(0d);
stepSize.setValue(0d);
integrationTime.setValue(0d);
zigZag.setValue(false);
setAppendFile(false);
setFileNameGeneration(true);
setFileName("");
setFileNameFormat("%06d.txt");
resetFileCounter();
setUserBacklash(0d);
// setNfsServer("");
// setNfsShare("");
waitUntilMotorNotOk(timeoutMotorOk);
}
/**
* Get motor of the OTFScan axis
* @return Name of the OTF motor
* @throws CAException
*/
public String getMotor() throws CAException, InterruptedException {
return(this.motor.getValue());
}
/**
* Set motor of the OTFScan axis
* @param motor
* @throws CAException
*/
public void setMotor(String motor) throws CAException, InterruptedException {
this.motor.setValue(motor);
}
/**
* Get encoder of the OTFScan axis
* @return Name of the used encoder
* @throws CAException
*/
public String getEncoder() throws CAException, InterruptedException {
return(this.encoder.getValue());
}
/**
* Set encoder to use of the OTFScan axis
* @param encoder
* @throws CAException
*/
public void setEncoder(String encoder) throws CAException, InterruptedException {
this.encoder.setValue(encoder);
}
/**
* Get begin position of the scan
* @return Begin position scan
* @throws CAException
*/
public Double getBegin() throws CAException, InterruptedException {
return(this.begin.getValue());
}
/**
* Set begin position of scan
* @param begin
* @throws Exception
*/
public void setBegin(Double begin) throws CAException, InterruptedException {
if(begin==null){
throw new IllegalArgumentException("Begin position must not be null");
}
if(begin < beginMin.getValue() || begin > beginMax.getValue()){
throw new IllegalArgumentException("Cannot set begin value to "+begin+ ". Value is outside range [min: "+beginMin.getValue()+" max: "+beginMax.getValue()+"]");
}
this.begin.setValue(begin);
}
/**
* Get minimum value of the begin position
* @return Min value for begin
* @throws CAException
*/
public Double getMinBegin() throws CAException, InterruptedException {
return(this.beginMin.getValue());
}
/**
* Get maximum value of the begin position
* @return Max value for begin
* @throws CAException
*/
public Double getMaxBegin() throws CAException, InterruptedException {
return(this.beginMax.getValue());
}
/**
* Get end position of the scan
* @return End position scan
* @throws CAException
*/
public Double getEnd() throws CAException, InterruptedException {
return(this.end.getValue());
}
/**
* Set end positon of scan
* @param end
* @throws CAException
*/
public void setEnd(Double end) throws CAException, InterruptedException {
if(end==null){
throw new IllegalArgumentException("End position must not be null");
}
if(end < endMin.getValue() || end > endMax.getValue()){
throw new IllegalArgumentException("Cannot set end value to "+end+ ". Value is outside range [min: "+endMin.getValue()+" max: "+endMax.getValue()+"]");
}
this.end.setValue(end);
}
/**
* Get minimum value of end position
* @return Min value for end
* @throws CAException
*/
public Double getMinEnd() throws CAException, InterruptedException {
return(this.endMin.getValue());
}
/**
* Get maximum value of end position
* @return Max value for end
* @throws CAException
*/
public Double getMaxEnd() throws CAException, InterruptedException {
return(this.endMax.getValue());
}
/**
* Get scan step size
* @return Step size
* @throws CAException
*/
public Double getStepSize() throws CAException, InterruptedException {
return(this.stepSize.getValue());
}
/**
* Set step size of scan
* @param stepSize
* @throws CAException
*/
public void setStepSize(Double stepSize) throws CAException, InterruptedException {
if(integrationTime==null){
throw new IllegalArgumentException("Step size must not be null");
}
// Check if step size is greater than min step size
if(stepSizeMin.getValue() != 0 && stepSize < stepSizeMin.getValue()){
throw new IllegalArgumentException("Step size value ["+stepSize+"] is less than minimum step size ["+stepSizeMin.getValue()+"]!");
}
this.stepSize.setValue(stepSize);
// TODO WORKAROUND - Wait to "ensure" that step size related fields are updated (i.e. min/max integration time)
Thread.sleep(1);
}
/**
* Get minimum integration time
* @return Min value for step size
* @throws CAException
*/
public double getMinStepSize() throws CAException, InterruptedException {
return(this.stepSizeMin.getValue());
}
/**
* Get scan integration time (time that is spend in one step)
* @return Integration time
* @throws CAException
*/
public Double getIntegrationTime() throws CAException, InterruptedException {
return(this.integrationTime.getValue());
}
/**
* Set integration time of scan
* @param integrationTime
* @throws CAException
*/
public void setIntegrationTime(Double integrationTime) throws CAException, InterruptedException {
if(integrationTime==null){
throw new IllegalArgumentException("Integration time must not be null");
}
// Check range (if limit is set to 0 then limit is not set)
double min = integrationTimeMin.getValue();
double max = integrationTimeMax.getValue();
if(min!= 0 && max!= 0){
if(integrationTime < min || integrationTime > max){
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: "+min+" max: "+max+"]");
}
}
else {
if(min!= 0 && integrationTime<min){
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: "+min+" max: - ]");
}
else if(max!= 0 && integrationTime>max){
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: - max: "+max+"]");
}
}
this.integrationTime.setValue(integrationTime);
}
/**
* Get minimum integration time
* @return Min value for integration time
* @throws CAException
*/
public Double getMinIntegrationTime() throws CAException, InterruptedException {
return(this.integrationTimeMin.getValue());
}
/**
* Get maximum integration time
* @return Max value for integration time
* @throws CAException
*/
public Double getMaxIntegrationTime() throws CAException, InterruptedException {
return(this.integrationTimeMax.getValue());
}
/**
* Get additional user defined backlash
* @return User backlash
* @throws CAException
*/
public Double getUserBacklash() throws CAException, InterruptedException {
return(this.userBacklash.getValue());
}
/**
* Set additional user defined backlash
* @param userBacklash
* @throws CAException
*/
public void setUserBacklash(Double userBacklash) throws CAException, InterruptedException {
if(userBacklash==null){
throw new IllegalArgumentException("User backlash must not be null");
}
this.userBacklash.setValue(userBacklash);
}
/**
* Get the current NFS server the data is written to
* @return Name of NFS server
* @throws CAException
*/
public String getNfsServer() throws CAException, InterruptedException {
return(this.nfsServer.getValue());
}
/**
* Set name of the NFS server the data is written to
* @param nfsServer
* @throws CAException
*/
public void setNfsServer(String nfsServer) throws CAException, InterruptedException {
this.nfsServer.setValue(nfsServer);
}
/**
* Get the NFS share the data is written to
* @return Name of NFS share
* @throws CAException
*/
public String getNfsShare() throws CAException, InterruptedException {
return(this.nfsShare.getValue());
}
/**
* Set name of the NFS share the data is written to
* @param nfsShare
* @throws CAException
*/
public void setNfsShare(String nfsShare) throws CAException, InterruptedException {
this.nfsShare.setValue(nfsShare);
}
/**
* Get the name of the data file
* @return Name of data file name
* @throws CAException
*/
public String getFileName() throws CAException, InterruptedException {
return(this.fileName.getValue());
}
/**
* Set name of the data file
* @param filename
* @throws CAException
*/
public void setFileName(String filename) throws CAException, InterruptedException {
this.fileName.setValue(filename);
}
/**
* Get File name formate
* @return Get format for file name
* @throws CAException
*/
public String getFileNameFormat() throws CAException, InterruptedException {
return(this.fileNameFormat.getValue());
}
/**
* Set file name formate of the data file
* @param fileNameFormat
* @throws Exception
*/
public void setFileNameFormat(String fileNameFormat) throws CAException, InterruptedException {
this.fileNameFormat.setValue(fileNameFormat);
}
/**
* Get value of the IOC based file name counter
* @return File counter
* @throws CAException
*/
public int getFileCounter() throws CAException, InterruptedException {
return(this.fileCount.getValue());
}
/**
* Reset the IOC based file counter
* @throws CAException
*/
public void resetFileCounter() throws CAException, InterruptedException {
this.resetFileCounter.setValue(1);
}
/**
* Get if append file option is activated
* @return Append file flag
* @throws CAException
*/
public boolean isAppendFile() throws CAException, InterruptedException {
return(this.appendFile.getValue());
}
/**
* Set whether to append the specified file if the file exists
* @param append
* @throws CAException
*/
public void setAppendFile(boolean append) throws CAException, InterruptedException {
this.appendFile.setValue(append);
}
/**
* Get if file name generation is on or off
* @return File name generation flag
* @throws CAException
*/
public boolean isFileNameGeneration() throws CAException, InterruptedException {
return(this.fileNameGeneration.getValue());
}
/**
* Set Whether the file name should be generated out of the file name format and the file counter
* @param generation
* @throws CAException
*/
public void setFileNameGeneration(boolean generation) throws CAException, InterruptedException {
this.fileNameGeneration.setValue(generation);
}
/**
* Get if ZigZag scan option is on or off
* @return ZigZag flag
* @throws CAException
*/
public boolean isZigZag() throws CAException, InterruptedException {
return(this.zigZag.getValue());
}
/**
* Set ZigZag scan mode on/off
* @param zigZag ZigZag mode on = true, ZigZag mode off = false
* @throws CAException
*/
public void setZigZag(boolean zigZag) throws CAException, InterruptedException {
this.zigZag.setValue(zigZag);
}
/**
* Get whether encoder is used
*/
public boolean isUseEncoder() throws CAException, InterruptedException {
return(this.useEncoder.getValue());
}
/**
* Set flag to use encoder
* @throws CAException
*/
public void setUseEncoder(boolean flag) throws CAException, InterruptedException {
this.useEncoder.setValue(flag);
}
/**
* Get the channels that are currently monitored by the OTFScan logic
* @return Names of the monitored channels
* @throws CAException
*/
public String[] getMonitoredChannels() throws CAException, InterruptedException {
String[] values = new String[this.monitoredChannels.size()];
for(int i=0; i<this.monitoredChannels.size();i++){
values[i] = monitoredChannels.get(i).getValue();
}
return(values);
}
/**
* Set the channels that need to be monitored.
* Note: As OTF only supports 8 channels to be monitored, only the first 8
* values of the passed channelNames are considered.
* @param values Array of channel names to be monitored
* @throws CAException
*/
public void setMonitoredChannels(String[] values) throws CAException, InterruptedException {
if(values.length>monitoredChannels.size()){
throw new IllegalArgumentException("Only up to "+monitoredChannels.size()+" monitored channels are supported by OTF");
}
for(int i=0; i<this.monitoredChannels.size(); i++){
if(values != null && i<values.length){
this.monitoredChannels.get(i).setValue(values[i]);
}
else{
this.monitoredChannels.get(i).setValue("");
}
}
}
/**
* Returns whether an scan is running
* @return Running flag
* @throws CAException
*/
public boolean isRunning() throws CAException, InterruptedException {
return(running.getValue());
}
/**
* Get status of the scan
* @return Status of the scan
* @throws CAException
*/
public Status getStatus() throws CAException, InterruptedException {
return(Status.values()[this.status.getValue()]);
}
/**
* Get the (error) message from the OTF records
* @return Message from OTF C logic
* @throws CAException
*/
public String getMessage() throws CAException, InterruptedException {
return(message.getValue());
}
/**
* Check whether the specified motor is recognized as ok (i.e. it is registered as OTFScan motor)
* @return Flag whether motor is ok
* @throws CAException
*/
public boolean isMotorOk() throws CAException, InterruptedException {
return(motorOk.getValue());
}
/**
* Wait until the motor flag goes to ok
* @param timeout Timout in milliseconds
*
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
*/
public void waitUntilMotorOk(long timeout) throws CAException, InterruptedException {
motorOk.waitForValue(true, timeout);
}
/**
* Wait until the motor flag goes to not ok
* @param timeout Timout in milliseconds
*
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
*/
public void waitUntilMotorNotOk(long timeout) throws CAException, InterruptedException {
motorOk.waitForValue(false, timeout);
}
public void waitUntilEncoderOk(long timeout) throws CAException, InterruptedException {
if(!useEncoder.getValue()){
return;
}
encoderOk.waitForValue(true, timeout);
}
}

View File

@@ -1,521 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
//import jcifs.smb.SmbException;
//import jcifs.smb.SmbFile;
import gov.aps.jca.CAException;
import ch.psi.fda.core.Action;
import ch.psi.fda.core.ActionLoop;
import ch.psi.fda.core.Sensor;
import ch.psi.fda.core.actors.OTFActuator;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
import ch.psi.fda.core.sensors.OTFReadbackSensor;
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
import ch.psi.jcae.ChannelBeanFactory;
/**
* ActionLoop that is implementing the OTF Scan logic.
* While executing the loop a full OTF scan procedure is executed.
* @author ebner
*
*/
public class OTFLoop implements ActionLoop {
// Get Logger
private static Logger logger = Logger.getLogger(OTFLoop.class.getName());
/**
* Flag to indicate whether the data of this loop will be grouped
* According to this flag the dataGroup flag in EndOfStream will be set.
*/
private boolean dataGroup = false;
// Constants
/**
* Maximum number of monitored channels
*/
private static final int numberOfMonitoredChannels = 8;
/**
* Maximum number of Scaler channels
*/
private static final int numberOfScalerChannels = 16;
/**
* Default timeout (in milliseconds) for wait operations
*/
private long timeout = 8000;
/**
* Name of the NFS server to place the data of the OTF logic
*/
private final String server;
/**
* Share on the NFS server to put the OTF data on to
*/
private final String share;
/**
* SMB share to access the data written by the OTF C logic
*/
private final String smbShare;
/**
* Flag whether the actor of this loop should move in zig zag mode
*/
private final boolean zigZag;
/**
* Bean holding all OTF channels and functionality.
*/
private OTFBean obean;
/**
* List of actions that are executed at the beginning of the loop.
*/
private List<Action> preActions;
/**
* List of actions that are executed at the end of the loop.
*/
private List<Action> postActions;
/**
* Special OTF Actuator
*/
private OTFActuator actor = null;
/**
* List of sensors of this loop
*/
private List<Sensor> sensors;
private List<Integer> dataIndexes;
/**
* Execution count of this loop. This count is used to determine the
* file name of the OTF file.
*/
private int executionCount;
/**
* Data queue sensor data is posted to. A message consists of a list of data objects
* that are read out of the sensors of this loop.
*/
private BlockingQueue<Message> dataQueue;
/**
* Flag that indicates that the loop was requested to abort.
*/
private volatile boolean abort = false;
/**
* Constructor
* @param channelPrefix Prefix of the OTF related records, e.g. MTEST-HW3-OTF
* @param server NFS server the OTF C Logic should put its data to
* @param share Share on NFS server to put the OTF C Logic data
* @param smbShare SMB share to get the data written by the OTF C Logic
* @param zigZag Operate loop in zig zag mode
*/
public OTFLoop(String channelPrefix, String server, String share, String smbShare, boolean zigZag){
// Initialize connection to the OTF records
try {
this.obean = new OTFBean();
ChannelBeanFactory.getFactory().createChannelBeans(obean, channelPrefix);
} catch (CAException e) {
throw new IllegalArgumentException("Unable to connect to the OTF channels",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to connect to the OTF channels",e);
}
// Store loop configuration
this.server = server;
this.share = share;
this.smbShare = smbShare;
this.zigZag = zigZag;
// Initialize lists used by the loop
this.preActions = new ArrayList<Action>();
this.postActions = new ArrayList<Action>();
this.sensors = new ArrayList<Sensor>();
this.dataQueue = new LinkedBlockingQueue<Message>(2000);
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#execute()
*/
@Override
public void execute() throws InterruptedException {
// Execute pre actions
for(Action action: preActions){
action.execute();
}
// Start scan
obean.start();
// Wait for end of scan
obean.waitUntilStopped();
// Read data from file
collectData();
// Execute post actions
for(Action action: postActions){
action.execute();
}
// Issue end of loop control message
dataQueue.put(new EndOfStreamMessage(dataGroup));
// Increase execution count
executionCount++;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
// Abort otf scan logic
obean.abort();
abort=true;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#prepare()
*/
@Override
public void prepare() {
executionCount = 0;
// Set abort flag to false
abort=false;
// Check whether actor is set for the loop
if(actor == null){
throw new IllegalStateException("No actor specified for this loop");
}
// list with all monitored channels
List<String> monitoredChannels = new ArrayList<String>();
dataIndexes = new ArrayList<Integer>();
int channelCount =0;
for(Sensor s: sensors){
if(s instanceof OTFNamedChannelSensor){
// Monitored channel
OTFNamedChannelSensor so = (OTFNamedChannelSensor) s;
if(channelCount>=numberOfMonitoredChannels){
throw new IllegalArgumentException("Only up to "+numberOfMonitoredChannels+" channels can be monitored by OTF");
}
monitoredChannels.add(so.getName());
dataIndexes.add(2+numberOfScalerChannels+channelCount);
channelCount++;
}
else if (s instanceof OTFScalerChannelSensor){
OTFScalerChannelSensor so = (OTFScalerChannelSensor) s;
if(so.getIndex()>=numberOfScalerChannels){
throw new IllegalArgumentException("Scaler index must be between 0<=index<"+numberOfScalerChannels);
}
dataIndexes.add(2+so.getIndex()); // scalers follow directly after the readback
}
else if (s instanceof MillisecondTimestampSensor){
dataIndexes.add(2+numberOfScalerChannels+numberOfMonitoredChannels);
}
else if (s instanceof OTFReadbackSensor){
dataIndexes.add(1);
}
else{
throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop");
}
}
// Set OTF parameters
try{
obean.resetToDefaults();
// Set actor properties
obean.setMotor(actor.getName());
obean.waitUntilMotorOk(timeout);
obean.setBegin(actor.getStart());
obean.setEnd(actor.getEnd());
obean.setStepSize(actor.getStepSize());
obean.setIntegrationTime(actor.getIntegrationTime());
// Override encoder if specified
if(actor.getReadback()!=null){
obean.setUseEncoder(true);
obean.setEncoder(actor.getReadback());
obean.waitUntilEncoderOk(timeout);
}
// Set user backlash
obean.setUserBacklash(actor.getAdditionalBacklash());
// NFS settings
obean.setNfsServer(server);
obean.setNfsShare(share);
obean.setFileNameGeneration(true);
obean.setAppendFile(false);
obean.setZigZag(zigZag); // Set ZigZag because there might be iterations
obean.setFileNameFormat("%06d"); // Force an update of the filename/counter by setting file format twice with different values
obean.setFileNameFormat("%06d.txt");
// Set monitored channels
obean.setMonitoredChannels(monitoredChannels.toArray(new String[monitoredChannels.size()]));
}
catch(CAException e){
throw new RuntimeException("Unable to set OTF configuration parameters",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to set OTF configuration parameters",e);
}
// Cleanup temporary directory
try{
DistributedFile tmpDir = new DistributedFile(smbShare);
if( !tmpDir.exists() || !tmpDir.isDirectory() ){
throw new RuntimeException("Cannot access OTF temporary directory "+tmpDir.getCanonicalPath());
}
DistributedFile[] files = tmpDir.listFiles();
for(int i=0;i<files.length;i++){
// Only delete item if it is not a directory and if it matches the given pattern.
if(files[i].isFile() && files[i].getName().matches("[0-9]+.txt")){
files[i].delete();
logger.fine("Delete file: "+files[i].getName());
}
}
}
catch(MalformedURLException e){
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException("Unable to access share (temporary files)",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#cleanup()
*/
@Override
public void cleanup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
// Close all connections used by the OTFBean
try {
ChannelBeanFactory.getFactory().destroyChannelBeans(obean);
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channels",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to destroy channels",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#getPreActions()
*/
@Override
public List<Action> getPreActions() {
return preActions;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#getPostActions()
*/
@Override
public List<Action> getPostActions() {
return postActions;
}
/**
* The structure of the data message depends on the sensors registered at this loop
* at the time this method is called.
* @return the data queue and the metadata of the data messages
*/
public DataQueue getDataQueue() {
DataMessageMetadata m = new DataMessageMetadata();
// Build up data message metadata based on the sensors currently registered.
for(Sensor s: sensors){
m.getComponents().add(new ComponentMetadata(s.getId()));
}
return new DataQueue(dataQueue, m);
}
/**
* Collect data written by the OTFScan logic
* @param dataSet
* @param tmpFile
*/
private void collectData() {
try{
final int timestampIndex = 2+numberOfScalerChannels+numberOfMonitoredChannels;
DistributedFile tmpFile = new DistributedFile(smbShare +"/"+ String.format("%06d.txt", executionCount));
logger.fine("Collect data from "+tmpFile.getCanonicalPath());
DistributedFile lockfile = new DistributedFile(tmpFile.getCanonicalPath() + ".lock");
logger.fine("Wait until file is written [lock file: "+lockfile.getCanonicalPath()+"]");
// Wait until file is created
while ((!tmpFile.exists()) || lockfile.exists()) {
Thread.sleep(500);
if(abort){
// If abort is issued while waiting for data immediately return without
// trying to read the data
return;
}
}
logger.fine("Read file " + tmpFile.getCanonicalPath());
InputStreamReader inreader = tmpFile.getInputStream();
BufferedReader in = new BufferedReader(inreader);
String line;
boolean firstline = true;
while (true) {
line = in.readLine();
if (line == null) {
break;
} else {
if(line.matches("^\\[.*")){
// Skip header lines
}
else{
if(firstline){
firstline=false;
continue;
}
DataMessage message = new DataMessage();
// Add data to dataset
String[] tokens = line.split("\t");
for(Integer i: dataIndexes){
try{
if(i == timestampIndex) {
// Calculate time in milliseconds
Double seconds = new Double(tokens[i]);
Double nanoseconds = new Double(tokens[i+1]);
Double v = seconds*1000+Math.floor(nanoseconds*0.000001);
message.getData().add(v);
}
else {
message.getData().add(new Double(tokens[i]));
}
}
catch(NumberFormatException e){
logger.warning("Cannot parse component ["+tokens[i]+"] from source file - will add 0 for this component");
message.getData().add(new Double(0));
}
}
dataQueue.put(message);
}
}
}
in.close();
inreader.close();
} catch(InterruptedException e){
throw new RuntimeException("An interrupt occured while waiting for the file to show up",e);
} catch (IOException e) {
throw new RuntimeException("An IO Exception occured while reading the OTF data file",e);
}
}
// Getter functions for variable parts
/**
* @return the sensors
*/
public List<Sensor> getSensors() {
return sensors;
}
/**
* @return the actor
*/
public OTFActuator getActor() {
return actor;
}
/**
* @param actor the actor to set
*/
public void setActor(OTFActuator actor) {
this.actor = actor;
}
/**
* @return the dataGroup
*/
public boolean isDataGroup() {
return dataGroup;
}
/**
* @param dataGroup the dataGroup to set
*/
public void setDataGroup(boolean dataGroup) {
this.dataGroup = dataGroup;
}
}

View File

@@ -1,157 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.annotation.CaChannel;
/**
* @author ebner
*
*/
public class CrlogicChannelsTemplate {
/**
* Status of the OTFSCAN IOC logic
*/
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
/**
* Ticks per second - IOC setting
* ATTENTION - This field must only be set bu the IOC - ATTENTION
*/
@CaChannel(type=Integer.class, name =":TPS")
private ChannelBean<Integer> ticksPerSecond;
/**
* Status of the OTFSCAN IOC logic
*/
@CaChannel(type=String.class, name =":STATUS")
private ChannelBean<String> status;
/**
* Message from the OTFSCAN IOC logic
*/
@CaChannel(type=String.class, name =":MSG")
private ChannelBean<String> message;
/**
* IOC ticks between data acquisition interrupts
*/
@CaChannel(type=Integer.class, name =":TBINT")
private ChannelBean<Integer> ticksBetweenInterrupts;
/**
* Name or ip address of the NFS server to save the data to
* (depending on the IOC setup)
*/
@CaChannel(type=String.class, name =":NFSSE")
private ChannelBean<String> nfsServer;
/**
* Name of the NFS share on the NFS server
*/
@CaChannel(type=String.class, name =":NFSSH")
private ChannelBean<String> nfsShare;
/**
* Name of the data file
*/
@CaChannel(type=String.class, name =":DFNAM")
private ChannelBean<String> dataFile;
/**
* Flag to identify whether the data file should be appended
*/
@CaChannel(type=Boolean.class, name =":FAPPE")
private ChannelBean<Boolean> appendFile;
/**
* Readout resources
*/
@CaChannel(type=String[].class, name =":RRES")
private ChannelBean<String[]> readoutResources;
/**
* @return the ticksPerSecond
*/
public ChannelBean<Integer> getTicksPerSecond() {
return ticksPerSecond;
}
/**
* @return the status
*/
public ChannelBean<String> getStatus() {
return status;
}
/**
* @return the message
*/
public ChannelBean<String> getMessage() {
return message;
}
/**
* @return the ticksBetweenInterrupts
*/
public ChannelBean<Integer> getTicksBetweenInterrupts() {
return ticksBetweenInterrupts;
}
/**
* @return the nfsServer
*/
public ChannelBean<String> getNfsServer() {
return nfsServer;
}
/**
* @return the nfsShare
*/
public ChannelBean<String> getNfsShare() {
return nfsShare;
}
/**
* @return the dataFile
*/
public ChannelBean<String> getDataFile() {
return dataFile;
}
/**
* @return the appendFile
*/
public ChannelBean<Boolean> getAppendFile() {
return appendFile;
}
/**
* @return the readoutResources
*/
public ChannelBean<String[]> getReadoutResources() {
return readoutResources;
}
}

View File

@@ -1,898 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.logging.Logger;
import jcifs.smb.SmbFile;
import gov.aps.jca.CAException;
import ch.psi.fda.core.Action;
import ch.psi.fda.core.ActionLoop;
import ch.psi.fda.core.Sensor;
import ch.psi.fda.core.actors.OTFActuator;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
import ch.psi.jcae.ChannelBeanFactory;
/**
* @author ebner
*
* While using Crlogic the IOC system clock rate should/must be set to 1000 (default 60)
*
* sysClkRateSet 1000
*
*/
public class CrlogicLoop implements ActionLoop {
// Get Logger
private static final Logger logger = Logger.getLogger(CrlogicLoop.class.getName());
/**
* Flag to indicate whether the data of this loop will be grouped
* According to this flag the dataGroup flag in EndOfStream will be set.
*/
private boolean dataGroup = false;
private boolean keepTmpFiles = false;
private BlockingQueue<String> readQueue = new LinkedBlockingQueue<String>();
private volatile boolean stopReadoutThread = false;
private Thread readoutThread;
// Constants
/**
* Default timeout (in milliseconds) for wait operations
*/
private long startStopTimeout = 8000;
/**
* Name of the NFS server to place the data of the OTF logic
*/
private final String server;
/**
* Share on the NFS server to put the OTF data on to
*/
private final String share;
/**
* SMB share to access the data written by the OTF C logic
*/
private final String smbShare;
/**
* Flag whether the actor of this loop should move in zig zag mode
*/
private final boolean zigZag;
boolean useReadback;
boolean useEncoder;
/**
* List of actions that are executed at the beginning of the loop.
*/
private List<Action> preActions;
/**
* List of actions that are executed at the end of the loop.
*/
private List<Action> postActions;
/**
* Prefix for the CRLOGIC channels
*/
private String prefix;
private CrlogicChannelsTemplate template;
private MotorChannelsTemplate motortemplate;
/**
* Semaphore to ensure that data is read in correct sequence
*/
private Semaphore semaphore = new Semaphore(1);
/**
* Special OTF Actuator
*/
private OTFActuator actuator = null;
/**
* List of sensors of this loop
*/
private List<Sensor> sensors;
private List<String> readoutResources;
private Map<Integer, CrlogicDeltaDataFilter> scalerIndices;
private CrlogicRangeDataFilter crlogicDataFilter;
/**
* Data queue sensor data is posted to. A message consists of a list of data objects
* that are read out of the sensors of this loop.
*/
private BlockingQueue<Message> dataQueue;
/**
* Abort status
*/
private boolean abort = false;
private boolean abortForce = false;
private Thread executionThread = null;
public CrlogicLoop(String prefix, String server, String share, String smbShare, boolean zigZag){
this.prefix = prefix;
this.server = server;
this.share = share;
this.smbShare = smbShare;
this.zigZag = zigZag;
// Initialize lists used by the loop
this.preActions = new ArrayList<Action>();
this.postActions = new ArrayList<Action>();
this.sensors = new ArrayList<Sensor>();
this.readoutResources = new ArrayList<String>();
this.scalerIndices = new HashMap<Integer, CrlogicDeltaDataFilter>();
this.crlogicDataFilter = new CrlogicRangeDataFilter();
this.dataQueue = new LinkedBlockingQueue<Message>(2000);
}
/**
* Collect data from share
* @param tmpFileName Name of the temporary file
* @throws InterruptedException
* @throws IOException
*/
private void collectData(String tmpDir, String tmpFileName) throws InterruptedException, IOException {
semaphore.acquire();
if (tmpDir.startsWith("smb:")) {
SmbFile tmpFile = new SmbFile(tmpDir, tmpFileName);
logger.info("Collect data from " + tmpFile.getCanonicalPath());
SmbFile lockfile = new SmbFile(tmpFile.getCanonicalPath() + ".lock");
logger.info("Wait until file is written [lock file: " + lockfile.getCanonicalPath() + "]");
// Wait until file is created
while ((!tmpFile.exists()) || lockfile.exists()) {
try{
Thread.sleep(100);
}
catch(InterruptedException e){
abort=true;
}
if(abort){
// If abort is issued while waiting for data immediately return without
// trying to read the data
return;
}
}
InputStreamReader inreader = new InputStreamReader(tmpFile.getInputStream());
BufferedReader in = new BufferedReader(inreader);
String line;
boolean firstline = true;
int linecount=0;
int mcounter=0;
// boolean wasInRangeBefore = false;
boolean discardAnyway = false;
while (true) {
line = in.readLine();
linecount++;
if (line == null) {
break;
} else {
// if(line.matches("^\\[.*")){
if (line.matches("^ *#.*")) {
// Skip header/comment lines
// logger.info("HEADER: " + line);
} else {
if (firstline) {
firstline = false;
continue;
}
// logger.info(line);
// Write into queue
DataMessage message = new DataMessage();
String[] tokens = line.split("\t");
boolean use = true;
for(int i=0;i<tokens.length;i++){
String t = tokens[i];
Double val;
if(i==0){
Double raw = new Double(t);
if(useEncoder){
val = crlogicDataFilter.calculatePositionMotorUseEncoder(raw);
}
else if(useReadback){
val = crlogicDataFilter.calculatePositionMotorUseReadback(raw);
}
else{
val = crlogicDataFilter.calculatePositionMotor(raw);
}
// Check whether data is within the configured range - otherwise drop data
use = crlogicDataFilter.filter(val);
// if(!use){
// break;
// }
}
else if(scalerIndices.containsKey(i)){
CrlogicDeltaDataFilter f = scalerIndices.get(i);
val = f.delta(new Double(t));
}
else{
val = new Double(t);
}
message.getData().add(val);
}
// Does not work if zigzag, ...
// // Use this to filter out motor retry movements at the end of the scan
// wasInRangeBefore = wasInRangeBefore | use;
// if(!use && wasInRangeBefore){
// discardAnyway=true;
// // Optimization - terminate read loop once range is left
// logger.info("Terminate read loop because point is outside range");
// break;
// }
// Filter data
if(use && !discardAnyway){
dataQueue.put(message);
mcounter++;
}
}
}
}
in.close();
inreader.close();
logger.info("Lines read: "+linecount+" Messages generated (after filtering): "+mcounter);
// Remove temporary file
if(!keepTmpFiles){
tmpFile.delete();
}
}
else{
// TODO - File in local file system
}
// Issue end of loop control message
dataQueue.put(new EndOfStreamMessage(dataGroup));
semaphore.release();
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#execute()
*/
@Override
public void execute() throws InterruptedException {
try{
double stepSize = actuator.getStepSize();
double start = actuator.getStart();
double end = actuator.getEnd();
double integrationTime = actuator.getIntegrationTime();
double ubacklash = actuator.getAdditionalBacklash();
// Set values for the datafilter
crlogicDataFilter.setStart(actuator.getStart());
crlogicDataFilter.setEnd(actuator.getEnd());
// Reset data filter
for(Integer k: scalerIndices.keySet()){
scalerIndices.get(k).reset();
}
synchronized(this){
// Set abort state to false
abort = false;
abortForce = false;
// Set execution thread to current thread
executionThread = Thread.currentThread();
}
// TODO each actuator will result in an additional sensor (at the beginning)
// Dependent on actuator settings (readback use encoder, ...)
// TODO filename generation?
final String tmpFileName = "tmp-"+System.currentTimeMillis()+".txt";
Long timeout = 600000l; // 10 minutes move timeout
// Check if logic is inactive, otherwise return early
if(!template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.INACTIVE.toString())){
logger.info("CRLOGIC is not inactive!");
// TODO Decide what to do in this situation
if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.FAULT.toString())){
// If in fault show message and recover
logger.info("CRLOGIC in FAULT state");
logger.info("Error message: "+template.getMessage().getValue());
logger.info("Recover logic and set it to INACTIVE");
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INACTIVE.toString());
}
else if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.ACTIVE.toString())){
template.getStatus().setValue(CrlogicChannelsTemplate.Status.STOP.toString());
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.INACTIVE.toString(), startStopTimeout);
}
else{
throw new RuntimeException("CRLOGIC is not inactive");
}
}
logger.info("Set parameters");
template.getNfsServer().setValue(server);
template.getNfsShare().setValue(share);
template.getDataFile().setValue(tmpFileName);
int tps = template.getTicksPerSecond().getValue();
logger.info("Ticks per second: "+tps);
logger.info("Set readout resources");
template.getReadoutResources().setValue(readoutResources.toArray(new String[readoutResources.size()]));
// Set ticks between interrupt to integration time
int ticks = (int)(tps*integrationTime);
template.getTicksBetweenInterrupts().setValue(ticks);
// Prepare motor
double totalTimeSeconds = Math.abs((end-start)/stepSize*integrationTime);
int hours = (int) Math.floor(totalTimeSeconds/60/60);
int minutes = (int) Math.floor(totalTimeSeconds/60-hours*60);
int seconds = (int) Math.floor(totalTimeSeconds-hours*60*60-minutes*60);
logger.info("Estimated time: "+hours+":"+minutes+":"+seconds);
int direction = 1;
if(end-start<0){
direction = -1;
}
double motorBaseSpeed = motortemplate.getBaseSpeed().getValue();
double motorHighLimit = motortemplate.getHighLimit().getValue();
double motorLowLimit = motortemplate.getLowLimit().getValue();
double motorBacklash = motortemplate.getBacklashDistance().getValue();
boolean respectMotorMinSpeed = false; // if false set min speed to 0
double motorMinSpeed = 0;
if(respectMotorMinSpeed){
motorMinSpeed = motorBaseSpeed;
}
// Check user parameters
// TODO start and end values must be between the motor high and low value - otherwise fail
if(start>motorHighLimit || start<motorLowLimit){
// Start value is outside motor high and/or low value
logger.info("Start value is outside motor high and/or low value");
throw new IllegalArgumentException("Start value is outside motor high and/or low value");
}
if(end>motorHighLimit || end<motorLowLimit){
// End value is outside motor high and/or low value
logger.info("End value is outside motor high and/or low value");
throw new IllegalArgumentException("End value is outside motor high and/or low value");
}
// TODO Check minimum step size
int minimumTicks = 10;
double minStepSize = motorMinSpeed*(minimumTicks/tps);
if(stepSize<minStepSize){
// Step size is too small
logger.info("Step size is too small");
throw new IllegalArgumentException("Step size is too small");
}
// TODO Check integration time
if(motorMinSpeed>0){
double maxIntegrationTime = stepSize/motorMinSpeed;
if(integrationTime>maxIntegrationTime){
logger.info("Integration time is too big");
// Integration time is too big
throw new IllegalArgumentException("Integration time is too big");
}
}
double motorMaxSpeed = motortemplate.getVelocity().getValue();
double minIntegrationTime = Math.min( (stepSize/motorMaxSpeed), ((double)minimumTicks/(double)tps) );
if(integrationTime<minIntegrationTime){
// Integration time is too small
logger.info("Integration time is too small [min integration time: "+minIntegrationTime+"]");
throw new IllegalArgumentException("Integration time is too small [min integration time: "+minIntegrationTime+"]");
}
// TODO Calculate and set motor speed, backlash, etc.
double motorSpeed = stepSize/integrationTime;
double backlash = (0.5*motorSpeed*motortemplate.getAccelerationTime().getValue())+motorBacklash+ubacklash;
double realEnd = end+(backlash*direction);
double realStart = start-(backlash*direction);
// Move to start
logger.info("Move motor to start ["+realStart+"]");
motortemplate.getSetValue().setValue(realStart, timeout); // Will block until move is done
// Set motor paramters
// Backup settings
logger.info("Backup motor settings");
double backupSpeed = motortemplate.getVelocity().getValue();
double backupBacklash = motorBacklash;
double backupMinSpeed = motorBaseSpeed;
try{
// Set motor settings
logger.info("Update motor settings");
// if(!respectMotorMinSpeed){
// motortemplate.getBaseSpeed().setValue(0d);
// }
// Set base speed as fast as possible but not faster than the original base speed.
double base = motorBaseSpeed;
if(motorSpeed<base){
base = motorSpeed;
}
motortemplate.getBaseSpeed().setValue(base);
motortemplate.getVelocity().setValue(motorSpeed);
motortemplate.getBacklashDistance().setValue(0d);
// Execute pre actions
for(Action action: preActions){
action.execute();
}
// Start crlogic logic
logger.info("Start CRLOGIC");
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INITIALIZE.toString());
try{
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.ACTIVE.toString(), startStopTimeout);
}
catch(CAException e){
logger.info( "Failed to start CRLOGIC. Logic in status: "+template.getStatus().getValue() );
if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.FAULT.toString())){
logger.info("Error message: "+template.getMessage().getValue());
}
// Recover to inactive
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INACTIVE.toString());
// TODO Improve error handling
throw new RuntimeException("Failed to start CRLOGIC. Logic in status: "+template.getStatus().getValue()+ " Error message: "+template.getMessage().getValue(), e);
}
// Move motor(s) to end / wait until motor is stopped
logger.info("Move motor to end ["+realEnd+"]");
try{
motortemplate.getSetValue().setValue(realEnd, timeout); // Will block until move is done
}
catch (InterruptedException e) {
if(abort & (!abortForce)){
// Abort motor move
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Stop.ordinal());
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Go.ordinal());
}
else{
throw e;
}
}
logger.info("Motor reached end position");
// Stop crlogic logic
logger.info("Stop CRLOGIC");
template.getStatus().setValue(CrlogicChannelsTemplate.Status.STOP.toString());
// Wait until stopped
logger.info("Wait until stopped");
try{
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.INACTIVE.toString(), startStopTimeout);
}
catch(CAException e){
logger.info( "Failed to stop CRLOGIC. Logic in status: "+template.getStatus().getValue() );
// TODO Improve error handling
throw new RuntimeException("Failed to stop CRLOGIC. Logic in status: "+template.getStatus().getValue(), e);
}
logger.info("CRLOGIC is now stopped");
// Execute post actions
for(Action action: postActions){
action.execute();
}
}
finally{
logger.info("Restore motor settings");
motortemplate.getBaseSpeed().setValue(backupMinSpeed);
motortemplate.getVelocity().setValue(backupSpeed);
motortemplate.getBacklashDistance().setValue(backupBacklash);
}
// Request read of data file
readQueue.put(tmpFileName);
// // Read data
// Thread t = new Thread(new Runnable() {
//
// @Override
// public void run() {
// try {
// collectData(smbShare, tmpFileName);
// } catch (InterruptedException e) {
// throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
// } catch (IOException e) {
// throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
// }
// }
// });
// t.start();
if(zigZag){
// Swap start and end
double aend = actuator.getEnd();
actuator.setEnd(actuator.getStart());
actuator.setStart(aend);
}
synchronized(this){
executionThread = null;
}
}
catch(CAException e){
throw new RuntimeException("Unable to execute crloop", e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
abort(false);
}
/**
* Abort logic
* @param force
*/
public synchronized void abort(boolean force){
abort = true;
abortForce = force;
// executionThread variable guarded by "this"
if(executionThread != null){
executionThread.interrupt();
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
stopReadoutThread = true;
readoutThread.interrupt();
// TODO eventually interrupt readout thread
try {
ChannelBeanFactory.getFactory().destroyChannelBeans(template);
ChannelBeanFactory.getFactory().destroyChannelBeans(motortemplate);
template = null;
motortemplate = null;
} catch (Exception e) {
throw new RuntimeException("Unable to destroy CrlogicLoop", e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#prepare()
*/
@Override
public void prepare() {
stopReadoutThread = false;
// Start readout Thread
readoutThread = new Thread(new Runnable() {
@Override
public void run() {
while(!stopReadoutThread){
String file;
try {
file = readQueue.take();
} catch (InterruptedException e) {
break;
}
// TODO Read file and
try {
collectData(smbShare, file);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
} catch (IOException e) {
throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
}
}
}
});
readoutThread.start();
try{
// Connect crlogic channels
template = new CrlogicChannelsTemplate();
logger.info("Connect channels");
ChannelBeanFactory.getFactory().createChannelBeans(template, prefix);
// Connect motor channels
motortemplate = new MotorChannelsTemplate();
ChannelBeanFactory.getFactory().createChannelBeans(motortemplate, actuator.getName());
useReadback = motortemplate.getUseReadback().getValue();
useEncoder = motortemplate.getUseEncoder().getValue();
logger.info("Motor type: "+ MotorChannelsTemplate.Type.values()[motortemplate.getType().getValue()]);
logger.info("Motor use readback: "+useReadback);
logger.info("Motor use encoder: "+useEncoder);
// TODO build up list of readout resources (based on sensors)
readoutResources.clear();
// first sensor is the actuator
// Determine mode of motor
if((!useReadback) && (!useEncoder)){
// Open loop
if(actuator.getReadback()!=null){
throw new IllegalArgumentException("Readback not supported if motor is configured in open loop");
}
else{
readoutResources.add(actuator.getName());
}
}
else if(useReadback && (!useEncoder)){
String readback;
// use readback link
if(actuator.getReadback()!=null){
// Use specified readback
readback = (actuator.getReadback());
}
else{
// Set resouce to readback link
readback = (motortemplate.getReadbackLink().getValue());
readback = readback.replaceAll(" +.*", ""); // remove NPP etc at the end
}
readoutResources.add(readback);
// Fill readback encoder settings
// Connect to encoder
EncoderChannelsTemplate encodertemplate = new EncoderChannelsTemplate();
ChannelBeanFactory.getFactory().createChannelBeans(encodertemplate, readback);
// Read encoder settings
if(encodertemplate.getDirection().getValue()==EncoderChannelsTemplate.Direction.Positive.ordinal()){
crlogicDataFilter.setEncoderDirection(1);
}
else{
crlogicDataFilter.setEncoderDirection(-1);
}
crlogicDataFilter.setEncoderOffset(encodertemplate.getOffset().getValue());
crlogicDataFilter.setEncoderResolution(encodertemplate.getResolution().getValue());
// Disconnect from encoder
ChannelBeanFactory.getFactory().destroyChannelBeans(encodertemplate);
}
else if (useEncoder && (!useReadback)){
// use readback link
if(actuator.getReadback()!=null){
throw new IllegalArgumentException("Readback not supported if motor is configured to use encoder");
}
else{
// Set resouce to readback link
readoutResources.add(actuator.getName()+"_ENC");
}
}
else{
throw new IllegalArgumentException("Motor configuration not supportet: use readback - "+useReadback+" use encoder - "+useEncoder);
}
// Fill Motor specific settings
if(motortemplate.getDirection().getValue()==MotorChannelsTemplate.Direction.Positive.ordinal()){
crlogicDataFilter.setMotorDirection(1);
}
else{
crlogicDataFilter.setMotorDirection(-1);
}
crlogicDataFilter.setMotorEncoderResolution(motortemplate.getEncoderResolution().getValue());
crlogicDataFilter.setMotorOffset(motortemplate.getOffset().getValue());
crlogicDataFilter.setMotorReadbackResolution(motortemplate.getReadbackResolution().getValue());
crlogicDataFilter.setMotorResolution(motortemplate.getMotorResolution().getValue());
// Clear all indices
scalerIndices.clear();
int c = 1; // We start at 1 because the actuator right now is an implicit sensor
for(Sensor s: sensors){
if(s instanceof OTFNamedChannelSensor){
// Monitored channel (MUST be configured MODULE ID'S)
OTFNamedChannelSensor so = (OTFNamedChannelSensor) s;
readoutResources.add(so.getName());
}
else if (s instanceof OTFScalerChannelSensor){
OTFScalerChannelSensor so = (OTFScalerChannelSensor) s;
readoutResources.add("SCALER"+so.getIndex());
scalerIndices.put(c, new CrlogicDeltaDataFilter());
}
else if (s instanceof MillisecondTimestampSensor){
readoutResources.add("TIMESTAMP");
}
else{
throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop");
}
c++;
}
// Workaround - somehow one has to add an empty thing to the value otherwise the c logic
// does not pick up the end
readoutResources.add("");
}
catch(Exception e){
throw new RuntimeException("Unable to prepare crloop: ",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#cleanup()
*/
@Override
public void cleanup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#getPreActions()
*/
@Override
public List<Action> getPreActions() {
return preActions;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#getPostActions()
*/
@Override
public List<Action> getPostActions() {
return postActions;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#isDataGroup()
*/
@Override
public boolean isDataGroup() {
// TODO Auto-generated method stub
return dataGroup;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.ActionLoop#setDataGroup(boolean)
*/
@Override
public void setDataGroup(boolean dataGroup) {
this.dataGroup = dataGroup;
}
/**
* @return the sensors
*/
public List<Sensor> getSensors() {
return sensors;
}
/**
* @return the actor
*/
public OTFActuator getActor() {
return actuator;
}
/**
* @param actor the actor to set
*/
public void setActor(OTFActuator actor) {
this.actuator = actor;
}
/**
* The structure of the data message depends on the sensors registered at this loop
* at the time this method is called.
* @return the data queue and the metadata of the data messages
*/
public DataQueue getDataQueue() {
DataMessageMetadata m = new DataMessageMetadata();
// Build up data message metadata based on the sensors currently registered.
m.getComponents().add(new ComponentMetadata(actuator.getId()));
for(Sensor s: sensors){
m.getComponents().add(new ComponentMetadata(s.getId()));
}
return new DataQueue(dataQueue, m);
}
/**
* @return the keepTmpFiles
*/
public boolean isKeepTmpFiles() {
return keepTmpFiles;
}
/**
* @param keepTmpFiles the keepTmpFiles to set
*/
public void setKeepTmpFiles(boolean keepTmpFiles) {
this.keepTmpFiles = keepTmpFiles;
}
}

View File

@@ -1,652 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.annotation.CaChannel;
/**
* @author ebner
*
*/
public class MotorChannelsTemplate {
public enum Type {SOFT_CHANNEL, MOTOR_SIMULATION, OMS_VME58, OMS_MAXv};
/**
* ## Drive section ##
* # User coordinates #
*/
/**
* .HLM High limit - double
*/
@CaChannel(type=Double.class, name =".HLM")
private ChannelBean<Double> highLimit;
/**
* .LLM Low limit - double
*/
@CaChannel(type=Double.class, name =".LLM")
private ChannelBean<Double> lowLimit;
/**
* .RBV Readback value - double
*/
@CaChannel(type=Double.class, name =".RBV", monitor=true)
private ChannelBean<Double> readbackValue;
/**
* .VAL Set value - double
*/
@CaChannel(type=Double.class, name =".VAL", monitor=true)
private ChannelBean<Double> setValue;
/**
* .RLV Relative move value - double
*/
@CaChannel(type=Double.class, name =".RLV")
private ChannelBean<Double> relativeMoveValue;
/**
* .TWV Teak value - double
*/
@CaChannel(type=Double.class, name =".TWV")
private ChannelBean<Double> tweakValue;
/**
* .TWR Tweak reverse - move left - int
*/
@CaChannel(type=Integer.class, name =".TWR")
private ChannelBean<Integer> tweakReverse;
/**
* .TWF Tweak forward - move right - int
*/
@CaChannel(type=Integer.class, name =".TWF")
private ChannelBean<Integer> tweakForward;
/**
* .JOGR Jog reverse - int
*/
@CaChannel(type=Integer.class, name =".JOGR")
private ChannelBean<Integer> jogReverse;
/**
* .JOGF Jog forward - int
*/
@CaChannel(type=Integer.class, name =".JOGF")
private ChannelBean<Integer> jogForward;
/**
* .HOMR Home reverse - int
*/
@CaChannel(type=Integer.class, name =".HOMR")
private ChannelBean<Integer> homeReverse;
/**
* .HOMF Home forward - int
*/
@CaChannel(type=Integer.class, name =".HOMF")
private ChannelBean<Integer> homeForward;
/**
* .EGU Engineering unit - String
*/
@CaChannel(type=String.class, name =".EGU")
private ChannelBean<String> engineeringUnit;
/**
* .DTYP Type - String (e.g. "OMS MAXv") see enum Type
*/
@CaChannel(type=Integer.class, name =".DTYP")
private ChannelBean<Integer> type;
/**
* .DESC Description - String
*/
@CaChannel(type=String.class, name =".DESC")
private ChannelBean<String> description;
/**
* # Dial coordinates #
*/
/**
* .DHLM Dial high limit - double
*/
@CaChannel(type=Double.class, name =".DHLM")
private ChannelBean<Double> dialHighLimit;
/**
* .DLLM Dial low limit - double
*/
@CaChannel(type=Double.class, name =".DLLM")
private ChannelBean<Double> dialLowLimit;
/**
* .DRBV Dial readback value - double
*/
@CaChannel(type=Double.class, name =".DRBV", monitor=true)
private ChannelBean<Double> dialReadbackValue;
/**
* .DVAL Dial set value - double
*/
@CaChannel(type=Double.class, name =".DVAL", monitor=true)
private ChannelBean<Double> dialSetValue;
/**
* .RVAL Raw value - int
*/
@CaChannel(type=Integer.class, name =".RVAL", monitor=true)
private ChannelBean<Integer> rawValue;
/**
* .RRBV Raw readback value - int
*/
@CaChannel(type=Integer.class, name =".RRBV", monitor=true)
private ChannelBean<Integer> rawReadbackValue;
/**
* .SPMG Stop/Pause/Move/Go - (0:"Stop", 1:"Pause", 2:"Move", 3:"Go") - 3
*/
public enum Commands { Stop, Pause, Move, Go };
@CaChannel(type=Integer.class, name =".SPMG")
private ChannelBean<Integer> command;
/**
* ## Calibration section ##
*/
/**
* .SET Set/Use Switch - (0:"Use", 1:"Set") - 0
*/
public enum Calibration {Use, Set};
@CaChannel(type=Integer.class, name =".SET")
private ChannelBean<Integer> calibration;
/**
* .OFF User offset (EGU) - double
*/
@CaChannel(type=Double.class, name =".OFF")
private ChannelBean<Double> offset;
/**
* .FOFF Offset-Freeze Switch - (0:"Variable", 1:"Frozen") - 1
*/
public enum OffsetMode {Variable, Frozen};
@CaChannel(type=Integer.class, name =".FOFF")
private ChannelBean<Integer> offsetMode;
/**
* .DIR User direction - (0:"Pos", 1:"Neg")
*/
public enum Direction {Positive, Negative};
@CaChannel(type=Integer.class, name =".DIR")
private ChannelBean<Integer> direction;
/**
* ## Dynamics ##
*/
/**
* .VELO Velocity (EGU/s) - double
*/
@CaChannel(type=Double.class, name =".VELO")
private ChannelBean<Double> velocity;
/**
* .BVEL Backlash velocity (EGU/s) - double
*/
@CaChannel(type=Double.class, name =".BVEL")
private ChannelBean<Double> backlashVelocity;
/**
* .VBAS Base speed (EGU/s) - double
*/
@CaChannel(type=Double.class, name =".VBAS")
private ChannelBean<Double> baseSpeed;
/**
* .ACCL Acceleration time / seconds to velocity - double
*/
@CaChannel(type=Double.class, name =".ACCL")
private ChannelBean<Double> accelerationTime;
/**
* .BACC Backlash acceleration time / seconds to velocity - double
*/
@CaChannel(type=Double.class, name =".BACC")
private ChannelBean<Double> backlashAccelerationTime;
/**
* .BDST Backlash distance (EGU) - double
*/
@CaChannel(type=Double.class, name =".BDST")
private ChannelBean<Double> backlashDistance;
/**
* .FRAC Move fraction - double
*/
@CaChannel(type=Double.class, name =".FRAC")
private ChannelBean<Double> moveFracion;
/**
* ## Resolution ##
*/
/**
* .MRES Motor resolution - double
*/
@CaChannel(type=Double.class, name =".MRES")
private ChannelBean<Double> motorResolution;
/**
* .ERES Encoder resolution - double
*/
@CaChannel(type=Double.class, name =".ERES")
private ChannelBean<Double> encoderResolution;
/**
* .RRES Readback resolution - double
*/
@CaChannel(type=Double.class, name =".RRES")
private ChannelBean<Double> readbackResolution;
/**
* .RDBD Retry deadband (EGU) - double
*/
@CaChannel(type=Double.class, name =".RDBD")
private ChannelBean<Double> retryDeadband;
/**
* .RTRY Max retry count - int
*/
@CaChannel(type=Integer.class, name =".RTRY")
private ChannelBean<Integer> maxRetryCount;
/**
* .RCNT Retry count - int
*/
@CaChannel(type=Integer.class, name =".RCNT", monitor=true)
private ChannelBean<Integer> retryCount;
/**
* .UEIP Use encoder (if present) - (0:"No", 1:"Yes")
*/
@CaChannel(type=Boolean.class, name =".UEIP")
private ChannelBean<Boolean> useEncoder;
/**
* .URIP Use readback link (if present) - (0:"No", 1:"Yes")
*/
@CaChannel(type=Boolean.class, name =".URIP")
private ChannelBean<Boolean> useReadback;
/**
* .DLY Readback delay (s) - double
*/
@CaChannel(type=Double.class, name =".DLY")
private ChannelBean<Double> readbackDelay;
/**
* .RDBL Readback link - String
*/
@CaChannel(type=String.class, name =".RDBL")
private ChannelBean<String> readbackLink;
/**
* .OMSL Output mode select - (0:"supervisory", 1:"closed_loop")
*/
public enum OutputMode {Supervisory, Closed_Loop};
@CaChannel(type=Integer.class, name =".OMSL")
private ChannelBean<Integer> outputMode;
/**
* ## Status ##
*/
/**
* .DMOV Done move - int
*/
@CaChannel(type=Boolean.class, name =".DMOV", monitor=true)
private ChannelBean<Boolean> moveDone;
/**
* @return the highLimit
*/
public ChannelBean<Double> getHighLimit() {
return highLimit;
}
/**
* @return the lowLimit
*/
public ChannelBean<Double> getLowLimit() {
return lowLimit;
}
/**
* @return the readbackValue
*/
public ChannelBean<Double> getReadbackValue() {
return readbackValue;
}
/**
* @return the setValue
*/
public ChannelBean<Double> getSetValue() {
return setValue;
}
/**
* @return the relativeMoveValue
*/
public ChannelBean<Double> getRelativeMoveValue() {
return relativeMoveValue;
}
/**
* @return the tweakValue
*/
public ChannelBean<Double> getTweakValue() {
return tweakValue;
}
/**
* @return the tweakReverse
*/
public ChannelBean<Integer> getTweakReverse() {
return tweakReverse;
}
/**
* @return the tweakForward
*/
public ChannelBean<Integer> getTweakForward() {
return tweakForward;
}
/**
* @return the jogReverse
*/
public ChannelBean<Integer> getJogReverse() {
return jogReverse;
}
/**
* @return the jogForward
*/
public ChannelBean<Integer> getJogForward() {
return jogForward;
}
/**
* @return the homeReverse
*/
public ChannelBean<Integer> getHomeReverse() {
return homeReverse;
}
/**
* @return the homeForward
*/
public ChannelBean<Integer> getHomeForward() {
return homeForward;
}
/**
* @return the engineeringUnit
*/
public ChannelBean<String> getEngineeringUnit() {
return engineeringUnit;
}
/**
* @return the type
*/
public ChannelBean<Integer> getType() {
return type;
}
/**
* @return the description
*/
public ChannelBean<String> getDescription() {
return description;
}
/**
* @return the dialHighLimit
*/
public ChannelBean<Double> getDialHighLimit() {
return dialHighLimit;
}
/**
* @return the dialLowLimit
*/
public ChannelBean<Double> getDialLowLimit() {
return dialLowLimit;
}
/**
* @return the dialReadbackValue
*/
public ChannelBean<Double> getDialReadbackValue() {
return dialReadbackValue;
}
/**
* @return the dialSetValue
*/
public ChannelBean<Double> getDialSetValue() {
return dialSetValue;
}
/**
* @return the rawValue
*/
public ChannelBean<Integer> getRawValue() {
return rawValue;
}
/**
* @return the rawReadbackValue
*/
public ChannelBean<Integer> getRawReadbackValue() {
return rawReadbackValue;
}
/**
* @return the command
*/
public ChannelBean<Integer> getCommand() {
return command;
}
/**
* @return the calibration
*/
public ChannelBean<Integer> getCalibration() {
return calibration;
}
/**
* @return the userOffset
*/
public ChannelBean<Double> getOffset() {
return offset;
}
/**
* @return the offsetMode
*/
public ChannelBean<Integer> getOffsetMode() {
return offsetMode;
}
/**
* @return the direction
*/
public ChannelBean<Integer> getDirection() {
return direction;
}
/**
* @return the velocity
*/
public ChannelBean<Double> getVelocity() {
return velocity;
}
/**
* @return the backlashVelocity
*/
public ChannelBean<Double> getBacklashVelocity() {
return backlashVelocity;
}
/**
* @return the baseSpeed
*/
public ChannelBean<Double> getBaseSpeed() {
return baseSpeed;
}
/**
* @return the accelerationTime
*/
public ChannelBean<Double> getAccelerationTime() {
return accelerationTime;
}
/**
* @return the backlashAccelerationTime
*/
public ChannelBean<Double> getBacklashAccelerationTime() {
return backlashAccelerationTime;
}
/**
* @return the backlashDistance
*/
public ChannelBean<Double> getBacklashDistance() {
return backlashDistance;
}
/**
* @return the moveFracion
*/
public ChannelBean<Double> getMoveFracion() {
return moveFracion;
}
/**
* @return the motorResolution
*/
public ChannelBean<Double> getMotorResolution() {
return motorResolution;
}
/**
* @return the encoderResolution
*/
public ChannelBean<Double> getEncoderResolution() {
return encoderResolution;
}
/**
* @return the readbackResolution
*/
public ChannelBean<Double> getReadbackResolution() {
return readbackResolution;
}
/**
* @return the retryDeadband
*/
public ChannelBean<Double> getRetryDeadband() {
return retryDeadband;
}
/**
* @return the maxRetryCount
*/
public ChannelBean<Integer> getMaxRetryCount() {
return maxRetryCount;
}
/**
* @return the retryCount
*/
public ChannelBean<Integer> getRetryCount() {
return retryCount;
}
/**
* @return the useEncoder
*/
public ChannelBean<Boolean> getUseEncoder() {
return useEncoder;
}
/**
* @return the useReadback
*/
public ChannelBean<Boolean> getUseReadback() {
return useReadback;
}
/**
* @return the readbackDelay
*/
public ChannelBean<Double> getReadbackDelay() {
return readbackDelay;
}
/**
* @return the readbackLink
*/
public ChannelBean<String> getReadbackLink() {
return readbackLink;
}
/**
* @return the outputMode
*/
public ChannelBean<Integer> getOutputMode() {
return outputMode;
}
/**
* @return the moveDone
*/
public ChannelBean<Boolean> getMoveDone() {
return moveDone;
}
}

View File

@@ -1,169 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* @author ebner
*
*/
public class ParallelCrlogicStreamMerge {
private BlockingQueue<Message> dataQueue;
private DataQueue primaryQueue;
private DataQueue secondaryQueue;
/**
* Class to merge two data streams into one. The secondary queues data is added to the primary queues data.
* The resulting queue therefor will hold the same amount of elements as the primary queue does.
* The datagroup flag set in the end of stream message will be set according to the flag set in the primary queue.
*
* @param pqueue Primary/master queue
* @param squeue Secondary queue
*/
public ParallelCrlogicStreamMerge(DataQueue pqueue, DataQueue squeue){
this.primaryQueue = pqueue;
this.secondaryQueue = squeue;
this.dataQueue = new LinkedBlockingQueue<Message>();
}
/**
* Merge the streams based on the timestamp
* @throws InterruptedException
*/
public void merge() throws InterruptedException{
// Actual data of the secondary queue
List<Object> currData = null;
// Take first element of the primary queue (wait until message is available)
Message m = primaryQueue.getQueue().take();
while(! (m instanceof EndOfStreamMessage)){
if(m instanceof DataMessage){
DataMessage dm = (DataMessage) m;
// Get and remove merge timestamp from the data of the message
Double timestamp = (Double) dm.getData().remove(1);
long milliseconds = (long) (timestamp*1000);
long nanoOffset = (long)((timestamp*1000-milliseconds)*1000000);
// System.out.println("timestamp: "+new Date(milliseconds)+" "+milliseconds+" ."+nanoOffset);
while(true){
// Assumption: the secondary Queue holds at least the data up to the
// timestamp of the primary queue
Message mess = secondaryQueue.getQueue().peek();
// Message mess = secondaryQueue.getQueue().take();
if(mess instanceof EndOfStreamMessage){
break;
}
if(mess == null){
break;
}
if(mess instanceof DataMessage){
// Check whether timestamp of the next message is bigger than the timestamp of the
// message from the primary queue - if the timestamp is bigger do not take message out of the queue
DataMessage msCheck = (DataMessage) mess;
// System.out.println("Mess: "+mess);
long currMilliCheck = ((Double) msCheck.getData().get(0)).longValue();
long currNanoCheck = ((Double) msCheck.getData().get(1)).longValue();
// Check
if(currMilliCheck>milliseconds || (currMilliCheck==milliseconds && currNanoCheck>nanoOffset)){
break;
}
DataMessage ms = (DataMessage) secondaryQueue.getQueue().take();
// System.out.println("Ms: "+ms);
currData = ms.getData();
// Remove timestamps
currData.remove(0);
currData.remove(0);
}
else{
// No DataMessage
break;
}
}
// Add data to primary data queue message and put it into the out queue
dm.getData().addAll(currData);
dataQueue.add(dm);
}
m = primaryQueue.getQueue().take();
}
// Add the end of stream message of the primary queue
dataQueue.add(m);
// Clear all remaining messages in secondary queue
secondaryQueue.getQueue().clear();
}
/**
* The structure of the data message depends on the sensors registered at this loop
* at the time this method is called.
* @return the data queue and the metadata of the data messages
*/
public DataQueue getDataQueue() {
DataMessageMetadata m = new DataMessageMetadata();
DataMessageMetadata pqm = primaryQueue.getDataMessageMetadata();
m.getComponents().add(pqm.getComponents().get(0)); // add first component (this is the actuator)
// Skip the next component as this is the timestamp used to merge the data
for(int i=2;i<pqm.getComponents().size();i++){
m.getComponents().add(pqm.getComponents().get(i));
}
DataMessageMetadata sqm = secondaryQueue.getDataMessageMetadata();
// Skip first two components of the message as this is the timestamp
for(int i=2;i<sqm.getComponents().size();i++){
m.getComponents().add(sqm.getComponents().get(i));
}
return new DataQueue(dataQueue, m);
}
}

View File

@@ -1,397 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import gov.aps.jca.CAException;
import gov.aps.jca.Monitor;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import ch.psi.fda.core.Action;
import ch.psi.fda.core.ActionLoop;
import ch.psi.fda.core.Sensor;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.MonitorListenerDoubleTimestamp;
/**
* @author ebner
*
* Assumptions: - The delay between the monitor writing the value to the
* monitor queue and the readout of all the queues is sufficient to
* prevent the situation that some monitors of events close to each
* other on different IOC's have not arrived yet. - The sequence of
* monitors fired for one channel is according to the sequence of the
* causes. No monitor package is overtaking an other package on the
* network.
*
* - No monitor events are lost on the network (while using monitors you
* cannot guarantee this)
*
* The data queue returned by this logic includes two items for the
* timestamp and nanoseconds offset. These two items are the first two
* items of a message The id's are: crTimestampMilliseconds
* crTimestampOffsetNanoseconds
*/
public class ScrlogicLoop implements ActionLoop {
private static String ID_TIMESTAMP_MILLISECONDS = "crTimestampMilliseconds";
private static String ID_TIMESTAMP_OFFSET_NANOSECONDS = "crTimestampOffsetNanoseconds";
// Get Logger
private static final Logger logger = Logger.getLogger(ScrlogicLoop.class.getName());
/**
* Data queue sensor data is posted to. A message consists of a list of data
* objects that are read out of the sensors of this loop.
*/
private final BlockingQueue<Message> dataQueue = new LinkedBlockingQueue<Message>();
private boolean dataGroup = false;
private final List<Action> preActions = new ArrayList<Action>();
private final List<Action> postActions = new ArrayList<Action>();
/**
* Sensors to read out
*/
private List<Sensor> sensors;
/**
* List of monitors that were attached to the sensor channels (i.e
* workaround)
*/
private final List<Monitor> monitors = new ArrayList<Monitor>();
/**
* List of blocking queues that hold the data for one sensor (channel)
*/
private final List<BlockingQueue<TimestampedValue>> queues = new ArrayList<BlockingQueue<TimestampedValue>>();
private CountDownLatch latch;
public ScrlogicLoop(List<Sensor> sensors) {
this.sensors = sensors;
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.Action#execute()
*/
@Override
public void execute() throws InterruptedException {
// Clear all queues
queues.clear();
latch = new CountDownLatch(1);
try {
// Attach monitors to the channels (this is actually a workaround)
for (Sensor sensor : sensors) {
if (sensor instanceof ChannelAccessDoubleSensor) {
ChannelAccessDoubleSensor s = (ChannelAccessDoubleSensor) sensor;
ChannelBean<Double> b = s.getChannel();
// Create data queue for the channel
final BlockingQueue<TimestampedValue> q = new LinkedBlockingQueue<TimestampedValue>();
queues.add(q);
Monitor m = b
.attachMonitor(new MonitorListenerDoubleTimestamp() {
@Override
public void valueChanged(Double value, Date timestamp, long nanosecondsOffset) {
// Add values to channel queue
q.add(new TimestampedValue(value, timestamp.getTime(), nanosecondsOffset));
}
});
monitors.add(m);
}
}
} catch (CAException e) {
new RuntimeException("Unable to create monitor for channels", e);
}
logger.info("Start data acquisition");
latch.await();
// Remove monitors
try {
for (int i = 0; i < sensors.size(); i++) {
Sensor sensor = sensors.get(i);
if (sensor instanceof ChannelAccessDoubleSensor) {
ChannelAccessDoubleSensor s = (ChannelAccessDoubleSensor) sensor;
ChannelBean<Double> b = s.getChannel();
try{
b.removeMonitor(monitors.get(i));
}
catch(IllegalArgumentException e){
logger.log(Level.SEVERE, "Unable to detach monitor", e);
}
}
}
} catch (CAException e) {
new RuntimeException(e);
}
finally{
// Clear all monitors in the list
monitors.clear();
}
// Merge data
merge();
// Clear data queues
for (BlockingQueue<TimestampedValue> q : queues) {
q.clear();
}
queues.clear();
// Put end of stream to the queue
dataQueue.add(new EndOfStreamMessage(dataGroup));
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.Action#abort()
*/
@Override
public void abort() {
latch.countDown();
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.Action#destroy()
*/
@Override
public void destroy() {
// Destroy all sensors
for (Sensor s : sensors) {
s.destroy();
}
sensors.clear();
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#prepare()
*/
@Override
public void prepare() {
// do nothing
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#cleanup()
*/
@Override
public void cleanup() {
// Do nothing
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#getPreActions()
*/
@Override
public List<Action> getPreActions() {
return preActions;
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#getPostActions()
*/
@Override
public List<Action> getPostActions() {
return postActions;
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#isDataGroup()
*/
@Override
public boolean isDataGroup() {
return dataGroup;
}
/*
* (non-Javadoc)
*
* @see ch.psi.fda.core.ActionLoop#setDataGroup(boolean)
*/
@Override
public void setDataGroup(boolean dataGroup) {
this.dataGroup = dataGroup;
}
/**
* The structure of the data message depends on the sensors registered at
* this loop at the time this method is called.
*
* @return the data queue and the metadata of the data messages
*/
public DataQueue getDataQueue() {
DataMessageMetadata m = new DataMessageMetadata();
// Build up data message metadata based on the channels registered.
m.getComponents().add(new ComponentMetadata(ID_TIMESTAMP_MILLISECONDS));
m.getComponents().add(
new ComponentMetadata(ID_TIMESTAMP_OFFSET_NANOSECONDS));
for (Sensor s : sensors) {
m.getComponents().add(new ComponentMetadata(s.getId()));
}
return new DataQueue(dataQueue, m);
}
private boolean hasNext(){
for (int i = 0; i < queues.size(); i++) {
if(!queues.get(i).isEmpty()){
return true;
}
}
return false;
}
/**
* Merge data collected by different monitor
*
* @throws InterruptedException
*/
private void merge() throws InterruptedException {
// Array to hold temporary channel values
TimestampedValue[] cvalues = new TimestampedValue[queues.size()];
TimestampedValueComparator comparator = new TimestampedValueComparator();
// Oldest value written
TimestampedValue globalOldest = null;
List<Integer> indexes = new ArrayList<Integer>();
while (hasNext()) {
// semaphore.acquire();
Thread.sleep(10); // Ensure that close by monitors have time to
// catch up / also ensure context switch
// Oldest value of this run
TimestampedValue oldest = null;
// Queue index of the oldest value of this run
indexes.clear();
// Find oldest element in any of the queues
for (int i = 0; i < queues.size(); i++) {
BlockingQueue<TimestampedValue> q = queues.get(i);
TimestampedValue ttcheck = q.peek();
if (ttcheck != null) {
if (oldest == null) {
// Update the oldest variable with current element
oldest = ttcheck;
indexes.clear();
indexes.add(i);
} else if (comparator.compare(ttcheck, oldest) < 0) {
// Check whether timestamp is less (older) than the current oldest timestamp.
oldest = ttcheck;
indexes.clear();
indexes.add(i);
} else if (comparator.compare(ttcheck, oldest) == 0) {
// SAME TIMESTAMP
indexes.add(i);
} else {
}
}
}
// logger.info("Index: "+index+" Permits: "+semaphore.availablePermits());
// System.out.println("indexes: "+indexes.size());
if (indexes.size() > 0) {
long timestamp = 0l;
long nanoOffset = 0l;
for (Integer index : indexes) {
// Get next older value
cvalues[index] = queues.get(index).poll();
if (globalOldest != null) {
if (comparator.compare(cvalues[index], globalOldest) >= 0) {
// Update the global oldest variable
globalOldest = cvalues[index];
timestamp = cvalues[index].getTimestamp();
nanoOffset = cvalues[index].getNanosecondsOffset();
} else {
// Monitors did not fire in sequence (an newer
// monitor overtook an older (from an other IOC))
logger.warning("Timestamped value out of sequence - discard value !!!!");
// Continue with next value ...
continue;
}
} else {
globalOldest = cvalues[index];
}
}
// Assemble data message ...
DataMessage message = new DataMessage();
message.getData().add(new Double(timestamp));
message.getData().add(new Double(nanoOffset));
for (int y = 0; y < cvalues.length; y++) {
if (cvalues[y] != null) {
message.getData().add(new Double(cvalues[y].getValue()));
} else {
message.getData().add(Double.NaN);
}
}
// System.out.println(message);
dataQueue.add(message);
}
}
}
}

View File

@@ -1,103 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import java.util.List;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.annotation.CaChannel;
/**
* @author ebner
*
*/
public class VSC16ScalerChannelsTemplate {
public enum Command {Done, Count};
/**
* Command
*/
@CaChannel(type=Integer.class, name =".CNT")
private ChannelBean<Integer> command;
public enum Mode {OneShot, AutoCount};
/**
* Count mode
*/
@CaChannel(type=Integer.class, name =".CONT")
private ChannelBean<Integer> mode;
/**
* Channel description
*/
@CaChannel(type=Boolean.class, name={".NM1", ".NM2", ".NM3", ".NM4", ".NM5", ".NM6", ".NM7", ".NM8", ".NM9", ".NM10", ".NM11", ".NM12", ".NM13", ".NM14", ".NM15", ".NM16"})
private List<ChannelBean<Boolean>> channelDescription;
/**
* Channel gate
*/
@CaChannel(type=Boolean.class, name={".G1", ".G2", ".G3", ".G4", ".G5", ".G6", ".G7", ".G8", ".G9", ".G10", ".G11", ".G12", ".G13", ".G14", ".G15", ".G16"})
private List<ChannelBean<Boolean>> channelGate;
/**
* Channel preset count
* If gate is on scaler will only count until this value
*/
@CaChannel(type=Integer.class, name={".PR1", ".PR2", ".PR3", ".PR4", ".PR5", ".PR6", ".PR7", ".PR8", ".PR9", ".PR10", ".PR11", ".PR12", ".PR13", ".PR14", ".PR15", ".PR16"})
private List<ChannelBean<Integer>> channelPresetCount;
/**
* @return the command
*/
public ChannelBean<Integer> getCommand() {
return command;
}
/**
* @return the mode
*/
public ChannelBean<Integer> getMode() {
return mode;
}
/**
* @return the channelDescription
*/
public List<ChannelBean<Boolean>> getChannelDescription() {
return channelDescription;
}
/**
* @return the channelGate
*/
public List<ChannelBean<Boolean>> getChannelGate() {
return channelGate;
}
/**
* @return the channelPresetCount
*/
public List<ChannelBean<Integer>> getChannelPresetCount() {
return channelPresetCount;
}
}

View File

@@ -1,83 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.messages;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Structure to hold the metadata of a component of a message.
* @author ebner
*
*/
public class DataMessageMetadata implements Serializable {
private static final long serialVersionUID = 1L;
/**
* List of the metadata of the message components
*/
private List<ComponentMetadata> components;
/**
* Default constructor
*/
public DataMessageMetadata(){
components = new ArrayList<ComponentMetadata>();
}
/**
* @return the list of component metadata of a message described by this object.
*/
public List<ComponentMetadata> getComponents() {
return components;
}
/**
* Get the index of the component with the specified Id
* @param componentId Id of the component to look for
* @return Index of the component
* @throws IllegalArgumentException There is no component with the specified Id
*/
public int getIndex(String componentId) throws IllegalArgumentException {
for(int i=0;i<components.size();i++){
ComponentMetadata c =components.get(i);
if(c.getId().equals(componentId)){
return(i);
}
}
throw new IllegalArgumentException("There is no message component with Id "+ componentId);
}
/**
* Clone data structure
* @return Cloned data structure
*/
public DataMessageMetadata clone(){
DataMessageMetadata metadata = new DataMessageMetadata();
for(int i=0;i<components.size();i++){
ComponentMetadata c =components.get(i);
metadata.getComponents().add(new ComponentMetadata(c.getId(), c.getDimension()));
}
return(metadata);
}
}

View File

@@ -1,66 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.messages;
import java.util.concurrent.BlockingQueue;
/**
* Container holding for holding a queue and the metadata of the
* data messages of that queue.
* @author ebner
*
*/
public class DataQueue {
/**
* Queue serving the messages
*/
private final BlockingQueue<Message> queue;
/**
* Metadata of the data messages of the queue
*/
private final DataMessageMetadata dataMessageMetadata;
/**
* Constructor
* @param queue Data queue
* @param dataMessageMetadata Metadata of the data messages of the queue
*/
public DataQueue(BlockingQueue<Message> queue, DataMessageMetadata dataMessageMetadata){
this.queue = queue;
this.dataMessageMetadata = dataMessageMetadata;
}
/**
* @return the queue
*/
public BlockingQueue<Message> getQueue() {
return queue;
}
/**
* @return the metadata
*/
public DataMessageMetadata getDataMessageMetadata() {
return dataMessageMetadata;
}
}

View File

@@ -1,75 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.scripting;
import java.util.HashMap;
/**
* Singleton dictionary class
*
* @author ebner
*
*/
public class JythonGlobalVariableDictionary {
private static JythonGlobalVariableDictionary instance = new JythonGlobalVariableDictionary();
private HashMap<String, JythonGlobalVariable> dictionary = new HashMap<String, JythonGlobalVariable>();
/**
* Private constructor
*/
private JythonGlobalVariableDictionary(){
}
/**
* Get singleton instance of the dictionary
* @return
*/
public static JythonGlobalVariableDictionary getInstance(){
return instance;
}
/**
* Get variable from dictionary. If the variable does not exist it will be created.
* @param name
* @return
*/
public JythonGlobalVariable getVariable(String name){
JythonGlobalVariable variable;
if(dictionary.containsKey(name)){
variable = dictionary.get(name);
}
else{
variable = new JythonGlobalVariable();
variable.setName(name);
dictionary.put(name, variable);
}
return variable;
}
/**
* Clear variable dictionary
*/
public void clear(){
dictionary.clear();
}
}

View File

@@ -1,75 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.scripting;
/**
* Mapping of a script parameter to a channel bean.
* @author ebner
*
*/
public class JythonParameterMappingChannel extends JythonParameterMapping {
/**
* Id of the component to map to this variable
*/
private String channel;
private Class<?> type;
/**
* Constructor accepting varible/id pair
* @param variable
* @param channel
* @param type
*/
public JythonParameterMappingChannel(String variable, String channel, Class<?> type){
super(variable);
this.channel = channel;
this.type = type;
}
/**
* @return the channel
*/
public String getChannel() {
return channel;
}
/**
* @param channel
*/
public void setChannel(String channel) {
this.channel = channel;
}
/**
* @return the type
*/
public Class<?> getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(Class<?> type) {
this.type = type;
}
}

View File

@@ -1,144 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.EngineConfiguration;
import ch.psi.fda.core.Sensor;
import ch.psi.jcae.ChannelBeanFactory;
import ch.psi.jcae.ChannelBean;
/**
* Scalar sensor that reads a double form a Channel Access channel
* @author ebner
*
*/
public class ChannelAccessDoubleArraySensor implements Sensor {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessDoubleArraySensor.class.getName());
/**
* Channel Access channel of this sensor
*/
private final ChannelBean<double[]> channel;
/**
* Number of elements to read from the waveform
*/
private final int numberOfElements;
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
* @param channelName Name of the Channel Access channel of this sensor
* @param numberOfElements Number of elements to read out of the waveform
*/
public ChannelAccessDoubleArraySensor(String id, String channelName, int numberOfElements){
try {
this.channel = ChannelBeanFactory.getFactory().createChannelBean(double[].class, channelName, false);
this.numberOfElements = numberOfElements;
this.id = id;
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#readout()
*/
@Override
public Object read() throws InterruptedException {
logger.finest("Read sensor "+channel.getName());
double[] v;
try {
v = channel.getValue(numberOfElements);
} catch (IllegalStateException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
throw e;
}
v = new double[numberOfElements];
for(int i =0;i<v.length;i++){
v[i] = Double.NaN;
}
} catch (CAException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
// Convert Exception into unchecked RuntimeException
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
}
v = new double[numberOfElements];
for(int i =0;i<v.length;i++){
v[i] = Double.NaN;
}
// } catch (InterruptedException e) {
// // Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// // return NaN (Not a Number)
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
// }
//
// v = new double[numberOfElements];
// for(int i =0;i<v.length;i++){
// v[i] = Double.NaN;
// }
}
return(v);
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy sensor channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,132 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.EngineConfiguration;
import ch.psi.fda.core.Sensor;
import ch.psi.jcae.ChannelBeanFactory;
import ch.psi.jcae.ChannelBean;
/**
* Scalar sensor that reads a double form a Channel Access channel
* @author ebner
*
*/
public class ChannelAccessDoubleSensor implements Sensor {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessDoubleSensor.class.getName());
/**
* Channel Access channel of this sensor
*/
private ChannelBean<Double> channel;
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
* @param channelName Name of the Channel Access channel of this sensor
*/
public ChannelAccessDoubleSensor(String id, String channelName){
try {
channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
this.id = id;
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#readout()
*/
@Override
public Object read() throws InterruptedException {
logger.finest("Read sensor "+channel.getName());
Double v;
try {
v = channel.getValue();
} catch (IllegalStateException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
throw e;
}
v = Double.NaN;
} catch (CAException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
// Convert Exception into unchecked RuntimeException
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
}
v = Double.NaN;
// } catch (InterruptedException e) {
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
// }
// v = Double.NaN;
}
return(v);
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy sensor channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
/**
* Get channel object of sensor
* @return
*/
public ChannelBean<Double> getChannel(){
return channel;
}
}

View File

@@ -1,124 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import ch.psi.fda.core.EngineConfiguration;
import ch.psi.fda.core.Sensor;
import ch.psi.jcae.ChannelBeanFactory;
import ch.psi.jcae.ChannelBean;
/**
* Scalar sensor that reads a double form a Channel Access channel
* @author ebner
*
*/
public class ChannelAccessStringSensor implements Sensor {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessStringSensor.class.getName());
/**
* Channel Access channel of this sensor
*/
private ChannelBean<String> channel;
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
* @param channelName Name of the Channel Access channel of this sensor
*/
public ChannelAccessStringSensor(String id, String channelName){
try {
channel = ChannelBeanFactory.getFactory().createChannelBean(String.class, channelName, false);
this.id = id;
} catch (CAException e) {
// Convert Exception into unchecked RuntimeException
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
} catch (InterruptedException e) {
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
}
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#readout()
*/
@Override
public Object read() throws InterruptedException {
logger.finest("Read sensor "+channel.getName());
String v;
try {
v = channel.getValue();
} catch (IllegalStateException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
throw e;
}
v = null;
} catch (CAException e) {
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
// return NaN (Not a Number)
if(EngineConfiguration.getInstance().isFailOnSensorError()){
// Convert Exception into unchecked RuntimeException
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
}
v = null;
// } catch (InterruptedException e) {
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
// }
// v = null;
}
return(v);
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Destroy channel
try {
logger.finest("Destroy sensor channel: "+channel.getName());
channel.destroy();
} catch (CAException e) {
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
}
}
}

View File

@@ -1,136 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import ch.psi.fda.core.Action;
import ch.psi.fda.core.Sensor;
/**
* Complex sensor that complements an other sensor with pre and post actions.
* Before reading out the complemented sensor the pre actions are executed. After the
* readout the post actions.
*
* @author ebner
*
*/
public class ComplexSensor implements Sensor {
// Get Logger
private static Logger logger = Logger.getLogger(ComplexSensor.class.getName());
/**
* Id of the sensor
*/
private String id;
/**
* Sensor to complement
*/
private final Sensor sensor;
/**
* Actions that are executed directly before the first step of this actor
*/
private final List<Action> preActions;
/**
* Actions that are executed directly after the last step of this actor
*/
private final List<Action> postActions;
/**
* Constructor
*/
public ComplexSensor(String id, Sensor sensor){
this.id = id;
this.sensor = sensor;
this.preActions = new ArrayList<Action>();
this.postActions = new ArrayList<Action>();
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#read()
*/
@Override
public Object read() throws InterruptedException {
// Execute pre actions
logger.finest("Execute pre actions");
for(Action action: preActions){
action.execute();
}
// Readout sensor
Object value = sensor.read();
// Execute post actions
logger.finest("Execute post actions");
for(Action action: postActions){
action.execute();
}
return value;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Destroy preActions
for(Action a: preActions){
a.destroy();
}
sensor.destroy();
// Destroy postActions
for(Action a: postActions){
a.destroy();
}
}
/**
* @return the preActions
*/
public List<Action> getPreActions() {
return preActions;
}
/**
* @return the postActions
*/
public List<Action> getPostActions() {
return postActions;
}
}

View File

@@ -1,84 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import ch.psi.fda.core.Sensor;
/**
* Sensor to read out a named (Epics) channel. This sensor can only be used within the
* OTFLoop. If it is used in other loops, the read value will always be 0.
* @author ebner
*
*/
public class OTFNamedChannelSensor implements Sensor {
/**
* Name of the channel
*/
private final String name;
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
* @param name Name of the (Epics) channel
*/
public OTFNamedChannelSensor(String id, String name){
this.id = id;
this.name = name;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#read()
*/
@Override
public Object read() {
// Always return 0 if read() method is called.
return 0d;
}
/**
* @return the name of the channel
*/
public String getName() {
return name;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Nothing to be done
}
}

View File

@@ -1,70 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import ch.psi.fda.core.Sensor;
/**
* Sensor to read actuator readback. This sensor must only be used within the
* OTFLoop. If it is used in other loops, the read value will always be 0.
* @author ebner
*
*/
public class OTFReadbackSensor implements Sensor {
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
*/
public OTFReadbackSensor(String id){
this.id = id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#read()
*/
@Override
public Object read() {
// Always return 0 if read() method is called.
return 0d;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Nothing to be done
}
}

View File

@@ -1,84 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import ch.psi.fda.core.Sensor;
/**
* Sensor to read out a scaler channel. This sensor can only be used within the
* OTFLoop. If it is used in other loops, the read value will always be 0.
* @author ebner
*
*/
public class OTFScalerChannelSensor implements Sensor {
/**
* Index of the scaler channel. The index starts at 0;
*/
private final int index;
/**
* Global id of the sensor
*/
private final String id;
/**
* Constructor
* @param id Global id of the sensor
* @param index Index of the scaler channel. Index starts at 0.
*/
public OTFScalerChannelSensor(String id, int index){
this.id = id;
this.index = index;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#read()
*/
@Override
public Object read() {
// Always return 0 if read() method is called.
return 0d;
}
/**
* @return the index of the scaler channel
*/
public int getIndex() {
return index;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see ch.psi.fda.core.Sensor#destroy()
*/
@Override
public void destroy() {
// Nothing to be done
}
}

View File

@@ -1,200 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.serializer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Logger;
import com.google.common.eventbus.Subscribe;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class DataSerializerTXT implements DataSerializer{
private static final Logger logger = Logger.getLogger(DataSerializerTXT.class.getName());
private File file;
private boolean appendSuffix = true;
private boolean first = true;
private File outfile;
private DataMessageMetadata meta;
private int icount;
private String basename;
private String extension;
private boolean newfile;
private boolean dataInBetween;
private BufferedWriter writer;
private StringBuffer b;
private StringBuffer b1;
/**
* @param metadata
* @param file
* @param appendSuffix Flag whether to append a _0000 suffix after the original file name
*/
public DataSerializerTXT(DataMessageMetadata meta, File file, boolean appendSuffix){
this.meta = meta;
this.file = file;
this.appendSuffix = appendSuffix;
}
@Subscribe
public void onMessage(Message message){
try{
if(first){
first=false;
// Write header
b = new StringBuffer();
b1 = new StringBuffer();
b.append("#");
b1.append("#");
for(ComponentMetadata c: meta.getComponents()){
b.append(c.getId());
b.append("\t");
b1.append(c.getDimension());
b1.append("\t");
}
b.setCharAt(b.length()-1, '\n');
b1.setCharAt(b1.length()-1, '\n');
icount = 0;
newfile = true;
dataInBetween = false;
writer = null;
// Get basename of the file
basename = this.file.getAbsolutePath(); // Determine file name
extension = basename.replaceAll("^.*\\.", ""); // Determine extension
basename = basename.replaceAll("\\."+extension+"$", "");
}
if(message instanceof DataMessage){
dataInBetween = true;
if(newfile){
// Open new file and write header
// Construct file name
if(appendSuffix){
outfile = new File(String.format("%s_%04d.%s", basename, icount, extension));
}
else{
outfile = new File(String.format("%s.%s", basename, extension));
}
// Open file
logger.fine("Open new data file: "+outfile.getAbsolutePath());
writer = new BufferedWriter(new FileWriter(outfile));
// Write header
writer.write(b.toString());
writer.write(b1.toString());
newfile=false;
}
// Write message to file - each message will result in one line
DataMessage m = (DataMessage) message;
StringBuffer buffer = new StringBuffer();
for(Object o: m.getData()){
if(o.getClass().isArray()){
// If the array object is of type double[] display its content
if(o instanceof double[]){
double[] oa = (double[]) o;
for(double o1 : oa){
buffer.append(o1);
buffer.append(" "); // Use space instead of tab
}
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
}
else if(o instanceof Object[]){
// TODO need to be recursive ...
Object[] oa = (Object[])o;
for(Object o1 : oa){
buffer.append(o1);
buffer.append(" "); // Use space instead of tab
}
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
}
else{
buffer.append("-"); // Not supported
}
}
else{
buffer.append(o);
buffer.append("\t");
}
}
if(buffer.length()>0){
buffer.deleteCharAt(buffer.length()-1); // Remove last character (i.e. \t)
buffer.append("\n"); // Append newline
}
writer.write(buffer.toString());
}
else if(message instanceof StreamDelimiterMessage){
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
logger.info("Delimiter - number: "+m.getNumber()+" iflag: "+m.isIflag());
if(m.isIflag() && appendSuffix){
// Only increase iflag counter if there was data in between
// subsequent StreamDelimiterMessages.
if(dataInBetween){
icount++;
}
dataInBetween = false;
// Set flag to open new file
newfile = true;
// Close file
writer.close();
}
}
else if (message instanceof EndOfStreamMessage){
if(writer!=null){
// Close file
writer.close(); //If the stream was closed previously this has no effect
}
}
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
}

View File

@@ -1,211 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.serializer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.google.common.eventbus.Subscribe;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
import ch.psi.fda.core.messages.Message;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class DataSerializerTXTSplit implements DataSerializer{
private DataMessageMetadata metadata;
private File file;
private int maxdim = 0;
private boolean first = true;
private List<String> header;
private List<String> data;
public DataSerializerTXTSplit(DataMessageMetadata metadata, File file){
this.metadata = metadata;
this.file = file;
// Determine maximum dimension
for(ComponentMetadata m: metadata.getComponents()){
if(m.getDimension()>maxdim){
maxdim=m.getDimension();
}
}
if(maxdim<1){
throw new RuntimeException("Split serializer only supports data > 1 dimension");
}
}
@Subscribe
public void onMessage(Message message) {
try{
if(first){
first=false;
header = new ArrayList<String>();
data = new ArrayList<String>();
// Write header
StringBuffer b = new StringBuffer();
StringBuffer b1 = new StringBuffer();
b.append("#");
b1.append("#");
for(ComponentMetadata c: metadata.getComponents()){
b.append(c.getId());
b.append("\t");
b1.append(c.getDimension());
b1.append("\t");
}
b.setCharAt(b.length()-1, '\n');
b1.setCharAt(b1.length()-1, '\n');
header.add(b.toString());
header.add(b1.toString());
}
// Write data
// Read Message
if(message instanceof DataMessage){
// Write message to file - each message will result in one line
DataMessage m = (DataMessage) message;
StringBuffer buffer = new StringBuffer();
for(Object o: m.getData()){
if(o.getClass().isArray()){
// If the array object is of type double[] display its content
if(o instanceof double[]){
double[] oa = (double[]) o;
for(double o1 : oa){
buffer.append(o1);
buffer.append(" "); // Use space instead of tab
}
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
}
else if(o instanceof Object[]){
// TODO need to be recursive ...
Object[] oa = (Object[])o;
for(Object o1 : oa){
buffer.append(o1);
buffer.append(" "); // Use space instead of tab
}
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
}
else{
buffer.append("-"); // Not supported
}
}
else{
buffer.append(o);
buffer.append("\t");
}
}
buffer.deleteCharAt(buffer.length()-1); // Remove last character (i.e. \t)
buffer.append("\n"); // Append newline
data.add(buffer.toString());
}
else if(message instanceof StreamDelimiterMessage){
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
if(m.getNumber()==maxdim-1){
writeData(header, data);
// Clear data
data.clear();
}
}
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
private void writeData(List<String> header, List<String> data) throws IOException{
// WORKAROUND BEGIN
File outfile;
// if(appendSuffix){
// Append a count suffix to the file. If there is already a file with
// this suffix increase the counter for the suffix
int cnt = 0;
String fname = this.file.getAbsolutePath(); // Determine file name
String extension = fname.replaceAll("^.*\\.", ""); // Determine extension
fname = fname.replaceAll("\\."+extension+"$", "");
outfile = new File(String.format("%s_%04d.%s", fname, cnt, extension));
while(outfile.exists()){
cnt++;
outfile = new File(String.format("%s_%04d.%s", fname, cnt, extension));
}
// }
// else{
// outfile = this.file;
// }
// WORKAROUND END
// Open file
BufferedWriter writer = new BufferedWriter(new FileWriter(outfile));
// Write header
for(String s: header){
writer.write(s);
}
// Write data
for(String s: data){
writer.write(s);
}
// Close file
writer.close();
}
/**
* Enable/disable the generation of the _0000 suffix in front of the extension of the out file
* @param appendSuffix the appendSuffix to set
*/
public void setAppendSuffix(boolean appendSuffix) {
// this.appendSuffix = appendSuffix;
}
}

View File

@@ -1,570 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.visualizer;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.google.common.eventbus.Subscribe;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.model.v1.ArrayDetector;
import ch.psi.fda.model.v1.ContinuousPositioner;
import ch.psi.fda.model.v1.Detector;
import ch.psi.fda.model.v1.LinearPositioner;
import ch.psi.fda.model.v1.Positioner;
import ch.psi.fda.model.v1.PseudoPositioner;
import ch.psi.fda.model.v1.Visualization;
import ch.psi.plot.Plot;
import ch.psi.plot.xy.LinePlot;
import ch.psi.plot.xy.XYSeriesCollectionP;
import ch.psi.plot.xy.XYSeriesP;
import ch.psi.plot.xyz.MatrixPlot;
import ch.psi.plot.xyz.MatrixPlotData;
/**
* Visualizer for visualizing data
* @author ebner
*
*/
public class Visualizer {
private static Logger logger = Logger.getLogger(Visualizer.class.getName());
private List<Plot> plots = new ArrayList<Plot>();
private boolean updateAtStreamElement = true;
private boolean updateAtStreamDelimiter = true;
private boolean updateAtEndOfStream = false;
private int ecount;
private boolean clearPlot;
private List<SeriesDataFilter> filters;
public Visualizer(DataMessageMetadata meta, List<Visualization> vl){
filters = mapVisualizations(meta, vl);
}
@Subscribe
public void onDataMessage(final DataMessage message){
// Clear is here as the plot should not be cleared after the last point is plotted
// but just before the first point of the next plot (cycle)
if (clearPlot) {
for (Plot plot: plots) {
if(plot instanceof MatrixPlot){
((MatrixPlotData) ((MatrixPlot)plot).getData()).clear();
}
}
clearPlot = false;
}
for(SeriesDataFilter filter: filters){
if(filter instanceof XYSeriesDataFilter){
XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter;
if(xyfilter.getActualSeries()==null || xyfilter.isNewseries()){
// First series that is filled by this filter!
XYSeriesP s = new XYSeriesP(xyfilter.getSeriesName() + " " + ecount + "-" + xyfilter.getCount());
((LinePlot)xyfilter.getPlot()).getData().addSeries(s);
xyfilter.setActualSeries(s);
xyfilter.setNewseries(false);
}
XYSeriesP series = xyfilter.getActualSeries(); // TODO Does not work with multiple series filter per plot !!!!
// There might be other values than double in the data, therefore we have to check for it
Object dX = message.getData().get(xyfilter.getIndexX());
Object dY = message.getData().get(xyfilter.getIndexY());
Double dataX = Double.NaN;
Double dataY = Double.NaN;
if(dX instanceof Double){
dataX = (Double) dX;
}
if(dY instanceof Double){
dataY = (Double) dY;
}
// Add Data to the series
series.add(dataX , dataY, updateAtStreamElement);
}
if(filter instanceof XYSeriesArrayDataFilter){
final XYSeriesArrayDataFilter xyfilter = (XYSeriesArrayDataFilter) filter;
// Ensure that there is no concurrent modification exception or synchronization problems with the
// Swing update task
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
XYSeriesP series = new XYSeriesP(xyfilter.getSeriesName() + "-" + xyfilter.getCount()); // Series name must be unique
xyfilter.incrementCount();
// ((LinePlot)xyfilter.getPlot()).getData().removeAllSeries(); // Remove all series from the data
// If we can agree only to display one series at a time also a clear() on the actual series is better
XYSeriesCollectionP sc = ((LinePlot)xyfilter.getPlot()).getData();
sc.addSeries(series);
// Remove outdated series
if(sc.getSeriesCount()>xyfilter.getMaxSeries()){
// Remove oldest series
sc.removeSeries(0);
}
double[] data = (double[]) message.getData().get(xyfilter.getIndexY());
// Copy data starting from offset to size
int size = data.length;
int offset = xyfilter.getOffset();
if(xyfilter.getSize()>0 && offset+xyfilter.getSize()<data.length){
size = offset + xyfilter.getSize();
}
for(int i=offset;i<size;i++){
series.add(i,data[i], false); // Do not fire change event - this would degrade performance drastically
}
series.fireSeriesChanged();
}
});
}
else if(filter instanceof XYZSeriesDataFilter){
XYZSeriesDataFilter xyzfilter = (XYZSeriesDataFilter) filter;
try{
((MatrixPlot)xyzfilter.getPlot()).getData().addData((Double) message.getData().get(xyzfilter.getIndexX()),(Double) message.getData().get(xyzfilter.getIndexY()), (Double) message.getData().get(xyzfilter.getIndexZ()));
}
catch (Exception e) {
// Ignore if something goes wrong while adding a datapoint
logger.log(Level.WARNING, "Unable to plot datapoint in matrix plot", e);
}
}
else if(filter instanceof XYZSeriesArrayDataFilter){
XYZSeriesArrayDataFilter xyzfilter = (XYZSeriesArrayDataFilter) filter;
try{
double[] data = (double[]) message.getData().get(xyzfilter.getIndexZ());
double y = (Double) message.getData().get(xyzfilter.getIndexY());
int offset = xyzfilter.getOffset();
int size = xyzfilter.getSize();
for(int i=offset;i<offset+size; i++){
((MatrixPlot)xyzfilter.getPlot()).getData().addData(i, y, data[i]);
}
// Update data if update by point is enabled
if(updateAtStreamElement){
xyzfilter.getPlot().update();
}
}
catch (Exception e) {
// Ignore if something goes wrong while adding a datapoint
logger.log(Level.WARNING, "Unable to plot datapoint in matrix plot", e);
}
}
}
}
@Subscribe
public void onStreamDelimiterMessage(StreamDelimiterMessage message){
for(SeriesDataFilter filter: filters){
if(filter instanceof XYSeriesDataFilter){
// Create new series
XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter;
if (message.getNumber() == xyfilter.getDimensionX()) {
// Indicate to create new series at the next message
xyfilter.setCount(xyfilter.getCount()+1); // Increment count of the filter
xyfilter.setNewseries(true);
}
}
}
// Update matrix plot at the end of each line
if(updateAtStreamDelimiter){
for (Plot plot: plots) {
if(plot instanceof MatrixPlot){
((MatrixPlot)plot).update();
}
else if(plot instanceof LinePlot){
((LinePlot) plot).update();
}
}
}
// Clear matrix plot if iflag is encountered
// TODO: One need to check whether the iflag belongs to a delimiter
// of a higher dimension than the highest dimension (axis) that
// is involved in the plot
if (message.isIflag()) {
clearPlot = true;
}
}
@Subscribe
public void onEndOfStreamMessage(EndOfStreamMessage message){
ecount++;
// Update plots if updateAtEndOfStream flag is set
if(updateAtEndOfStream){
// Update matrix plots
for (Plot plot: plots) {
if(plot instanceof MatrixPlot){
((MatrixPlot)plot).update();
((MatrixPlot)plot).adaptColorMapScale(); // Update color scale at the end
}
else if(plot instanceof LinePlot){
((LinePlot) plot).update();
}
}
}
}
public void configure(){
ecount = 0;
clearPlot = false;
}
/**
* Retrieve id string of the passed object
* @param object
* @return Id string of object
*/
private String getId(Object object){
String id;
if(object instanceof Positioner){
id = ((Positioner)object).getId();
}
else if (object instanceof Detector){
id = ((Detector)object).getId();
}
else if (object instanceof ch.psi.fda.model.v1.Manipulation){
id = ((ch.psi.fda.model.v1.Manipulation)object).getId();
}
// For testing purposes
else if(object instanceof String){
id = (String) object;
}
else{
throw new RuntimeException("Unable to identify id of object reference "+object);
}
return id;
}
/**
* Get configured visualizations
* Note: This method is public because it is also used by the VisualizationEngine
* @param vl List of configured visualizations
* @return List of visualization configuration
*/
private List<SeriesDataFilter> mapVisualizations(DataMessageMetadata meta, List<Visualization> vl){
List<SeriesDataFilter> filters = new ArrayList<SeriesDataFilter>();
for(Visualization v: vl){
if(v instanceof ch.psi.fda.model.v1.LinePlot){
ch.psi.fda.model.v1.LinePlot lp = (ch.psi.fda.model.v1.LinePlot) v;
// Create plot for visualization
ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle());
plots.add(plot);
// Create data filter for visualization
String idX = getId(lp.getX());
int indexX = meta.getIndex(idX);
int dimX = meta.getComponents().get(indexX).getDimension();
List<Object> l = lp.getY();
for(Object o: l){
String idY = getId(o);
int indexY = meta.getIndex(idY);
int dimY = meta.getComponents().get(indexY).getDimension();
XYSeriesDataFilter filter = new XYSeriesDataFilter(idX, idY, indexX, indexY, plot);
filter.setDimensionX(dimX);
filter.setDimensionY(dimY);
filter.setSeriesName(idY);
filters.add(filter);
}
}
else if(v instanceof ch.psi.fda.model.v1.LinePlotArray){
// Array visualization
ch.psi.fda.model.v1.LinePlotArray lp = (ch.psi.fda.model.v1.LinePlotArray) v;
// Create plot for visualization
ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle());
plots.add(plot);
// Create data filter for visualization
List<Object> l = lp.getY();
for(Object o: l){
String idY = getId(o);
int indexY = meta.getIndex(idY);
int dimY = meta.getComponents().get(indexY).getDimension();
XYSeriesArrayDataFilter filter = new XYSeriesArrayDataFilter(idY, indexY, plot);
filter.setDimensionY(dimY);
filter.setMaxSeries(lp.getMaxSeries()*lp.getY().size()); // Workaround - keep for each array max series
filter.setOffset(lp.getOffset());
filter.setSize(lp.getSize());
filter.setSeriesName(idY);
filters.add(filter);
}
}
else if(v instanceof ch.psi.fda.model.v1.MatrixPlot){
// MatrixPlot does currently not support RegionPositioners because of the
// plotting problems this would cause. If regions of the positioner have different
// step sizes it is not easily possible (without (specialized) rasterization) to plot the data.
ch.psi.fda.model.v1.MatrixPlot mp = (ch.psi.fda.model.v1.MatrixPlot) v;
double minX, maxX;
int nX;
double minY, maxY;
int nY;
String idX, idY, idZ;
// X Axis
if(mp.getX() instanceof LinearPositioner){
LinearPositioner linp = ((LinearPositioner)mp.getX());
idX = linp.getId();
minX = (Math.min(linp.getStart(), linp.getEnd()));
maxX = (Math.max(linp.getStart(), linp.getEnd()));
nX = ((int) Math.floor((Math.abs(maxX-minX))/linp.getStepSize()) + 1);
}
else if(mp.getX() instanceof PseudoPositioner){
PseudoPositioner pp = ((PseudoPositioner)mp.getX());
idX = pp.getId();
minX = (1); // Count starts at 1
maxX = (pp.getCounts());
nX = (pp.getCounts());
}
else if(mp.getX() instanceof ContinuousPositioner){
ContinuousPositioner conp = ((ContinuousPositioner)mp.getX());
idX = conp.getId();
minX = (Math.min(conp.getStart(), conp.getEnd()));
maxX = (Math.max(conp.getStart(), conp.getEnd()));
nX = ((int) Math.floor((Math.abs(maxX-minX))/conp.getStepSize()) + 1);
}
else{
// Fail as we cannot determine the min, max and number of steps
throw new RuntimeException(mp.getX().getClass().getName()+" is not supported as x-axis of a MatrixPlot");
}
// Y Axis
if(mp.getY() instanceof LinearPositioner){
LinearPositioner linp = ((LinearPositioner)mp.getY());
idY = linp.getId();
minY = (Math.min(linp.getStart(), linp.getEnd()));
maxY = (Math.max(linp.getStart(), linp.getEnd()));
nY = ((int) Math.floor((Math.abs(maxY-minY))/linp.getStepSize()) + 1);
}
else if(mp.getY() instanceof PseudoPositioner){
PseudoPositioner pp = ((PseudoPositioner)mp.getY());
idY = pp.getId();
minY = (1); // Count starts at 1
maxY = (pp.getCounts());
nY = (pp.getCounts());
}
else{
// Fail as we cannot determine the min, max and number of steps
throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as y-axis of a MatrixPlot");
}
// Z Dimension
idZ = getId(mp.getZ());
// Create plot for visualization
MatrixPlotData data = new MatrixPlotData(minX, maxX, nX, minY, maxY, nY);
MatrixPlot plot = new MatrixPlot(mp.getTitle(), data);
plots.add(plot);
// Create data filter for visualization
int indexX = meta.getIndex(idX);
int indexY = meta.getIndex(idY);
int indexZ = meta.getIndex(idZ);
int dimX = meta.getComponents().get(indexX).getDimension();
int dimY = meta.getComponents().get(indexY).getDimension();
int dimZ = meta.getComponents().get(indexZ).getDimension();
XYZSeriesDataFilter filter = new XYZSeriesDataFilter(idX, idY, idZ, indexX, indexY, indexZ, plot);
filter.setDimensionX(dimX);
filter.setDimensionY(dimY);
filter.setDimensionZ(dimZ);
filters.add(filter);
}
else if(v instanceof ch.psi.fda.model.v1.MatrixPlotArray){
// Support for 2D waveform plots
ch.psi.fda.model.v1.MatrixPlotArray mp = (ch.psi.fda.model.v1.MatrixPlotArray) v;
// Get size of the array detector
int arraySize = 0;
Object o = mp.getZ();
if(o instanceof ArrayDetector){
ArrayDetector ad = (ArrayDetector) o;
arraySize = ad.getArraySize();
}
else{
// Workaround
arraySize = mp.getSize(); // of array is from a manipulation the size is not known. Then the size will indicate the size of the array to display
}
int offset = mp.getOffset();
// Determine size for array
int size = mp.getSize();
if(size>0 && offset+size<arraySize){
size = mp.getSize();
}
else{
size=arraySize-offset;
}
double minY, maxY;
int nY;
double minX = offset;
double maxX = offset+size-1;
int nX = size;
String idY, idZ;
// Y Axis
if(mp.getY() instanceof LinearPositioner){
LinearPositioner linp = ((LinearPositioner)mp.getY());
idY = linp.getId();
minY = (Math.min(linp.getStart(), linp.getEnd()));
maxY = (Math.max(linp.getStart(), linp.getEnd()));
nY = ((int) Math.floor((Math.abs(maxY-minY))/linp.getStepSize()) + 1);
}
else if(mp.getY() instanceof PseudoPositioner){
PseudoPositioner pp = ((PseudoPositioner)mp.getY());
idY = pp.getId();
minY = (1); // Count starts at 1
maxY = (pp.getCounts());
nY = (pp.getCounts());
}
else if(mp.getY() instanceof ContinuousPositioner){
ContinuousPositioner conp = ((ContinuousPositioner)mp.getY());
idY = conp.getId();
minY = (Math.min(conp.getStart(), conp.getEnd()));
maxY = (Math.max(conp.getStart(), conp.getEnd()));
nY = ((int) Math.floor((Math.abs(maxY-minY))/conp.getStepSize()) + 1);
}
else{
// Fail as we cannot determine the min, max and number of steps
throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as x-axis of a MatrixPlot");
}
// Z Dimension
idZ = getId(mp.getZ());
// Create plot for visualization
MatrixPlotData data = new MatrixPlotData(minX, maxX, nX, minY, maxY, nY);
MatrixPlot plot = new MatrixPlot(mp.getTitle(), data);
plots.add(plot);
// Create data filter for visualization
int indexY = meta.getIndex(idY);
int indexZ = meta.getIndex(idZ);
int dimY = meta.getComponents().get(indexY).getDimension();
int dimZ = meta.getComponents().get(indexZ).getDimension();
XYZSeriesArrayDataFilter filter = new XYZSeriesArrayDataFilter(idY, idZ, indexY, indexZ, offset, size, plot);
filter.setDimensionY(dimY);
filter.setDimensionZ(dimZ);
filters.add(filter);
}
else{
// Visualization type (currently) not supported
throw new RuntimeException(v.getClass().getName()+" is not supported as visualization type");
}
}
return filters;
}
/**
* Get the plot panels for the visualizations
* @return List of configured JPanels
*/
public List<JPanel> getPlotPanels(){
List<JPanel> panels = new ArrayList<JPanel>();
for(Plot plot: plots){
panels.add(plot.getChartPanel());
}
return panels;
}
/**
* @return the updateAtStreamElement
*/
public boolean isUpdateAtStreamElement() {
return updateAtStreamElement;
}
/**
* @param updateAtStreamElement the updateAtStreamElement to set
*/
public void setUpdateAtStreamElement(boolean updateAtStreamElement) {
this.updateAtStreamElement = updateAtStreamElement;
}
/**
* @return the updateAtStreamDelimiter
*/
public boolean isUpdateAtStreamDelimiter() {
return updateAtStreamDelimiter;
}
/**
* @param updateAtStreamDelimiter the updateAtStreamDelimiter to set
*/
public void setUpdateAtStreamDelimiter(boolean updateAtStreamDelimiter) {
this.updateAtStreamDelimiter = updateAtStreamDelimiter;
}
/**
* @return the updateAtEndOfStream
*/
public boolean isUpdateAtEndOfStream() {
return updateAtEndOfStream;
}
/**
* @param updateAtEndOfStream the updateAtEndOfStream to set
*/
public void setUpdateAtEndOfStream(boolean updateAtEndOfStream) {
this.updateAtEndOfStream = updateAtEndOfStream;
}
}

View File

@@ -1,187 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.visualizer;
import ch.psi.plot.Plot;
import ch.psi.plot.xy.XYSeriesP;
/**
* Metadata of a group of XYSeries.
* This metadata holds the information needed by the DataVisualizer
* to plot series.
*
* @author ebner
*
*/
public class XYSeriesDataFilter implements SeriesDataFilter{
private final String idX;
private final String idY;
// Name of the series generated by this filter
private String seriesName = "";
// Index of stream message components used for x and y
private final int indexX;
private final int indexY;
// Dimension of the x,y value - used to determine whether a new series should be created for this filter
private int dimensionX;
private int dimensionY;
// Number of series generated for this filter
private int count = 0;
// Plot the data of this filter goes to
private final Plot plot;
// TODO WORKAROUND - XYZ filter must not have this property !!!!
private XYSeriesP actualSeries = null;
private boolean newseries = false;
public XYSeriesDataFilter(String idX, String idY, int indexX, int indexY, Plot plot){
this.idX = idX;
this.idY = idY;
this.indexX = indexX;
this.indexY = indexY;
this.plot = plot;
}
/**
* @return the xId
*/
public String getIdX() {
return idX;
}
/**
* @return the yId
*/
public String getIdY() {
return idY;
}
/**
* @return the seriesName
*/
public String getSeriesName() {
return seriesName;
}
/**
* @param seriesName the seriesName to set
*/
public void setSeriesName(String seriesName) {
this.seriesName = seriesName;
}
/**
* @return the indexX
*/
public int getIndexX() {
return indexX;
}
/**
* @return the indexY
*/
public int getIndexY() {
return indexY;
}
/**
* @return the dimensionX
*/
public int getDimensionX() {
return dimensionX;
}
/**
* @return the dimensionY
*/
public int getDimensionY() {
return dimensionY;
}
/**
* @param dimensionY the dimensionY to set
*/
public void setDimensionY(int dimensionY) {
this.dimensionY = dimensionY;
}
/**
* @param dimensionX the dimensionX to set
*/
public void setDimensionX(int dimensionX) {
this.dimensionX = dimensionX;
}
/**
* @return the count
*/
public int getCount() {
return count;
}
/**
* @param count the count to set
*/
public void setCount(int count) {
this.count = count;
}
/**
* @return the plot
*/
public Plot getPlot() {
return plot;
}
/**
* @return the actualSeries
*/
public XYSeriesP getActualSeries() {
return actualSeries;
}
/**
* @param actualSeries the actualSeries to set
*/
public void setActualSeries(XYSeriesP actualSeries) {
this.actualSeries = actualSeries;
}
/**
* @return the newseries
*/
public boolean isNewseries() {
return newseries;
}
/**
* @param newseries the newseries to set
*/
public void setNewseries(boolean newseries) {
this.newseries = newseries;
}
}

View File

@@ -1,21 +0,0 @@
#!/bin/bash
BASEDIR=$(cd $(dirname $0);pwd)
EPICS_DISPLAY_PATH=/work/sls/config/medm:$EPICS_DISPLAY_PATH
export EPICS_DISPLAY_PATH
# OTFSCAN MEDM
medm -x -macro "P=MTEST-HW3-OTFX" G_OTFSCAN_user.adl &
# Motor MEDM
medm -x -macro "P=MTEST-HW3:, M=MOT1" motorx_more.adl &
#medm -x -macro "ENC=MTEST-HW3:EC1" G_ECM_514A_encoder.adl &
medm -x -macro "P=MTEST-HW3:, M=MOT2" motorx_more.adl &
#medm -x -macro "ENC=MTEST-HW3:EC2" G_ECM_514A_encoder.adl &
medm -x -macro "P=MTEST-PC-MOTOR:, M=MOT1" motorx_more.adl &
# Scaler MEDM
medm -x -macro "P=MTEST-HW3:, S=JS" scaler16.adl &

View File

@@ -1,2 +0,0 @@
# Load test template
dbLoadTemplate("MTEST-PC-FDA_test.subs")

View File

@@ -1,5 +0,0 @@
file test.template {
{
P = MTEST-PC-FDA:
}
}

View File

@@ -1,17 +0,0 @@
MODULE = MTEST-PC-FDA
export MODULE
build:
clean:
install: build
swit -V -ioc MTEST-PC-FDA
help:
@echo "The following targets are available with this Makefile:-"
@echo "make (calls default target)"
@echo "make build (default)"
@echo "make install"
@echo "make clean"
@echo "make help"

View File

@@ -1,42 +0,0 @@
# Binary Output
record(bo, "$(P)BO") {
field(DESC, "Binary Output")
}
# Binary Output
record(bo, "$(P)BO2") {
field(DESC, "Binary Output 2")
field(VAL, "0")
}
# Analog Output
record(ao, "$(P)AO") {
field(PREC, "6")
field(DESC, "Analog Output")
}
# String Output
record(stringout, "$(P)SOUT") {
}
# Double Waveform (100 Elements)
record(waveform, "$(P)DWAVE") {
field(DESC, "Double Waveform")
field(PREC, "6")
field(NELM, "100")
field(FTVL, "DOUBLE")
}
# Integer Waveform (100 Elements)
record(waveform, "$(P)LWAVE") {
field(DESC, "Long Waveform")
field(NELM, "100")
field(FTVL, "LONG")
}
# Character Waveform (100 Elements)
record(waveform, "$(P)CWAVE") {
field(DESC, "Character Waveform")
field(NELM, "100")
field(FTVL, "CHAR")
}

View File

@@ -1,209 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.aq;
import static org.junit.Assert.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import ch.psi.fda.aq.Collector;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.ControlMessage;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
public class CollectorTest {
private static Logger logger = Logger.getLogger(CollectorTest.class.getName());
private EventBus bus;
private BlockingQueue<Message> q1;
private BlockingQueue<Message> q2;
private BlockingQueue<Message> q3;
private DataMessageMetadata m1;
private DataMessageMetadata m2;
private DataMessageMetadata m3;
@Before
public void setUp() throws Exception {
bus = new EventBus();
// Create blocking queues
q1 = new LinkedBlockingQueue<Message>();
q2 = new LinkedBlockingQueue<Message>();
q3 = new LinkedBlockingQueue<Message>();
m1 = new DataMessageMetadata();
m1.getComponents().add(new ComponentMetadata("id2-0"));
m2 = new DataMessageMetadata();
m2.getComponents().add(new ComponentMetadata("id1-0"));
m3 = new DataMessageMetadata();
m3.getComponents().add(new ComponentMetadata("id0-0"));
// Dimension y 1,2,3
DataMessage m = new DataMessage();
m.getData().add(1d);
q1.put(m);
m = new DataMessage();
m.getData().add(2d);
q1.put(m);
m = new DataMessage();
m.getData().add(3d);
q1.put(m);
q1.put(new EndOfStreamMessage());
// Dimension x 0.1,0.2
m = new DataMessage();
m.getData().add(0.1);
q2.put(m);
m = new DataMessage();
m.getData().add(0.2);
q2.put(m);
q2.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.1);
q2.put(m);
m = new DataMessage();
m.getData().add(0.2);
q2.put(m);
q2.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.1);
q2.put(m);
m = new DataMessage();
m.getData().add(0.2);
q2.put(m);
q2.put(new EndOfStreamMessage());
// Dimension
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
m = new DataMessage();
m.getData().add(0.01);
q3.put(m);
m = new DataMessage();
m.getData().add(0.02);
q3.put(m);
q3.put(new EndOfStreamMessage());
}
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.aq.Collector#run()}.
* @throws InterruptedException
*/
@Test
public void testRun() throws InterruptedException {
Collector collector = new Collector(bus);
collector.getQueues().add(new DataQueue(q1, m1));
collector.getQueues().add(new DataQueue(q2, m2));
collector.getQueues().add(new DataQueue(q3, m3));
// Check component metadata of output queue
int c=2;
for(ComponentMetadata cm: collector.getMetadata().getComponents()){
logger.info(cm.toString());
if(cm.getDimension() != c){
fail("Dimension number does not match required dimension number");
}
if(! cm.getId().equals("id"+c+"-0")){
fail("Id does not match required id");
}
c--;
}
// check wether messages arrive
bus.register(new Object(){
@Subscribe
public void onMessage(Message m){
if(m instanceof DataMessage){
DataMessage x = (DataMessage) m;
logger.info( x.toString() );
}
else if(m instanceof ControlMessage){
logger.info("---- "+m.toString()+" ----");
}
}
});
collector.run();
}
}

View File

@@ -1,103 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.actions;
import gov.aps.jca.CAException;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.core.actions.JythonAction;
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
/**
* @author ebner
*
*/
public class JythonActionTest {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
* @throws CAException
*/
@Test
public void testExecute() throws CAException {
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
mapping.add(new JythonParameterMappingChannel("o", TestChannels.ANALOG_OUT, Double.class));
JythonAction action = new JythonAction(script, mapping);
// Execute action
action.execute();
}
/**
* Check whether too much mappings are detected
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
* @throws CAException
*/
@Test(expected=IllegalArgumentException.class)
public void testWrongMapping1() throws CAException {
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
mapping.add(new JythonParameterMappingChannel("o", TestChannels.ANALOG_OUT, Double.class));
mapping.add(new JythonParameterMappingChannel("b", TestChannels.ANALOG_OUT, Double.class));
JythonAction action = new JythonAction(script, mapping);
// Execute action
action.execute();
}
/**
* Check whether a mapping to a wrong variable is detected
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
* @throws CAException
*/
@Test(expected=IllegalArgumentException.class)
public void testWrongMapping2() throws CAException {
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
mapping.add(new JythonParameterMappingChannel("ooo", TestChannels.ANALOG_OUT, Double.class));
JythonAction action = new JythonAction(script, mapping);
// Execute action
action.execute();
}
}

View File

@@ -1,145 +0,0 @@
/**
*
* Copyright 2012 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestConfiguration;
/**
* @author ebner
*
*/
public class DistributedFileTest {
private static final Logger logger = Logger.getLogger(DistributedFileTest.class.getName());
DistributedFile file;
DistributedFile smbfile;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
file = new DistributedFile("src/test/resources");
smbfile = new DistributedFile(TestConfiguration.getInstance().getSmbShare());
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getCanonicalPath()}.
* @throws IOException
*/
@Test
public void testGetCanonicalPath() throws IOException {
logger.info(file.getCanonicalPath());
logger.info(smbfile.getCanonicalPath());
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#exists()}.
* @throws IOException
*/
@Test
public void testExists() throws IOException {
if(!file.exists()){
fail("Indicating wrong file status (file actually exists)");
}
if(!smbfile.exists()){
fail("Indicating wrong file status (file actually exists)");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#isDirectory()}.
* @throws IOException
*/
@Test
public void testIsDirectory() throws IOException {
if(!file.isDirectory()){
fail("Indicating wrong file type (file is directory)");
}
if(!smbfile.isDirectory()){
fail("Indicating wrong file type (file is directory)");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#listFiles()}.
*/
@Test
public void testListFiles() {
// fail("Not yet implemented");
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getName()}.
*/
@Test
public void testGetName() {
logger.info(file.getName());
logger.info(smbfile.getName());
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#isFile()}.
* @throws IOException
*/
@Test
public void testIsFile() throws IOException {
if(file.isFile()){
fail("Indicating wrong file type (file is directory)");
}
if(smbfile.isFile()){
fail("Indicating wrong file type (file is directory)");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#delete()}.
*/
@Test
public void testDelete() {
// fail("Not yet implemented");
}
/**
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getInputStream()}.
*/
@Test
public void testGetInputStream() {
// fail("Not yet implemented");
}
}

View File

@@ -1,242 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops;
import static org.junit.Assert.*;
import gov.aps.jca.CAException;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestConfiguration;
import ch.psi.fda.core.actors.OTFActuator;
import ch.psi.fda.core.loops.OTFLoop;
import ch.psi.fda.core.messages.ControlMessage;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
import ch.psi.fda.core.sensors.OTFReadbackSensor;
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* @author ebner
*
*/
public class OTFLoopTest {
// Get Logger
private static Logger logger = Logger.getLogger(OTFLoopTest.class.getName());
class TestCollector implements Runnable{
private final BlockingQueue<Message> queue;
public TestCollector(BlockingQueue<Message> queue){
this.queue = queue;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
while(true){
Message m = queue.take();
if(m instanceof DataMessage){
DataMessage x = (DataMessage) m;
logger.fine( x.toString() );
}
else if(m instanceof ControlMessage){
logger.fine("---- "+m.toString()+" ----");
}
}
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "An Exception occured while reading data from the data queue", e);
}
}
}
private static final TestConfiguration configuration = TestConfiguration.getInstance();
private OTFLoop loopZigZag;
private OTFLoop loop;
private ChannelBean<Integer> statusChannel;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
statusChannel = ChannelBeanFactory.getFactory().createChannelBean(Integer.class, configuration.getOtfPrefix()+":USTAT", false);
OTFActuator actor = new OTFActuator("id", configuration.getMotor1(), null, 0, 8, 0.5, 0.5, 0);
OTFReadbackSensor s1 = new OTFReadbackSensor("id0");
OTFScalerChannelSensor s2 = new OTFScalerChannelSensor("id1", 0);
OTFScalerChannelSensor s3 = new OTFScalerChannelSensor("id2", 1);
MillisecondTimestampSensor s4 = new MillisecondTimestampSensor("id3");
OTFNamedChannelSensor s5 = new OTFNamedChannelSensor("id4", configuration.getAnalogIn1());
// ZigZag loop
loopZigZag = new OTFLoop(configuration.getOtfPrefix(), configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), true);
loopZigZag.setActor(actor);
loopZigZag.getSensors().add(s1);
loopZigZag.getSensors().add(s2);
loopZigZag.getSensors().add(s3);
loopZigZag.getSensors().add(s4);
loopZigZag.getSensors().add(s5);
// Normal loop
loop = new OTFLoop(configuration.getOtfPrefix(), configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), false);
loop.setActor(actor);
loop.getSensors().add(s1);
loop.getSensors().add(s2);
loop.getSensors().add(s3);
loop.getSensors().add(s4);
loop.getSensors().add(s5);
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
* Test ordinary 1D OTF scan
* @throws CAException
*/
@Test
public void testExecute() throws CAException, InterruptedException {
Thread t = new Thread(new TestCollector(loop.getDataQueue().getQueue()));
t.start();
loop.prepare();
loop.execute();
loop.cleanup();
if(statusChannel.getValue()!=1){
fail("OTF C Logic status is not on INACTIVE");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
* Test OTF ZigZag mode
* @throws CAException
*/
@Test
public void testExecuteZigZag() throws CAException, InterruptedException {
Thread t = new Thread(new TestCollector(loopZigZag.getDataQueue().getQueue()));
t.start();
loopZigZag.prepare();
loopZigZag.execute();
loopZigZag.execute();
loopZigZag.cleanup();
if(statusChannel.getValue()!=1){
fail("OTF C Logic status is not on INACTIVE");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
* Test abort functionality while executing an OTF scan
* @throws CAException
*/
@Test
public void testExecuteAbort() throws CAException, InterruptedException {
// Data collector thread
Thread t = new Thread(new TestCollector(loop.getDataQueue().getQueue()));
t.start();
// Thread to simulate asynchronous abort operation
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(6000); // Wait some seconds before aborting the loop
loop.abort();
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "An Exception occured while testing the abort functionality", e);
}
}
});
t1.start();
loop.prepare();
loop.execute();
loop.cleanup();
if(statusChannel.getValue()!=1){
fail("OTF C Logic status is not on INACTIVE");
}
}
/**
* Test method for {@link ch.psi.fda.core.loops.ActorSensorLoop#getDataMessageMetadata()}.
*/
@Test
public void testGetDataMessageMetadata(){
DataMessageMetadata m = loop.getDataQueue().getDataMessageMetadata();
int numberOfSensors = 5;
if(m.getComponents().size() != numberOfSensors){
fail("Loop returned wrong number of components inside the data message metadata");
}
boolean fail = false;
for(int x=0;x<numberOfSensors; x++){
if(! m.getComponents().get(x).getId().equals("id"+x)){
fail = true;
}
}
if(fail){
fail("Ids of the component metadata elements inside the data message metadata is not correct");
}
}
}

View File

@@ -1,136 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* @author ebner
*
*/
public class ParallelCrlogicStreamMergeTest {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.loops.cr.ParallelCrlogicStreamMerge#merge()}.
* @throws InterruptedException
*/
@Test
public void testMerge() throws InterruptedException {
BlockingQueue<Message> dataQueue = new LinkedBlockingQueue<Message>();
DataMessage dm = new DataMessage();
dm.getData().add(0.0035d);
dm.getData().add(10.000000123);
dataQueue.add(dm);
dm = new DataMessage();
dm.getData().add(0.015);
dm.getData().add(10.000000143);
dataQueue.add(dm);
dm = new DataMessage();
dm.getData().add(0.026);
dm.getData().add(10.000000163);
dataQueue.add(dm);
dataQueue.add(new EndOfStreamMessage());
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("cractuator"));
dmm.getComponents().add(new ComponentMetadata("tstamp"));
DataQueue dqueue = new DataQueue(dataQueue, dmm);
BlockingQueue<Message> dataQueue2 = new LinkedBlockingQueue<Message>();
DataMessage dm2 = new DataMessage();
dm2.getData().add(9000d);
dm2.getData().add(122d);
dm2.getData().add(0.1d);
dataQueue2.add(dm2);
dm2 = new DataMessage();
dm2.getData().add(10000d);
dm2.getData().add(122d);
dm2.getData().add(1d);
dataQueue2.add(dm2);
dm2 = new DataMessage();
dm2.getData().add(10000d);
dm2.getData().add(153d);
dm2.getData().add(2d);
dataQueue2.add(dm2);
dm2 = new DataMessage();
dm2.getData().add(10000d);
dm2.getData().add(162d);
dm2.getData().add(3d);
dataQueue2.add(dm2);
dataQueue2.add(new EndOfStreamMessage());
DataMessageMetadata dmm2 = new DataMessageMetadata();
dmm2.getComponents().add(new ComponentMetadata("milli"));
dmm2.getComponents().add(new ComponentMetadata("nano"));
dmm2.getComponents().add(new ComponentMetadata("sensor1"));
DataQueue dqueue2 = new DataQueue(dataQueue2, dmm2);
ParallelCrlogicStreamMerge streamMerge = new ParallelCrlogicStreamMerge(dqueue, dqueue2);
streamMerge.merge();
// Print merged queue
BlockingQueue<Message> queue = streamMerge.getDataQueue().getQueue();
Message m = queue.take();
while(! (m instanceof EndOfStreamMessage)){
System.out.println(m.toString());
m = queue.take();
}
}
}

View File

@@ -1,152 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.loops.cr;
import gov.aps.jca.CAException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestConfiguration;
import ch.psi.fda.core.Sensor;
import ch.psi.fda.core.actors.OTFActuator;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
import ch.psi.jcae.ChannelBeanFactory;
/**
* @author ebner
*
*/
public class ParallelCrlogicTest {
// Get Logger
private static final Logger logger = Logger.getLogger(ParallelCrlogicTest.class.getName());
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
// @Ignore
@Test(timeout=60000)
public void testExecute() throws InterruptedException, CAException{
TestConfiguration c = TestConfiguration.getInstance();
boolean zigZag = false;
String readback = null;
double start = 0;
double end = 2;
double stepSize = 0.01;
double integrationTime = 0.01;
double additionalBacklash = 0;
List<Sensor> sensors = new ArrayList<Sensor>();
ChannelAccessDoubleSensor s2 = new ChannelAccessDoubleSensor("mot1", c.getMotor1()+".RVAL");
ChannelAccessDoubleSensor s1 = new ChannelAccessDoubleSensor("mot2", c.getMotor1()+".RBV");
ChannelAccessDoubleSensor s3 = new ChannelAccessDoubleSensor("mot2", "ARIDI-PCT:CURRENT");
sensors.add(s1);
sensors.add(s2);
sensors.add(s3);
ScrlogicLoop scrlogic = new ScrlogicLoop(sensors);
CrlogicLoop crlogic = new CrlogicLoop(c.getCrlogicPrefix(), c.getServer(), c.getShare(), c.getSmbShare(), zigZag);
crlogic.setActor(new OTFActuator("cmot", c.getMotor1(), readback, start, end, stepSize, integrationTime, additionalBacklash));
crlogic.getSensors().add(new OTFNamedChannelSensor("trigger", "TRIGGER0"));
crlogic.getSensors().add(new OTFScalerChannelSensor("scaler0", 0));
crlogic.getSensors().add(new OTFScalerChannelSensor("scaler1", 1));
crlogic.getSensors().add(new MillisecondTimestampSensor("timestamp"));
// Initialize scaler template
VSC16ScalerChannelsTemplate scalertemplate = new VSC16ScalerChannelsTemplate();
ChannelBeanFactory.getFactory().createChannelBeans(scalertemplate, c.getPrefixScaler());
ParallelCrlogic pcrlogic = new ParallelCrlogic(crlogic, scrlogic);
logger.info("Start scaler");
scalertemplate.getCommand().setValueNoWait(VSC16ScalerChannelsTemplate.Command.Count.ordinal());
pcrlogic.prepare();
pcrlogic.execute();
pcrlogic.cleanup();
logger.info("Stop scaler");
scalertemplate.getCommand().setValue(VSC16ScalerChannelsTemplate.Command.Done.ordinal());
System.out.println("PARALLEL CRLOGIC data:");
BlockingQueue<Message> queue = pcrlogic.getDataQueue().getQueue();
Message m = queue.take();
while(! (m instanceof EndOfStreamMessage)){
System.out.println(m.toString());
m = queue.take();
}
// Destroy scaler template
ChannelBeanFactory.getFactory().destroyChannelBeans(scalertemplate);
pcrlogic.destroy();
// System.out.println("CRLOGIC data:");
// BlockingQueue<Message> queue = crlogic.getDataQueue().getQueue();
// Message m = queue.take();
// while(! (m instanceof EndOfStreamMessage)){
// System.out.println(m.toString());
// m = queue.take();
// }
//
//
// System.out.println("SCRLOGIC data:");
// queue = scrlogic.getDataQueue().getQueue();
// m = queue.take();
// while(! (m instanceof EndOfStreamMessage)){
// System.out.println(m.toString());
// m = queue.take();
// }
}
}

View File

@@ -1,86 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.core.sensors.ChannelAccessDoubleArraySensor;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Test class for the ScalarDoubleSensorChannelAccess class.
* @author ebner
*
*/
public class ChannelAccessDoubleArraySensorTest {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessDoubleArraySensorTest.class.getName());
private static final String channelName = TestChannels.DOUBLE_WAVEFORM;
private static final int numberOfPoints = 10;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
* @throws CAException
*/
@Test
public void testRead() throws CAException, InterruptedException {
ChannelAccessDoubleArraySensor sensor = new ChannelAccessDoubleArraySensor("id0", channelName, numberOfPoints);
ChannelBean<double[]> channel = ChannelBeanFactory.getFactory().createChannelBean(double[].class, channelName, false);
// Prepare sensor channel
double[] setValue = new double[] { 0.1,0.2,0.3,4,5,6,77,88,99,10.2};
channel.setValue(setValue);
// Get sensor readout value
double[] value = (double[]) sensor.read();
for(int i=0;i<setValue.length;i++){
logger.finest("Sensor value["+i+"]: "+value[i]);
if(Math.abs(value[i] - setValue[i])>0.0000001){ // The precision of the channel is 6
fail("Sensor readout value does not match actual value");
}
}
}
}

View File

@@ -1,84 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Test class for the ScalarDoubleSensorChannelAccess class.
* @author ebner
*
*/
public class ChannelAccessDoubleSensorTest {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessDoubleSensorTest.class.getName());
private static final String channelName = TestChannels.ANALOG_OUT;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
* @throws CAException
*/
@Test
public void testRead() throws CAException, InterruptedException {
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor("id0", channelName);
ChannelBean<Double> channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
// Prepare sensor channel
Double setValue = 0.1d;
channel.setValue(setValue);
// Get sensor readout value
Double value = (Double) sensor.read();
logger.finest("Sensor value: "+value);
if(!value.equals(setValue)){
fail("Sensor readout value does not match actual value");
}
}
}

View File

@@ -1,77 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
/**
* Test class for the ScalarDoubleSensorChannelAccess class.
* @author ebner
*
*/
public class ChannelAccessStringSensorTest {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessStringSensorTest.class.getName());
private static final String channelName = TestChannels.ANALOG_OUT+".NAME";
private static final String actualValue = TestChannels.ANALOG_OUT;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
* @throws CAException
*/
@Test
public void testRead() throws CAException, InterruptedException {
ChannelAccessStringSensor sensor = new ChannelAccessStringSensor("id0", channelName);
// Get sensor readout value
String value = (String) sensor.read();
logger.info("Sensor value: "+value);
if(!value.equals(actualValue)){
fail("Sensor readout "+value+" value does not match actual value "+actualValue);
}
}
}

View File

@@ -1,133 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.core.sensors;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.logging.Logger;
import gov.aps.jca.CAException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.core.Action;
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
import ch.psi.fda.core.sensors.ComplexSensor;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* Test class for the ScalarDoubleSensorChannelAccess class.
* @author ebner
*
*/
public class ComplexSensorTest {
// Get Logger
private static Logger logger = Logger.getLogger(ComplexSensorTest.class.getName());
private static final String channelName = TestChannels.ANALOG_OUT;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
* @throws CAException
*/
@Test
public void testRead() throws CAException, InterruptedException {
final HashMap<String, Long> timestamps = new HashMap<String,Long>();
ChannelAccessDoubleSensor s1 = new ChannelAccessDoubleSensor("id0", channelName);
ComplexSensor sensor = new ComplexSensor("id2", s1);
// Add pre action
sensor.getPreActions().add(new Action() {
@Override
public void execute() {
logger.info("PreAction");
timestamps.put("pre", System.currentTimeMillis());
}
@Override
public void destroy() {
}
@Override
public void abort() {
}
});
// Add post action
sensor.getPostActions().add(new Action() {
@Override
public void execute() {
logger.info("PostAction");
timestamps.put("post", System.currentTimeMillis());
}
@Override
public void destroy() {
}
@Override
public void abort() {
}
});
// Create channel bean for test sensor channel
ChannelBean<Double> channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
// Prepare sensor channel
Double setValue = 0.1d;
channel.setValue(setValue);
// Get sensor readout value
Double value = (Double) sensor.read();
logger.finest("Sensor value: "+value);
if(!value.equals(setValue)){
fail("Sensor readout value does not match actual value");
}
if(timestamps.get("post")<timestamps.get("pre")){
fail("Post got executed before pre");
}
}
}

View File

@@ -1,303 +0,0 @@
/**
*
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.visualizer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataMessageMetadata;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.StreamDelimiterMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.model.v1.MatrixPlot;
import ch.psi.fda.model.v1.PseudoPositioner;
import ch.psi.fda.model.v1.Visualization;
import ch.psi.fda.visualizer.Visualizer;
/**
* All test cases in this test class are meant to be executed manually
* Remove @Ignore in front of the test function to be able to run it.
*
* @author ebner
*
*/
public class DataVisualizerTest {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.visualizer.Visualizer#run()}.
* @throws InterruptedException
*/
@Ignore
@Test
public void testRun() throws InterruptedException {
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
DataMessageMetadata dm = new DataMessageMetadata();
dm.getComponents().add(new ComponentMetadata("id1", 0));
dm.getComponents().add(new ComponentMetadata("id2", 0));
dm.getComponents().add(new ComponentMetadata("id3", 0));
DataQueue queue = new DataQueue(q,dm);
// Create visualization
List<Visualization> vlist = new ArrayList<Visualization>();
ch.psi.fda.model.v1.LinePlot p = new ch.psi.fda.model.v1.LinePlot();
p.setX("id1");
p.getY().add("id2");
vlist.add(p);
p = new ch.psi.fda.model.v1.LinePlot();
p.setX("id1");
p.getY().add("id3");
vlist.add(p);
// Create visualizer
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
JPanel pan = new JPanel();
for(JPanel pp: visualizer.getPlotPanels()){
pan.add(pp);
}
f.add(pan);
f.setVisible(true);
// Thread creating data
Thread t = new Thread(new Runnable() {
@Override
public void run() {
DataMessage m;
for(double t=0;t<4;t++){
for(double i =0;i<100;i=i+0.1){
m = new DataMessage();
m.getData().add(i);
m.getData().add(t+Math.sin(i));
m.getData().add(t+Math.cos(i));
q.add(m);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException("Sleep interrupted",e);
}
}
q.add(new StreamDelimiterMessage(0));
}
q.add(new EndOfStreamMessage());
}
});
// Start data thread
t.start();
// visualizer.visualize();
t.join();
Thread.sleep(10000);
}
@Ignore
@Test
public void testRunArray() throws InterruptedException {
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
DataMessageMetadata dm = new DataMessageMetadata();
dm.getComponents().add(new ComponentMetadata("id1", 0));
DataQueue queue = new DataQueue(q,dm);
// Create visualization
List<Visualization> vlist = new ArrayList<Visualization>();
ch.psi.fda.model.v1.LinePlotArray p = new ch.psi.fda.model.v1.LinePlotArray();
p.getY().add("id1");
p.setMaxSeries(10);
vlist.add(p);
// Create visualizer
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
JPanel pan = new JPanel();
for(JPanel pp: visualizer.getPlotPanels()){
pan.add(pp);
}
f.add(pan);
f.setVisible(true);
// Thread creating data
Thread t = new Thread(new Runnable() {
@Override
public void run() {
DataMessage m;
int npoints = 10000;
for(double t=0;t<10;t++){
double[] values = new double[npoints];
for(int i=0;i<npoints;i++){
values[i]= Math.sin(i*0.01)+Math.cos(t);
}
m = new DataMessage();
m.getData().add(values);
q.add(m);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException("Sleep interrupted",e);
}
}
q.add(new StreamDelimiterMessage(0));
q.add(new EndOfStreamMessage());
}
});
// Start data thread
t.start();
// visualizer.visualize();
t.join();
Thread.sleep(10000);
}
/**
* Test method for {@link ch.psi.fda.visualizer.Visualizer#run()}.
* @throws InterruptedException
*/
@Ignore
@Test
public void testRun2D() throws InterruptedException {
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
DataMessageMetadata dm = new DataMessageMetadata();
dm.getComponents().add(new ComponentMetadata("id1", 1));
dm.getComponents().add(new ComponentMetadata("id2", 0));
dm.getComponents().add(new ComponentMetadata("id3", 0));
DataQueue queue = new DataQueue(q,dm);
List<Visualization> vlist = new ArrayList<Visualization>();
ch.psi.fda.model.v1.LinePlot p = new ch.psi.fda.model.v1.LinePlot();
p.setX("id2");
p.getY().add("id3");
vlist.add(p);
// 0d,4d,5,0d,100d,1001
PseudoPositioner pos = new PseudoPositioner();
pos.setId("id1");
pos.setCounts(5);
PseudoPositioner pos1 = new PseudoPositioner();
pos1.setId("id2");
pos1.setCounts(1000);
MatrixPlot mp = new MatrixPlot();
mp.setX(pos);
mp.setY(pos1);
mp.setZ("id3");
vlist.add(mp);
// Create visualizer
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
// f.add(plot.getPlotPanel());
JPanel pan = new JPanel();
for(JPanel pp: visualizer.getPlotPanels()){
pan.add(pp);
}
f.add(pan);
f.setVisible(true);
// Thread creating data
Thread t = new Thread(new Runnable() {
@Override
public void run() {
DataMessage m;
for(double t=1;t<=5;t++){
for(double i=1;i<=1000;i++){
m = new DataMessage();
m.getData().add(t);
m.getData().add(i);
m.getData().add(t+Math.cos(i));
q.add(m);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException("Sleep interrupted",e);
}
}
q.add(new StreamDelimiterMessage(0));
}
q.add(new EndOfStreamMessage());
}
});
// Start data thread
t.start();
// visualizer.visualize();
t.join();
Thread.sleep(10000);
}
}

View File

@@ -1,32 +0,0 @@
# Specify the handlers to create in the root logger
##handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
handlers = java.util.logging.ConsoleHandler
# Set the default logging level for the root logger
.level=ALL
# Set the default logging level for new ConsoleHandler instances
java.util.logging.ConsoleHandler.level=ALL
# Set the default formatter for new ConsoleHandler instances
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Set the default logging level for new FileHandler instances
##java.util.logging.FileHandler.level=ALL
# Set the default formatter for new ConsoleHandler instances
##java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# Naming of the output file:
##java.util.logging.FileHandler.pattern=/Users/ebner/Workspace/Eclipse/workspace-xasec/ch.psi.x10/resources/logs/fda-%u.%g.log
# Limiting size of output file in bytes (10000kb):
##java.util.logging.FileHandler.limit=10000000
# Number of output files to cycle through, by appending an
# integer to the base file name:
##java.util.logging.FileHandler.count=10
# Set the default logging level for the logger named com.mycompany
ch.psi.fda.level=ALL
com.cosylab.epics.level=ALL

View File

@@ -1,4 +0,0 @@
# Test properties file
ch.psi.jcae.ContextFactory.addressList=129.129.130.255 129.129.130.37 129.129.145.26 129.129.130.88 129.129.130.142
ch.psi.jcae.ChannelBeanFactory.retries=4

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Thu Mar 17 08:20:35 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip

164
gradlew vendored Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,54 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>bin</id>
<!-- Generates a zip package containing the needed files -->
<formats>
<format>zip</format>
</formats>
<!-- Adds dependencies to zip package under lib directory -->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
<fileSets>
<!-- Adds startup scripts to the root directory of zip package -->
<fileSet>
<fileMode>0755</fileMode>
<directory>src/main/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
<!-- <fileSet>
<directory>src/main/assembly/www</directory>
<outputDirectory>www</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet> -->
<!-- <fileSet>
<fileMode>0755</fileMode>
<directory>src/main/assembly/var</directory>
<outputDirectory>var</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet> -->
<!-- adds jar package to the root directory of zip package -->
<!-- <fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet> -->
</fileSets>
</assembly>

View File

@@ -0,0 +1,40 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
# Execute java
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.ConversionMain $ARGUMENTS

View File

@@ -0,0 +1,40 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
# Execute java
java -Xmx1024m -XX:MaxPermSize=128m -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS -cp $CLASSPATH ch.psi.fda.ui.RemoteAcquisitionMain $ARGUMENTS

View File

@@ -0,0 +1,40 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
# Execute java
java -Xmx1024m -XX:MaxPermSize=128m -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS -cp $CLASSPATH ch.psi.fda.ui.AcquisitionMain $ARGUMENTS

View File

@@ -0,0 +1,42 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
#HUB_BASE=$BASEDIR/../
#export HUB_BASE
java $VM_ARGUMENTS -cp $CLASSPATH -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties ch.psi.fda.rest.FdaServer $ARGUMENTS

View File

@@ -0,0 +1,40 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
# Execute java
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.VisualizationZMQMain $ARGUMENTS

View File

@@ -0,0 +1,40 @@
#!/bin/bash
CURRENTDIR=`pwd`
# Resolve symlinks
BASEDIR=$0
while [ -h "$BASEDIR" ]; do
ls=`ls -ld "$BASEDIR"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
BASEDIR="$link"
else
BASEDIR="`dirname "$BASEDIR"`/$link"
fi
done
BASEDIR=`dirname "$BASEDIR"`
SCRIPTNAME=`basename ${0}`
APPLICATION_HOME=$BASEDIR/../..
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
ARGUMENTS=
VM_ARGUMENTS=
for i in $@
do
if [ `expr $i : '-D.*'` != '0' ] ;then
# Extract VM options
VM_ARGUMENTS="$VM_ARGUMENTS $i"
else
ARGUMENTS="$ARGUMENTS $i"
fi
done
# Execute java
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.VisualizationMain $ARGUMENTS

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6158
src/main/assembly/www/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
/* ==========================================================================
Author's custom styles
========================================================================== */

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,222 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/bootstrap.min.css">
<style>
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<script src="js/jquery-2.0.0.min.js"></script>
<script type='text/javascript'>
var base = '../hub';
var stream;
function getVersion() {
$.get(base+'/version', function(data) {
$('#version').empty();
$('#version').append(data)
});
}
function getBeamlines() {
$.get(base, function(data) {
/* update beamlines selection */
$('#selectionBeamline').empty();
for (var i in data){
beamline = data[i];
$('#selectionBeamline').append('<option value="'+beamline+'">'+beamline+'</option>')
}
/* $('#selectionBeamline')[0].selectedIndex=0; */
connectStream(data[0]);
});
}
function updateKeys(beamline, keys){
keytag = $('#beamlineKeys');
keytag.empty();
table='<table class="table table-hover"><thead><tr><td>Key</td><td>Value</td></tr></thead><tbody>';
for(k in keys){
table=table+'<tr><td>'+k+'</td><td>'+
'<div class="input-append">'+
'<input type="text" value="'+keys[k]+'" onchange="setKey(\''+beamline+'\',\''+k+'\',$(this).val())">'+
//'<button class="btn" type="button" onclick="setKey(\''+beamline+'\',\''+k+'\',$(this).prev().val())">Update</button>'+
'<button class="btn" type="button" onclick="deleteKey(\''+beamline+'\',\''+k+'\')">Delete</button>'+
'</div>'+
'</td></tr>';
}
table = table+'<tr>'+
'<td><input id="keyToAdd" type="text" placeholder="Key"></td>'+
'<td><div class="input-append">'+
'<input id="valueToAdd"type="text" placeholder="Value">'+
'<button class="btn" type="button" onclick="setKey(\''+beamline+'\',$(\'#keyToAdd\').val(),$(\'#valueToAdd\').val())">Add</button>'+
'</div></td>'+
'</tr>';
table = table+'</table></tbody>';
keytag.append(table);
}
function connectStream(beamline) {
closeStream();
stream = new EventSource(base + '/' + beamline + '/stream');
stream.onmessage = function(event) {
keys=JSON.parse(event.data)
updateKeys(beamline, keys);
};
getKeys(beamline);
}
function closeStream() {
try {
stream.close();
} catch (e) {
}
}
function getKeys(beamline){
$.get(base+'/'+beamline+'/keys', function(data) {
updateKeys(beamline, data );
});
}
function setKey(beamline, key, value){
$.ajax({
url: base+'/'+beamline+'/keys/'+key,
type: 'PUT',
data: value,
success: function(result) {
}
});
}
function deleteKey(beamline, key){
$.ajax({
url: base+'/'+beamline+'/keys/'+key,
type: 'DELETE',
success: function(result) {
}
});
}
function addBeamline(beamline){
getKeys(beamline); /*create beamline*/
getBeamlines();
}
function deleteBeamline(beamline){
$.ajax({
url: base+'/'+beamline,
type: 'DELETE',
success: function(result) {
getBeamlines(); /* Update beamline list */
}
});
}
</script>
</head>
<body>
<!-- <script>
var source = new EventSource('../server-sent-events/');
source.onmessage = function(e) {
$('#messagefield') = e.data;
};
</script> -->
<!--[if lt IE 7]>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
<![endif]-->
<!-- This code is taken from http://twitter.github.com/bootstrap/examples/hero.html -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="#">hub</a>
</div>
</div>
</div>
<div class="container">
<!-- Main hero unit for a primary marketing message or call to action -->
<!-- <div class="hero-unit">
<p>This is the central Hub administration page ...</p>
</div> -->
<!-- Example row of columns -->
<div class="row">
<div class="span5">
<h2>Key Group</h2>
<div>
<select id="selectionBeamline">
<!-- <option value="sydney">Sydney</option> -->
</select>
</div>
<div id="beamlineKeys"></div>
</div>
</div>
<div class="row">
<div class="span5">
<h2>Key Group Management</h2>
<div class="input-append">
<input class="span2" id="appendedInputButton" placeholder="Key Group" type="text">
<button id="addBeamlineBtn" class="btn" type="button" onclick="addBeamline($(this).prev().val());$(this).prev().val('')">Add</button>
<button id="addBeamlineBtn" class="btn" type="button" onclick="deleteBeamline($(this).prev().prev().val());$(this).prev().prev().val('')">Delete</button>
</div>
</div>
</div>
<hr>
<footer>
<p>Hub - Version <span id='version'></span> - &copy; Paul Scherrer Institute 2013</p>
</footer>
</div>
<!-- /container -->
<script>
/* update beamlines */
getVersion();
getBeamlines();
$('#selectionBeamline').change(function(){connectStream($('#selectionBeamline').val())});
</script>
<script>
window.jQuery
|| document
.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')
</script>
<script src="js/vendor/bootstrap.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
package ch.psi.fda;
import java.io.File;
import ch.psi.fda.edescriptor.EDescriptor;
import ch.psi.fda.vdescriptor.VDescriptor;
public interface DescriptorProvider {
public void load(File ... files );
public EDescriptor getEDescriptor();
public VDescriptor getVDescriptor();
public Class<?> getEDescriptorClass();
}

View File

@@ -0,0 +1,28 @@
package ch.psi.fda;
public interface EContainer {
/**
* Initialize execution container like required resources, etc.
*/
public void initialize();
/**
* Executes the logic implemented by the ExecutionContainer
* Execute is a blocking function and must not return before the actual logic is executed
*/
public void execute();
/**
* Try to abort the execution of the logic
*/
public void abort();
public boolean isActive();
/**
* Destroy execution container and free all allocated resources
*/
public void destroy();
}

Some files were not shown because too many files have changed in this diff Show More