183 Commits

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
5660fafe25 Fixed bug regarding the execution of manipulations 2013-10-04 13:03:34 +02:00
bf3535a9b5 optimized data flow for scans without manipulations 2013-10-04 11:27:40 +02:00
b9c15b0fc8 Added EventBus to collector 2013-10-04 11:16:08 +02:00
83dd7654ed small changes before messingup with guice 2013-10-03 16:19:09 +02:00
e723f66df3 More cleanup 2013-10-03 14:24:17 +02:00
1574dcc7bb Cleanup 2013-10-03 14:20:24 +02:00
1de3b6c14e Cleanup 2013-10-03 13:55:34 +02:00
2a6018c4f5 Fixed all compile problems and migrated all serializers and
deserializers to Guava EventBus.
2013-10-03 13:44:08 +02:00
c3238e4d22 Unfinished removal of the dispatcher class. tested the migration of the
serializer to EventBus.
Test is/was successfull but things now need to be cleaned up properly!
There are various compilation errors in the code
2013-10-03 10:57:20 +02:00
4045873135 Moved on to google guava EventBus for visualizer ... 2013-10-03 10:30:29 +02:00
3e38e4002d Experiment with zmq pub/sub for visualization.
- after the scan somehow the zmq library still takes 100% CPU time -
very strange
2013-10-03 09:30:36 +02:00
0958b76bb0 cleanup conversion class 2013-10-02 13:52:44 +02:00
eaffe7ff91 Fixed compiler warnings 2013-10-02 13:49:29 +02:00
70cb7a8939 removed obsolete functionality
upgraded to java 1.7 and set project encoding to UTF-8
2013-10-02 13:30:50 +02:00
0b9ee77f76 Merge branch 'master' into 1.0.0 2013-10-02 13:05:36 +02:00
81af4449dc FDA-81
Reverted change that filename inside xml always matches that actual
filename.
2013-09-30 08:38:12 +02:00
cbef08682a Added comments and modified some test 2013-08-29 08:11:35 +02:00
7f59fc1ab2 Changes for parameters, ... 2013-08-02 15:18:18 +02:00
d915137288 Added test code for r/edescriptors ... 2013-08-02 12:38:58 +02:00
ef1b318017 Latest ideas and tests for FDA NG 2013-07-31 13:03:37 +02:00
26f2897a7e Fixed asynchronous/nowait confusion 2013-07-30 15:37:06 +02:00
6fedd86d23 reorganized again
debugging some channel access problems ...
2013-07-30 13:19:55 +02:00
f84a5696b0 reorganized package structure for new dataacquisition engine 2013-07-30 11:36:26 +02:00
e64d341a38 Changes 2013-07-29 15:22:33 +02:00
bc0763a22c Now all action related methods should work ... 2013-07-29 11:18:20 +02:00
4a59731669 Started new concept to generate an acquisition script instead of using
complex objects that need to be maintained by ourself
2013-07-26 13:40:06 +02:00
1d05d36b5c Moved to newest jcae 2013-07-25 08:22:24 +02:00
93cd7668b6 Starting with 2.0.0 development 2013-07-23 13:41:52 +02:00
374 changed files with 22569 additions and 23610 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.6">
<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,5 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

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,205 +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>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>
<source>1.6</source>
<target>1.6</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,299 +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.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ch.psi.fda.install.ApplicationConfigurator;
/**
* @author ebner
*
*/
public class AcquisitionEngineConfiguration {
private static final Logger logger = Logger.getLogger(AcquisitionEngineConfiguration.class.getName());
private static final AcquisitionEngineConfiguration instance = new AcquisitionEngineConfiguration();
private String otfChannelPrefix;
private String otfNfsServer;
private String otfNfsShare;
private String otfSmbShare;
private String otfScalerPrefix;
private boolean otfUseCrlogic;
private String otfCrlogicPrefix;
private boolean otfCrlogicKeepTmpFiles;
/**
* Base directory for data. The directory may contain date macros. The string may contain any @see java.text.SimpleDateFormat
* patterns within ${ } brackets. The macros are resolved with the actual time while the get method
* of this property is called.
*/
private String dataBaseDirectory = System.getProperty("user.home");
/**
* Prefix of the data file. The prefix may contain date macros. The string may contain any @see java.text.SimpleDateFormat
* patterns within ${ } brackets. The macros are resolved with the actual time while the get method
* of this property is called.
*/
private String dataFilePrefix = "";
/**
* Maximum time for a actor move
*/
private Long actorMoveTimeout = 600000l; // 10 Minutes maximum move time
private String smptServer;
/**
* Default Constructor
* The constructor will read the configuration from the /fda.properties file (resource) located in the classpath.
*/
private AcquisitionEngineConfiguration(){
loadConfiguration();
}
/**
* Get instance of this configuration
* @return configuration
*/
public static AcquisitionEngineConfiguration getInstance(){
return(instance);
}
/**
* Load configuration from properties file
*/
private void loadConfiguration() {
String config = System.getProperty(ApplicationConfigurator.FDA_CONFIG_FILE_ARGUMENT);
Properties properties = new Properties();
if(config != null){
try {
properties.load(new FileReader(config));
} catch (FileNotFoundException e) {
throw new RuntimeException("Configuration file "+config+" not found", e);
} catch (IOException e) {
throw new RuntimeException("Cannot read configuration file "+config, e);
}
}
else{
logger.warning("No configfile specified !");
}
// The defaults are set here
otfChannelPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.channelPrefix", "");
otfScalerPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.scalerPrefix", "");
otfNfsServer = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.nfsServer", "");
otfNfsShare = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.nfsShare", "");
otfSmbShare = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.smbShare", "");
otfUseCrlogic = new Boolean(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.useCrlogic", "false"));
otfCrlogicPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.crlogicPrefix", "");
otfCrlogicKeepTmpFiles = new Boolean(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.crlogicKeepTmpFiles", "false"));
// Workaround
// dataBaseDirectory = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".data.baseDirectory", ".");
if(System.getProperty(ApplicationConfigurator.FDA_HOME_ARGUMENT)!=null){
dataBaseDirectory = System.getProperty(ApplicationConfigurator.FDA_HOME_ARGUMENT)+"/data";
}
else{
dataBaseDirectory = "./data";
}
dataFilePrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".data.filePrefix","");
actorMoveTimeout = new Long(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".actorMoveTimeout","600000"));
smptServer= properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".notification.host","mail.psi.ch");
}
/**
* Reload this configuration from the corresponding properties file
* @throws IOException
*/
public void reloadConfiguration() throws IOException{
loadConfiguration();
}
/**
* @return the otfChannelPrefix
*/
public String getOtfChannelPrefix() {
return otfChannelPrefix;
}
/**
* @return the otfScalerPrefix
*/
public String getOtfScalerPrefix() {
return otfScalerPrefix;
}
/**
* @return the otfNfsServer
*/
public String getOtfNfsServer() {
return otfNfsServer;
}
/**
* @return the otfNfsShare
*/
public String getOtfNfsShare() {
return otfNfsShare;
}
/**
* @return the otfSmbShare
*/
public String getOtfSmbShare() {
return otfSmbShare;
}
/**
* @return the otfUseCrlogic
*/
public boolean isOtfUseCrlogic() {
return otfUseCrlogic;
}
/**
* @return the dataBaseDirectory
*/
public String getDataBaseDirectory() {
return dataBaseDirectory;
}
/**
* @return the dataFilePrefix
*/
public String getDataFilePrefix() {
return dataFilePrefix;
}
/**
* @return the smptServer
*/
public String getSmptServer() {
return smptServer;
}
/**
* @return the otfCrlogicPrefix
*/
public String getOtfCrlogicPrefix() {
return otfCrlogicPrefix;
}
/**
* @return the otfCrlogicKeepTmpFiles
*/
public boolean isOtfCrlogicKeepTmpFiles() {
return otfCrlogicKeepTmpFiles;
}
/**
* @return the actorMoveTimeout
*/
public Long getActorMoveTimeout() {
return actorMoveTimeout;
}
public String replaceMacros(String string, Date date, String name){
String newString = string;
// Replace scan name macros
newString = newString.replaceAll("\\$\\{name\\}", name);
// Replace date macros
Pattern pattern = Pattern.compile("\\$\\{[a-z,A-Z,-,_,:]*\\}");
Matcher matcher = pattern.matcher(newString);
while(matcher.find()){
String datePattern = matcher.group();
datePattern = datePattern.replaceAll("\\$\\{", "");
datePattern = datePattern.replaceAll("\\}", "");
SimpleDateFormat datef = new SimpleDateFormat(datePattern);
newString = matcher.replaceFirst(datef.format(date));
matcher = pattern.matcher(newString);
}
return newString;
}
public void setOtfChannelPrefix(String otfChannelPrefix) {
this.otfChannelPrefix = otfChannelPrefix;
}
public void setOtfNfsServer(String otfNfsServer) {
this.otfNfsServer = otfNfsServer;
}
public void setOtfNfsShare(String otfNfsShare) {
this.otfNfsShare = otfNfsShare;
}
public void setOtfSmbShare(String otfSmbShare) {
this.otfSmbShare = otfSmbShare;
}
public void setOtfScalerPrefix(String otfScalerPrefix) {
this.otfScalerPrefix = otfScalerPrefix;
}
public void setOtfUseCrlogic(boolean otfUseCrlogic) {
this.otfUseCrlogic = otfUseCrlogic;
}
public void setOtfCrlogicPrefix(String otfCrlogicPrefix) {
this.otfCrlogicPrefix = otfCrlogicPrefix;
}
public void setOtfCrlogicKeepTmpFiles(boolean otfCrlogicKeepTmpFiles) {
this.otfCrlogicKeepTmpFiles = otfCrlogicKeepTmpFiles;
}
public void setDataBaseDirectory(String dataBaseDirectory) {
this.dataBaseDirectory = dataBaseDirectory;
}
public void setDataFilePrefix(String dataFilePrefix) {
this.dataFilePrefix = dataFilePrefix;
}
public void setActorMoveTimeout(Long actorMoveTimeout) {
this.actorMoveTimeout = actorMoveTimeout;
}
public void setSmptServer(String smptServer) {
this.smptServer = smptServer;
}
}

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,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.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;
/**
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
* asynchronously.
* @author ebner
*
*/
public class ChannelAccessConditionAnd<E extends Integer> implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionAnd.class.getName());
/**
* Channel to set
*/
private final ChannelBean<E> channel;
/**
* Value to wait for
*/
private final E 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, E expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<E>) ChannelBeanFactory.getFactory().createChannelBean( (Class<E>) 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<E>() {
@Override
public int compare(E o1, E 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,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.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;
/**
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
* asynchronously.
* @author ebner
*
*/
public class ChannelAccessConditionOr<E extends Integer> implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionOr.class.getName());
/**
* Channel to set
*/
private final ChannelBean<E> channel;
/**
* Value to wait for
*/
private final E 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, E expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<E>) ChannelBeanFactory.getFactory().createChannelBean( (Class<E>) 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<E>() {
@Override
public int compare(E o1, E 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;
/**
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
* asynchronously.
* @author ebner
*
*/
public class ChannelAccessConditionRegex<E extends String> implements Action {
// Get Logger
private static Logger logger = Logger.getLogger(ChannelAccessConditionRegex.class.getName());
/**
* Channel to set
*/
private final ChannelBean<E> channel;
/**
* Value to wait for
*/
private final E 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, E expectedValue, Long timeout){
if(timeout !=null && timeout<=0){
throw new IllegalArgumentException("Timeout must be > 0");
}
try {
this.channel = (ChannelBean<E>) ChannelBeanFactory.getFactory().createChannelBean( (Class<E>) 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<E>() {
@Override
public int compare(E o1, E 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,165 +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.collector;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
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 BlockingQueue<Message> outQueue;
/**
* Constructor
*/
public Collector(){
queues = new ArrayList<DataQueue>();
outQueue = new LinkedBlockingQueue<Message>(1000); // Create bounded queue to prevent running out of memory ...
}
/* (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
}
try {
outQueue.put(new EndOfStreamMessage());
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Unable to terminate stream with and End of Stream Message",e);
}
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
outQueue.put(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
outQueue.put(ddm);
}
}
/**
* @return the queues
*/
public List<DataQueue> getQueues() {
return queues;
}
/**
* Get the outgoing data queue.
* Attention, only call this method after all ingoing queues were registered! Otherwise the data returned
* by this method is not accurate.
* @return output queue of collector
*/
public DataQueue getOutQueue(){
DataMessageMetadata dataMessageMetadata = new DataMessageMetadata();
dataMessageMetadata.getComponents();
// 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(new DataQueue(outQueue, dataMessageMetadata));
}
}

View File

@@ -1,88 +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.collector;
import java.util.ArrayList;
import java.util.List;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class DataDispatcher implements Runnable{
private DataQueue queue;
private List<DataQueue> outQueues;
public DataDispatcher(DataQueue queue){
this.queue = queue;
this.outQueues = new ArrayList<DataQueue>();
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// TODO Need to synchronize message metadata
// for(DataQueue q: outQueues){
// }
// Dispatch Messages
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
// Clone message ...
for(DataQueue q: outQueues){
q.getQueue().put(message);
}
// Read next message
message = queue.getQueue().take();
}
// Write end of stream message
for(DataQueue q: outQueues){
q.getQueue().put(message);
}
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
}
}
/**
* @return the outQueues
*/
public List<DataQueue> getOutQueues() {
return outQueues;
}
}

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,123 +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.manipulator;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
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 Manipulator implements Runnable{
/**
* Outgoing data queue
*/
private final DataQueue outQueue;
/**
* Incomming data queue
*/
private final DataQueue queue;
/**
* List of manipulations
*/
private final List<Manipulation> manipulations;
/**
* Constructor
* @param queue
* @param manipulations
*/
// TODO need to support multiple (a list of) manipulation(s)
public Manipulator(DataQueue queue, List<Manipulation> manipulations){
this.manipulations = manipulations;
// Create outgoing data metadata
DataMessageMetadata dmetadata = queue.getDataMessageMetadata().clone();
// Initialize manipulations and create outgoing metadata
for(Manipulation manipulation: this.manipulations){
// Initialize manipulation
// manipulation.initialize(queue.getDataMessageMetadata());
manipulation.initialize(dmetadata);
// Add manipulation id to metadata
dmetadata.getComponents().add(new ComponentMetadata(manipulation.getId(),0)); // Calculated component always belongs to lowes dimension
}
this.queue = queue;
this.outQueue = new DataQueue(new LinkedBlockingQueue<Message>(1000) , dmetadata ); // Create bounded queue to prevent running out of memory ...
}
/**
* @return the outQueue
*/
public DataQueue getOutQueue() {
return outQueue;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// Dispatch Messages
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
if(message instanceof DataMessage){
DataMessage dm = (DataMessage) message;
for(Manipulation manipulation: manipulations){
dm.getData().add(manipulation.execute(dm));
}
}
// Put message to outgoing queue ...
outQueue.getQueue().put(message);
// Read next message
message = queue.getQueue().take();
}
// Write end of stream message
outQueue.getQueue().put(message);
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data manipulator was interrupted while writing data to file",e);
}
}
}

View File

@@ -1,81 +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.ArrayList;
import java.util.List;
/**
* Structure to hold the metadata of a component of a message.
* @author ebner
*
*/
public class DataMessageMetadata {
/**
* 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,205 +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.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import ch.psi.fda.model.v1.Configuration;
import ch.psi.fda.model.v1.Data;
/**
* Manage the serialization and deserialization of the model
* @author ebner
*
*/
public class ModelManager {
/**
* Deserialize an instance of a data model of the type Configuration
* Before creating the object model variables will be replaced
*
* @param file Scan file
* @param variables Scan variables
* @throws JAXBException Something went wrong while unmarshalling
* @throws SAXException Cannot read model schema file
* @throws ParserConfigurationException
* @throws IOException
* @throws TransformerFactoryConfigurationError
* @throws TransformerException
*/
public static Configuration unmarshall(File file, HashMap<String, String> variables) throws JAXBException, SAXException, IOException,
ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException {
// Load template file
Transformer xformer = TransformerFactory.newInstance().newTransformer(new StreamSource(file));
// Overwrite parameters
for(String key: variables.keySet()){
xformer.setParameter(key, variables.get(key));
}
// Workaround for complex parameters (parameter including xml fragments)
// How the workaround works:
// Because we want to set complex parameters we first have to apply the xslt transformation to the input
// stream and create an other output stream. In the template file the complex parameter must be referenced as follows
// <xsl:value-of select="$var.regions" disable-output-escaping="yes" />
// If it is not done this way the < and > of the tags will be replaced by &lt; and &gt;
// Also if we directly transform to a DOMResult the dom tree would not include the
// nodes added by the parameter but just a text object. Therefor we do the workaround via the StreamResult ...
ByteArrayOutputStream bstream = new ByteArrayOutputStream();
StreamResult sresult = new StreamResult(bstream);
// Perform transformation (using template file also as input source)
xformer.transform(new StreamSource(file), sresult );
// Workaround for complex parameters
ByteArrayInputStream bistream = new ByteArrayInputStream(bstream.toByteArray());
StreamSource bsource = new StreamSource(bistream);
JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller u = context.createUnmarshaller();
// Validation
SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source s = new StreamSource(Configuration.class.getResourceAsStream("/model-v1.xsd"));
Schema schema = sf.newSchema(new Source[]{s}); // Use schema reference provided in XML
u.setSchema(schema);
try{
Configuration model = (Configuration) u.unmarshal(bsource, Configuration.class).getValue();
// Ensure that the filename inside the xml file is always the file name
Data d = model.getData();
if(d==null){
d = new Data();
model.setData(d);
}
d.setFileName(file.getName().replaceAll("\\.xml$", ""));
return (model);
}
catch(UnmarshalException e){
// Check
if(e.getLinkedException() instanceof SAXParseException){
throw new RuntimeException("Configuration file does not comply to required model specification\nCause: "+e.getLinkedException().getMessage(), e);
}
throw e;
}
}
/**
* Deserialize an instance of a data model of the type Configuration
* @param file
* @throws JAXBException Something went wrong while unmarshalling
* @throws SAXException Cannot read model schema file
*/
public static Configuration unmarshall(File file) throws JAXBException, SAXException {
JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller u = context.createUnmarshaller();
// Validation
SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source s = new StreamSource(Configuration.class.getResourceAsStream("/model-v1.xsd"));
Schema schema = sf.newSchema(new Source[]{s}); // Use schema reference provided in XML
u.setSchema(schema);
try{
Configuration model = (Configuration) u.unmarshal(new StreamSource(file), Configuration.class).getValue();
// Ensure that the filename inside the xml file is always the file name
Data d = model.getData();
if(d==null){
d = new Data();
model.setData(d);
}
d.setFileName(file.getName().replaceAll("\\.xml$", ""));
return (model);
}
catch(UnmarshalException e){
// Check
if(e.getLinkedException() instanceof SAXParseException){
throw new RuntimeException("Configuration file does not comply to required model specification\nCause: "+e.getLinkedException().getMessage(), e);
}
throw e;
}
}
/**
* Serialize an instance of a data model of the type Configuration
* @param model Model datastructure
* @param file File to write the model data into
* @throws JAXBException Something went wrong while marshalling model
* @throws SAXException Cannot read model schema files
*/
public static void marshall(Configuration model, File file) throws JAXBException, SAXException{
QName qname = new QName("http://www.psi.ch/~ebner/models/scan/1.0", "configuration");
JAXBContext context = JAXBContext.newInstance(Configuration.class);
Marshaller m = context.createMarshaller();
m.setProperty("jaxb.formatted.output", true);
// Validation
SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source s = new StreamSource(Configuration.class.getResourceAsStream("/model-v1.xsd"));
Schema schema = sf.newSchema(new Source[]{s}); // Use schema reference provided in XML
m.setSchema(schema);
// Set scan name equal to file name
Data d = model.getData();
if(d==null){
d = new Data();
model.setData(d);
}
d.setFileName(file.getName().replaceAll("\\.xml$", ""));
m.marshal( new JAXBElement<Configuration>(qname, Configuration.class, model ), file);
}
}

View File

@@ -1,179 +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.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.jmatio.io.MatFileWriter;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLDouble;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.DataQueue;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* Serialize data received by a DataQueue into a Matlab file
* @author ebner
*
*/
public class DataSerializerMAT implements DataSerializer{
private DataQueue queue;
private File file;
private boolean appendSuffix = false;
/**
* Construtor
* @param queue Data queue holding the data to serialize
* @param file Name of the Matlab file to serialize the data to
*/
public DataSerializerMAT(DataQueue queue, File file){
this.queue = queue;
this.file = file;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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
// Transposed data list
List<List<Object>> dlist = new ArrayList<List<Object>>();
List<Class<?>> clist = new ArrayList<Class<?>>();
boolean firstF = true;
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
if(message instanceof DataMessage){
DataMessage m = (DataMessage) message;
// Initialize list
if(firstF){
for(Object o: m.getData()){
dlist.add(new ArrayList<Object>());
clist.add(o.getClass());
}
firstF=false;
}
// Put data into data list
for(int i=0;i< m.getData().size();i++){
Object object = m.getData().get(i);
dlist.get(i).add(object);
}
}
// Read next message
message = queue.getQueue().take();
}
// Create Matlab vectors
ArrayList<MLArray> matlablist = new ArrayList<MLArray>();
for(int t=0; t<dlist.size(); t++ ){
// Get component metadata
ComponentMetadata c = queue.getDataMessageMetadata().getComponents().get(t);
c.getId();
List<Object> list = dlist.get(t);
if(clist.get(t).isArray()){
// Array Handling
}
else if(clist.get(t).equals(Double.class)){
// Data is of type Double
MLDouble darray = new MLDouble(escapeString(c.getId()),(Double[])list.toArray(new Double[list.size()]),1);
matlablist.add(darray);
}
}
// Write Matlab file
MatFileWriter writerr = new MatFileWriter();
writerr.write(outfile, matlablist);
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
/**
* Escape string to be Matlab key conform
* @param value
* @return Escaped string value
*/
private String escapeString(String value){
String evalue = value.replaceAll("-", "_");
evalue = evalue.replaceAll(":", "_");
evalue = evalue.replaceAll("\\.", "_");
evalue = evalue.replaceAll(" ", "_");
evalue = evalue.replaceAll("\\(", "_");
evalue = evalue.replaceAll("\\)", "_");
evalue = evalue.replaceAll("\\[", "_");
evalue = evalue.replaceAll("\\]", "_");
return(evalue);
}
}

View File

@@ -1,254 +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.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import com.jmatio.io.MatFileWriter;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLDouble;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
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;
/**
* Serialize data received by a DataQueue into a Matlab file
* @author ebner
*
*/
public class DataSerializerMAT2D implements DataSerializer{
// Get Logger
private static final Logger logger = Logger.getLogger(DataSerializerMAT2D.class.getName());
private DataQueue queue;
private File file;
private boolean appendSuffix = false;
/**
* Construtor
* @param queue Data queue holding the data to serialize
* @param file Name of the Matlab file to serialize the data to
*/
public DataSerializerMAT2D(DataQueue queue, File file){
this.queue = queue;
this.file = file;
// Check if input queue does only hold 2D data
int maxdim=0;
for(ComponentMetadata m: queue.getDataMessageMetadata().getComponents()){
if(m.getDimension()>maxdim){
maxdim=m.getDimension();
}
if(m.getDimension()>1){
throw new RuntimeException("Serializer does only support 2D data (XD data found)");
}
}
if(maxdim<1){
throw new RuntimeException("Serializer does only support 2D data ("+maxdim+"D data found)");
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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
// Transposed data list
List<List<List<Object>>> dlist = new ArrayList<List<List<Object>>>();
List<Class<?>> clist = new ArrayList<Class<?>>();
int dsize = 0; // Size of the dimension
int dcount = 0;
Integer mindsize = null;
boolean firstF = true;
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
if(message instanceof DataMessage){
DataMessage m = (DataMessage) message;
// Initialize list
if(firstF){
for(Object o: m.getData()){
// TODO Create list of lists (for each line one list - to
// be able to fill up empty data points if there are some)
List<List<Object>> l = new ArrayList<List<Object>>();
l.add(new ArrayList<Object>());
dlist.add(l);
clist.add(o.getClass());
}
firstF=false;
}
// Put data into data list
for(int i=0;i< m.getData().size();i++){
Object object = m.getData().get(i);
List<List<Object>> lo = dlist.get(i);
lo.get(lo.size()-1).add(object); // add data to latest list
}
dcount++;
}
else if(message instanceof StreamDelimiterMessage){
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
if(m.getNumber()==0){
// Determine minimum dimension size
if(dsize<dcount){
dsize=dcount;
}
// Determine maximum dimension size
if(mindsize == null){
mindsize=dcount;
}
if(mindsize>dcount){
mindsize=dcount;
}
// Add a new list for all component to the dlist
for(List<List<Object>> lo:dlist){
lo.add(new ArrayList<Object>());
}
dcount=0;
}
}
// Read next message
message = queue.getQueue().take();
}
logger.info("dsize: "+dsize + " mindsize:"+mindsize);
// Create Matlab vectors
ArrayList<MLArray> matlablist = new ArrayList<MLArray>();
logger.info("dlist size: "+dlist.size());
for(int t=0; t<dlist.size(); t++ ){
// Get component metadata
ComponentMetadata c = queue.getDataMessageMetadata().getComponents().get(t);
// Combine all lists to one big list (pad if there are data points missing)
List<Object> list = new ArrayList<Object>();
List<List<Object>> ol = dlist.get(t);
// Remove last array list as it is empty
ol.remove(ol.size()-1);
for(List<Object> li: ol){
list.addAll(li);
// Pad list if there are missing data points for some lines
for(int i=li.size();i<dsize;i++){
logger.info("Pad data point: "+i);
list.add(Double.NaN);
}
}
// List<Object> list = dlist.get(t);
logger.info("List: "+list.size());
if(clist.get(t).isArray()){
// Array Handling
}
else if(clist.get(t).equals(Double.class)){
// Data is of type Double
MLDouble darray = new MLDouble(escapeString(c.getId()),(Double[])list.toArray(new Double[list.size()]), dsize);
matlablist.add(darray);
}
}
// Write Matlab file
MatFileWriter writerr = new MatFileWriter();
writerr.write(outfile, matlablist);
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
/**
* Escape string to be Matlab key conform
* @param value
* @return Escaped string value
*/
private String escapeString(String value){
String evalue = value.replaceAll("-", "_");
evalue = evalue.replaceAll(":", "_");
evalue = evalue.replaceAll("\\.", "_");
evalue = evalue.replaceAll(" ", "_");
evalue = evalue.replaceAll("\\(", "_");
evalue = evalue.replaceAll("\\)", "_");
evalue = evalue.replaceAll("\\[", "_");
evalue = evalue.replaceAll("\\]", "_");
return(evalue);
}
}

View File

@@ -1,235 +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.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import com.jmatio.io.MatFileWriter;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLDouble;
import ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
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;
/**
* Serialize data received by a DataQueue into a Matlab file
* @author ebner
*
*/
public class DataSerializerMAT2DZigZag implements DataSerializer{
// Get Logger
private static final Logger logger = Logger.getLogger(DataSerializerMAT2DZigZag.class.getName());
private DataQueue queue;
private File file;
private boolean appendSuffix = false;
/**
* Construtor
* @param queue Data queue holding the data to serialize
* @param file Name of the Matlab file to serialize the data to
*/
public DataSerializerMAT2DZigZag(DataQueue queue, File file){
this.queue = queue;
this.file = file;
// Check if input queue does only hold 2D data
int maxdim=0;
for(ComponentMetadata m: queue.getDataMessageMetadata().getComponents()){
if(m.getDimension()>maxdim){
maxdim=m.getDimension();
}
if(m.getDimension()>1){
throw new RuntimeException("Serializer does only support 2D data (XD data found)");
}
}
if(maxdim<1){
throw new RuntimeException("Serializer does only support 2D data ("+maxdim+"D data found)");
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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
// Transposed data list
List<List<Object>> dlist = new ArrayList<List<Object>>();
List<List<Object>> dlistTmp = new ArrayList<List<Object>>();
List<Class<?>> clist = new ArrayList<Class<?>>();
int dsize = 0; // Size of the dimension
int dcount = 0;
int delimiterCount = 0;
boolean firstF = true;
boolean firstC = true;
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
if(message instanceof DataMessage){
DataMessage m = (DataMessage) message;
if(firstC){
for(Object o: m.getData()){
dlist.add(new ArrayList<Object>());
clist.add(o.getClass());
firstC=false;
}
}
// Initialize list
if(firstF){
for(int i=0;i<m.getData().size();i++){
dlistTmp.add(new ArrayList<Object>());
}
firstF=false;
}
// Put data into data list
for(int i=0;i< m.getData().size();i++){
Object object = m.getData().get(i);
dlistTmp.get(i).add(object);
}
dcount++;
}
else if(message instanceof StreamDelimiterMessage){
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
if(m.getNumber()==0){
if(dsize<dcount){
dsize=dcount;
}
dcount=0;
// Add temporary list to final list
for(int i=0;i<dlist.size();i++){
if(delimiterCount%2==1){
Collections.reverse(dlistTmp.get(i));
}
dlist.get(i).addAll(dlistTmp.get(i));
}
dlistTmp.clear();
firstF=true;
delimiterCount++;
}
}
// Read next message
message = queue.getQueue().take();
}
// Create Matlab vectors
ArrayList<MLArray> matlablist = new ArrayList<MLArray>();
logger.info("dlist size: "+dlist.size());
for(int t=0; t<dlist.size(); t++ ){
// Get component metadata
ComponentMetadata c = queue.getDataMessageMetadata().getComponents().get(t);
List<Object> list = dlist.get(t);
if(clist.get(t).isArray()){
// Array Handling
}
else if(clist.get(t).equals(Double.class)){
// Data is of type Double
MLDouble darray = new MLDouble(escapeString(c.getId()),(Double[])list.toArray(new Double[list.size()]), dsize);
matlablist.add(darray);
}
}
// Write Matlab file
MatFileWriter writerr = new MatFileWriter();
writerr.write(outfile, matlablist);
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
/**
* Escape string to be Matlab key conform
* @param value
* @return Escaped string value
*/
private String escapeString(String value){
String evalue = value.replaceAll("-", "_");
evalue = evalue.replaceAll(":", "_");
evalue = evalue.replaceAll("\\.", "_");
evalue = evalue.replaceAll(" ", "_");
evalue = evalue.replaceAll("\\(", "_");
evalue = evalue.replaceAll("\\)", "_");
evalue = evalue.replaceAll("\\[", "_");
evalue = evalue.replaceAll("\\]", "_");
return(evalue);
}
}

View File

@@ -1,235 +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 ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
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.messages.StreamDelimiterMessage;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class DataSerializerTXT implements DataSerializer{
// Get Logger
private static final Logger logger = Logger.getLogger(DataSerializerTXT.class.getName());
private DataQueue queue;
private File file;
private boolean appendSuffix = true;
/**
*
* @param queue
* @param file
* @param appendSuffix Flag whether to append a _0000 suffix after the original file name
*/
public DataSerializerTXT(DataQueue queue, File file, boolean appendSuffix){
this.queue = queue;
this.file = file;
this.appendSuffix = appendSuffix;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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
// Write header
StringBuffer b = new StringBuffer();
StringBuffer b1 = new StringBuffer();
b.append("#");
b1.append("#");
for(ComponentMetadata c: queue.getDataMessageMetadata().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');
int icount = 0;
boolean newfile = true;
boolean dataInBetween = false;
BufferedWriter writer = null;
// Get basename of the file
String basename = this.file.getAbsolutePath(); // Determine file name
String extension = basename.replaceAll("^.*\\.", ""); // Determine extension
basename = basename.replaceAll("\\."+extension+"$", "");
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
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();
}
}
// Read next message
message = queue.getQueue().take();
}
if(writer!=null){
// Close file
writer.close(); //If the stream was closed previously this has no effect
}
// Writer can be null if a scan is defined without a dimension
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
// /**
// * 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,205 +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 ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
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;
/**
* Serialize data received by a DataQueue into a Matlab file
* @author ebner
*
*/
public class DataSerializerTXT2D implements DataSerializer{
private DataQueue queue;
private File file;
private boolean appendSuffix = false;
/**
* Construtor
* @param queue Data queue holding the data to serialize
* @param file Name of the Matlab file to serialize the data to
*/
public DataSerializerTXT2D(DataQueue queue, File file){
this.queue = queue;
this.file = file;
// Check if input queue does only hold 2D data
int maxdim=0;
for(ComponentMetadata m: queue.getDataMessageMetadata().getComponents()){
if(m.getDimension()>maxdim){
maxdim=m.getDimension();
}
if(m.getDimension()>1){
throw new RuntimeException("Serializer does only support 2D data (XD data found)");
}
}
if(maxdim<1){
throw new RuntimeException("Serializer does only support 2D data ("+maxdim+"D data found)");
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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("(_[0-9]+)?\\."+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
// Transposed data list
List<List<Object>> dlist = new ArrayList<List<Object>>();
List<Class<?>> clist = new ArrayList<Class<?>>();
int dsize = 0; // Size of the dimension
int dcount = 0;
boolean firstF = true;
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
if(message instanceof DataMessage){
DataMessage m = (DataMessage) message;
// Initialize list
if(firstF){
for(Object o: m.getData()){
dlist.add(new ArrayList<Object>());
clist.add(o.getClass());
}
firstF=false;
}
// Put data into data list
for(int i=0;i< m.getData().size();i++){
Object object = m.getData().get(i);
dlist.get(i).add(object);
}
dcount++;
}
else if(message instanceof StreamDelimiterMessage){
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
if(m.getNumber()==0){
if(dsize<dcount){
dsize=dcount;
}
dcount=0;
}
}
// Read next message
message = queue.getQueue().take();
}
// Open file
BufferedWriter writer = new BufferedWriter(new FileWriter(outfile));
// Create text images
for(int t=0; t<dlist.size(); t++ ){
// Get component metadata
ComponentMetadata c = queue.getDataMessageMetadata().getComponents().get(t);
writer.write(c.getId()+"\n");
List<Object> list = dlist.get(t);
if(clist.get(t).isArray()){
// Array Handling
}
else if(clist.get(t).equals(Double.class)){
// Data is of type Double
StringBuffer b = new StringBuffer();
int counter = 0;
for(Object o: list){
b.append(o);
counter++;
if(counter==dsize){
b.append("\n");
counter=0;
}
else{
b.append(" ");
}
}
writer.write(b.toString());
}
writer.write("\n");
}
// Close file
writer.close();
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} catch (IOException e) {
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
}
}
}

View File

@@ -1,240 +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 ch.psi.fda.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.DataMessage;
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;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class DataSerializerTXTSplit implements DataSerializer{
private DataQueue queue;
private File file;
private int maxdim = 0;
// private boolean appendSuffix = false;
public DataSerializerTXTSplit(DataQueue queue, File file){
this.queue = queue;
this.file = file;
// Determine maximum dimension
for(ComponentMetadata m: queue.getDataMessageMetadata().getComponents()){
if(m.getDimension()>maxdim){
maxdim=m.getDimension();
}
}
if(maxdim<1){
throw new RuntimeException("Split serializer only supports data > 1 dimension");
}
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try{
// 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
List<String> header = new ArrayList<String>();
// Write header
StringBuffer b = new StringBuffer();
StringBuffer b1 = new StringBuffer();
b.append("#");
b1.append("#");
for(ComponentMetadata c: queue.getDataMessageMetadata().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());
List<String> data = new ArrayList<String>();
// Write data
// Read Message
Message message = queue.getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
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();
}
}
// Read next message
message = queue.getQueue().take();
}
// // Open file
// BufferedWriter writer = new BufferedWriter(new FileWriter(outfile));
//
// // Close file
// writer.close();
} catch (InterruptedException e) {
// TODO Stop loop and exit logic instead of throwing an Exception
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
} 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,74 +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 ch.psi.fda.core.messages.DataQueue;
/**
* @author ebner
*
*/
public class FilterSet {
private DataQueue queue;
private List<SeriesDataFilter> filters = new ArrayList<SeriesDataFilter>();
private String name;
public FilterSet(DataQueue queue){
this("", queue);
}
public FilterSet(String name, DataQueue queue){
this.queue = queue;
}
/**
* @return the queue
*/
public DataQueue getQueue() {
return queue;
}
/**
* @return the filters
*/
public List<SeriesDataFilter> getFilters() {
return filters;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,676 +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 org.jfree.data.xy.XYSeries;
import ch.psi.fda.core.messages.DataMessage;
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.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.JFreeMatrixPlot;
//import ch.psi.plot.xyz.JFreeMatrixPlotData;
//import ch.psi.plot.xyz.JFreeMatrixPlotMetadata;
import ch.psi.plot.xyz.MatrixPlot;
import ch.psi.plot.xyz.MatrixPlotData;
/**
* Serialize data received by a DataQueue
* @author ebner
*
*/
public class Visualizer {
// Logger
private static Logger logger = Logger.getLogger(Visualizer.class.getName());
private FilterSet filterSet = null;
private List<Plot> plots = new ArrayList<Plot>();
private Thread visualizationThread = null;
/**
* Terminate at end of stream
*/
private boolean terminateAtEOS = false;
private volatile boolean terminate = false;
private boolean updateAtStreamElement = true;
private boolean updateAtStreamDelimiter = true;
private boolean updateAtEndOfStream = false;
public Visualizer(DataQueue queue, List<Visualization> vl){
addFilterSet(queue, vl);
}
private void addFilterSet(DataQueue queue, List<Visualization> vl){
filterSet = mapVisualizations(queue, vl);
}
/**
* Visualize data
* Method blocks until visualization is done
*/
public void visualize() {
if(filterSet != null ){
DataQueue queue = filterSet.getQueue();
List<SeriesDataFilter> filters = filterSet.getFilters();
int ecount = 0;
boolean clearPlot = false;
terminate = false;
// Read Messages
Message message = null;
try {
message = queue.getQueue().take();
} catch (InterruptedException e) {
terminate = true;
// Reset interrupted status
Thread.currentThread().interrupt();
}
while ( (!Thread.currentThread().isInterrupted()) && (!terminate) ) {
if (message instanceof DataMessage) {
final DataMessage m = (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 = ((LinePlot) xyfilter.getPlot()).getData().getSeries(xyfilter.getCount()); // TODO Does not work with multiple series filter per plot !!!!
XYSeriesP series = xyfilter.getActualSeries(); // TODO Does not work with multiple series filter per plot !!!!
// series.add((Double) m.getData().get(xyfilter.getIndexX()), (Double) m.getData().get(xyfilter.getIndexY()));
// There might be other values than double in the data, therefore we have to check for it
Object dX = m.getData().get(xyfilter.getIndexX());
Object dY = m.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[]) m.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) m.getData().get(xyzfilter.getIndexX()),(Double) m.getData().get(xyzfilter.getIndexY()), (Double) m.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[]) m.getData().get(xyzfilter.getIndexZ());
double y = (Double) m.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);
}
}
}
} else if (message instanceof StreamDelimiterMessage) {
StreamDelimiterMessage ddm = (StreamDelimiterMessage) message;
for(SeriesDataFilter filter: filters){
if(filter instanceof XYSeriesDataFilter){
// Create new series
XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter;
if (ddm.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 (ddm.isIflag()) {
clearPlot = true;
}
} else if (message instanceof EndOfStreamMessage) {
ecount++;
if(terminateAtEOS){
terminate = true;
}
// 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();
}
}
}
}
// End loop if terminate flag is true
if(terminate){
break;
}
// Read next message
try {
message = queue.getQueue().take();
} catch (InterruptedException e) {
terminate = true;
// Reset interrupted status
Thread.currentThread().interrupt();
}
}
}
logger.info("End visualization");
}
/**
* Starts a visualization thread for this visualizer
*/
public void startVisualization(){
// Throw an exception if visualization is already running
if(visualizationThread!=null){
throw new IllegalStateException("Visualization already running");
}
visualizationThread = new Thread(new Runnable() {
@Override
public void run() {
visualize();
}
});
// Start thread
visualizationThread.start();
}
/**
* Stop visualization thread of this visualizer
* Waits until the visualiztion thread is stopped
* @throws InterruptedException
*/
public void stopVisualization() throws InterruptedException{
// Wait until visualiztion thread is stopped
visualizationThread.interrupt();
visualizationThread.join(10000); // Wait 10 seconds to have the visualization Thread to come to an end
visualizationThread = null;
}
/**
* 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 FilterSet mapVisualizations(DataQueue queue, List<Visualization> vl){
FilterSet fset = new FilterSet(queue);
List<SeriesDataFilter> filters = fset.getFilters();
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 = queue.getDataMessageMetadata().getIndex(idX);
int dimX = queue.getDataMessageMetadata().getComponents().get(indexX).getDimension();
List<Object> l = lp.getY();
for(Object o: l){
String idY = getId(o);
int indexY = queue.getDataMessageMetadata().getIndex(idY);
int dimY = queue.getDataMessageMetadata().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 = queue.getDataMessageMetadata().getIndex(idY);
int dimY = queue.getDataMessageMetadata().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 = queue.getDataMessageMetadata().getIndex(idX);
int indexY = queue.getDataMessageMetadata().getIndex(idY);
int indexZ = queue.getDataMessageMetadata().getIndex(idZ);
int dimX = queue.getDataMessageMetadata().getComponents().get(indexX).getDimension();
int dimY = queue.getDataMessageMetadata().getComponents().get(indexY).getDimension();
int dimZ = queue.getDataMessageMetadata().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 = queue.getDataMessageMetadata().getIndex(idY);
int indexZ = queue.getDataMessageMetadata().getIndex(idZ);
int dimY = queue.getDataMessageMetadata().getComponents().get(indexY).getDimension();
int dimZ = queue.getDataMessageMetadata().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 fset;
}
/**
* 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;
}
/**
* @param terminateAtEOS the terminateAtEOS to set
*/
public void setTerminateAtEOS(boolean terminateAtEOS) {
this.terminateAtEOS = terminateAtEOS;
}
/**
* @return the terminateAtEOS
*/
public boolean isTerminateAtEOS() {
return terminateAtEOS;
}
/**
* @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,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,236 +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.collector;
import static org.junit.Assert.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
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.core.collector.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;
/**
* @author ebner
*
*/
public class CollectorTest {
// Get Logger
private static Logger logger = Logger.getLogger(CollectorTest.class.getName());
class TestCollector implements Runnable{
private final DataQueue queue;
public TestCollector(DataQueue queue){
this.queue = queue;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
while(true){
Message m = queue.getQueue().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 BlockingQueue<Message> q1;
private BlockingQueue<Message> q2;
private BlockingQueue<Message> q3;
private DataMessageMetadata m1;
private DataMessageMetadata m2;
private DataMessageMetadata m3;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
// 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());
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.core.collector.Collector#run()}.
* @throws InterruptedException
*/
@Test
public void testRun() throws InterruptedException {
Collector collector = new Collector();
collector.getQueues().add(new DataQueue(q1, m1));
collector.getQueues().add(new DataQueue(q2, m2));
collector.getQueues().add(new DataQueue(q3, m3));
Thread t = new Thread(new TestCollector(collector.getOutQueue()));
t.start();
// Check component metadata of output queue
int c=2;
for(ComponentMetadata cm: collector.getOutQueue().getDataMessageMetadata().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--;
}
collector.run();
// Wait some time to ensure that collector was able to finish processing
Thread.sleep(2000);
// Execute collector via the ExecutorService framework
// ExecutorService executor = Executors.newCachedThreadPool();
// executor.execute(collector);
}
}

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,66 +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.util.logging.Logger;
import jcifs.smb.SmbFile;
import org.junit.Ignore;
import org.junit.Test;
/**
* @author ebner
*
*/
public class SambaTest {
private static final Logger logger = Logger.getLogger(SambaTest.class.getName());
@Test
public void testSamba() throws Exception{
// System.setProperty("jcifs.smb.client.dfs.disabled", "true");
// System.setProperty("jcifs.smb.client.ssnLimit", "1");
// System.setProperty("jcifs.smb.client.domain", "x05la.psi.ch");
// System.setProperty("jcifs.smb.client.username", "x05laop");
// System.setProperty("jcifs.smb.client.password", "mXAS");
//
// System.setProperty("jcifs.util.loglevel", "6");
// System.setProperty("jcifs.smb.lmCompatibility", "0");
// jcifs.smb.client.{domain,username,password
String smbShare = "";
// smbShare = "smb://x05laop:mXAS@x05la/x05laop/Data1/otfTmp/";
// smbShare = "smb://x05la.psi.ch/x05laop/Data1/otfTmp/";
// smbShare = "smb://x05laop:mXAS@x05la/x05laop/Data1/otfTmp/000000.txt.lock";
smbShare = "smb://:@yoke.psi.ch/nfs/";
// NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("x05laop:mXAS");
// SmbFile tmpDir = new SmbFile(smbShare,auth);
// SmbFile tmpDir = new SmbFile(smbShare);
// tmpDir.createNewFile();
// logger.info(""+tmpDir.exists());
// logger.info(""+tmpDir.isDirectory());
// SmbFile tmpFile = new SmbFile(tmpDir, "000000.txt.lock");
// tmpFile.exists();
}
}

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,153 +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.Ignore;
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,547 +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.manipulator;
import static org.junit.Assert.*;
import gov.aps.jca.CAException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import ch.psi.fda.TestChannels;
import ch.psi.fda.core.manipulator.JythonManipulation;
import ch.psi.fda.core.manipulator.Manipulation;
import ch.psi.fda.core.manipulator.Manipulator;
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.scripting.JythonParameterMapping;
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
import ch.psi.fda.core.scripting.JythonParameterMappingID;
import ch.psi.jcae.ChannelBean;
import ch.psi.jcae.ChannelBeanFactory;
/**
* @author ebner
*
*/
public class ManipulatorTest {
// Get Logger
private static Logger logger = Logger.getLogger(ManipulatorTest.class.getName());
/**
* @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.manipulator.Manipulator#Manipulator()}.
*/
@Test(expected=IllegalArgumentException.class)
public void testConstructor() {
DataMessageMetadata dmm = new DataMessageMetadata();
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
String id="computedId";
String script = "import math\ndef process(o):\n return math.cos(10.0) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
// This constructor need to throw an IllegalArgumentException as there is no component
// id "myid" which is expected in the mapping
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
new Manipulator(inQueue, manipulations);
}
@Test
public void testConstructorNoMappingNoParam() {
DataMessageMetadata dmm = new DataMessageMetadata();
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
m.getData().add(0.2d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process():\n return 0.0";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
new Manipulator(inQueue, manipulations);
// Expect IllegalArgument Exception as there is no mapping for the parameter c
}
@Test
public void testConstructorMappingNoParam() {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
dmm.getComponents().add(new ComponentMetadata("myid2"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
m.getData().add(0.2d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process():\n return 0.0";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
new Manipulator(inQueue, manipulations);
// Expect IllegalArgument Exception as there is no mapping for the parameter c
}
/**
* Test method for {@link ch.psi.fda.core.manipulator.Manipulator#Manipulator()}.
*/
@Test(expected=IllegalArgumentException.class)
public void testConstructorNoMapping() {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
dmm.getComponents().add(new ComponentMetadata("myid2"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
m.getData().add(0.2d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process(o ,c):\n return math.cos(c) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
new Manipulator(inQueue, manipulations);
// Expect IllegalArgument Exception as there is no mapping for the parameter c
}
/**
* Test method for {@link ch.psi.fda.core.manipulator.Manipulator#run()}.
* @throws InterruptedException
*/
@Test
public void testRun() throws InterruptedException {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process(o):\n return math.cos(10.0) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
Manipulator manipulator = new Manipulator(inQueue, manipulations);
// Check whether output queue message structur complies to expected one
DataMessageMetadata outMeta = manipulator.getOutQueue().getDataMessageMetadata();
// Test whether only the expected components are within the outgoing queue
if(outMeta.getComponents().size()!=2){
fail("There are more than the expected components in the outgoing message");
}
// Test whether the id of the first component matches the expected id
if(!outMeta.getComponents().get(0).getId().equals("myid")){
fail("Id of the first component does not match the expected id 'myid'");
}
// Test whether the id of the second component (which was computed) matches the expected id
if(!outMeta.getComponents().get(1).getId().equals("cid")){
fail("Id of the second component does not match the expected id 'cid'");
}
manipulator.run();
Message message = manipulator.getOutQueue().getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
logger.info(message.toString());
if(message instanceof DataMessage){
DataMessage dm = (DataMessage) message;
dm.getData().get(0);
double res = ((Double)dm.getData().get(1)) - (Math.cos(10.0)+Math.sin(((Double)dm.getData().get(0))));
if( Math.abs(res) > 0.000000001){
fail("Calculation failed");
}
}
message = manipulator.getOutQueue().getQueue().take();
}
logger.info(""+(Math.cos(10.0)+Math.sin(10)));
}
/**
* Test run that returns an integer
* @throws InterruptedException
*/
@Test
public void testRunIntegerReturn() throws InterruptedException {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process(o):\n return 1";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
Manipulator manipulator = new Manipulator(inQueue, manipulations);
// Check whether output queue message structur complies to expected one
DataMessageMetadata outMeta = manipulator.getOutQueue().getDataMessageMetadata();
// Test whether only the expected components are within the outgoing queue
if(outMeta.getComponents().size()!=2){
fail("There are more than the expected components in the outgoing message");
}
// Test whether the id of the first component matches the expected id
if(!outMeta.getComponents().get(0).getId().equals("myid")){
fail("Id of the first component does not match the expected id 'myid'");
}
// Test whether the id of the second component (which was computed) matches the expected id
if(!outMeta.getComponents().get(1).getId().equals("cid")){
fail("Id of the second component does not match the expected id 'cid'");
}
manipulator.run();
Message message = manipulator.getOutQueue().getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
logger.info(message.toString());
if(message instanceof DataMessage){
DataMessage dm = (DataMessage) message;
dm.getData().get(0);
}
message = manipulator.getOutQueue().getQueue().take();
}
}
/**
* Test method for {@link ch.psi.fda.core.manipulator.Manipulator#run()}.
* @throws InterruptedException
*/
@Ignore
@Test
public void testRunLongTimeTest() throws InterruptedException {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
final DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(1000), dmm);
Thread tf = new Thread(new Runnable() {
@Override
public void run() {
try{
for(Double i=0d;i<1000000;i++){
DataMessage m = new DataMessage();
m.getData().add(i);
inQueue.getQueue().put(m);
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// }
}
inQueue.getQueue().put(new EndOfStreamMessage());
}
catch(InterruptedException e){
e.printStackTrace();
}
}
});
String id="cid";
String script = "import math\ndef process(o):\n return math.cos(10.0) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
Manipulator manipulator = new Manipulator(inQueue, manipulations);
Thread t = new Thread(manipulator);
final DataQueue outQueue = manipulator.getOutQueue();
Thread tp = new Thread(new Runnable() {
@Override
public void run() {
try{
int count=0;
Message message;
while((message = outQueue.getQueue().take()) != null){
if(!(message instanceof EndOfStreamMessage)){
logger.info(count+" - "+message.toString());
}
else{
break;
}
count++;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
});
tf.start();
t.start();
tp.start();
tf.join();
t.join();
tp.join();
}
/**
* Test method for {@link ch.psi.fda.core.manipulator.Manipulator#run()}.
* @throws InterruptedException
*/
@Test
public void testRunMultipleParameter() throws InterruptedException {
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
dmm.getComponents().add(new ComponentMetadata("myid2"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
m.getData().add(0.2d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process(o ,c):\n return math.cos(c) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
mapping.add(new JythonParameterMappingID("c", "myid2"));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
Manipulator manipulator = new Manipulator(inQueue, manipulations);
// Check whether output queue message structur complies to expected one
DataMessageMetadata outMeta = manipulator.getOutQueue().getDataMessageMetadata();
// Test whether only the expected components are within the outgoing queue
if(outMeta.getComponents().size()!=3){
fail("There are more than the expected components in the outgoing message");
}
// Test whether the id of the first component matches the expected id
if(!outMeta.getComponents().get(0).getId().equals("myid")){
fail("Id of the first component does not match the expected id 'myid'");
}
if(!outMeta.getComponents().get(1).getId().equals("myid2")){
fail("Id of the first component does not match the expected id 'myid'");
}
// Test whether the id of the second component (which was computed) matches the expected id
if(!outMeta.getComponents().get(2).getId().equals("cid")){
fail("Id of the second component does not match the expected id 'cid'");
}
manipulator.run();
Message message = manipulator.getOutQueue().getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
logger.info(message.toString());
if(message instanceof DataMessage){
DataMessage dm = (DataMessage) message;
dm.getData().get(0);
double res = ((Double)dm.getData().get(2)) - (Math.cos(((Double)dm.getData().get(1)))+Math.sin(((Double)dm.getData().get(0))));
if( Math.abs(res) > 0.000000001){
fail("Calculation failed");
}
}
message = manipulator.getOutQueue().getQueue().take();
}
logger.info(""+(Math.cos(0.2)+Math.sin(10)));
}
/**
* Test method for {@link ch.psi.fda.core.manipulator.Manipulator#run()}.
* @throws InterruptedException
* @throws CAException
*/
@Test
public void testRunMultipleParameterAndChannel() throws InterruptedException, CAException {
Double setValue = 12.22;
ChannelBean<Double> cbean = ChannelBeanFactory.getFactory().createChannelBean(Double.class, TestChannels.ANALOG_OUT, false);
DataMessageMetadata dmm = new DataMessageMetadata();
dmm.getComponents().add(new ComponentMetadata("myid"));
dmm.getComponents().add(new ComponentMetadata("myid2"));
DataQueue inQueue = new DataQueue(new LinkedBlockingQueue<Message>(), dmm);
DataMessage m = new DataMessage();
m.getData().add(10d);
m.getData().add(0.2d);
inQueue.getQueue().add(m);
inQueue.getQueue().add(new EndOfStreamMessage());
String id="cid";
String script = "import math\ndef process(o ,c,d):\n d.setValue("+setValue+")\n print d.getValue()\n return math.cos(c) + math.sin(o)";
List<JythonParameterMapping> mapping = new ArrayList<JythonParameterMapping>();
mapping.add(new JythonParameterMappingID("o", "myid"));
mapping.add(new JythonParameterMappingID("c", "myid2"));
mapping.add(new JythonParameterMappingChannel("d", TestChannels.ANALOG_OUT, Double.class));
JythonManipulation manipulation = new JythonManipulation(id, script, mapping);
List<Manipulation> manipulations = new ArrayList<Manipulation>();
manipulations.add(manipulation);
Manipulator manipulator = new Manipulator(inQueue, manipulations);
// Check whether output queue message structur complies to expected one
DataMessageMetadata outMeta = manipulator.getOutQueue().getDataMessageMetadata();
// Test whether only the expected components are within the outgoing queue
if(outMeta.getComponents().size()!=3){
fail("There are more than the expected components in the outgoing message");
}
// Test whether the id of the first component matches the expected id
if(!outMeta.getComponents().get(0).getId().equals("myid")){
fail("Id of the first component does not match the expected id 'myid'");
}
if(!outMeta.getComponents().get(1).getId().equals("myid2")){
fail("Id of the first component does not match the expected id 'myid'");
}
// Test whether the id of the second component (which was computed) matches the expected id
if(!outMeta.getComponents().get(2).getId().equals("cid")){
fail("Id of the second component does not match the expected id 'cid'");
}
// Change something different on the channel than the value that will be set in the manipulator script
cbean.setValue(setValue+1);
manipulator.run();
Message message = manipulator.getOutQueue().getQueue().take();
while(!(message instanceof EndOfStreamMessage)){
logger.info(message.toString());
if(message instanceof DataMessage){
DataMessage dm = (DataMessage) message;
dm.getData().get(0);
double res = ((Double)dm.getData().get(2)) - (Math.cos(((Double)dm.getData().get(1)))+Math.sin(((Double)dm.getData().get(0))));
if( Math.abs(res) > 0.000000001){
fail("Calculation failed");
}
}
message = manipulator.getOutQueue().getQueue().take();
}
logger.info(""+(Math.cos(0.2)+Math.sin(10)));
// Check whether the channel was set correctly by the manipulator script
if(Math.abs(cbean.getValue()-setValue)>0.00000001){
fail("Channel was not set correctly in the manipulator script");
}
}
}

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,127 +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.deserializer;
import java.io.File;
import java.net.URI;
import java.net.URL;
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.core.messages.ComponentMetadata;
import ch.psi.fda.core.messages.ControlMessage;
import ch.psi.fda.core.messages.DataMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
/**
* @author ebner
*
* For testing whether the created MDA file is correct use following
* program on a SLS SL5 beamline console (or slslc05/06)
*/
public class DataDeserializerMDATest {
// Get Logger
private static Logger logger = Logger.getLogger(DataDeserializerMDATest.class.getName());
private DataDeserializerMDA deserializer;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
URL url = this.getClass().getClassLoader().getResource("testdata/mda/mdadata7.mda");
deserializer = new DataDeserializerMDA(new File(new URI(url.toString())));
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.deserializer.DataDeserializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRun() throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
BlockingQueue<Message> q = deserializer.getQueue().getQueue();
while(true){
Message m = q.take();
if(m instanceof DataMessage){
DataMessage x = (DataMessage) m;
logger.info( x.toString() );
}
else if(m instanceof ControlMessage){
if(m instanceof EndOfStreamMessage){
break;
}
logger.info("---- "+m.toString()+" ----");
}
}
StringBuilder b = new StringBuilder();
b.append("[");
StringBuilder b1 = new StringBuilder();
b1.append("[");
for(ComponentMetadata cm : deserializer.getQueue().getDataMessageMetadata().getComponents()){
b.append(" ");
b.append(cm.getId());
b1.append(" ");
b1.append(cm.getDimension());
}
b.append(" ]");
b1.append(" ]");
logger.info("Metadata "+b.toString());
logger.info("Metadata "+b1.toString());
} catch (InterruptedException e) {
logger.log(Level.SEVERE, "An Exception occured while reading data from the data queue", e);
}
}
});
Thread tt = new Thread(deserializer);
tt.start();
t.start();
tt.join();
t.join();
}
}

View File

@@ -1,235 +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.File;
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.StreamDelimiterMessage;
import ch.psi.fda.core.messages.EndOfStreamMessage;
import ch.psi.fda.core.messages.Message;
import ch.psi.fda.serializer.DataSerializer;
import ch.psi.fda.serializer.DataSerializerMAT;
import ch.psi.fda.serializer.DataSerializerMAT2D;
import ch.psi.fda.serializer.DataSerializerTXT;
import ch.psi.fda.serializer.DataSerializerTXT2D;
import ch.psi.fda.serializer.DataSerializerTXTSplit;
/**
* @author ebner
*
*/
public class DataSerializerTest {
private static final String tmpDirectory = "target/tmp";
private DataQueue queue;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
new File(tmpDirectory).mkdirs();
BlockingQueue<Message> q3 = new LinkedBlockingQueue<Message>();
DataMessageMetadata m3 = new DataMessageMetadata();
this.queue = new DataQueue(q3, m3);
}
/**
* Generate 1D data
* @throws InterruptedException
*/
private void generate1DData() throws InterruptedException{
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id0", 0));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id1", 0));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id2", 0));
// Dimension
DataMessage m = new DataMessage();
m.getData().add(0.000000000000000001);
m.getData().add(0.1);
m.getData().add(1d); // have this value as double
queue.getQueue().put(m);
m = new DataMessage();
m.getData().add(0.02);
m.getData().add(0.2);
m.getData().add(2d); // have this value as double
queue.getQueue().put(m);
queue.getQueue().put(new EndOfStreamMessage());
}
/**
* Generate 2D test data
* @throws InterruptedException
*/
private void generate2DData() throws InterruptedException{
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id0", 1));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id1", 0));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id2", 0));
for(double i=0;i<5;i++){
for(double t=0.1; t<10; t=t+0.1){
// Dimension
DataMessage m = new DataMessage();
m.getData().add(i);
m.getData().add(t);
m.getData().add(Math.log(t)); // have this value as double
queue.getQueue().put(m);
}
queue.getQueue().put(new StreamDelimiterMessage(0));
}
queue.getQueue().put(new StreamDelimiterMessage(1));
queue.getQueue().put(new EndOfStreamMessage());
}
/**
* Generate 3d test data
* @throws InterruptedException
*/
private void generate3DData() throws InterruptedException{
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id0", 2));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id1", 1));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id2", 0));
queue.getDataMessageMetadata().getComponents().add(new ComponentMetadata("id3", 0));
for(double z=30;z<36;z++){
for(double i=0;i<6;i++){
for(double t=0.1; t<1.1; t=t+0.1){
// Dimension
DataMessage m = new DataMessage();
m.getData().add(z);
m.getData().add(i);
m.getData().add(t);
m.getData().add(Math.log(t)); // have this value as double
queue.getQueue().put(m);
}
queue.getQueue().put(new StreamDelimiterMessage(0));
}
queue.getQueue().put(new StreamDelimiterMessage(1));
}
queue.getQueue().put(new StreamDelimiterMessage(2));
queue.getQueue().put(new EndOfStreamMessage());
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRunTXT() throws InterruptedException {
generate1DData();
DataSerializer serializer = new DataSerializerTXT(queue, new File(tmpDirectory+"/test.txt"), true);
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRunMAT() throws InterruptedException {
generate1DData();
DataSerializer serializer = new DataSerializerMAT(queue, new File(tmpDirectory+"/test.mat"));
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRunMAT2D() throws InterruptedException {
generate2DData();
DataSerializer serializer = new DataSerializerMAT2D(queue, new File(tmpDirectory+"/test-2d.mat"));
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRunTXT2D() throws InterruptedException {
generate2DData();
DataSerializer serializer = new DataSerializerTXT2D(queue, new File(tmpDirectory+"/test-2d.txt"));
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerTXT#run()}.
* @throws InterruptedException
*/
@Test
public void testRunSplitTXT() throws InterruptedException {
generate2DData();
DataSerializer serializer = new DataSerializerTXTSplit(queue, new File(tmpDirectory+"/test-2d-split.txt"));
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerMDA#run()}.
* @throws InterruptedException
*/
@Test
public void testRun2D() throws InterruptedException {
generate2DData();
DataSerializer serializer = new DataSerializerMDA(queue, new File(tmpDirectory+"/test-2d.mda"));
serializer.run();
}
/**
* Test method for {@link ch.psi.fda.serializer.DataSerializerMDA#run()}.
* @throws InterruptedException
*/
@Test
public void testRun3D() throws InterruptedException {
generate3DData();
DataSerializer serializer = new DataSerializerMDA(queue, new File(tmpDirectory+"/test-3d.mda"));
serializer.run();
}
}

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

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