mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-14 22:07:12 +02:00
Compare commits
6 Commits
dev/client
...
developer
Author | SHA1 | Date | |
---|---|---|---|
d19fe8b66a | |||
f4345a91a1 | |||
ec67617e5c | |||
bab6a5e9e1 | |||
f84454fbc1 | |||
c92830f854 |
64
.github/workflows/build_wheel.yml
vendored
Normal file
64
.github/workflows/build_wheel.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
name: Build wheel
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_wheels:
|
||||||
|
name: Build wheels on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest,]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build wheels
|
||||||
|
run: pipx run cibuildwheel==2.23.0
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
||||||
|
path: ./wheelhouse/*.whl
|
||||||
|
|
||||||
|
build_sdist:
|
||||||
|
name: Build source distribution
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build sdist
|
||||||
|
run: pipx run build --sdist
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cibw-sdist
|
||||||
|
path: dist/*.tar.gz
|
||||||
|
|
||||||
|
upload_pypi:
|
||||||
|
needs: [build_wheels, build_sdist]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: pypi
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
|
||||||
|
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
# unpacks all CIBW artifacts into dist/
|
||||||
|
pattern: cibw-*
|
||||||
|
path: dist
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
@ -42,6 +42,7 @@ set(SPHINX_SOURCE_FILES
|
|||||||
src/pyexamples.rst
|
src/pyexamples.rst
|
||||||
src/pyPatternGenerator.rst
|
src/pyPatternGenerator.rst
|
||||||
src/servers.rst
|
src/servers.rst
|
||||||
|
src/multidet.rst
|
||||||
src/receiver_api.rst
|
src/receiver_api.rst
|
||||||
src/result.rst
|
src/result.rst
|
||||||
src/type_traits.rst
|
src/type_traits.rst
|
||||||
|
@ -6,6 +6,8 @@ Usage
|
|||||||
|
|
||||||
The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
|
The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
|
||||||
|
|
||||||
|
.. _cl-module-index-label:
|
||||||
|
|
||||||
Module index
|
Module index
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Modules are indexed based on their order in the hostname command. They are used to configure a specific module within a detector and are followed by a ':' in syntax.
|
Modules are indexed based on their order in the hostname command. They are used to configure a specific module within a detector and are followed by a ':' in syntax.
|
||||||
|
@ -28,6 +28,12 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
receiver_api
|
receiver_api
|
||||||
examples
|
examples
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: how to
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
multidet
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Python API
|
:caption: Python API
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
228
docs/src/multidet.rst
Normal file
228
docs/src/multidet.rst
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
Using multiple detectors
|
||||||
|
==========================
|
||||||
|
|
||||||
|
The slsDetectorPackage supports using several detectors on the same computer.
|
||||||
|
This can either be two users, that need to use the same computer without interfering
|
||||||
|
with each other, or the same user that wants to use multiple detectors at the same time.
|
||||||
|
The detectors in turn can consist of multiple modules. For example, a 9M Jungfrau detector
|
||||||
|
consists of 18 modules which typically are addressed at once as a single detector.
|
||||||
|
|
||||||
|
.. note ::
|
||||||
|
|
||||||
|
To address a single module of a multi-module detector you can use the module index.
|
||||||
|
|
||||||
|
- Command line: :ref:`cl-module-index-label`
|
||||||
|
- Python: :ref:`py-module-index-label`
|
||||||
|
|
||||||
|
|
||||||
|
Coming back to multiple detectors we have two tools to our disposal:
|
||||||
|
|
||||||
|
#. Detector index
|
||||||
|
#. The SLSDETNAME environment variable
|
||||||
|
|
||||||
|
They can be used together or separately depending on the use case.
|
||||||
|
|
||||||
|
Detector index
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When configuring a detector you can specify a detector index. The default is 0.
|
||||||
|
|
||||||
|
**Command line**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Given that we have two detectors (my-det and my-det2) that we want to use,
|
||||||
|
# we can configure them with different indices.
|
||||||
|
|
||||||
|
# Configure the first detector with index 0
|
||||||
|
$ sls_detector_put hostname my-det
|
||||||
|
|
||||||
|
# Set number of frames for detector 0 to 10
|
||||||
|
$ sls_detector_put frames 10
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
#Configure the second detector with index 1 (notice the 1- before hostname)
|
||||||
|
$ sls_detector_put 1-hostname my-det2
|
||||||
|
|
||||||
|
|
||||||
|
# Further configuration
|
||||||
|
...
|
||||||
|
|
||||||
|
# Set number of frames for detector 1 to 19
|
||||||
|
$ sls_detector_put 1-frames 19
|
||||||
|
|
||||||
|
# Note that if we call sls_detector_get without specifying the index,
|
||||||
|
# it will return the configuration of detector 0
|
||||||
|
$ sls_detector_get frames
|
||||||
|
10
|
||||||
|
|
||||||
|
The detector index is added to the name of the shared memory segment, so in this case
|
||||||
|
the shared memory segments would be:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
|
||||||
|
#First detector
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_module_0
|
||||||
|
|
||||||
|
#Second detector
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_module_0
|
||||||
|
|
||||||
|
|
||||||
|
**Python**
|
||||||
|
|
||||||
|
The main difference between the command line and the Python API is that you set the index
|
||||||
|
when you create the detector object and you don't have to repeat it for every call.
|
||||||
|
|
||||||
|
The C++ API works int the same way.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import Detector
|
||||||
|
|
||||||
|
|
||||||
|
# The same can be achieved in Python by creating a detector object with an index.
|
||||||
|
# Again we have two detectors (my-det and my-det2) that we want to use:
|
||||||
|
|
||||||
|
# Configure detector with index 0
|
||||||
|
d = Detector()
|
||||||
|
|
||||||
|
# If the detector has already been configured and has a shared memory
|
||||||
|
# segment, you can omit setting the hostname again
|
||||||
|
d.hostname = 'my-det'
|
||||||
|
|
||||||
|
#Further configuration
|
||||||
|
...
|
||||||
|
|
||||||
|
# Configure a second detector with index 1
|
||||||
|
d2 = Detector(1)
|
||||||
|
d2.hostname = 'my-det2'
|
||||||
|
|
||||||
|
d.frames = 10
|
||||||
|
d2.frames = 19
|
||||||
|
|
||||||
|
|
||||||
|
$SLSDETNAME
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
To avoid interfering with other users on shared PCs it is best to always set the SLSDETNAME environmental variable.
|
||||||
|
Imagining a fictive user: Anna, we can set SLSDETNAME from the shell before configuring the detector:
|
||||||
|
|
||||||
|
**Command line**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Set the SLSDETNAME variable
|
||||||
|
$ export SLSDETNAME=Anna
|
||||||
|
|
||||||
|
# You can check that it is set
|
||||||
|
$ echo $SLSDETNAME
|
||||||
|
Anna
|
||||||
|
|
||||||
|
# Now configures a detector with index 0 and prefixed with the name Anna
|
||||||
|
# /dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
$ sls_detector_put hostname my-det
|
||||||
|
|
||||||
|
|
||||||
|
.. tip ::
|
||||||
|
|
||||||
|
Set SLSDETNAME in your .bashrc in order to not forget it when opening a new terminal.
|
||||||
|
|
||||||
|
|
||||||
|
**Python**
|
||||||
|
|
||||||
|
With python the best way is to set the SLSDETNAME from the command line before starting the python interpreter.
|
||||||
|
|
||||||
|
Bash:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ export SLSDETNAME=Anna
|
||||||
|
|
||||||
|
Python:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import Detector
|
||||||
|
|
||||||
|
# Now configures a detector with index 0 and prefixed with the name Anna
|
||||||
|
# /dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
d = Detector()
|
||||||
|
d.hostname = 'my-det'
|
||||||
|
|
||||||
|
You can also set SLSDETNAME from within the Python interpreter, but you have to be aware that it will only
|
||||||
|
affect the current process and not the whole shell session.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.environ['SLSDETNAME'] = 'Anna'
|
||||||
|
|
||||||
|
# You can check that it is set
|
||||||
|
print(os.environ['SLSDETNAME']) # Output: Anna
|
||||||
|
|
||||||
|
#Now SLSDETNAME is set to Anna but as soon as you exit the python interpreter
|
||||||
|
# it will not be set anymore
|
||||||
|
|
||||||
|
.. note ::
|
||||||
|
|
||||||
|
Python has two ways of reading environment variables: `**os.environ**` as shown above which throws a
|
||||||
|
KeyError if the variable is not set and `os.getenv('SLSDETNAME')` which returns None if the variable is not set.
|
||||||
|
|
||||||
|
For more details see the official python documentation on: https://docs.python.org/3/library/os.html#os.environ
|
||||||
|
|
||||||
|
|
||||||
|
Checking for other detectors
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
If using shared accounts on a shared computer (which you anyway should not do), it is good practice to check
|
||||||
|
if there are other detectors configured by other users before configuring your own detector.
|
||||||
|
|
||||||
|
You can do this by listing the files in the shared memory directory `/dev/shm/` that start with `sls`. In this
|
||||||
|
example we can see that two single module detectors are configured one with index 0 and one with index 1.
|
||||||
|
SLSDETNAME is set to `Anna` so it makes sense to assume that she is the user that configured these detectors.
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# List the files in /dev/shm that starts with sls
|
||||||
|
$ ls /dev/shm/sls*
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_module_0_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_module_0_Anna
|
||||||
|
|
||||||
|
We also provide a command: user, which gets information about the shared memory segment that
|
||||||
|
the client points to without doing any changes.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#in this case 3 simulated Mythen3 modules
|
||||||
|
$ sls_detector_get user
|
||||||
|
user
|
||||||
|
Hostname: localhost+localhost+localhost+
|
||||||
|
Type: Mythen3
|
||||||
|
PID: 1226078
|
||||||
|
User: l_msdetect
|
||||||
|
Date: Mon Jun 2 05:46:20 PM CEST 2025
|
||||||
|
|
||||||
|
|
||||||
|
Other considerations
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The shared memory is not the only way to interfere with other users. You also need to make sure that you are not
|
||||||
|
using the same:
|
||||||
|
|
||||||
|
* rx_tcpport
|
||||||
|
* Unique combination of udp_dstip and udp_dstport
|
||||||
|
* rx_zmqport
|
||||||
|
* zmqport
|
||||||
|
|
||||||
|
.. attention ::
|
||||||
|
|
||||||
|
The computer that you are using need to have enough resources to run multiple detectors at the same time.
|
||||||
|
This includes CPU and network bandwidth. Please coordinate with the other users!
|
||||||
|
|
@ -123,6 +123,47 @@ in a large detector.
|
|||||||
# Set exposure time for module 1, 5 and 7
|
# Set exposure time for module 1, 5 and 7
|
||||||
d.setExptime(0.1, [1,5,7])
|
d.setExptime(0.1, [1,5,7])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _py-module-index-label:
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Accessing individual modules
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Using the C++ like API you can access individual modules in a large detector
|
||||||
|
by passing in the module index as an argument to the function.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# Read the UDP destination port for all modules
|
||||||
|
>>> d.getDestinationUDPPort()
|
||||||
|
[50001, 50002, 50003]
|
||||||
|
|
||||||
|
|
||||||
|
# Read it for module 0 and 1
|
||||||
|
>>> d.getDestinationUDPPort([0, 1])
|
||||||
|
[50001, 50002]
|
||||||
|
|
||||||
|
>>> d.setDestinationUDPPort(50010, 1)
|
||||||
|
>>> d.getDestinationUDPPort()
|
||||||
|
[50001, 50010, 50003]
|
||||||
|
|
||||||
|
From the more pythonic API there is no way to read from only one module but you can read
|
||||||
|
and then use list slicing to get the values for the modules you are interested in.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> d.udp_dstport
|
||||||
|
[50001, 50010, 50003]
|
||||||
|
>>> d.udp_dstport[0]
|
||||||
|
50001
|
||||||
|
|
||||||
|
#For some but not all properties you can also pass in a dictionary with module index as key
|
||||||
|
>>> ip = IpAddr('127.0.0.1')
|
||||||
|
>>> d.udp_dstip = {1:ip}
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
Finding functions
|
Finding functions
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -14,4 +14,4 @@ slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
|
|||||||
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
slsDetectorPackage/9.1.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/9.1.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
slsDetectorPackage/9.1.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/9.1.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
|
slsDetectorPackage/9.2.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
|
@ -29,6 +29,7 @@ target_link_libraries(slsDetectorObject
|
|||||||
slsProjectOptions
|
slsProjectOptions
|
||||||
slsSupportStatic
|
slsSupportStatic
|
||||||
pthread
|
pthread
|
||||||
|
rt
|
||||||
PRIVATE
|
PRIVATE
|
||||||
slsProjectWarnings
|
slsProjectWarnings
|
||||||
)
|
)
|
||||||
@ -97,7 +98,8 @@ if(SLS_USE_TEXTCLIENT)
|
|||||||
add_executable(${val1} src/CmdApp.cpp)
|
add_executable(${val1} src/CmdApp.cpp)
|
||||||
|
|
||||||
target_link_libraries(${val1}
|
target_link_libraries(${val1}
|
||||||
slsDetectorStatic
|
slsDetectorStatic
|
||||||
|
pthread
|
||||||
)
|
)
|
||||||
SET_SOURCE_FILES_PROPERTIES( src/Caller.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")
|
SET_SOURCE_FILES_PROPERTIES( src/Caller.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")
|
||||||
|
|
||||||
|
@ -1203,7 +1203,7 @@ void Module::setDestinationUDPIP(const IpAddr ip) {
|
|||||||
}
|
}
|
||||||
sendToDetector(F_SET_DEST_UDP_IP, ip, nullptr);
|
sendToDetector(F_SET_DEST_UDP_IP, ip, nullptr);
|
||||||
if (shm()->useReceiverFlag) {
|
if (shm()->useReceiverFlag) {
|
||||||
MacAddr retval{uint64_t(0)};
|
MacAddr retval(0LU);
|
||||||
sendToReceiver(F_SET_RECEIVER_UDP_IP, ip, retval);
|
sendToReceiver(F_SET_RECEIVER_UDP_IP, ip, retval);
|
||||||
LOG(logINFO) << "Setting destination udp mac of Module " << moduleIndex
|
LOG(logINFO) << "Setting destination udp mac of Module " << moduleIndex
|
||||||
<< " to " << retval;
|
<< " to " << retval;
|
||||||
@ -1226,7 +1226,7 @@ void Module::setDestinationUDPIP2(const IpAddr ip) {
|
|||||||
}
|
}
|
||||||
sendToDetector(F_SET_DEST_UDP_IP2, ip, nullptr);
|
sendToDetector(F_SET_DEST_UDP_IP2, ip, nullptr);
|
||||||
if (shm()->useReceiverFlag) {
|
if (shm()->useReceiverFlag) {
|
||||||
MacAddr retval{uint64_t(0)};
|
MacAddr retval(0LU);
|
||||||
sendToReceiver(F_SET_RECEIVER_UDP_IP2, ip, retval);
|
sendToReceiver(F_SET_RECEIVER_UDP_IP2, ip, retval);
|
||||||
LOG(logINFO) << "Setting destination udp mac2 of Module " << moduleIndex
|
LOG(logINFO) << "Setting destination udp mac2 of Module " << moduleIndex
|
||||||
<< " to " << retval;
|
<< " to " << retval;
|
||||||
|
@ -25,12 +25,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
#ifdef __APPLE__
|
|
||||||
// On macOS SHM_NAME_MAX is 31 so we need the shortest possible prefix
|
#define SHM_DETECTOR_PREFIX "/slsDetectorPackage_detector_"
|
||||||
#define SHM_DETECTOR_PREFIX "/sls_"
|
|
||||||
#else
|
|
||||||
#define SHM_DETECTOR_PREFIX "/slsDetectorPackage_detector_"
|
|
||||||
#endif
|
|
||||||
#define SHM_MODULE_PREFIX "_module_"
|
#define SHM_MODULE_PREFIX "_module_"
|
||||||
#define SHM_ENV_NAME "SLSDETNAME"
|
#define SHM_ENV_NAME "SLSDETNAME"
|
||||||
|
|
||||||
@ -207,11 +203,6 @@ template <typename T> class SharedMemory {
|
|||||||
throw SharedMemoryError(msg);
|
throw SharedMemoryError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// On macOS, fstat returns the allocated size and not the requested size.
|
|
||||||
// This means we can't check for size since we always get for example 16384 bytes.
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
auto actual_size = static_cast<size_t>(sb.st_size);
|
auto actual_size = static_cast<size_t>(sb.st_size);
|
||||||
auto expected_size = sizeof(T);
|
auto expected_size = sizeof(T);
|
||||||
if (actual_size != expected_size) {
|
if (actual_size != expected_size) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
// #include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -178,30 +178,30 @@ IpAddr InterfaceNameToIp(const std::string &ifn) {
|
|||||||
|
|
||||||
MacAddr InterfaceNameToMac(const std::string &inf) {
|
MacAddr InterfaceNameToMac(const std::string &inf) {
|
||||||
// TODO! Copied from genericSocket needs to be refactored!
|
// TODO! Copied from genericSocket needs to be refactored!
|
||||||
// struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
// char mac[32];
|
char mac[32];
|
||||||
// const int mac_len = sizeof(mac);
|
const int mac_len = sizeof(mac);
|
||||||
// memset(mac, 0, mac_len);
|
memset(mac, 0, mac_len);
|
||||||
|
|
||||||
// int sock = socket(PF_INET, SOCK_STREAM, 0);
|
int sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
// strncpy(ifr.ifr_name, inf.c_str(), sizeof(ifr.ifr_name) - 1);
|
strncpy(ifr.ifr_name, inf.c_str(), sizeof(ifr.ifr_name) - 1);
|
||||||
// ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
|
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
|
||||||
|
|
||||||
// if (-1 == ioctl(sock, SIOCGIFHWADDR, &ifr)) {
|
if (-1 == ioctl(sock, SIOCGIFHWADDR, &ifr)) {
|
||||||
// perror("ioctl(SIOCGIFHWADDR) ");
|
perror("ioctl(SIOCGIFHWADDR) ");
|
||||||
// return MacAddr{};
|
return MacAddr{};
|
||||||
// }
|
}
|
||||||
// for (int j = 0, k = 0; j < 6; j++) {
|
for (int j = 0, k = 0; j < 6; j++) {
|
||||||
// k += snprintf(
|
k += snprintf(
|
||||||
// mac + k, mac_len - k - 1, j ? ":%02X" : "%02X",
|
mac + k, mac_len - k - 1, j ? ":%02X" : "%02X",
|
||||||
// (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
|
(int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
|
||||||
// }
|
}
|
||||||
// mac[mac_len - 1] = '\0';
|
mac[mac_len - 1] = '\0';
|
||||||
|
|
||||||
// if (sock != 1) {
|
if (sock != 1) {
|
||||||
// close(sock);
|
close(sock);
|
||||||
// }
|
}
|
||||||
return MacAddr();
|
return MacAddr(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
void validatePortNumber(uint16_t port) {
|
void validatePortNumber(uint16_t port) {
|
||||||
|
@ -25,6 +25,7 @@ target_link_libraries(tests
|
|||||||
slsProjectOptions
|
slsProjectOptions
|
||||||
slsSupportStatic
|
slsSupportStatic
|
||||||
pthread
|
pthread
|
||||||
|
rt
|
||||||
PRIVATE
|
PRIVATE
|
||||||
slsProjectWarnings
|
slsProjectWarnings
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ from utils_for_test import (
|
|||||||
cleanSharedmemory,
|
cleanSharedmemory,
|
||||||
startProcessInBackground,
|
startProcessInBackground,
|
||||||
startProcessInBackgroundWithLogFile,
|
startProcessInBackgroundWithLogFile,
|
||||||
|
checkLogForErrors,
|
||||||
startDetectorVirtualServer,
|
startDetectorVirtualServer,
|
||||||
loadConfig,
|
loadConfig,
|
||||||
ParseArguments
|
ParseArguments
|
||||||
@ -34,6 +35,9 @@ def startFrameSynchronizerPullSocket(name, fp):
|
|||||||
fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt'
|
fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt'
|
||||||
cmd = ['python', '-u', 'frameSynchronizerPullSocket.py']
|
cmd = ['python', '-u', 'frameSynchronizerPullSocket.py']
|
||||||
startProcessInBackgroundWithLogFile(cmd, fp, fname)
|
startProcessInBackgroundWithLogFile(cmd, fp, fname)
|
||||||
|
time.sleep(1)
|
||||||
|
checkLogForErrors(fp, fname)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def startFrameSynchronizer(num_mods, fp):
|
def startFrameSynchronizer(num_mods, fp):
|
||||||
@ -44,16 +48,14 @@ def startFrameSynchronizer(num_mods, fp):
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
def acquire(fp):
|
def acquire(fp, det):
|
||||||
Log(LogLevel.INFO, 'Acquiring')
|
Log(LogLevel.INFO, 'Acquiring')
|
||||||
Log(LogLevel.INFO, 'Acquiring', fp)
|
Log(LogLevel.INFO, 'Acquiring', fp)
|
||||||
d = Detector()
|
det.acquire()
|
||||||
d.acquire()
|
|
||||||
|
|
||||||
|
|
||||||
def testFramesCaught(name, num_frames):
|
def testFramesCaught(name, det, num_frames):
|
||||||
d = Detector()
|
fnum = det.rx_framescaught[0]
|
||||||
fnum = d.rx_framescaught[0]
|
|
||||||
if fnum != num_frames:
|
if fnum != num_frames:
|
||||||
raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}")
|
raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}")
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ def testFramesCaught(name, num_frames):
|
|||||||
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp)
|
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp)
|
||||||
|
|
||||||
|
|
||||||
def testZmqHeadetTypeCount(name, num_mods, num_frames, fp):
|
def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp):
|
||||||
|
|
||||||
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}")
|
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}")
|
||||||
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp)
|
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp)
|
||||||
@ -88,8 +90,7 @@ def testZmqHeadetTypeCount(name, num_mods, num_frames, fp):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# test if file contents matches expected counts
|
# test if file contents matches expected counts
|
||||||
d = Detector()
|
num_ports_per_module = 1 if name == "gotthard2" else det.numinterfaces
|
||||||
num_ports_per_module = 1 if name == "gotthard2" else d.numinterfaces
|
|
||||||
total_num_frame_parts = num_ports_per_module * num_mods * num_frames
|
total_num_frame_parts = num_ports_per_module * num_mods * num_frames
|
||||||
for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]:
|
for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]:
|
||||||
if htype_counts[htype] != expected_count:
|
if htype_counts[htype] != expected_count:
|
||||||
@ -111,10 +112,10 @@ def startTestsForAll(args, fp):
|
|||||||
startDetectorVirtualServer(server, args.num_mods, fp)
|
startDetectorVirtualServer(server, args.num_mods, fp)
|
||||||
startFrameSynchronizerPullSocket(server, fp)
|
startFrameSynchronizerPullSocket(server, fp)
|
||||||
startFrameSynchronizer(args.num_mods, fp)
|
startFrameSynchronizer(args.num_mods, fp)
|
||||||
loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
|
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
|
||||||
acquire(fp)
|
acquire(fp, d)
|
||||||
testFramesCaught(server, args.num_frames)
|
testFramesCaught(server, d, args.num_frames)
|
||||||
testZmqHeadetTypeCount(server, args.num_mods, args.num_frames, fp)
|
testZmqHeadetTypeCount(server, d, args.num_mods, args.num_frames, fp)
|
||||||
Log(LogLevel.INFO, '\n')
|
Log(LogLevel.INFO, '\n')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeException(f'Synchronizer Tests failed') from e
|
raise RuntimeException(f'Synchronizer Tests failed') from e
|
||||||
|
@ -104,7 +104,7 @@ def startProcessInBackground(cmd, fp):
|
|||||||
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
||||||
|
|
||||||
|
|
||||||
def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name):
|
def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name: str):
|
||||||
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name)
|
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name)
|
||||||
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp)
|
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp)
|
||||||
try:
|
try:
|
||||||
@ -114,6 +114,22 @@ def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name):
|
|||||||
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
||||||
|
|
||||||
|
|
||||||
|
def checkLogForErrors(fp, log_file_path: str):
|
||||||
|
try:
|
||||||
|
with open(log_file_path, 'r') as log_file:
|
||||||
|
for line in log_file:
|
||||||
|
if 'Error' in line:
|
||||||
|
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}")
|
||||||
|
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}", fp)
|
||||||
|
raise RuntimeException("Error found in log file")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Log file not found: {log_file_path}")
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exception while reading log: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def runProcessWithLogFile(name, cmd, fp, log_file_name):
|
def runProcessWithLogFile(name, cmd, fp, log_file_name):
|
||||||
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name)
|
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name)
|
||||||
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp)
|
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp)
|
||||||
@ -140,7 +156,7 @@ def startDetectorVirtualServer(name :str, num_mods, fp):
|
|||||||
for i in range(num_mods):
|
for i in range(num_mods):
|
||||||
port_no = SERVER_START_PORTNO + (i * 2)
|
port_no = SERVER_START_PORTNO + (i * 2)
|
||||||
cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)]
|
cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)]
|
||||||
startProcessInBackground(cmd, fp)
|
startProcessInBackgroundWithLogFile(cmd, fp, "/tmp/virtual_det_" + name + str(i) + ".txt")
|
||||||
match name:
|
match name:
|
||||||
case 'jungfrau':
|
case 'jungfrau':
|
||||||
time.sleep(7)
|
time.sleep(7)
|
||||||
@ -201,6 +217,8 @@ def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1)
|
|||||||
d.frames = num_frames
|
d.frames = num_frames
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
|
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
def ParseArguments(description, default_num_mods=1):
|
def ParseArguments(description, default_num_mods=1):
|
||||||
|
Reference in New Issue
Block a user