Compare commits

...

80 Commits

Author SHA1 Message Date
a86fd00e59 Merge branch 'main' into 8.0.0.rc 2023-11-13 16:38:25 +01:00
24894667b7 release fw for ctb 2023-11-13 16:03:52 +01:00
4b414bfddb release notes 2023-11-12 15:39:58 +01:00
15d357d9ab release notes 2023-11-12 15:32:28 +01:00
f95de054f9 formatting 2023-11-12 15:29:34 +01:00
0aef8113dd documentation and examples 2023-11-12 15:11:36 +01:00
9785a41048 Merge branch '8.0.0.rc' of github.com:slsdetectorgroup/slsDetectorPackage into 8.0.0.rc 2023-11-10 17:29:47 +01:00
417e1a88a5 fixed doc 2023-11-10 17:29:35 +01:00
9c0dd0385d updating docs 2023-11-10 16:02:21 +01:00
5ab64efe3e added python 3.12 to the conda build variants 2023-11-10 14:18:38 +01:00
8f77e4d4fe added python 3.12 to the conda build variants 2023-11-10 14:17:40 +01:00
41c5b75b10 trigger signal issues handled at acquire (#862)
* if blocking and handling sync, only master gets blocking acq, slaves get non blocking as they are first and so dont get status or error caught when slaves dont get trigger (due to not connected etc) and acq returns with slaves still in waiting status. so check status of all in blocking acq

* for all dets with sync, ensure atleast one master when starting acq

* docs updated about sync
2023-11-10 11:24:18 +01:00
bfe53c6693 udpated release notes 2023-11-09 15:10:17 +01:00
f7997dd09a 8.0.0.rc: fix server logic in checking detector idle (#860)
* fix buggy logic in checking detector idle and an argument check
2023-11-09 15:07:03 +01:00
c64e87a2b6 7.0.3.rc: fix server logic in checking detector idle (#859)
* fix buggy logic in checking detector idle and an argument check
2023-11-09 14:21:11 +01:00
5eeb8e29c1 project version change 2023-11-08 17:31:29 +01:00
09697fa325 updated release notes 2023-11-08 17:30:07 +01:00
90b4daef39 updated release notes 2023-11-08 17:28:48 +01:00
2082f1eee7 updated release notes 2023-11-08 17:28:17 +01:00
d3a636b563 updated release notes 2023-11-08 17:24:56 +01:00
50b9b6ca39 update release notes 2023-11-08 14:14:04 +01:00
e86b57cdfc versioning, format, release notes, update test simulator (no need for psutil) 2023-11-08 12:12:17 +01:00
14e11e8b5b formatting and versioning 2023-11-08 11:43:09 +01:00
beafe86554 execute command inside server fixed (from fix simulator tests and exec command PR) (#856) 2023-11-08 09:26:00 +01:00
af3dc1e7f4 7.0.3.rc: execute command inside server fixed (from fix simulator tests and exec command PR) (#855)
* execute command inside server fixed (from fix simulator tests and exec command PR)
2023-11-08 09:25:52 +01:00
573177203b formatting 2023-11-07 14:51:15 +01:00
a3ca9ebce5 updating release notes 2023-11-07 14:35:42 +01:00
8174fc9691 Update RELEASE.txt 2023-11-07 12:34:10 +01:00
d6eac6da71 updated release notes 2023-11-07 11:22:09 +01:00
56c7ae4852 8.0.0.rc: fix py virtual test (#841)
* fix virtual test when it fails

* catching errors in tests and removing sigchild ignore so servers (process in background) executing commands will not fail (pclose no child processes, if sigchld is ignored) fixed

* uncommented python loading config

* somehow killal slsReciever in second detector test fails even though no receiver running

* fixing script for virtual simlator test:fixed issue with check if process running, fixed moench tests
2023-11-07 09:30:24 +01:00
9b9b09ceaf 703rc/tests/fix execute command (#842)
* fix execute command
* fix for tests for ctb
2023-11-07 09:29:48 +01:00
cfebaee2a5 handling inconsistent fnums to be -1 in gui, so when one sets 0 (change of value) will also give an exception (#853) 2023-11-06 16:11:40 +01:00
4613c54f57 handling inconsistent fnums to be -1 in gui, so when one sets 0 (change of value) will also give an exception (#852) 2023-11-06 16:11:25 +01:00
51f9d6f011 8.0.0rc: : gui acq finished callback for different status (#851)
* fix acquisition finished status to have different status for different modules, but does not have to be error. for eg. jf sync fw (2.4.1 gives idle for master and stopped for slaves when stopping acquiistion)
2023-11-06 16:08:23 +01:00
58ac7ac280 7.0.3.rc: gui acq finished callback for different status (#847)
* fix acquisition finished status to have different status for different modules, but does not have to be error. for eg. jf sync fw (2.4.1 gives idle for master and stopped for slaves when stopping acquiistion)
2023-11-06 16:07:38 +01:00
82edfa75d3 7.0.3.rc: process the raw data files as a list (#848)
* Added file list option for moenchRawDataProcess
2023-11-03 12:10:20 +01:00
35ed926047 formatting 2023-10-25 09:36:51 +02:00
4023ed0775 updated versioning 2023-10-25 09:36:04 +02:00
b6ef3bc39e updated release notest 2023-10-25 09:15:10 +02:00
2035666792 versioning and binaries updated 2023-10-25 08:43:23 +02:00
1ff4d806e7 minor 2023-10-25 08:25:02 +02:00
3861379653 updated release notes 2023-10-24 17:39:47 +02:00
91140bbb71 formatting 2023-10-24 11:17:18 +02:00
a5632fcbea fix warning for prev_val (variable size array) in tests (#837) 2023-10-23 15:55:13 +02:00
d44329117d fix warning for prev_val (variable size array) in tests (#836) 2023-10-23 15:52:59 +02:00
4a454aa698 tests for jf (#835) 2023-10-19 16:55:29 +02:00
0e43072db8 eiger required fw version to 32: fix for blocking trigger in quad (#833) 2023-10-18 17:04:26 +02:00
6c67025ea8 7.0.3.rc eiger: fw version to 32 (quad blocking trigger) (#832)
* eiger required fw version to 32: fix for blocking trigger in quad
2023-10-18 16:51:17 +02:00
e5ee27dbfa 8.0.0.rc jf: reconfigure chip when touching electron collection mode bit (#830)
* jf: if bit 14 in reg 0x5d (electron mode collection bit) is changed, configure chip if v1.1 and powered on. so touch writeregister (setbit/clearbit also calls write register in the end). replace when electroncollectionmode command introduced
2023-10-18 10:49:44 +02:00
601249cc71 8.0.0.rc jf: change status reg bits (#828)
* rewrite of status reg bits, waiting state includes both wati for trigger and start frame, blocking trigger only waits if its not in waiting for trigger and run busy enabled, error state connected in firmware
2023-10-18 10:36:56 +02:00
ff60b8c379 8.0.0.rc: jf sync: stopping master gives idle (#823)
* jf sync mode master could return idle when stopped and so not all modules return the same value and must check for 'stopped or idle', Also must throw if any of the module gives an error

* added contains_only to sls::Result (#827)

* added variadic template for checking if a result contains only specified values

* fix for gcc4.8

* renamed to Result::contains_only

* stop on only the positions

---------

Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com>
2023-10-13 15:25:19 +02:00
37ce3d6f59 7.0.3.rc: jf sync: stopping master gives idle (#822)
* jf sync mode master could return idle when stopped and so not all modules return the same value and must check for 'stopped or idle', Also must throw if any of the module gives an error ( not jungfrau, but eiger could)

* added contains_only to sls::Result (#827)

* added variadic template for checking if a result contains only specified values

* fix for gcc4.8

* renamed to Result::contains_only

* stop on only the positions

---------

Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com>
2023-10-13 12:27:43 +02:00
bf26533fd8 8.0.0.rc: jf fix pedestal (#820)
* jf pedestal fix: touch enable bit last
2023-10-05 10:28:51 +02:00
7106273521 update 2d gain plot (if no x and ymin/max changes or window resizing): setFixedWidth was updating for window resize, updated virtual servers for g2 and jungfrau to keep changing gain and data for every frame (#817) 2023-10-03 17:22:14 +02:00
1484d038de 7.03.rc: update 2d gain plot color map (if no x and ymin/max changes or window resizing): setFixedWidth was updating for window resize, updated virtual servers for g2 and jungfrau to keep changing gain and data for every frame. the data value (#818) 2023-10-03 17:22:03 +02:00
fb0090c79e removing the misleading word 'Simulating' when programmig fpga (#814) 2023-09-28 16:20:59 +02:00
adc68cd519 formatting 2023-09-28 15:51:40 +02:00
1566eef247 703rc/fix numeric limits (#812)
* fixed compilation for fedora for numeric_limits

* formatting
2023-09-28 10:49:02 +02:00
e7cd90db78 fixed crashing of moench03RawDataProcess when nframes>0 (#810) 2023-09-27 09:22:40 +02:00
45414149fe binaries in for the previous PR 2023-09-22 15:59:35 +02:00
48759f440e 703rc/fix port size (#802)
* validate port numbers in client

* validate port numbers created at virtual servers and receiver process as tcp ports
2023-09-18 08:59:53 +02:00
b367b7e431 fixed some interpolation issues (#796) 2023-08-28 13:38:19 +02:00
f0b2a6f6f9 update release notes 2023-08-25 14:02:50 +02:00
f761046bfc updated docs and versions 2023-07-12 16:50:13 +02:00
1a859b83db formatting 2023-07-12 16:06:31 +02:00
70bfc875a6 updating release notes 2023-07-11 17:02:27 +02:00
c0755308a4 updating release notes 2023-07-11 17:01:14 +02:00
ab5509e10c updating release notes 2023-07-11 17:00:42 +02:00
004cb26646 updated firmware versions for 7.0.2 2023-07-10 12:21:19 +02:00
a4f47a5945 synced master status running when setting to slave (#747)
* jf: unsync before setting master/slave and then sync (if it was set) to overcome master going into running state when making it a slave and synced

* add tests for this condition

* updated release notes, updated min fw version requirement for v1.0 boards
2023-05-25 11:04:05 +02:00
312f3f473d fix that only master starts second and not all (for start acq), typo with pos and masters list (#743) 2023-05-11 10:20:17 +02:00
5871086cd6 formatting 2023-05-08 17:04:04 +02:00
6a0fe823b3 enable fix g0 when in expert mode (when gain mode enabled and not just visible) (#736) 2023-05-08 14:20:21 +02:00
5912aae53e Rx roi zmq (#726)
adding rx_roi also in the zmq header for external guis to put the "yellow box".. sending full roi instead of -1, and sending for each zmq port. "(multiple yellow boxes)".
2023-05-08 12:23:05 +02:00
8833ccf5cc 7.0.2.rc (#721)
* row and column for jungfrau mixed up

* multi module jungfrau sync must do slaves first then master for start acquisition and send software trigger, and master first and then slaves for stopacquisition

* non blocking to slaves first and only then blocking/nonblocking to the master for sending software trigger(jungfrau multi mod sync)

* fixed get/set timing jungfrau when sync enabled, getsync during blocking acquire (for trigger or stop) will get stuck as it should ask the stop server

* switching between 1 and 2 interfaces did not set gui/client zmq port properly. Resulted in dummy streaming forever. fixed

* formatting, refactoring: const & for positions, multi mod M3 stop first master first

* adding missing cstdint for gcc 13

* Refactoring handle sync out, handling synchronization also for softwaretrigger for m3, for start/sync/stop for g2/g1

---------

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
2023-05-08 12:11:19 +02:00
77c558a7be formatting 2023-03-24 12:54:55 +01:00
378fc301b8 updating client version, release version and project_version in CMakeLists.txt 2023-03-23 15:43:17 +01:00
87d6e16090 7.0.1 fix det server version (#702)
* check server version before initial checks, catch old server version exception, get old server version as 64 bit and print it along with exception
2023-03-23 15:37:01 +01:00
2ef021041c rx_arping sigchld (#701)
* rx_arping pclose gave -1 due to sigchld being ignored, fixed with sig handler doing a wait
2023-03-23 13:58:40 +01:00
574127b5ac fix hdf5 compilation using det spec fields in header (#700)
* fix hdf5 compilation using det spec fields in header
2023-03-23 12:30:38 +01:00
72 changed files with 1068 additions and 434 deletions

View File

@ -2,7 +2,7 @@
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.14)
project(slsDetectorPackage) project(slsDetectorPackage)
set(PROJECT_VERSION 7.0.0) set(PROJECT_VERSION 8.0.0)
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")

View File

@ -1,36 +1,264 @@
SLS Detector Package Major Release 7.x.x released on xx.xx.2023 SLS Detector Package Major Release 8.0.0 released on 13.11.2023
=============================================================== ===============================================================
This document describes the differences between v7.x.x and v7.0.2 This document describes the differences between v8.0.0 and v7.0.3
CONTENTS CONTENTS
-------- --------
1 New, Changed or Resolved Features 1 Compilation Changes
1.1 Compilation 2 New or Changed Features
1.2 Callback 2.1 Breaking API
1.3 Python 2.2 Resolved or Changed Features
1.4 Client 2.3 New Features
1.5 Detector Server 3 On-board Detector Server Compatibility
1.6 Simulator 4 Firmware Requirements
1.7 Receiver 5 Kernel Requirements
1.8 Gui 6 Download, Documentation & Support
2 On-board Detector Server Compatibility
3 Firmware Requirements
4 Kernel Requirements
5 Download, Documentation & Support
1 New, Changed or Resolved Features 2 Compilation Changes
=====================
* Minimum CMake version changed from 3.12 to 3.14
* Internal zmq lib
Building zmq from tar file in repo (libs/libzmq/libzmq-4.3.4.tar.gz),
but added option (SLS_FETCH_ZMQ_FROM_GITHUB) to pull zmq version (v4.3.4)
from github (https://github.com/zeromq/libzmq.git)
* Internal pybind11 lib
Building pybind11 from tar file in repo (libs/pybind11/v2.11.0.tar.gz),
but added option (SLS_FETCH_PYBIND11_FROM_GITHUB) to pull pybind11 version
(v2.11.0) from github (https://github.com/pybind/pybind11)
2 New, Changed or Resolved Features
===================================== =====================================
- moench being made compatible with jungfrau 2.0 boards (jungfrau structure, away from ctb)
- eiger febl and feb in versions 2.1 Breaking API
- fix ctb slow adcs ==================
Firmware
--------
* [Jungfrau] Status register and Sync mode fix
The regiser bit definition changed and fixes for stable control in sync mode.
Effect: Master and slaves give same status (previously master is sometimes 'idle' when acquisition is stopped), same #frames left and #nextframenumber.
Also ERROR status connected, but never noticed to occur.
For user, everything is transparent unless one touches status register
using advanced commands.
* [Moench] Status: Development mode
Moench is now being made compatible with Jungfrau v2.0 readout boards.
Hence, firmware and software is in development mode.
7.x.x will continue to have fixes for Moench until this version is deployed.
* [Ctb] Fixes and features described later on.
Client
======
* Datatype change of port numbers from int to uint16_t
API: setVirtualDetectorServers,
get/setRxPort, get/setControlPort, get/setStopPort,
get/setDestinationUDPPort(2), get/setRxZmqPort, get/setClientZmqPort
* [Eiger] versions, hardware version, febl/r firmware version
Versions command modified to give more info about hardware version ['fx30', 'fx70'] and Febl/r firmware versions.
Command line: versions (output modified), hardwareversion (added for Eiger)
API added for Eiger: getHardwareVersion, getFrontEndFirmwareVersion
Enums added: fpgaPosition {FRONT_LEFT, FRONT_RIGHT}
* [Ctb] Voltage->Power name change
Command line: voltagelist ->powerlist
API: get/setVoltage -> get/setPower, get/setVoltageList -> get/setPowerList,
getMeasuredVoltage -> getMeasuredPower
2.2 Resolved or Changed Features
================================
Detector Server
---------------
* Set bit and clear bit validation
Previously, validation expected all the other bits in the register to
not change. Now, it only validates the selected bit.
* [Jungfrau] Electron collection mode (bit 14 of 0x5D register)
Affected Command line: setbit, clearbit, reg
Affected API: setBit, clearBit, writeRegister
Electron collection mode and requires chip reconfiguration.
Temporary fix added that touching this bit will reconfigure chip if chip
is v1.1 and powered on. Permanent fix by introducing a command for the
same in future release.
* [Ctb] Fixes
- Patioctrl, patsetbit, patbitmask
MSB (64 bit unsigned) could not be set as a value of -1 was interpreted
as a 'get'. Fixed in server.
- Allow dac tristate when v_limit is set. Fixed.
- Changing fw bit from disable analog to enable analog
- Allow adc enable for 1 GbE and 10GbE to be 0.
- Slow ADCs previously misread (a high 5k+ value). Firmware updated
and software adjusted now.
- Allow non blocking acquire for 1GbE. Added Transmitting status when it
might still be reading from fifo.
- Clean memory before reading from fifo in 1GbE mode. Read fifo then
RD strobe (corresponding firmware fix) fixes number of reads, but
increases all pipelines by 1.
- Fixed pattern viewer (auto legend buf without wait and loop), allow
pyat files. (/patterngenerator)
Simulator
---------
* Unique TCP port for multiple simulators
Checks include unique TCP port-hostname combo.
Receiver
--------
* Unique TCP port for multiple receivers
7.x.x already has automatically increasing TCP ports in shared memory
for multiple receivers. Now, checks include unique TCP port-hostname
combo.
* [Ctb] Fixes
- Readout mode updated
'rx_hostname' should configure the receiver with parameters from detector,
but readout mode in receiver always configured at start up to Analog only.
Fixed.
- Incorrect image size in zmq header, which happens when dbit list is
less than 64 bits. Fixed.
- Rearranging digital data when dbit list less than 64 bits fixed.
Client
------
* [Jungfrau][Mythen3][Gotthard2] Sync mode should have at least one master
Multi module synced detectors should have at least one master when
starting acquisition, else it will throw. Once master is done acquiring
(blocking mode), status of all modules checked to ensure none of the
slaves in waiting due to hardware issues such as cabling.
2.3 New Features
================
Client
------
* [Jungfrau] Pedestal mode
Command line: pedestalmode
API: get/setPedestalMode
Example:
pedestalmode 0 # turns off pedestal mode
pedestalmode 50 10 # turns on pedestal mode (50 pedestal frames, 10 loops)
In pedestal mode, number of frames/triggers
is overwritten by '#pedestal_frames x #pedestal_loops x 2'.
In auto timing mode or trigger mode with #frames > 1, #frames is overwritten
with #triggers is 1. Otherwise, #triggers is overwritten with #frames is 1.
In pedestal mode, one cannot set #frames, #triggers or timing mode (exception).
Disabling pedestal mode will set back to normal mode with normal previous
values of #frames and #triggers.
* Source UDP IP: Auto
Command line: udp_srcip, udp_srcip2
API: get/setSourceUDPIP(2)
Allow 'auto' for udp_srcip to pick up IP from detector hostname. Not allowed
for Gotthard1.
* Custom row and column for detector UDP header
Command line: row, column
API: get/setRow, get/setColumn
By default, row and column of module is determined in a pre-determined
manner or by custom detector size (Command line: detsize).
This is useful if user accesses row and column in multi- detector UDP header
or for the GUI to rearrange for complete image.
Option now added to set custom row and column.
* [Ctb] Features
- List for ADC, signal, power, slowadc
Also allow their list to set names and to obtain their indices and values.
Command line: dacname, dacindex,
adclist, adcname, adcindex,
signallist, signalname,signalindex,
powerlist, powername, powerindex, powervalues,
slowadclist, slowadcname, slowadcindex, slowadcvalues
API: get/setDacName, getDacIndex,
get/setAdcNames, getAdcIndex, get/setAdcName,
get/setSignalNames, getSignalIndex, get/setSignalName,
get/setPowerNames, getPowerIndex, get/setPowerName, getPowerList,
get/setSlowADCNames, getSlowADCIndex, get/setSlowADCName, getSlowADCList
- Added more modes for transceiver in read out mode.
Allow to set number of samples and enable mask for transceiver.
Command line: romode (more modes: 'transceiver', 'digital_transceiver'),
tsamples, transceiverenable
API: get/setTransceiverEnableMask, get/setNumberOfTransceiverSamples,
get/setReadoutMode (more enums: TRANSCEIVER_ONLY, DIGITAL_AND_TRANSCEIVER)
- Command to get file name with path of last pattern uploaded.
Command line: patfname
API: getPatterFileName
* Automatic test script for all virtual simulators added.
@ -38,13 +266,13 @@ This document describes the differences between v7.x.x and v7.0.2
========================================== ==========================================
Eiger 7.0.0 Eiger 8.0.0
Jungfrau 7.0.2 Jungfrau 8.0.0
Mythen3 7.0.0 Mythen3 8.0.0
Gotthard2 7.0.0 Gotthard2 8.0.0
Gotthard 7.0.0 Gotthard 8.0.0
Moench 7.0.0 Moench 8.0.0
Ctb 7.0.0 Ctb 8.0.0
On-board Detector Server Upgrade On-board Detector Server Upgrade
@ -65,21 +293,21 @@ This document describes the differences between v7.x.x and v7.0.2
======================== ========================
Eiger 20.02.2023 (v31) Eiger 02.10.2023 (v32) (updated in 7.0.3)
Jungfrau 04.11.2022 (v1.4, HW v1.0) Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0)
03.11.2022 (v2.4, HW v2.0) 21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0)
Mythen3 24.01.2023 (v1.4) Mythen3 24.01.2023 (v1.4) (updated in 7.0.0)
Gotthard2 23.11.2022 (v0.3) Gotthard2 23.11.2022 (v0.3) (updated in 7.0.0)
Gotthard 08.02.2018 (50um and 25um Master) Gotthard 08.02.2018 (50um and 25um Master)
09.02.2018 (25 um Slave) 09.02.2018 (25 um Slave)
Moench 05.12.2022 (v0.3) Moench 10.07.2023 (v0.3.2) (updated in 8.0.0, under development)
Ctb 03.04.2023 (v1.2?) Ctb 28.08.2023 (v1.2) (updated in 8.0.0)
Detector Upgrade Detector Upgrade

2
cmk.sh
View File

@ -26,7 +26,7 @@ CMAKE_PRE=""
CMAKE_POST="" CMAKE_POST=""
usage() { echo -e " usage() { echo -e "
Usage: $0 [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of threads>] [-k <CMake command>] [-l <Install directory>] [m] [n] [-p] [r] [s] [t] [u] [z] Usage: $0 [-b] [-c] [-d <HDF5 directory>] [-e] [-g] [-h] [-i] [-j <Number of threads>] [-k <CMake command>] [-l <Install directory>] [-m] [-n] [-p] [-r] [-s] [-t] [-u] [-z]
-[no option]: only make -[no option]: only make
-b: Builds/Rebuilds CMake files normal mode -b: Builds/Rebuilds CMake files normal mode
-c: Clean -c: Clean

View File

@ -2,7 +2,6 @@ python:
- 3.8 - 3.8
- 3.9 - 3.9
- 3.10 - 3.10
- 3.11 - 3.11
- 3.12
numpy:
- 1.17

View File

@ -19,7 +19,7 @@ A minimal CMakeLists.txt could look like this:
.. code-block:: cmake .. code-block:: cmake
project(myDetectorIntegration) project(myDetectorIntegration)
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.14)
add_subdirectory(slsDetectorPackage) add_subdirectory(slsDetectorPackage)
#Add your executable #Add your executable
@ -43,7 +43,7 @@ should be needed, otherwise specify cmake prefix path.
.. code-block:: cmake .. code-block:: cmake
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.14)
project(myintegration) project(myintegration)
find_package(slsDetectorPackage 5.0 REQUIRED) find_package(slsDetectorPackage 5.0 REQUIRED)

View File

@ -13,24 +13,36 @@ To use the basic building blocks, meaning sls_detector_get/put and
the shared libraries these are needed: the shared libraries these are needed:
* Linux, preferably recent kernel (currently no cross platform support) * Linux, preferably recent kernel (currently no cross platform support)
* CMake > 3.12 * CMake >= 3.14
* C++11 compatible compiler. (We test with gcc and clang) * C++11 compatible compiler. (We test with gcc and clang)
* ZeroMQ version 4
-----------------------
GUI
-----------------------
* Qt 5.9
* Qwt 6.1.5 (packaged in libs/)
----------------------- -----------------------
Python bindings Python bindings
----------------------- -----------------------
* Python > 3.6 * Python > 3.6
* pybind11 (packaged in libs/) * pybind11 2.11.0 (packaged in libs)
.. note ::
Refer :ref:`pybind11 notes. <pybind for different slsDetectorPackage versions>`
-----------------------
ZeroMQ
-----------------------
* Zeromq 4.3.4 (packaged in libs)
.. note ::
Refer :ref:`zeromq notes. <zeromq for different slsDetectorPackage versions>`
-----------------------
GUI
-----------------------
* Qt 5.9
* Qwt 6.1.5 (packaged in libs)
----------------------- -----------------------
Moench executables Moench executables
@ -54,4 +66,6 @@ Packaged in libs/
* catch2 (unit testing) * catch2 (unit testing)
* rapidjson (streaming from receiver) * rapidjson (streaming from receiver)
* pybind11 (python bindings) * pybind11 (python bindings)
* qwt (gui plotting)
* libzmq (streaming to/from receiver)

View File

@ -1,16 +1,19 @@
Detector Detector
============================================== ==============================================
The sls::Detector is the new public API to control The sls::Detector is the public API to control
detectors from C++. This API is also used internally detectors from C++. This API is also used internally
for the Python bindings and the command line interface. for the Python bindings and the command line interface.
If a receiver has been configured this is also controlled If a receiver has been configured, this is also controlled
through this class. through this class.
Most, if not all, functions are called in parallel Most, if not all, functions are called in parallel
and the return value is a thin std::vector wrapper and the return value is a thin std::vector wrapper
containing results from all modules. (Result<T>) containing results from all modules. (:ref:`Result class<Result Class>`)
Here are some :ref:`examples <Cplusplus Api Examples>` on how to use the API.
.. _Cplusplus Api Examples:
.. doxygenclass:: sls::Detector .. doxygenclass:: sls::Detector
:members: :members:
:undoc-members: :undoc-members:

View File

@ -1,3 +1,4 @@
.. _Cplusplus Api Examples:
@ -53,8 +54,8 @@ then set up the detector.
jungfrauDetectorServer_virtual jungfrauDetectorServer_virtual
This launches a virtual Jungfrau detector server. As default is uses port 1952 and 1953 This launches a virtual Jungfrau detector server. As default it uses port 1952 and 1953
for communication over TCP. Most commands go on 1952 and only stop and status on 1953. for communication over TCP. Most commands go on 1952 and only a few such as stop and status on 1953.
**Run example to configure** **Run example to configure**
@ -90,7 +91,10 @@ std::vector.
sls::Result<int> res1{1, 1, 1}; sls::Result<int> res1{1, 1, 1};
std::cout << "res1: " << res1 << '\n'; std::cout << "res1: " << res1 << '\n';
res1.squash(); res1.squash();
# return -1 if different
res1.squash(-1); res1.squash(-1);
# throw exception with custom message if different
res1.tsquash("Values are different);

View File

@ -120,7 +120,7 @@ Program from console
# removes old server from respawn, sets up new lnked server to respawn # removes old server from respawn, sets up new lnked server to respawn
# programs fpga, reboots # programs fpga, reboots
# v5.0.0 - 6.0.0 (copies server from tftp folder of the pc) # older versions: v5.0.0 - 6.0.0 using tftp from tftp folder of pc
sls_detector_put update jungfrauDetectorServervxxx pcxxx xx.pof sls_detector_put update jungfrauDetectorServervxxx pcxxx xx.pof
# v6.1.1 - present (copies server from the full path provided) # v6.1.1 - present (copies server from the full path provided)
@ -190,7 +190,7 @@ Program from console
# removes old server from respawn, sets up new lnked server to respawn # removes old server from respawn, sets up new lnked server to respawn
# programs fpga, reboots # programs fpga, reboots
# v5.0.0 - 6.0.0 (copies server from tftp folder of the pc) # older versions: v5.0.0 - 6.0.0 using tftp from tftp folder of pc
sls_detector_put update mythen3DetectorServervxxx pcxxx xxx.rbf sls_detector_put update mythen3DetectorServervxxx pcxxx xxx.rbf
# v6.1.1 - present (copies server from the full path provided) # v6.1.1 - present (copies server from the full path provided)
@ -224,7 +224,7 @@ Program from console
# removes old server from respawn, sets up new lnked server to respawn # removes old server from respawn, sets up new lnked server to respawn
# programs fpga, reboots # programs fpga, reboots
# v5.0.0 - 6.0.0 (copies server from tftp folder of the pc) # older versions: v5.0.0 - 6.0.0 using tftp from tftp folder of pc
sls_detector_put update gotthard2DetectorServervxxx pcxxx xxx.rbf sls_detector_put update gotthard2DetectorServervxxx pcxxx xxx.rbf
# v6.1.1 - present (copies server from the full path provided) # v6.1.1 - present (copies server from the full path provided)
@ -275,7 +275,7 @@ Program from console
# removes old server from respawn, sets up new lnked server to respawn # removes old server from respawn, sets up new lnked server to respawn
# programs fpga, reboots # programs fpga, reboots
# v5.0.0 - 6.0.0 (copies server from tftp folder of the pc) # older versions: v5.0.0 - 6.0.0 using tftp from tftp folder of pc
sls_detector_put update moenchDetectorServervxxx pcxxx xx.pof sls_detector_put update moenchDetectorServervxxx pcxxx xx.pof
# v6.1.1 - present (copies server from the full path provided) # v6.1.1 - present (copies server from the full path provided)
@ -310,7 +310,7 @@ Program from console
# removes old server from respawn, sets up new lnked server to respawn # removes old server from respawn, sets up new lnked server to respawn
# programs fpga, reboots # programs fpga, reboots
# v5.0.0 - 6.0.0 (copies server from tftp folder of the pc) # older versions: v5.0.0 - 6.0.0 using tftp from tftp folder of pc
sls_detector_put update ctbDetectorServervxxx pcxxx xx.pof sls_detector_put update ctbDetectorServervxxx pcxxx xx.pof
# v6.1.1 - present (copies server from the full path provided) # v6.1.1 - present (copies server from the full path provided)

View File

@ -8,8 +8,8 @@ Welcome to slsDetectorPackage's documentation!
.. note :: .. note ::
This is the documentation for the latest development version of slsDetectorPackage This is the documentation for the latest development version of slsDetectorPackage.
For documentation on current and previous releases visit the official page: https://www.psi.ch/en/detectors/documentation For further documentation, visit the official page: https://www.psi.ch/en/detectors/documentation
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1

View File

@ -57,7 +57,6 @@ We have three different packages available:
Build from source Build from source
------------------- -------------------
1. Download Source Code from github 1. Download Source Code from github
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -65,23 +64,9 @@ Build from source
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 6.1.1 git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 6.1.1
.. note ::
| **Pybind for Python** For v6.x.x of slsDetectorPackage and older, refer :ref:`pybind11 notes on cloning. <pybind for different slsDetectorPackage versions>`
| v7.0.0+:
| pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
| Older versions:
| pybind11 is a submodule. Must be cloned using "recursive" and updated when switching between versions using the following commands.
.. code-block:: bash
# clone using recursive to get pybind11 submodule
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
# update submodule when switching between releases
cd slsDetectorPackage
git submodule update --init
.. _build from source using cmake: .. _build from source using cmake:
@ -118,20 +103,23 @@ Instead of the cmake command, one can use ccmake to get a list of options to con
ccmake .. ccmake ..
# choose the options # choose the options
# first press [c] - configure # first press [c] - configure (maybe multiple times till you see [g])
# then press [g] - generate # then press [g] - generate
=============================== ===============================
=============================== ===========================================
Example cmake options Comment Example cmake options Comment
=============================== =========================================== =============================== ===============================
-DSLS_USE_PYTHON=ON Python -DSLS_USE_PYTHON=ON Python
-DPython_FIND_VIRTUALENV=ONLY Python from only the conda environment -DPython_FIND_VIRTUALENV=ONLY Python from the conda env
-DZeroMQ_HINT=/usr/lib64 Use system zmq instead
-DSLS_USE_GUI=ON GUI -DSLS_USE_GUI=ON GUI
=============================== =========================================== -DSLS_USE_HDF5=ON HDF5
-DSLS_USE_SIMULATOR=ON Simulator
=============================== ===============================
.. note ::
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
Build using in-built cmk.sh script Build using in-built cmk.sh script
@ -142,9 +130,9 @@ Build using in-built cmk.sh script
The binaries are generated in slsDetectorPackage/build/bin directory. The binaries are generated in slsDetectorPackage/build/bin directory.
Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of threads>] Usage: $0 [-b] [-c] [-d <HDF5 directory>] [-e] [-g] [-h] [-i]
[-k <CMake command>] [-l <Install directory>] [m] [n] [-p] [-q <Zmq hint directory>] [-j <Number of threads>] [-k <CMake command>] [-l <Install directory>]
[r] [s] [t] [u] [z] [-m] [-n] [-p] [-r] [-s] [-t] [-u] [-z]
-[no option]: only make -[no option]: only make
-b: Builds/Rebuilds CMake files normal mode -b: Builds/Rebuilds CMake files normal mode
-c: Clean -c: Clean
@ -159,7 +147,6 @@ Build using in-built cmk.sh script
-m: Manuals -m: Manuals
-n: Manuals without compiling doxygen (only rst) -n: Manuals without compiling doxygen (only rst)
-p: Builds/Rebuilds Python API -p: Builds/Rebuilds Python API
-q: Zmq hint directory
-r: Build/Rebuilds only receiver -r: Build/Rebuilds only receiver
-s: Simulator -s: Simulator
-t: Build/Rebuilds only text client -t: Build/Rebuilds only text client
@ -176,9 +163,13 @@ Build using in-built cmk.sh script
# new build, python and compile in parallel: # new build, python and compile in parallel:
./cmk.sh -cbpj5 ./cmk.sh -cbpj5
#To use the system zmq (/usr/lib64) instead #For rebuilding only certain sections
./cmk.sh -cbj5 -q /usr/lib64 ./cmk.sh -tg #only text client and gui
./cmk.sh -r #only receiver
.. note ::
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
Build on old distributions Build on old distributions
@ -191,7 +182,7 @@ using this compiler
.. code-block:: bash .. code-block:: bash
#Create an environment with the dependencies #Create an environment with the dependencies
conda create -n myenv gxx_linux-64 cmake zmq conda create -n myenv gxx_linux-64 cmake
conda activate myenv conda activate myenv
# outside slsDetecorPackage folder # outside slsDetecorPackage folder
@ -200,6 +191,11 @@ using this compiler
make -j12 make -j12
.. note ::
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for dependencies for conda. <zeromq for different slsDetectorPackage versions>`
Build slsDetectorGui (Qt5) Build slsDetectorGui (Qt5)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -228,9 +224,9 @@ Build slsDetectorGui (Qt5)
# create environment to compile # create environment to compile
# on rhel7 # on rhel7
conda create -n slsgui zeromq gxx_linux-64 gxx_linux-64 mesa-libgl-devel-cos6-x86_64 qt conda create -n slsgui gxx_linux-64 gxx_linux-64 mesa-libgl-devel-cos6-x86_64 qt
# on fedora or newer systems # on fedora or newer systems
conda create -n slsgui zeromq qt conda create -n slsgui qt
# when using conda compilers, would also need libgl, but no need for it on fedora unless maybe using it with ROOT # when using conda compilers, would also need libgl, but no need for it on fedora unless maybe using it with ROOT
@ -246,6 +242,9 @@ Build slsDetectorGui (Qt5)
cd slsDetectorPackage cd slsDetectorPackage
./cmk.sh -cbgj9 ./cmk.sh -cbgj9
.. note ::
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for dependencies for conda. <zeromq for different slsDetectorPackage versions>`
@ -258,7 +257,7 @@ is to use conda
.. code-block:: bash .. code-block:: bash
conda create -n myenv python sphinx_rtd_theme breathe conda create -n myenv python=3.12 sphinx sphinx_rtd_theme breathe doxygen numpy
.. code-block:: bash .. code-block:: bash
@ -270,3 +269,51 @@ is to use conda
make docs # generate API docs and build Sphinx RST make docs # generate API docs and build Sphinx RST
make rst # rst only, saves time in case the API did not change make rst # rst only, saves time in case the API did not change
Pybind and Zeromq
^^^^^^^^^^^^^^^^^^^
.. _pybind for different slsDetectorPackage versions:
| **Pybind for Python**
| v8.0.0+:
| pybind11 (v2.11.0) is built
| * by default from tar file in repo (libs/pybind/v2.11.0.tar.gz)
| * or use advanced option SLS_FETCH_PYBIND11_FROM_GITHUB [`link <https://github.com/pybind/pybind11>`__].
|
| v7.x.x:
| pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
| Older versions:
| pybind11 is a submodule. Must be cloned using "recursive" and updated when switching between versions using the following commands.
.. code-block:: bash
# Note: Only for v6.x.x versions and older
# clone using recursive to get pybind11 submodule
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
# update submodule when switching between releases
cd slsDetectorPackage
git submodule update --init
.. _zeromq for different slsDetectorPackage versions:
| **Zeromq**
| v8.0.0+:
| zeromq (v4.3.4) is built
| * by default from tar file in repo (libs/libzmq/libzmq-4.3.4.tar.gz)
| * or use advanced option SLS_FETCH_ZMQ_FROM_GITHUB [`link <https://github.com/zeromq/libzmq.git>`__].
|
| v7.x.x and older:
| zeromq must be installed and one can hint its location using
| * cmake option:'-DZeroMQ_HINT=/usr/lib64' or
| * option '-q' in cmk.sh script: : ./cmk.sh -cbj5 -q /usr/lib64
| * 'zeromq' dependency added when installing using conda

View File

@ -109,12 +109,14 @@ For Multiple Modules
# connects to mulitple modules # connects to mulitple modules
hostname bchipxxx+bchipyyy+ hostname bchipxxx+bchipyyy+
# connects to receivers at ports 2012 and 2014 # tcp port increases for each module (multi detector command)
rx_hostname mpc1922:2012+mpc1922:2013+ rx_tcpport 2012
# sets differernt destination udp ports # connects to receivers at ports 2012 and 2014
0:udp_dstport 50012 rx_hostname mpc1922
1:udp_dstport 50014
# increasing udp ports (multi detector command)
udp_dstport 50012
# source udp ips must be same subnet at destintaion udp ips # source udp ips must be same subnet at destintaion udp ips
0:udp_srcip 192.168.1.112 0:udp_srcip 192.168.1.112

View File

@ -1,3 +1,5 @@
.. _Result Class:
Result Result
============================================== ==============================================

View File

@ -52,8 +52,13 @@ Client Commands
# multi modules with custom ports # multi modules with custom ports
rx_hostname xxx:1955+xxx:1956+ rx_hostname xxx:1955+xxx:1956+
# multi modules using increasing tcp ports when using multi detector command
rx_tcpport 1955
rx_hostname xxx
# multi modules with custom ports on same rxr pc # or specify multi modules with custom ports on same rxr pc
0:rx_tcpport 1954 0:rx_tcpport 1954
1:rx_tcpport 1955 1:rx_tcpport 1955
2:rx_tcpport 1956 2:rx_tcpport 1956

View File

@ -92,6 +92,9 @@ Common
sls_detector_put rx_arping 1 sls_detector_put rx_arping 1
#. Only the slaves get no data
* Check trigger cabling and trigger configuration
* When you cannot stop Jungfrau slaves in sync mode, refer to :ref:`Cannot stop slaves<Jungfrau Troubleshooting Sync Slaves Cannot Stop>`.
.. _Receiver PC Tuning: .. _Receiver PC Tuning:
@ -421,3 +424,20 @@ Cannot get multi module data
* Comment out this line in the config file: powerchip 1 * Comment out this line in the config file: powerchip 1
* Powering on the chip increases the power consumption by a considerable amount. If commenting out this line aids in getting data (strange data due to powered off chip), then it could be the power supply current limit. Fix it (possibly to 8A current limit) and uncomment the powerchip line back in config file. * Powering on the chip increases the power consumption by a considerable amount. If commenting out this line aids in getting data (strange data due to powered off chip), then it could be the power supply current limit. Fix it (possibly to 8A current limit) and uncomment the powerchip line back in config file.
.. _Jungfrau Troubleshooting Sync Slaves Cannot Stop:
Cannot stop slaves in sync mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. If cabling is accessible, ensure termination board and flatband cable between the masters and the slaves are connnected properly. Then try to stop.
#. If cabling is inaccessible, unsync first so that the slaves can get the stop directly from the client using the command. Then, don't use sync mode until the cabling is fixed.
.. code-block:: bash
# unsync, slaves command will fail as it is still in waiting state
sls_detector_put sync 0
# stop should now be successful as master does not determine the stop anymore
sls_detector_put stop

View File

@ -86,7 +86,8 @@ For a Single Module (With Options)
udp_dstport 50012 udp_dstport 50012
# source udp ips must be same subnet at destintaion udp ips # source udp ips must be same subnet at destintaion udp ips
udp_srcip 192.168.1.112 # takes the same ip as hostname
udp_srcip auto
# destination udp ip picked up from rx_hostname (if auto) # destination udp ip picked up from rx_hostname (if auto)
udp_dstip auto udp_dstip auto
@ -101,12 +102,14 @@ For Multiple Modules
virtual 2 1912 virtual 2 1912
# or hostname localhost:1912+localhost:1914+ # or hostname localhost:1912+localhost:1914+
# connects to receivers at ports 2012 and 2014 # increasing receiver tcp ports (multi detector command)
rx_hostname mpc1922:2012+mpc1922:2013+ rx_tcpport 2012
# sets differernt destination udp ports # connects to reciever at port 2012 and 2013
0:udp_dstport 50012 rx_hostname mpc1922
1:udp_dstport 50014
# sets increasing destination udp ports
udp_dstport 50012
# source udp ips must be same subnet at destintaion udp ips # source udp ips must be same subnet at destintaion udp ips
0:udp_srcip 192.168.1.112 0:udp_srcip 192.168.1.112

View File

@ -4,27 +4,33 @@ detsize 1024 512
# detector hostname for controls # detector hostname for controls
hostname beb059+beb058+ hostname beb059+beb058+
# 1Gb receiver pc hostname with tcp port to configure receiver # increasing receiver tcp port (multi detector command)
rx_hostname x12sa-vcons:1991+x12sa-vcons:1992 rx_tcpport 1991
# 1Gb receiver pc hostname to configure receiver
rx_hostname x12sa-vcons
# or 1Gb receiver pc hostname with tcp port to configure receiver
#rx_hostname x12sa-vcons:1991+x12sa-vcons:1992
# increasing udp destination ports for all half modules
udp_dstport 50011
# udp port first quadrant, first halfmodule # udp port first quadrant, first halfmodule
0:udp_dstport 50011 #0:udp_dstport 50011
# udp port second quadrant, first halfmodule # udp port second quadrant, first halfmodule
0:udp_dstport2 50012 #0:udp_dstport2 50012
# udp port first quadrant, second halfmodule
#1:udp_dstport 50013
# udp port second quadrant, second halfmodule
#1:udp_dstport2 50014
# udp IP of the receiver over 10Gb # udp IP of the receiver over 10Gb
0:udp_dstip 10.0.30.210 0:udp_dstip 10.0.30.210
# first half module 10 Gb IP (same subnet as 0:udp_dstip) # first half module 10 Gb IP (same subnet as 0:udp_dstip)
0:udp_srcip 10.0.30.100 0:udp_srcip 10.0.30.100
# udp port first quadrant, second halfmodule
1:udp_dstport 50013
# udp port second quadrant, second halfmodule
1:udp_dstport2 50014
# udp IP of the receiver over 10Gb, # udp IP of the receiver over 10Gb,
1:udp_dstip 10.0.40.210 1:udp_dstip 10.0.40.210

View File

@ -4,18 +4,23 @@ detsize 1024 512
# detector hostname for controls # detector hostname for controls
hostname beb059+beb058+ hostname beb059+beb058+
# 1Gb receiver pc hostname with tcp port to configure receiver # increasing receiver tcp port (multi detector command)
rx_hostname x12sa-vcons:1991+x12sa-vcons:1992 rx_tcpport 1991
# 1Gb receiver pc hostname to configure receiver
rx_hostname x12sa-vcons
# increasing udp destination ports for all half modules
udp_dstport 50011
# udp port first quadrant, first halfmodule # udp port first quadrant, first halfmodule
0:udp_dstport 50011 #0:udp_dstport 50011
#udp port second quadrant, first halfmodule #udp port second quadrant, first halfmodule
0:udp_dstport2 50012 #0:udp_dstport2 50012
# udp port first quadrant, second halfmodule # udp port first quadrant, second halfmodule
1:udp_dstport 50013 #1:udp_dstport 50013
# udp port second quadrant, second halfmodule # udp port second quadrant, second halfmodule
1:udp_dstport2 50014 #1:udp_dstport2 50014
# output directory # output directory
fpath /sls/X12SA/data/x12saop/Data10/Eiger0.5M fpath /sls/X12SA/data/x12saop/Data10/Eiger0.5M

View File

@ -4,14 +4,18 @@ detsize 1024 1024
# detector hostname # detector hostname
hostname bchip048+bchip052+ hostname bchip048+bchip052+
# 1Gb receiver pc hostname (default tcpport: 1954) # increasing receiver ports 1954 and 1955 (multi detector command)
rx_hostname pcmoench01:1954+pcmoench01:1955+ rx_tcpport 1954
# 1Gb receiver pc hostname
rx_hostname pcmoench01
# increasing udp ports 50004 and 50005 (multi detector command)
udp_dstport 50004
# or custom udp destination port (receiver) for 1st module
#0:udp_dstport 50014
# udp configurations for 1st module
# udp destination port (receiver)
0:udp_dstport 50004
# udp destination ip (receiver) # udp destination ip (receiver)
0:udp_dstip 10.1.1.100 0:udp_dstip 10.1.1.100
@ -19,17 +23,11 @@ rx_hostname pcmoench01:1954+pcmoench01:1955+
# udp source ip (same subnet as 0:udp_dstip) # udp source ip (same subnet as 0:udp_dstip)
0:udp_srcip 10.1.1.10 0:udp_srcip 10.1.1.10
# udp configurations for 2nd module
# udp destination port (receiver)
1:udp_dstport 50005
# udp destination ip (receiver) # udp destination ip (receiver)
1:udp_dstip 10.1.1.100 1:udp_dstip 10.1.2.100
# udp source ip (same subnet as 1:udp_dstip) # udp source ip (same subnet as 1:udp_dstip)
1:udp_srcip 10.1.1.11 1:udp_srcip 10.1.2.11
@ -45,5 +43,5 @@ timing trigger
# output file directory # output file directory
fpath /external_pool/jungfrau_data/softwaretest fpath /external_pool/jungfrau_data/softwaretest
# disable file writing # disable file writing (default)
fwrite 0 fwrite 0

View File

@ -2,10 +2,8 @@
hostname localhost:1900+localhost:1902+ hostname localhost:1900+localhost:1902+
# udp destination ports # udp destination ports
0:udp_dstport 50000 udp_dstport 50000
0:udp_dstport2 50001 udp_dstport2 50001
1:udp_dstport 50002
1:udp_dstport2 50003
# receiver hostname # receiver hostname
rx_hostname mpc1922:2000+mpc1922:2001+ rx_hostname mpc1922:2000+mpc1922:2001+

View File

@ -5,24 +5,26 @@ detsize 2048 1024
virtual 4 1952 virtual 4 1952
# udp destination ports # udp destination ports
0:udp_dstport2 50001 udp_dstport 50001
0:udp_dstport2 50002 #0:udp_dstport2 50001
1:udp_dstport 50003 #0:udp_dstport2 50002
1:udp_dstport2 50004 #1:udp_dstport 50003
2:udp_dstport 50005 #1:udp_dstport2 50004
2:udp_dstport2 50006 #2:udp_dstport 50005
3:udp_dstport 50007 #2:udp_dstport2 50006
3:udp_dstport2 50008 #3:udp_dstport 50007
#3:udp_dstport2 50008
# udp source ip (same subnet as udp_dstip) # udp source ip (same subnet as udp_dstip)
udp_srcip 192.168.1.100 udp_srcip 192.168.1.100
udp_srcip2 192.168.1.100 udp_srcip2 192.168.1.100
# receiver hostname and tcpports # receiver hostname and tcpports
0:rx_tcpport 1970 rx_tcpport 1970
1:rx_tcpport 1971 #0:rx_tcpport 1970
2:rx_tcpport 1972 #1:rx_tcpport 1971
3:rx_tcpport 1973 #2:rx_tcpport 1972
#3:rx_tcpport 1973
rx_hostname mpc1922 rx_hostname mpc1922
# udp destination ip from rx_hostname # udp destination ip from rx_hostname

View File

@ -360,7 +360,8 @@ class Detector(CppDetectorApi):
@property @property
def settings(self): def settings(self):
""" """
Detector settings. Enum: detectorSettings Detector settings.
Enum: detectorSettings
Note Note
----- -----
@ -400,6 +401,9 @@ class Detector(CppDetectorApi):
def framesl(self): def framesl(self):
""" """
[Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB] Number of frames left in acquisition.\n [Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB] Number of frames left in acquisition.\n
Note
----
[Gotthard2] only in continuous auto mode. [Gotthard2] only in continuous auto mode.
:setter: Not Implemented :setter: Not Implemented
@ -475,7 +479,8 @@ class Detector(CppDetectorApi):
@element @element
def gaincaps(self): def gaincaps(self):
""" """
[Mythen3] Gain caps. Enum: M3_GainCaps \n [Mythen3] Gain caps.
Enum: M3_GainCaps
Note Note
---- ----
@ -573,8 +578,6 @@ class Detector(CppDetectorApi):
""" """
Period between frames, accepts either a value in seconds or datetime.timedelta Period between frames, accepts either a value in seconds or datetime.timedelta
Note
-----
:getter: always returns in seconds. To get in DurationWrapper, use getPeriod :getter: always returns in seconds. To get in DurationWrapper, use getPeriod
Example Example
@ -641,9 +644,6 @@ class Detector(CppDetectorApi):
""" """
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2] Delay after trigger, accepts either a value in seconds, DurationWrapper or datetime.timedelta [Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2] Delay after trigger, accepts either a value in seconds, DurationWrapper or datetime.timedelta
Note
-----
:getter: always returns in seconds. To get in DurationWrapper, use getDelayAfterTrigger :getter: always returns in seconds. To get in DurationWrapper, use getDelayAfterTrigger
Example Example
@ -895,7 +895,8 @@ class Detector(CppDetectorApi):
@element @element
def rx_discardpolicy(self): def rx_discardpolicy(self):
""" """
Frame discard policy of receiver. Enum: frameDiscardPolicy Frame discard policy of receiver.
Enum: frameDiscardPolicy
Note Note
----- -----
@ -969,7 +970,8 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def fformat(self): def fformat(self):
""" File format of data file in receiver. Enum: fileFormat """ File format of data file in receiver.
Enum: fileFormat
Note Note
----- -----
@ -1565,7 +1567,8 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def status(self): def status(self):
"""Gets detector status. Enum: runStatus """Gets detector status.
Enum: runStatus
Note Note
----- -----
@ -1579,7 +1582,8 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def rx_status(self): def rx_status(self):
"""Gets receiver listener status. Enum: runStatus """Gets receiver listener status.
Enum: runStatus
Note Note
----- -----
@ -1673,6 +1677,11 @@ class Detector(CppDetectorApi):
def sync(self): def sync(self):
""" """
[Jungfrau][Moench] Enables or disables synchronization between modules. [Jungfrau][Moench] Enables or disables synchronization between modules.
Note
----
Sync mode requires at least one master configured. Also requires flatband cabling between master and slave with termination board.
""" """
return self.getSynchronization() return self.getSynchronization()
@ -1803,6 +1812,7 @@ class Detector(CppDetectorApi):
def daclist(self): def daclist(self):
""" """
List of enums/names for every dac for this detector List of enums/names for every dac for this detector
:setter: Only implemented for Chiptestboard :setter: Only implemented for Chiptestboard
""" """
@ -1815,9 +1825,7 @@ class Detector(CppDetectorApi):
@property @property
def adclist(self): def adclist(self):
""" """
List of names for every adc for this board. 32 adcs [Chiptestboard] List of names for every adc for this board. 32 adcs
:setter: Only implemented for Chiptestboard
""" """
return self.getAdcNames() return self.getAdcNames()
@ -1828,9 +1836,7 @@ class Detector(CppDetectorApi):
@property @property
def signallist(self): def signallist(self):
""" """
List of names for every io signal for this board. 64 signals [Chiptestboard] List of names for every io signal for this board. 64 signals
:setter: Only implemented for Chiptestboard
""" """
return self.getSignalNames() return self.getSignalNames()
@ -1841,8 +1847,7 @@ class Detector(CppDetectorApi):
@property @property
def powerlist(self): def powerlist(self):
""" """
List of names for every power for this board. 5 power supply [Chiptestboard] List of names for every power for this board. 5 power supply
:setter: Only implemented for Chiptestboard
""" """
return self.getPowerNames() return self.getPowerNames()
@ -1854,8 +1859,7 @@ class Detector(CppDetectorApi):
@property @property
def slowadclist(self): def slowadclist(self):
""" """
List of names for every slowadc for this board. 8 slowadc [Chiptestboard] List of names for every slowadc for this board. 8 slowadc
:setter: Only implemented for Chiptestboard
""" """
return self.getSlowADCNames() return self.getSlowADCNames()
@ -1874,7 +1878,7 @@ class Detector(CppDetectorApi):
@property @property
def powervalues(self): def powervalues(self):
"""Gets the power values for every power for this detector.""" """[Chiptestboard] Gets the power values for every power for this detector."""
return { return {
power.name.lower(): element_if_equal(np.array(self.getPower(power))) power.name.lower(): element_if_equal(np.array(self.getPower(power)))
for power in self.getPowerList() for power in self.getPowerList()
@ -1882,7 +1886,7 @@ class Detector(CppDetectorApi):
@property @property
def slowadcvalues(self): def slowadcvalues(self):
"""Gets the slow adc values for every slow adc for this detector.""" """[Chiptestboard] Gets the slow adc values for every slow adc for this detector."""
return { return {
slowadc.name.lower(): element_if_equal(np.array(self.getSlowADC(slowadc))) slowadc.name.lower(): element_if_equal(np.array(self.getSlowADC(slowadc)))
for slowadc in self.getSlowADCList() for slowadc in self.getSlowADCList()
@ -2056,8 +2060,7 @@ class Detector(CppDetectorApi):
----- -----
To set default rate correction from trimbit file, use setDefaultRateCorrection To set default rate correction from trimbit file, use setDefaultRateCorrection
Known Issue Known Issue:
------------
:getter: Always give 0 due to the microseconds precision. :getter: Always give 0 due to the microseconds precision.
:setter: Use scientific notation to set custom rate correction, since timedelta resolution is 1 microseconds. \n :setter: Use scientific notation to set custom rate correction, since timedelta resolution is 1 microseconds. \n
@ -2081,7 +2084,8 @@ class Detector(CppDetectorApi):
@element @element
def readoutspeed(self): def readoutspeed(self):
""" """
[Eiger][Jungfrau|Gotthard2] Readout speed of chip. Enum: speedLevel [Eiger][Jungfrau|Gotthard2] Readout speed of chip.
Enum: speedLevel
Note Note
----- -----
@ -2170,7 +2174,8 @@ class Detector(CppDetectorApi):
@element @element
def timing(self): def timing(self):
""" """
Set Timing Mode of detector. Enum: timingMode Set Timing Mode of detector.
Enum: timingMode
Note Note
----- -----
@ -2230,13 +2235,11 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def type(self): def type(self):
""" Returns detector type. Enum: detectorType """ Returns detector type.
Enum: detectorType
Note [EIGER, JUNGFRAU, GOTTHARD, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD]
----
:setter: Not implemented :setter: Not implemented
Values: EIGER, JUNGFRAU, GOTTHARD, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD
""" """
return self.getDetectorType() return self.getDetectorType()
@ -2497,9 +2500,6 @@ class Detector(CppDetectorApi):
""" """
[Eiger] Measured sub frame period between last sub frame and previous one. [Eiger] Measured sub frame period between last sub frame and previous one.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return ut.reduce_time(self.getMeasuredSubFramePeriod()) return ut.reduce_time(self.getMeasuredSubFramePeriod())
@ -2777,7 +2777,8 @@ class Detector(CppDetectorApi):
@property @property
def gainmode(self): def gainmode(self):
""" """
[Jungfrau] Detector gain mode. Enum: gainMode [Jungfrau] Detector gain mode.
Enum: gainMode
Note Note
----- -----
@ -2890,11 +2891,8 @@ class Detector(CppDetectorApi):
@property @property
def maxclkphaseshift(self): def maxclkphaseshift(self):
""" """
[Gotthard2][Mythen3] Absolute maximum Phase shift of clocks. [Gotthard2][Mythen3] Absolute maximum Phase shift of clocks.
Note
----
:setter: Not Implemented :setter: Not Implemented
Example Example
@ -2912,7 +2910,8 @@ class Detector(CppDetectorApi):
@element @element
def timingsource(self): def timingsource(self):
""" """
[Gotthard2] Timing source. Enum: timingSourceType [Gotthard2] Timing source.
Enum: timingSourceType
Note Note
----- -----
@ -2956,7 +2955,8 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def burstmode(self): def burstmode(self):
"""[Gotthard2] Burst mode of detector. Enum: burstMode """[Gotthard2] Burst mode of detector.
Enum: burstMode
Note Note
---- ----
@ -2974,9 +2974,6 @@ class Detector(CppDetectorApi):
""" """
[Gotthard2] Period between 2 bursts. Only in burst mode and auto timing mode. [Gotthard2] Period between 2 bursts. Only in burst mode and auto timing mode.
Note
-----
:getter: always returns in seconds. To get in DurationWrapper, use getBurstPeriod :getter: always returns in seconds. To get in DurationWrapper, use getBurstPeriod
:setter: Not Implemented :setter: Not Implemented
@ -3099,7 +3096,8 @@ class Detector(CppDetectorApi):
@property @property
def vetoalg(self): def vetoalg(self):
"""[Gotthard2] Algorithm used for veto. Enum: vetoAlgorithm, streamingInterface """[Gotthard2] Algorithm used for veto.
Enum: vetoAlgorithm, streamingInterface
Note Note
---- ----
@ -3273,7 +3271,8 @@ class Detector(CppDetectorApi):
@element @element
def romode(self): def romode(self):
""" """
[CTB] Readout mode of detector. Enum: readoutMode [CTB] Readout mode of detector.
Enum: readoutMode
Note Note
------ ------
@ -3379,9 +3378,6 @@ class Detector(CppDetectorApi):
def maxdbitphaseshift(self): def maxdbitphaseshift(self):
"""[CTB][Jungfrau] Absolute maximum Phase shift of of the clock to latch digital bits. """[CTB][Jungfrau] Absolute maximum Phase shift of of the clock to latch digital bits.
Note
-----
:setter: Not Implemented :setter: Not Implemented
""" """
return self.getMaxDBITPhaseShift() return self.getMaxDBITPhaseShift()
@ -3426,9 +3422,6 @@ class Detector(CppDetectorApi):
def maxadcphaseshift(self): def maxadcphaseshift(self):
"""[Jungfrau][Moench][CTB] Absolute maximum Phase shift of ADC clock. """[Jungfrau][Moench][CTB] Absolute maximum Phase shift of ADC clock.
Note
-----
:setter: Not Implemented :setter: Not Implemented
""" """
return self.getMaxADCPhaseShift() return self.getMaxADCPhaseShift()
@ -3478,9 +3471,6 @@ class Detector(CppDetectorApi):
""" """
[Ctb] Sync clock in MHz. [Ctb] Sync clock in MHz.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getSYNCClock() return self.getSYNCClock()
@ -3488,10 +3478,7 @@ class Detector(CppDetectorApi):
@property @property
def pattern(self): def pattern(self):
"""[Mythen3][Ctb] Loads ASCII pattern file directly to server (instead of executing line by line). """[Mythen3][Ctb] Loads ASCII pattern file directly to server (instead of executing line by line).
Note
----
:getter: Not Implemented :getter: Not Implemented
Example Example
@ -3919,10 +3906,7 @@ class Detector(CppDetectorApi):
@element @element
def im_a(self): def im_a(self):
"""[Ctb] Measured current of power supply a in mA. """[Ctb] Measured current of power supply a in mA.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getMeasuredCurrent(dacIndex.I_POWER_A) return self.getMeasuredCurrent(dacIndex.I_POWER_A)
@ -3932,9 +3916,6 @@ class Detector(CppDetectorApi):
def im_b(self): def im_b(self):
"""[Ctb] Measured current of power supply b in mA. """[Ctb] Measured current of power supply b in mA.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getMeasuredCurrent(dacIndex.I_POWER_B) return self.getMeasuredCurrent(dacIndex.I_POWER_B)
@ -3944,9 +3925,6 @@ class Detector(CppDetectorApi):
def im_c(self): def im_c(self):
"""[Ctb] Measured current of power supply c in mA. """[Ctb] Measured current of power supply c in mA.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getMeasuredCurrent(dacIndex.I_POWER_C) return self.getMeasuredCurrent(dacIndex.I_POWER_C)
@ -3956,9 +3934,6 @@ class Detector(CppDetectorApi):
def im_d(self): def im_d(self):
"""[Ctb] Measured current of power supply d in mA. """[Ctb] Measured current of power supply d in mA.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getMeasuredCurrent(dacIndex.I_POWER_D) return self.getMeasuredCurrent(dacIndex.I_POWER_D)
@ -3968,9 +3943,6 @@ class Detector(CppDetectorApi):
def im_io(self): def im_io(self):
"""[Ctb] Measured current of power supply io in mA. """[Ctb] Measured current of power supply io in mA.
Note
-----
:setter: Not implemented :setter: Not implemented
""" """
return self.getMeasuredCurrent(dacIndex.I_POWER_IO) return self.getMeasuredCurrent(dacIndex.I_POWER_IO)
@ -4020,9 +3992,6 @@ class Detector(CppDetectorApi):
def exptimel(self): def exptimel(self):
"""[Gotthard] Exposure time left for current frame. """[Gotthard] Exposure time left for current frame.
Note
-----
:getter: always returns in seconds. To get in DurationWrapper, use getExptimeLeft :getter: always returns in seconds. To get in DurationWrapper, use getExptimeLeft
:setter: Not Implemented :setter: Not Implemented
@ -4057,9 +4026,6 @@ class Detector(CppDetectorApi):
""" """
[Gotthard2][Mythen3] Frequency of clock in Hz. [Gotthard2][Mythen3] Frequency of clock in Hz.
Note
----
:setter: Not implemented. Use clkdiv to set frequency :setter: Not implemented. Use clkdiv to set frequency
Example Example
@ -4079,7 +4045,9 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def polarity(self): def polarity(self):
"""[Mythen3] Set positive or negative polarity. Enum: polarity""" """[Mythen3] Set positive or negative polarity.
Enum: polarity
"""
return self.getPolarity() return self.getPolarity()
@polarity.setter @polarity.setter

View File

@ -1 +0,0 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServerv8.0.0

View File

@ -1 +0,0 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer

View File

@ -0,0 +1 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv8.0.0

View File

@ -193,6 +193,7 @@ void qDrawPlot::SetupPlots() {
gainplot2d = new SlsQt2DPlot(boxPlot, true); gainplot2d = new SlsQt2DPlot(boxPlot, true);
gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5, gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5,
nPixelsY - 0.5, gainData); nPixelsY - 0.5, gainData);
gainplot2d->Update();
gainplot2d->hide(); gainplot2d->hide();
connect(plot2d, SIGNAL(PlotZoomedSignal(const QRectF &)), this, connect(plot2d, SIGNAL(PlotZoomedSignal(const QRectF &)), this,
SLOT(Zoom2DGainPlot(const QRectF &))); SLOT(Zoom2DGainPlot(const QRectF &)));
@ -1009,6 +1010,7 @@ void qDrawPlot::Update2dPlot() {
if (isGainDataExtracted) { if (isGainDataExtracted) {
gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5, gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5,
nPixelsY - 0.5, gainData); nPixelsY - 0.5, gainData);
gainplot2d->Update();
if (!gainplot2d->isVisible()) { if (!gainplot2d->isVisible()) {
gainplot2d->setFixedWidth(plot2d->width() / gainplot2d->setFixedWidth(plot2d->width() /
qDefs::DATA_GAIN_PLOT_RATIO); qDefs::DATA_GAIN_PLOT_RATIO);

View File

@ -803,8 +803,9 @@ void qTabMeasurement::GetNextFrameNumber() {
"Inconsistent starting frame number for all detectors."); "Inconsistent starting frame number for all detectors.");
spinNextFrameNumber->setValue(retval); spinNextFrameNumber->setValue(retval);
} }
CATCH_DISPLAY("Could not get starting frame number.", CATCH_HANDLE("Could not get starting frame number.",
"qTabMeasurement::GetNextFrameNumber") "qTabMeasurement::GetNextFrameNumber", spinNextFrameNumber,
&QSpinBox::setValue, -1)
connect(spinNextFrameNumber, SIGNAL(valueChanged(int)), this, connect(spinNextFrameNumber, SIGNAL(valueChanged(int)), this,
SLOT(SetNextFrameNumber(int))); SLOT(SetNextFrameNumber(int)));
} }

View File

@ -10,7 +10,7 @@
#define HARDWARE_VERSION_NAMES \ #define HARDWARE_VERSION_NAMES \
{ "FX70T", "FX30T" } { "FX70T", "FX30T" }
#define REQUIRED_FIRMWARE_VERSION (31) #define REQUIRED_FIRMWARE_VERSION (32)
// virtual ones renamed for consistency // virtual ones renamed for consistency
// real ones keep previous name for compatibility (already in production) // real ones keep previous name for compatibility (already in production)
#ifdef VIRTUAL #ifdef VIRTUAL

View File

@ -3323,6 +3323,27 @@ void *start_timer(void *arg) {
break; break;
} }
// change gain and data for every frame
{
const int nchannels = NCHIP * NCHAN;
int gainVal = 0;
for (int i = 0; i < nchannels; ++i) {
if ((i % nchannels) < 400) {
gainVal = 1 + frameNr;
} else if ((i % nchannels) < 800) {
gainVal = 2 + frameNr;
} else {
gainVal = 3 + frameNr;
}
int dataVal =
*((uint16_t *)(imageData + i * sizeof(uint16_t)));
dataVal += frameNr;
int channelVal =
(dataVal & ~GAIN_VAL_MSK) | (gainVal << GAIN_VAL_OFST);
*((uint16_t *)(imageData + i * sizeof(uint16_t))) =
(uint16_t)channelVal;
}
}
// sleep for exposure time // sleep for exposure time
struct timespec begin, end; struct timespec begin, end;
clock_gettime(CLOCK_REALTIME, &begin); clock_gettime(CLOCK_REALTIME, &begin);

View File

@ -24,16 +24,18 @@
#define RUN_BUSY_OFST (0) #define RUN_BUSY_OFST (0)
#define RUN_BUSY_MSK (0x00000001 << RUN_BUSY_OFST) #define RUN_BUSY_MSK (0x00000001 << RUN_BUSY_OFST)
#define WAITING_FOR_TRIGGER_OFST (3) #define WAITING_FOR_TRIGGER_OFST (1)
#define WAITING_FOR_TRIGGER_MSK (0x00000001 << WAITING_FOR_TRIGGER_OFST) #define WAITING_FOR_TRIGGER_MSK (0x00000001 << WAITING_FOR_TRIGGER_OFST)
#define DELAYBEFORE_OFST (4) // Not used in software #define WAITING_FOR_START_FRAME_OFST (2)
#define DELAYBEFORE_MSK (0x00000001 << DELAYBEFORE_OFST) // Not used in software #define WAITING_FOR_START_FRAME_MSK (0x00000001 << WAITING_FOR_START_FRAME_OFST)
#define DELAYAFTER_OFST (5) // Not used in software #define ACQUIRING_FRAME_OFST (3) // Not used in software
#define DELAYAFTER_MSK (0x00000001 << DELAYAFTER_OFST) // Not used in software #define ACQUIRING_FRAME_MSK (0x00000001 << ACQUIRING_FRAME_OFST)
#define STOPPED_OFST (15) #define WAITING_FOR_PERIOD_TO_ELAPSE_OFST (4) // Not used in software
#define WAITING_FOR_PERIOD_TO_ELAPSE_MSK (0x00000001 << WAITING_FOR_PERIOD_TO_ELAPSE_OFST)
#define STOPPED_OFST (8)
#define STOPPED_MSK (0x00000001 << STOPPED_OFST) #define STOPPED_MSK (0x00000001 << STOPPED_OFST)
#define RUNMACHINE_BUSY_OFST (17) #define INTERNAL_STOP_OFST (9)
#define RUNMACHINE_BUSY_MSK (0x00000001 << RUNMACHINE_BUSY_OFST) #define INTERNAL_STOP_MSK (0x00000001 << INTERNAL_STOP_OFST)
/* Look at me register */ /* Look at me register */
#define LOOK_AT_ME_REG (0x03 << MEM_MAP_SHIFT) // Not used in firmware or software #define LOOK_AT_ME_REG (0x03 << MEM_MAP_SHIFT) // Not used in firmware or software

View File

@ -2552,8 +2552,7 @@ void setPedestalMode(int enable, uint8_t frames, uint16_t loops) {
if (enable) { if (enable) {
LOG(logINFOBLUE, ("Enabling pedestal mode [frames: %hhu, loops: %hu]\n", LOG(logINFOBLUE, ("Enabling pedestal mode [frames: %hhu, loops: %hu]\n",
frames, loops)); frames, loops));
// enable
bus_w(addr, bus_r(addr) | PEDESTAL_MODE_ENBLE_MSK);
// frames // frames
bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_LNGTH_MSK); bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_LNGTH_MSK);
bus_w(addr, bus_r(addr) | ((frames << PEDESTAL_MODE_LNGTH_OFST) & bus_w(addr, bus_r(addr) | ((frames << PEDESTAL_MODE_LNGTH_OFST) &
@ -2562,6 +2561,8 @@ void setPedestalMode(int enable, uint8_t frames, uint16_t loops) {
bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_ITRTNS_MSK); bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_ITRTNS_MSK);
bus_w(addr, bus_r(addr) | ((loops << PEDESTAL_MODE_ITRTNS_OFST) & bus_w(addr, bus_r(addr) | ((loops << PEDESTAL_MODE_ITRTNS_OFST) &
PEDESTAL_MODE_ITRTNS_MSK)); PEDESTAL_MODE_ITRTNS_MSK));
// enable
bus_w(addr, bus_r(addr) | PEDESTAL_MODE_ENBLE_MSK);
// if it was switched off before, remember the #frames and #triggers // if it was switched off before, remember the #frames and #triggers
if (prevPedestalEnable == 0) { if (prevPedestalEnable == 0) {
@ -2726,6 +2727,7 @@ void *start_timer(void *arg) {
if (i % pixelsPerPacket == 0) { if (i % pixelsPerPacket == 0) {
++dataVal; ++dataVal;
} }
if ((i % 1024) < 300) { if ((i % 1024) < 300) {
gainVal = 1; gainVal = 1;
} else if ((i % 1024) < 600) { } else if ((i % 1024) < 600) {
@ -2766,6 +2768,28 @@ void *start_timer(void *arg) {
clock_gettime(CLOCK_REALTIME, &begin); clock_gettime(CLOCK_REALTIME, &begin);
usleep(expUs); usleep(expUs);
// change gain and data for every frame
{
const int npixels = (NCHAN * NCHIP);
for (int i = 0; i < npixels; ++i) {
int gainVal = 0;
if ((i % 1024) < 300) {
gainVal = 1 + iframes;
} else if ((i % 1024) < 600) {
gainVal = 2 + iframes;
} else {
gainVal = 3 + iframes;
}
int dataVal =
*((uint16_t *)(imageData + i * sizeof(uint16_t)));
dataVal += iframes;
int pixelVal =
(dataVal & ~GAIN_VAL_MSK) | (gainVal << GAIN_VAL_OFST);
*((uint16_t *)(imageData + i * sizeof(uint16_t))) =
(uint16_t)pixelVal;
}
}
int srcOffset = 0; int srcOffset = 0;
int srcOffset2 = DATA_BYTES / 2; int srcOffset2 = DATA_BYTES / 2;
int row0 = (numInterfaces == 1 ? detPos[1] : detPos[3]); int row0 = (numInterfaces == 1 ? detPos[1] : detPos[3]);
@ -2900,14 +2924,17 @@ int softwareTrigger(int block) {
LOG(logINFO, ("Sending Software Trigger\n")); LOG(logINFO, ("Sending Software Trigger\n"));
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_SOFTWARE_TRIGGER_MSK); bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_SOFTWARE_TRIGGER_MSK);
bus_w(CONTROL_REG, bus_r(CONTROL_REG) & ~CONTROL_SOFTWARE_TRIGGER_MSK); bus_w(CONTROL_REG, bus_r(CONTROL_REG) & ~CONTROL_SOFTWARE_TRIGGER_MSK);
// wait to make sure its out of this state and even 'wait for start frame'
usleep(100);
#ifndef VIRTUAL #ifndef VIRTUAL
// block till frame is sent out // block till frame sent out & back to wait for trigger (or not busy
// anymore)
if (block) { if (block) {
enum runStatus s = getRunStatus(); uint32_t retval = bus_r(STATUS_REG);
while (s == RUNNING || s == TRANSMITTING) { while ((retval & RUN_BUSY_MSK) && !(retval & WAITING_FOR_TRIGGER_MSK)) {
usleep(5000); usleep(5000);
s = getRunStatus(); retval = bus_r(STATUS_REG);
} }
} }
LOG(logINFO, ("Ready for Next Trigger...\n")); LOG(logINFO, ("Ready for Next Trigger...\n"));
@ -2940,9 +2967,16 @@ enum runStatus getRunStatus() {
u_int32_t retval = bus_r(STATUS_REG); u_int32_t retval = bus_r(STATUS_REG);
LOG(logINFO, ("Status Register: %08x\n", retval)); LOG(logINFO, ("Status Register: %08x\n", retval));
// error
if (retval & INTERNAL_STOP_MSK) {
LOG(logINFOBLUE, ("Status: ERROR\n"));
s = ERROR;
}
// running // running
if (retval & RUN_BUSY_MSK) { else if (retval & RUN_BUSY_MSK) {
if (retval & WAITING_FOR_TRIGGER_MSK) { if ((retval & WAITING_FOR_TRIGGER_MSK) ||
(retval & WAITING_FOR_START_FRAME_MSK)) {
LOG(logINFOBLUE, ("Status: WAITING\n")); LOG(logINFOBLUE, ("Status: WAITING\n"));
s = WAITING; s = WAITING;
} else { } else {
@ -2953,19 +2987,13 @@ enum runStatus getRunStatus() {
// not running // not running
else { else {
// stopped or error // stopped or idle
if (retval & STOPPED_MSK) { if (retval & STOPPED_MSK) {
LOG(logINFOBLUE, ("Status: STOPPED\n")); LOG(logINFOBLUE, ("Status: STOPPED\n"));
s = STOPPED; s = STOPPED;
} else if (retval & RUNMACHINE_BUSY_MSK) { } else {
LOG(logINFOBLUE, ("Status: READ MACHINE BUSY\n"));
s = TRANSMITTING;
} else if (!retval) {
LOG(logINFOBLUE, ("Status: IDLE\n")); LOG(logINFOBLUE, ("Status: IDLE\n"));
s = IDLE; s = IDLE;
} else {
LOG(logERROR, ("Status: Unknown status %08x\n", retval));
s = ERROR;
} }
} }

View File

@ -15,6 +15,11 @@ u_int32_t *csp0base = 0;
#define CSP0 0x20200000 #define CSP0 0x20200000
#define MEM_SIZE 0x100000 #define MEM_SIZE 0x100000
#ifdef JUNGFRAUD
extern void configureChip();
#endif
void bus_w16(u_int32_t offset, u_int16_t data) { void bus_w16(u_int32_t offset, u_int16_t data) {
volatile u_int16_t *ptr1; volatile u_int16_t *ptr1;
ptr1 = (u_int16_t *)(csp0base + offset / 2); ptr1 = (u_int16_t *)(csp0base + offset / 2);
@ -80,7 +85,21 @@ u_int32_t readRegister(u_int32_t offset) {
} }
u_int32_t writeRegister(u_int32_t offset, u_int32_t data) { u_int32_t writeRegister(u_int32_t offset, u_int32_t data) {
// if electron mode bit touched
#ifdef JUNGFRAUD
int electronCollectionModeChange = 0;
if ((offset << MEM_MAP_SHIFT) == DAQ_REG) {
if ((readRegister(offset) ^ data) & DAQ_ELCTRN_CLLCTN_MDE_MSK) {
electronCollectionModeChange = 1;
}
}
#endif
bus_w(offset << MEM_MAP_SHIFT, data); bus_w(offset << MEM_MAP_SHIFT, data);
#ifdef JUNGFRAUD
if (electronCollectionModeChange) {
configureChip();
}
#endif
return readRegister(offset); return readRegister(offset);
} }

View File

@ -532,6 +532,11 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
fflush(stdout); fflush(stdout);
FILE *sysFile = popen(cmd, "r"); FILE *sysFile = popen(cmd, "r");
if (sysFile == NULL) {
ret = FAIL;
sprintf(mess, "Executing cmd[%s] failed\n", cmd);
return ret;
}
while (fgets(temp, tempsize, sysFile) != NULL) { while (fgets(temp, tempsize, sysFile) != NULL) {
// size left excludes terminating character // size left excludes terminating character
size_t sizeleft = MAX_STR_LENGTH - strlen(result) - 1; size_t sizeleft = MAX_STR_LENGTH - strlen(result) - 1;
@ -547,17 +552,15 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
if (strlen(result) == 0) { if (strlen(result) == 0) {
strcpy(result, "No result"); strcpy(result, "No result");
} }
int retval = OK;
int success = pclose(sysFile); int success = pclose(sysFile);
if (success) { if (success == -1) {
retval = FAIL; ret = FAIL;
LOG(logERROR, ("Executing cmd[%s]:%s\n", cmd, result)); strcpy(mess, result);
LOG(logERROR, ("Executing cmd[%s] failed:%s\n", cmd, mess));
} else { } else {
LOG(level, ("Result:\n[%s]\n", result)); LOG(level, ("Result:\n[%s]\n", result));
} }
return ret;
return retval;
} }
int M_nofunc(int file_des) { int M_nofunc(int file_des) {
@ -585,7 +588,7 @@ int exec_command(int file_des) {
// set // set
if (Server_VerifyLock() == OK) { if (Server_VerifyLock() == OK) {
ret = executeCommand(cmd, retval, logINFO); executeCommand(cmd, retval, logINFO);
} }
return Server_SendResult(file_des, OTHER, retval, sizeof(retval)); return Server_SendResult(file_des, OTHER, retval, sizeof(retval));
} }
@ -1948,59 +1951,57 @@ int acquire(int blocking, int file_des) {
#ifdef EIGERD #ifdef EIGERD
// check for hardware mac and hardware ip // check for hardware mac and hardware ip
if (udpDetails[0].srcmac != getDetectorMAC()) { if (udpDetails[0].srcmac != getDetectorMAC()) {
ret = FAIL; ret = FAIL;
uint64_t sourcemac = getDetectorMAC(); uint64_t sourcemac = getDetectorMAC();
char src_mac[MAC_ADDRESS_SIZE]; char src_mac[MAC_ADDRESS_SIZE];
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac); getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
sprintf( sprintf(mess,
mess,
"Invalid udp source mac address for this detector. Must be " "Invalid udp source mac address for this detector. Must be "
"same as hardware detector mac address %s\n", "same as hardware detector mac address %s\n",
src_mac); src_mac);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else if (!enableTenGigabitEthernet(GET_FLAG) && } else if (!enableTenGigabitEthernet(GET_FLAG) &&
(udpDetails[0].srcip != getDetectorIP())) { (udpDetails[0].srcip != getDetectorIP())) {
ret = FAIL; ret = FAIL;
uint32_t sourceip = getDetectorIP(); uint32_t sourceip = getDetectorIP();
char src_ip[INET_ADDRSTRLEN]; char src_ip[INET_ADDRSTRLEN];
getIpAddressinString(src_ip, sourceip); getIpAddressinString(src_ip, sourceip);
sprintf( sprintf(mess,
mess,
"Invalid udp source ip address for this detector. Must be " "Invalid udp source ip address for this detector. Must be "
"same as hardware detector ip address %s in 1G readout " "same as hardware detector ip address %s in 1G readout "
"mode \n", "mode \n",
src_ip); src_ip);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else } else
#endif #endif
if (configured == FAIL) { if (configured == FAIL) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because ");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else if (sharedMemory_getScanStatus() == RUNNING) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because a scan is "
"already running!\n");
LOG(logERROR, (mess));
} else {
memset(scanErrMessage, 0, MAX_STR_LENGTH);
sharedMemory_setScanStop(0);
sharedMemory_setScanStatus(IDLE); // if it was error
if (pthread_create(&pthread_tid, NULL, &start_state_machine,
&blocking)) {
ret = FAIL; ret = FAIL;
strcpy(mess, "Could not start acquisition because "); strcpy(mess, "Could not start acquisition thread!\n");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else if (sharedMemory_getScanStatus() == RUNNING) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because a scan is "
"already running!\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else { } else {
memset(scanErrMessage, 0, MAX_STR_LENGTH); // wait for blocking always (scan or not)
sharedMemory_setScanStop(0); // non blocking-no scan also wait (for error message)
sharedMemory_setScanStatus(IDLE); // if it was error // non blcoking-scan dont wait (there is scanErrorMessage)
if (pthread_create(&pthread_tid, NULL, &start_state_machine, if (blocking || !scan) {
&blocking)) { pthread_join(pthread_tid, NULL);
ret = FAIL;
strcpy(mess, "Could not start acquisition thread!\n");
LOG(logERROR, (mess));
} else {
// wait for blocking always (scan or not)
// non blocking-no scan also wait (for error message)
// non blcoking-scan dont wait (there is scanErrorMessage)
if (blocking || !scan) {
pthread_join(pthread_tid, NULL);
}
} }
} }
}
} }
return Server_SendResult(file_des, INT32, NULL, 0); return Server_SendResult(file_des, INT32, NULL, 0);
} }
@ -4771,7 +4772,8 @@ int set_read_n_rows(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if ((Server_VerifyLock() == OK) &&
(check_detector_idle("set number of rows") == OK)) {
if (arg < MIN_ROWS_PER_READOUT || arg > MAX_ROWS_PER_READOUT) { if (arg < MIN_ROWS_PER_READOUT || arg > MAX_ROWS_PER_READOUT) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
@ -4803,8 +4805,7 @@ int set_read_n_rows(int file_des) {
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else } else
#elif defined(JUNGFRAUD) || defined(MOENCHD) #elif defined(JUNGFRAUD) || defined(MOENCHD)
if ((check_detector_idle("set number of rows") == OK) && if (arg % READ_N_ROWS_MULTIPLE != 0) {
(arg % READ_N_ROWS_MULTIPLE != 0)) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not set number of rows. %d must be a multiple " "Could not set number of rows. %d must be a multiple "
@ -8471,9 +8472,9 @@ int set_master(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if ((Server_VerifyLock() == OK) &&
if ((check_detector_idle("set master") == OK) && (check_detector_idle("set master") == OK)) {
(arg != 0 && arg != 1)) { if (arg != 0 && arg != 1) {
ret = FAIL; ret = FAIL;
sprintf(mess, "Could not set master. Invalid argument %d.\n", arg); sprintf(mess, "Could not set master. Invalid argument %d.\n", arg);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
@ -9027,9 +9028,9 @@ int set_flip_rows(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if ((Server_VerifyLock() == OK) &&
if ((check_detector_idle("set flip rows") == OK) && (check_detector_idle("set flip rows") == OK)) {
(arg != 0 && arg != 1)) { if (arg != 0 && arg != 1) {
ret = FAIL; ret = FAIL;
sprintf(mess, "Could not set flip rows. Invalid argument %d.\n", sprintf(mess, "Could not set flip rows. Invalid argument %d.\n",
arg); arg);
@ -10364,9 +10365,9 @@ int set_synchronization(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if ((Server_VerifyLock() == OK) &&
if ((check_detector_idle("set synchronization") == OK) && (check_detector_idle("set synchronization") == OK)) {
(arg != 0 && arg != 1)) { if (arg != 0 && arg != 1) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not set synchronization. Invalid argument %d.\n", "Could not set synchronization. Invalid argument %d.\n",

View File

@ -216,7 +216,10 @@ class Detector {
/** [Jungfrau][Moench] **/ /** [Jungfrau][Moench] **/
Result<bool> getSynchronization(Positions pos = {}) const; Result<bool> getSynchronization(Positions pos = {}) const;
/** [Jungfrau][Moench] */ /** [Jungfrau][Moench] Sync mode requires at least one master configured.
Also requires flatband cabling between master and slave with
termination board.
*/
void setSynchronization(bool value); void setSynchronization(bool value);
/** [Gotthard2][Mythen3] */ /** [Gotthard2][Mythen3] */

View File

@ -8,7 +8,8 @@
* from the detector. Since every module could have a different value, we need * from the detector. Since every module could have a different value, we need
* to return a vector instead of just a single value. * to return a vector instead of just a single value.
* *
* Easy conversions to single values are provided using the squash method. * Easy conversions to single values are provided using the squash and tsquash
* method.
*/ */
#include <algorithm> #include <algorithm>
@ -16,6 +17,7 @@
#include <vector> #include <vector>
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/TypeTraits.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
namespace sls { namespace sls {
@ -128,6 +130,25 @@ template <class T, class Allocator = std::allocator<T>> class Result {
/** Test whether all elements of the result are equal */ /** Test whether all elements of the result are equal */
bool equal() const noexcept { return allEqual(vec); } bool equal() const noexcept { return allEqual(vec); }
/** Test whether any element of the result are equal to a value */
bool any(const T &value) const noexcept { return anyEqualTo(vec, value); }
template <typename V, typename... Args, typename = AllSame<V, Args...>>
typename std::enable_if<std::is_same<V, T>::value, bool>::type
contains_only(const V &a, const Args &...args) const noexcept {
auto values = {a, args...};
for (const auto &element : vec) {
int found = 0;
for (const auto &value : values) {
if (value == element)
found++;
}
if (!found)
return false;
}
return true;
}
/** Convert Result<T> to std::vector<T> */ /** Convert Result<T> to std::vector<T> */
operator std::vector<T>() { return vec; } operator std::vector<T>() { return vec; }
}; };

View File

@ -1543,7 +1543,9 @@ class CmdProxy {
INTEGER_COMMAND_SET_NOID_GET_ID( INTEGER_COMMAND_SET_NOID_GET_ID(
sync, getSynchronization, setSynchronization, StringTo<int>, sync, getSynchronization, setSynchronization, StringTo<int>,
"[0, 1]\n\t[Jungfrau][Moench] Enables or disables " "[0, 1]\n\t[Jungfrau][Moench] Enables or disables "
"synchronization between modules."); "synchronization between modules. Sync mode requires at least one "
"master configured. Also requires flatband cabling between master and "
"slave with termination board.");
INTEGER_COMMAND_VEC_ID(row, getRow, setRow, StringTo<int>, INTEGER_COMMAND_VEC_ID(row, getRow, setRow, StringTo<int>,
"[value]\n\tSet Detector row (udp header) to value. " "[value]\n\tSet Detector row (udp header) to value. "

View File

@ -18,6 +18,7 @@
#include <chrono> #include <chrono>
#include <fstream> #include <fstream>
#include <set>
#include <thread> #include <thread>
namespace sls { namespace sls {
@ -873,18 +874,26 @@ void Detector::startDetectorReadout() {
void Detector::stopDetector(Positions pos) { void Detector::stopDetector(Positions pos) {
// stop and check status X times
int retries{0}; int retries{0};
// avoid default construction of runStatus::IDLE on squash auto status = getDetectorStatus(pos);
auto status = getDetectorStatus().squash(defs::runStatus::RUNNING);
while (status != defs::runStatus::IDLE && // jf sync fix: status [stopped or idle] = [stopped]
status != defs::runStatus::STOPPED) { // sync issue: (master idle sometimes, slaves stopped)
if (status == defs::runStatus::ERROR) {
throw RuntimeError( // eiger fix: stop multiple times from multi client till all modules stopped
"Could not stop detector. Returned error status."); // issue: asynchronous start and stop scripts with a module being started
// (stop before) and waiting for the other to be done. So a module that was
// idle before stopping will return running (after async start script) when
// getting status after, which will then be stopped again.
while (!status.contains_only(defs::runStatus::IDLE,
defs::runStatus::STOPPED)) {
if (status.any(defs::runStatus::ERROR)) {
throw RuntimeError("Could not stop detector. At least one module "
"returned error status.");
} }
pimpl->stopDetector(pos); pimpl->stopDetector(pos);
status = getDetectorStatus().squash(defs::runStatus::RUNNING); status = getDetectorStatus(pos);
++retries; ++retries;
if (retries == 10) if (retries == 10)
@ -903,7 +912,7 @@ void Detector::stopDetector(Positions pos) {
for (auto it : res) { for (auto it : res) {
maxVal = std::max(maxVal, it); maxVal = std::max(maxVal, it);
} }
setNextFrameNumber(maxVal + 1); setNextFrameNumber(maxVal + 1, pos);
} }
} break; } break;
default: default:

View File

@ -1220,10 +1220,26 @@ int DetectorImpl::acquire() {
dataProcessingThread.join(); dataProcessingThread.join();
if (acquisition_finished != nullptr) { if (acquisition_finished != nullptr) {
int status = Parallel(&Module::getRunStatus, {}).squash(ERROR); // status
runStatus status = IDLE;
auto statusList = Parallel(&Module::getRunStatus, {});
status = statusList.squash(ERROR);
// difference, but none error
if (status == ERROR && (!statusList.any(ERROR))) {
// handle jf sync issue (master idle, slaves stopped)
if (statusList.contains_only(IDLE, STOPPED)) {
status = STOPPED;
} else
status = statusList.squash(RUNNING);
}
// progress
auto a = Parallel(&Module::getReceiverProgress, {}); auto a = Parallel(&Module::getReceiverProgress, {});
double progress = (*std::max_element(a.begin(), a.end())); double progress = (*std::max_element(a.begin(), a.end()));
acquisition_finished(progress, status, acqFinished_p);
// callback
acquisition_finished(progress, static_cast<int>(status),
acqFinished_p);
} }
clock_gettime(CLOCK_REALTIME, &end); clock_gettime(CLOCK_REALTIME, &end);
@ -1293,13 +1309,24 @@ void DetectorImpl::startAcquisition(const bool blocking, Positions pos) {
std::vector<int> masters; std::vector<int> masters;
std::vector<int> slaves; std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves); getMasterSlaveList(pos, masters, slaves);
if (masters.empty()) {
throw RuntimeError("Cannot start acquisition in sync mode. No "
"master module found");
}
if (!slaves.empty()) { if (!slaves.empty()) {
Parallel(&Module::startAcquisition, slaves); Parallel(&Module::startAcquisition, slaves);
} }
if (!masters.empty()) { if (blocking) {
Parallel((blocking ? &Module::startAndReadAll Parallel(&Module::startAndReadAll, masters);
: &Module::startAcquisition), // ensure all status normal (slaves not blocking)
masters); // to catch those slaves that are still 'waiting'
auto status = Parallel(&Module::getRunStatus, pos);
if (!status.contains_only(IDLE, STOPPED, RUN_FINISHED)) {
throw RuntimeError("Acquisition not successful. "
"Unexpected detector status");
}
} else {
Parallel(&Module::startAcquisition, masters);
} }
} }
// all in parallel // all in parallel

View File

@ -84,9 +84,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/ */
virtual ~DetectorImpl(); virtual ~DetectorImpl();
template <class CT> struct NonDeduced { template <class CT> struct NonDeduced { using type = CT; };
using type = CT;
};
template <typename RT, typename... CT> template <typename RT, typename... CT>
Result<RT> Parallel(RT (Module::*somefunc)(CT...), Result<RT> Parallel(RT (Module::*somefunc)(CT...),
std::vector<int> positions, std::vector<int> positions,

View File

@ -356,15 +356,29 @@ TEST_CASE("powerindex", "[.cmd]") {
TEST_CASE("powervalues", "[.cmd]") { TEST_CASE("powervalues", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
REQUIRE_NOTHROW(proxy.Call("powervalues", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("powervalues", {}, -1, PUT)); auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
REQUIRE_NOTHROW(proxy.Call("powervalues", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("powervalues", {}, -1, PUT));
} else {
REQUIRE_THROWS(proxy.Call("powervalues", {}, -1, GET));
}
} }
TEST_CASE("slowadcvalues", "[.cmd]") { TEST_CASE("slowadcvalues", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
REQUIRE_NOTHROW(proxy.Call("slowadcvalues", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("slowadcvalues", {}, -1, PUT)); auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
REQUIRE_NOTHROW(proxy.Call("slowadcvalues", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("slowadcvalues", {}, -1, PUT));
} else {
REQUIRE_THROWS(proxy.Call("slowadcvalues", {}, -1, GET));
}
} }
TEST_CASE("slowadclist", "[.cmd]") { TEST_CASE("slowadclist", "[.cmd]") {

View File

@ -689,10 +689,11 @@ TEST_CASE("confadc", "[.cmd]") {
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
int ndet = det.size(); const int ndet = det.size();
int nchip = 10; const int nchip = 10;
int nadc = 32; const int nadc = 32;
int prev_val[ndet][nchip][nadc]; std::vector<std::vector<std::vector<int>>> prev_val(
ndet, std::vector<std::vector<int>>(nchip, std::vector<int>(nadc)));
for (int i = 0; i != ndet; ++i) { for (int i = 0; i != ndet; ++i) {
for (int j = 0; j != nchip; ++j) { for (int j = 0; j != nchip; ++j) {
for (int k = 0; k != nadc; ++k) { for (int k = 0; k != nadc; ++k) {

View File

@ -23,7 +23,7 @@ TEST_CASE("Setting and reading back Jungfrau dacs", "[.cmd][.dacs]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::MOENCH) { if (det_type == defs::JUNGFRAU) {
SECTION("vb_comp") { test_dac(defs::VB_COMP, "vb_comp", 1220); } SECTION("vb_comp") { test_dac(defs::VB_COMP, "vb_comp", 1220); }
SECTION("vdd_prot") { test_dac(defs::VDD_PROT, "vdd_prot", 3000); } SECTION("vdd_prot") { test_dac(defs::VDD_PROT, "vdd_prot", 3000); }
SECTION("vin_com") { test_dac(defs::VIN_COM, "vin_com", 1053); } SECTION("vin_com") { test_dac(defs::VIN_COM, "vin_com", 1053); }
@ -163,7 +163,7 @@ TEST_CASE("chipversion", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::MOENCH) { if (det_type == defs::JUNGFRAU) {
REQUIRE_NOTHROW(proxy.Call("chipversion", {}, -1, GET)); REQUIRE_NOTHROW(proxy.Call("chipversion", {}, -1, GET));
} else { } else {
REQUIRE_THROWS(proxy.Call("chipversion", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("chipversion", {}, -1, GET));
@ -705,6 +705,34 @@ TEST_CASE("sync", "[.cmd]") {
proxy.Call("sync", {}, -1, GET, oss); proxy.Call("sync", {}, -1, GET, oss);
REQUIRE(oss.str() == "sync 1\n"); REQUIRE(oss.str() == "sync 1\n");
} }
// setting sync when running
{
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode in test");
auto prev_frames =
det.getNumberOfFrames().tsquash("inconsistent #frames in test");
auto prev_exptime =
det.getExptime().tsquash("inconsistent exptime in test");
auto prev_period =
det.getPeriod().tsquash("inconsistent period in test");
det.setTimingMode(defs::AUTO_TIMING);
det.setNumberOfFrames(10000);
det.setExptime(std::chrono::microseconds(200));
det.setPeriod(std::chrono::milliseconds(1000));
det.setSynchronization(1);
det.startDetector();
REQUIRE_THROWS(proxy.Call("sync", {"0"}, -1, PUT));
{
std::ostringstream oss;
proxy.Call("sync", {}, -1, GET, oss);
REQUIRE(oss.str() == "sync 1\n");
}
det.stopDetector();
det.setTimingMode(prev_timing);
det.setNumberOfFrames(prev_frames);
det.setExptime(prev_exptime);
det.setPeriod(prev_period);
}
det.setSynchronization(prev_val); det.setSynchronization(prev_val);
} else { } else {
REQUIRE_THROWS(proxy.Call("sync", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("sync", {}, -1, GET));

View File

@ -18,5 +18,92 @@ using test::GET;
using test::PUT; using test::PUT;
/* dacs */ /* dacs */
TEST_CASE("Setting and reading back moench dacs", "[.cmd][.dacs]") {
// vbp_colbuf, vipre, vin_cm, vb_sda, vcasc_sfp, vout_cm, vipre_cds,
// ibias_sfp
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::MOENCH) {
SECTION("vbp_colbuf") {
test_dac(defs::VBP_COLBUF, "vbp_colbuf", 1300);
}
SECTION("vipre") { test_dac(defs::VIPRE, "vipre", 1000); }
SECTION("vin_cm") { test_dac(defs::VIN_CM, "vin_cm", 1400); }
SECTION("vb_sda") { test_dac(defs::VB_SDA, "vb_sda", 680); }
SECTION("vcasc_sfp") { test_dac(defs::VCASC_SFP, "vcasc_sfp", 1428); }
SECTION("vout_cm") { test_dac(defs::VOUT_CM, "vout_cm", 1200); }
SECTION("vipre_cds") { test_dac(defs::VIPRE_CDS, "vipre_cds", 800); }
SECTION("ibias_sfp") { test_dac(defs::IBIAS_SFP, "ibias_sfp", 900); }
// eiger
REQUIRE_THROWS(proxy.Call("vthreshold", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vsvp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vsvn", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vtrim", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vrpreamp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vrshaper", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vtgstv", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcmp_ll", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcmp_lr", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcal", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcmp_rl", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcmp_rr", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("rxb_rb", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("rxb_lb", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcn", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vishaper", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("iodelay", {}, -1, GET));
// gotthard
REQUIRE_THROWS(proxy.Call("vref_ds", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcascn_pb", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcascp_pb", {}, -1, GET));
// REQUIRE_THROWS(proxy.Call("vout_cm", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcasc_out", {}, -1, GET));
// REQUIRE_THROWS(proxy.Call("vin_cm", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_comp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("ib_test_c", {}, -1, GET));
// mythen3
REQUIRE_THROWS(proxy.Call("vrpreamp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vrshaper", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vrshaper_n", {}, -1, GET));
// REQUIRE_THROWS(proxy.Call("vipre", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vishaper", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vdcsh", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vth1", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vth2", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vth3", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcal_n", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcal_p", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vtrim", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcassh", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcas", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vicin", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vipre_out", {}, -1, GET));
// gotthard2
REQUIRE_THROWS(proxy.Call("vref_h_adc", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_comp_fe", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_comp_adc", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcom_cds", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_rstore", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_opa_1st", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_comp_fe", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcom_adc1", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_l_adc", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_cds", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_cs", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_opa_fd", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vcom_adc2", {}, -1, GET));
// jungfrau
REQUIRE_THROWS(proxy.Call("vb_comp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vdd_prot", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vin_com", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_prech", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_pixbuf", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vb_ds", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_ds", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vref_comp", {}, -1, GET));
}
}
} // namespace sls } // namespace sls

View File

@ -2064,7 +2064,7 @@ TEST_CASE("defaultdac", "[.cmd]") {
det.setDefaultDac(it, prev_val[i], {i}); det.setDefaultDac(it, prev_val[i], {i});
} }
} }
if (det_type == defs::JUNGFRAU || det_type == defs::MOENCH) { if (det_type == defs::JUNGFRAU) {
std::vector<defs::dacIndex> daclist = { std::vector<defs::dacIndex> daclist = {
defs::VREF_PRECH, defs::VREF_DS, defs::VREF_COMP}; defs::VREF_PRECH, defs::VREF_DS, defs::VREF_COMP};
for (auto it : daclist) { for (auto it : daclist) {
@ -2417,10 +2417,13 @@ TEST_CASE("scan", "[.cmd]") {
notImplementedInd = defs::VCASCP_PB; notImplementedInd = defs::VCASCP_PB;
break; break;
case defs::JUNGFRAU: case defs::JUNGFRAU:
case defs::MOENCH:
ind = defs::VB_COMP; ind = defs::VB_COMP;
notImplementedInd = defs::VSVP; notImplementedInd = defs::VSVP;
break; break;
case defs::MOENCH:
ind = defs::VIN_CM;
notImplementedInd = defs::VSVP;
break;
case defs::GOTTHARD: case defs::GOTTHARD:
ind = defs::VREF_DS; ind = defs::VREF_DS;
notImplementedInd = defs::VSVP; notImplementedInd = defs::VSVP;
@ -3472,7 +3475,7 @@ TEST_CASE("lock", "[.cmd]") {
TEST_CASE("execcommand", "[.cmd]") { TEST_CASE("execcommand", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
REQUIRE_NOTHROW(proxy.Call("execcommand", {"ls"}, -1, PUT)); REQUIRE_NOTHROW(proxy.Call("execcommand", {"ls *.txt"}, -1, PUT));
} }
TEST_CASE("framecounter", "[.cmd]") { TEST_CASE("framecounter", "[.cmd]") {

View File

@ -196,4 +196,24 @@ TEST_CASE("String conversions") {
"[{one: 1}, {one: 1, three: 3, two: 2}, {one: 1}]"); "[{one: 1}, {one: 1, three: 3, two: 2}, {one: 1}]");
} }
TEST_CASE("Any element is equal") {
Result<int> r{1, 2, 3, 4, 5};
REQUIRE(r.any(3));
REQUIRE_FALSE(r.any(9));
}
TEST_CASE("Result contains only the specified elements") {
Result<int> r{1, 1, 1};
REQUIRE(r.contains_only(1));
REQUIRE(r.contains_only(1, 1));
}
TEST_CASE("Only with multiple values") {
Result<int> r{1, 1, 2, 1, 2, 1, 1};
REQUIRE_FALSE(r.contains_only(1));
REQUIRE_FALSE(r.contains_only(2));
REQUIRE(r.contains_only(1, 2));
REQUIRE(r.contains_only(2, 1));
}
} // namespace sls } // namespace sls

View File

@ -103,4 +103,13 @@ template <typename T> struct is_vector : public std::false_type {};
template <typename T> template <typename T>
struct is_vector<std::vector<T>> : public std::true_type {}; struct is_vector<std::vector<T>> : public std::true_type {};
template <class...> struct Conjunction : std::true_type {};
template <class B1> struct Conjunction<B1> : B1 {};
template <class B1, class... Bn>
struct Conjunction<B1, Bn...>
: std::conditional<bool(B1::value), Conjunction<Bn...>, B1>::type {};
template <typename T, typename... Ts>
using AllSame =
typename std::enable_if<Conjunction<std::is_same<T, Ts>...>::value>::type;
} // namespace sls } // namespace sls

View File

@ -1,13 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-other // SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
/** API versions */ /** API versions */
#define RELEASE "developer" #define RELEASE "8.0.0"
#define APILIB "developer 0x230224" #define APILIB "8.0.0 0x231108"
#define APIRECEIVER "developer 0x230224" #define APIRECEIVER "8.0.0 0x231108"
#define APICTB "developer 0x230922" #define APICTB "8.0.0 0x231109"
#define APIGOTTHARD "developer 0x230922" #define APIGOTTHARD "8.0.0 0x231109"
#define APIGOTTHARD2 "developer 0x230922" #define APIGOTTHARD2 "8.0.0 0x231109"
#define APIMYTHEN3 "developer 0x230922" #define APIJUNGFRAU "8.0.0 0x231109"
#define APIMOENCH "developer 0x230922" #define APIMYTHEN3 "8.0.0 0x231109"
#define APIEIGER "developer 0x230922" #define APIMOENCH "8.0.0 0x231109"
#define APIJUNGFRAU "developer 0x230928" #define APIEIGER "8.0.0 0x231109"

View File

@ -4,7 +4,7 @@
This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers. This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers.
''' '''
import argparse import argparse
import os, sys, subprocess, time, colorama, signal, psutil import os, sys, subprocess, time, colorama, signal
from colorama import Fore from colorama import Fore
from slsdet import Detector, detectorType, detectorSettings from slsdet import Detector, detectorType, detectorSettings
@ -21,29 +21,37 @@ class RuntimeException (Exception):
def Log(color, message): def Log(color, message):
print('\n' + color + message, flush=True) print('\n' + color + message, flush=True)
def checkIfProcessRunning(processName): def checkIfProcessRunning(processName):
''' cmd = "ps -ef | grep " + processName
Check if there is any running process that contains the given name processName. print(cmd)
https://gist.github.com/Sanix-Darker/8cbed2ff6f8eb108ce2c8c51acd2aa5a res=subprocess.getoutput(cmd)
''' print(res)
# Iterate over the all the running process # eg. of output
for proc in psutil.process_iter(): #l_user 250506 243295 0 14:38 pts/5 00:00:00 /bin/sh -c ps -ef | grep slsReceiver
try: #l_user 250508 250506 0 14:38 pts/5 00:00:00 grep slsReceiver
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower(): print('how many')
return True cmd = "ps -ef | grep " + processName + " | wc -l"
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): print(cmd)
pass res=subprocess.getoutput(cmd)
return False; print(res)
if res == '2':
return False
return True
def killProcess(name): def killProcess(name):
if checkIfProcessRunning(name): if checkIfProcessRunning(name):
Log(Fore.GREEN, 'killing ' + name) Log(Fore.GREEN, 'killing ' + name)
p = subprocess.run(['killall', name]) p = subprocess.run(['killall', name])
if p.returncode != 0: if p.returncode != 0:
raise RuntimeException('error in killall ' + name) raise RuntimeException('killall failed for ' + name)
else:
print('process not running : ' + name)
def cleanup(name, d): def cleanup(name):
''' '''
kill both servers, receivers and clean shared memory kill both servers, receivers and clean shared memory
''' '''
@ -51,18 +59,27 @@ def cleanup(name, d):
killProcess(name + 'DetectorServer_virtual') killProcess(name + 'DetectorServer_virtual')
killProcess('slsReceiver') killProcess('slsReceiver')
killProcess('slsMultiReceiver') killProcess('slsMultiReceiver')
d.freeSharedMemory() cleanSharedmemory()
def cleanSharedmemory():
Log(Fore.GREEN, 'Cleaning up shared memory...')
try:
p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp)
except:
Log(Fore.RED, 'Could not free shared memory')
raise
def startProcessInBackground(name): def startProcessInBackground(name):
try: try:
# in background and dont print output # in background and dont print output
p = subprocess.Popen(name.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) p = subprocess.Popen(name.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False)
Log(Fore.GREEN, 'Starting up ' + name + ' ...') Log(Fore.GREEN, 'Starting up ' + name + ' ...')
except: except:
Log(Fore.RED, 'Could not start ' + name) Log(Fore.RED, 'Could not start ' + name)
raise raise
def startServer(name): def startServer(name):
startProcessInBackground(name + 'DetectorServer_virtual') startProcessInBackground(name + 'DetectorServer_virtual')
# second half # second half
if name == 'eiger': if name == 'eiger':
@ -79,6 +96,7 @@ def startReceiver(name):
time.sleep(2) time.sleep(2)
def loadConfig(name, rx_hostname, settingsdir): def loadConfig(name, rx_hostname, settingsdir):
Log(Fore.GREEN, 'Loading config')
try: try:
d = Detector() d = Detector()
if name == 'eiger': if name == 'eiger':
@ -106,25 +124,36 @@ def loadConfig(name, rx_hostname, settingsdir):
Log(Fore.RED, 'Could not load config for ' + name) Log(Fore.RED, 'Could not load config for ' + name)
raise raise
def startCmdTests(name, fp): def startCmdTests(name, fp, fname):
try: Log(Fore.GREEN, 'Cmd Tests for ' + name)
p = subprocess.run(['tests', '--abort', '[.cmd]'], stdout=fp, stderr=fp) cmd = 'tests --abort [.cmd] -s -o ' + fname
if p.returncode != 0: p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
raise Exception p.check_returncode()
except:
Log(Fore.RED, 'Cmd tests failed for ' + name) with open (fname, 'r') as f:
raise for line in f:
if "FAILED" in line:
msg = 'Cmd tests failed for ' + name + '!!!'
Log(Fore.RED, msg)
raise Exception(msg)
Log(Fore.GREEN, 'Cmd Tests successful for ' + name)
def startGeneralTests(fp, fname):
Log(Fore.GREEN, 'General Tests')
cmd = 'tests --abort -s -o ' + fname
p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
p.check_returncode()
with open (fname, 'r') as f:
for line in f:
if "FAILED" in line:
msg = 'General tests failed !!!'
Log(Fore.RED, msg)
raise Exception(msg)
Log(Fore.GREEN, 'General Tests successful')
def startNormalTests(d, fp):
try:
Log(Fore.BLUE, '\nNormal tests')
p = subprocess.run(['tests', '--abort' ], stdout=fp, stderr=fp)
if p.returncode != 0:
raise Exception
d.freeSharedMemory()
except:
Log(Fore.RED, 'Normal tests failed')
raise
# parse cmd line for rx_hostname and settingspath using the argparse library # parse cmd line for rx_hostname and settingspath using the argparse library
@ -149,46 +178,51 @@ if args.servers is None:
else: else:
servers = args.servers servers = args.servers
Log(Fore.WHITE, 'rx_hostname: ' + args.rx_hostname + '\settingspath: \'' + args.settingspath + '\'')
Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\'')
# handle zombies (else killing slsReceivers will fail)
# dont care about child process success
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
# redirect to file # redirect to file
prefix_fname = '/tmp/slsDetectorPackage_virtual_test'
original_stdout = sys.stdout original_stdout = sys.stdout
original_stderr = sys.stderr original_stderr = sys.stderr
fname = '/tmp/slsDetectorPackage_virtual_test.txt' fname = prefix_fname + '_log.txt'
Log(Fore.BLUE, 'Tests -> ' + fname) Log(Fore.BLUE, '\nLog File: ' + fname)
with open(fname, 'w') as fp: with open(fname, 'w') as fp:
# general tests
file_results = prefix_fname + '_results_general.txt'
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
sys.stdout = fp sys.stdout = fp
sys.stderr = fp sys.stderr = fp
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
d = Detector() startGeneralTests(fp, file_results)
# TODO: redirect Detector object print out also to file
startNormalTests(d, fp)
for server in servers: for server in servers:
try: try:
# print to terminal for progress # print to terminal for progress
sys.stdout = original_stdout sys.stdout = original_stdout
sys.stderr = original_stderr sys.stderr = original_stderr
Log(Fore.BLUE, server + ' tests') file_results = prefix_fname + '_results_cmd_' + server + '.txt'
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
sys.stdout = fp sys.stdout = fp
sys.stderr = fp sys.stderr = fp
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
# cmd tests for det # cmd tests for det
Log(Fore.BLUE, 'Cmd Tests for ' + server) cleanup(server)
cleanup(server, d)
startServer(server) startServer(server)
startReceiver(server) startReceiver(server)
loadConfig(server, args.rx_hostname, args.settingspath) loadConfig(server, args.rx_hostname, args.settingspath)
startCmdTests(server, fp) startCmdTests(server, fp, file_results)
cleanup(server, d) cleanup(server)
except: except:
cleanup(server, d) Log(log.RED, 'Exception caught. Cleaning up.')
cleanup(server)
sys.stdout = original_stdout
sys.stderr = original_stderr
Log(Fore.RED, 'Cmd tests failed for ' + server + '!!!')
raise raise