Compare commits

..

37 Commits

Author SHA1 Message Date
0251aa9e63 fixed linking issue in arping and shm test (#659)
Co-authored-by: Erik Frojdh <erik.frojdh@psi.ch>
2023-02-14 14:49:00 +01:00
7c047cab4a udpated version to rc4 2023-02-14 10:30:45 +01:00
572332f870 fix test for eiger half module for gap pixels (#658) 2023-02-14 09:22:32 +01:00
d90bf6c7df formatting 2023-02-13 11:36:41 +01:00
5c8c3ae3f3 fix to access to shared memory that doesnt exist (#638)
* fix to access to shared memory that doesnt exist

* fix for freeing shm and then setting hostname from API

* exception error message moved to private function

* refactoring to avoid allocating intermediate string
2023-02-13 11:29:54 +01:00
18136fed9d exception messages (#656)
* fix exception messages for more printout about sockets or more detail
2023-02-13 11:22:05 +01:00
fc42720208 allow half modules and odd number of half modules to use the gui with gap pixels disabled (#655) 2023-02-13 11:21:35 +01:00
e6505650cb proper update of client and rx versions to 7.0.0.rc3 2023-02-10 16:34:04 +01:00
ba6fdb9695 udpated client and rx versions to rc3 2023-02-10 16:04:32 +01:00
8361f2bb96 zmq: set zmq buffer size also to 0 if hwm >= 25 (#653) 2023-02-10 08:57:36 +01:00
4ee4d66977 Jf zeromq display (#644)
* modified ZmqSocket to expose the SO_RCVBUF and SO_SENDBUF parameters. Modified DataStreamer.cpp to change the SENDBUF to 1MB when HWL is <10. Modified Datastreamer.cpp so that when HWL is changed, socket is unbind/rebind. Added rebind to ZmqSocket.cpp.
Changed slot UpdatePlot() in qdrawplot.h from privat tto public, added plot->UpdatePlot() after every axis range change, so the plots are updated immediatly and not at the next image.
Added onlinedisp_zmq program which connects to the receiver ZMQ port and show images and histos. Compiled against  ROOT 6.22/02. Added examples files.

* added setbuffer size also for gui, moved hardcoded values to a macro, removed unnecessary return of ok or success, added actual zmq exception message to could not create sockets error

* zmq: changing buffer size done within hwm

---------

Co-authored-by: mozzanica <l_mozzanica@mpc2012.psi.ch>
Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
2023-02-09 17:24:28 +01:00
e14f6981a0 Fix tests (#647)
* fixes tests
2023-02-09 15:57:05 +01:00
8158ef876c eiger: quad write/read reg (dr) and quad positions (#649)
* eiger: adding mask to read/write registers. useful for setting quad parameters as they might have different values for left and right fpga registers.
** fix quad position
* fix quad flipping
* formatting
2023-02-09 15:55:35 +01:00
ebb6f53b21 Fix rx arping socket bind (#646)
* first tries with a process intead of thread for rx_arping

* Moving delete pointer of udp socket to stopReciever,so rx_arping can only be set when udp socket is closed

* refactoring and formatting

* unused variable processId

* ignore sigchild to prevent zombie from child processes being killed
2023-02-03 17:18:09 +01:00
e172df79f3 format 2023-02-03 11:23:19 +01:00
55bf73f3b7 unicast udp_srcmac (#642)
* udp_srcmac can only be a unicast address (LSB of first octet must be 0)

* renamed binaries
2023-02-03 10:56:19 +01:00
c62ce0ce6b m3:changed str_clk (clkdiv 3) default to 166MHz (6) (#643) 2023-01-30 17:05:42 +01:00
3a3628c475 m3 firmware version change (#637)
* m3 firmware version change

* changed binary name to rc3
2023-01-27 10:54:45 +01:00
9ba907f9f7 added none or 0 to unset bad channels (#632)
* added none or 0 to unset bad channels

* free function split to get int array from string of arguments for badchannels

* missed a file

* allowing list for badchannels in command line

* added badchannels in python

* added size check

* more comments in Detector.h and added more tests for facny command line badchannels

* removeDuplicates accept any container, added tests

* corner cases: 1:5,6,7 or 5,6,7 or just 1:5

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
2023-01-27 09:59:31 +01:00
3f7c9529dd m3: changed clk 0 1 2 to 100MHz (#636)
* m3: changed clk 0 1 2 to 100MHz

* m3:fix clk 2

* binaries in
2023-01-25 11:54:37 +01:00
c7af9c9f3e fix for versions command in python failing for eiger due to hardware version not implemented (#602) 2023-01-24 11:05:32 +01:00
0b17318f10 formatting 2023-01-24 10:37:52 +01:00
1f907b911e added documentation about zmq json header (#629)
* added documentation about zmq json header

* fix from 7.0.0 field name changes in zmq header
2023-01-23 14:15:14 +01:00
c5b621b684 intialize pattern addresses with default, else they are created with value 0 and overwrite the default in server (#628) 2023-01-23 10:59:18 +01:00
946e6aa817 badchannel segfault for multi module (#620)
* badchannels segfaults when there are no badchannels for next modules, fixed

* added example badchannels

* refactoring casting
2023-01-20 17:39:25 +01:00
3682644e15 incorrectly using detsize, caught and fixing it in background (#619) 2023-01-19 11:10:05 +01:00
a6aaa2c3c6 adding fliprows to python (#625) 2023-01-19 11:03:04 +01:00
ac64afe747 print also the level when using command line to set/get patloop, patnloop, patwait, patwaittime (#621) 2023-01-19 10:44:17 +01:00
d19f6a3d0d initialchecks werent being bypassed because of the wrong exception being caught. fixed (#623) 2023-01-19 10:43:27 +01:00
d77b353481 Corrected wrong coloring in plotPattern 2023-01-18 08:59:30 +01:00
7466c0bc8f M3 deserialize (#618)
* m3: updated serializing loop in trimming

* fixed the deserializing loop again
2023-01-17 09:39:58 +01:00
713639d001 Fix gotthard delay (#606)
* fix for set delay for gotthard1 (verification adds master delay even if its not master)

* binaries in

* binaries name
2023-01-17 09:16:43 +01:00
3cc4d25eb9 Merge branch '7.0.0.rc' of https://github.com/slsdetectorgroup/slsDetectorPackage into 7.0.0.rc 2023-01-16 15:05:59 +01:00
0d905923dd Corrected a typo in plotPattern.py 2023-01-16 15:03:16 +01:00
e747a5811f added missing equality operator for DurationWrapper in Python (M3 exptime fix) (#615) 2023-01-16 14:12:12 +01:00
22b3229d94 m3: updated serializing loop in trimming (#613) 2023-01-16 13:43:28 +01:00
d106109f6c fixed hostname not split (+) in python (#609)
* fixed hostname not split (+) in python

* also for rx_hostname
2023-01-16 13:33:11 +01:00
86 changed files with 3342 additions and 1434 deletions

View File

@ -86,6 +86,145 @@ Client Commands
sls_detector_get -h rx_framescaught sls_detector_get -h rx_framescaught
ZMQ: Json Header Format
------------------------
**Change in field names from slsDetectorPackage v6.x.x to v7.0.0**
* detSpec1 <- bunchId
* detSpec2 <- reserved
* detSpec3 <- debug
* detSpec4 <- roundRNumber
**Format**
.. code-block:: bash
{
"jsonversion": unsigned int,
"bitmode": unsigned int,
"fileIndex": unsigned long int,
"detshape": [
unsigned int,
unsigned int
],
"shape": [
unsigned int,
unsigned int
],
"size": unsigned int,
"acqIndex": unsigned long int,
"frameIndex": unsigned long int,
"progress": double,
"fname": string,
"data": unsigned int,
"completeImage": unsigned int,
"frameNumber": unsigned long long int,
"expLength": unsigned int,
"packetNumber": unsigned int,
"detSpec1": unsigned long int,
"timestamp": unsigned long int,
"modId": unsigned int,
"row": unsigned int,
"column": unsigned int,
"detSpec2": unsigned int,
"detSpec3": unsigned int,
"detSpec4": unsigned int,
"detType": unsigned int,
"version": unsigned int,
"flipRows": unsigned int,
"quad": unsigned int,
"addJsonHeader": {
string : string
}
}
+--------------+----------------------------------------------+
| Field | Description |
+--------------+----------------------------------------------+
| jsonversion | Version of the json header. |
| | Value at 4 for v6.x.x and v7.x.x |
+--------------+----------------------------------------------+
| bitmode | Bits per pixel [4|8|16|32] |
+--------------+----------------------------------------------+
| fileIndex | Current file acquisition index |
+--------------+----------------------------------------------+
| detshape | Geometry of the entire detector |
+--------------+----------------------------------------------+
| shape | Geometry of the current port streamed out |
+--------------+----------------------------------------------+
| size | Size of image of current port in bytesout |
+--------------+----------------------------------------------+
| acqIndex | Frame number from the detector (redundant) |
+--------------+----------------------------------------------+
| frameIndex | Frame number of current acquisition |
| | (Starting at 0) |
+--------------+----------------------------------------------+
| progress | Progress of current acquisition in % |
+--------------+----------------------------------------------+
| fname | Current file name |
+--------------+----------------------------------------------+
| data | 1 if there is data following |
| | 0 if dummy header |
+--------------+----------------------------------------------+
| completeImage| 1 if no missing packets for this frame |
| | in this port, else 0 |
+--------------+----------------------------------------------+
| frameNumber | Frame number |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| expLength | subframe number (32 bit eiger) |
| | or real time exposure time in 100ns (others) |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| packetNumber | Number of packets caught for that frame |
+--------------+----------------------------------------------+
| detSpec1 | See :ref:`here<Detector Specific Fields>` |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| timestamp | Timestamp with 10 MHz clock |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| modId | Module Id |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| row | Row number in detector |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| column | Column number in detector |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| detSpec2 | See :ref:`here<Detector Specific Fields>` |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| detSpec3 | See :ref:`here<Detector Specific Fields>` |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| detSpec4 | See :ref:`here<Detector Specific Fields>` |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| detType | Detector type enum |
| detSpec3 | See :ref:`Detector enum<Detector Enum>` |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| version | Detector header version. At 2 |
| | [From detector udp header] |
+--------------+----------------------------------------------+
| flipRows | 1 if rows should be flipped. |
| | Usually for Eiger bottom. |
+--------------+----------------------------------------------+
| quad | 1 if its an Eiger quad. |
+--------------+----------------------------------------------+
| addJsonHeader| Optional custom parameters that is required |
| | for processing code. |
+--------------+----------------------------------------------+
File format File format
-------------- --------------

6
examples/badchannel.txt Normal file
View File

@ -0,0 +1,6 @@
0
10, 30
40:45 50:52
1279
# all bad channels are applied for all counters in deector

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

After

Width:  |  Height:  |  Size: 299 KiB

View File

@ -31,7 +31,7 @@ alpha_wait = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
alpha_wait_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2] alpha_wait_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
# Loop colors and line styles (6 needed from 0 to 5) # Loop colors and line styles (6 needed from 0 to 5)
colors_loop = ['tab:green', 'tab:red', 'tab:purple', 'tab:brown', 'tab:ping', 'tab:grey'] colors_loop = ['tab:green', 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:grey']
linestyles_loop = ['-.', '-.', '-.', '-.', '-.', '-.'] linestyles_loop = ['-.', '-.', '-.', '-.', '-.', '-.']
alpha_loop = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5] alpha_loop = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
alpha_loop_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2] alpha_loop_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
@ -527,7 +527,7 @@ for idx, i in enumerate(range(nbiteff)):
linestyle=linestyles_loop[2], color=colors_loop[2], alpha=alpha_loop[2], linestyle=linestyles_loop[2], color=colors_loop[2], alpha=alpha_loop[2],
label="loop 2: " + str(nloop2) + " times" if idx == 0 else "", linewidth=2.0) label="loop 2: " + str(nloop2) + " times" if idx == 0 else "", linewidth=2.0)
axs2[idx].plot([loop2_end, loop2_end], [-10, 10], axs2[idx].plot([loop2_end, loop2_end], [-10, 10],
linestyle=linestyles_loop[0], color=colors_loop[0], alpha=alpha_loop[2], linewidth=2.0) linestyle=linestyles_loop[2], color=colors_loop[2], alpha=alpha_loop[2], linewidth=2.0)
# Loop 3 # Loop 3
if nloop3 is not None: if nloop3 is not None:

View File

@ -14,7 +14,7 @@ streamingInterface = slsDetectorDefs.streamingInterface
defs = slsDetectorDefs defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from _slsdet import xy from _slsdet import xy
from . import utils as ut from . import utils as ut
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
@ -162,12 +162,8 @@ class Detector(CppDetectorApi):
@hostname.setter @hostname.setter
def hostname(self, hostnames): def hostname(self, hostnames):
if isinstance(hostnames, str): args = hostname_list(hostnames)
hostnames = [hostnames] self.setHostname(args)
if isinstance(hostnames, list):
self.setHostname(hostnames)
else:
raise ValueError("hostname needs to be string or list of strings")
@property @property
@ -271,7 +267,7 @@ class Detector(CppDetectorApi):
@element @element
def rx_threads(self): def rx_threads(self):
""" """
Get thread ids from the receiver in order of [parent, tcp, listener 0, processor 0, streamer 0, listener 1, processor 1, streamer 1, arping]. Get kernel thread ids from the receiver in order of [parent, tcp, listener 0, processor 0, streamer 0, listener 1, processor 1, streamer 1, arping].
Note Note
----- -----
@ -784,7 +780,8 @@ class Detector(CppDetectorApi):
@rx_hostname.setter @rx_hostname.setter
def rx_hostname(self, hostname): def rx_hostname(self, hostname):
self.setRxHostname(hostname) args = hostname_list(hostname)
self.setRxHostname(args)
@property @property
@element @element
@ -1568,6 +1565,20 @@ class Detector(CppDetectorApi):
def trimval(self, value): def trimval(self, value):
ut.set_using_dict(self.setAllTrimbits, value) ut.set_using_dict(self.setAllTrimbits, value)
@property
@element
def fliprows(self):
"""
[Eiger] flips rows paramater sent to slsreceiver to stream as json parameter to flip rows in gui. \n
[Jungfrau] flips rows in the detector itself. For bottom module and number of interfaces must be set to 2. slsReceiver and slsDetectorGui does not handle.
"""
return self.getFlipRows()
@fliprows.setter
def fliprows(self, value):
ut.set_using_dict(self.setFlipRows, value)
@property @property
@element @element
def master(self): def master(self):
@ -1593,6 +1604,19 @@ class Detector(CppDetectorApi):
def sync(self, value): def sync(self, value):
ut.set_using_dict(self.setSynchronization, value) ut.set_using_dict(self.setSynchronization, value)
@property
@element
def badchannels(self):
"""
[fname|none|0]\n\t[Gotthard2][Mythen3] Sets the bad channels (from file of bad channel numbers) to be masked out. None or 0 unsets all the badchannels.\n
[Mythen3] Also does trimming
"""
return self.getBadChannels()
@badchannels.setter
def badchannels(self, value):
ut.set_using_dict(self.setBadChannels, value)
@property @property
@element @element
def lock(self): def lock(self):
@ -1802,6 +1826,15 @@ class Detector(CppDetectorApi):
@property @property
def versions(self): def versions(self):
if self.type == detectorType.EIGER:
return {'type': self.type,
'package': self.packageversion,
'client': self.clientversion,
'firmware': self.firmwareversion,
'detectorserver': self.detectorserverversion,
'kernel': self.kernelversion,
'receiver': self.rx_version}
return {'type': self.type, return {'type': self.type,
'package': self.packageversion, 'package': self.packageversion,
'client': self.clientversion, 'client': self.clientversion,

View File

@ -261,3 +261,20 @@ def merge_args(*args):
else: else:
raise ValueError("Multiple dictionaries passes cannot merge args") raise ValueError("Multiple dictionaries passes cannot merge args")
def hostname_list(args):
"""
Generates a list from a hostname string
* Lists are passed through
* as are tuples (conversion in pybind11 to vector)
* if + is found it splits the string
"""
if isinstance(args, (list, tuple)):
return args
elif(isinstance(args, str)):
hosts = args.split('+')
hosts = [it for it in hosts if len(it)]
return hosts
else:
raise ValueError("hostname needs to be string or list of strings")

View File

@ -219,6 +219,21 @@ void init_det(py::module &m) {
(void (Detector::*)(const std::string &, sls::Positions)) & (void (Detector::*)(const std::string &, sls::Positions)) &
Detector::setBadChannels, Detector::setBadChannels,
py::arg(), py::arg() = Positions{}); py::arg(), py::arg() = Positions{});
CppDetectorApi.def(
"getBadChannels",
(Result<std::vector<int>>(Detector::*)(sls::Positions) const) &
Detector::getBadChannels,
py::arg() = Positions{});
CppDetectorApi.def(
"setBadChannels",
(void (Detector::*)(const std::vector<int>, sls::Positions)) &
Detector::setBadChannels,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def(
"setBadChannels",
(void (Detector::*)(const std::vector<std::vector<int>>)) &
Detector::setBadChannels,
py::arg());
CppDetectorApi.def("isVirtualDetectorServer", CppDetectorApi.def("isVirtualDetectorServer",
(Result<bool>(Detector::*)(sls::Positions) const) & (Result<bool>(Detector::*)(sls::Positions) const) &
Detector::isVirtualDetectorServer, Detector::isVirtualDetectorServer,

View File

@ -12,6 +12,7 @@ void init_duration(py::module &m) {
.def("total_seconds", &DurationWrapper::total_seconds) .def("total_seconds", &DurationWrapper::total_seconds)
.def("count", &DurationWrapper::count) .def("count", &DurationWrapper::count)
.def("set_count", &DurationWrapper::set_count) .def("set_count", &DurationWrapper::set_count)
.def("__eq__", &DurationWrapper::operator==)
.def("__repr__", [](const DurationWrapper &self) { .def("__repr__", [](const DurationWrapper &self) {
std::stringstream ss; std::stringstream ss;
ss << "sls::DurationWrapper(total_seconds: " << self.total_seconds() ss << "sls::DurationWrapper(total_seconds: " << self.total_seconds()

View File

@ -8,7 +8,7 @@ Testing functions from utils.py
import pytest import pytest
from slsdet.utils import * from slsdet.utils import *
from slsdet import IpAddr, MacAddr from slsdet import IpAddr, MacAddr, DurationWrapper
import datetime as dt import datetime as dt
import pathlib import pathlib
from pathlib import Path from pathlib import Path
@ -22,7 +22,11 @@ def test_iterable():
def test_reduce_time_to_single_value_from_list(): def test_reduce_time_to_single_value_from_list():
t = 3 * [dt.timedelta(seconds=1)] t = [dt.timedelta(seconds=1) for i in range(3)]
assert reduce_time(t) == 1
def test_reduce_time_to_single_value_from_list_DurationWrapper():
t = [DurationWrapper(1) for i in range(3)]
assert reduce_time(t) == 1 assert reduce_time(t) == 1
@ -83,6 +87,12 @@ def test_all_equal_str_fails():
assert all_equal('aaab') == False assert all_equal('aaab') == False
def test_all_equal_DurationWrapper():
assert all_equal([DurationWrapper(1), DurationWrapper(1)])
def test_all_equal_DurationWrapper_fail():
assert not all_equal([DurationWrapper(1), DurationWrapper(2)])
def test_element_if_equal_int(): def test_element_if_equal_int():
assert element_if_equal([5, 5]) == 5 assert element_if_equal([5, 5]) == 5
@ -342,3 +352,32 @@ def test_merge_args_tuple():
def test_merge_args_dict_with_tuple(): def test_merge_args_dict_with_tuple():
assert merge_args({0: (1,2)}, 3) == ({0: (1,2,3)},) assert merge_args({0: (1,2)}, 3) == ({0: (1,2,3)},)
def test_hostname_to_list():
s = "localhost"
r = hostname_list(s)
assert r == [s]
def test_hostname_to_list_passthrough():
args = ["localhost"]
ret = hostname_list(args)
assert ret == args
args = ("localhost",)
ret = hostname_list(args)
assert ret == args
def test_splitting_hostname():
args = 'apple+banana+pear+'
ret = hostname_list(args)
assert ret == ['apple', 'banana', 'pear']
#not sensitive to trailing +
args = 'apple+banana+pear'
ret = hostname_list(args)
assert ret == ['apple', 'banana', 'pear']
def test_hostame_throws_on_wrong_args():
with pytest.raises(Exception) as e:
hostname_list(5)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,20 +40,31 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
out by a module i.e. using the slsReceiver (160x160 pixels, 40 packets out by a module i.e. using the slsReceiver (160x160 pixels, 40 packets
1286 large etc.) \param c crosstalk parameter for the output buffer 1286 large etc.) \param c crosstalk parameter for the output buffer
*/ */
#ifndef ZMQ
#define off sizeof(jf_header)
#endif
#ifdef ZMQ
#define off 0
#endif
jungfrauModuleData() jungfrauModuleData()
: slsDetectorData<uint16_t>(1024, 512, : slsDetectorData<uint16_t>(1024, 512,
1024* 512 * 2 + sizeof(jf_header)) { 1024* 512 * 2 + off) {
for (int ix = 0; ix < 1024; ix++) { for (int ix = 0; ix < 1024; ix++) {
for (int iy = 0; iy < 512; iy++) { for (int iy = 0; iy < 512; iy++) {
dataMap[iy][ix] = sizeof(jf_header) + (1024 * iy + ix) * 2; dataMap[iy][ix] = off + (1024 * iy + ix) * 2;
#ifdef HIGHZ #ifdef HIGHZ
dataMask[iy][ix] = 0x3fff; dataMask[iy][ix] = 0x3fff;
#endif #endif
} }
} }
iframe = 0; iframe = 0;
// cout << "data struct created" << endl; // cout << "data struct created" << endl;
}; };

View File

@ -0,0 +1,64 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
#module add CBFlib/0.9.5
INCDIR=-I. -I../ -I../interpolations -I../interpolations/etaVEL -I../dataStructures -I../../slsSupportLib/include/ -I../../slsReceiverSoftware/include/ -I../tiffio/include
LDFLAG= ../tiffio/src/tiffIO.cpp -L/usr/lib64/ -lpthread -lm -lstdc++ -pthread -lrt -ltiff -O3 -std=c++11
MAIN=jungfrauClusterFinder.cpp
all: jungfrauRawDataProcess
jungfrauRawDataProcess: jungfrauRawDataProcess.cpp $(INCS) clean
g++ -o jungfrauRawDataProcess jungfrauRawDataProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DMODULE
jungfrauRawDataProcessStrx: jungfrauRawDataProcess.cpp $(INCS) clean
g++ -o jungfrauRawDataProcessStrx jungfrauRawDataProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DJFSTRX
jungfrauRawDataProcessStrxAldo: jungfrauRawDataProcess.cpp $(INCS) clean
g++ -o jungfrauRawDataProcessStrxAldo jungfrauRawDataProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DJFSTRX -DALDO
jungfrauRawDataProcessStrxOld: jungfrauRawDataProcess.cpp $(INCS) clean
g++ -o jungfrauRawDataProcessStrxOld jungfrauRawDataProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DJFSTRXOLD
jungfrauRawDataProcessStrxOldAldo: jungfrauRawDataProcess.cpp $(INCS) clean
g++ -o jungfrauRawDataProcessStrxOldAldo jungfrauRawDataProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DJFSTRXOLD -DALDO
jungfrauClusterFinder: jungfrauClusterFinder.cpp $(INCS) clean
g++ -o jungfrauClusterFinder jungfrauClusterFinder.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL
jungfrauClusterFinderHighZ: jungfrauClusterFinder.cpp $(INCS) clean
g++ -o jungfrauClusterFinderHighZ jungfrauClusterFinder.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DSAVE_ALL -DHIGHZ
jungfrauMakeEta: jungfrauInterpolation.cpp $(INCS) clean
g++ -o jungfrauMakeEta jungfrauInterpolation.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DFF
jungfrauInterpolation: jungfrauInterpolation.cpp $(INCS) clean
g++ -o jungfrauInterpolation jungfrauInterpolation.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF)
jungfrauNoInterpolation: jungfrauNoInterpolation.cpp $(INCS) clean
g++ -o jungfrauNoInterpolation jungfrauNoInterpolation.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF)
jungfrauPhotonCounter: jungfrauPhotonCounter.cpp $(INCS) clean
g++ -o jungfrauPhotonCounter jungfrauPhotonCounter.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWRECEIVER
jungfrauAnalog: jungfrauPhotonCounter.cpp $(INCS) clean
g++ -o jungfrauAnalog jungfrauPhotonCounter.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWRECEIVER -DANALOG
jungfrauPhotonCounterHighZ: jungfrauPhotonCounter.cpp $(INCS) clean
g++ -o jungfrauPhotonCounterHighZ jungfrauPhotonCounter.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWRECEIVER -DHIGHZ
jungfrauAnalogHighZ: jungfrauPhotonCounter.cpp $(INCS) clean
g++ -o jungfrauAnalogHighZ jungfrauPhotonCounter.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWRECEIVER -DANALOG -DHIGHZ
clean:
rm -f jungfrauClusterFinder jungfrauMakeEta jungfrauInterpolation jungfrauNoInterpolation jungfrauPhotonCounter jungfrauAnalog

View File

@ -1,25 +1,19 @@
# 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
INCDIR= -I. -I../dataStructures ../tiffIO.cpp -I../ -I../interpolations/ -I../../slsSupportLib/include/ -I../../slsReceiverSoftware/include/ -I../../libs/rapidjson/ INCDIR= -I. -I../dataStructures ../tiffio/src/tiffIO.cpp -I../ -I../interpolations/ -I../../slsSupportLib/include/ -I../../slsReceiverSoftware/include/ -I../../libs/rapidjson/ -I../tiffio/include
LDFLAG= -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -O3 -std=c++11 -Wall -L../../build/bin/ -lSlsSupport LDFLAG= -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -O3 -std=c++11 -Wall -L../../build/bin/ -lSlsSupport
#-L../../bin -lhdf5 -L. #-L../../bin -lhdf5 -L.
#DESTDIR?=../bin #DESTDIR?=../bin
all: moenchZmqProcess moenchZmq04Process all: jungfrauZmqProcess
#moenchZmqProcessCtbGui #jungfrauZmqProcessCtbGui
moenchZmqProcess: moenchZmqProcess.cpp clean jungfrauZmqProcess: jungfrauZmqProcess.cpp clean
g++ -o moenchZmqProcess moenchZmqProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWZMQ -DINTERP g++ -o jungfrauZmqProcess jungfrauZmqProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWZMQ -DINTERP
moenchZmq04Process: moenchZmqProcess.cpp clean
g++ -o moench04ZmqProcess moenchZmqProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWZMQ -DINTERP -DMOENCH04
#moenchZmqProcessCtbGui: moenchZmqProcess.cpp clean
# g++ -o moenchZmqProcessCtbGui moenchZmqProcess.cpp $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF) -DNEWZMQ -DINTERP -DCTBGUI
clean: clean:
rm -f moenchZmqProcess rm -f jungfrauZmqProcess

View File

@ -0,0 +1,26 @@
ROOTSYS=/opt/cern/v6/root
#/afs/psi.ch/project/sls_det_sof/roottware/root_v5.34.23_sl6_64bit
LIBZMQDIR = $(PWD)
LIBZMQ = -L$(LIBZMQDIR) -lzmq
SHLIB_PATH=/opt/cern/v6/root/lib
CMAKE_PREFIX_PATH=/opt/cern/v6/root
DYLD_LIBRARY_PATH=/opt/cern/v6/root/lib
INCDIR= -I. -I../dataStructures ../tiffio/src/tiffIO.cpp -I../ -I../interpolations/ -I../../slsSupportLib/include/ -I../../slsReceiverSoftware/include/ -I../../libs/rapidjson/ -I../tiffio/include
LDFLAG= -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -O3 -std=c++11 -Wall -L../../build/bin/ -lSlsSupport
#-L../../bin -lhdf5 -L.
default: onlinedisp_zmq
onlinedisp_zmq: onlinedisp_zmq.cpp onlinedisp_zmq.h
# flags from root-config --cflags --glibs
g++ -o onlinedisp_zmq onlinedisp_zmq.cpp -I. -I$(ROOTSYS)/include -Wall -g -lm -L. -lzmq -pthread -lrt -L$(ROOTSYS)/lib -lGui -lCore -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -m64 $(LDFLAG) $(INCDIR) $(LIBHDF5) $(LIBRARYCBF)
#-lCint

View File

@ -0,0 +1,10 @@
sls_detector_put rx_jsonpara detectorMode counting
sls_detector_put rx_jsonpara frameMode newPedestal
sls_detector_put rx_jsonpara frameMode frame
sls_detector_put rx_jsonpara detectorMode analog
sls_detector_put rx_jsonpara threshold 150
sls_detector_put rx_jsonpara threshold 0
sls_detector_put rx_jsonpara threshold 300
sls_detector_put rx_zmqhwm 50

View File

@ -0,0 +1,418 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
//#include "sls/ansi.h"
#include <iostream>
#undef CORR
#define C_GHOST 0.0004
#define CM_ROWS 50
#define RAWDATA
#ifndef JFSTRX
#ifndef JFSTRXOLD
#ifndef MODULE
#include "jungfrauHighZSingleChipData.h"
#endif
#ifdef MODULE
#include "jungfrauModuleData.h"
#endif
#endif
#endif
#ifdef JFSTRX
#include "jungfrauLGADStrixelsData.h"
#endif
#ifdef JFSTRXOLD
#include "jungfrauStrixelsHalfModuleOldDesign.h"
#endif
#include "multiThreadedCountingDetector.h"
#include "singlePhotonDetector.h"
#include <fstream>
#include <map>
#include <stdio.h>
#include <sys/stat.h>
#include <ctime>
using namespace std;
int main(int argc, char *argv[]) {
if (argc < 5) {
cout << "Usage is " << argv[0]
<< "indir outdir fname(no extension) fextension [runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
"[nframes] [xmin xmax ymin ymax] [gainmap]"
<< endl;
cout << "threshold <0 means analog; threshold=0 means cluster finder; "
"threshold>0 means photon counting"
<< endl;
cout << "nframes <0 means sum everything; nframes=0 means one file per "
"run; nframes>0 means one file every nframes"
<< endl;
return 1;
}
int fifosize = 1000;
int nthreads = 10;
int csize = 3;
int nsigma = 5;
int nped = 10000;
int cf = 0;
#ifndef JFSTRX
#ifndef JFSTRXOLD
#ifndef MODULE
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
int nx = 256, ny = 256;
#endif
#ifdef MODULE
jungfrauModuleData *decoder = new jungfrauModuleData();
int nx = 1024, ny = 512;
#endif
#endif
#endif
#ifdef JFSTRX
cout << "bbb" << endl;
jungfrauLGADStrixelsData *decoder = new jungfrauLGADStrixelsData();
int nx = 1024/5, ny = 512*5;
#endif
#ifdef JFSTRXOLD
cout << "ccc" << endl;
jungfrauStrixelsHalfModuleOldDesign *decoder = new jungfrauStrixelsHalfModuleOldDesign();
int nx = 1024*3, ny = 512/3;
#endif
decoder->getDetectorSize(nx, ny);
cout << "Detector size is " << nx << " " << ny << endl;
double *gainmap = NULL;
//float *gm;
int ff, np;
// cout << " data size is " << dsize;
ifstream filebin;
char *indir = argv[1];
char *outdir = argv[2];
char *fformat = argv[3];
char *fext = argv[4];
int runmin = 0;
// cout << "argc is " << argc << endl;
if (argc >= 6) {
runmin = atoi(argv[5]);
}
int runmax = runmin;
if (argc >= 7) {
runmax = atoi(argv[6]);
}
char *pedfile = NULL;
if (argc >= 8) {
pedfile = argv[7];
}
double thr = 0;
double thr1 = 1;
if (argc >= 9) {
thr = atof(argv[8]);
}
int nframes = 0;
if (argc >= 10) {
nframes = atoi(argv[9]);
}
int xmin = 0, xmax = nx, ymin = 0, ymax = ny;
if (argc >= 14) {
xmin = atoi(argv[10]);
xmax = atoi(argv[11]);
ymin = atoi(argv[12]);
ymax = atoi(argv[13]);
}
char *gainfname = NULL;
if (argc > 14) {
gainfname = argv[14];
cout << "Gain map file name is: " << gainfname << endl;
}
char ffname[10000];
char fname[10000];
char imgfname[10000];
char cfname[10000];
std::time_t end_time;
FILE *of = NULL;
cout << "input directory is " << indir << endl;
cout << "output directory is " << outdir << endl;
cout << "input file is " << fformat << endl;
cout << "runmin is " << runmin << endl;
cout << "runmax is " << runmax << endl;
if (pedfile)
cout << "pedestal file is " << pedfile << endl;
if (thr > 0)
cout << "threshold is " << thr << endl;
cout << "Nframes is " << nframes << endl;
uint32_t nnx, nny;
singlePhotonDetector *filter = new singlePhotonDetector(
decoder, csize, nsigma, 1, NULL, nped, 200, -1, -1, gainmap, NULL);
if (gainfname) {
if (filter->readGainMap(gainfname))
cout << "using gain map " << gainfname << endl;
else
cout << "Could not open gain map " << gainfname << endl;
} else
thr = 0.15 * thr;
filter->newDataSet();
//int dsize = decoder->getDataSize();
if (thr > 0) {
cout << "threshold is " << thr << endl;
filter->setThreshold(thr);
cf = 0;
} else
cf = 1;
filter->setROI(xmin, xmax, ymin, ymax);
std::time(&end_time);
cout << std::ctime(&end_time) << endl;
char *buff;
// multiThreadedAnalogDetector *mt=new
// multiThreadedAnalogDetector(filter,nthreads,fifosize);
multiThreadedCountingDetector *mt =
new multiThreadedCountingDetector(filter, nthreads, fifosize);
#ifndef ANALOG
mt->setDetectorMode(ePhotonCounting);
cout << "Counting!" << endl;
if (thr > 0) {
cf = 0;
}
#endif
//{
#ifdef ANALOG
mt->setDetectorMode(eAnalog);
cout << "Analog!" << endl;
cf = 0;
// thr1=thr;
#endif
// }
mt->StartThreads();
mt->popFree(buff);
// cout << "mt " << endl;
int ifr = 0;
char froot[1000];
double *ped=new double[nx * ny];//, *ped1;
int pos,pos1;
if (pedfile) {
if (string(pedfile).find(".dat") != std::string::npos) {
pos1=string(pedfile).rfind("/");
strcpy(froot,pedfile+pos1);
pos=string(froot).find(".dat");
froot[pos]='\0';
}
cout << "PEDESTAL " << endl;
// sprintf(imgfname, "%s/pedestals.tiff", outdir);
if (string(pedfile).find(".tif") == std::string::npos) {
sprintf(fname, "%s", pedfile);
cout << fname << endl;
std::time(&end_time);
//cout << "aaa" << std::ctime(&end_time) << endl;
mt->setFrameMode(ePedestal);
// sprintf(fn,fformat,irun);
filebin.open((const char *)(fname), ios::in | ios::binary);
// //open file
if (filebin.is_open()) {
ff = -1;
while (decoder->readNextFrame(filebin, ff, np, buff)) {
// if (np == 40) {
if ((ifr+1) % 100 == 0) {
cout << " ****" << decoder->getValue(buff,20,20);// << endl;
}
mt->pushData(buff);
mt->nextThread();
mt->popFree(buff);
ifr++;
if (ifr % 100 == 0) {
cout << " ****" << ifr << " " << ff << " " << np << endl;
} //else
//cout << ifr << " " << ff << " " << np << endl;
if (ifr>=1000)
break;
ff = -1;
}
filebin.close();
while (mt->isBusy()) {
;
}
sprintf(imgfname, "%s/%s_ped.tiff", outdir, froot);
mt->writePedestal(imgfname);
sprintf(imgfname, "%s/%s_rms.tiff", outdir, froot);
mt->writePedestalRMS(imgfname);
} else
cout << "Could not open pedestal file " << fname
<< " for reading " << endl;
} else {
float *pp = ReadFromTiff(pedfile, nny, nnx);
if (pp && (int)nnx == nx && (int)nny == ny) {
for (int i = 0; i < nx * ny; i++) {
ped[i] = pp[i];
}
delete[] pp;
mt->setPedestal(ped);
cout << "Pedestal set from tiff file " << pedfile << endl;
} else {
cout << "Could not open pedestal tiff file " << pedfile
<< " for reading " << endl;
}
}
std::time(&end_time);
cout << std::ctime(&end_time) << endl;
}
ifr = 0;
int ifile = 0;
mt->setFrameMode(eFrame);
for (int irun = runmin; irun <= runmax; irun++) {
cout << "DATA ";
// sprintf(fn,fformat,irun);
sprintf(ffname, "%s/%s.%s", indir, fformat, fext);
sprintf(fname, (const char*)ffname, irun);
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
sprintf(imgfname, (const char*)ffname, irun);
sprintf(ffname, "%s/%s.clust", outdir, fformat);
sprintf(cfname, (const char*)ffname, irun);
cout << fname << " ";
cout << imgfname << endl;
std::time(&end_time);
cout << std::ctime(&end_time) << endl;
// cout << fname << " " << outfname << " " << imgfname << endl;
filebin.open((const char *)(fname), ios::in | ios::binary);
// //open file
ifile = 0;
if (filebin.is_open()) {
if (thr <= 0 && cf != 0) { // cluster finder
if (of == NULL) {
of = fopen(cfname, "w");
if (of) {
mt->setFilePointer(of);
cout << "file pointer set " << endl;
} else {
cout << "Could not open " << cfname << " for writing "
<< endl;
mt->setFilePointer(NULL);
return 1;
}
}
}
// //while read frame
ff = -1;
ifr = 0;
while (decoder->readNextFrame(filebin, ff, np, buff)) {
// if (np == 40) {
// //push
if ((ifr+1) % 100 == 0) {
cout << " ****" << decoder->getValue(buff,20,20);// << endl;
}
mt->pushData(buff);
// // //pop
mt->nextThread();
mt->popFree(buff);
ifr++;
if (ifr % 100 == 0)
cout << " " << ifr << " " << ff << endl;
if (nframes > 0) {
if (ifr % nframes == 0) {
sprintf(ffname, "%s/%s_f%05d.tiff", outdir, fformat,
ifile);
sprintf(imgfname, (const char*)ffname, irun);
mt->writeImage(imgfname, thr1);
mt->clearImage();
ifile++;
}
}
// } else
// cout << ifr << " " << ff << " " << np << endl;
ff = -1;
}
cout << "--" << endl;
filebin.close();
while (mt->isBusy()) {
;
}
if (nframes >= 0) {
if (nframes > 0) {
sprintf(ffname, "%s/%s_f%05d.tiff", outdir, fformat, ifile);
sprintf(imgfname, (const char*)ffname, irun);
} else {
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
sprintf(imgfname, (const char*)ffname, irun);
}
cout << "Writing tiff to " << imgfname << " " << thr1 << endl;
mt->writeImage(imgfname, thr1);
mt->clearImage();
if (of) {
fclose(of);
of = NULL;
mt->setFilePointer(NULL);
}
}
std::time(&end_time);
cout << std::ctime(&end_time) << endl;
} else
cout << "Could not open " << fname << " for reading " << endl;
}
if (nframes < 0) {
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
strcpy(imgfname, ffname);
cout << "Writing tiff to " << imgfname << " " << thr1 << endl;
mt->writeImage(imgfname, thr1);
}
return 0;
}

View File

@ -0,0 +1,679 @@
#include "onlinedisp_zmq.h"
bool hasallpede;
TH1F * his102;TH1F * his101;
int processedf;
sls::zmqHeader zHeader;
#define PEDEFNAME "current_pede.dat"
#define NPRO 50
#define NPRI 50
//#define JFSTRX
#ifdef JFSTRX
#include "jungfrauLGADStrixelsData.h"
#else
#include "jungfrauModuleData.h"
#endif
int main(int argc, char* argv[])
{
goout=1;
hasallpede=false;
dophotonmap=true; if ((argc<3)) {printf("USAGE: command photon_energy_(peakinADC) [rx_ip] [port] \n"); return -1 ;}
else {
phene=atoi(argv[1]);
if (phene<0) dophotonmap=false;
threshold=float (phene/2);
printf( " \n");
printf( "phene %d \n",phene);
}
if (argc>=3) {
strcpy(serverip,argv[2]);
printf("ip is %s ",serverip);
}
portnum=30001;
if (argc>=4 ){ portnum= atoi(argv[3]);
}
printf(", port number is %d ",portnum); printf(". \n");
#ifdef JFSTRX
cout << "JFSTRX" << endl;
jungfrauLGADStrixelsData *decoder = new jungfrauLGADStrixelsData();
nx = 1024/5; ny= 512*5;
#else
nx = 1024; ny= 512;
#endif
gain_flag=false;
pede_flag=false;
bw_flag=false;
HDraw_every=20;
fixranges=false;
hchptr = (short*) malloc(NCH*sizeof(short));
startsocket(); //create and connect ZMQ
for (ipx=0;ipx<NCH;ipx++) hchptr[(ipx)]=0;
// cout<< decoder->getValue((char*)(hchptr),279,130)<<endl;
nonblock(NB_ENABLE);
cout <<"opening the rootapp" <<endl;
rootapp = new TApplication("Online JF display",&argc, argv);
LoadPaletteFalse();
char hname[100];
his1000= new TH2F("his1000","2d , ev. pede corrected",nx,-0.5,nx-0.5,ny,-0.5,ny-0.5);
his1000->SetOption("colz");
his2000= new TH2F("his2000","2d gain ",nx,-0.5,nx-0.5,ny,-0.5,ny-0.5);
his2000->GetZaxis()->SetRangeUser(0,4);
if (dophotonmap) {
his3000= new TH2F("his3000"," photon map ",nx,-0.5,nx-0.5,ny,-0.5,ny-0.5);
}
else {
his3000= new TH2F("his3000"," raw adc ",nx,-0.5,nx-0.5,ny,-0.5,ny-0.5);
}
his4500= new TH2F("his45000","L vs R",101,-50,500,101,-50,500);
hchip=new TH1I*[8];
for (i=0;i<8;i++) {
sprintf(hname,"hchip%d",i);
hchip[i] = new TH1I(hname,hname,NBIN,MIN_POS,MAX_POS);
}
cout <<"end of histo booking" <<endl;
if (A2==NULL) A2 = new TCanvas("A2","Plotting Canvas gain",150,10,500,250);
if (A3==NULL) A3 = new TCanvas("A3","Plotting Canvas ADC",150,360,1200,550);
if (A4==NULL) A4 = new TCanvas("A4","Plotting Canvas PHs",750,300,1000,800);
A4->Clear();
A4->Divide(4,2,0.005,0.005);
if (A5==NULL) A5 = new TCanvas("A5","Plotting Canvas Photon Map",750,300,1000,600);
if (A6==NULL) A6 = new TCanvas("A6","Plotting Canvas LvsR",650,250,650,660);
gSystem->ProcessEvents();
int running=0;
char runc[15]="*\\-/|";
printhelp();
while (1==1) { // loop on streamed frames
if(!zmqSocket->ReceiveHeader(0,zHeader, SLS_DETECTOR_JSON_HEADER_VERSION)){
cout<< "Receiver stopped, waiting for new stream" << endl;
zmqSocket->Disconnect();
zmqSocket->Connect();
}
else {
// if (((icount++)%10)==0) cout <<"recived frameindex "<<zHeader.frameIndex <<endl;
//cout <<"there" <<endl;
zmqSocket->ReceiveData(0, (char *)(&image_data), NCH*2);
}
{
framesinstream++;
running++;
fill1Ds=true; //alway fill 1d and LR plots
//if (((framesinstream%(int(HDraw_every)))==(int (HDraw_every)-1))) {fill1Ds=true;}else{fill1Ds=false;}
if (((framesinstream%(HDraw_every))==(HDraw_every)-1)) {show2Ds=true;}else{show2Ds=false;}
if (((framesinstream%NPRI)==NPRI-1)) { cout<<"\r "<<"frame (from start): "<<framesinstream<<" " << runc[((running/NPRI)%5)]<< " discarded frames %=" << (1-float(processedf)/float(zHeader.frameIndex-frameIndex_old))*100 << " current framenumber= " <<zHeader.frameIndex << " "<<std::flush; processedf=0;frameIndex_old=zHeader.frameIndex;}
npacket=0;
if (show2Ds) {
his1000->Reset();
his2000->Reset();
if (!dophotonmap) his3000->Reset(); //FOR RAW ADC DISPLAY
}
if ((fill1Ds)or(show2Ds)or(dophotonmap)) { // do something, otherwise skip to the next
processedf++;
for (i=0 ;i<NCH;i++) {
adcvalue= (image_data[i]) & 0x3fff;
if ((image_data[i] & 0xc000)!=0){ gain = (image_data[i]>>14) & 0x3;} else {gain=0;}
if (pede_flag){
if (gain_flag)
{
if ((gain==0)||(!hasallpede)) adcpedecorr=(adcvalue&0x3fff)*fgaind[i]-fpeded[i]*fgaind[i];
if ((gain==1)&&hasallpede) adcpedecorr=(fpedeG1d[i]*fgaind[i]+G1Poffset-adcvalue*fgaind[i])*30.0;
if ((gain==3)&&hasallpede) adcpedecorr=(fpedeG2d[i]*fgaind[i]+G2Poffset-adcvalue*fgaind[i])*340.0;
}
else
{
if ((gain==0)||(!hasallpede)) adcpedecorr=(adcvalue&0x3fff)-fpeded[i];
if ((gain==1)&&hasallpede) adcpedecorr=(fpedeG1d[i]+G1Poffset-adcvalue)*30.0;
if ((gain==3)&&hasallpede) adcpedecorr=(fpedeG2d[i]+G2Poffset-adcvalue)*340.0;
}
} else {adcpedecorr=float (adcvalue);} //end of if pede
if ((adcpedecorr>threshold)&&(pede_flag)) hchptr[(i)]= hchptr[(i)]+(int)((adcpedecorr+threshold)/phene);
if (fill1Ds) {
if (((i%1024)<1004)&&((i%1024)>20)&&((i/1024)>20)) { //skip the pix near guardring for PH plots
ichip= i/(256*256*4)*4+((i/256)%4) ;
hchip[ichip]->Fill(adcpedecorr,1);
if (((i%256)<253)&&((i%256)>2)) his4500->Fill(adcpedecorrold,adcpedecorr,1);
adcpedecorrold=adcpedecorr;
}
}//if (fill1Ds)
if ((show2Ds)) {
factor=2.0;
value=adcpedecorr;
if ((i%256==0)||(i%256==255)) value=int(value/factor);
if ((i/1024==255)||(i/1024==256)||(i/1024==767)||(i/1024==768)) value=int(value/factor);
his1000->Fill(float(i%1024),float(int (i/1024)),value);
if (!dophotonmap) his3000->Fill(float(i%1024),float(int (i/1024)) ,adcvalue);
his2000->Fill(float(i%1024),float(int (i/1024)) ,gain);
value=(int)(hchptr[i]);
if ((i%256==0)||(i%256==255)) value=int(value/factor);
if ((i/1024==255)||(i/1024==256)||(i/1024==767)||(i/1024==768)) value=int(value/factor);
if (dophotonmap) his3000->Fill(float(i%1024),float(int (i/1024)),float(value));
}
}// for (i=0 ;i<NCH-0;i++)
}// /end of do something
if ((show2Ds)) {
for (ipx=0;ipx<NCH;ipx++) hchptr[(ipx)]=0;
Plot2DHistos(); Plot1DHistos();
}
ifp=kbhit();
processifp(ifp);
if (((framesinstream%NPRO))==NPRO-1) gSystem->ProcessEvents();
}
}// end of infinite loop
rootapp->Run();
nonblock(NB_DISABLE);
return 0;
}
void processifp(int ifp){
if (ifp!=0){
c=fgetc(stdin);
if (c=='s') {if (goout==0){goout=1;}else {myloop();}}
if (c=='S') SetRanges();
if (c=='+') { HDraw_every=HDraw_every*0.8;cout<< endl <<"Drawing every "<< HDraw_every<<" frames "<<endl; }
if (c=='-') { HDraw_every=HDraw_every*1.25;cout<< endl <<"Drawing every "<< HDraw_every<<" frames "<<endl;}
if (c=='G') {gain_flag=not gain_flag ;if (gain_flag) {cout<<"gain corr enab."<< endl;}else {cout<<"gain corr disab."<< endl;}}
if (c=='[') { G1Poffset=G1Poffset-10;cout<< endl <<"G1Poffset "<<G1Poffset<<endl; }
if (c==']') { G1Poffset=G1Poffset+10;cout<< endl <<"G1Poffset "<<G1Poffset<<endl; }
if (c=='{') { G2Poffset=G2Poffset-10;cout<< endl <<"G2Poffset "<<G2Poffset<<endl; }
if (c=='}') { G2Poffset=G2Poffset+10;cout<< endl <<"G2Poffset "<<G2Poffset<<endl; }
if (c=='p') { //stopsocket();
loadpede();//startsocket();
}
if (c=='b') {LoadPaletteBW(1.1111);bw_flag=true; }
if (c=='B') {LoadPaletteBW(0.9);bw_flag=true; }
if (c=='O') savepede();
if (c=='o') readpede();
if (c=='P') loadallpede();
if (c=='u') his1000->SetOption("surf2z");
if (c=='C') his1000->SetOption("colz");
if (c=='q') exit(0);
if (c=='r') historeset();
if (c=='R') axisreset();
}
}
void loadallpede(){
cout <<"not implemented "<< endl;
// hasallpede=true;
// system("./sls_detector_put setbit 0x5d 12 "); //setting to FSG1 ;
// loadpede();
// loadpede();
// for (i=0;i<NCH;i++) {fpedeG1d[i]=fpeded[i];}
// system("./sls_detector_put setbit 0x5d 13 "); //setting to FSG0 ;
// sleep(1);
// loadpede();
// loadpede();
// for (i=0;i<NCH;i++) {fpedeG2d[i]=fpeded[i];}
// system("./sls_detector_put clearbit 0x5d 12 "); //setting to G0;
// system("./sls_detector_put clearbit 0x5d 13 "); //setting to G0;
// sleep(2);
// loadpede();
// loadpede();
}
void loadpede(void){
//startsocket();
framesinstream=0;
pede_flag=true;
nframes=0;
for (ipx=0;ipx<NCH;ipx++) fpeded[ipx]=0;
while (framesinstream<50) { // loop on files
if (!zmqSocket->ReceiveHeader(0,zHeader, SLS_DETECTOR_JSON_HEADER_VERSION)){
return;
}
cout <<"received frameindex "<<zHeader.frameIndex << endl;
zmqSocket->ReceiveData(0, (char *)(&image_data), NCH*2);
framesinstream++;nframes++;
for (ipx=0;ipx<NCH;ipx++) fpeded[ipx]=(fpeded[ipx]*(nframes-1)+(float)(image_data[ipx]&0x3fff))/(float)(nframes);
}
for (ipx=0;ipx<NCH;ipx++) { ipeded[ipx]=(short)(fpeded[ipx]);
if (ipx%60033==0) printf("i=%d pede= %d %f .\n",ipx, ipeded[ipx],fpeded[ipx]);
}
printf("total frames for pede: %d \n",nframes);
//stopsocket();
printhelp();
}
int kbhit()
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
void myloop(void){ //wait doing nothing.
goout=0;
int ifp;
while (goout==0){
ifp=kbhit();
processifp(ifp);
gSystem->ProcessEvents();
usleep(5000);
}
}
void printhelp(){
cout<< endl << "s=start/pause| p/n=getnewpede/raw | o/O=read/save pede | n=nopede(raw) | r/R=rst His/Axis | +/- = faster/slower ref. |q=exit | U/C sUrf2/Colz " <<endl;
}
void historeset(){
his4500->Reset();
his3000->Reset();
for (i=0;i<8;i++) {
hchip[i]->Reset();
}
Plot2DHistos();
Plot1DHistos();
}
void SetRanges() {
string str;
std::cin.clear();
//cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout<< endl;
cout<< " adc min " <<endl;
//getline(cin, str);
// adcmin= stoi(str);
std::cin >> adcmin;
cout<< " adc max " <<endl;
std::cin >> adcmax;
cout<< " p.map min " <<endl;
std::cin >> pmmin;
cout<< " p.map max " <<endl;
std::cin >> pmmax;
fixranges=true;
}
void axisreset(){
fixranges=false;
his1000->GetXaxis()->UnZoom();
his1000->GetYaxis()->UnZoom();
his1000->GetZaxis()->UnZoom();
his2000->GetXaxis()->UnZoom();
his2000->GetYaxis()->UnZoom();
his3000->GetZaxis()->UnZoom();
for (i=0;i<8;i++) {
hchip[i]->GetXaxis()->UnZoom();
hchip[i]->GetYaxis()->UnZoom();
}
his4500->GetXaxis()->UnZoom();
his4500->GetYaxis()->UnZoom();
his4500->GetZaxis()->UnZoom();
Plot2DHistos();
Plot1DHistos();
}
void nonblock(int state)
{
struct termios ttystate;
//get the terminal state
tcgetattr(STDIN_FILENO, &ttystate);
if (state==NB_ENABLE)
{
//turn off canonical mode
ttystate.c_lflag &= ~ICANON;
//minimum of number input read.
ttystate.c_cc[VMIN] = 1;
}
else if (state==NB_DISABLE)
{ //turn on canonical mode
ttystate.c_lflag |= ICANON;
}
//set the terminal attributes.
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
void LoadPaletteFalse(){
const Int_t NRGBs = 5;
const Int_t NCont = 90;
Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 };
Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 };
TColor::CreateGradientColorTable(NRGBs, stops, red,green, blue, NCont);
gStyle->SetNumberContours(NCont);
TColor::CreateGradientColorTable(NRGBs, stops, red,green ,blue, NCont);
gStyle->SetNumberContours(NCont);
}
void LoadPaletteBW(float gammatune){
vgamma=vgamma*gammatune;
cout<< "gamma is "<<vgamma<<endl;
const Int_t NRGBs = 99;
const Int_t NCont = 990;
Double_t stops[NRGBs] ;
Double_t red[NRGBs] ;
Double_t green[NRGBs];
Double_t blue[NRGBs] ;
for (int iRGB=0;iRGB<NRGBs;iRGB++){
stops[iRGB] =(1/float(NRGBs)*float(iRGB));
red[iRGB] = pow(stops[iRGB],vgamma);
green[iRGB] = red[iRGB];
blue[iRGB] =red[iRGB];
// cout << iRGB<<" "<< stops[iRGB] <<" " << red[iRGB]<<endl;
}
TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
gStyle->SetNumberContours(NCont);
// TColor::SetPalette(52,0,1);
}
void Plot1DHistos(void){
if (hchip[0]->GetXaxis()->GetLast()!=oldh0xlast){
oldh0xlast=hchip[0]->GetXaxis()->GetLast();
oldh0xfirst=hchip[0]->GetXaxis()->GetFirst();
for (int ipad=1; ipad<8;ipad++) {
hchip[ipad]->GetXaxis()->SetRange(oldh0xfirst,oldh0xlast);
}
}
for (int ipad=0; ipad<8;ipad++) {
A4->cd(ipad+1);
gStyle->SetOptStat(1); gPad->SetLogy();
hchip[ipad%4+(1-int(ipad/4))*4]->Draw();
}
A4->cd();
A4->Update();
}
void Plot2DHistos(void){
gStyle->SetOptStat(0);
A3->cd();
// if (bw_flag) LoadPaletteBW(1.0);
if (fixranges) {
his1000->GetZaxis()->SetRangeUser(float(adcmin),float(adcmax));
his3000->GetZaxis()->SetRangeUser(float(pmmin),float(pmmax));
}
his1000->SetMinimum(-200);
his1000->Draw();
A3->Update();
A2->cd();
// if (bw_flag) LoadPaletteFalse();
his2000->GetXaxis()->SetRange(his1000->GetXaxis()->GetFirst(),his1000->GetXaxis()->GetLast());
his2000->GetYaxis()->SetRange(his1000->GetYaxis()->GetFirst(),his1000->GetYaxis()->GetLast());
his2000->Draw("colz");
A2->Update();
A5->cd();
his3000->GetXaxis()->SetRange(his1000->GetXaxis()->GetFirst(),his1000->GetXaxis()->GetLast());
his3000->GetYaxis()->SetRange(his1000->GetYaxis()->GetFirst(),his1000->GetYaxis()->GetLast());
his3000->Draw("colz");
A5->Update();
A6->cd();
his4500->Draw("colz");
A6->Update();
}
void startsocket(void) {
try {
zmqSocket = new sls::ZmqSocket(serverip, portnum);
} catch (...) {
cprintf(RED,
"Error: Could not create Zmq socket on port %d with ip %s\n",
portnum, serverip);
delete zmqSocket;
return;
}
zmqSocket->SetReceiveHighWaterMark(3);
zmqSocket->SetReceiveBuffer(1024*1024);
zmqSocket->Connect();
cout<<"Zmq Client[] "<< zmqSocket->GetZmqServerAddress()<<endl;
haveconnection=true;
}
void tryconnect(void)
{
int itry=0;
cout<< endl;
while (haveconnection==false) {
sleep(1);
cout<<"\r trying to (re)connect " <<itry++ << " " << endl ;
startsocket();
}
}
void stopsocket(void) {
// cout<<" cfd " << cfd << endl;;
delete zmqSocket;
zmqSocket=0;
//zmqSocket->~ZmqSocket ();
haveconnection=false;
}
void savepede(void) {
int pfd;
pfd=open(PEDEFNAME,O_CREAT|O_WRONLY, 0666);
if (pfd==-1) perror("open pede file");
write(pfd,fpeded,2*NCH*sizeof(float));
write(pfd,fpedeG1d,2*NCH*sizeof(float));
write(pfd,fpedeG2d,2*NCH*sizeof(float));
close(pfd);
}
void readpede(void) {
int pfd;
pfd=open(PEDEFNAME,O_RDONLY);
if (pfd==-1) perror("open pede file");
read(pfd,fpeded,NCH*2*sizeof(float));
read(pfd,fpedeG1d,NCH*2*sizeof(float));
read(pfd,fpedeG2d,NCH*2*sizeof(float));
close(pfd);
pede_flag=true;
hasallpede=true;
}

View File

@ -0,0 +1,204 @@
/**************************************************************************/
/* Header files section needs cleanup */
/**************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "sls/ZmqSocket.h"
#include "sls/tiffIO.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h> /* exit() */
#include <string.h> /* memset(), memcpy() */
#include <sys/utsname.h> /* uname() */
#include <sys/types.h>
#include <sys/socket.h> /* socket(), bind(),
listen(), accept() */
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h> /* fork(), write(), close() */
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <cmath>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <rapidjson/document.h> //json header in zmq stream
#include <omp.h>
#define NTHREADS 2
#include <chrono>
#include <cstdio>
#include <ctime> // time_t
using namespace std;
using namespace std::chrono;
using namespace sls;
#include "TCanvas.h"
#include "TH1F.h"
#include "TF1.h"
#include "TH2F.h"
#include "TMath.h"
#include "TFile.h"
#include "TStyle.h"
#include "TSystem.h"
#include "TTimer.h"
#include "TProfile.h"
#include "TColor.h"
#include <iostream>
#include <fstream>
#include <termios.h>
#include <TApplication.h>
#include <stdio.h>
#include <math.h>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
#include "sls/ansi.h"
#define SLS_DETECTOR_JSON_HEADER_VERSION 0x4
#define PI 3.14159265
#define FALSE 0
#define OFFSET 0
#define NBIN 500
#define MIN_POS -500.5 // 400.5
#define MAX_POS 3499.5 //-100.5
#define NCH 524288
// #define NCH 262144 in case of half_frames
char serverip[256];
int portnum;
FILE * sfilefd;
short* hchptr; // photon counted map "histogram"
int value;
float factor=1.84;
int npacket=0;
int totalnpacket=0;
float vgamma;
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
struct in_addr inadr;
struct hostent *server;
int i=0;
int ipx=0;
bool haveconnection;
TStyle *gStyle;
TApplication* rootapp;
TCanvas *A2;
TCanvas *A3;
TCanvas *A4;
TCanvas *A5;
TCanvas *A6;
TH1I **hchip;
TH2F **h4500chip;
short image_data[NCH*2];
short imaged[NCH*2];
float fpeded[NCH*2];
float fpedeG2d[NCH*2];
float fpedeG1d[NCH*2];
short ipeded[NCH*2];
short pcimaged[NCH*2];
float fgaind[NCH*2];
float adcpedecorr,adcpedecorrold;
bool gain_flag;
bool bw_flag;
bool fill2Ds;
bool show2Ds;
bool fill1Ds;
bool pede_flag;
bool dophotonmap;
int nx, ny;
int nframes;
int goout;
int framesinstream;
int ifp;
float threshold;
int phene;
int adcvalue;
int gain;
int ichip;
int frameIndex_old;
char pedefilename[128];
int framenum,bunchid;
TH2F* his1000;
TH2F* his2000;
TH2F* his3000;
TH2F* his4500;
TH1I* hproj;
TH1I* hchcum;
using namespace std;
void printhelp(void);
void processifp(int ifp);
void historeset(void);
void SetRanges(void);
void startsocket(void);
void stopsocket(void);
void axisreset(void);
int kbhit(void);
void myloop(void);
void loadpede(void);
void loadallpede(void);
void loadgain(void);
void nonblock(int state);
void LoadPaletteFalse(void);
void LoadPaletteBW(float);
void Plot1DHistos(void);
void Plot2DHistos(void);
void savepede(void);
void readpede(void);
int findinterpoindex(int startindex);
int findclumax(int startindex);
void tryconnect(void) ;
#define NB_ENABLE 1
#define NB_DISABLE 0
char c;
int HDraw_every;
float oldh0xfirst,oldh0xlast;
int idx;
int GXPoffset,G1Poffset,G2Poffset;
int ix,iy;
int adcmin,adcmax;
int pmmin,pmmax; //min/mnx for the photon map
bool fixranges;
sls::ZmqSocket *zmqSocket= NULL;

View File

@ -59,6 +59,7 @@ class qDrawPlot : public QWidget, private Ui::PlotObject {
void ClonePlot(); void ClonePlot();
void SavePlot(); void SavePlot();
void SetGapPixels(bool enable); void SetGapPixels(bool enable);
void UpdatePlot();
protected: protected:
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
@ -67,7 +68,7 @@ class qDrawPlot : public QWidget, private Ui::PlotObject {
void Zoom1DGainPlot(const QRectF &rect); void Zoom1DGainPlot(const QRectF &rect);
void Zoom2DGainPlot(const QRectF &rect); void Zoom2DGainPlot(const QRectF &rect);
void SetSaveFileName(QString val); void SetSaveFileName(QString val);
void UpdatePlot(); // void UpdatePlot();
signals: signals:
void AcquireFinishedSignal(); void AcquireFinishedSignal();

View File

@ -47,6 +47,7 @@ class qTabPlot : public QWidget, private Ui::TabPlotObject {
private: private:
void SetupWidgetWindow(); void SetupWidgetWindow();
void Initialization(); void Initialization();
bool VerifyGapPixelsAllowed();
void Select1DPlot(bool enable); void Select1DPlot(bool enable);
void GetGapPixels(); void GetGapPixels();
void GetStreamingFrequency(); void GetStreamingFrequency();
@ -60,7 +61,8 @@ class qTabPlot : public QWidget, private Ui::TabPlotObject {
Detector *det; Detector *det;
qDrawPlot *plot; qDrawPlot *plot;
bool is1d; bool is1d{false};
bool isGapPixelsAllowed{false};
/** default plot and axis titles */ /** default plot and axis titles */
static QString defaultPlotTitle; static QString defaultPlotTitle;

View File

@ -16,7 +16,7 @@ QString qTabPlot::defaultImageYAxisTitle("Pixel");
QString qTabPlot::defaultImageZAxisTitle("Intensity"); QString qTabPlot::defaultImageZAxisTitle("Intensity");
qTabPlot::qTabPlot(QWidget *parent, Detector *detector, qDrawPlot *p) qTabPlot::qTabPlot(QWidget *parent, Detector *detector, qDrawPlot *p)
: QWidget(parent), det(detector), plot(p), is1d(false) { : QWidget(parent), det(detector), plot(p) {
setupUi(this); setupUi(this);
SetupWidgetWindow(); SetupWidgetWindow();
LOG(logDEBUG) << "Plot ready"; LOG(logDEBUG) << "Plot ready";
@ -57,11 +57,7 @@ void qTabPlot::SetupWidgetWindow() {
chkGainPlot1D->setChecked(true); chkGainPlot1D->setChecked(true);
plot->EnableGainPlot(true); plot->EnableGainPlot(true);
break; break;
case slsDetectorDefs::EIGER:
chkGapPixels->setEnabled(true);
break;
case slsDetectorDefs::JUNGFRAU: case slsDetectorDefs::JUNGFRAU:
chkGapPixels->setEnabled(true);
chkGainPlot->setEnabled(true); chkGainPlot->setEnabled(true);
chkGainPlot->setChecked(true); chkGainPlot->setChecked(true);
plot->EnableGainPlot(true); plot->EnableGainPlot(true);
@ -69,6 +65,8 @@ void qTabPlot::SetupWidgetWindow() {
default: default:
break; break;
} }
isGapPixelsAllowed = VerifyGapPixelsAllowed();
chkGapPixels->setEnabled(isGapPixelsAllowed);
Select1DPlot(is1d); Select1DPlot(is1d);
Initialization(); Initialization();
@ -195,6 +193,29 @@ void qTabPlot::Initialization() {
connect(dispZMax, SIGNAL(editingFinished()), this, SLOT(isZMaxModified())); connect(dispZMax, SIGNAL(editingFinished()), this, SLOT(isZMaxModified()));
} }
bool qTabPlot::VerifyGapPixelsAllowed() {
try {
switch (det->getDetectorType().squash()) {
case slsDetectorDefs::JUNGFRAU:
return true;
case slsDetectorDefs::EIGER:
if (det->getQuad().squash(false)) {
return true;
}
// full modules
if (det->getModuleGeometry().y % 2 == 0) {
return true;
}
return false;
default:
return false;
}
}
CATCH_DISPLAY("Could not verify if gap pixels allowed.",
"qTabPlot::VerifyGapPixelsAllowed")
return false;
}
void qTabPlot::Select1DPlot(bool enable) { void qTabPlot::Select1DPlot(bool enable) {
LOG(logDEBUG) << "Selecting " << (enable ? "1" : "2") << "D Plot"; LOG(logDEBUG) << "Selecting " << (enable ? "1" : "2") << "D Plot";
is1d = enable; is1d = enable;
@ -487,6 +508,7 @@ void qTabPlot::SetXYRange() {
} }
plot->SetXYRangeChanged(disablezoom, xyRange, isRange); plot->SetXYRangeChanged(disablezoom, xyRange, isRange);
plot->UpdatePlot();
emit DisableZoomSignal(disablezoom); emit DisableZoomSignal(disablezoom);
} }
@ -624,6 +646,7 @@ void qTabPlot::SetZRange() {
zRange[1] = val; zRange[1] = val;
} }
plot->SetZRange(zRange, isZRange); plot->SetZRange(zRange, isZRange);
plot->UpdatePlot();
} }
void qTabPlot::GetStreamingFrequency() { void qTabPlot::GetStreamingFrequency() {
@ -770,15 +793,10 @@ void qTabPlot::Refresh() {
boxFrequency->setEnabled(true); boxFrequency->setEnabled(true);
GetStreamingFrequency(); GetStreamingFrequency();
GetHwm(); GetHwm();
// gain plot, gap pixels enable // gain plot
switch (det->getDetectorType().squash()) { switch (det->getDetectorType().squash()) {
case slsDetectorDefs::EIGER:
chkGapPixels->setEnabled(true);
GetGapPixels();
break;
case slsDetectorDefs::JUNGFRAU: case slsDetectorDefs::JUNGFRAU:
chkGainPlot->setEnabled(true); chkGainPlot->setEnabled(true);
chkGapPixels->setEnabled(true);
GetGapPixels(); GetGapPixels();
break; break;
case slsDetectorDefs::GOTTHARD2: case slsDetectorDefs::GOTTHARD2:
@ -787,6 +805,11 @@ void qTabPlot::Refresh() {
default: default:
break; break;
} }
// gap pixels
if (isGapPixelsAllowed) {
chkGapPixels->setEnabled(true);
GetGapPixels();
}
} else { } else {
boxFrequency->setEnabled(false); boxFrequency->setEnabled(false);
chkGainPlot->setEnabled(false); chkGainPlot->setEnabled(false);

View File

@ -1106,7 +1106,9 @@ int Beb_SetDetectorPosition(int pos[]) {
int posRight[2] = {Beb_top ? pos[X] + 1 : pos[X], pos[Y]}; int posRight[2] = {Beb_top ? pos[X] + 1 : pos[X], pos[Y]};
if (Beb_quadEnable) { if (Beb_quadEnable) {
posRight[Y] = 1; // right is next row posLeft[Y] = 1; // left is next row
posLeft[X] = 0; // left same first row
posRight[Y] = 0; // right same first row
posRight[X] = 0; // right same first column posRight[X] = 0; // right same first column
} }

View File

@ -25,7 +25,7 @@ target_include_directories(eigerDetectorServer_virtual
) )
target_compile_definitions(eigerDetectorServer_virtual target_compile_definitions(eigerDetectorServer_virtual
PUBLIC EIGERD PCCOMPILE STOP_SERVER PUBLIC EIGERD PCCOMPILE STOP_SERVER #TEST_MOD_GEOMETRY
PUBLIC VIRTUAL #VIRTUAL_9M PUBLIC VIRTUAL #VIRTUAL_9M
) )

View File

@ -1240,19 +1240,16 @@ int Feb_Control_GetDynamicRange(int *retval) {
int Feb_Control_Disable16bitConversion(int disable) { int Feb_Control_Disable16bitConversion(int disable) {
LOG(logINFO, ("%s 16 bit expansion\n", disable ? "Disabling" : "Enabling")); LOG(logINFO, ("%s 16 bit expansion\n", disable ? "Disabling" : "Enabling"));
uint32_t bitmask = DAQ_REG_HRDWRE_DSBL_16BIT_MSK;
unsigned int regval = 0; unsigned int regval = 0;
if (!Feb_Control_ReadRegister(DAQ_REG_HRDWRE, &regval)) {
LOG(logERROR, ("Could not %s 16 bit expansion (bit mode)\n",
(disable ? "disable" : "enable")));
return 0;
}
if (disable) { if (disable) {
regval |= DAQ_REG_HRDWRE_DSBL_16BIT_MSK; regval |= bitmask;
} else { } else {
regval &= ~DAQ_REG_HRDWRE_DSBL_16BIT_MSK; regval &= ~bitmask;
} }
if (!Feb_Control_WriteRegister(DAQ_REG_HRDWRE, regval)) { if (!Feb_Control_WriteRegister_BitMask(DAQ_REG_HRDWRE, regval, bitmask)) {
LOG(logERROR, ("Could not %s 16 bit expansion (bit mode)\n", LOG(logERROR, ("Could not %s 16 bit expansion (bit mode)\n",
(disable ? "disable" : "enable"))); (disable ? "disable" : "enable")));
return 0; return 0;
@ -1262,11 +1259,12 @@ int Feb_Control_Disable16bitConversion(int disable) {
int Feb_Control_Get16bitConversionDisabled(int *ret) { int Feb_Control_Get16bitConversionDisabled(int *ret) {
unsigned int regval = 0; unsigned int regval = 0;
if (!Feb_Control_ReadRegister(DAQ_REG_HRDWRE, &regval)) { if (!Feb_Control_ReadRegister_BitMask(DAQ_REG_HRDWRE, &regval,
DAQ_REG_HRDWRE_DSBL_16BIT_MSK)) {
LOG(logERROR, ("Could not get 16 bit expansion (bit mode)\n")); LOG(logERROR, ("Could not get 16 bit expansion (bit mode)\n"));
return 0; return 0;
} }
if (regval & DAQ_REG_HRDWRE_DSBL_16BIT_MSK) { if (regval) {
*ret = 1; *ret = 1;
} else { } else {
*ret = 0; *ret = 0;
@ -1667,6 +1665,15 @@ int Feb_Control_GetReadNRows() {
} }
int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) { int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) {
return Feb_Control_WriteRegister_BitMask(offset, data, BIT32_MSK);
}
int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval) {
return Feb_Control_ReadRegister_BitMask(offset, retval, BIT32_MASK);
}
int Feb_Control_WriteRegister_BitMask(uint32_t offset, uint32_t data,
uint32_t bitmask) {
uint32_t actualOffset = offset; uint32_t actualOffset = offset;
char side[2][10] = {"right", "left"}; char side[2][10] = {"right", "left"};
unsigned int addr[2] = {Feb_Control_rightAddress, Feb_Control_leftAddress}; unsigned int addr[2] = {Feb_Control_rightAddress, Feb_Control_leftAddress};
@ -1690,24 +1697,41 @@ int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) {
for (int iloop = 0; iloop < 2; ++iloop) { for (int iloop = 0; iloop < 2; ++iloop) {
if (run[iloop]) { if (run[iloop]) {
LOG(logDEBUG1, LOG(logDEBUG1, ("Writing 0x%x to %s 0x%x (mask:0x%x)\n", data,
("Writing 0x%x to %s 0x%x\n", data, side[iloop], actualOffset)); side[iloop], actualOffset, bitmask));
if (!Feb_Interface_WriteRegister(addr[iloop], actualOffset, data, 0,
0)) { uint32_t writeVal = 0;
LOG(logERROR, ("Could not write 0x%x to %s addr 0x%x\n", data, if (!Feb_Interface_ReadRegister(addr[iloop], actualOffset,
&writeVal)) {
LOG(logERROR, ("Could not read %s addr 0x%x register\n",
side[iloop], actualOffset)); side[iloop], actualOffset));
return 0; return 0;
} }
uint32_t regVal = 0; // set only the bits in the mask
if (!Feb_Interface_ReadRegister(addr[iloop], actualOffset, writeVal &= ~(bitmask);
&regVal)) { writeVal |= (data & bitmask);
LOG(logERROR, ("Could not read %s register\n", addr[iloop]));
LOG(logDEBUG1, ("writing 0x%x to 0x%x\n", writeVal, actualOffset));
if (!Feb_Interface_WriteRegister(addr[iloop], actualOffset,
writeVal, 0, 0)) {
LOG(logERROR, ("Could not write 0x%x to %s addr 0x%x\n",
writeVal, side[iloop], actualOffset));
return 0; return 0;
} }
if (regVal != data) { writeVal &= bitmask;
uint32_t readVal = 0;
if (!Feb_Interface_ReadRegister(addr[iloop], actualOffset,
&readVal)) {
return 0;
}
readVal &= bitmask;
if (writeVal != readVal) {
LOG(logERROR, LOG(logERROR,
("Could not write %s register. Write 0x%x, read 0x%x\n", ("Could not write %s addr 0x%x register. Wrote "
addr[iloop], data, regVal)); "0x%x, read 0x%x (mask:0x%x)\n",
side[iloop], actualOffset, writeVal, readVal, bitmask));
return 0; return 0;
} }
} }
@ -1716,7 +1740,8 @@ int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) {
return 1; return 1;
} }
int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval) { int Feb_Control_ReadRegister_BitMask(uint32_t offset, uint32_t *retval,
uint32_t bitmask) {
uint32_t actualOffset = offset; uint32_t actualOffset = offset;
char side[2][10] = {"right", "left"}; char side[2][10] = {"right", "left"};
unsigned int addr[2] = {Feb_Control_rightAddress, Feb_Control_leftAddress}; unsigned int addr[2] = {Feb_Control_rightAddress, Feb_Control_leftAddress};
@ -1746,8 +1771,9 @@ int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval) {
side[iloop], actualOffset)); side[iloop], actualOffset));
return 0; return 0;
} }
LOG(logDEBUG1, ("Read 0x%x from %s 0x%x\n", value[iloop], value[iloop] &= bitmask;
side[iloop], actualOffset)); LOG(logDEBUG1, ("Read 0x%x from %s 0x%x (mask:0x%x)\n",
value[iloop], side[iloop], actualOffset, bitmask));
*retval = value[iloop]; *retval = value[iloop];
// if not the other (left, not right OR right, not left), return the // if not the other (left, not right OR right, not left), return the
// value // value
@ -1758,7 +1784,7 @@ int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval) {
} }
// Inconsistent values when reading both registers // Inconsistent values when reading both registers
if ((run[0] & run[1]) & (value[0] != value[1])) { if ((run[0] & run[1]) & (value[0] != value[1])) {
LOG(logERROR, ("Inconsistent values read from %s 0x%x and %s 0x%x\n", LOG(logERROR, ("Inconsistent values read from %s: 0x%x and %s: 0x%x\n",
side[0], value[0], side[1], value[1])); side[0], value[0], side[1], value[1]));
return 0; return 0;
} }

View File

@ -95,7 +95,10 @@ int Feb_Control_SetReadNRows(int value);
int Feb_Control_GetReadNRows(); int Feb_Control_GetReadNRows();
int Feb_Control_WriteRegister(uint32_t offset, uint32_t data); int Feb_Control_WriteRegister(uint32_t offset, uint32_t data);
int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval); int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval);
int Feb_Control_WriteRegister_BitMask(uint32_t offset, uint32_t data,
uint32_t bitmask);
int Feb_Control_ReadRegister_BitMask(uint32_t offset, uint32_t *retval,
uint32_t bitmask);
// pulsing // pulsing
int Feb_Control_Pulse_Pixel(int npulses, int x, int y); int Feb_Control_Pulse_Pixel(int npulses, int x, int y);
int Feb_Control_PulsePixelNMove(int npulses, int inc_x_pos, int inc_y_pos); int Feb_Control_PulsePixelNMove(int npulses, int inc_x_pos, int inc_y_pos);

View File

@ -861,12 +861,15 @@ int setDynamicRange(int dr) {
LOG(logINFO, ("Setting dynamic range: %d\n", dr)); LOG(logINFO, ("Setting dynamic range: %d\n", dr));
#else #else
sharedMemory_lockLocalLink(); sharedMemory_lockLocalLink();
if (Feb_Control_SetDynamicRange(dr)) { if (!Feb_Control_SetDynamicRange(dr)) {
if (!Beb_SetUpTransferParameters(dr)) { LOG(logERROR, ("Could not set dynamic range in feb\n"));
LOG(logERROR, ("Could not set bit mode in the back end\n")); sharedMemory_unlockLocalLink();
sharedMemory_unlockLocalLink(); return FAIL;
return eiger_dynamicrange; }
} if (!Beb_SetUpTransferParameters(dr)) {
LOG(logERROR, ("Could not set bit mode in the back end\n"));
sharedMemory_unlockLocalLink();
return eiger_dynamicrange;
} }
sharedMemory_unlockLocalLink(); sharedMemory_unlockLocalLink();
#endif #endif
@ -2664,6 +2667,10 @@ void *start_timer(void *arg) {
header->modId = eiger_virtual_module_id; header->modId = eiger_virtual_module_id;
header->row = row; header->row = row;
header->column = colLeft; header->column = colLeft;
if (eiger_virtual_quad_mode) {
header->row = 1; // left is next row
header->column = 0; // left same first column
}
char packetData2[packetsize]; char packetData2[packetsize];
memset(packetData2, 0, packetsize); memset(packetData2, 0, packetsize);
@ -2672,11 +2679,11 @@ void *start_timer(void *arg) {
header->version = SLS_DETECTOR_HEADER_VERSION; header->version = SLS_DETECTOR_HEADER_VERSION;
header->frameNumber = frameNr + iframes; header->frameNumber = frameNr + iframes;
header->packetNumber = i; header->packetNumber = i;
header->modId = eiger_virtual_module_id; header->modId = eiger_virtual_module_id + 1;
header->row = row; header->row = row;
header->column = colRight; header->column = colRight;
if (eiger_virtual_quad_mode) { if (eiger_virtual_quad_mode) {
header->row = 1; // right is next row header->row = 0; // right is next row
header->column = 0; // right same first column header->column = 0; // right same first column
} }

View File

@ -137,6 +137,7 @@ enum MASTERINDEX { MASTER_HARDWARE, OW_MASTER, OW_SLAVE };
#define UDP_HEADER_MAX_FRAME_VALUE (0xFFFFFFFFFFFF) #define UDP_HEADER_MAX_FRAME_VALUE (0xFFFFFFFFFFFF)
#define BIT16_MASK (0xFFFF) #define BIT16_MASK (0xFFFF)
#define BIT32_MSK (0xFFFFFFFF)
#define DAC_MIN_MV (0) #define DAC_MIN_MV (0)
#define DAC_MAX_MV (2048) #define DAC_MAX_MV (2048)

View File

@ -1007,7 +1007,9 @@ int setDelayAfterTrigger(int64_t val) {
// validate for tolerance // validate for tolerance
int64_t retval = getDelayAfterTrigger(); int64_t retval = getDelayAfterTrigger();
val /= (1E-9 * CLK_FREQ); val /= (1E-9 * CLK_FREQ);
val -= masterdefaultdelay; if (master) {
val -= masterdefaultdelay;
}
if (val != retval) { if (val != retval) {
return FAIL; return FAIL;
} }

View File

@ -313,7 +313,7 @@ patternParameters *setChannelRegisterChip(int ichip, char *mask,
chanReg, ichip * NCHAN + ich * NCOUNTERS, chanReg, ichip * NCHAN + ich * NCOUNTERS,
ichip * NCHAN_1_COUNTER + ich, ichip, ich)); ichip * NCHAN_1_COUNTER + ich, ichip, ich));
} }
for (int i = 0; i < 24; i++) { for (int i = 0; i < 23; i++) {
patword = clearBit(SIGNAL_clk, patword); patword = clearBit(SIGNAL_clk, patword);
pat->word[iaddr++] = patword; pat->word[iaddr++] = patword;

View File

@ -3,7 +3,7 @@
#pragma once #pragma once
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define REQRD_FRMWRE_VRSN (0x221205) #define REQRD_FRMWRE_VRSN (0x230124)
#define KERNEL_DATE_VRSN "Mon May 10 18:00:21 CEST 2021" #define KERNEL_DATE_VRSN "Mon May 10 18:00:21 CEST 2021"
#define ID_FILE "detid_mythen3.txt" #define ID_FILE "detid_mythen3.txt"
@ -57,10 +57,10 @@
#define DEFAULT_TRIMBIT_VALUE (0) #define DEFAULT_TRIMBIT_VALUE (0)
#define DEFAULT_COUNTER_DISABLED_VTH_VAL (2800) #define DEFAULT_COUNTER_DISABLED_VTH_VAL (2800)
#define DEFAULT_READOUT_C0 (12) //(083333333) // rdo_clk, 83.33 MHz #define DEFAULT_READOUT_C0 (10) //(100000000) // rdo_clk, 100 MHz
#define DEFAULT_READOUT_C1 (12) //(083333333) // rdo_smp_clk, 83.33 MHz #define DEFAULT_READOUT_C1 (10) //(100000000) // rdo_smp_clk, 100 MHz
#define DEFAULT_SYSTEM_C0 (20) //(050000000) // run_clk, 20 MHz #define DEFAULT_SYSTEM_C0 (10) //(100000000) // run_clk, 100 MHz
#define DEFAULT_SYSTEM_C1 (8) //(125000000) // str_clk, 125 MHz const #define DEFAULT_SYSTEM_C1 (6) //(166666666) // str_clk, 166 MHz const
#define DEFAULT_SYSTEM_C2 (5) //(200000000) // smp_clk, 200 MHz const #define DEFAULT_SYSTEM_C2 (5) //(200000000) // smp_clk, 200 MHz const
#define DEFAULT_TRIMMING_RUN_CLKDIV (40) // (25000000) // 25 MHz #define DEFAULT_TRIMMING_RUN_CLKDIV (40) // (25000000) // 25 MHz

View File

@ -5139,11 +5139,20 @@ int set_source_udp_mac(int file_des) {
if (Server_VerifyLock() == OK) { if (Server_VerifyLock() == OK) {
if (check_detector_idle("configure mac") == OK) { if (check_detector_idle("configure mac") == OK) {
if (udpDetails[0].srcmac != arg) { if (udpDetails[0].srcmac != arg) {
for (int iRxEntry = 0; iRxEntry != MAX_UDP_DESTINATION; // multicast (LSB of first octet = 1)
++iRxEntry) { if ((arg >> 40) & 0x1) {
udpDetails[iRxEntry].srcmac = arg; ret = FAIL;
sprintf(mess,
"Cannot set source mac address. Must be a unicast "
"address (LSB of first octet should be 0).");
LOG(logERROR, (mess));
} else {
for (int iRxEntry = 0; iRxEntry != MAX_UDP_DESTINATION;
++iRxEntry) {
udpDetails[iRxEntry].srcmac = arg;
}
configure_mac();
} }
configure_mac();
} }
} }
} }

View File

@ -221,6 +221,17 @@ class Detector {
*/ */
void setBadChannels(const std::string &fname, Positions pos = {}); void setBadChannels(const std::string &fname, Positions pos = {});
/** [Gotthard2][Mythen3] */
Result<std::vector<int>> getBadChannels(Positions pos = {}) const;
/** [Gotthard2][Mythen3] Empty list resets bad channel list */
void setBadChannels(const std::vector<int> list, Positions pos = {});
/** [Gotthard2][Mythen3] Size of list should match number of modules. Each
* value is at module level and can start at 0. Empty vector resets bad
* channel list. */
void setBadChannels(const std::vector<std::vector<int>> list);
Result<bool> isVirtualDetectorServer(Positions pos = {}) const; Result<bool> isVirtualDetectorServer(Positions pos = {}) const;
///@} ///@}
@ -932,9 +943,10 @@ class Detector {
/** Client IP Address that last communicated with the receiver */ /** Client IP Address that last communicated with the receiver */
Result<IpAddr> getRxLastClientIP(Positions pos = {}) const; Result<IpAddr> getRxLastClientIP(Positions pos = {}) const;
/** Get thread ids from the receiver in order of [parent, tcp, listener 0, /** Get kernel thread ids from the receiver in order of [parent, tcp,
* processor 0, streamer 0, listener 1, processor 1, streamer 1, arping]. If * listener 0, processor 0, streamer 0, listener 1, processor 1, streamer 1,
* no streamer yet or there is no second interface, it gives 0 in its place. * arping]. If no streamer yet or there is no second interface, it gives 0
* in its place.
*/ */
Result<std::array<pid_t, NUM_RX_THREAD_IDS>> Result<std::array<pid_t, NUM_RX_THREAD_IDS>>
getRxThreadIds(Positions pos = {}) const; getRxThreadIds(Positions pos = {}) const;

View File

@ -7,6 +7,7 @@
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/bit_utils.h" #include "sls/bit_utils.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/file_utils.h"
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
@ -548,9 +549,9 @@ std::string CmdProxy::BadChannels(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[fname]\n\t[Gotthard2][Mythen3] Sets the bad channels (from " os << "[fname|none|0]\n\t[Gotthard2][Mythen3] Sets the bad channels "
"file of bad channel numbers) to be masked out." "(from file of bad channel numbers) to be masked out. None or 0 "
"\n\t[Mythen3] Also does trimming" "unsets all the badchannels.\n\t[Mythen3] Also does trimming"
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
if (args.size() != 1) { if (args.size() != 1) {
@ -559,10 +560,25 @@ std::string CmdProxy::BadChannels(int action) {
det->getBadChannels(args[0], std::vector<int>{det_id}); det->getBadChannels(args[0], std::vector<int>{det_id});
os << "successfully retrieved" << '\n'; os << "successfully retrieved" << '\n';
} else if (action == defs::PUT_ACTION) { } else if (action == defs::PUT_ACTION) {
if (args.size() != 1) { bool parse = false;
if (args.size() == 0) {
WrongNumberOfParameters(1); WrongNumberOfParameters(1);
} else if (args.size() == 1) {
if (args[0] == "none" || args[0] == "0") {
det->setBadChannels(std::vector<int>{},
std::vector<int>{det_id});
} else if (args[0].find(".") != std::string::npos) {
det->setBadChannels(args[0], std::vector<int>{det_id});
} else {
parse = true;
}
}
// parse multi args or single one with range or single value
if (parse || args.size() > 1) {
// get channels
auto list = getChannelsFromStringList(args);
det->setBadChannels(list, std::vector<int>{det_id});
} }
det->setBadChannels(args[0], std::vector<int>{det_id});
os << "successfully loaded" << '\n'; os << "successfully loaded" << '\n';
} else { } else {
throw RuntimeError("Unknown action"); throw RuntimeError("Unknown action");
@ -2839,6 +2855,8 @@ std::string CmdProxy::PatternLoopAddresses(int action) {
if (cmd != "patlimits") { if (cmd != "patlimits") {
GetLevelAndUpdateArgIndex(action, "patloop", level, iArg, nGetArgs, GetLevelAndUpdateArgIndex(action, "patloop", level, iArg, nGetArgs,
nPutArgs); nPutArgs);
if (cmd != "patloop0" && cmd != "patloop1" && cmd != "patloop2")
os << level << ' ';
} }
if (action == defs::GET_ACTION) { if (action == defs::GET_ACTION) {
auto t = auto t =
@ -2878,6 +2896,8 @@ std::string CmdProxy::PatternLoopCycles(int action) {
int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1; int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1;
GetLevelAndUpdateArgIndex(action, "patnloop", level, iArg, nGetArgs, GetLevelAndUpdateArgIndex(action, "patnloop", level, iArg, nGetArgs,
nPutArgs); nPutArgs);
if (cmd != "patnloop0" && cmd != "patnloop1" && cmd != "patnloop2")
os << level << ' ';
if (action == defs::GET_ACTION) { if (action == defs::GET_ACTION) {
auto t = det->getPatternLoopCycles(level, std::vector<int>{det_id}); auto t = det->getPatternLoopCycles(level, std::vector<int>{det_id});
os << OutString(t) << '\n'; os << OutString(t) << '\n';
@ -2912,6 +2932,8 @@ std::string CmdProxy::PatternWaitAddress(int action) {
int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1; int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1;
GetLevelAndUpdateArgIndex(action, "patwait", level, iArg, nGetArgs, GetLevelAndUpdateArgIndex(action, "patwait", level, iArg, nGetArgs,
nPutArgs); nPutArgs);
if (cmd != "patwait0" && cmd != "patwait1" && cmd != "patwait2")
os << level << ' ';
if (action == defs::GET_ACTION) { if (action == defs::GET_ACTION) {
auto t = det->getPatternWaitAddr(level, std::vector<int>{det_id}); auto t = det->getPatternWaitAddr(level, std::vector<int>{det_id});
os << OutStringHex(t, 4) << '\n'; os << OutStringHex(t, 4) << '\n';
@ -2945,6 +2967,9 @@ std::string CmdProxy::PatternWaitTime(int action) {
int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1; int level = -1, iArg = 0, nGetArgs = 0, nPutArgs = 1;
GetLevelAndUpdateArgIndex(action, "patwaittime", level, iArg, nGetArgs, GetLevelAndUpdateArgIndex(action, "patwaittime", level, iArg, nGetArgs,
nPutArgs); nPutArgs);
if (cmd != "patwaittime0" && cmd != "patwaittime1" &&
cmd != "patwaittime2")
os << level << ' ';
if (action == defs::GET_ACTION) { if (action == defs::GET_ACTION) {
auto t = det->getPatternWaitTime(level, std::vector<int>{det_id}); auto t = det->getPatternWaitTime(level, std::vector<int>{det_id});
os << OutString(t) << '\n'; os << OutString(t) << '\n';

View File

@ -1767,11 +1767,12 @@ class CmdProxy {
rx_lastclient, getRxLastClientIP, rx_lastclient, getRxLastClientIP,
"\n\tClient IP Address that last communicated with the receiver."); "\n\tClient IP Address that last communicated with the receiver.");
GET_COMMAND(rx_threads, getRxThreadIds, GET_COMMAND(
"\n\tGet thread ids from the receiver in order of [parent, " rx_threads, getRxThreadIds,
"tcp, listener 0, processor 0, streamer 0, listener 1, " "\n\tGet kernel thread ids from the receiver in order of [parent, "
"processor 1, streamer 1, arping]. If no streamer yet or there " "tcp, listener 0, processor 0, streamer 0, listener 1, "
"is no second interface, it gives 0 in its place."); "processor 1, streamer 1, arping]. If no streamer yet or there "
"is no second interface, it gives 0 in its place.");
INTEGER_COMMAND_VEC_ID(rx_arping, getRxArping, setRxArping, StringTo<int>, INTEGER_COMMAND_VEC_ID(rx_arping, getRxArping, setRxArping, StringTo<int>,
"[0, 1]\n\tStarts a thread in slsReceiver to arping " "[0, 1]\n\tStarts a thread in slsReceiver to arping "

View File

@ -349,6 +349,29 @@ void Detector::setBadChannels(const std::string &fname, Positions pos) {
pimpl->setBadChannels(fname, pos); pimpl->setBadChannels(fname, pos);
} }
Result<std::vector<int>> Detector::getBadChannels(Positions pos) const {
return pimpl->Parallel(&Module::getBadChannels, pos);
}
void Detector::setBadChannels(const std::vector<std::vector<int>> list) {
if (list.size() != static_cast<size_t>(size())) {
std::stringstream ss;
ss << "Number of bad channel sets (" << list.size()
<< ") needs to match the number of modules (" << size() << ")";
throw RuntimeError(ss.str());
}
for (int idet = 0; idet < size(); ++idet) {
// TODO! Call in parallel since loading trimbits is slow?
pimpl->Parallel(&Module::setBadChannels, {idet}, list[idet]);
}
}
void Detector::setBadChannels(const std::vector<int> list, Positions pos) {
pimpl->setBadChannels(list, pos);
}
Result<bool> Detector::isVirtualDetectorServer(Positions pos) const { Result<bool> Detector::isVirtualDetectorServer(Positions pos) const {
return pimpl->Parallel(&Module::isVirtualDetectorServer, pos); return pimpl->Parallel(&Module::isVirtualDetectorServer, pos);
} }

View File

@ -253,14 +253,15 @@ void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
} }
void DetectorImpl::setHostname(const std::vector<std::string> &name) { void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// this check is there only to allow the previous detsizechan command // do not free always to allow the previous detsize/ initialchecks command
if (shm()->totalNumberOfModules != 0) { if (shm.exists() && shm()->totalNumberOfModules != 0) {
LOG(logWARNING) << "There are already module(s) in shared memory." LOG(logWARNING) << "There are already module(s) in shared memory."
"Freeing Shared memory now."; "Freeing Shared memory now.";
bool initialChecks = shm()->initialChecks;
freeSharedMemory(); freeSharedMemory();
}
// could be called after freeing shm from API
if (!shm.exists()) {
setupDetector(); setupDetector();
shm()->initialChecks = initialChecks;
} }
for (const auto &hostname : name) { for (const auto &hostname : name) {
addModule(hostname); addModule(hostname);
@ -342,28 +343,32 @@ void DetectorImpl::updateDetectorSize() {
"updating detector size. "); "updating detector size. ");
} }
int maxx = shm()->numberOfChannels.x;
int maxy = shm()->numberOfChannels.y;
int nModx = 0, nMody = 0; int nModx = 0, nMody = 0;
// 1d, add modules along x axis // 1d, add modules along x axis
if (modSize.y == 1) { if (modSize.y == 1) {
if (maxx == 0) { int detSizeX = shm()->numberOfChannels.x;
maxx = modSize.x * size(); int maxChanX = modSize.x * size();
// user given detsizex used only within max value
if (detSizeX > 1 && detSizeX <= maxChanX) {
maxChanX = detSizeX;
} }
nModx = maxx / modSize.x; nModx = maxChanX / modSize.x;
nMody = size() / nModx; nMody = size() / nModx;
if ((maxx % modSize.x) > 0) { if ((maxChanX % modSize.x) > 0) {
++nMody; ++nMody;
} }
} }
// 2d, add modules along y axis (due to eiger top/bottom) // 2d, add modules along y axis (due to eiger top/bottom)
else { else {
if (maxy == 0) { int detSizeY = shm()->numberOfChannels.y;
maxy = modSize.y * size(); int maxChanY = modSize.y * size();
// user given detsizey used only within max value
if (detSizeY > 1 && detSizeY <= maxChanY) {
maxChanY = detSizeY;
} }
nMody = maxy / modSize.y; nMody = maxChanY / modSize.y;
nModx = size() / nMody; nModx = size() / nMody;
if ((maxy % modSize.y) > 0) { if ((maxChanY % modSize.y) > 0) {
++nModx; ++nModx;
} }
} }
@ -515,19 +520,18 @@ void DetectorImpl::setTransmissionDelay(int step) {
f.get(); f.get();
} }
int DetectorImpl::destroyReceivingDataSockets() { void DetectorImpl::destroyReceivingDataSockets() {
LOG(logINFO) << "Going to destroy data sockets"; LOG(logINFO) << "Going to destroy data sockets";
// close socket // close socket
zmqSocket.clear(); zmqSocket.clear();
client_downstream = false; client_downstream = false;
LOG(logINFO) << "Destroyed Receiving Data Socket(s)"; LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
return OK;
} }
int DetectorImpl::createReceivingDataSockets() { void DetectorImpl::createReceivingDataSockets() {
if (client_downstream) { if (client_downstream) {
return OK; return;
} }
LOG(logINFO) << "Going to create data sockets"; LOG(logINFO) << "Going to create data sockets";
@ -554,24 +558,22 @@ int DetectorImpl::createReceivingDataSockets() {
int hwm = shm()->zmqHwm; int hwm = shm()->zmqHwm;
if (hwm >= 0) { if (hwm >= 0) {
zmqSocket[iSocket]->SetReceiveHighWaterMark(hwm); zmqSocket[iSocket]->SetReceiveHighWaterMark(hwm);
if (zmqSocket[iSocket]->GetReceiveHighWaterMark() != hwm) { // need not reconnect. cannot be connected (detector idle)
throw ZmqSocketError("Could not set zmq rcv hwm to " +
std::to_string(hwm));
}
} }
LOG(logINFO) << "Zmq Client[" << iSocket << "] at " LOG(logINFO) << "Zmq Client[" << iSocket << "] at "
<< zmqSocket.back()->GetZmqServerAddress() << "[hwm: " << zmqSocket.back()->GetZmqServerAddress() << "[hwm: "
<< zmqSocket.back()->GetReceiveHighWaterMark() << "]"; << zmqSocket.back()->GetReceiveHighWaterMark() << "]";
} catch (...) { } catch (std::exception &e) {
LOG(logERROR) << "Could not create Zmq socket on port " << portnum;
destroyReceivingDataSockets(); destroyReceivingDataSockets();
return FAIL; std::ostringstream oss;
oss << "Could not create zmq sub socket on port " << portnum;
oss << " [" << e.what() << ']';
throw RuntimeError(oss.str());
} }
} }
client_downstream = true; client_downstream = true;
LOG(logINFO) << "Receiving Data Socket(s) created"; LOG(logINFO) << "Receiving Data Socket(s) created";
return OK;
} }
void DetectorImpl::readFrameFromReceiver() { void DetectorImpl::readFrameFromReceiver() {
@ -1111,9 +1113,7 @@ void DetectorImpl::setDataStreamingToClient(bool enable) {
destroyReceivingDataSockets(); destroyReceivingDataSockets();
// create data threads // create data threads
} else { } else {
if (createReceivingDataSockets() == FAIL) { createReceivingDataSockets();
throw RuntimeError("Could not create data threads in client.");
}
} }
} }
@ -1146,11 +1146,7 @@ void DetectorImpl::setClientStreamingHwm(const int limit) {
if (limit >= 0) { if (limit >= 0) {
for (auto &it : zmqSocket) { for (auto &it : zmqSocket) {
it->SetReceiveHighWaterMark(limit); it->SetReceiveHighWaterMark(limit);
if (it->GetReceiveHighWaterMark() != limit) { // need not reconnect. cannot be connected (detector idle)
shm()->zmqHwm = -1;
throw ZmqSocketError("Could not set zmq rcv hwm to " +
std::to_string(limit));
}
} }
LOG(logINFO) << "Setting Client Zmq socket rcv hwm to " << limit; LOG(logINFO) << "Setting Client Zmq socket rcv hwm to " << limit;
} }
@ -1774,6 +1770,10 @@ void DetectorImpl::setBadChannels(const std::string &fname, Positions pos) {
if (list.empty()) { if (list.empty()) {
throw RuntimeError("Bad channel file is empty."); throw RuntimeError("Bad channel file is empty.");
} }
setBadChannels(list, pos);
}
void DetectorImpl::setBadChannels(const std::vector<int> list, Positions pos) {
// update to multi values if multi modules // update to multi values if multi modules
if (isAllPositions(pos)) { if (isAllPositions(pos)) {
@ -1790,20 +1790,24 @@ void DetectorImpl::setBadChannels(const std::string &fname, Positions pos) {
" out of bounds."); " out of bounds.");
} }
int ch = badchannel % nchan; int ch = badchannel % nchan;
int imod = badchannel / nchan; size_t imod = badchannel / nchan;
if (imod >= (int)modules.size()) { if (imod >= modules.size()) {
throw RuntimeError("Invalid bad channel list. " + throw RuntimeError("Invalid bad channel list. " +
std::to_string(badchannel) + std::to_string(badchannel) +
" out of bounds."); " out of bounds.");
} }
if (badchannels.size() != imod + 1) {
if ((int)badchannels.size() != imod + 1) {
badchannels.push_back(std::vector<int>{}); badchannels.push_back(std::vector<int>{});
} }
badchannels[imod].push_back(ch); badchannels[imod].push_back(ch);
} }
for (int imod = 0; imod != (int)modules.size(); ++imod) { for (size_t imod = 0; imod != modules.size(); ++imod) {
Parallel(&Module::setBadChannels, {imod}, badchannels[imod]); // add empty vector if no bad channels in this module
if (badchannels.size() != imod + 1) {
badchannels.push_back(std::vector<int>{});
}
Parallel(&Module::setBadChannels, {static_cast<int>(imod)},
badchannels[imod]);
} }
} else if (pos.size() != 1) { } else if (pos.size() != 1) {

View File

@ -306,6 +306,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
void getBadChannels(const std::string &fname, Positions pos) const; void getBadChannels(const std::string &fname, Positions pos) const;
void setBadChannels(const std::string &fname, Positions pos); void setBadChannels(const std::string &fname, Positions pos);
void setBadChannels(const std::vector<int> list, Positions pos);
std::vector<std::string> getCtbDacNames() const; std::vector<std::string> getCtbDacNames() const;
std::string getCtbDacName(defs::dacIndex i) const; std::string getCtbDacName(defs::dacIndex i) const;
@ -348,8 +349,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
void updateDetectorSize(); void updateDetectorSize();
int destroyReceivingDataSockets(); void destroyReceivingDataSockets();
int createReceivingDataSockets(); void createReceivingDataSockets();
/** /**
* Reads frames from receiver through a constant socket * Reads frames from receiver through a constant socket

View File

@ -76,7 +76,7 @@ void Module::setHostname(const std::string &hostname,
initialDetectorServerChecks(); initialDetectorServerChecks();
checkDetectorVersionCompatibility(); checkDetectorVersionCompatibility();
LOG(logINFO) << "Module Version Compatibility - Success"; LOG(logINFO) << "Module Version Compatibility - Success";
} catch (const DetectorError &e) { } catch (const RuntimeError &e) {
if (!initialChecks) { if (!initialChecks) {
LOG(logWARNING) << "Bypassing Initial Checks at your own risk!"; LOG(logWARNING) << "Bypassing Initial Checks at your own risk!";
} else { } else {

View File

@ -9,7 +9,15 @@
namespace sls { namespace sls {
Pattern::Pattern() = default; Pattern::Pattern() {
// initialize pattern addresses
for (int i = 0; i != MAX_PATTERN_LEVELS; ++i) {
pat->startloop[i] = MAX_PATTERN_LENGTH - 1;
pat->stoploop[i] = MAX_PATTERN_LENGTH - 1;
pat->wait[i] = MAX_PATTERN_LENGTH - 1;
}
}
Pattern::~Pattern() { delete pat; } Pattern::~Pattern() { delete pat; }
Pattern::Pattern(const Pattern &other) { Pattern::Pattern(const Pattern &other) {

View File

@ -33,7 +33,7 @@ namespace sls {
template <typename T> class SharedMemory { template <typename T> class SharedMemory {
static constexpr int NAME_MAX_LENGTH = 255; static constexpr int NAME_MAX_LENGTH = 255;
std::string name; std::string name;
T *shared_struct{}; T *shared_struct{nullptr};
public: public:
// moduleid of -1 creates a detector only shared memory // moduleid of -1 creates a detector only shared memory
@ -64,8 +64,18 @@ template <typename T> class SharedMemory {
unmapSharedMemory(); unmapSharedMemory();
} }
T *operator()() { return shared_struct; } T *operator()() {
const T *operator()() const { return shared_struct; } if (shared_struct)
return shared_struct;
throw SharedMemoryError(getNoShmAccessMessage());
}
const T *operator()() const {
if (shared_struct)
return shared_struct;
throw SharedMemoryError(getNoShmAccessMessage());
}
std::string getName() const { return name; } std::string getName() const { return name; }
bool exists() { bool exists() {
@ -204,6 +214,11 @@ template <typename T> class SharedMemory {
throw SharedMemoryError(msg); throw SharedMemoryError(msg);
} }
} }
const char *getNoShmAccessMessage() const {
return ("No shared memory to access. Create it first with "
"hostname or config command.");
};
}; };
} // namespace sls } // namespace sls

View File

@ -186,12 +186,14 @@ TEST_CASE("patloop", "[.cmd]") {
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patloop", {sLoop, "0x20", "0x5c"}, -1, PUT, oss); proxy.Call("patloop", {sLoop, "0x20", "0x5c"}, -1, PUT, oss);
REQUIRE(oss.str() == "patloop [0x0020, 0x005c]\n"); REQUIRE(oss.str() ==
"patloop " + sLoop + " [0x0020, 0x005c]\n");
} }
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patloop", {sLoop}, -1, GET, oss); proxy.Call("patloop", {sLoop}, -1, GET, oss);
REQUIRE(oss.str() == "patloop [0x0020, 0x005c]\n"); REQUIRE(oss.str() ==
"patloop " + sLoop + " [0x0020, 0x005c]\n");
} }
for (int iDet = 0; iDet != det.size(); ++iDet) { for (int iDet = 0; iDet != det.size(); ++iDet) {
det.setPatternLoopAddresses(iLoop, prev_val[iDet][0], det.setPatternLoopAddresses(iLoop, prev_val[iDet][0],
@ -233,12 +235,12 @@ TEST_CASE("patnloop", "[.cmd]") {
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patnloop", {sLoop, "5"}, -1, PUT, oss); proxy.Call("patnloop", {sLoop, "5"}, -1, PUT, oss);
REQUIRE(oss.str() == "patnloop 5\n"); REQUIRE(oss.str() == "patnloop " + sLoop + " 5\n");
} }
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patnloop", {sLoop}, -1, GET, oss); proxy.Call("patnloop", {sLoop}, -1, GET, oss);
REQUIRE(oss.str() == "patnloop 5\n"); REQUIRE(oss.str() == "patnloop " + sLoop + " 5\n");
} }
for (int iDet = 0; iDet != det.size(); ++iDet) { for (int iDet = 0; iDet != det.size(); ++iDet) {
det.setPatternLoopCycles(iLoop, prev_val[iDet], {iDet}); det.setPatternLoopCycles(iLoop, prev_val[iDet], {iDet});
@ -279,12 +281,12 @@ TEST_CASE("patwait", "[.cmd]") {
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patwait", {sLoop, "0x5c"}, -1, PUT, oss); proxy.Call("patwait", {sLoop, "0x5c"}, -1, PUT, oss);
REQUIRE(oss.str() == "patwait 0x005c\n"); REQUIRE(oss.str() == "patwait " + sLoop + " 0x005c\n");
} }
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patwait", {sLoop}, -1, GET, oss); proxy.Call("patwait", {sLoop}, -1, GET, oss);
REQUIRE(oss.str() == "patwait 0x005c\n"); REQUIRE(oss.str() == "patwait " + sLoop + " 0x005c\n");
} }
for (int iDet = 0; iDet != det.size(); ++iDet) { for (int iDet = 0; iDet != det.size(); ++iDet) {
det.setPatternWaitAddr(iLoop, prev_val[iDet], {iDet}); det.setPatternWaitAddr(iLoop, prev_val[iDet], {iDet});
@ -325,12 +327,12 @@ TEST_CASE("patwaittime", "[.cmd]") {
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patwaittime", {sLoop, "8589936640"}, -1, PUT, oss); proxy.Call("patwaittime", {sLoop, "8589936640"}, -1, PUT, oss);
REQUIRE(oss.str() == "patwaittime 8589936640\n"); REQUIRE(oss.str() == "patwaittime " + sLoop + " 8589936640\n");
} }
{ {
std::ostringstream oss; std::ostringstream oss;
proxy.Call("patwaittime", {sLoop}, -1, GET, oss); proxy.Call("patwaittime", {sLoop}, -1, GET, oss);
REQUIRE(oss.str() == "patwaittime 8589936640\n"); REQUIRE(oss.str() == "patwaittime " + sLoop + " 8589936640\n");
} }
for (int iDet = 0; iDet != det.size(); ++iDet) { for (int iDet = 0; iDet != det.size(); ++iDet) {
det.setPatternWaitTime(iLoop, prev_val[iDet], {iDet}); det.setPatternWaitTime(iLoop, prev_val[iDet], {iDet});

View File

@ -524,8 +524,10 @@ TEST_CASE("gappixels", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
bool quad = det.getQuad().squash(false);
bool fullModule = (det.getModuleGeometry().y % 2 == 0);
if (det_type == defs::JUNGFRAU || det_type == defs::EIGER) { if (det_type == defs::JUNGFRAU || (det_type == defs::EIGER && (quad || fullModule))) {
auto prev_val = det.getGapPixelsinCallback(); auto prev_val = det.getGapPixelsinCallback();
{ {
std::ostringstream oss; std::ostringstream oss;
@ -644,6 +646,8 @@ TEST_CASE("badchannels", "[.cmd]") {
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2 || det_type == defs::MYTHEN3) { if (det_type == defs::GOTTHARD2 || det_type == defs::MYTHEN3) {
auto prev = det.getBadChannels();
REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET));
std::string fname_put = std::string fname_put =
@ -656,6 +660,51 @@ TEST_CASE("badchannels", "[.cmd]") {
std::vector<int> expected = {0, 12, 15, 40, 41, 42, 43, 44, 1279}; std::vector<int> expected = {0, 12, 15, 40, 41, 42, 43, 44, 1279};
REQUIRE(list == expected); REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"none"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
REQUIRE(list.empty());
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_put}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {"0"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
REQUIRE(list.empty());
REQUIRE_NOTHROW(proxy.Call("badchannels", {"12"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {12};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call(
"badchannels", {"0", "12,", "15", "43", "40:45", "1279"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {0, 12, 15, 40, 41, 42, 43, 44, 1279};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"40:45"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {40, 41, 42, 43, 44};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"5,6,7"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {5, 6, 7};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"1:5,6,7"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {1, 2, 3, 4, 6, 7};
REQUIRE(list == expected);
det.setBadChannels(prev);
} else { } else {
REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET));
} }
@ -1222,7 +1271,7 @@ TEST_CASE("clkphase", "[.cmd]") {
} }
std::string s_deg_val = "15"; std::string s_deg_val = "15";
if (det_type == defs::MYTHEN3) { if (det_type == defs::MYTHEN3) {
s_deg_val = "15"; s_deg_val = "14";
} else if (det_type == defs::GOTTHARD2) { } else if (det_type == defs::GOTTHARD2) {
s_deg_val = "23"; s_deg_val = "23";
} }

View File

@ -101,7 +101,7 @@ TEST_CASE("Move SharedMemory", "[detector]") {
shm2 = std::move(shm); // shm is now a moved from object! shm2 = std::move(shm); // shm is now a moved from object!
CHECK(shm2()->x == 9); CHECK(shm2()->x == 9);
CHECK(shm() == nullptr); REQUIRE_THROWS(shm()); // trying to access should throw instead of returning a nullptr
CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") + CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") +
std::to_string(shm_id)); std::to_string(shm_id));
shm2.removeSharedMemory(); shm2.removeSharedMemory();

View File

@ -4,6 +4,8 @@
#include "Arping.h" #include "Arping.h"
#include <chrono> #include <chrono>
#include <signal.h>
#include <thread>
#include <unistd.h> #include <unistd.h>
namespace sls { namespace sls {
@ -18,7 +20,7 @@ Arping::Arping() {}
Arping::~Arping() { Arping::~Arping() {
if (IsRunning()) { if (IsRunning()) {
StopThread(); StopProcess();
} }
} }
@ -33,59 +35,66 @@ void Arping::SetInterfacesAndIps(const int index, const std::string &interface,
// create commands to arping // create commands to arping
std::ostringstream os; std::ostringstream os;
os << "arping -c 1 -U -I " << interface << " " << ip; os << "arping -c 1 -U -I " << interface << " " << ip;
// to read error messages
os << " 2>&1";
std::string cmd = os.str(); std::string cmd = os.str();
commands[index] = cmd; commands[index] = cmd;
} }
pid_t Arping::GetThreadId() const { return threadId; } pid_t Arping::GetProcessId() const { return childPid; }
bool Arping::IsRunning() const { return runningFlag; } bool Arping::IsRunning() const { return runningFlag; }
void Arping::StartThread() { void Arping::StartProcess() {
TestCommands(); TestCommands();
try {
t = std::thread(&Arping::ThreadExecution, this); // to prevent zombies from child processes being killed
} catch (...) { signal(SIGCHLD, SIG_IGN);
throw RuntimeError("Could not start arping thread");
// Needs to be a fork and udp socket deleted after Listening threads
// done running to prevent udp socket cannot bind because of popen
// that forks
childPid = fork();
// child process
if (childPid == 0) {
LOG(logINFOBLUE) << "Created [ Arping Process, Tid: " << gettid()
<< " ]";
ProcessExecution();
}
// parent process
else if (childPid > 0) {
runningFlag = true;
}
// error
else {
throw RuntimeError("Could not start arping Process");
} }
runningFlag = true;
} }
void Arping::StopThread() { void Arping::StopProcess() {
LOG(logINFOBLUE) << "Exiting [ Arping Process ]";
if (kill(childPid, SIGTERM)) {
throw RuntimeError("Could not kill the arping Process");
}
runningFlag = false; runningFlag = false;
t.join();
} }
void Arping::ThreadExecution() { void Arping::ProcessExecution() {
threadId = gettid(); while (true) {
LOG(logINFOBLUE) << "Created [ Arping Thread, Tid: " << threadId << " ]";
while (runningFlag) {
std::string error = ExecuteCommands(); std::string error = ExecuteCommands();
// just print (was already tested at thread start) // just print (was already tested at Process start)
if (!error.empty()) { if (!error.empty()) {
LOG(logERROR) << error; LOG(logERROR) << error;
} }
const auto interval = std::chrono::seconds(60);
// wait for 60s as long as thread not killed std::this_thread::sleep_for(interval);
int nsecs = 0;
while (runningFlag && nsecs != 60) {
std::this_thread::sleep_for(std::chrono::seconds(1));
++nsecs;
}
} }
LOG(logINFOBLUE) << "Exiting [ Arping Thread, Tid: " << threadId << " ]";
threadId = 0;
} }
void Arping::TestCommands() { void Arping::TestCommands() {
// atleast one interface must be set up // atleast one interface must be set up
if (commands[0].empty()) { if (commands[0].empty()) {
throw RuntimeError( throw RuntimeError(
"Could not arping. Interface not set up in apring thread"); "Could not arping. Interface not set up in arping Process");
} }
// test if arping commands throw an error // test if arping commands throw an error
std::string error = ExecuteCommands(); std::string error = ExecuteCommands();
@ -101,7 +110,7 @@ std::string Arping::ExecuteCommands() {
if (cmd.empty()) if (cmd.empty())
continue; continue;
LOG(logDEBUG) << "Executing Arping Command: " << cmd; LOG(logDEBUG1) << "Executing Arping Command: " << cmd;
// execute command // execute command
FILE *sysFile = popen(cmd.c_str(), "r"); FILE *sysFile = popen(cmd.c_str(), "r");

View File

@ -2,15 +2,15 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once #pragma once
/** /**
*@short creates/destroys an ARPing thread to arping the interfaces slsReceiver *@short creates/destroys an ARPing child process to arping the interfaces
is listening to. slsReceiver is listening to.
*/ */
#include "receiver_defs.h" #include "receiver_defs.h"
#include "sls/logger.h" #include "sls/logger.h"
#include <atomic> #include <atomic>
#include <thread> #include <unistd.h>
namespace sls { namespace sls {
@ -22,21 +22,20 @@ class Arping {
void SetInterfacesAndIps(const int index, const std::string &interface, void SetInterfacesAndIps(const int index, const std::string &interface,
const std::string &ip); const std::string &ip);
pid_t GetThreadId() const; pid_t GetProcessId() const;
bool IsRunning() const; bool IsRunning() const;
void StartThread(); void StartProcess();
void StopThread(); void StopProcess();
private: private:
void TestCommands(); void TestCommands();
std::string ExecuteCommands(); std::string ExecuteCommands();
void ThreadExecution(); void ProcessExecution();
std::vector<std::string> commands = std::vector<std::string> commands =
std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS); std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS);
std::atomic<bool> runningFlag{false}; std::atomic<bool> runningFlag{false};
std::thread t; std::atomic<pid_t> childPid{0};
std::atomic<pid_t> threadId{0};
}; };
} // namespace sls } // namespace sls

View File

@ -320,165 +320,122 @@ int ClientInterface::setup_receiver(Interface &socket) {
auto arg = socket.Receive<rxParameters>(); auto arg = socket.Receive<rxParameters>();
LOG(logDEBUG) << ToString(arg); LOG(logDEBUG) << ToString(arg);
// if object exists, verify unlocked and idle, else only verify lock
// (connecting first time)
if (receiver != nullptr) {
verifyIdle(socket);
}
// basic setup
setDetectorType(arg.detType);
impl()->setDetectorSize(arg.numberOfModule);
impl()->setModulePositionId(arg.moduleIndex);
impl()->setDetectorHostname(arg.hostname);
// udp setup
// update retvals only if detmac is not the same as in detector
MacAddr retvals[2]; MacAddr retvals[2];
if (arg.udp_dstip != 0) { try {
MacAddr r = setUdpIp(IpAddr(arg.udp_dstip)); // if object exists, verify unlocked and idle, else only verify lock
MacAddr detMac{arg.udp_dstmac}; // (connecting first time)
if (detMac != r) { if (receiver != nullptr) {
retvals[0] = r; verifyIdle(socket);
} }
}
if (arg.udp_dstip2 != 0) {
MacAddr r = setUdpIp2(IpAddr(arg.udp_dstip2));
MacAddr detMac{arg.udp_dstmac2};
if (detMac != r) {
retvals[1] = r;
}
}
impl()->setUDPPortNumber(arg.udp_dstport);
impl()->setUDPPortNumber2(arg.udp_dstport2);
if (detType == JUNGFRAU || detType == GOTTHARD2) {
try {
impl()->setNumberofUDPInterfaces(arg.udpInterfaces);
} catch (const RuntimeError &e) {
throw RuntimeError("Failed to set number of interfaces to " +
std::to_string(arg.udpInterfaces));
}
}
impl()->setUDPSocketBufferSize(0);
// acquisition parameters // basic setup
impl()->setNumberOfFrames(arg.frames); setDetectorType(arg.detType);
impl()->setNumberOfTriggers(arg.triggers); impl()->setDetectorSize(arg.numberOfModule);
if (detType == GOTTHARD2) { impl()->setModulePositionId(arg.moduleIndex);
impl()->setNumberOfBursts(arg.bursts); impl()->setDetectorHostname(arg.hostname);
}
if (detType == JUNGFRAU) { // udp setup
impl()->setNumberOfAdditionalStorageCells(arg.additionalStorageCells); // update retvals only if detmac is not the same as in detector
} if (arg.udp_dstip != 0) {
if (detType == MOENCH || detType == CHIPTESTBOARD) { MacAddr r = setUdpIp(IpAddr(arg.udp_dstip));
try { MacAddr detMac{arg.udp_dstmac};
if (detMac != r) {
retvals[0] = r;
}
}
if (arg.udp_dstip2 != 0) {
MacAddr r = setUdpIp2(IpAddr(arg.udp_dstip2));
MacAddr detMac{arg.udp_dstmac2};
if (detMac != r) {
retvals[1] = r;
}
}
impl()->setUDPPortNumber(arg.udp_dstport);
impl()->setUDPPortNumber2(arg.udp_dstport2);
if (detType == JUNGFRAU || detType == GOTTHARD2) {
impl()->setNumberofUDPInterfaces(arg.udpInterfaces);
}
impl()->setUDPSocketBufferSize(0);
// acquisition parameters
impl()->setNumberOfFrames(arg.frames);
impl()->setNumberOfTriggers(arg.triggers);
if (detType == GOTTHARD2) {
impl()->setNumberOfBursts(arg.bursts);
}
if (detType == JUNGFRAU) {
impl()->setNumberOfAdditionalStorageCells(
arg.additionalStorageCells);
}
if (detType == MOENCH || detType == CHIPTESTBOARD) {
impl()->setNumberofAnalogSamples(arg.analogSamples); impl()->setNumberofAnalogSamples(arg.analogSamples);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set num analog samples to " +
std::to_string(arg.analogSamples) +
" due to fifo structure memory allocation.");
} }
} if (detType == CHIPTESTBOARD) {
if (detType == CHIPTESTBOARD) {
try {
impl()->setNumberofDigitalSamples(arg.digitalSamples); impl()->setNumberofDigitalSamples(arg.digitalSamples);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set num digital samples to " +
std::to_string(arg.analogSamples) +
" due to fifo structure memory allocation.");
} }
} if (detType != MYTHEN3) {
if (detType != MYTHEN3) { impl()->setAcquisitionTime(std::chrono::nanoseconds(arg.expTimeNs));
impl()->setAcquisitionTime(std::chrono::nanoseconds(arg.expTimeNs)); }
} impl()->setAcquisitionPeriod(std::chrono::nanoseconds(arg.periodNs));
impl()->setAcquisitionPeriod(std::chrono::nanoseconds(arg.periodNs)); if (detType == EIGER) {
if (detType == EIGER) { impl()->setSubExpTime(std::chrono::nanoseconds(arg.subExpTimeNs));
impl()->setSubExpTime(std::chrono::nanoseconds(arg.subExpTimeNs)); impl()->setSubPeriod(std::chrono::nanoseconds(arg.subExpTimeNs) +
impl()->setSubPeriod(std::chrono::nanoseconds(arg.subExpTimeNs) + std::chrono::nanoseconds(arg.subDeadTimeNs));
std::chrono::nanoseconds(arg.subDeadTimeNs)); impl()->setActivate(static_cast<bool>(arg.activate));
impl()->setActivate(static_cast<bool>(arg.activate)); impl()->setDetectorDataStream(LEFT, arg.dataStreamLeft);
impl()->setDetectorDataStream(LEFT, arg.dataStreamLeft); impl()->setDetectorDataStream(RIGHT, arg.dataStreamRight);
impl()->setDetectorDataStream(RIGHT, arg.dataStreamRight);
try {
impl()->setQuad(arg.quad == 0 ? false : true); impl()->setQuad(arg.quad == 0 ? false : true);
} catch (const RuntimeError &e) { impl()->setThresholdEnergy(arg.thresholdEnergyeV[0]);
throw RuntimeError("Could not set quad to " +
std::to_string(arg.quad) +
" due to fifo strucutre memory allocation");
} }
impl()->setThresholdEnergy(arg.thresholdEnergyeV[0]); if (detType == EIGER || detType == JUNGFRAU) {
} impl()->setReadNRows(arg.readNRows);
if (detType == EIGER || detType == JUNGFRAU) {
impl()->setReadNRows(arg.readNRows);
}
if (detType == MYTHEN3) {
std::array<int, 3> val;
for (int i = 0; i < 3; ++i) {
val[i] = arg.thresholdEnergyeV[i];
} }
impl()->setThresholdEnergy(val); if (detType == MYTHEN3) {
} std::array<int, 3> val;
if (detType == EIGER || detType == MYTHEN3) { for (int i = 0; i < 3; ++i) {
try { val[i] = arg.thresholdEnergyeV[i];
}
impl()->setThresholdEnergy(val);
}
if (detType == EIGER || detType == MYTHEN3) {
impl()->setDynamicRange(arg.dynamicRange); impl()->setDynamicRange(arg.dynamicRange);
} catch (const RuntimeError &e) {
throw RuntimeError(
"Could not set dynamic range. Could not allocate "
"memory for fifo or could not start listening/writing threads");
} }
} impl()->setTimingMode(arg.timMode);
impl()->setTimingMode(arg.timMode); if (detType == EIGER || detType == MOENCH || detType == CHIPTESTBOARD ||
if (detType == EIGER || detType == MOENCH || detType == CHIPTESTBOARD || detType == MYTHEN3) {
detType == MYTHEN3) {
try {
impl()->setTenGigaEnable(arg.tenGiga); impl()->setTenGigaEnable(arg.tenGiga);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set 10GbE.");
} }
} if (detType == CHIPTESTBOARD) {
if (detType == CHIPTESTBOARD) {
try {
impl()->setReadoutMode(arg.roMode); impl()->setReadoutMode(arg.roMode);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set read out mode "
"due to fifo memory allocation.");
} }
} if (detType == CHIPTESTBOARD || detType == MOENCH) {
if (detType == CHIPTESTBOARD || detType == MOENCH) {
try {
impl()->setADCEnableMask(arg.adcMask); impl()->setADCEnableMask(arg.adcMask);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set adc enable mask "
"due to fifo memory allcoation");
}
try {
impl()->setTenGigaADCEnableMask(arg.adc10gMask); impl()->setTenGigaADCEnableMask(arg.adc10gMask);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set 10Gb adc enable mask "
"due to fifo memory allcoation");
} }
} if (detType == GOTTHARD) {
if (detType == GOTTHARD) {
try {
impl()->setDetectorROI(arg.roi); impl()->setDetectorROI(arg.roi);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set ROI");
} }
if (detType == MYTHEN3) {
impl()->setCounterMask(arg.countermask);
impl()->setAcquisitionTime1(
std::chrono::nanoseconds(arg.expTime1Ns));
impl()->setAcquisitionTime2(
std::chrono::nanoseconds(arg.expTime2Ns));
impl()->setAcquisitionTime3(
std::chrono::nanoseconds(arg.expTime3Ns));
impl()->setGateDelay1(std::chrono::nanoseconds(arg.gateDelay1Ns));
impl()->setGateDelay2(std::chrono::nanoseconds(arg.gateDelay2Ns));
impl()->setGateDelay3(std::chrono::nanoseconds(arg.gateDelay3Ns));
impl()->setNumberOfGates(arg.gates);
}
if (detType == GOTTHARD2) {
impl()->setBurstMode(arg.burstType);
}
impl()->setScan(arg.scanParams);
} catch (std::exception &e) {
throw RuntimeError("Could not setup receiver [" +
std::string(e.what()) + ']');
} }
if (detType == MYTHEN3) {
impl()->setCounterMask(arg.countermask);
impl()->setAcquisitionTime1(std::chrono::nanoseconds(arg.expTime1Ns));
impl()->setAcquisitionTime2(std::chrono::nanoseconds(arg.expTime2Ns));
impl()->setAcquisitionTime3(std::chrono::nanoseconds(arg.expTime3Ns));
impl()->setGateDelay1(std::chrono::nanoseconds(arg.gateDelay1Ns));
impl()->setGateDelay2(std::chrono::nanoseconds(arg.gateDelay2Ns));
impl()->setGateDelay3(std::chrono::nanoseconds(arg.gateDelay3Ns));
impl()->setNumberOfGates(arg.gates);
}
if (detType == GOTTHARD2) {
impl()->setBurstMode(arg.burstType);
}
impl()->setScan(arg.scanParams);
return socket.sendResult(retvals); return socket.sendResult(retvals);
} }
@ -502,13 +459,10 @@ void ClientInterface::setDetectorType(detectorType arg) {
detType = GENERIC; detType = GENERIC;
receiver = make_unique<Implementation>(arg); receiver = make_unique<Implementation>(arg);
detType = arg; detType = arg;
} catch (std::exception &e) { } catch (const std::exception &e) {
std::ostringstream os; throw RuntimeError("Could not set detector type in the receiver. [" +
os << "Could not set detector type in the receiver. "; std::string(e.what()) + ']');
os << e.what();
throw RuntimeError(os.str());
} }
// callbacks after (in setdetectortype, the object is reinitialized) // callbacks after (in setdetectortype, the object is reinitialized)
if (startAcquisitionCallBack != nullptr) if (startAcquisitionCallBack != nullptr)
impl()->registerCallBackStartAcquisition(startAcquisitionCallBack, impl()->registerCallBackStartAcquisition(startAcquisitionCallBack,
@ -536,8 +490,8 @@ int ClientInterface::set_detector_roi(Interface &socket) {
verifyIdle(socket); verifyIdle(socket);
try { try {
impl()->setDetectorROI(arg); impl()->setDetectorROI(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set ROI"); throw RuntimeError("Could not set ROI [" + std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -616,10 +570,10 @@ int ClientInterface::set_num_analog_samples(Interface &socket) {
} }
try { try {
impl()->setNumberofAnalogSamples(value); impl()->setNumberofAnalogSamples(value);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set num analog samples to " + throw RuntimeError("Could not set number of analog samples to " +
std::to_string(value) + std::to_string(value) + " [" +
" due to fifo structure memory allocation."); std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -632,11 +586,12 @@ int ClientInterface::set_num_digital_samples(Interface &socket) {
} }
try { try {
impl()->setNumberofDigitalSamples(value); impl()->setNumberofDigitalSamples(value);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set num digital samples to " + throw RuntimeError("Could not set number of digital samples to " +
std::to_string(value) + std::to_string(value) + " [" +
" due to fifo structure memory allocation."); std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -743,9 +698,9 @@ int ClientInterface::set_dynamic_range(Interface &socket) {
} else { } else {
try { try {
impl()->setDynamicRange(dr); impl()->setDynamicRange(dr);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not allocate memory for fifo or " throw RuntimeError("Could not set dynamic range [" +
"could not start listening/writing threads"); std::string(e.what()) + ']');
} }
} }
} }
@ -781,7 +736,12 @@ int ClientInterface::get_status(Interface &socket) {
int ClientInterface::start_receiver(Interface &socket) { int ClientInterface::start_receiver(Interface &socket) {
if (impl()->getStatus() == IDLE) { if (impl()->getStatus() == IDLE) {
LOG(logDEBUG1) << "Starting Receiver"; LOG(logDEBUG1) << "Starting Receiver";
impl()->startReceiver(); try {
impl()->startReceiver();
} catch (const std::exception &e) {
throw RuntimeError("Could not start reciever [" +
std::string(e.what()) + ']');
}
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -791,12 +751,16 @@ int ClientInterface::stop_receiver(Interface &socket) {
if (impl()->getStatus() == RUNNING) { if (impl()->getStatus() == RUNNING) {
LOG(logDEBUG1) << "Stopping Receiver"; LOG(logDEBUG1) << "Stopping Receiver";
impl()->setStoppedFlag(static_cast<bool>(arg)); impl()->setStoppedFlag(static_cast<bool>(arg));
impl()->stopReceiver(); try {
impl()->stopReceiver();
} catch (const std::exception &e) {
throw RuntimeError("Could not stop receiver [" +
std::string(e.what()) + ']');
}
} }
auto s = impl()->getStatus(); auto s = impl()->getStatus();
if (s != IDLE) if (s != IDLE)
throw RuntimeError("Could not stop receiver. It as it is: " + throw RuntimeError("Could not stop receiver. Status: " + ToString(s));
ToString(s));
return socket.Send(OK); return socket.Send(OK);
} }
@ -811,7 +775,12 @@ int ClientInterface::set_file_dir(Interface &socket) {
throw RuntimeError("Receiver path needs to be absolute path"); throw RuntimeError("Receiver path needs to be absolute path");
LOG(logDEBUG1) << "Setting file path: " << fpath; LOG(logDEBUG1) << "Setting file path: " << fpath;
impl()->setFilePath(fpath); try {
impl()->setFilePath(fpath);
} catch (const std::exception &e) {
throw RuntimeError("Could not set file path [" + std::string(e.what()) +
']');
}
return socket.Send(OK); return socket.Send(OK);
} }
@ -893,7 +862,12 @@ int ClientInterface::set_file_write(Interface &socket) {
} }
verifyIdle(socket); verifyIdle(socket);
LOG(logDEBUG1) << "Setting File write enable:" << enable; LOG(logDEBUG1) << "Setting File write enable:" << enable;
impl()->setFileWriteEnable(enable); try {
impl()->setFileWriteEnable(enable);
} catch (const std::exception &e) {
throw RuntimeError("Could not enable/disable file write [" +
std::string(e.what()) + ']');
}
return socket.Send(OK); return socket.Send(OK);
} }
@ -948,8 +922,9 @@ int ClientInterface::enable_tengiga(Interface &socket) {
LOG(logDEBUG1) << "Setting 10GbE:" << val; LOG(logDEBUG1) << "Setting 10GbE:" << val;
try { try {
impl()->setTenGigaEnable(val); impl()->setTenGigaEnable(val);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set 10GbE."); throw RuntimeError("Could not set 10GbE. [" +
std::string(e.what()) + ']');
} }
} }
int retval = impl()->getTenGigaEnable(); int retval = impl()->getTenGigaEnable();
@ -965,9 +940,9 @@ int ClientInterface::set_fifo_depth(Interface &socket) {
LOG(logDEBUG1) << "Setting fifo depth:" << value; LOG(logDEBUG1) << "Setting fifo depth:" << value;
try { try {
impl()->setFifoDepth(value); impl()->setFifoDepth(value);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set fifo depth due to fifo structure " throw RuntimeError("Could not set fifo depth [" +
"memory allocation."); std::string(e.what()) + ']');
} }
} }
int retval = impl()->getFifoDepth(); int retval = impl()->getFifoDepth();
@ -1002,10 +977,12 @@ int ClientInterface::set_streaming(Interface &socket) {
LOG(logDEBUG1) << "Setting data stream enable:" << index; LOG(logDEBUG1) << "Setting data stream enable:" << index;
try { try {
impl()->setDataStreamEnable(index); impl()->setDataStreamEnable(index);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set data stream enable to " + throw RuntimeError("Could not set data stream enable to " +
std::to_string(index)); std::to_string(index) + " [" +
std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -1064,7 +1041,12 @@ int ClientInterface::set_file_format(Interface &socket) {
} }
verifyIdle(socket); verifyIdle(socket);
LOG(logDEBUG1) << "Setting file format:" << f; LOG(logDEBUG1) << "Setting file format:" << f;
impl()->setFileFormat(f); try {
impl()->setFileFormat(f);
} catch (const std::exception &e) {
throw RuntimeError("Could not set file format to " + ToString(f) +
" [" + std::string(e.what()) + ']');
}
auto retval = impl()->getFileFormat(); auto retval = impl()->getFileFormat();
validate(f, retval, "set file format", DEC); validate(f, retval, "set file format", DEC);
@ -1185,7 +1167,13 @@ int ClientInterface::set_udp_socket_buffer_size(Interface &socket) {
"Receiver socket buffer size exceeded max (INT_MAX/2)"); "Receiver socket buffer size exceeded max (INT_MAX/2)");
} }
LOG(logDEBUG1) << "Setting UDP Socket Buffer size: " << size; LOG(logDEBUG1) << "Setting UDP Socket Buffer size: " << size;
impl()->setUDPSocketBufferSize(size); try {
impl()->setUDPSocketBufferSize(size);
} catch (const std::exception &e) {
throw RuntimeError("Could not set udp socket buffer size to " +
std::to_string(size) + " [" +
std::string(e.what()) + ']');
}
} }
int retval = impl()->getUDPSocketBufferSize(); int retval = impl()->getUDPSocketBufferSize();
if (size != 0) if (size != 0)
@ -1264,9 +1252,9 @@ int ClientInterface::set_readout_mode(Interface &socket) {
LOG(logDEBUG1) << "Setting readout mode: " << arg; LOG(logDEBUG1) << "Setting readout mode: " << arg;
try { try {
impl()->setReadoutMode(arg); impl()->setReadoutMode(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError( throw RuntimeError("Could not set read out mode [" +
"Could not set read out mode due to fifo memory allocation."); std::string(e.what()) + ']');
} }
} }
auto retval = impl()->getReadoutMode(); auto retval = impl()->getReadoutMode();
@ -1282,10 +1270,11 @@ int ClientInterface::set_adc_mask(Interface &socket) {
LOG(logDEBUG1) << "Setting 1Gb ADC enable mask: " << arg; LOG(logDEBUG1) << "Setting 1Gb ADC enable mask: " << arg;
try { try {
impl()->setADCEnableMask(arg); impl()->setADCEnableMask(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError( throw RuntimeError("Could not set adc enable mask [" +
"Could not set adc enable mask due to fifo memory allcoation"); std::string(e.what()) + ']');
} }
auto retval = impl()->getADCEnableMask(); auto retval = impl()->getADCEnableMask();
if (retval != arg) { if (retval != arg) {
std::ostringstream os; std::ostringstream os;
@ -1349,10 +1338,10 @@ int ClientInterface::set_quad_type(Interface &socket) {
LOG(logDEBUG1) << "Setting quad:" << quadEnable; LOG(logDEBUG1) << "Setting quad:" << quadEnable;
try { try {
impl()->setQuad(quadEnable == 0 ? false : true); impl()->setQuad(quadEnable == 0 ? false : true);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set quad to " + throw RuntimeError("Could not set quad to " +
std::to_string(quadEnable) + std::to_string(quadEnable) + " [" +
" due to fifo strucutre memory allocation"); std::string(e.what()) + ']');
} }
} }
int retval = impl()->getQuad() ? 1 : 0; int retval = impl()->getQuad() ? 1 : 0;
@ -1487,10 +1476,12 @@ int ClientInterface::set_num_interfaces(Interface &socket) {
LOG(logDEBUG1) << "Setting Number of UDP Interfaces:" << arg; LOG(logDEBUG1) << "Setting Number of UDP Interfaces:" << arg;
try { try {
impl()->setNumberofUDPInterfaces(arg); impl()->setNumberofUDPInterfaces(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Failed to set number of interfaces to " + throw RuntimeError("Could not set number of interfaces to " +
std::to_string(arg)); std::to_string(arg) + " [" + std::string(e.what()) +
']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -1500,10 +1491,11 @@ int ClientInterface::set_adc_mask_10g(Interface &socket) {
LOG(logDEBUG1) << "Setting 10Gb ADC enable mask: " << arg; LOG(logDEBUG1) << "Setting 10Gb ADC enable mask: " << arg;
try { try {
impl()->setTenGigaADCEnableMask(arg); impl()->setTenGigaADCEnableMask(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError( throw RuntimeError("Could not set 10Gb adc enable mask [" +
"Could not set 10Gb adc enable mask due to fifo memory allcoation"); std::string(e.what()) + ']');
} }
auto retval = impl()->getTenGigaADCEnableMask(); auto retval = impl()->getTenGigaADCEnableMask();
if (retval != arg) { if (retval != arg) {
std::ostringstream os; std::ostringstream os;
@ -1519,7 +1511,12 @@ int ClientInterface::set_counter_mask(Interface &socket) {
auto arg = socket.Receive<uint32_t>(); auto arg = socket.Receive<uint32_t>();
verifyIdle(socket); verifyIdle(socket);
LOG(logDEBUG1) << "Setting counters: " << arg; LOG(logDEBUG1) << "Setting counters: " << arg;
impl()->setCounterMask(arg); try {
impl()->setCounterMask(arg);
} catch (const std::exception &e) {
throw RuntimeError("Could not set counter mask [" +
std::string(e.what()) + ']');
}
return socket.Send(OK); return socket.Send(OK);
} }
@ -1715,7 +1712,12 @@ int ClientInterface::set_arping(Interface &socket) {
} }
verifyIdle(socket); verifyIdle(socket);
LOG(logDEBUG1) << "Starting/ Killing arping thread:" << value; LOG(logDEBUG1) << "Starting/ Killing arping thread:" << value;
impl()->setArping(value, udpips); try {
impl()->setArping(value, udpips);
} catch (const std::exception &e) {
throw RuntimeError("Could not start/kill arping thread [" +
std::string(e.what()) + ']');
}
return socket.Send(OK); return socket.Send(OK);
} }
@ -1733,9 +1735,11 @@ int ClientInterface::set_receiver_roi(Interface &socket) {
verifyIdle(socket); verifyIdle(socket);
try { try {
impl()->setReceiverROI(arg); impl()->setReceiverROI(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set ReceiverROI"); throw RuntimeError("Could not set Receiver ROI [" +
std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }
@ -1747,9 +1751,11 @@ int ClientInterface::set_receiver_roi_metadata(Interface &socket) {
verifyIdle(socket); verifyIdle(socket);
try { try {
impl()->setReceiverROIMetadata(arg); impl()->setReceiverROIMetadata(arg);
} catch (const RuntimeError &e) { } catch (const std::exception &e) {
throw RuntimeError("Could not set ReceiverROI metadata"); throw RuntimeError("Could not set ReceiverROI metadata [" +
std::string(e.what()) + ']');
} }
return socket.Send(OK); return socket.Send(OK);
} }

View File

@ -87,19 +87,18 @@ void DataStreamer::CreateZmqSockets(uint32_t port, const IpAddr ip, int hwm) {
std::string sip = ip.str(); std::string sip = ip.str();
try { try {
zmqSocket = new ZmqSocket(portnum, (ip != 0 ? sip.c_str() : nullptr)); zmqSocket = new ZmqSocket(portnum, (ip != 0 ? sip.c_str() : nullptr));
// set if custom // set if custom
if (hwm >= 0) { if (hwm >= 0) {
zmqSocket->SetSendHighWaterMark(hwm); zmqSocket->SetSendHighWaterMark(hwm);
if (zmqSocket->GetSendHighWaterMark() != hwm) { // needed, or HWL is not taken
throw RuntimeError( zmqSocket->Rebind();
"Could not set zmq send high water mark to " +
std::to_string(hwm));
}
} }
} catch (...) { } catch (std::exception &e) {
LOG(logERROR) << "Could not create Zmq socket on port " << portnum std::ostringstream oss;
<< " for Streamer " << index; oss << "Could not create zmq pub socket on port " << portnum;
throw; oss << " [" << e.what() << ']';
throw RuntimeError(oss.str());
} }
LOG(logINFO) << index << " Streamer: Zmq Server started at " LOG(logINFO) << index << " Streamer: Zmq Server started at "
<< zmqSocket->GetZmqServerAddress() << zmqSocket->GetZmqServerAddress()

View File

@ -78,11 +78,12 @@ void Implementation::SetupFifoStructure() {
try { try {
fifo.push_back( fifo.push_back(
sls::make_unique<Fifo>(i, datasize, generalData->fifoDepth)); sls::make_unique<Fifo>(i, datasize, generalData->fifoDepth));
} catch (...) { } catch (const std::exception &e) {
fifo.clear(); fifo.clear();
generalData->fifoDepth = 0; generalData->fifoDepth = 0;
throw RuntimeError("Could not allocate memory for fifo structure " + std::ostringstream oss;
std::to_string(i) + ". FifoDepth is now 0."); oss << e.what() << ". Fifo depth is now 0";
throw RuntimeError(oss.str());
} }
// set the listener & dataprocessor threads to point to the right fifo // set the listener & dataprocessor threads to point to the right fifo
if (listener.size()) if (listener.size())
@ -165,12 +166,10 @@ void Implementation::setDetectorType(const detectorType d) {
SetupListener(i); SetupListener(i);
dataProcessor.push_back(sls::make_unique<DataProcessor>(i)); dataProcessor.push_back(sls::make_unique<DataProcessor>(i));
SetupDataProcessor(i); SetupDataProcessor(i);
} catch (...) { } catch (const std::exception &e) {
listener.clear(); listener.clear();
dataProcessor.clear(); dataProcessor.clear();
throw RuntimeError( throw;
"Could not create listener/dataprocessor threads (index:" +
std::to_string(i) + ")");
} }
} }
@ -212,6 +211,7 @@ void Implementation::SetupDataStreamer(int i) {
streamingHwm); streamingHwm);
dataStreamer[i]->SetAdditionalJsonHeader(additionalJsonHeader); dataStreamer[i]->SetAdditionalJsonHeader(additionalJsonHeader);
dataStreamer[i]->SetFileIndex(fileIndex); dataStreamer[i]->SetFileIndex(fileIndex);
dataStreamer[i]->SetQuadEnable(quadEnable);
dataStreamer[i]->SetFlipRows(flipRows); dataStreamer[i]->SetFlipRows(flipRows);
dataStreamer[i]->SetNumberofPorts(numPorts); dataStreamer[i]->SetNumberofPorts(numPorts);
dataStreamer[i]->SetQuadEnable(quadEnable); dataStreamer[i]->SetQuadEnable(quadEnable);
@ -351,19 +351,21 @@ std::array<pid_t, NUM_RX_THREAD_IDS> Implementation::getThreadIds() const {
retval[id++] = 0; retval[id++] = 0;
} }
} }
retval[NUM_RX_THREAD_IDS - 1] = arping.GetThreadId(); retval[NUM_RX_THREAD_IDS - 1] = arping.GetProcessId();
return retval; return retval;
} }
bool Implementation::getArping() const { return arping.IsRunning(); } bool Implementation::getArping() const { return arping.IsRunning(); }
pid_t Implementation::getArpingThreadId() const { return arping.GetThreadId(); } pid_t Implementation::getArpingProcessId() const {
return arping.GetProcessId();
}
void Implementation::setArping(const bool i, void Implementation::setArping(const bool i,
const std::vector<std::string> ips) { const std::vector<std::string> ips) {
if (i != arping.IsRunning()) { if (i != arping.IsRunning()) {
if (!i) { if (!i) {
arping.StopThread(); arping.StopProcess();
} else { } else {
// setup interface // setup interface
for (int i = 0; i != generalData->numUDPInterfaces; ++i) { for (int i = 0; i != generalData->numUDPInterfaces; ++i) {
@ -374,7 +376,7 @@ void Implementation::setArping(const bool i,
} }
arping.SetInterfacesAndIps(i, eth[i], ips[i]); arping.SetInterfacesAndIps(i, eth[i], ips[i]);
} }
arping.StartThread(); arping.StartProcess();
} }
} }
} }
@ -665,8 +667,9 @@ void Implementation::startReceiver() {
startAcquisitionCallBack(filePath, fileName, fileIndex, imageSize, startAcquisitionCallBack(filePath, fileName, fileIndex, imageSize,
pStartAcquisition); pStartAcquisition);
} catch (const std::exception &e) { } catch (const std::exception &e) {
throw RuntimeError("Start Acquisition Callback Error: " + std::ostringstream oss;
std::string(e.what())); oss << "Start Acquisition Callback Error: " << e.what();
throw RuntimeError(oss.str());
} }
if (rawDataReadyCallBack != nullptr) { if (rawDataReadyCallBack != nullptr) {
LOG(logINFO) << "Data Write has been defined externally"; LOG(logINFO) << "Data Write has been defined externally";
@ -713,6 +716,10 @@ void Implementation::stopReceiver() {
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
} }
// delete the udp sockets
for (const auto &it : listener)
it->DeleteUDPSocket();
if (fileWriteEnable && modulePos == 0) { if (fileWriteEnable && modulePos == 0) {
// master and virtual file (hdf5) // master and virtual file (hdf5)
StartMasterWriter(); StartMasterWriter();
@ -777,8 +784,9 @@ void Implementation::stopReceiver() {
status = IDLE; status = IDLE;
LOG(logINFO) << "Receiver Stopped"; LOG(logINFO) << "Receiver Stopped";
LOG(logINFO) << "Status: " << ToString(status); LOG(logINFO) << "Status: " << ToString(status);
throw RuntimeError("Acquisition Finished Callback Error: " + std::ostringstream oss;
std::string(e.what())); oss << "Acquisition Finished Callback Error: " << e.what();
throw RuntimeError(oss.str());
} }
} }
} }
@ -859,7 +867,7 @@ void Implementation::CreateUDPSockets() {
} }
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
shutDownUDPSockets(); shutDownUDPSockets();
throw RuntimeError("Could not create UDP Socket(s)."); throw;
} }
LOG(logDEBUG) << "UDP socket(s) created successfully."; LOG(logDEBUG) << "UDP socket(s) created successfully.";
} }
@ -879,7 +887,9 @@ void Implementation::SetupWriter() {
shutDownUDPSockets(); shutDownUDPSockets();
for (const auto &it : dataProcessor) for (const auto &it : dataProcessor)
it->CloseFiles(); it->CloseFiles();
throw RuntimeError("Could not create first data file."); std::ostringstream oss;
oss << "Could not set up writer: " << e.what();
throw RuntimeError(oss.str());
} }
} }
@ -968,10 +978,9 @@ void Implementation::StartMasterWriter() {
} }
} }
#endif #endif
} catch (std::exception &e) { } catch (const std::exception &e) {
// ignore it and just print it // ignore it and just print it
LOG(logWARNING) << "Caught exception when handling virtual hdf5 file [" LOG(logWARNING) << "Error creating master/virtualfiles: " << e.what();
<< e.what() << "]";
} }
} }
@ -1032,12 +1041,10 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
SetupListener(i); SetupListener(i);
dataProcessor.push_back(sls::make_unique<DataProcessor>(i)); dataProcessor.push_back(sls::make_unique<DataProcessor>(i));
SetupDataProcessor(i); SetupDataProcessor(i);
} catch (...) { } catch (const std::exception &e) {
listener.clear(); listener.clear();
dataProcessor.clear(); dataProcessor.clear();
throw RuntimeError( throw;
"Could not create listener/dataprocessor threads (index:" +
std::to_string(i) + ")");
} }
// streamer threads // streamer threads
@ -1045,16 +1052,14 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
try { try {
dataStreamer.push_back(sls::make_unique<DataStreamer>(i)); dataStreamer.push_back(sls::make_unique<DataStreamer>(i));
SetupDataStreamer(i); SetupDataStreamer(i);
} catch (...) { } catch (const std::exception &e) {
if (dataStreamEnable) { if (dataStreamEnable) {
dataStreamer.clear(); dataStreamer.clear();
dataStreamEnable = false; dataStreamEnable = false;
for (const auto &it : dataProcessor) for (const auto &it : dataProcessor)
it->SetDataStreamEnable(dataStreamEnable); it->SetDataStreamEnable(dataStreamEnable);
} }
throw RuntimeError( throw;
"Could not create datastreamer threads (index:" +
std::to_string(i) + ")");
} }
} }
} }
@ -1165,12 +1170,12 @@ void Implementation::setDataStreamEnable(const bool enable) {
try { try {
dataStreamer.push_back(sls::make_unique<DataStreamer>(i)); dataStreamer.push_back(sls::make_unique<DataStreamer>(i));
SetupDataStreamer(i); SetupDataStreamer(i);
} catch (...) { } catch (const std::exception &e) {
dataStreamer.clear(); dataStreamer.clear();
dataStreamEnable = false; dataStreamEnable = false;
for (const auto &it : dataProcessor) for (const auto &it : dataProcessor)
it->SetDataStreamEnable(dataStreamEnable); it->SetDataStreamEnable(dataStreamEnable);
throw RuntimeError("Could not set data stream enable."); throw;
} }
} }
SetThreadPriorities(); SetThreadPriorities();

View File

@ -54,7 +54,7 @@ class Implementation : private virtual slsDetectorDefs {
void setThreadIds(const pid_t parentTid, const pid_t tcpTid); void setThreadIds(const pid_t parentTid, const pid_t tcpTid);
std::array<pid_t, NUM_RX_THREAD_IDS> getThreadIds() const; std::array<pid_t, NUM_RX_THREAD_IDS> getThreadIds() const;
bool getArping() const; bool getArping() const;
pid_t getArpingThreadId() const; pid_t getArpingProcessId() const;
void setArping(const bool i, const std::vector<std::string> ips); void setArping(const bool i, const std::vector<std::string> ips);
ROI getReceiverROI() const; ROI getReceiverROI() const;
void setReceiverROI(const ROI arg); void setReceiverROI(const ROI arg);
@ -323,7 +323,7 @@ class Implementation : private virtual slsDetectorDefs {
// acquisition // acquisition
std::atomic<runStatus> status{IDLE}; std::atomic<runStatus> status{IDLE};
bool stoppedFlag{false}; std::atomic<bool> stoppedFlag{false};
scanParameters scanParams{}; scanParameters scanParams{};
// network configuration (UDP) // network configuration (UDP)

View File

@ -148,30 +148,34 @@ void Listener::RecordFirstIndex(uint64_t fnum) {
} }
void Listener::CreateUDPSocket(int &actualSize) { void Listener::CreateUDPSocket(int &actualSize) {
if (disabledPort) {
return;
}
uint32_t packetSize = generalData->packetSize;
if (generalData->detType == GOTTHARD2 && index != 0) {
packetSize = generalData->vetoPacketSize;
}
try { try {
if (disabledPort) {
return;
}
uint32_t packetSize = generalData->packetSize;
if (generalData->detType == GOTTHARD2 && index != 0) {
packetSize = generalData->vetoPacketSize;
}
udpSocket = nullptr; udpSocket = nullptr;
udpSocket = make_unique<UdpRxSocket>( udpSocket = make_unique<UdpRxSocket>(
udpPortNumber, packetSize, udpPortNumber, packetSize,
(eth.length() ? InterfaceNameToIp(eth).str().c_str() : nullptr), (eth.length() ? InterfaceNameToIp(eth).str().c_str() : nullptr),
generalData->udpSocketBufferSize); generalData->udpSocketBufferSize);
LOG(logINFO) << index << ": UDP port opened at port " << udpPortNumber; LOG(logINFO) << index << ": UDP port opened at port " << udpPortNumber;
} catch (...) {
throw RuntimeError("Could not create UDP socket on port " + udpSocketAlive = true;
std::to_string(udpPortNumber));
// doubled due to kernel bookkeeping (could also be less due to
// permissions)
actualSize = udpSocket->getBufferSize();
} catch (std::exception &e) {
std::ostringstream oss;
oss << "Could not create UDP socket on port " << udpPortNumber << " ["
<< e.what() << ']';
throw RuntimeError(oss.str());
} }
udpSocketAlive = true;
// doubled due to kernel bookkeeping (could also be less due to permissions)
actualSize = udpSocket->getBufferSize();
} }
void Listener::ShutDownUDPSocket() { void Listener::ShutDownUDPSocket() {
@ -184,6 +188,13 @@ void Listener::ShutDownUDPSocket() {
} }
} }
void Listener::DeleteUDPSocket() {
if (udpSocket) {
udpSocket.reset();
LOG(logINFO) << "Closed UDP port " << udpPortNumber;
}
}
void Listener::CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize) { void Listener::CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize) {
// custom setup (s != 0) // custom setup (s != 0)
// default setup at startup (s = 0) // default setup at startup (s = 0)

View File

@ -50,6 +50,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
void ResetParametersforNewAcquisition(); void ResetParametersforNewAcquisition();
void CreateUDPSocket(int &actualSize); void CreateUDPSocket(int &actualSize);
void ShutDownUDPSocket(); void ShutDownUDPSocket();
void DeleteUDPSocket();
/** to set & get actual buffer size */ /** to set & get actual buffer size */
void CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize); void CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize);

View File

@ -31,6 +31,11 @@ namespace sls {
// #define ZMQ_DETAIL // #define ZMQ_DETAIL
#define ROIVERBOSITY #define ROIVERBOSITY
// high water mark for gui
#define DEFFAULT_LOW_ZMQ_HWM (25)
#define DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE (1024 * 1024) // 1MB
#define DEFAULT_ZMQ_BUFFERSIZE (0) // os default
/** zmq header structure */ /** zmq header structure */
struct zmqHeader { struct zmqHeader {
/** true if incoming data, false if end of acquisition */ /** true if incoming data, false if end of acquisition */
@ -108,15 +113,29 @@ class ZmqSocket {
/** Returns high water mark for outbound messages */ /** Returns high water mark for outbound messages */
int GetSendHighWaterMark(); int GetSendHighWaterMark();
/** Sets high water mark for outbound messages. Default 1000 (zmqlib) */ /** Sets high water mark for outbound messages. Default 1000 (zmqlib). Also
* changes send buffer size depending on hwm. Must rebind. */
void SetSendHighWaterMark(int limit); void SetSendHighWaterMark(int limit);
/** Returns high water mark for inbound messages */ /** Returns high water mark for inbound messages */
int GetReceiveHighWaterMark(); int GetReceiveHighWaterMark();
/** Sets high water mark for inbound messages. Default 1000 (zmqlib) */ /** Sets high water mark for inbound messages. Default 1000 (zmqlib). Also
* changes receiver buffer size depending on hwm. Must reconnect */
void SetReceiveHighWaterMark(int limit); void SetReceiveHighWaterMark(int limit);
/** Gets kernel buffer for outbound messages. Default 0 (os) */
int GetSendBuffer();
/** Sets kernel buffer for outbound messages. Default 0 (os) */
void SetSendBuffer(int limit);
/** Gets kernel buffer for inbound messages. Default 0 (os) */
int GetReceiveBuffer();
/** Sets kernel buffer for inbound messages. Default 0 (os) */
void SetReceiveBuffer(int limit);
/** /**
* Returns Port Number * Returns Port Number
* @returns Port Number * @returns Port Number
@ -129,6 +148,9 @@ class ZmqSocket {
*/ */
std::string GetZmqServerAddress() { return sockfd.serverAddress; } std::string GetZmqServerAddress() { return sockfd.serverAddress; }
/** unbinds and rebind, to apply changes of HWM */
void Rebind();
/** /**
* Connect client socket to server socket * Connect client socket to server socket
* @returns 1 for fail, 0 for success * @returns 1 for fail, 0 for success

View File

@ -148,6 +148,18 @@ Squash(const Container &c, typename Container::value_type default_value = {}) {
return default_value; return default_value;
} }
template <typename T>
typename std::enable_if<is_container<T>::value, bool>::type
removeDuplicates(T &c) {
auto containerSize = c.size();
std::sort(c.begin(), c.end());
c.erase(std::unique(c.begin(), c.end()), c.end());
if (c.size() != containerSize) {
return true;
}
return false;
}
} // namespace sls } // namespace sls
#endif // CONTAINER_UTILS_H #endif // CONTAINER_UTILS_H

View File

@ -50,6 +50,8 @@ ssize_t getFileSize(FILE *fd, const std::string &prependErrorString);
std::string getFileNameFromFilePath(const std::string &fpath); std::string getFileNameFromFilePath(const std::string &fpath);
std::vector<int> getChannelsFromStringList(const std::vector<std::string> list);
/** File can have # for comments. /** File can have # for comments.
* Channels can be separated by spaces, commas * Channels can be separated by spaces, commas
* and ranges provided using ':', eg. 23:29 * and ranges provided using ':', eg. 23:29

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 "7.0.0.rc1" #define RELEASE "7.0.0.rc4"
#define APILIB "7.0.0.rc1 0x221208" #define APICTB "7.0.0.rc3 0x230130"
#define APIRECEIVER "7.0.0.rc1 0x221208" #define APIGOTTHARD "7.0.0.rc3 0x230130"
#define APICTB "7.0.0.rc1 0x221212" #define APIGOTTHARD2 "7.0.0.rc3 0x230130"
#define APIGOTTHARD "7.0.0.rc1 0x221212" #define APIJUNGFRAU "7.0.0.rc3 0x230130"
#define APIGOTTHARD2 "7.0.0.rc1 0x221212" #define APIMYTHEN3 "7.0.0.rc3 0x230130"
#define APIJUNGFRAU "7.0.0.rc1 0x221212" #define APIMOENCH "7.0.0.rc3 0x230130"
#define APIMYTHEN3 "7.0.0.rc1 0x221212" #define APIEIGER "7.0.0.rc3 0x230130"
#define APIMOENCH "7.0.0.rc1 0x221212" #define APILIB "7.0.0.rc4 0x230214"
#define APIEIGER "7.0.0.rc1 0x221212" #define APIRECEIVER "7.0.0.rc4 0x230214"

View File

@ -27,15 +27,18 @@ UdpRxSocket::UdpRxSocket(int port, ssize_t packet_size, const char *hostname,
const std::string portname = std::to_string(port); const std::string portname = std::to_string(port);
if (getaddrinfo(hostname, portname.c_str(), &hints, &res)) { if (getaddrinfo(hostname, portname.c_str(), &hints, &res)) {
throw RuntimeError("Failed at getaddrinfo with " + throw RuntimeError("Failed at getaddrinfo with " +
std::string(hostname)); std::string(hostname) + " [" +
std::string(strerror(errno)) + ']');
} }
sockfd_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); sockfd_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd_ == -1) { if (sockfd_ == -1) {
throw RuntimeError("Failed to create UDP RX socket"); throw RuntimeError("Failed to create UDP RX socket [" +
std::string(strerror(errno)) + ']');
} }
if (bind(sockfd_, res->ai_addr, res->ai_addrlen) == -1) { if (bind(sockfd_, res->ai_addr, res->ai_addrlen) == -1) {
close(sockfd_); close(sockfd_);
throw RuntimeError("Failed to bind UDP RX socket"); throw RuntimeError("Failed to bind UDP RX socket [" +
std::string(strerror(errno)) + ']');
} }
freeaddrinfo(res); freeaddrinfo(res);
@ -74,13 +77,15 @@ int UdpRxSocket::getBufferSize() const {
int ret = 0; int ret = 0;
socklen_t optlen = sizeof(ret); socklen_t optlen = sizeof(ret);
if (getsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &ret, &optlen) == -1) if (getsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &ret, &optlen) == -1)
throw RuntimeError("Could not get socket buffer size"); throw RuntimeError("Could not get socket buffer size [" +
std::string(strerror(errno)) + ']');
return ret; return ret;
} }
void UdpRxSocket::setBufferSize(int size) { void UdpRxSocket::setBufferSize(int size) {
if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size))) if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)))
throw RuntimeError("Could not set socket buffer size"); throw RuntimeError("Could not set socket buffer size [" +
std::string(strerror(errno)) + ']');
} }
void UdpRxSocket::Shutdown() { void UdpRxSocket::Shutdown() {

View File

@ -102,6 +102,16 @@ void ZmqSocket::SetSendHighWaterMark(int limit) {
PrintError(); PrintError();
throw ZmqSocketError("Could not set ZMQ_SNDHWM"); throw ZmqSocketError("Could not set ZMQ_SNDHWM");
} }
if (GetSendHighWaterMark() != limit) {
throw ZmqSocketError("Could not set ZMQ_SNDHWM to " +
std::to_string(limit));
}
int bufsize = DEFAULT_ZMQ_BUFFERSIZE;
if (limit < DEFFAULT_LOW_ZMQ_HWM) {
bufsize = DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE;
}
SetSendBuffer(bufsize);
} }
int ZmqSocket::GetReceiveHighWaterMark() { int ZmqSocket::GetReceiveHighWaterMark() {
@ -110,7 +120,7 @@ int ZmqSocket::GetReceiveHighWaterMark() {
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &value, if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &value,
&value_size)) { &value_size)) {
PrintError(); PrintError();
throw ZmqSocketError("Could not get ZMQ_SNDHWM"); throw ZmqSocketError("Could not get ZMQ_RCVHWM");
} }
return value; return value;
} }
@ -119,7 +129,77 @@ void ZmqSocket::SetReceiveHighWaterMark(int limit) {
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &limit, if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &limit,
sizeof(limit))) { sizeof(limit))) {
PrintError(); PrintError();
throw ZmqSocketError("Could not set ZMQ_SNDHWM"); throw ZmqSocketError("Could not set ZMQ_RCVHWM");
}
if (GetReceiveHighWaterMark() != limit) {
throw ZmqSocketError("Could not set ZMQ_RCVHWM to " +
std::to_string(limit));
}
int bufsize = DEFAULT_ZMQ_BUFFERSIZE;
if (limit < DEFFAULT_LOW_ZMQ_HWM) {
bufsize = DEFAULT_LOW_ZMQ_HWM_BUFFERSIZE;
}
SetReceiveBuffer(bufsize);
}
int ZmqSocket::GetSendBuffer() {
int value = 0;
size_t value_size = sizeof(value);
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &value,
&value_size)) {
PrintError();
throw ZmqSocketError("Could not get ZMQ_SNDBUF");
}
return value;
}
void ZmqSocket::SetSendBuffer(int limit) {
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SNDBUF, &limit,
sizeof(limit))) {
PrintError();
throw ZmqSocketError("Could not set ZMQ_SNDBUF");
}
if (GetSendBuffer() != limit) {
throw ZmqSocketError("Could not set ZMQ_SNDBUF to " +
std::to_string(limit));
}
}
int ZmqSocket::GetReceiveBuffer() {
int value = 0;
size_t value_size = sizeof(value);
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &value,
&value_size)) {
PrintError();
throw ZmqSocketError("Could not get ZMQ_RCVBUF");
}
return value;
}
void ZmqSocket::SetReceiveBuffer(int limit) {
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVBUF, &limit,
sizeof(limit))) {
PrintError();
throw ZmqSocketError("Could not set ZMQ_RCVBUF");
}
if (GetReceiveBuffer() != limit) {
throw ZmqSocketError("Could not set ZMQ_RCVBUF to " +
std::to_string(limit));
}
}
void ZmqSocket::Rebind() { // the purpose is to apply HWL changes, which are
// frozen at bind, which is in the constructor.
// unbbind
if (zmq_unbind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
PrintError();
throw ZmqSocketError("Could not unbind socket");
}
// bind address
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
PrintError();
throw ZmqSocketError("Could not bind socket");
} }
} }

View File

@ -2,6 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#include "sls/file_utils.h" #include "sls/file_utils.h"
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/container_utils.h"
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_exceptions.h" #include "sls/sls_detector_exceptions.h"
@ -165,6 +166,63 @@ ssize_t getFileSize(FILE *fd, const std::string &prependErrorString) {
return fileSize; return fileSize;
} }
std::vector<int>
getChannelsFromStringList(const std::vector<std::string> list) {
std::vector<int> channels;
for (auto line : list) {
// replace comma with space
std::replace_if(
begin(line), end(line), [](char c) { return (c == ','); }, ' ');
// split line (delim space)
std::vector<std::string> vec = split(line, ' ');
// for every channel separated by space
for (auto it : vec) {
// find range and replace with sequence of x to y
auto result = it.find(':');
if (result != std::string::npos) {
try {
int istart = StringTo<int>(it.substr(0, result));
int istop = StringTo<int>(
it.substr(result + 1, it.length() - result - 1));
LOG(logDEBUG1) << "istart:" << istart << " istop:" << istop;
std::vector<int> range(istop - istart);
std::generate(range.begin(), range.end(),
[n = istart]() mutable { return n++; });
for (auto range_it : range) {
channels.push_back(range_it);
}
} catch (std::exception &e) {
throw RuntimeError(
"Could not load channels. Invalid channel range: " +
it);
}
}
// else convert to int
else {
int ival = 0;
try {
ival = StringTo<int>(it);
} catch (std::exception &e) {
throw RuntimeError(
"Could not load channels. Invalid channel number: " +
it);
}
channels.push_back(ival);
}
}
}
if (removeDuplicates(channels)) {
LOG(logWARNING) << "Removed duplicates from channel file";
}
LOG(logDEBUG1) << "list:" << ToString(channels);
return channels;
}
std::vector<int> getChannelsFromFile(const std::string &fname) { std::vector<int> getChannelsFromFile(const std::string &fname) {
// read bad channels file // read bad channels file
std::ifstream input_file(fname); std::ifstream input_file(fname);
@ -172,73 +230,19 @@ std::vector<int> getChannelsFromFile(const std::string &fname) {
throw RuntimeError("Could not open bad channels file " + fname + throw RuntimeError("Could not open bad channels file " + fname +
" for reading"); " for reading");
} }
std::vector<int> list; std::vector<std::string> lines;
for (std::string line; std::getline(input_file, line);) { for (std::string line; std::getline(input_file, line);) {
// ignore comments // ignore comments
if (line.find('#') != std::string::npos) { if (line.find('#') != std::string::npos) {
line.erase(line.find('#')); line.erase(line.find('#'));
} }
// ignore empty lines
// replace comma with space if (line.empty()) {
std::replace_if( continue;
begin(line), end(line), [](char c) { return (c == ','); }, ' ');
// replace x:y with a sequence of x to y
auto result = line.find(':');
while (result != std::string::npos) {
auto start = line.rfind(' ', result);
if (start == std::string::npos) {
start = 0;
} else
++start;
int istart = StringTo<int>(line.substr(start, result - start));
auto stop = line.find(' ', result);
if (stop == std::string::npos) {
stop = line.length();
}
int istop =
StringTo<int>(line.substr(result + 1, stop - result - 1));
std::vector<int> v(istop - istart);
std::generate(v.begin(), v.end(),
[n = istart]() mutable { return n++; });
line.replace(start, stop - start, ToString(v));
LOG(logDEBUG1) << line;
result = line.find(':');
}
// remove punctuations including [ and ]
line.erase(std::remove_if(begin(line), end(line), ispunct), end(line));
LOG(logDEBUG) << "\nline: [" << line << ']';
// split line (delim space) and push to list
std::vector<std::string> vec = split(line, ' ');
for (auto it : vec) {
int ival = 0;
try {
ival = StringTo<int>(it);
} catch (std::exception &e) {
throw RuntimeError("Could not load channels from file. Invalid "
"channel number: " +
it);
}
list.push_back(ival);
} }
lines.push_back(line);
} }
return getChannelsFromStringList(lines);
// remove duplicates from list
auto listSize = list.size();
std::sort(list.begin(), list.end());
list.erase(unique(list.begin(), list.end()), list.end());
if (list.size() != listSize) {
LOG(logWARNING) << "Removed duplicates from channel file";
}
LOG(logDEBUG1) << "list:" << ToString(list);
return list;
} }
std::string getAbsolutePathFromCurrentProcess(const std::string &fname) { std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {

View File

@ -136,4 +136,18 @@ TEST_CASE("compare a vector of arrays", "[support]") {
CHECK(minusOneIfDifferent(vec1) == arr); CHECK(minusOneIfDifferent(vec1) == arr);
} }
TEST_CASE("remove duplicates from vector") {
std::vector<int> v{5, 6, 5, 3};
auto r = removeDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{3, 5, 6});
}
TEST_CASE("remove duplicated empty vector") {
std::vector<int> v;
auto r = removeDuplicates(v);
CHECK(r == false); // no elements to remove
CHECK(v == std::vector<int>{});
}
} // namespace sls } // namespace sls