mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-17 15:27:13 +02:00
Compare commits
230 Commits
9.2.0
...
jf_h5reade
Author | SHA1 | Date | |
---|---|---|---|
ab2e290658 | |||
1b0e891912 | |||
292d65491a | |||
36faec6ad3 | |||
01d3dc7115 | |||
062002243e | |||
98b1e287a4 | |||
e1f46d4747 | |||
d8c3fa0df3 | |||
27530fca31 | |||
cc7f13a10e | |||
625f4353fb | |||
2815913d10 | |||
5fa2402ec5 | |||
4d7d3c9138 | |||
c3f1d05033 | |||
0e4cb7cbcd | |||
bace9edf89 | |||
99735c3ee5 | |||
2571397c70 | |||
497c3abfc2 | |||
fca31cc432 | |||
8fe4a78feb | |||
ee170fa2e0 | |||
da760b2b93 | |||
2c8c2a46ea | |||
9625a8058c | |||
4d8bdae836 | |||
3297707ab7 | |||
598154645c | |||
9d8f9a9ba9 | |||
68f163b757 | |||
b8c5bb2045 | |||
b45df191e5 | |||
01cc745787 | |||
f9bc2eb126 | |||
4c86ad3198 | |||
5be0724f82 | |||
7c652498e4 | |||
721d536350 | |||
361437428d | |||
aadbfeaf2d | |||
f119d14e7c | |||
f8b12201f8 | |||
585c92be66 | |||
7c8639b8ae | |||
a138b5b365 | |||
9fde62ae30 | |||
29fe988583 | |||
6740d9b363 | |||
1d1b55b864 | |||
c32732b22e | |||
1e6b6fef0a | |||
5ab2c1693e | |||
0b3cd499a8 | |||
884e17f0c4 | |||
d0ccf236c0 | |||
396b955db7 | |||
5f14eb32aa | |||
cfec7c18ec | |||
04583acb21 | |||
95e11d668a | |||
772e58c743 | |||
470e2633c3 | |||
3312adddd1 | |||
46152d2419 | |||
b5c82783d6 | |||
dc85a48864 | |||
dc8a34592a | |||
96ae1a1cca | |||
3793e7b7d4 | |||
713e4f6822 | |||
fada23365e | |||
6dd0a5b0dd | |||
c3b197f209 | |||
9f49ac6457 | |||
0b3ead6353 | |||
8b3625fc01 | |||
0da508a8b7 | |||
608eb1a436 | |||
c0bc6fe25a | |||
a0d540fd72 | |||
46a46b65e5 | |||
4f62b1a05c | |||
45dadf8b90 | |||
e8e84a4e72 | |||
2f390971e6 | |||
b7e17d1320 | |||
c54b1cb6af | |||
ddb89bce34 | |||
f056f9d31b | |||
3e2d34bec7 | |||
5e8a354194 | |||
8c35fc16b9 | |||
ac0394e176 | |||
d9a50ad9f4 | |||
ce0450d498 | |||
7b531059a0 | |||
bc187bb198 | |||
eb8c34f53b | |||
d9a50705e4 | |||
f4626c2c81 | |||
e0a48e1e75 | |||
ec4eb1978e | |||
842b376801 | |||
13b2cada66 | |||
dd6354ff94 | |||
3c2f149c22 | |||
0a5b5aac4b | |||
18d781c35a | |||
9c111fbeab | |||
222d9e4839 | |||
9508dd1adc | |||
cf62f8cae8 | |||
08c10679e6 | |||
2b68b2158b | |||
6e5b058fc1 | |||
ace2b3a938 | |||
5a8213024e | |||
bd66228b30 | |||
721d296712 | |||
62dd5c8d4e | |||
e1c9754cd2 | |||
ff101e19cd | |||
e8ac048114 | |||
3c79e8d7b2 | |||
a74fb2bcd1 | |||
63bb79d727 | |||
8d87a6ee4e | |||
ab01940769 | |||
23aa9c2814 | |||
35c37998f3 | |||
010f736e80 | |||
4dcbcad435 | |||
8f8a92b9c5 | |||
9b13ddf6be | |||
49db2fbee7 | |||
684eee984d | |||
297c3752e3 | |||
670d4dbce4 | |||
a0e5304df6 | |||
fa504e6675 | |||
2b8fbad47d | |||
a095a4ffce | |||
d74da4cf04 | |||
9321d6d03a | |||
45a9a74137 | |||
bede3003b6 | |||
b9b4f1ae35 | |||
3c2062f23e | |||
e7247f1fee | |||
905a509a17 | |||
b4dc1dde6c | |||
964ab19b42 | |||
ce8911de10 | |||
d1e5b0bc42 | |||
4b3ed22f76 | |||
aad1ab0cf4 | |||
117637863d | |||
e933a25453 | |||
f1f369b48c | |||
6b149244d3 | |||
436d180e93 | |||
c43a4030a5 | |||
5fd319725e | |||
fb77bc7f1d | |||
8a5bd21ecc | |||
cb99aa40cb | |||
41bb7ca1ed | |||
d85d4f94d6 | |||
ea288a1939 | |||
be607e8a2e | |||
7396ceed54 | |||
243c555798 | |||
7b1e74f4a4 | |||
fcbb87b71a | |||
3a1945116a | |||
884104156b | |||
830ce66a4c | |||
69e1702493 | |||
027534cc2f | |||
633f83f9c7 | |||
b73684612b | |||
71ca4e9f0f | |||
6e826d2840 | |||
315d49f8df | |||
25854f7736 | |||
bc6814ad0b | |||
7608d6392c | |||
adcaf6b3df | |||
577362f95e | |||
cfa0b003ba | |||
266ace44a2 | |||
a8a4cc641e | |||
d2dead070c | |||
0583a0703c | |||
19f4c07642 | |||
b587e95717 | |||
f3a3fb09bf | |||
f0fc547c6f | |||
3150276bfe | |||
7b4740ced2 | |||
16bfcc17ce | |||
a9c366890b | |||
4ae2edf686 | |||
69fb5876cb | |||
543b311c06 | |||
669e5f3c7a | |||
a6a4ea7f21 | |||
31f6a6de61 | |||
9d2d4f49d4 | |||
76ee52a3ca | |||
732c54d273 | |||
c0cbccd7d4 | |||
783b95b1f3 | |||
d8e3e38c33 | |||
7a03e56f09 | |||
9bc20ab9b4 | |||
95b7be6842 | |||
51d34063ac | |||
d2fcc1f344 | |||
2b93ef4565 | |||
78cbe8e660 | |||
0ee54be252 | |||
f90a9b7520 | |||
558c2de85c | |||
877a648d9e | |||
9ea5101299 | |||
c57f10c242 | |||
6d6b6b98df |
29
.gitea/workflows/rh8-native.yml
Normal file
29
.gitea/workflows/rh8-native.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Build on RHEL8
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
container:
|
||||||
|
image: gitea.psi.ch/detectors/rhel8-detectors-dev
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
run: |
|
||||||
|
echo Cloning ${{ github.ref_name }}
|
||||||
|
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
|
||||||
|
|
||||||
|
- name: Build library
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||||
|
make -j 2
|
||||||
|
|
||||||
|
- name: C++ unit tests
|
||||||
|
working-directory: ${{gitea.workspace}}/build
|
||||||
|
run: ctest
|
27
.gitea/workflows/rh9-native.yml
Normal file
27
.gitea/workflows/rh9-native.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: Build on RHEL9
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
container:
|
||||||
|
image: gitea.psi.ch/detectors/rhel9-detectors-dev
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
||||||
|
- name: Build library
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||||
|
make -j 2
|
||||||
|
|
||||||
|
- name: C++ unit tests
|
||||||
|
working-directory: ${{gitea.workspace}}/build
|
||||||
|
run: ctest
|
@ -44,6 +44,10 @@ endif()
|
|||||||
# Patch is applied in the FetchContent_Declare
|
# Patch is applied in the FetchContent_Declare
|
||||||
set(SLS_LIBZMQ_VERSION "4.3.4")
|
set(SLS_LIBZMQ_VERSION "4.3.4")
|
||||||
|
|
||||||
|
find_program(PATCH_EXECUTABLE patch)
|
||||||
|
if(NOT PATCH_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "The 'patch' tool is required for patching lib zeromq. Please install it.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(SLS_FETCH_ZMQ_FROM_GITHUB)
|
if(SLS_FETCH_ZMQ_FROM_GITHUB)
|
||||||
# Opt in to pull down a zmq version from github instead of
|
# Opt in to pull down a zmq version from github instead of
|
||||||
@ -216,7 +220,7 @@ endif()
|
|||||||
# to control options for the libraries
|
# to control options for the libraries
|
||||||
if(NOT TARGET slsProjectOptions)
|
if(NOT TARGET slsProjectOptions)
|
||||||
add_library(slsProjectOptions INTERFACE)
|
add_library(slsProjectOptions INTERFACE)
|
||||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
|
target_compile_features(slsProjectOptions INTERFACE cxx_std_17)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET slsProjectWarnings)
|
if (NOT TARGET slsProjectWarnings)
|
||||||
@ -329,7 +333,8 @@ if (SLS_USE_INTEGRATION_TESTS)
|
|||||||
endif (SLS_USE_INTEGRATION_TESTS)
|
endif (SLS_USE_INTEGRATION_TESTS)
|
||||||
|
|
||||||
if (SLS_USE_PYTHON)
|
if (SLS_USE_PYTHON)
|
||||||
find_package (Python 3.8 COMPONENTS Interpreter Development)
|
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
||||||
|
set(PYBIND11_FINDPYTHON ON) # Needed for RH8
|
||||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
pybind11
|
pybind11
|
||||||
|
50
RELEASE.txt
50
RELEASE.txt
@ -1,13 +1,21 @@
|
|||||||
SLS Detector Package Minor Release 9.2.0 released on 02.06.2025
|
SLS Detector Package Major Release x.x.x released on xx.xx.202x
|
||||||
==================================================================
|
===============================================================
|
||||||
|
|
||||||
This document describes the differences between v9.2.0 and v9.1.1
|
This document describes the differences between vx.x.x and vx.0.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CONTENTS
|
CONTENTS
|
||||||
--------
|
--------
|
||||||
1 New or Changed Features
|
1 New, Changed or Resolved Features
|
||||||
|
1.1 Compilation
|
||||||
|
1.2 Callback
|
||||||
|
1.3 Python
|
||||||
|
1.4 Client
|
||||||
|
1.5 Detector Server
|
||||||
|
1.6 Simulator
|
||||||
|
1.7 Receiver
|
||||||
|
1.8 Gui
|
||||||
2 On-board Detector Server Compatibility
|
2 On-board Detector Server Compatibility
|
||||||
3 Firmware Requirements
|
3 Firmware Requirements
|
||||||
4 Kernel Requirements
|
4 Kernel Requirements
|
||||||
@ -16,21 +24,10 @@ This document describes the differences between v9.2.0 and v9.1.1
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
1 New or Changed Features
|
1 New, Changed or Resolved Features
|
||||||
=========================
|
=====================================
|
||||||
|
|
||||||
|
|
||||||
Python
|
|
||||||
------
|
|
||||||
|
|
||||||
|
|
||||||
* Python module is now built using scikit-build-core
|
|
||||||
|
|
||||||
|
|
||||||
* slsdet is available on PyPI from this release onwards
|
|
||||||
|
|
||||||
|
|
||||||
* Updated documentation on python module installation
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -39,10 +36,9 @@ This document describes the differences between v9.2.0 and v9.1.1
|
|||||||
|
|
||||||
|
|
||||||
Eiger 9.0.0
|
Eiger 9.0.0
|
||||||
Jungfrau 9.1.0
|
Jungfrau 9.0.0
|
||||||
Mythen3 9.1.1
|
Mythen3 9.0.0
|
||||||
Gotthard2 9.0.0
|
Gotthard2 9.0.0
|
||||||
Gotthard 9.0.0
|
|
||||||
Moench 9.0.0
|
Moench 9.0.0
|
||||||
|
|
||||||
|
|
||||||
@ -69,17 +65,14 @@ This document describes the differences between v9.2.0 and v9.1.1
|
|||||||
|
|
||||||
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
||||||
|
|
||||||
Jungfrau 09.02.2025 (v1.6, HW v1.0) (updated in 9.1.0)
|
Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0)
|
||||||
08.02.2025 (v2.6, HW v2.0) (updated in 9.1.0)
|
21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0)
|
||||||
|
|
||||||
Mythen3 13.11.2024 (v2.0) (updated in 9.0.0)
|
Mythen3 11.10.2024 (v1.5) (updated in 9.0.0)
|
||||||
|
|
||||||
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
||||||
|
|
||||||
Moench 26.10.2023 (v2.0) (updated in 8.0.2)
|
Moench 26.10.2023 (v2.0) (updated in 9.0.0)
|
||||||
|
|
||||||
Gotthard 08.02.2018 (50um and 25um Master)
|
|
||||||
09.02.2018 (25 um Slave)
|
|
||||||
|
|
||||||
|
|
||||||
Detector Upgrade
|
Detector Upgrade
|
||||||
@ -93,8 +86,6 @@ This document describes the differences between v9.2.0 and v9.1.1
|
|||||||
Gotthard2 via command <.rbf>
|
Gotthard2 via command <.rbf>
|
||||||
Moench via command <.pof>
|
Moench via command <.pof>
|
||||||
|
|
||||||
Gotthard cannot be upgraded remotely
|
|
||||||
|
|
||||||
Except Eiger,
|
Except Eiger,
|
||||||
upgrade
|
upgrade
|
||||||
Using command 'programfpga' or
|
Using command 'programfpga' or
|
||||||
@ -215,4 +206,3 @@ This document describes the differences between v9.2.0 and v9.1.1
|
|||||||
|
|
||||||
dhanya.thattil@psi.ch
|
dhanya.thattil@psi.ch
|
||||||
erik.frojdh@psi.ch
|
erik.frojdh@psi.ch
|
||||||
alice.mazzoleni@psi.ch
|
|
||||||
|
@ -28,7 +28,6 @@ requirements:
|
|||||||
- libgl-devel # [linux]
|
- libgl-devel # [linux]
|
||||||
- libtiff
|
- libtiff
|
||||||
- zlib
|
- zlib
|
||||||
- expat
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
- libstdcxx-ng
|
- libstdcxx-ng
|
||||||
|
@ -40,6 +40,7 @@ set(SPHINX_SOURCE_FILES
|
|||||||
src/pydetector.rst
|
src/pydetector.rst
|
||||||
src/pyenums.rst
|
src/pyenums.rst
|
||||||
src/pyexamples.rst
|
src/pyexamples.rst
|
||||||
|
src/pyPatternGenerator.rst
|
||||||
src/servers.rst
|
src/servers.rst
|
||||||
src/receiver_api.rst
|
src/receiver_api.rst
|
||||||
src/result.rst
|
src/result.rst
|
||||||
@ -53,6 +54,7 @@ set(SPHINX_SOURCE_FILES
|
|||||||
src/serverdefaults.rst
|
src/serverdefaults.rst
|
||||||
src/quick_start_guide.rst
|
src/quick_start_guide.rst
|
||||||
src/troubleshooting.rst
|
src/troubleshooting.rst
|
||||||
|
src/pattern.rst
|
||||||
src/receivers.rst
|
src/receivers.rst
|
||||||
src/slsreceiver.rst
|
src/slsreceiver.rst
|
||||||
src/udpheader.rst
|
src/udpheader.rst
|
||||||
|
@ -21,7 +21,7 @@ print('\n\n\n\n SERVER CSV')
|
|||||||
|
|
||||||
src = Path('@CMAKE_SOURCE_DIR@')/'slsDetectorServers/'
|
src = Path('@CMAKE_SOURCE_DIR@')/'slsDetectorServers/'
|
||||||
detectors = ['Mythen3', 'Gotthard2', 'Eiger',
|
detectors = ['Mythen3', 'Gotthard2', 'Eiger',
|
||||||
'Jungfrau', 'Moench', 'Gotthard', 'Ctb']
|
'Jungfrau', 'Moench', 'Ctb']
|
||||||
|
|
||||||
|
|
||||||
for det in detectors:
|
for det in detectors:
|
||||||
|
@ -320,61 +320,6 @@ Moench
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gotthard I
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
{
|
|
||||||
"Version": 7.2,
|
|
||||||
"Timestamp": "Wed Nov 13 15:16:19 2024",
|
|
||||||
"Detector Type": "Gotthard",
|
|
||||||
"Timing Mode": "auto",
|
|
||||||
"Geometry": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"Image Size in bytes": 2560,
|
|
||||||
"Pixels": {
|
|
||||||
"x": 1280,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"Max Frames Per File": 20000,
|
|
||||||
"Frame Discard Policy": "nodiscard",
|
|
||||||
"Frame Padding": 1,
|
|
||||||
"Scan Parameters": "[disabled]",
|
|
||||||
"Total Frames": 1,
|
|
||||||
"Receiver Roi": {
|
|
||||||
"xmin": 4294967295,
|
|
||||||
"xmax": 4294967295,
|
|
||||||
"ymin": 4294967295,
|
|
||||||
"ymax": 4294967295
|
|
||||||
},
|
|
||||||
"Exptime": "1.00001ms",
|
|
||||||
"Period": "1s",
|
|
||||||
"Detector Roi": {
|
|
||||||
"xmin": 4294967295,
|
|
||||||
"xmax": 4294967295
|
|
||||||
},
|
|
||||||
"Frames in File": 1,
|
|
||||||
"Frame Header Format": {
|
|
||||||
"Frame Number": "8 bytes",
|
|
||||||
"SubFrame Number/ExpLength": "4 bytes",
|
|
||||||
"Packet Number": "4 bytes",
|
|
||||||
"Bunch ID": "8 bytes",
|
|
||||||
"Timestamp": "8 bytes",
|
|
||||||
"Module Id": "2 bytes",
|
|
||||||
"Row": "2 bytes",
|
|
||||||
"Column": "2 bytes",
|
|
||||||
"Reserved": "2 bytes",
|
|
||||||
"Debug": "4 bytes",
|
|
||||||
"Round Robin Number": "2 bytes",
|
|
||||||
"Detector Type": "1 byte",
|
|
||||||
"Header Version": "1 byte",
|
|
||||||
"Packets Caught Mask": "64 bytes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Chip Test Board
|
Chip Test Board
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@ -414,6 +359,7 @@ Chip Test Board
|
|||||||
"Digital Flag": 0,
|
"Digital Flag": 0,
|
||||||
"Digital Samples": 1000,
|
"Digital Samples": 1000,
|
||||||
"Dbit Offset": 0,
|
"Dbit Offset": 0,
|
||||||
|
"Dbit Reorder": 1,
|
||||||
"Dbit Bitset": 0,
|
"Dbit Bitset": 0,
|
||||||
"Transceiver Mask": "0x3",
|
"Transceiver Mask": "0x3",
|
||||||
"Transceiver Flag": 0,
|
"Transceiver Flag": 0,
|
||||||
|
@ -131,42 +131,6 @@ Program from console
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Gotthard I
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Download
|
|
||||||
^^^^^^^^^^^^^
|
|
||||||
- detector server corresponding to package in slsDetectorPackage/serverBin
|
|
||||||
|
|
||||||
- `pof files <https://github.com/slsdetectorgroup/slsDetectorFirmware>`__
|
|
||||||
|
|
||||||
|
|
||||||
.. _firmware upgrade using blaster for blackfin:
|
|
||||||
|
|
||||||
Upgrade
|
|
||||||
^^^^^^^^
|
|
||||||
.. warning ::
|
|
||||||
| Gotthard firmware cannot be upgraded remotely and requires the use of USB-Blaster.
|
|
||||||
| It is generally updated by us.
|
|
||||||
|
|
||||||
#. Download `Altera Quartus software or Quartus programmer <https://fpgasoftware.intel.com/20.1/?edition=standard&platform=linux&product=qprogrammer#tabs-4>`__.
|
|
||||||
|
|
||||||
|
|
||||||
#. Start Quartus programmer, click on Hardware Setup. In the "Currently selected hardware" window, select USB-Blaster.
|
|
||||||
|
|
||||||
#. In the Mode combo box, select "Active Serial Programming".
|
|
||||||
|
|
||||||
#. Plug the end of your USB-Blaster with the adaptor provided to the connector 'AS config' on the Gotthard board.
|
|
||||||
|
|
||||||
#. Click on 'Add file'. Select programming (pof) file provided by us.
|
|
||||||
|
|
||||||
#. Check "Program/Configure" and "Verify". Push the start button. Wait until the programming process is finished.
|
|
||||||
|
|
||||||
#. In case of error messages, check the polarity of cable (that pin1 corresponds) and that the correct programming connector is selected.
|
|
||||||
|
|
||||||
#. Reboot the detector.
|
|
||||||
|
|
||||||
|
|
||||||
Mythen III
|
Mythen III
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@ -396,7 +360,3 @@ How to get back mtd3 drive remotely (udpating kernel)
|
|||||||
more /proc/mtd # verify mtd3 is listed
|
more /proc/mtd # verify mtd3 is listed
|
||||||
|
|
||||||
|
|
||||||
Last Resort using USB Blaster
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
If none of these steps work, the last resort might be physically upgrading the firmware using a USB blaster, which also requires opening up the detector. Instructions for all the blackfin detectors are the same as the one for :ref:`gotthard firmware upgrade <firmware upgrade using blaster for blackfin>`.
|
|
@ -36,6 +36,8 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
pydetector
|
pydetector
|
||||||
pyenums
|
pyenums
|
||||||
pyexamples
|
pyexamples
|
||||||
|
pyPatternGenerator
|
||||||
|
pattern
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Command line
|
:caption: Command line
|
||||||
@ -79,9 +81,8 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
:caption: Receiver
|
:caption: Receiver
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
slsreceiver
|
|
||||||
receivers
|
receivers
|
||||||
|
slsreceiver
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Receiver Files
|
:caption: Receiver Files
|
||||||
|
@ -6,33 +6,18 @@
|
|||||||
Installation
|
Installation
|
||||||
===============
|
===============
|
||||||
|
|
||||||
.. contents::
|
One can either install pre-built binaries using conda or build from source.
|
||||||
:local:
|
|
||||||
:depth: 2
|
|
||||||
:backlinks: top
|
|
||||||
|
|
||||||
|
.. warning ::
|
||||||
|
|
||||||
Overview
|
Before building from source make sure that you have the
|
||||||
--------------
|
:doc:`dependencies <../dependencies>` installed. If installing using conda, conda will
|
||||||
|
manage the dependencies. Avoid also installing packages with pip.
|
||||||
The ``slsDetectorPackage`` provides core detector software implemented in C++, along with Python bindings packaged as the ``slsdet`` Python extension module. Choose the option that best fits your environment and use case.
|
|
||||||
|
|
||||||
:ref:`conda pre-built binaries`:
|
|
||||||
Install pre-built binaries for the C++ client, receiver, GUI and the Python API (``slsdet``), simplifying setup across platforms.
|
|
||||||
|
|
||||||
:ref:`pip`:
|
|
||||||
Install only the Python extension module, either by downloading the pre-built library from PyPI or by building the extension locally from source. Available only from v9.2.0 onwards.
|
|
||||||
|
|
||||||
:ref:`build from source`:
|
|
||||||
Compile the entire package yourself, including both the C++ core and the Python bindings, for maximum control and customization. However, make sure that you have the :doc:`dependencies <../dependencies>` installed. If installing using conda, conda will manage the dependencies. Avoid installing packages with pip and conda simultaneously.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Install binaries using conda
|
||||||
.. _conda pre-built binaries:
|
----------------------------------
|
||||||
|
|
||||||
1. Install pre-built binaries using conda (Recommended)
|
|
||||||
--------------------------------------------------------
|
|
||||||
|
|
||||||
Conda is not only useful to manage python environments but can also
|
Conda is not only useful to manage python environments but can also
|
||||||
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
||||||
@ -78,29 +63,12 @@ We have four different packages available:
|
|||||||
conda search moenchzmq
|
conda search moenchzmq
|
||||||
|
|
||||||
|
|
||||||
.. _pip:
|
|
||||||
|
|
||||||
2. Pip
|
|
||||||
-------
|
|
||||||
The Python extension module ``slsdet`` can be installed using pip. This is available from v9.2.0 onwards.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
#Install the Python extension module from PyPI
|
|
||||||
pip install slsdet
|
|
||||||
|
|
||||||
# or install the python extension locally from source
|
|
||||||
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 9.2.0
|
|
||||||
cd slsDetectorPackage
|
|
||||||
pip install .
|
|
||||||
|
|
||||||
|
|
||||||
.. _build from source:
|
Build from source
|
||||||
|
----------------------
|
||||||
|
|
||||||
3. Build from source
|
1. Download Source Code from github
|
||||||
-------------------------
|
|
||||||
|
|
||||||
3.1. Download Source Code from github
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -115,12 +83,12 @@ The Python extension module ``slsdet`` can be installed using pip. This is avail
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.2. Build from Source
|
2. Build from Source
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
One can either build using cmake or use the in-built cmk.sh script.
|
One can either build using cmake or use the in-built cmk.sh script.
|
||||||
|
|
||||||
3.2.1. Build using CMake
|
Build using CMake
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -167,7 +135,7 @@ Example cmake options Comment
|
|||||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||||
|
|
||||||
|
|
||||||
3.2.2. Build using in-built cmk.sh script
|
Build using in-built cmk.sh script
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
@ -217,8 +185,8 @@ Example cmake options Comment
|
|||||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||||
|
|
||||||
|
|
||||||
3.3. Build on old distributions using conda
|
Build on old distributions
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||||
@ -242,7 +210,7 @@ using this compiler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.4. Build slsDetectorGui (Qt5)
|
Build slsDetectorGui (Qt5)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
1. Using pre-built binary on conda
|
1. Using pre-built binary on conda
|
||||||
@ -303,7 +271,7 @@ using this compiler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.5. Build this documentation
|
Build this documentation
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The documentation for the slsDetectorPackage is build using a combination
|
The documentation for the slsDetectorPackage is build using a combination
|
||||||
@ -326,8 +294,8 @@ is to use conda
|
|||||||
make rst # rst only, saves time in case the API did not change
|
make rst # rst only, saves time in case the API did not change
|
||||||
|
|
||||||
|
|
||||||
4. Pybind and Zeromq
|
Pybind and Zeromq
|
||||||
-------------------------
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. _pybind for different slsDetectorPackage versions:
|
.. _pybind for different slsDetectorPackage versions:
|
||||||
|
|
||||||
|
@ -288,56 +288,6 @@ Moench
|
|||||||
| Frame Header Format | Expected frame header format for the data files |
|
| Frame Header Format | Expected frame header format for the data files |
|
||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
|
|
||||||
Gotthard I
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| **Key** | **Description** |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Version | Version of the master file |
|
|
||||||
| | Current value:8.0 |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Timestamp | Timestamp of creation of master file |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Detector Type | Detector type |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Timing Mode | Timing Mode |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Geometry | Number of UDP ports in x and y dimension for |
|
|
||||||
| | complete detector |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Image Size in bytes | Image size in bytes per UDP port |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Pixels | Number of pixels in x and y dimension |
|
|
||||||
| | per UDP port |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Max Frames Per File | Maximum frames per file |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Frame Discard Policy | Receiever Frame discard policy |
|
|
||||||
| | for partial frames |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Frame Padding | Receiver Frame padding enable |
|
|
||||||
| | for partial frames |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Scan Parameters | Scanning mode on detector |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Total Frames | Total number of frames and triggers expected |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Exptime | Exposure time |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Period | Period between frames |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Detector Roi | Roi in detector restricted to an ADC. |
|
|
||||||
| | Includes xmax |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Burst Mode | Burst mode of detector |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
| Frame Header Format | Expected frame header format for the data files |
|
|
||||||
+-----------------------+-------------------------------------------------+
|
|
||||||
|
|
||||||
Chip Test Board
|
Chip Test Board
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
@ -395,6 +345,9 @@ Chip Test Board
|
|||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
| Dbit Offset | Digital offset of valid data in bytes |
|
| Dbit Offset | Digital offset of valid data in bytes |
|
||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
|
| Dbit Reorder | Reorder such that it groups each signal (0-63) |
|
||||||
|
| | from all the different samples together |
|
||||||
|
+-----------------------+-------------------------------------------------+
|
||||||
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
||||||
|
122
docs/src/pattern.rst
Normal file
122
docs/src/pattern.rst
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
Pattern
|
||||||
|
========================
|
||||||
|
|
||||||
|
This is a test and development feature implemented only for Ctb, Xilinx_Ctb and Mythen3.
|
||||||
|
|
||||||
|
A pattern is a sequence of 64-bit words which is executed using a clock on the FPGA. Each of the 64 bits is connected to a pin or internal signal of the FPGA. The purpose of a pattern is to provide a way to change these 64 signals with precise timing. Commands run by the detector server could manipulate the same signals as the pattern, but they cannot enforce a change in a specific clock cycle.
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
A pattern is written to memory on the FPGA using the patword command.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
patword 0x0000 0x000000000000000A
|
||||||
|
patword 0x0001 0x000000000000000B
|
||||||
|
patword 0x0002 0x000000000000000C
|
||||||
|
patword 0x0003 0x000000000000000D
|
||||||
|
patword 0x0004 0x000000000000000E
|
||||||
|
|
||||||
|
The example above writes a five-word pattern into FPGA memory. The first argument is the memory address, the second argument is the content to be written into this address. Before executing a pattern one has to set the address limits of the pattern:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
patlimits 0x0000 0x0004
|
||||||
|
|
||||||
|
This instructs the firmware to execute the commands from address 0 to 4 (including 0 and 4). The execution can be started from the pyctbgui or with the commands
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
start [Ctb, Xilinx_Ctb]
|
||||||
|
patternstart [Mythen3]
|
||||||
|
|
||||||
|
The maximal number of patword addresses is 8192. However, it is possible to extend the length of the pattern sequence using loops and wait commands. Loops can be configured with the following commands:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
patloop 0 0x0001 0x0003
|
||||||
|
patnloop 0 7
|
||||||
|
|
||||||
|
The first argument of both commands is the ID of the loop. Ctb and Xilinx_Ctb can have 6 loops (ID 0-5), Mythen3 can have 4 loop definitions. The commands above configure the loop with ID 0 to run 7 times and jump from the patword with address 3 to the patword with address 1. Important: If patnloop is set to 1, the addresses 0x1-0x3 will execute exactly once; if it is set to 0, the pattern addresses will be skipped.
|
||||||
|
|
||||||
|
The same idea is used to introduce wait times. The example below causes the patword at address 0x0002 to be active for 9 clock cycles before the execution continues.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
patwait 0 0x0002
|
||||||
|
patwaittime 0 9
|
||||||
|
|
||||||
|
Waits can be placed inside a loop and loops can be nested.
|
||||||
|
|
||||||
|
**patioctrl**
|
||||||
|
|
||||||
|
The function of each bit in the sequence of 64-bit words depends on the connected detector and firmware version. Some of the 64 bits might connect directly to pads of a chip. The patioctrl command is used to configure the direction of some of these signals (not all of them !! See tables below). Signals where the corresponding bit in the argument of patioctrl is set to 1 will be driven from the FPGA.
|
||||||
|
|
||||||
|
**patsetbit and patmask**
|
||||||
|
|
||||||
|
The functions patsetbit and patmask can be used to ignore a specific bit of the pattern.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
patmask 0x0101
|
||||||
|
patsetbit 0x0001
|
||||||
|
|
||||||
|
Patmask configures bit 0 and 8 of the pattern to be set to their value in patsetbit. These bits will be ignored during pattern execution and will always be 0 (bit 8) and 1 (bit 0).
|
||||||
|
|
||||||
|
The mappings of bit positions in the pattern word to signals/pads of the FPGA are listed below for the three detector types where patterns are used. In the case of the two CTB's, connections of the signals to actual pads of a chip depend on the layout of the used detector adapter board. Therefore, each type of detector adapter board adds an additional mapping layer.
|
||||||
|
|
||||||
|
**CTB Pattern Bit Mapping**
|
||||||
|
|
||||||
|
.. table::
|
||||||
|
|
||||||
|
+----+---+------+----+----------+-------------------+----------------+
|
||||||
|
| 63 | 62| 61-57| 56 | 55-48 | 47-32 | 31-0 |
|
||||||
|
+----+---+------+----+----------+-------------------+----------------+
|
||||||
|
| A | D| --- | T | EXTIO | DO, stream source | DIO |
|
||||||
|
+----+---+------+----+----------+-------------------+----------------+
|
||||||
|
|
||||||
|
DIO: Driving the 32 FPGA pins corresponding to the lowest 32 bits of the patioctrl command. If bits in patioctrl are 0, the same bit positions in DIO will switch to input pins and connect to dbit sampling. Additionally, some of these 32 bits have an automatic override by detector-specific statemachines which is active whenever one of these statemachines is running (currently bits 7,8,11,14 and 20).
|
||||||
|
|
||||||
|
DO: Directly connected to 16 FPGA pins. Output only. Not influenced by patioctrl. Also connected to bit 47-32 in all Ctb dbit samples. All of them can be used as dbit sample trigger. In addition, every bit of DO can be selected as trigger for sending out a udp packet with samples to the receiver.
|
||||||
|
|
||||||
|
EXTIO: Similar to DIO, but not used as input to the fpga. With the corresponding patioctrl bits set to 0 these pins will switch to a high impedance mode and be ignored by the firmware.
|
||||||
|
|
||||||
|
T: trigger output
|
||||||
|
|
||||||
|
D: enable signal for digital sampling
|
||||||
|
|
||||||
|
A: adc enable
|
||||||
|
|
||||||
|
**Xilinx_CTB Pattern Bit Mapping**
|
||||||
|
|
||||||
|
.. table::
|
||||||
|
|
||||||
|
+-------+----------------+
|
||||||
|
| 63-32 | 31-0 |
|
||||||
|
+-------+----------------+
|
||||||
|
| --- | DIO |
|
||||||
|
+-------+----------------+
|
||||||
|
|
||||||
|
DIO: Driving the 32 FPGA pins corresponding to the lowest 32 bits of the patioctrl command. If bits in patioctrl are 0, the same bit positions in DIO will switch to input pins and connect to dbit sampling. Additionally, some of these 32 bits have an automatic override by detector-specific statemachines which is active whenever these sm's are running (currently bits 7,8,11,14 and 20).
|
||||||
|
|
||||||
|
|
||||||
|
**Mythen3 Pattern Bit Mapping**
|
||||||
|
|
||||||
|
.. table::
|
||||||
|
|
||||||
|
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||||
|
| 63-33 | 32 | 31-25 | 24 | 23 | 22 | 21 | 20 | 19 |
|
||||||
|
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||||
|
| --- | signARD| --- | CHSclk | cnt_rst | sto_rst | STATLOAD | STO | SIN |
|
||||||
|
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||||
|
|
||||||
|
.. table::
|
||||||
|
|
||||||
|
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||||
|
| 18 | 17 | 16-14 | 13 | 12 | 11 | 10 | 9-0 |
|
||||||
|
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||||
|
| SR_MODE | clk | EN | PULSE | RD | CHSIN | ANAMode | TBLOAD |
|
||||||
|
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||||
|
|
||||||
|
For Mythen3 the pattern word only connects to output pins of the FPGA when the pattern is running. Afterwards the signals will switch back to other logic in the FPGA. Both CTB's hold the last executed pattern word until a new pattern is started.
|
34
docs/src/pyPatternGenerator.rst
Normal file
34
docs/src/pyPatternGenerator.rst
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
PatternGenerator
|
||||||
|
=====================================================
|
||||||
|
|
||||||
|
Python class to generate patterns for the Chip Test Board.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import PatternGenerator
|
||||||
|
|
||||||
|
p = PatternGenerator()
|
||||||
|
p.SB(5)
|
||||||
|
p.PW()
|
||||||
|
p.SB(8,9)
|
||||||
|
p.PW()
|
||||||
|
p.CB(5)
|
||||||
|
|
||||||
|
Created a pattern like this:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
patword 0x0000 0x0000000000000020
|
||||||
|
patword 0x0001 0x0000000000000320
|
||||||
|
patword 0x0002 0x0000000000000300
|
||||||
|
patioctrl 0x0000000000000000
|
||||||
|
patlimits 0x0000 0x0002
|
||||||
|
...
|
||||||
|
|
||||||
|
.. py:currentmodule:: slsdet
|
||||||
|
|
||||||
|
.. autoclass:: PatternGenerator
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
:inherited-members:
|
@ -1,25 +1,25 @@
|
|||||||
Custom Receiver
|
Receivers
|
||||||
=================
|
=================
|
||||||
|
|
||||||
The receiver essentially listens to UDP data packets sent out by the detector.
|
Receiver processes can be run on same or different machines as the client, receives the data from the detector (via UDP packets).
|
||||||
|
When using the slsReceiver/ slsMultiReceiver, they can be further configured by the client control software (via TCP/IP) to set file name, file path, progress of acquisition etc.
|
||||||
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
|
||||||
|
|
||||||
|
|
||||||
| Please note the following when using a custom receiver:
|
To know more about detector receiver configuration, please check out :ref:`detector udp header and udp commands in the config file <detector udp header>`
|
||||||
|
|
||||||
* **udp_dstmac** must be configured in the config file. This parameter is not required when using an in-built receiver.
|
Custom Receiver
|
||||||
|
----------------
|
||||||
|
|
||||||
* Cannot use "auto" for **udp_dstip**.
|
| When using custom receiver with our package, ensure that **udp_dstmac** is also configured in the config file. This parameter is not required when using slsReceiver.
|
||||||
|
|
||||||
* No **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
| Cannot use "auto" for **udp_dstip**.
|
||||||
|
|
||||||
|
| Also ensure that there are no **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
||||||
|
|
||||||
The main difference is the lack of **rx_** commands or file commands (eg. **f**write, **f**path) and the **udp_dstmac** is required in config file.
|
|
||||||
|
|
||||||
Example of a custom receiver config file
|
Example of a custom receiver config file
|
||||||
|
|
||||||
|
* The main difference is the lack of **rx_** commands or file commands (eg. fwrite, fpath) and the udp_dstmac is required in config file.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# detector hostname
|
# detector hostname
|
||||||
|
@ -89,18 +89,3 @@ DACS
|
|||||||
:widths: 35, 35
|
:widths: 35, 35
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
||||||
Gotthard
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. csv-table:: Default values
|
|
||||||
:file: gotthard.csv
|
|
||||||
:widths: 35, 35
|
|
||||||
:header-rows: 1
|
|
||||||
|
|
||||||
DACS
|
|
||||||
^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. csv-table:: Gotthard DACS
|
|
||||||
:file: gotthard-dacs.csv
|
|
||||||
:widths: 35, 35
|
|
||||||
:header-rows: 1
|
|
@ -27,12 +27,11 @@ Arguments
|
|||||||
-p, --port <port> : TCP communication port with client.
|
-p, --port <port> : TCP communication port with client.
|
||||||
-g, --nomodule : [Mythen3][Gotthard2]
|
-g, --nomodule : [Mythen3][Gotthard2]
|
||||||
Generic or No Module mode. Skips detector type checks.
|
Generic or No Module mode. Skips detector type checks.
|
||||||
-f, --phaseshift <value> : [Gotthard] only. Sets phase shift.
|
|
||||||
-d, --devel : Developer mode. Skips firmware checks.
|
-d, --devel : Developer mode. Skips firmware checks.
|
||||||
-u, --update : Update mode. Skips firmware checks and initial detector setup.
|
-u, --update : Update mode. Skips firmware checks and initial detector setup.
|
||||||
-i, --ignore-config : [Eiger][Jungfrau][Gotthard][Gotthard2][Moench]
|
-i, --ignore-config : [Eiger][Jungfrau][Gotthard2][Moench]
|
||||||
Ignore config file.
|
Ignore config file.
|
||||||
-m, --master <master> : [Eiger][Mythen3][Gotthard][Gotthard2]
|
-m, --master <master> : [Eiger][Mythen3][Gotthard2]
|
||||||
Set Master to 0 or 1. Precedence over config file. Only for virtual servers except Eiger.
|
Set Master to 0 or 1. Precedence over config file. Only for virtual servers except Eiger.
|
||||||
-t, --top <top> : [Eiger] Set Top to 0 or 1. Precedence over config file.
|
-t, --top <top> : [Eiger] Set Top to 0 or 1. Precedence over config file.
|
||||||
-s, --stopserver : Stop server. Do not use as it is created by control server
|
-s, --stopserver : Stop server. Do not use as it is created by control server
|
||||||
@ -65,7 +64,7 @@ One can start the on-board detector server automatically upon powering on the bo
|
|||||||
/home/root/executables/eigerDetectorServer &> /dev/null &
|
/home/root/executables/eigerDetectorServer &> /dev/null &
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
Jungfrau | Moench | CTB | Gotthard I
|
Jungfrau | Moench | CTB
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# Edit inittab on board
|
# Edit inittab on board
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
.. _Detector Server Upgrade:
|
.. _Detector Server Upgrade:
|
||||||
|
|
||||||
Upgrade
|
Upgrade
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -1,55 +1,16 @@
|
|||||||
In-built Receiver
|
slsReceiver/ slsMultiReceiver
|
||||||
================================
|
================================
|
||||||
|
|
||||||
|
| One has to start the slsReceiver before loading config file or using any receiver commands (prefix: **rx_** )
|
||||||
|
|
||||||
|
|
||||||
The receiver essentially listens to UDP data packets sent out by the detector. It's main features are:
|
|
||||||
|
|
||||||
- **Listening**: Receives UDP data from the detector.
|
|
||||||
- **Writing to File**: Optionally writes received data to disk.
|
|
||||||
- **Streaming via ZMQ**: Optionally streams out the data using ZeroMQ.
|
|
||||||
|
|
||||||
Each of these operations runs asynchronously and in parallel for each UDP port.
|
|
||||||
|
|
||||||
|
|
||||||
.. note ::
|
|
||||||
|
|
||||||
* Can be run on the same or different machine as the client.
|
|
||||||
* Can be configured by the client. (set file name/ discard policy, get progress etc.)
|
|
||||||
* Has to be started before the client runs any receiver specific command.
|
|
||||||
|
|
||||||
|
|
||||||
Receiver Variants
|
|
||||||
-----------------
|
|
||||||
There are three main receiver types. How to start them is described :ref:`below<Starting up the Receiver>`.
|
|
||||||
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
| Receiver Type | slsReceiver | slsMultiReceiver |slsFrameSynchronizer |
|
|
||||||
+======================+====================+=========================================+================================+
|
|
||||||
| Modules Supported | 1 | Multiple | Multiple |
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
| Internal Architecture| Threads per porttt | Multiple child processes of slsReceiver | Multi-threading of slsReceiver |
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
| ZMQ Streaming | Disabled by default| Disabled by default | Enabled, not optional |
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
| ZMQ Synchronization | No | No | Yes, across ports |
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
| Image Reconstruction | No | No | No |
|
|
||||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _Starting up the Receiver:
|
|
||||||
|
|
||||||
Starting up the Receiver
|
|
||||||
-------------------------
|
|
||||||
For a Single Module
|
For a Single Module
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
slsReceiver # default port 1954
|
# default port 1954
|
||||||
|
slsReceiver
|
||||||
|
|
||||||
slsReceiver -t2012 # custom port 2012
|
# custom port 2012
|
||||||
|
slsReceiver -t2012
|
||||||
|
|
||||||
|
|
||||||
For Multiple Modules
|
For Multiple Modules
|
||||||
@ -57,66 +18,57 @@ For Multiple Modules
|
|||||||
|
|
||||||
# each receiver (for each module) requires a unique tcp port (if all on same machine)
|
# each receiver (for each module) requires a unique tcp port (if all on same machine)
|
||||||
|
|
||||||
# option 1 (one for each module)
|
# using slsReceiver in multiple consoles
|
||||||
slsReceiver
|
slsReceiver
|
||||||
slsReceiver -t1955
|
slsReceiver -t1955
|
||||||
|
|
||||||
# option 2
|
# slsMultiReceiver [starting port] [number of receivers]
|
||||||
slsMultiReceiver 2012 2
|
slsMultiReceiver 2012 2
|
||||||
|
|
||||||
# option 3
|
# slsMultiReceiver [starting port] [number of receivers] [print each frame header for debugging]
|
||||||
slsFrameSynchronizer 2012 2
|
slsMultiReceiver 2012 2 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Client Commands
|
Client Commands
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
* Client commands to the receiver begin with **rx_** or **f_** (file commands).
|
| One can remove **udp_dstmac** from the config file, as the slsReceiver fetches this from the **udp_ip**.
|
||||||
|
|
||||||
* **rx_hostname** has to be the first command to the receiver so the client knows which receiver process to communicate with.
|
| One can use "auto" for **udp_dstip** if one wants to use default ip of **rx_hostname**.
|
||||||
|
|
||||||
* Can use 'auto' for **udp_dstip** if using 1GbE interface or the :ref:`virtual simulators<Virtual Detector Servers>`.
|
| The first command to the receiver (**rx_** commands) should be **rx_hostname**. The following are the different ways to establish contact.
|
||||||
|
|
||||||
|
|
||||||
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
|
||||||
|
|
||||||
|
|
||||||
The following are the different ways to establish contact using **rx_hostname** command.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# ---single module---
|
# default receiver tcp port (1954)
|
||||||
|
|
||||||
# default receiver port at 1954
|
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# custom receiver port
|
# custom receiver port
|
||||||
rx_hostname xxx:1957 # option 1
|
rx_hostname xxx:1957
|
||||||
|
|
||||||
rx_tcpport 1957 # option 2
|
# custom receiver port
|
||||||
|
rx_tcpport 1954
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
|
# multi modules with custom ports
|
||||||
|
rx_hostname xxx:1955+xxx:1956+
|
||||||
|
|
||||||
# ---multi module---
|
|
||||||
|
|
||||||
# using increasing tcp ports
|
# multi modules using increasing tcp ports when using multi detector command
|
||||||
rx_tcpport 1955
|
rx_tcpport 1955
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# custom ports
|
# or specify multi modules with custom ports on same rxr pc
|
||||||
rx_hostname xxx:1955+xxx:1958+ # option 1
|
0:rx_tcpport 1954
|
||||||
|
|
||||||
0:rx_tcpport 1954 # option 2
|
|
||||||
1:rx_tcpport 1955
|
1:rx_tcpport 1955
|
||||||
2:rx_tcpport 1956
|
2:rx_tcpport 1956
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# custom ports on different receiver machines
|
# multi modules with custom ports on different rxr pc
|
||||||
0:rx_tcpport 1954
|
0:rx_tcpport 1954
|
||||||
0:rx_hostname xxx
|
0:rx_hostname xxx
|
||||||
1:rx_tcpport 1955
|
1:rx_tcpport 1955
|
||||||
1:rx_hostname yyyrxr
|
1:rx_hostname yyy
|
||||||
|
|
||||||
|
|
||||||
| Example commands:
|
| Example commands:
|
||||||
@ -139,32 +91,6 @@ The following are the different ways to establish contact using **rx_hostname**
|
|||||||
sls_detector_get -h rx_framescaught
|
sls_detector_get -h rx_framescaught
|
||||||
|
|
||||||
|
|
||||||
Example of a config file using in-built receiver
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
# detector hostname
|
|
||||||
hostname bchip052+bchip053+
|
|
||||||
|
|
||||||
# udp destination port (receiver)
|
|
||||||
# sets increasing destination udp ports starting at 50004
|
|
||||||
udp_dstport 50004
|
|
||||||
|
|
||||||
# udp destination ip (receiver)
|
|
||||||
0:udp_dstip 10.0.1.100
|
|
||||||
1:udp_dstip 10.0.2.100
|
|
||||||
|
|
||||||
# udp source ip (same subnet as udp_dstip)
|
|
||||||
0:udp_srcip 10.0.1.184
|
|
||||||
1:udp_srcip 10.0.2.184
|
|
||||||
|
|
||||||
# udp destination mac - not required (picked up from udp_dstip)
|
|
||||||
#udp_dstmac 22:47:d5:48:ad:ef
|
|
||||||
|
|
||||||
# connects to receivers at increasing tcp port starting at 1954
|
|
||||||
rx_hostname mpc3434
|
|
||||||
# same as rx_hostname mpc3434:1954+mpc3434:1955+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Performance
|
Performance
|
||||||
|
@ -385,14 +385,6 @@ Cannot get data without a module attached
|
|||||||
You cannot get data without a module attached as a specific pin is floating. Attach module to get data.
|
You cannot get data without a module attached as a specific pin is floating. Attach module to get data.
|
||||||
|
|
||||||
|
|
||||||
Gotthard
|
|
||||||
----------
|
|
||||||
|
|
||||||
|
|
||||||
Missing first frame or next frame after a delay
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Connect the data link from the Module directly to receiver pc or to a private network.
|
|
||||||
|
|
||||||
|
|
||||||
Mythen3
|
Mythen3
|
||||||
--------
|
--------
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.. _detector udp header config:
|
.. _detector udp header:
|
||||||
|
|
||||||
|
|
||||||
Config file
|
Config file
|
||||||
|
@ -92,14 +92,14 @@ Detector Enum
|
|||||||
================ ========
|
================ ========
|
||||||
GENERIC 0
|
GENERIC 0
|
||||||
EIGER 1
|
EIGER 1
|
||||||
GOTTHARD 2
|
GOTTHARD* 2
|
||||||
JUNGFRAU 3
|
JUNGFRAU 3
|
||||||
CHIPTESTBOARD 4
|
CHIPTESTBOARD 4
|
||||||
MOENCH 5
|
MOENCH 5
|
||||||
MYTHEN3 6
|
MYTHEN3 6
|
||||||
GOTTHARD2 7
|
GOTTHARD2 7
|
||||||
================ ========
|
================ ========
|
||||||
|
* deprecated since v10.0.0
|
||||||
|
|
||||||
|
|
||||||
Previous Versions
|
Previous Versions
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
.. _Virtual Detector Servers:
|
.. _Virtual Detector Servers:
|
||||||
|
|
||||||
Simulators
|
Simulators
|
||||||
===========
|
===========
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ Binaries
|
|||||||
|
|
||||||
eigerDetectorServer_virtual
|
eigerDetectorServer_virtual
|
||||||
jungfrauDetectorServer_virtual
|
jungfrauDetectorServer_virtual
|
||||||
gotthardDetectorServer_virtual
|
|
||||||
gotthard2DetectorServer_virtual
|
gotthard2DetectorServer_virtual
|
||||||
mythen3DetectorServer_virtual
|
mythen3DetectorServer_virtual
|
||||||
moenchDetectorServer_virtual
|
moenchDetectorServer_virtual
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
# detector hostname
|
|
||||||
hostname bchip007
|
|
||||||
|
|
||||||
# receiver pc hostname of 1Gb IP of the machine
|
|
||||||
rx_hostname my_receiver_hostname
|
|
||||||
|
|
||||||
# output directory
|
|
||||||
fpath /bigRAID/datadir_gotthard/rec_test_data
|
|
||||||
|
|
||||||
# high voltage
|
|
||||||
highvoltage 120
|
|
||||||
|
|
@ -12,5 +12,6 @@ slsDetectorPackage/8.0.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
|||||||
slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||||
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
|
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
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
|
|||||||
from pyctbgui.utils.defines import Defines
|
from pyctbgui.utils.defines import Defines
|
||||||
from pyctbgui.utils.plotPattern import PlotPattern
|
from pyctbgui.utils.plotPattern import PlotPattern
|
||||||
|
|
||||||
|
from slsdet import DurationWrapper
|
||||||
|
|
||||||
class PatternTab(QtWidgets.QWidget):
|
class PatternTab(QtWidgets.QWidget):
|
||||||
|
|
||||||
@ -61,7 +62,10 @@ class PatternTab(QtWidgets.QWidget):
|
|||||||
getattr(self.view, f"lineEditLoop{i}Wait").editingFinished.connect(partial(self.setPatLoopWaitAddress, i))
|
getattr(self.view, f"lineEditLoop{i}Wait").editingFinished.connect(partial(self.setPatLoopWaitAddress, i))
|
||||||
getattr(self.view,
|
getattr(self.view,
|
||||||
f"spinBoxLoop{i}Repetition").editingFinished.connect(partial(self.setPatLoopRepetition, i))
|
f"spinBoxLoop{i}Repetition").editingFinished.connect(partial(self.setPatLoopRepetition, i))
|
||||||
getattr(self.view, f"spinBoxLoop{i}WaitTime").editingFinished.connect(partial(self.setPatLoopWaitTime, i))
|
getattr(self.view, f"doubleSpinBoxLoop{i}WaitClocks").editingFinished.connect(partial(self.setPatLoopWaitClocks, i))
|
||||||
|
getattr(self.view, f"spinBoxLoop{i}WaitInterval").editingFinished.connect(partial(self.setPatLoopWaitInterval, i))
|
||||||
|
getattr(self.view, f"comboBoxLoop{i}WaitInterval").currentIndexChanged.connect(partial(self.setPatLoopWaitInterval, i))
|
||||||
|
self.view.toolButtonTogglePageWaitTime.clicked.connect(self.setTogglePageWaitTime)
|
||||||
self.view.pushButtonCompiler.clicked.connect(self.setCompiler)
|
self.view.pushButtonCompiler.clicked.connect(self.setCompiler)
|
||||||
self.view.pushButtonUncompiled.clicked.connect(self.setUncompiledPatternFile)
|
self.view.pushButtonUncompiled.clicked.connect(self.setUncompiledPatternFile)
|
||||||
self.view.pushButtonPatternFile.clicked.connect(self.setPatternFile)
|
self.view.pushButtonPatternFile.clicked.connect(self.setPatternFile)
|
||||||
@ -91,7 +95,8 @@ class PatternTab(QtWidgets.QWidget):
|
|||||||
self.getPatLoopStartStopAddress(i)
|
self.getPatLoopStartStopAddress(i)
|
||||||
self.getPatLoopWaitAddress(i)
|
self.getPatLoopWaitAddress(i)
|
||||||
self.getPatLoopRepetition(i)
|
self.getPatLoopRepetition(i)
|
||||||
self.getPatLoopWaitTime(i)
|
self.getPatLoopWaitClocks(i)
|
||||||
|
self.getPatLoopWaitInterval(i)
|
||||||
|
|
||||||
# Pattern Tab functions
|
# Pattern Tab functions
|
||||||
|
|
||||||
@ -182,17 +187,67 @@ class PatternTab(QtWidgets.QWidget):
|
|||||||
self.det.patnloop[level] = spinBox.value()
|
self.det.patnloop[level] = spinBox.value()
|
||||||
self.getPatLoopRepetition(level)
|
self.getPatLoopRepetition(level)
|
||||||
|
|
||||||
def getPatLoopWaitTime(self, level):
|
def getPatLoopWaitClocks(self, level):
|
||||||
retval = self.det.patwaittime[level]
|
retval = self.det.patwaittime[level]
|
||||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
spinBox = getattr(self.view, f"doubleSpinBoxLoop{level}WaitClocks")
|
||||||
spinBox.editingFinished.disconnect()
|
spinBox.editingFinished.disconnect()
|
||||||
spinBox.setValue(retval)
|
spinBox.setValue(retval)
|
||||||
spinBox.editingFinished.connect(partial(self.setPatLoopWaitTime, level))
|
spinBox.editingFinished.connect(partial(self.setPatLoopWaitClocks, level))
|
||||||
|
|
||||||
|
def setPatLoopWaitClocks(self, level):
|
||||||
|
spinBox = getattr(self.view, f"doubleSpinBoxLoop{level}WaitClocks")
|
||||||
|
self.det.patwaittime[level] = int(spinBox.value())
|
||||||
|
self.getPatLoopWaitClocks(level)
|
||||||
|
|
||||||
|
def getPatLoopWaitInterval(self, level):
|
||||||
|
retval = self.det.getPatternWaitInterval(level)[0].count()
|
||||||
|
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitInterval")
|
||||||
|
comboBox = getattr(self.view, f"comboBoxLoop{level}WaitInterval")
|
||||||
|
spinBox.editingFinished.disconnect()
|
||||||
|
comboBox.currentIndexChanged.disconnect()
|
||||||
|
# Converting to right time unit for period
|
||||||
|
if retval >= 1e9:
|
||||||
|
comboBox.setCurrentIndex(0)
|
||||||
|
spinBox.setValue(retval / 1e9)
|
||||||
|
elif retval >= 1e6:
|
||||||
|
comboBox.setCurrentIndex(1)
|
||||||
|
spinBox.setValue(retval / 1e6)
|
||||||
|
elif retval >= 1e3:
|
||||||
|
comboBox.setCurrentIndex(2)
|
||||||
|
spinBox.setValue(retval / 1e3)
|
||||||
|
else:
|
||||||
|
comboBox.setCurrentIndex(3)
|
||||||
|
spinBox.setValue(retval)
|
||||||
|
spinBox.editingFinished.connect(partial(self.setPatLoopWaitInterval, level))
|
||||||
|
comboBox.currentIndexChanged.connect(partial(self.setPatLoopWaitInterval, level))
|
||||||
|
|
||||||
|
def setPatLoopWaitInterval(self, level):
|
||||||
|
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitInterval")
|
||||||
|
comboBox = getattr(self.view, f"comboBoxLoop{level}WaitInterval")
|
||||||
|
value = spinBox.value()
|
||||||
|
if comboBox.currentIndex() == 0:
|
||||||
|
value *= 1e9
|
||||||
|
elif comboBox.currentIndex() == 1:
|
||||||
|
value *= 1e6
|
||||||
|
elif comboBox.currentIndex() == 2:
|
||||||
|
value *= 1e3
|
||||||
|
t = DurationWrapper()
|
||||||
|
t.set_count(int(value))
|
||||||
|
self.det.patwaittime[level] = t
|
||||||
|
self.getPatLoopWaitInterval(level)
|
||||||
|
|
||||||
|
def setTogglePageWaitTime(self):
|
||||||
|
if self.view.stackedWidgetWaitTime.currentIndex() == 0:
|
||||||
|
self.view.stackedWidgetWaitTime.setCurrentIndex(1)
|
||||||
|
self.view.labelWaitTime.setText("Time")
|
||||||
|
for i in range(Defines.pattern.loops_count):
|
||||||
|
self.getPatLoopWaitInterval(i)
|
||||||
|
else:
|
||||||
|
self.view.stackedWidgetWaitTime.setCurrentIndex(0)
|
||||||
|
self.view.labelWaitTime.setText("Clocks")
|
||||||
|
for i in range(Defines.pattern.loops_count):
|
||||||
|
self.getPatLoopWaitClocks(i)
|
||||||
|
|
||||||
def setPatLoopWaitTime(self, level):
|
|
||||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
|
||||||
self.det.patwaittime[level] = spinBox.value()
|
|
||||||
self.getPatLoopWaitTime(level)
|
|
||||||
|
|
||||||
def setCompiler(self):
|
def setCompiler(self):
|
||||||
response = QtWidgets.QFileDialog.getOpenFileName(
|
response = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
@ -450,7 +505,7 @@ class PatternTab(QtWidgets.QWidget):
|
|||||||
f"{getattr(self.view, f'lineEditLoop{i}Stop').text()}")
|
f"{getattr(self.view, f'lineEditLoop{i}Stop').text()}")
|
||||||
|
|
||||||
commands.append(f"patwait {i} {getattr(self.view, f'lineEditLoop{i}Wait').text()}")
|
commands.append(f"patwait {i} {getattr(self.view, f'lineEditLoop{i}Wait').text()}")
|
||||||
commands.append(f"patwaittime {i} {getattr(self.view, f'spinBoxLoop{i}WaitTime').text()}")
|
commands.append(f"patwaittime {i} {getattr(self.view, f'doubleSpinBoxLoop{i}WaitClocks').text()}")
|
||||||
commands.append(f"patlimits {self.view.lineEditStartAddress.text()}, {self.view.lineEditStopAddress.text()}")
|
commands.append(f"patlimits {self.view.lineEditStartAddress.text()}, {self.view.lineEditStopAddress.text()}")
|
||||||
# commands.append(f"patfname {self.view.lineEditPatternFile.text()}")
|
# commands.append(f"patfname {self.view.lineEditPatternFile.text()}")
|
||||||
return commands
|
return commands
|
||||||
|
@ -22,6 +22,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.plotTab = None
|
self.plotTab = None
|
||||||
self.legend: LegendItem | None = None
|
self.legend: LegendItem | None = None
|
||||||
self.rx_dbitoffset = None
|
self.rx_dbitoffset = None
|
||||||
|
self.rx_dbitreorder = None
|
||||||
self.rx_dbitlist = None
|
self.rx_dbitlist = None
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
@ -29,6 +30,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.updateDigitalBitEnable()
|
self.updateDigitalBitEnable()
|
||||||
self.updateIOOut()
|
self.updateIOOut()
|
||||||
self.getDBitOffset()
|
self.getDBitOffset()
|
||||||
|
self.getDBitReorder()
|
||||||
|
|
||||||
def connect_ui(self):
|
def connect_ui(self):
|
||||||
for i in range(Defines.signals.count):
|
for i in range(Defines.signals.count):
|
||||||
@ -49,6 +51,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.plotTab = self.mainWindow.plotTab
|
self.plotTab = self.mainWindow.plotTab
|
||||||
@ -87,60 +90,79 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.legend.addItem(plot, name)
|
self.legend.addItem(plot, name)
|
||||||
|
|
||||||
@recordOrApplyPedestal
|
@recordOrApplyPedestal
|
||||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitlist, isPlottedArray, rx_dbitoffset, romode,
|
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitreorder, rx_dbitlist, isPlottedArray, romode,
|
||||||
nADCEnabled):
|
nADCEnabled):
|
||||||
"""
|
|
||||||
transform raw waveform data into a processed numpy array
|
|
||||||
@param data: raw waveform data
|
|
||||||
"""
|
|
||||||
dbitoffset = rx_dbitoffset
|
|
||||||
if romode == 2:
|
|
||||||
dbitoffset += nADCEnabled * 2 * aSamples
|
|
||||||
digital_array = np.array(np.frombuffer(data, offset=dbitoffset, dtype=np.uint8))
|
|
||||||
nbitsPerDBit = dSamples
|
|
||||||
if nbitsPerDBit % 8 != 0:
|
|
||||||
nbitsPerDBit += (8 - (dSamples % 8))
|
|
||||||
offset = 0
|
|
||||||
arr = []
|
|
||||||
for i in rx_dbitlist:
|
|
||||||
# where numbits * numsamples is not a multiple of 8
|
|
||||||
if offset % 8 != 0:
|
|
||||||
offset += (8 - (offset % 8))
|
|
||||||
if not isPlottedArray[i]:
|
|
||||||
offset += nbitsPerDBit
|
|
||||||
return None
|
|
||||||
waveform = np.zeros(dSamples)
|
|
||||||
for iSample in range(dSamples):
|
|
||||||
# all samples for digital bit together from slsReceiver
|
|
||||||
index = int(offset / 8)
|
|
||||||
iBit = offset % 8
|
|
||||||
bit = (digital_array[index] >> iBit) & 1
|
|
||||||
waveform[iSample] = bit
|
|
||||||
offset += 1
|
|
||||||
arr.append(waveform)
|
|
||||||
|
|
||||||
return np.array(arr)
|
#transform raw waveform data into a processed numpy array
|
||||||
|
#@param data: raw waveform data
|
||||||
|
|
||||||
|
start_digital_data = 0
|
||||||
|
if romode == 2:
|
||||||
|
start_digital_data += nADCEnabled * 2 * aSamples
|
||||||
|
digital_array = np.array(np.frombuffer(data, offset=start_digital_data, dtype=np.uint8))
|
||||||
|
if rx_dbitreorder:
|
||||||
|
samples_per_bit = np.empty((len(rx_dbitlist), dSamples), dtype=np.uint8) #stored per row all the corresponding signals of all samples
|
||||||
|
nbitsPerDBit = dSamples
|
||||||
|
if nbitsPerDBit % 8 != 0:
|
||||||
|
nbitsPerDBit += (8 - (dSamples % 8))
|
||||||
|
bit_index = 0
|
||||||
|
for idx, i in enumerate(rx_dbitlist):
|
||||||
|
# where numbits * numsamples is not a multiple of 8
|
||||||
|
if bit_index % 8 != 0:
|
||||||
|
bit_index += (8 - (bit_index % 8))
|
||||||
|
if not isPlottedArray[i]:
|
||||||
|
bit_index += nbitsPerDBit
|
||||||
|
samples_per_bit[idx, :] = np.nan
|
||||||
|
continue
|
||||||
|
for iSample in range(dSamples):
|
||||||
|
# all samples for digital bit together from slsReceiver
|
||||||
|
index = int(bit_index / 8)
|
||||||
|
iBit = bit_index % 8
|
||||||
|
bit = (digital_array[index] >> iBit) & 1
|
||||||
|
samples_per_bit[idx,iSample] = bit
|
||||||
|
bit_index += 1
|
||||||
|
return samples_per_bit
|
||||||
|
else:
|
||||||
|
nbitsPerSample = len(rx_dbitlist) if len(rx_dbitlist) % 8 == 0 else len(rx_dbitlist) + (8 - (len(rx_dbitlist) % 8))
|
||||||
|
bits_per_sample = np.empty((dSamples, len(rx_dbitlist)), dtype=np.uint8) #store per row all selected bits of a sample
|
||||||
|
for iSample in range(dSamples):
|
||||||
|
bit_index = nbitsPerSample * iSample
|
||||||
|
for idx, i in enumerate(rx_dbitlist):
|
||||||
|
if not isPlottedArray[i]:
|
||||||
|
bit_index += 1
|
||||||
|
bits_per_sample[iSample, idx] = np.nan
|
||||||
|
|
||||||
|
index = int(bit_index/8)
|
||||||
|
iBit = idx % 8
|
||||||
|
bit = (digital_array[index] >> iBit) & 1
|
||||||
|
bits_per_sample[iSample, idx] = bit
|
||||||
|
bit_index += 1
|
||||||
|
return bits_per_sample.T.copy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def processWaveformData(self, data, aSamples, dSamples):
|
def processWaveformData(self, data, aSamples, dSamples):
|
||||||
"""
|
|
||||||
view function
|
#view function
|
||||||
plots processed waveform data
|
#plots processed waveform data
|
||||||
data: raw waveform data
|
#data: raw waveform data
|
||||||
dsamples: digital samples
|
#dsamples: digital samples
|
||||||
asamples: analog samples
|
#asamples: analog samples
|
||||||
"""
|
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
waveforms = {}
|
waveforms = {}
|
||||||
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
||||||
|
|
||||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitlist, isPlottedArray,
|
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitreorder, self.rx_dbitlist, isPlottedArray,
|
||||||
self.rx_dbitoffset, self.mainWindow.romode.value,
|
self.mainWindow.romode.value,
|
||||||
self.mainWindow.nADCEnabled)
|
self.mainWindow.nADCEnabled)
|
||||||
|
|
||||||
irow = 0
|
irow = 0
|
||||||
for idx, i in enumerate(self.rx_dbitlist):
|
for idx, i in enumerate(self.rx_dbitlist):
|
||||||
# bits enabled but not plotting
|
# bits enabled but not plotting
|
||||||
waveform = digital_array[idx]
|
waveform = digital_array[idx, :]
|
||||||
if waveform is None:
|
if np.isnan(waveform[0]):
|
||||||
continue
|
continue
|
||||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||||
@ -151,8 +173,10 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
irow += 1
|
irow += 1
|
||||||
else:
|
else:
|
||||||
self.mainWindow.digitalPlots[i].setY(0)
|
self.mainWindow.digitalPlots[i].setY(0)
|
||||||
|
|
||||||
return waveforms
|
return waveforms
|
||||||
|
|
||||||
|
|
||||||
def initializeAllDigitalPlots(self):
|
def initializeAllDigitalPlots(self):
|
||||||
self.mainWindow.plotDigitalWaveform = pg.plot()
|
self.mainWindow.plotDigitalWaveform = pg.plot()
|
||||||
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
||||||
@ -360,14 +384,25 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
||||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||||
|
|
||||||
|
def getDBitReorder(self):
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.disconnect()
|
||||||
|
self.rx_dbitreorder = self.det.rx_dbitreorder
|
||||||
|
self.view.checkBoxDBitReorder.setChecked(self.rx_dbitreorder)
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||||
|
|
||||||
|
|
||||||
def setDbitOffset(self):
|
def setDbitOffset(self):
|
||||||
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
||||||
|
|
||||||
|
def setDbitReorder(self):
|
||||||
|
self.det.rx_dbitreorder = self.view.checkBoxDBitReorder.isChecked()
|
||||||
|
|
||||||
def saveParameters(self) -> list:
|
def saveParameters(self) -> list:
|
||||||
commands = []
|
commands = []
|
||||||
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
||||||
if len(dblist) > 0:
|
if len(dblist) > 0:
|
||||||
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
||||||
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
||||||
|
commands.append(f"rx_dbitreorder {self.view.checkBoxDBitReorder.isChecked()}")
|
||||||
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
||||||
return commands
|
return commands
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6074,6 +6074,33 @@
|
|||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_17">
|
<layout class="QGridLayout" name="gridLayout_17">
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QLabel" name="label_66">
|
<widget class="QLabel" name="label_66">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@ -6086,6 +6113,36 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QCheckBox" name="checkBoxDBitReorder">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>DBit Reorder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_48">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>IO Control Register:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -6133,50 +6190,18 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="5">
|
||||||
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
<spacer name="horizontalSpacer_22">
|
||||||
<property name="minimumSize">
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>40</width>
|
||||||
<height>32</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
</spacer>
|
||||||
<size>
|
|
||||||
<width>150</width>
|
|
||||||
<height>32</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_48">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>IO Control Register:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -11,13 +11,9 @@ build-backend = "scikit_build_core.build"
|
|||||||
[project]
|
[project]
|
||||||
name = "slsdet"
|
name = "slsdet"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
dependencies = [
|
|
||||||
"numpy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
before-all = "uname -a"
|
before-all = "uname -a"
|
||||||
build = "cp{311,312,313}-manylinux_x86_64"
|
|
||||||
|
|
||||||
[tool.scikit-build.build]
|
[tool.scikit-build.build]
|
||||||
verbose = true
|
verbose = true
|
||||||
|
@ -27,6 +27,7 @@ set_target_properties(_slsdet PROPERTIES
|
|||||||
set( PYTHON_FILES
|
set( PYTHON_FILES
|
||||||
slsdet/__init__.py
|
slsdet/__init__.py
|
||||||
slsdet/adcs.py
|
slsdet/adcs.py
|
||||||
|
slsdet/bits.py
|
||||||
slsdet/dacs.py
|
slsdet/dacs.py
|
||||||
slsdet/powers.py
|
slsdet/powers.py
|
||||||
slsdet/decorators.py
|
slsdet/decorators.py
|
||||||
@ -37,8 +38,8 @@ set( PYTHON_FILES
|
|||||||
slsdet/enums.py
|
slsdet/enums.py
|
||||||
slsdet/errors.py
|
slsdet/errors.py
|
||||||
slsdet/gaincaps.py
|
slsdet/gaincaps.py
|
||||||
slsdet/gotthard.py
|
|
||||||
slsdet/pattern.py
|
slsdet/pattern.py
|
||||||
|
slsdet/PatternGenerator.py
|
||||||
slsdet/gotthard2.py
|
slsdet/gotthard2.py
|
||||||
slsdet/moench.py
|
slsdet/moench.py
|
||||||
slsdet/proxy.py
|
slsdet/proxy.py
|
||||||
@ -64,10 +65,6 @@ configure_file( scripts/test_virtual.py
|
|||||||
${CMAKE_BINARY_DIR}/test_virtual.py
|
${CMAKE_BINARY_DIR}/test_virtual.py
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(scripts/frameSynchronizerPullSocket.py
|
|
||||||
${CMAKE_BINARY_DIR}/bin/frameSynchronizerPullSocket.py COPYONLY)
|
|
||||||
|
|
||||||
|
|
||||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
|
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
|
||||||
${CMAKE_BINARY_DIR}/bin/slsdet/VERSION
|
${CMAKE_BINARY_DIR}/bin/slsdet/VERSION
|
||||||
)
|
)
|
||||||
|
@ -55,7 +55,6 @@ servers = [
|
|||||||
# "jungfrauDetectorServer",
|
# "jungfrauDetectorServer",
|
||||||
"mythen3DetectorServer",
|
"mythen3DetectorServer",
|
||||||
# "gotthard2DetectorServer",
|
# "gotthard2DetectorServer",
|
||||||
# "gotthardDetectorServer",
|
|
||||||
# "ctbDetectorServer",
|
# "ctbDetectorServer",
|
||||||
# "moenchDetectorServer",
|
# "moenchDetectorServer",
|
||||||
]
|
]
|
||||||
|
226
python/slsdet/PatternGenerator.py
Normal file
226
python/slsdet/PatternGenerator.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
from . import Detector, Pattern
|
||||||
|
from .bits import setbit, clearbit
|
||||||
|
import textwrap
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class PatternGenerator:
|
||||||
|
"""
|
||||||
|
Class to generate a pattern for the SLS detector. Intents to as closely as possible
|
||||||
|
mimic the old pattern generation in the C code.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self.pattern = Pattern()
|
||||||
|
self.iaddr = 0
|
||||||
|
|
||||||
|
def SB(self, *bits):
|
||||||
|
"""
|
||||||
|
Set one or several bits. Change will take affect with the next PW.
|
||||||
|
"""
|
||||||
|
for bit in bits:
|
||||||
|
self.pattern.word[self.iaddr] = setbit(bit, self.pattern.word[self.iaddr])
|
||||||
|
return self.pattern.word[self.iaddr]
|
||||||
|
|
||||||
|
def CB(self, *bits):
|
||||||
|
"""
|
||||||
|
Clear one or several bits. Change will take affect with the next PW.
|
||||||
|
"""
|
||||||
|
for bit in bits:
|
||||||
|
self.pattern.word[self.iaddr] = clearbit(bit, self.pattern.word[self.iaddr])
|
||||||
|
return self.pattern.word[self.iaddr]
|
||||||
|
|
||||||
|
|
||||||
|
def _pw(self, verbose = False):
|
||||||
|
if verbose:
|
||||||
|
print(f'{self.iaddr:#06x} {self.pattern.word[self.iaddr]:#018x}')
|
||||||
|
|
||||||
|
#Limits are inclusive so we need to increment the address before writing the next word
|
||||||
|
self.pattern.limits[1] = self.iaddr
|
||||||
|
self.iaddr += 1
|
||||||
|
self.pattern.word[self.iaddr] = self.pattern.word[self.iaddr-1]
|
||||||
|
|
||||||
|
def PW(self, x = 1, verbose = False):
|
||||||
|
for i in range(x):
|
||||||
|
self._pw(verbose)
|
||||||
|
|
||||||
|
# def REPEAT(self, x, verbose = False):
|
||||||
|
# for i in range(x):
|
||||||
|
# self._pw(verbose)
|
||||||
|
|
||||||
|
# def PW2(self, verbose = 0):
|
||||||
|
# self.REPEAT(2, verbose)
|
||||||
|
|
||||||
|
|
||||||
|
def CLOCKS(self, bit, times = 1, length = 1, verbose = False):
|
||||||
|
"""
|
||||||
|
clocks "bit" n "times", every half clock is long "length"
|
||||||
|
length is optional, default value is 1
|
||||||
|
"""
|
||||||
|
for i in range(0, times):
|
||||||
|
self.SB(bit); self.PW(length, verbose)
|
||||||
|
self.CB(bit); self.PW(length, verbose)
|
||||||
|
|
||||||
|
def CLOCK(self, bit, length = 1, verbose = 0):
|
||||||
|
self.CLOCKS(bit, 1, length ,verbose)
|
||||||
|
|
||||||
|
def serializer(self, value, serInBit, clkBit, nbits, msbfirst = True, length = 1):
|
||||||
|
"""serializer(value,serInBit,clkBit,nbits,msbfirst=1,length=1)
|
||||||
|
Produces the .pat file needed to serialize a word into a shift register.
|
||||||
|
value: value to be serialized
|
||||||
|
serInBit: control bit corresponding to serial in
|
||||||
|
clkBit: control bit corresponding to the clock
|
||||||
|
nbits: number of bits of the target register to load
|
||||||
|
msbfirst: if 1 pushes in the MSB first (default),
|
||||||
|
if 0 pushes in the LSB first
|
||||||
|
length: length of all the PWs in the pattern
|
||||||
|
It produces no output because it modifies directly the members of the class pat via SB and CB"""
|
||||||
|
|
||||||
|
c = value
|
||||||
|
self.CB(serInBit, clkBit)
|
||||||
|
self.PW(length) #generate initial line with clk and serIn to 0
|
||||||
|
|
||||||
|
start = 0
|
||||||
|
stop = nbits
|
||||||
|
step = 1
|
||||||
|
|
||||||
|
if msbfirst:
|
||||||
|
start = nbits - 1
|
||||||
|
stop = -1
|
||||||
|
step =- 1 #reverts loop if msb has to be pushed in first
|
||||||
|
|
||||||
|
for i in range(start, stop, step):
|
||||||
|
if c & (1<<i):
|
||||||
|
self.SB(serInBit)
|
||||||
|
self.PW(length)
|
||||||
|
else:
|
||||||
|
self.CB(serInBit)
|
||||||
|
self.PW(length)
|
||||||
|
self.SB(clkBit)
|
||||||
|
self.PW(length)
|
||||||
|
self.CB(clkBit)
|
||||||
|
self.PW(length)
|
||||||
|
|
||||||
|
self.CB(serInBit, clkBit)
|
||||||
|
self.PW(length) #generate final line with clk and serIn to 0
|
||||||
|
|
||||||
|
|
||||||
|
#NOT IMPLEMENTED YET
|
||||||
|
#TODO! What should setstop do? Or can we remove it?
|
||||||
|
#def setstop():
|
||||||
|
#
|
||||||
|
|
||||||
|
def setoutput(self, bit):
|
||||||
|
self.pattern.ioctrl = setbit(bit, self.pattern.ioctrl)
|
||||||
|
|
||||||
|
def setinput(self, bit):
|
||||||
|
self.pattern.ioctrl= clearbit(bit, self.pattern.ioctrl)
|
||||||
|
|
||||||
|
#TODO! What should setclk do? Or can we remove it?
|
||||||
|
# def setclk(bit):
|
||||||
|
# self.clkctrl=self.setbit(bit,self.clkctrl)
|
||||||
|
|
||||||
|
def setinputs(self, *args):
|
||||||
|
for i in args:
|
||||||
|
self.setinput(i)
|
||||||
|
|
||||||
|
def setoutputs(self, *args):
|
||||||
|
for i in args:
|
||||||
|
self.setoutput(i)
|
||||||
|
|
||||||
|
#def setclks(self, *args):
|
||||||
|
# for i in args:
|
||||||
|
# self.setclk(i)
|
||||||
|
|
||||||
|
def setnloop(self, i, reps):
|
||||||
|
self.pattern.nloop[i] = reps
|
||||||
|
|
||||||
|
def setstartloop(self, i):
|
||||||
|
"""
|
||||||
|
Set startloop[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.startloop[i] = self.iaddr
|
||||||
|
|
||||||
|
def setstoploop(self, i):
|
||||||
|
"""
|
||||||
|
Set stoploop[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.stoploop[i] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setstart(self):
|
||||||
|
"""
|
||||||
|
Set start of pattern to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.limits[0]=self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setstop(self,l):
|
||||||
|
"""
|
||||||
|
Set stop of pattern to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.limits[1] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setwaitpoint(self, i):
|
||||||
|
"""
|
||||||
|
Set wait[i] to the current address.
|
||||||
|
"""
|
||||||
|
self.pattern.wait[i] = self.iaddr
|
||||||
|
|
||||||
|
|
||||||
|
def setwaittime(self, i, t):
|
||||||
|
"""
|
||||||
|
Set waittime[i] to t.
|
||||||
|
"""
|
||||||
|
self.pattern.waittime[i] = t
|
||||||
|
|
||||||
|
|
||||||
|
def setwait(self, i, t):
|
||||||
|
"""
|
||||||
|
Set wait[i] to the current address and waittime[i] to t.
|
||||||
|
"""
|
||||||
|
self.setwait(i)
|
||||||
|
self.setwaittime(i, t)
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return textwrap.dedent(f"""\
|
||||||
|
PatternBuilder:
|
||||||
|
patlimits: {self.pattern.limits}
|
||||||
|
startloop: {self.pattern.startloop}
|
||||||
|
stoploop: {self.pattern.stoploop}
|
||||||
|
nloop: {self.pattern.nloop}
|
||||||
|
wait: {self.pattern.wait}
|
||||||
|
waittime: {self.pattern.waittime}""")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.pattern.str()
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
print(self)
|
||||||
|
|
||||||
|
def save(self, fname):
|
||||||
|
"""Save pattern to text file"""
|
||||||
|
fname = str(fname) #Accept also Path objects, but C++ code needs a string
|
||||||
|
self.pattern.save(fname)
|
||||||
|
|
||||||
|
def load(self, fname):
|
||||||
|
"""Load pattern from text file"""
|
||||||
|
fname = str(fname) #Accept also Path objects, but C++ code needs a string
|
||||||
|
n = self.pattern.load(fname)
|
||||||
|
|
||||||
|
#If the firs and only word is 0 we assume an empty pattern
|
||||||
|
if n == 1 and self.pattern.word[0] == 0:
|
||||||
|
n = 0
|
||||||
|
self.iaddr = n
|
||||||
|
|
||||||
|
#To make PW work as expected we need to set 1+last word to the last word
|
||||||
|
if n > 0:
|
||||||
|
self.pattern.word[n] = self.pattern.word[n-1]
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_detector(self, det):
|
||||||
|
"""
|
||||||
|
Load the pattern into the detector.
|
||||||
|
"""
|
||||||
|
det.setPattern(self.pattern)
|
@ -9,10 +9,10 @@ from .detector import Detector
|
|||||||
from .jungfrau import Jungfrau
|
from .jungfrau import Jungfrau
|
||||||
from .mythen3 import Mythen3
|
from .mythen3 import Mythen3
|
||||||
from .gotthard2 import Gotthard2
|
from .gotthard2 import Gotthard2
|
||||||
from .gotthard import Gotthard
|
|
||||||
from .moench import Moench
|
from .moench import Moench
|
||||||
from .pattern import Pattern, patternParameters
|
from .pattern import Pattern, patternParameters
|
||||||
from .gaincaps import Mythen3GainCapsWrapper
|
from .gaincaps import Mythen3GainCapsWrapper
|
||||||
|
from .PatternGenerator import PatternGenerator
|
||||||
|
|
||||||
from . import _slsdet
|
from . import _slsdet
|
||||||
xy = _slsdet.xy
|
xy = _slsdet.xy
|
||||||
|
31
python/slsdet/bits.py
Normal file
31
python/slsdet/bits.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def setbit(bit, word):
|
||||||
|
if isinstance(word, np.generic):
|
||||||
|
mask = word.dtype.type(1)
|
||||||
|
mask = mask << bit
|
||||||
|
else:
|
||||||
|
mask = 1 << bit
|
||||||
|
return word | mask
|
||||||
|
|
||||||
|
|
||||||
|
def setbit_arr(bit, arr):
|
||||||
|
arr |= arr.dtype.type(1 << bit)
|
||||||
|
|
||||||
|
|
||||||
|
def clearbit(bit, word):
|
||||||
|
"""
|
||||||
|
Clear the bit at position bit in word.
|
||||||
|
Two paths to avoid converting the types.
|
||||||
|
"""
|
||||||
|
if isinstance(word, np.generic):
|
||||||
|
mask = word.dtype.type(1)
|
||||||
|
mask = ~(mask << bit)
|
||||||
|
else:
|
||||||
|
mask = ~(1 << bit)
|
||||||
|
return word & mask
|
||||||
|
|
||||||
|
|
||||||
|
def clearbit_arr(bit, arr):
|
||||||
|
arr &= arr.dtype.type(~(1 << bit))
|
@ -274,7 +274,7 @@ class Detector(CppDetectorApi):
|
|||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def serialnumber(self):
|
def serialnumber(self):
|
||||||
"""Jungfrau][Gotthard][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
"""Jungfrau][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
||||||
return ut.lhex(self.getSerialNumber())
|
return ut.lhex(self.getSerialNumber())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -312,7 +312,7 @@ class Detector(CppDetectorApi):
|
|||||||
-----
|
-----
|
||||||
[Eiger] Options: 4, 8, 12, 16, 32. If set to 32, also sets clkdivider to 2 (quarter speed), else to 0 (full speed)\n
|
[Eiger] Options: 4, 8, 12, 16, 32. If set to 32, also sets clkdivider to 2 (quarter speed), else to 0 (full speed)\n
|
||||||
[Mythen3] Options: 8, 16, 32 \n
|
[Mythen3] Options: 8, 16, 32 \n
|
||||||
[Jungfrau][Moench][Gotthard][Ctb][Mythen3][Gotthard2][Xilinx Ctb] 16
|
[Jungfrau][Moench][Ctb][Mythen3][Gotthard2][Xilinx Ctb] 16
|
||||||
"""
|
"""
|
||||||
return self.getDynamicRange()
|
return self.getDynamicRange()
|
||||||
|
|
||||||
@ -372,7 +372,6 @@ class Detector(CppDetectorApi):
|
|||||||
|
|
||||||
[Eiger] Use threshold command to load settings
|
[Eiger] Use threshold command to load settings
|
||||||
[Jungfrau] GAIN0, HIGHGAIN0 \n
|
[Jungfrau] GAIN0, HIGHGAIN0 \n
|
||||||
[Gotthard] DYNAMICGAIN, HIGHGAIN, LOWGAIN, MEDIUMGAIN, VERYHIGHGAIN \n
|
|
||||||
[Gotthard2] DYNAMICGAIN, FIXGAIN1, FIXGAIN2 \n
|
[Gotthard2] DYNAMICGAIN, FIXGAIN1, FIXGAIN2 \n
|
||||||
[Eiger] settings loaded from file found in settingspath
|
[Eiger] settings loaded from file found in settingspath
|
||||||
[Moench] G1_HIGHGAIN, G1_LOWGAIN, G2_HIGHCAP_HIGHGAIN, G2_HIGHCAP_LOWGAIN, G2_LOWCAP_HIGHGAIN, G2_LOWCAP_LOWGAIN, G4_HIGHGAIN, G4_LOWGAIN
|
[Moench] G1_HIGHGAIN, G1_LOWGAIN, G2_HIGHCAP_HIGHGAIN, G2_HIGHCAP_LOWGAIN, G2_LOWCAP_HIGHGAIN, G2_LOWCAP_LOWGAIN, G4_HIGHGAIN, G4_LOWGAIN
|
||||||
@ -404,7 +403,7 @@ class Detector(CppDetectorApi):
|
|||||||
@element
|
@element
|
||||||
def framesl(self):
|
def framesl(self):
|
||||||
"""
|
"""
|
||||||
[Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of frames left in acquisition.\n
|
[Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of frames left in acquisition.\n
|
||||||
|
|
||||||
Note
|
Note
|
||||||
----
|
----
|
||||||
@ -635,7 +634,7 @@ class Detector(CppDetectorApi):
|
|||||||
@element
|
@element
|
||||||
def periodl(self):
|
def periodl(self):
|
||||||
"""
|
"""
|
||||||
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Period left for current frame.
|
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Period left for current frame.
|
||||||
|
|
||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
@ -657,7 +656,7 @@ class Detector(CppDetectorApi):
|
|||||||
@element
|
@element
|
||||||
def delay(self):
|
def delay(self):
|
||||||
"""
|
"""
|
||||||
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay after trigger, accepts either a value in seconds, DurationWrapper or datetime.timedelta
|
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay after trigger, accepts either a value in seconds, DurationWrapper or datetime.timedelta
|
||||||
|
|
||||||
:getter: always returns in seconds. To get in DurationWrapper, use getDelayAfterTrigger
|
:getter: always returns in seconds. To get in DurationWrapper, use getDelayAfterTrigger
|
||||||
|
|
||||||
@ -699,7 +698,7 @@ class Detector(CppDetectorApi):
|
|||||||
@element
|
@element
|
||||||
def delayl(self):
|
def delayl(self):
|
||||||
"""
|
"""
|
||||||
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay left after trigger during acquisition, accepts either a value in seconds, datetime.timedelta or DurationWrapper
|
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay left after trigger during acquisition, accepts either a value in seconds, datetime.timedelta or DurationWrapper
|
||||||
|
|
||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
@ -1444,8 +1443,6 @@ class Detector(CppDetectorApi):
|
|||||||
@udp_srcip.setter
|
@udp_srcip.setter
|
||||||
def udp_srcip(self, ip):
|
def udp_srcip(self, ip):
|
||||||
if ip == "auto":
|
if ip == "auto":
|
||||||
if self.type == detectorType.GOTTHARD:
|
|
||||||
raise NotImplementedError('Auto for udp_srcip cannot be used for GotthardI')
|
|
||||||
ip = socket.gethostbyname(self.hostname[0])
|
ip = socket.gethostbyname(self.hostname[0])
|
||||||
ip = ut.make_ip(ip)
|
ip = ut.make_ip(ip)
|
||||||
ut.set_using_dict(self.setSourceUDPIP, ip)
|
ut.set_using_dict(self.setSourceUDPIP, ip)
|
||||||
@ -1526,7 +1523,6 @@ class Detector(CppDetectorApi):
|
|||||||
|
|
||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
[Gotthard] 0, 90, 110, 120, 150, 180, 200 \n
|
|
||||||
[Eiger][Mythen3][Gotthard2] 0 - 200 \n
|
[Eiger][Mythen3][Gotthard2] 0 - 200 \n
|
||||||
[Jungfrau][Moench][Ctb] 0, 60 - 200
|
[Jungfrau][Moench][Ctb] 0, 60 - 200
|
||||||
"""
|
"""
|
||||||
@ -1654,7 +1650,7 @@ class Detector(CppDetectorApi):
|
|||||||
def master(self):
|
def master(self):
|
||||||
"""
|
"""
|
||||||
[Eiger][Gotthard2][Jungfrau][Moench] Sets (half) module to master and other(s) to slaves.\n
|
[Eiger][Gotthard2][Jungfrau][Moench] Sets (half) module to master and other(s) to slaves.\n
|
||||||
[Gotthard][Gotthard2][Mythen3][Eiger][Jungfrau][Moench] Gets if the current (half) module is master.
|
[Gotthard2][Mythen3][Eiger][Jungfrau][Moench] Gets if the current (half) module is master.
|
||||||
"""
|
"""
|
||||||
return self.getMaster()
|
return self.getMaster()
|
||||||
|
|
||||||
@ -1912,7 +1908,7 @@ class Detector(CppDetectorApi):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def adcreg(self):
|
def adcreg(self):
|
||||||
"""[Jungfrau][Moench][Ctb][Gotthard] Writes to an adc register
|
"""[Jungfrau][Moench][Ctb] Writes to an adc register
|
||||||
|
|
||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
@ -1941,7 +1937,7 @@ class Detector(CppDetectorApi):
|
|||||||
@element
|
@element
|
||||||
def triggersl(self):
|
def triggersl(self):
|
||||||
"""
|
"""
|
||||||
[Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of triggers left in acquisition.\n
|
[Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of triggers left in acquisition.\n
|
||||||
|
|
||||||
Note
|
Note
|
||||||
----
|
----
|
||||||
@ -2206,7 +2202,7 @@ class Detector(CppDetectorApi):
|
|||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
Default: AUTO_TIMING \n
|
Default: AUTO_TIMING \n
|
||||||
[Jungfrau][Moench][Gotthard][Ctb][Gotthard2][Xilinx Ctb] AUTO_TIMING, TRIGGER_EXPOSURE \n
|
[Jungfrau][Moench][Ctb][Gotthard2][Xilinx Ctb] AUTO_TIMING, TRIGGER_EXPOSURE \n
|
||||||
[Mythen3] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, TRIGGER_GATED \n
|
[Mythen3] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, TRIGGER_GATED \n
|
||||||
[Eiger] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER
|
[Eiger] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER
|
||||||
"""
|
"""
|
||||||
@ -2263,7 +2259,7 @@ class Detector(CppDetectorApi):
|
|||||||
def type(self):
|
def type(self):
|
||||||
""" Returns detector type.
|
""" Returns detector type.
|
||||||
Enum: detectorType
|
Enum: detectorType
|
||||||
[EIGER, JUNGFRAU, GOTTHARD, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD]
|
[EIGER, JUNGFRAU, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD]
|
||||||
|
|
||||||
:setter: Not implemented
|
:setter: Not implemented
|
||||||
"""
|
"""
|
||||||
@ -3467,6 +3463,16 @@ class Detector(CppDetectorApi):
|
|||||||
def rx_dbitoffset(self, value):
|
def rx_dbitoffset(self, value):
|
||||||
ut.set_using_dict(self.setRxDbitOffset, value)
|
ut.set_using_dict(self.setRxDbitOffset, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def rx_dbitreorder(self):
|
||||||
|
"""[Ctb] Reorder digital data to group together all samples per signal. Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together."""
|
||||||
|
return self.getRxDbitReorder()
|
||||||
|
|
||||||
|
@rx_dbitreorder.setter
|
||||||
|
def rx_dbitreorder(self, value):
|
||||||
|
ut.set_using_dict(self.setRxDbitReorder, value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def maxadcphaseshift(self):
|
def maxadcphaseshift(self):
|
||||||
@ -3479,15 +3485,13 @@ class Detector(CppDetectorApi):
|
|||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def adcphase(self):
|
def adcphase(self):
|
||||||
"""[Gotthard][Jungfrau][Moench][CTB] Sets phase shift of ADC clock.
|
"""[Jungfrau][Moench][CTB] Sets phase shift of ADC clock.
|
||||||
|
|
||||||
Note
|
Note
|
||||||
-----
|
-----
|
||||||
[Jungfrau][Moench] Absolute phase shift. Changing Speed also resets adcphase to recommended defaults.\n
|
[Jungfrau][Moench] Absolute phase shift. Changing Speed also resets adcphase to recommended defaults.\n
|
||||||
[Ctb] Absolute phase shift. Changing adcclk also resets adcphase and sets it to previous values.\n
|
[Ctb] Absolute phase shift. Changing adcclk also resets adcphase and sets it to previous values.
|
||||||
[Gotthard] Relative phase shift.
|
|
||||||
|
|
||||||
:getter: Not implemented for Gotthard
|
|
||||||
"""
|
"""
|
||||||
return self.getADCPhase()
|
return self.getADCPhase()
|
||||||
|
|
||||||
@ -3704,6 +3708,12 @@ class Detector(CppDetectorApi):
|
|||||||
"""
|
"""
|
||||||
[Ctb][Mythen3][Xilinx Ctb] Wait time in clock cycles of loop level provided.
|
[Ctb][Mythen3][Xilinx Ctb] Wait time in clock cycles of loop level provided.
|
||||||
|
|
||||||
|
Info
|
||||||
|
----
|
||||||
|
|
||||||
|
:getter: Always return in clock cycles. To get in DurationWrapper, use getPatternWaitInterval
|
||||||
|
:setter: Accepts either a value in clock cycles or a time unit (timedelta, DurationWrapper)
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
>>> d.patwaittime[0] = 5
|
>>> d.patwaittime[0] = 5
|
||||||
@ -3713,41 +3723,85 @@ class Detector(CppDetectorApi):
|
|||||||
0: 5
|
0: 5
|
||||||
1: 20
|
1: 20
|
||||||
2: 30
|
2: 30
|
||||||
|
>>> # using timedelta (up to microseconds precision)
|
||||||
|
>>> from datetime import timedelta
|
||||||
|
>>> d.patwaittime[0] = timedelta(seconds=1, microseconds=3)
|
||||||
|
>>>
|
||||||
|
>>> # using DurationWrapper to set in seconds
|
||||||
|
>>> from slsdet import DurationWrapper
|
||||||
|
>>> d.patwaittime[0] = DurationWrapper(1.2)
|
||||||
|
>>>
|
||||||
|
>>> # using DurationWrapper to set in ns
|
||||||
|
>>> t = DurationWrapper()
|
||||||
|
>>> t.set_count(500)
|
||||||
|
>>> d.patwaittime = t
|
||||||
|
>>>
|
||||||
|
>>> # to get in clock cycles
|
||||||
|
>>> d.patwaittime
|
||||||
|
1000
|
||||||
|
>>>
|
||||||
|
>>> d.getPatternWaitInterval(0)
|
||||||
|
sls::DurationWrapper(total_seconds: 1.23 count: 1230000000)
|
||||||
"""
|
"""
|
||||||
return PatWaitTimeProxy(self)
|
return PatWaitTimeProxy(self)
|
||||||
|
|
||||||
@property
|
|
||||||
@element
|
|
||||||
def patwaittime0(self):
|
|
||||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 0 time in clock cycles."""
|
|
||||||
return self.getPatternWaitTime(0)
|
|
||||||
|
|
||||||
@patwaittime0.setter
|
def create_patwaittime_property(level):
|
||||||
def patwaittime0(self, nclk):
|
docstring_template ="""
|
||||||
nclk = ut.merge_args(0, nclk)
|
Deprecated command. Use patwaittime instead.
|
||||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
[Ctb][Mythen3][Xilinx Ctb] Wait time in clock cycles of loop level {level} provided.
|
||||||
|
|
||||||
@property
|
Info
|
||||||
@element
|
----
|
||||||
def patwaittime1(self):
|
|
||||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 1 time in clock cycles."""
|
|
||||||
return self.getPatternWaitTime(1)
|
|
||||||
|
|
||||||
@patwaittime1.setter
|
:getter: Always return in clock cycles. To get in DurationWrapper, use getPatternWaitInterval
|
||||||
def patwaittime1(self, nclk):
|
:setter: Accepts either a value in clock cycles or a time unit (timedelta, DurationWrapper)
|
||||||
nclk = ut.merge_args(1, nclk)
|
|
||||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
|
||||||
|
|
||||||
@property
|
Example
|
||||||
@element
|
-------
|
||||||
def patwaittime2(self):
|
>>> d.patwaittime{level} = 5
|
||||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 2 time in clock cycles."""
|
>>> d.patwaittime{level}
|
||||||
return self.getPatternWaitTime(2)
|
5
|
||||||
|
>>> # using timedelta (up to microseconds precision)
|
||||||
|
>>> from datetime import timedelta
|
||||||
|
>>> d.patwaittime{level} = timedelta(seconds=1, microseconds=3)
|
||||||
|
>>>
|
||||||
|
>>> # using DurationWrapper to set in seconds
|
||||||
|
>>> from slsdet import DurationWrapper
|
||||||
|
>>> d.patwaittime{level} = DurationWrapper(1.2)
|
||||||
|
>>>
|
||||||
|
>>> # using DurationWrapper to set in ns
|
||||||
|
>>> t = DurationWrapper()
|
||||||
|
>>> t.set_count(500)
|
||||||
|
>>> d.patwaittime{level} = t
|
||||||
|
>>>
|
||||||
|
>>> # to get in clock cycles
|
||||||
|
>>> d.patwaittime{level}
|
||||||
|
1000
|
||||||
|
>>>
|
||||||
|
>>> d.getPatternWaitInterval(level)
|
||||||
|
sls::DurationWrapper(total_seconds: 1.23 count: 1230000000)
|
||||||
|
"""
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def patwaittime(self):
|
||||||
|
return self.getPatternWaitClocks(level)
|
||||||
|
|
||||||
@patwaittime2.setter
|
@patwaittime.setter
|
||||||
def patwaittime2(self, nclk):
|
def patwaittime(self, value):
|
||||||
nclk = ut.merge_args(2, nclk)
|
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
||||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
nclk = ut.merge_args(level, value)
|
||||||
|
ut.set_using_dict(self.setPatternWaitClocks, level, *nclk)
|
||||||
|
else:
|
||||||
|
ut.set_time_using_dict(self.setPatternWaitInterval, level, value)
|
||||||
|
|
||||||
|
patwaittime.__doc__ = docstring_template.format(level=level)
|
||||||
|
|
||||||
|
return patwaittime
|
||||||
|
|
||||||
|
patwaittime0 = create_patwaittime_property(0)
|
||||||
|
patwaittime1 = create_patwaittime_property(1)
|
||||||
|
patwaittime2 = create_patwaittime_property(2)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -4038,27 +4092,6 @@ class Detector(CppDetectorApi):
|
|||||||
return ClkDivProxy(self)
|
return ClkDivProxy(self)
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
---------------------------<<<Gotthard specific>>>---------------------------
|
|
||||||
"""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def exptimel(self):
|
|
||||||
"""[Gotthard] Exposure time left for current frame.
|
|
||||||
|
|
||||||
:getter: always returns in seconds. To get in DurationWrapper, use getExptimeLeft
|
|
||||||
:setter: Not Implemented
|
|
||||||
|
|
||||||
Example
|
|
||||||
-----------
|
|
||||||
>>> d.exptimel
|
|
||||||
181.23
|
|
||||||
>>> d.getExptimeLeft()
|
|
||||||
[sls::DurationWrapper(total_seconds: 181.23 count: 181230000000)]
|
|
||||||
"""
|
|
||||||
t = self.getExptimeLeft()
|
|
||||||
return reduce_time(t)
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
---------------------------<<<Mythen3 specific>>>---------------------------
|
---------------------------<<<Mythen3 specific>>>---------------------------
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
|
||||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
This file contains the specialization for the Moench detector
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
from .detector import Detector, freeze
|
|
||||||
from .dacs import DetectorDacs
|
|
||||||
from . import _slsdet
|
|
||||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
|
||||||
from .detector_property import DetectorProperty
|
|
||||||
|
|
||||||
# @freeze
|
|
||||||
|
|
||||||
# vref_ds, vcascn_pb, vcascp_pb, vout_cm, vcasc_out, vin_cm, vref_comp, ib_test_c
|
|
||||||
class GotthardDacs(DetectorDacs):
|
|
||||||
_dacs = [('vref_ds', dacIndex.VREF_DS, 0, 4000, 660),
|
|
||||||
('vcascn_pb', dacIndex.VCASCN_PB, 0, 4000, 650),
|
|
||||||
('vcascp_pb,', dacIndex.VCASCP_PB, 0, 4000, 1480),
|
|
||||||
('vout_cm', dacIndex.VOUT_CM, 0, 4000, 1520),
|
|
||||||
('vcasc_out', dacIndex.VCASC_OUT, 0, 4000, 1320),
|
|
||||||
('vin_cm', dacIndex.VIN_CM, 0, 4000, 1350),
|
|
||||||
('vref_comp', dacIndex.VREF_COMP, 0, 4000, 350),
|
|
||||||
('ib_test_c', dacIndex.IB_TESTC, 0, 4000, 2001),
|
|
||||||
]
|
|
||||||
_dacnames = [_d[0] for _d in _dacs]
|
|
||||||
|
|
||||||
#vthreshold??
|
|
||||||
|
|
||||||
|
|
||||||
@freeze
|
|
||||||
class Gotthard(Detector):
|
|
||||||
"""
|
|
||||||
Subclassing Detector to set up correct dacs and detector specific
|
|
||||||
functions.
|
|
||||||
"""
|
|
||||||
_detector_dynamic_range = [16]
|
|
||||||
|
|
||||||
|
|
||||||
_settings = ['standard', 'highgain', 'lowgain', 'veryhighgain', 'verylowgain']
|
|
||||||
"""available settings for Eiger, note almost always standard"""
|
|
||||||
|
|
||||||
def __init__(self, id=0):
|
|
||||||
super().__init__(id)
|
|
||||||
self._frozen = False
|
|
||||||
self._dacs = GotthardDacs(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dacs(self):
|
|
||||||
return self._dacs
|
|
@ -275,10 +275,13 @@ class PatWaitTimeProxy:
|
|||||||
self.det = det
|
self.det = det
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return element_if_equal(self.det.getPatternWaitTime(key))
|
return element_if_equal(self.det.getPatternWaitClocks(key))
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
set_proxy_using_dict(self.det.setPatternWaitTime, key, value)
|
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
||||||
|
set_proxy_using_dict(self.det.setPatternWaitClocks, key, value)
|
||||||
|
else:
|
||||||
|
set_proxy_using_dict(self.det.setPatternWaitInterval, key, value)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
max_levels = MAX_PATTERN_LEVELS
|
max_levels = MAX_PATTERN_LEVELS
|
||||||
|
@ -1293,20 +1293,6 @@ void init_det(py::module &m) {
|
|||||||
(void (Detector::*)(defs::collectionMode, sls::Positions)) &
|
(void (Detector::*)(defs::collectionMode, sls::Positions)) &
|
||||||
Detector::setCollectionMode,
|
Detector::setCollectionMode,
|
||||||
py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("getROI",
|
|
||||||
(Result<defs::ROI>(Detector::*)(sls::Positions) const) &
|
|
||||||
Detector::getROI,
|
|
||||||
py::arg() = Positions{});
|
|
||||||
CppDetectorApi.def("setROI",
|
|
||||||
(void (Detector::*)(defs::ROI, int)) & Detector::setROI,
|
|
||||||
py::arg(), py::arg());
|
|
||||||
CppDetectorApi.def(
|
|
||||||
"clearROI", (void (Detector::*)(sls::Positions)) & Detector::clearROI,
|
|
||||||
py::arg() = Positions{});
|
|
||||||
CppDetectorApi.def("getExptimeLeft",
|
|
||||||
(Result<sls::ns>(Detector::*)(sls::Positions) const) &
|
|
||||||
Detector::getExptimeLeft,
|
|
||||||
py::arg() = Positions{});
|
|
||||||
CppDetectorApi.def("getNumberOfBursts",
|
CppDetectorApi.def("getNumberOfBursts",
|
||||||
(Result<int64_t>(Detector::*)(sls::Positions) const) &
|
(Result<int64_t>(Detector::*)(sls::Positions) const) &
|
||||||
Detector::getNumberOfBursts,
|
Detector::getNumberOfBursts,
|
||||||
@ -1678,6 +1664,14 @@ void init_det(py::module &m) {
|
|||||||
(void (Detector::*)(int, sls::Positions)) &
|
(void (Detector::*)(int, sls::Positions)) &
|
||||||
Detector::setRxDbitOffset,
|
Detector::setRxDbitOffset,
|
||||||
py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def("getRxDbitReorder",
|
||||||
|
(Result<bool>(Detector::*)(sls::Positions) const) &
|
||||||
|
Detector::getRxDbitReorder,
|
||||||
|
py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def("setRxDbitReorder",
|
||||||
|
(void (Detector::*)(bool, sls::Positions)) &
|
||||||
|
Detector::setRxDbitReorder,
|
||||||
|
py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("setDigitalIODelay",
|
CppDetectorApi.def("setDigitalIODelay",
|
||||||
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
||||||
Detector::setDigitalIODelay,
|
Detector::setDigitalIODelay,
|
||||||
@ -1861,13 +1855,22 @@ void init_det(py::module &m) {
|
|||||||
Detector::setPatternWaitAddr,
|
Detector::setPatternWaitAddr,
|
||||||
py::arg(), py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def(
|
CppDetectorApi.def(
|
||||||
"getPatternWaitTime",
|
"getPatternWaitClocks",
|
||||||
(Result<uint64_t>(Detector::*)(int, sls::Positions) const) &
|
(Result<uint64_t>(Detector::*)(int, sls::Positions) const) &
|
||||||
Detector::getPatternWaitTime,
|
Detector::getPatternWaitClocks,
|
||||||
py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("setPatternWaitTime",
|
CppDetectorApi.def("setPatternWaitClocks",
|
||||||
(void (Detector::*)(int, uint64_t, sls::Positions)) &
|
(void (Detector::*)(int, uint64_t, sls::Positions)) &
|
||||||
Detector::setPatternWaitTime,
|
Detector::setPatternWaitClocks,
|
||||||
|
py::arg(), py::arg(), py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def(
|
||||||
|
"getPatternWaitInterval",
|
||||||
|
(Result<sls::ns>(Detector::*)(int, sls::Positions) const) &
|
||||||
|
Detector::getPatternWaitInterval,
|
||||||
|
py::arg(), py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def("setPatternWaitInterval",
|
||||||
|
(void (Detector::*)(int, sls::ns, sls::Positions)) &
|
||||||
|
Detector::setPatternWaitInterval,
|
||||||
py::arg(), py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("getPatternMask",
|
CppDetectorApi.def("getPatternMask",
|
||||||
(Result<uint64_t>(Detector::*)(sls::Positions)) &
|
(Result<uint64_t>(Detector::*)(sls::Positions)) &
|
||||||
|
@ -121,13 +121,9 @@ void init_enums(py::module &m) {
|
|||||||
.value("VTHRESHOLD", slsDetectorDefs::dacIndex::VTHRESHOLD)
|
.value("VTHRESHOLD", slsDetectorDefs::dacIndex::VTHRESHOLD)
|
||||||
.value("IO_DELAY", slsDetectorDefs::dacIndex::IO_DELAY)
|
.value("IO_DELAY", slsDetectorDefs::dacIndex::IO_DELAY)
|
||||||
.value("VREF_DS", slsDetectorDefs::dacIndex::VREF_DS)
|
.value("VREF_DS", slsDetectorDefs::dacIndex::VREF_DS)
|
||||||
.value("VCASCN_PB", slsDetectorDefs::dacIndex::VCASCN_PB)
|
|
||||||
.value("VCASCP_PB", slsDetectorDefs::dacIndex::VCASCP_PB)
|
|
||||||
.value("VOUT_CM", slsDetectorDefs::dacIndex::VOUT_CM)
|
.value("VOUT_CM", slsDetectorDefs::dacIndex::VOUT_CM)
|
||||||
.value("VCASC_OUT", slsDetectorDefs::dacIndex::VCASC_OUT)
|
|
||||||
.value("VIN_CM", slsDetectorDefs::dacIndex::VIN_CM)
|
.value("VIN_CM", slsDetectorDefs::dacIndex::VIN_CM)
|
||||||
.value("VREF_COMP", slsDetectorDefs::dacIndex::VREF_COMP)
|
.value("VREF_COMP", slsDetectorDefs::dacIndex::VREF_COMP)
|
||||||
.value("IB_TESTC", slsDetectorDefs::dacIndex::IB_TESTC)
|
|
||||||
.value("VB_COMP", slsDetectorDefs::dacIndex::VB_COMP)
|
.value("VB_COMP", slsDetectorDefs::dacIndex::VB_COMP)
|
||||||
.value("VDD_PROT", slsDetectorDefs::dacIndex::VDD_PROT)
|
.value("VDD_PROT", slsDetectorDefs::dacIndex::VDD_PROT)
|
||||||
.value("VIN_COM", slsDetectorDefs::dacIndex::VIN_COM)
|
.value("VIN_COM", slsDetectorDefs::dacIndex::VIN_COM)
|
||||||
|
@ -20,8 +20,10 @@ void init_pattern(py::module &m) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
py::class_<sls::Pattern> Pattern(m, "Pattern");
|
py::class_<sls::Pattern> Pattern(m, "Pattern");
|
||||||
Pattern.def(py::init());
|
Pattern.def(py::init())
|
||||||
Pattern.def("load", &sls::Pattern::load);
|
.def("load", &sls::Pattern::load)
|
||||||
Pattern.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
.def("save", &sls::Pattern::save)
|
||||||
|
.def("str", &sls::Pattern::str)
|
||||||
|
.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
||||||
py::return_value_policy::reference);
|
py::return_value_policy::reference);
|
||||||
}
|
}
|
||||||
|
152
python/tests/test_PatternGenerator.py
Normal file
152
python/tests/test_PatternGenerator.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import pytest
|
||||||
|
from slsdet import PatternGenerator
|
||||||
|
|
||||||
|
|
||||||
|
def apply_detconf(p):
|
||||||
|
"""
|
||||||
|
Hacky workaround to apply detConf_mh02 to a pattern
|
||||||
|
"""
|
||||||
|
DACMON = 0
|
||||||
|
cnt_en_3 = 1
|
||||||
|
pulse_counter_en = 2
|
||||||
|
cnt_en_1 = 3
|
||||||
|
par_load = 4
|
||||||
|
pulse_mux_ctr = 5
|
||||||
|
reset_cnt = 6
|
||||||
|
reset_periphery = 7
|
||||||
|
config_load = 8
|
||||||
|
cnt_en_0 = 9
|
||||||
|
tbl = 10
|
||||||
|
clk_ext = 11
|
||||||
|
trimbit_load_reg = 12
|
||||||
|
store = 13
|
||||||
|
data_in = 14
|
||||||
|
en_pll_clk = 15
|
||||||
|
cnt_en_2 = 16
|
||||||
|
DACINT = 17
|
||||||
|
data_out_slow = 18 #IN
|
||||||
|
COMP2_MON = 19 #IN
|
||||||
|
start_read = 20
|
||||||
|
dac_store = 21
|
||||||
|
CNT3_MON = 22 #IN
|
||||||
|
EN_PIX_DIG_MON = 23
|
||||||
|
clk_sel = 24
|
||||||
|
BUSY = 25 #IN
|
||||||
|
COMP3_MON = 26 #IN
|
||||||
|
CNT2_MON = 27 #IN
|
||||||
|
|
||||||
|
dbit_ena=62 #FIFO LATCH
|
||||||
|
adc_ena=63 #ADC ENABLE
|
||||||
|
|
||||||
|
#FPGA input/ouutputs
|
||||||
|
p.setoutput(DACMON)
|
||||||
|
p.setoutput(cnt_en_3)
|
||||||
|
p.setoutput(pulse_counter_en)
|
||||||
|
p.setoutput(cnt_en_1)
|
||||||
|
p.setoutput(par_load)
|
||||||
|
p.setoutput(pulse_mux_ctr)
|
||||||
|
p.setoutput(reset_cnt)
|
||||||
|
p.setoutput(reset_periphery)
|
||||||
|
p.setoutput(cnt_en_0)
|
||||||
|
p.setoutput(tbl)
|
||||||
|
p.setoutput(clk_ext)
|
||||||
|
p.setoutput(config_load)
|
||||||
|
p.setoutput(trimbit_load_reg)
|
||||||
|
p.setoutput(store)
|
||||||
|
p.setoutput(data_in)
|
||||||
|
p.setoutput(en_pll_clk)
|
||||||
|
p.setoutput(cnt_en_2)
|
||||||
|
p.setoutput(DACINT)
|
||||||
|
p.setinput(data_out_slow)
|
||||||
|
p.setinput(COMP2_MON)
|
||||||
|
p.setoutput(start_read)
|
||||||
|
p.setoutput(dac_store)
|
||||||
|
p.setinput(CNT3_MON)
|
||||||
|
p.setoutput(EN_PIX_DIG_MON)
|
||||||
|
p.setoutput(clk_sel)
|
||||||
|
p.setinput(BUSY)
|
||||||
|
p.setinput(COMP3_MON)
|
||||||
|
p.setinput(CNT2_MON)
|
||||||
|
|
||||||
|
#system signals
|
||||||
|
p.setoutput(adc_ena)
|
||||||
|
# FIFO LATCH
|
||||||
|
p.setoutput(dbit_ena)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_first_two_PW():
|
||||||
|
p = PatternGenerator()
|
||||||
|
|
||||||
|
#The pattern is created with a single empty word
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 0
|
||||||
|
|
||||||
|
p.SB(8)
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
#When doing the first PW the empty word is overwritten
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 0
|
||||||
|
assert p.pattern.word[0] == 256
|
||||||
|
|
||||||
|
p.SB(9)
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
#When doing the second PW we add a new word
|
||||||
|
assert p.pattern.limits[0] == 0
|
||||||
|
assert p.pattern.limits[1] == 1
|
||||||
|
assert p.pattern.word[0] == 256
|
||||||
|
assert p.pattern.word[1] == 768
|
||||||
|
|
||||||
|
def test_simple_pattern():
|
||||||
|
"""
|
||||||
|
Using enable pll pattern for MH02
|
||||||
|
"""
|
||||||
|
en_pll_clk = 15
|
||||||
|
p = PatternGenerator()
|
||||||
|
p = apply_detconf(p)
|
||||||
|
p.SB(en_pll_clk)
|
||||||
|
p.PW()
|
||||||
|
p.PW()
|
||||||
|
|
||||||
|
lines = str(p).split("\n")
|
||||||
|
|
||||||
|
enable_pll_pattern = [
|
||||||
|
"patword 0x0000 0x0000000000008000",
|
||||||
|
"patword 0x0001 0x0000000000008000",
|
||||||
|
"patioctrl 0xc000000001b3ffff",
|
||||||
|
"patlimits 0x0000 0x0001",
|
||||||
|
"patloop 0 0x1fff 0x1fff",
|
||||||
|
"patnloop 0 0",
|
||||||
|
"patloop 1 0x1fff 0x1fff",
|
||||||
|
"patnloop 1 0",
|
||||||
|
"patloop 2 0x1fff 0x1fff",
|
||||||
|
"patnloop 2 0",
|
||||||
|
"patloop 3 0x1fff 0x1fff",
|
||||||
|
"patnloop 3 0",
|
||||||
|
"patloop 4 0x1fff 0x1fff",
|
||||||
|
"patnloop 4 0",
|
||||||
|
"patloop 5 0x1fff 0x1fff",
|
||||||
|
"patnloop 5 0",
|
||||||
|
"patwait 0 0x1fff",
|
||||||
|
"patwaittime 0 0",
|
||||||
|
"patwait 1 0x1fff",
|
||||||
|
"patwaittime 1 0",
|
||||||
|
"patwait 2 0x1fff",
|
||||||
|
"patwaittime 2 0",
|
||||||
|
"patwait 3 0x1fff",
|
||||||
|
"patwaittime 3 0",
|
||||||
|
"patwait 4 0x1fff",
|
||||||
|
"patwaittime 4 0",
|
||||||
|
"patwait 5 0x1fff",
|
||||||
|
"patwaittime 5 0",
|
||||||
|
]
|
||||||
|
|
||||||
|
assert len(lines) == len(enable_pll_pattern)
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
assert line == enable_pll_pattern[i]
|
50
python/tests/test_bits.py
Normal file
50
python/tests/test_bits.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
from slsdet.bits import clearbit, clearbit_arr, setbit, setbit_arr
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_on_python_int():
|
||||||
|
val = 5 # 0b101
|
||||||
|
r = clearbit(0, val)
|
||||||
|
assert r == 4
|
||||||
|
assert val == 5
|
||||||
|
|
||||||
|
def test_setbit_on_python_int():
|
||||||
|
val = 5 # 0b101
|
||||||
|
r = setbit(1, val)
|
||||||
|
assert r == 7
|
||||||
|
assert val == 5
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_doesnt_change_type():
|
||||||
|
word = np.int32(5)
|
||||||
|
ret = setbit(0, word)
|
||||||
|
assert isinstance(ret, np.int32)
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_doesnt_change_type():
|
||||||
|
word = np.uint8(5)
|
||||||
|
ret = clearbit(0, word)
|
||||||
|
assert isinstance(ret, np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_on_array_element():
|
||||||
|
arr = np.zeros(10, dtype=np.uint64)
|
||||||
|
arr[5] = setbit(0, arr[5])
|
||||||
|
arr[5] = setbit(1, arr[5])
|
||||||
|
arr[5] = setbit(4, arr[5])
|
||||||
|
assert arr[4] == 0
|
||||||
|
assert arr[5] == 19 # 0b10011
|
||||||
|
assert arr[6] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_setbit_arr():
|
||||||
|
arr = np.zeros(10, dtype=np.int32)
|
||||||
|
setbit_arr(3, arr[3:9])
|
||||||
|
assert all(arr == np.array((0, 0, 0, 8, 8, 8, 8, 8, 8, 0), dtype=np.int32))
|
||||||
|
|
||||||
|
|
||||||
|
def test_clearbit_arr():
|
||||||
|
arr = np.array((5, 5, 5), dtype=np.int8)
|
||||||
|
clearbit_arr(0, arr)
|
||||||
|
assert all(arr == (4, 4, 4))
|
1
serverBin/ctbDetectorServer_developer
Symbolic link
1
serverBin/ctbDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.1.0
|
|
1
serverBin/eigerDetectorServer_developer
Symbolic link
1
serverBin/eigerDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServerv9.0.0
|
|
1
serverBin/gotthard2DetectorServer_developer
Symbolic link
1
serverBin/gotthard2DetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServerv9.0.0
|
|
1
serverBin/gotthardDetectorServer_developer
Symbolic link
1
serverBin/gotthardDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServerv9.0.0
|
|
1
serverBin/jungfrauDetectorServer_developer
Symbolic link
1
serverBin/jungfrauDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0
|
|
1
serverBin/moenchDetectorServer_developer
Symbolic link
1
serverBin/moenchDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServerv9.0.0
|
|
1
serverBin/mythen3DetectorServer_developer
Symbolic link
1
serverBin/mythen3DetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.1.1
|
|
1
serverBin/xilinx_ctbDetectorServer_developer
Symbolic link
1
serverBin/xilinx_ctbDetectorServer_developer
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer
|
@ -1 +0,0 @@
|
|||||||
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.1.0
|
|
@ -3,14 +3,14 @@
|
|||||||
#ifndef ANALOGDETECTOR_H
|
#ifndef ANALOGDETECTOR_H
|
||||||
#define ANALOGDETECTOR_H
|
#define ANALOGDETECTOR_H
|
||||||
|
|
||||||
//#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "commonModeSubtractionNew.h"
|
#include "commonModeSubtractionNew.h"
|
||||||
#include "ghostSummation.h"
|
#include "ghostSummation.h"
|
||||||
#include "pedestalSubtraction.h"
|
#include "pedestalSubtraction.h"
|
||||||
|
#include "sls/tiffIO.h"
|
||||||
#include "slsDetectorData.h"
|
#include "slsDetectorData.h"
|
||||||
#include "slsInterpolation.h"
|
#include "slsInterpolation.h"
|
||||||
#include "sls/tiffIO.h"
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#ifdef ROOTSPECTRUM
|
#ifdef ROOTSPECTRUM
|
||||||
@ -90,6 +90,8 @@ template <class dataType> class analogDetector {
|
|||||||
ymin = 0;
|
ymin = 0;
|
||||||
ymax = ny;
|
ymax = ny;
|
||||||
fMode = ePedestal;
|
fMode = ePedestal;
|
||||||
|
dMode = eInterpolating;
|
||||||
|
// std::cout << "dMode " << dMode << std::endl;
|
||||||
thr = 0;
|
thr = 0;
|
||||||
myFile = NULL;
|
myFile = NULL;
|
||||||
#ifdef ROOTSPECTRUM
|
#ifdef ROOTSPECTRUM
|
||||||
@ -111,15 +113,20 @@ template <class dataType> class analogDetector {
|
|||||||
destructor. Deletes the pdestalSubtraction array and the image
|
destructor. Deletes the pdestalSubtraction array and the image
|
||||||
*/
|
*/
|
||||||
virtual ~analogDetector() {
|
virtual ~analogDetector() {
|
||||||
|
// std::cout << "#### Debug: Destructing analogDetector! ####"
|
||||||
|
// << std::endl;
|
||||||
for (int i = 0; i < ny; i++) {
|
for (int i = 0; i < ny; i++) {
|
||||||
delete[] stat[i];
|
if (stat[i]) { delete[] stat[i]; stat[i] = nullptr; }
|
||||||
|
// delete[] stat[i];
|
||||||
/* delete [] pedMean[i]; */
|
/* delete [] pedMean[i]; */
|
||||||
/* delete [] pedVariance[i]; */
|
/* delete [] pedVariance[i]; */
|
||||||
};
|
}
|
||||||
/* delete [] pedMean; */
|
/* delete [] pedMean; */
|
||||||
/* delete [] pedVariance; */
|
/* delete [] pedVariance; */
|
||||||
delete[] stat;
|
// delete[] stat;
|
||||||
delete[] image;
|
// delete[] image;
|
||||||
|
if (stat) { delete[] stat; stat = nullptr; }
|
||||||
|
if (image) { delete[] image; image = nullptr; }
|
||||||
#ifdef ROOTSPECTRUM
|
#ifdef ROOTSPECTRUM
|
||||||
delete hs;
|
delete hs;
|
||||||
#ifdef ROOTCLUST
|
#ifdef ROOTCLUST
|
||||||
@ -137,6 +144,8 @@ template <class dataType> class analogDetector {
|
|||||||
*/
|
*/
|
||||||
analogDetector(analogDetector *orig) {
|
analogDetector(analogDetector *orig) {
|
||||||
/* copy construction from orig*/
|
/* copy construction from orig*/
|
||||||
|
// std::cout << "#### Debug: Calling analogDetector cloning method! ####"
|
||||||
|
// << std::endl;
|
||||||
det = orig->det;
|
det = orig->det;
|
||||||
nx = orig->nx;
|
nx = orig->nx;
|
||||||
ny = orig->ny;
|
ny = orig->ny;
|
||||||
@ -152,6 +161,8 @@ template <class dataType> class analogDetector {
|
|||||||
thr = orig->thr;
|
thr = orig->thr;
|
||||||
// nSigma=orig->nSigma;
|
// nSigma=orig->nSigma;
|
||||||
fMode = orig->fMode;
|
fMode = orig->fMode;
|
||||||
|
dMode = orig->dMode;
|
||||||
|
// std::cout << "dMode " << dMode << std::endl;
|
||||||
myFile = orig->myFile;
|
myFile = orig->myFile;
|
||||||
|
|
||||||
stat = new pedestalSubtraction *[ny];
|
stat = new pedestalSubtraction *[ny];
|
||||||
@ -216,12 +227,75 @@ template <class dataType> class analogDetector {
|
|||||||
ghSum = NULL;
|
ghSum = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
constructor creating a deep copy of another analog detector
|
||||||
|
\param other analog Detector structure to be copied
|
||||||
|
*/
|
||||||
|
analogDetector(const analogDetector &other)
|
||||||
|
: det(other.det), nx(other.nx), ny(other.ny), dataSign(other.dataSign),
|
||||||
|
iframe(other.iframe), gmap(other.gmap), id(other.id),
|
||||||
|
xmin(other.xmin), xmax(other.xmax), ymin(other.ymin),
|
||||||
|
ymax(other.ymax), thr(other.thr), fMode(other.fMode),
|
||||||
|
dMode(other.dMode), myFile(NULL) {
|
||||||
|
|
||||||
|
// std::cout << "#### Debug: Calling analogDetector copy constructor! ####"
|
||||||
|
// << std::endl;
|
||||||
|
|
||||||
|
// Deep copy the stat array
|
||||||
|
stat = new pedestalSubtraction *[ny];
|
||||||
|
for (int i = 0; i < ny; i++) {
|
||||||
|
stat[i] = new pedestalSubtraction[nx];
|
||||||
|
std::copy(other.stat[i], other.stat[i] + nx, stat[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy image array
|
||||||
|
image = new int[nx * ny];
|
||||||
|
std::copy(other.image, other.image + (nx * ny), image);
|
||||||
|
|
||||||
|
// Copy common-mode subtraction object (if it exists)
|
||||||
|
if (other.cmSub) {
|
||||||
|
cmSub = other.cmSub->Clone();
|
||||||
|
std::cout << "Copying cmSub" << std::endl;
|
||||||
|
} else {
|
||||||
|
cmSub = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy ghost summation object (if it exists)
|
||||||
|
if (other.ghSum) {
|
||||||
|
ghSum = other.ghSum->Clone();
|
||||||
|
std::cout << "Copying ghSum" << std::endl;
|
||||||
|
} else {
|
||||||
|
ghSum = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure pedestal values are copied properly
|
||||||
|
int nped = other.GetNPedestals(0, 0);
|
||||||
|
for (int iy = 0; iy < ny; ++iy) {
|
||||||
|
for (int ix = 0; ix < nx; ++ix) {
|
||||||
|
stat[iy][ix].SetNPedestals(nped);
|
||||||
|
setPedestal(ix, iy, other.getPedestal(ix, iy),
|
||||||
|
other.getPedestalRMS(ix, iy),
|
||||||
|
other.GetNPedestals(ix, iy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
clone. Must be virtual!
|
clone. Must be virtual!
|
||||||
\returns a clone of the original analog detector
|
\returns a clone of the original analog detector
|
||||||
*/
|
*/
|
||||||
virtual analogDetector *Clone() = 0;
|
virtual analogDetector *Clone() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deep copy. Must be virtual!
|
||||||
|
This is a new addition because of multithreaded storage cell data (where
|
||||||
|
each sc has its own mutex). If the pure virtual function exists here,
|
||||||
|
EVERY derived class has to overwrite it! That means a Copy() function
|
||||||
|
must also be implemented in any derived class. \returns a deep copy of
|
||||||
|
the original analog detector
|
||||||
|
*/
|
||||||
|
virtual analogDetector *Copy() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gives an id to the structure. For debugging purposes in case of
|
Gives an id to the structure. For debugging purposes in case of
|
||||||
multithreading. \param i is to be set \returns current id
|
multithreading. \param i is to be set \returns current id
|
||||||
@ -548,6 +622,11 @@ template <class dataType> class analogDetector {
|
|||||||
return ped;
|
return ped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Const version for use in the copy constructor
|
||||||
|
virtual double getPedestal(int ix, int iy, int cm = 0) const {
|
||||||
|
return stat[iy][ix].getPedestal();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
gets pedestal rms (i.e. noise)
|
gets pedestal rms (i.e. noise)
|
||||||
\param ix pixel x coordinate
|
\param ix pixel x coordinate
|
||||||
@ -566,6 +645,11 @@ template <class dataType> class analogDetector {
|
|||||||
return ped;
|
return ped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Const version for use in the copy constructor
|
||||||
|
virtual double getPedestalRMS(int ix, int iy) const {
|
||||||
|
return stat[iy][ix].getPedestalRMS();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
sets pedestal
|
sets pedestal
|
||||||
\param ix pixel x coordinate
|
\param ix pixel x coordinate
|
||||||
@ -1226,7 +1310,7 @@ template <class dataType> class analogDetector {
|
|||||||
/** gets number of samples for moving average pedestal calculation
|
/** gets number of samples for moving average pedestal calculation
|
||||||
\returns actual number of samples
|
\returns actual number of samples
|
||||||
*/
|
*/
|
||||||
int GetNPedestals(int ix, int iy) {
|
int GetNPedestals(int ix, int iy) const {
|
||||||
if (ix >= 0 && ix < nx && iy >= 0 && iy < ny)
|
if (ix >= 0 && ix < nx && iy >= 0 && iy < ny)
|
||||||
return stat[iy][ix].GetNPedestals();
|
return stat[iy][ix].GetNPedestals();
|
||||||
else
|
else
|
||||||
|
@ -50,6 +50,8 @@ template <typename Element> class CircularFifo {
|
|||||||
mutable sem_t data_mutex;
|
mutable sem_t data_mutex;
|
||||||
mutable sem_t free_mutex;
|
mutable sem_t free_mutex;
|
||||||
unsigned int increment(unsigned int idx_) const;
|
unsigned int increment(unsigned int idx_) const;
|
||||||
|
int id_;
|
||||||
|
int thread_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Element> int CircularFifo<Element>::getDataValue() const {
|
template <typename Element> int CircularFifo<Element>::getDataValue() const {
|
||||||
@ -74,14 +76,18 @@ template <typename Element> int CircularFifo<Element>::getFreeValue() const {
|
|||||||
template <typename Element>
|
template <typename Element>
|
||||||
bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
|
bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
|
||||||
// check for fifo full
|
// check for fifo full
|
||||||
if (no_block && isFull())
|
if (no_block && isFull()) {
|
||||||
return false;
|
//std::cout << "Full Fifo at push. Returning." << std::endl;
|
||||||
|
return false; // No space, return immediately
|
||||||
|
}
|
||||||
|
|
||||||
sem_wait(&free_mutex);
|
//std::cout << "Thread " << thread_id_ <<" Push Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
|
||||||
array[tail] = item_;
|
|
||||||
tail = increment(tail);
|
sem_wait(&free_mutex); // Wait for space
|
||||||
sem_post(&data_mutex);
|
array[tail] = item_; // Add item to the buffer
|
||||||
return true;
|
tail = increment(tail); // Move the tail pointer
|
||||||
|
sem_post(&data_mutex); // Signal that there is new data
|
||||||
|
return true; // Success
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Consumer only: Removes and returns item from the queue
|
/** Consumer only: Removes and returns item from the queue
|
||||||
@ -94,14 +100,18 @@ bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
|
|||||||
template <typename Element>
|
template <typename Element>
|
||||||
bool CircularFifo<Element>::pop(Element *&item_, bool no_block) {
|
bool CircularFifo<Element>::pop(Element *&item_, bool no_block) {
|
||||||
// check for fifo empty
|
// check for fifo empty
|
||||||
if (no_block && isEmpty())
|
if (no_block && isEmpty()) {
|
||||||
return false;
|
//std::cout << "Empty Fifo at pop. Returning." << std::endl;
|
||||||
|
return false; // No data in fifo, return immediately
|
||||||
|
}
|
||||||
|
|
||||||
sem_wait(&data_mutex);
|
//std::cout << "Thread " << thread_id_ << " Pop Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
|
||||||
item_ = array[head];
|
|
||||||
head = increment(head);
|
sem_wait(&data_mutex); // Wait for data
|
||||||
sem_post(&free_mutex);
|
item_ = array[head]; // Retreive item from the current head of the buffer
|
||||||
return true;
|
head = increment(head); // Move the head pointer (to point to the next item)
|
||||||
|
sem_post(&free_mutex); // Signal that there is new free space available
|
||||||
|
return true; //Success
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Useful for testinng and Consumer check of status
|
/** Useful for testinng and Consumer check of status
|
||||||
|
482
slsDetectorCalibration/dataStructures/HDF5File.cpp
Normal file
482
slsDetectorCalibration/dataStructures/HDF5File.cpp
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
#include "HDF5File.h"
|
||||||
|
|
||||||
|
#include "ansi.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fmt/ranges.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No class member helper functions
|
||||||
|
*/
|
||||||
|
std::string vectorToString(std::vector<hsize_t> const& v) {
|
||||||
|
return fmt::format("({})", fmt::join(v, ", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* increment frame offset (if s dimension exists, loop through all before incrementing z)
|
||||||
|
* should also work if file_dims[1] is not s but x (in that case we ignore it)
|
||||||
|
*/
|
||||||
|
void conditionalIncrement(std::vector<hsize_t>& vec, hsize_t max_value) {
|
||||||
|
|
||||||
|
if (vec.size() < 3) {
|
||||||
|
throw std::invalid_argument("Vector must have at least 3 elements.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If vector has 4 elements, increment vec[1] first
|
||||||
|
if (vec.size() == 4) {
|
||||||
|
if (++vec[1] >= max_value) { //max_value is never reached!
|
||||||
|
vec[1] = 0; // Reset and increment vec[0]
|
||||||
|
++vec[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If vector has 3 elements, increment vec[0] directly
|
||||||
|
else if (vec.size() == 3) {
|
||||||
|
++vec[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDatatypeSize(hid_t dataset) {
|
||||||
|
|
||||||
|
hid_t datatype = H5Dget_type(dataset);
|
||||||
|
H5T_class_t class_id = H5Tget_class(datatype);
|
||||||
|
size_t type_size = H5Tget_size(datatype);
|
||||||
|
|
||||||
|
H5Tclose(datatype);
|
||||||
|
|
||||||
|
std::cout << " dataset type class: " << class_id
|
||||||
|
<< ", size: " << type_size << " bytes\n";
|
||||||
|
|
||||||
|
//Ensure the read datatype matches a system native type correctly
|
||||||
|
//hid_t read_type = (type_size == 8) ? H5T_NATIVE_LLONG : H5T_NATIVE_UINT;
|
||||||
|
|
||||||
|
//return read_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* **********************
|
||||||
|
* Class member functions
|
||||||
|
* **********************
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
/*
|
||||||
|
HDF5File::HDF5File () {
|
||||||
|
//InitializeParameters(); //old
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
HDF5File::~HDF5File () {
|
||||||
|
|
||||||
|
if(current_image)
|
||||||
|
delete [] current_image;
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void HDF5File::SetImageDataPath (std::string const& name) {
|
||||||
|
std::cout << "Image dataset path set to " << name << std::endl;
|
||||||
|
data_datasetname = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDF5File::SetFrameIndexPath (std::string const& name) {
|
||||||
|
std::cout << "Frame index dataset path set to " << name << std::endl;
|
||||||
|
index_datasetname = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDF5File::InitializeDimensions () {
|
||||||
|
|
||||||
|
rank = H5Sget_simple_extent_ndims(dataspace);
|
||||||
|
file_dims.resize(rank);
|
||||||
|
H5Sget_simple_extent_dims(dataspace, file_dims.data(), nullptr);
|
||||||
|
|
||||||
|
std::cout << "Dataset dimensions: " << vectorToString(file_dims) << "\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<hsize_t> HDF5File::GetDatasetDimensions() {
|
||||||
|
return file_dims;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<hsize_t> HDF5File::GetChunkDimensions() {
|
||||||
|
return chunk_dims;
|
||||||
|
}
|
||||||
|
|
||||||
|
hsize_t HDF5File::GetRank() {
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HDF5File::ValidateDimensions () {
|
||||||
|
|
||||||
|
// validate rank
|
||||||
|
if(rank != RANK) {
|
||||||
|
cprintf(RED,"rank found %llu. Expected %d\n", rank, RANK);
|
||||||
|
std::cerr << "Error: Rank could not be validated\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate file dimensions of x and y (assuming those are the last two dimensions of the dataset)
|
||||||
|
if ( (file_dims[file_dims.size()-2] != DEFAULT_X_DIMS) || (file_dims[file_dims.size()-1] != DEFAULT_Y_DIMS) ) {
|
||||||
|
cprintf(RED,"file dimensions of x found %llu. Expected %d\n", file_dims[file_dims.size()-2], DEFAULT_X_DIMS);
|
||||||
|
cprintf(RED,"file dimensions of y found %llu. Expected %d\n", file_dims[file_dims.size()-1], DEFAULT_Y_DIMS);
|
||||||
|
std::cerr << "Error: Dataset dimensions could not be validated\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cprintf(GREEN, "File rank & dimensions validated.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HDF5File::ReadChunkDimensions () {
|
||||||
|
|
||||||
|
// Get layout
|
||||||
|
hid_t plist_id = H5Dget_create_plist(dataset);
|
||||||
|
|
||||||
|
if (H5Pget_layout (plist_id) != H5D_CHUNKED) {
|
||||||
|
cprintf(RED,"NOTE: Dataset is not chunked!\n");
|
||||||
|
std::cerr << "Error: Dataset is not chunked\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Chunk Dimensions
|
||||||
|
int rank_chunk = H5Pget_chunk (plist_id, 0, nullptr);
|
||||||
|
chunk_dims.resize(rank_chunk);
|
||||||
|
H5Pget_chunk (plist_id, rank_chunk, chunk_dims.data());
|
||||||
|
|
||||||
|
std::cout << "Chunk dimensions: " << vectorToString(chunk_dims) << "\n";
|
||||||
|
|
||||||
|
H5Pclose (plist_id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HDF5File::ValidateChunkDimensions () {
|
||||||
|
|
||||||
|
// validate rank
|
||||||
|
if(chunk_dims.size() != rank) {
|
||||||
|
cprintf(RED,"Chunk rank does not match dataset rank! Found %lu. Expected %llu\n", chunk_dims.size(), rank);
|
||||||
|
std::cerr << "Error: Chunk rank does not match dataset rank\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate chunk dimensions of x and y (assuming those are the last two dimensions of the dataset)
|
||||||
|
if ( (chunk_dims[chunk_dims.size()-2] != DEFAULT_CHUNK_X_DIMS) || (chunk_dims[chunk_dims.size()-1] != DEFAULT_CHUNK_Y_DIMS) ) {
|
||||||
|
cprintf(RED,"file dimensions of x found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-2], DEFAULT_CHUNK_X_DIMS);
|
||||||
|
cprintf(RED,"file dimensions of y found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-1], DEFAULT_CHUNK_Y_DIMS);
|
||||||
|
std::cerr << "Error: Chunk dimensions could not be validated\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cprintf(GREEN, "Chunk rank & dimensions validated.");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HDF5File::OpenFrameIndexDataset() {
|
||||||
|
|
||||||
|
// Get all the frame numbers
|
||||||
|
// Open frame index dataset
|
||||||
|
hid_t fi_dataset = H5Dopen2 (file, index_datasetname.c_str(), H5P_DEFAULT);
|
||||||
|
if (fi_dataset < 0){
|
||||||
|
cprintf (RED,"Could not open frame index dataset %s\n", index_datasetname.c_str());
|
||||||
|
std::cerr << "Error: Could not open frame index dataset\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hid_t fi_dataspace = H5Dget_space (fi_dataset);
|
||||||
|
int fi_rank = H5Sget_simple_extent_ndims(fi_dataspace);
|
||||||
|
std::vector<hsize_t> fi_dims(fi_rank);
|
||||||
|
H5Sget_simple_extent_dims (fi_dataspace, fi_dims.data(), nullptr);
|
||||||
|
|
||||||
|
std::cout << "Frame index dataset dimensions: " << vectorToString(fi_dims) << "\n";
|
||||||
|
|
||||||
|
// validate size
|
||||||
|
if (fi_dims[0] != file_dims[0]) {
|
||||||
|
cprintf (RED,"Frame index dimensions of z found %llu. Expected %llu\n", fi_dims[0], file_dims[0]);
|
||||||
|
std::cerr << "Error: Z dimension of frame index dataset does not align with z dimension of image dataset\n";
|
||||||
|
H5Sclose (fi_dataspace);
|
||||||
|
H5Dclose (fi_dataset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate frame index memory
|
||||||
|
frame_index_list.resize(fi_dims[0]); //file_dims
|
||||||
|
|
||||||
|
// read and print datatype size of dataset
|
||||||
|
std::cout << "Frame index";
|
||||||
|
printDatatypeSize(fi_dataset);
|
||||||
|
|
||||||
|
// make sure we only read the first column of the frame index dataset (not all storage cells)
|
||||||
|
//NOTE: For XFEL datasets, this may mean that some frame numbers are skipped
|
||||||
|
//(because they assign a unique frame number to every storage cell)
|
||||||
|
//Possibly, there is a cleaner fix for this...
|
||||||
|
std::vector<hsize_t> start(fi_rank,0);
|
||||||
|
std::vector<hsize_t> count(fi_rank,1);
|
||||||
|
count[0] = fi_dims[0];
|
||||||
|
hid_t memspace = H5Screate_simple (fi_rank, count.data(), nullptr);
|
||||||
|
if (memspace < 0) {
|
||||||
|
std::cerr << "Error: Failed to create memory space for HDF5 read operation\n";
|
||||||
|
H5Sclose(memspace);
|
||||||
|
H5Sclose(fi_dataspace);
|
||||||
|
H5Dclose(fi_dataset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create hyperslab selection
|
||||||
|
if (H5Sselect_hyperslab(fi_dataspace, H5S_SELECT_SET, start.data(), nullptr, count.data(), nullptr) < 0 ) {
|
||||||
|
cprintf (RED,"Could not create hyperslab for %s\n", vectorToString(start).c_str());
|
||||||
|
std::cerr << "Error: Hyperslab creation failed for " << vectorToString(start) << "\n";
|
||||||
|
H5Sclose(memspace);
|
||||||
|
H5Sclose (fi_dataspace);
|
||||||
|
H5Dclose(fi_dataset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//read frame index values
|
||||||
|
//Is u32 correct? I would think not. But I get a segmentation fault if I use u64.
|
||||||
|
if (H5Dread (fi_dataset, H5T_STD_U64LE, memspace, fi_dataspace, H5P_DEFAULT, frame_index_list.data()) < 0) {
|
||||||
|
cprintf (RED,"Could not read frame index dataset %s\n", index_datasetname.c_str());
|
||||||
|
std::cerr << "Error: Could not read frame index dataset\n";
|
||||||
|
H5Sclose(memspace);
|
||||||
|
H5Sclose (fi_dataspace);
|
||||||
|
H5Dclose (fi_dataset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
H5Sclose(memspace);
|
||||||
|
H5Sclose (fi_dataspace);
|
||||||
|
H5Dclose(fi_dataset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HDF5File::OpenResources (char const*const fname, bool validate) {
|
||||||
|
|
||||||
|
std::cout << "Debug HDF5File.cpp: Attempting to open file " << fname << std::endl;
|
||||||
|
// Open File
|
||||||
|
file = H5Fopen (fname, H5F_ACC_RDONLY, H5P_DEFAULT);
|
||||||
|
if (file < 0) {
|
||||||
|
cprintf(RED,"Could not open hdf5 file\n");
|
||||||
|
std::cerr << "Error: H5Fopen failed\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cprintf(BLUE, "Opened File: %s\n", fname);
|
||||||
|
|
||||||
|
// Open Dataset
|
||||||
|
dataset = H5Dopen2 (file, data_datasetname.c_str(), H5P_DEFAULT);
|
||||||
|
if (dataset < 0){
|
||||||
|
cprintf(RED,"Could not open dataset\n");
|
||||||
|
std::cerr << "Error: H5Dopen2 failed\n";
|
||||||
|
CloseResources ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cprintf(BLUE, "Opened Dataset: %s\n", data_datasetname.c_str());
|
||||||
|
|
||||||
|
// print datatype size of dataset
|
||||||
|
std::cout << "Image";
|
||||||
|
printDatatypeSize(dataset);
|
||||||
|
|
||||||
|
// Create Dataspace
|
||||||
|
dataspace = H5Dget_space (dataset);
|
||||||
|
if (dataspace < 0){
|
||||||
|
cprintf(RED,"Could not open dataspace\n");
|
||||||
|
std::cerr << "Error: H5Dget_space failed\n";
|
||||||
|
CloseResources ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Dimensions
|
||||||
|
InitializeDimensions();
|
||||||
|
// Get chunk dimensions
|
||||||
|
if (!ReadChunkDimensions()) {
|
||||||
|
CloseResources();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate file dimensions
|
||||||
|
if (validate) {
|
||||||
|
if ( !ValidateDimensions() || !ValidateChunkDimensions() ) {
|
||||||
|
CloseResources();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read frame indices
|
||||||
|
if (!OpenFrameIndexDataset()) {
|
||||||
|
CloseResources();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HDF5File::CloseResources () {
|
||||||
|
if (dataspace >=0 ) {
|
||||||
|
H5Sclose(dataspace);
|
||||||
|
dataspace = -1;
|
||||||
|
}
|
||||||
|
if (dataset >=0 ) {
|
||||||
|
H5Dclose(dataset);
|
||||||
|
dataset = -1;
|
||||||
|
}
|
||||||
|
if (file >=0 ) {
|
||||||
|
H5Fclose(file);
|
||||||
|
file = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function takes uint16_t* argument to make explicit that the caller has to handle memory allocation and deallocation.
|
||||||
|
* This is legacy caused by the structure with which the slsDetectorCalibration cluster finder is written.
|
||||||
|
* (Best practice for modern C++ would be using smart pointers.)
|
||||||
|
*
|
||||||
|
* Originially, this function took uint16_t** which may lead to memory management issues since image gets redirected
|
||||||
|
* to point to current_image, which is owned by HDF5File.
|
||||||
|
* (Good practice in classic C-style. HDF5File needs to clean up the resource at destruction.)
|
||||||
|
*
|
||||||
|
* \param image pointer to uint16_t, buffer which the image is read into. (Memory handled by caller!)
|
||||||
|
* \param offset contains iFrame at [0] and storage cell number at [1],
|
||||||
|
* depending on dimensionality of the dataset, the storage cell number may not be included.
|
||||||
|
* Note that frame number (as read from file) may (likely) differ from frame index (in the dataset)!
|
||||||
|
*/
|
||||||
|
int HDF5File::ReadImage (uint16_t* image, std::vector<hsize_t>& offset ) {
|
||||||
|
|
||||||
|
// Validate input arguments
|
||||||
|
if (!image) {
|
||||||
|
std::cerr << "Error: image buffer is null.\n";
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
if ( offset.size() != rank-2 ) {
|
||||||
|
cprintf ( RED,"Offset vector must have size %llu. Found %lu\n", rank-2, offset.size() );
|
||||||
|
std::cerr << "Error: Wrong offset vector size\n";
|
||||||
|
CloseResources ();
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize frame_offset
|
||||||
|
if (frame_offset.empty())
|
||||||
|
frame_offset.resize(rank,0);
|
||||||
|
|
||||||
|
// Check if we reached the end of file
|
||||||
|
// Compares that the offsets of frame and storage cell (Z and S) have reached the end of file
|
||||||
|
// Excludes X and Y indices (of the image dataset) from the comparison
|
||||||
|
// As it is now, this never triggers, because frame_offset[1] is never equals file_dims[1]=16
|
||||||
|
/*
|
||||||
|
if( std::equal( frame_offset.cbegin(), frame_offset.cend()-2, file_dims.cbegin() ) ) {
|
||||||
|
printf("End of file reached\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (frame_offset[0] == file_dims[0]) {
|
||||||
|
printf("End of file reached\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* //old
|
||||||
|
if (frame_offset[0] == file_dims[0]-1) {
|
||||||
|
printf("end of file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Validate frame_offset index
|
||||||
|
if (frame_offset[0] >= frame_index_list.size()) {
|
||||||
|
std::cerr << "Error: frame_offset[0] = " << frame_offset[0] << " of bounds.\n";
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if images exist at the current frame offset
|
||||||
|
if (frame_index_list[frame_offset[0]] == 0) {
|
||||||
|
cprintf (RED,"No images at this frame offset %llu\n", frame_offset[0]);
|
||||||
|
std::cerr << "Error: Framenumber 0 at this frame offset\n";
|
||||||
|
CloseResources ();
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: Ensure dataset and dataspace are valid
|
||||||
|
if (dataset < 0) {
|
||||||
|
std::cerr << "Error: Invalid dataset ID.\n";
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
if (dataspace < 0) {
|
||||||
|
std::cerr << "Error: Invalid dataspace.\n";
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the size of the hyperslab to read
|
||||||
|
std::vector<hsize_t> frame_size(rank, 1);
|
||||||
|
std::copy(file_dims.begin() + rank-2, file_dims.end(), frame_size.begin() + rank-2);
|
||||||
|
/*
|
||||||
|
for ( int d=0; d < rank; ++d ) {
|
||||||
|
if (d < rank-2)
|
||||||
|
frame_size[d] = 1;
|
||||||
|
if ( d >= rank-2 )
|
||||||
|
frame_size[d] = file_dims[d];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Define memory space
|
||||||
|
hid_t memspace = H5Screate_simple (rank, frame_size.data(), nullptr);
|
||||||
|
if (memspace < 0) {
|
||||||
|
std::cerr << "Error: Failed to create memory space for HDF5 read operation\n";
|
||||||
|
CloseResources();
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create hyperslab selection
|
||||||
|
// This aligns dataspace such that we read the correct frame
|
||||||
|
if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, frame_offset.data(), nullptr, frame_size.data(), nullptr) < 0 ) {
|
||||||
|
cprintf (RED,"Could not create hyperslab for frame offset %s\n", vectorToString(frame_offset).c_str());
|
||||||
|
std::cerr << "Error: Hyperslab creation failed for frame offset " << vectorToString(frame_offset) << "\n";
|
||||||
|
CloseResources();
|
||||||
|
H5Sclose(memspace);
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read dataset into image buffer (previously read to current_image owned by HDF5File)
|
||||||
|
if (H5Dread(dataset, H5T_STD_U16LE, memspace, dataspace, H5P_DEFAULT, image) < 0 ) {
|
||||||
|
cprintf (RED,"Could not read dataset for frame offset %s\n", vectorToString(frame_offset).c_str());
|
||||||
|
std::cerr << "Error: Reading of dataset failed for given start frame offset " << vectorToString(frame_offset) << "\n";
|
||||||
|
CloseResources ();
|
||||||
|
H5Sclose(memspace);
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up memory space
|
||||||
|
H5Sclose(memspace);
|
||||||
|
|
||||||
|
//*image = current_image; //if uint16_t** is passed, HDF5File owns the resource image points to, which is potentially dangerous
|
||||||
|
|
||||||
|
// Return frame number
|
||||||
|
unsigned int retval = frame_index_list[frame_offset[0]];
|
||||||
|
|
||||||
|
// Pass updated frame offset value(s) via offset parameter vector
|
||||||
|
std::copy_n(frame_offset.begin(), offset.size(), offset.begin());
|
||||||
|
/*
|
||||||
|
std::transform( offset.begin(), offset.end(), offset.begin(),
|
||||||
|
[&, i = 0](size_t) mutable { return frame_offset[i++]; } );
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Increment frame offset correctly
|
||||||
|
conditionalIncrement(frame_offset, file_dims[1]);
|
||||||
|
//++frame_offset[0]; //old
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HDF5File::PrintCurrentImage (uint16_t* image) {
|
||||||
|
printf("\n");
|
||||||
|
printf("Frame %llu, Image: %llu\n", frame_offset[0]-1, frame_index_list[frame_offset[0]-1]);
|
||||||
|
|
||||||
|
hsize_t size = file_dims[rank-1] * file_dims[rank-2];
|
||||||
|
for (hsize_t i = 0; i < size; ++i){
|
||||||
|
printf("%u ", image[i]);
|
||||||
|
if (!((i+1) % file_dims[rank-2] ))
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
printf("\n\n\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
159
slsDetectorCalibration/dataStructures/HDF5File.h
Normal file
159
slsDetectorCalibration/dataStructures/HDF5File.h
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#pragma once
|
||||||
|
/************************************************
|
||||||
|
* @file HDF5Fle.h
|
||||||
|
* @short functions to open/close/read HDF5 File
|
||||||
|
* Adapted for generalization, accepts rank 3 and 4
|
||||||
|
* Supports control over storage cells
|
||||||
|
***********************************************/
|
||||||
|
/**
|
||||||
|
*@short functions to open/close/read HDF5 File
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "hdf5.h"
|
||||||
|
#include "hdf5_hl.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#define MAX_STR_LENGTH 1000
|
||||||
|
|
||||||
|
#define RANK 4 // Dimension of the image dataset, only for validation
|
||||||
|
#define DEFAULT_Z_DIMS 10000 // only for validation
|
||||||
|
#define DEFAULT_Y_DIMS 1024 // only for validation
|
||||||
|
#define DEFAULT_X_DIMS 512 // only for validation
|
||||||
|
//#define DEFAULT_S_DIMS 1 // Storage cells
|
||||||
|
|
||||||
|
#define DEFAULT_CHUNK_Z_DIMS 1 // only for validation
|
||||||
|
#define DEFAULT_CHUNK_Y_DIMS 1024 // only for validation
|
||||||
|
#define DEFAULT_CHUNK_X_DIMS 512 // only for validation
|
||||||
|
//#define DEFAULT_CHUNK_S_DIMS 1
|
||||||
|
|
||||||
|
|
||||||
|
#define DATA_DATASETNAME "/data/JF18T01V01/data" //Furka JF
|
||||||
|
#define INDEX_DATASETNAME "/data/JF18T01V01/frame_index"
|
||||||
|
|
||||||
|
//enum{Z,S,X,Y}; //S is the storage cell //enum is not used
|
||||||
|
|
||||||
|
class HDF5File {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
//HDF5File () = default; //No need to declare if it is default
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
//~HDF5File () = default; //Since the destructor is default (and copy and move are default too)
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<hsize_t> GetDatasetDimensions ();
|
||||||
|
|
||||||
|
std::vector<hsize_t> GetChunkDimensions ();
|
||||||
|
|
||||||
|
hsize_t GetRank ();
|
||||||
|
|
||||||
|
void SetImageDataPath (std::string const& name);
|
||||||
|
|
||||||
|
void SetFrameIndexPath (std::string const& name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open HDF5 file and dataset,
|
||||||
|
* reads frame index dataset to array
|
||||||
|
* @param fname file name
|
||||||
|
* @param validate true if one must validate if file is
|
||||||
|
* chunked with dims [? x 128 x 512] and chunk dims [1 x 128 x 512]
|
||||||
|
* @returns 1 if successful, else 0 if fail
|
||||||
|
*/
|
||||||
|
int OpenResources (const char* const fname, bool validate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close Open resources
|
||||||
|
*/
|
||||||
|
void CloseResources ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an image into current_image,
|
||||||
|
* increment Z-offset (frame) and (if rank==4) storage cell
|
||||||
|
* @returns frame number read from file,
|
||||||
|
*/
|
||||||
|
int ReadImage (uint16_t* image, std::vector<hsize_t>& offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print current image in memory
|
||||||
|
*/
|
||||||
|
void PrintCurrentImage (uint16_t* image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize dimensions of image dataset for each new file
|
||||||
|
*/
|
||||||
|
void InitializeDimensions ();
|
||||||
|
|
||||||
|
bool ReadChunkDimensions ();
|
||||||
|
|
||||||
|
bool ValidateDimensions ();
|
||||||
|
|
||||||
|
bool ValidateChunkDimensions ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open dataset containing the frame numbers
|
||||||
|
*/
|
||||||
|
bool OpenFrameIndexDataset ();
|
||||||
|
|
||||||
|
|
||||||
|
/** file name */
|
||||||
|
std::string file_name{};
|
||||||
|
/** dataset name for image data */
|
||||||
|
std::string data_datasetname = DATA_DATASETNAME;
|
||||||
|
/** dataset name for frame index data */
|
||||||
|
std::string index_datasetname = INDEX_DATASETNAME;
|
||||||
|
|
||||||
|
/** file handle */
|
||||||
|
hid_t file{};
|
||||||
|
/** dataspace handle */
|
||||||
|
hid_t dataspace{};
|
||||||
|
/** memory space handle */
|
||||||
|
//hid_t memspace; //old
|
||||||
|
/** dataset handle */
|
||||||
|
hid_t dataset{};
|
||||||
|
|
||||||
|
/** file dimensions */
|
||||||
|
std::vector<hsize_t> file_dims{};
|
||||||
|
//hsize_t file_dims[RANK]{}; //static array (dimensions are known)
|
||||||
|
|
||||||
|
/** chunk dimensions
|
||||||
|
** not necessarily required
|
||||||
|
** useful for optimization or validation */
|
||||||
|
std::vector<hsize_t> chunk_dims{};
|
||||||
|
//hsize_t chunk_dims[RANK]{};
|
||||||
|
|
||||||
|
/** Rank of the image dataset */
|
||||||
|
hsize_t rank{};
|
||||||
|
|
||||||
|
/** number of frames */
|
||||||
|
unsigned int number_of_frames{};
|
||||||
|
|
||||||
|
/** frame index list */
|
||||||
|
std::vector<hsize_t> frame_index_list{};
|
||||||
|
|
||||||
|
/** Current image
|
||||||
|
** dynamic array
|
||||||
|
** uint16_t pointer format is chosen to support use with slsDetectorCalibration cluster finder */
|
||||||
|
//uint16_t* current_image{nullptr};
|
||||||
|
//uint16_t current_chunk[DEFAULT_CHUNK_Z_DIMS][DEFAULT_CHUNK_Y_DIMS][DEFAULT_CHUNK_X_DIMS];
|
||||||
|
|
||||||
|
/** Current frame offset
|
||||||
|
** (Z-offset, S-offset, 0, 0) or (Z-offset, 0, 0), increments automatically with ReadImage */
|
||||||
|
std::vector<hsize_t> frame_offset{};
|
||||||
|
//hsize_t frame_offset[RANK]{};
|
||||||
|
|
||||||
|
};
|
@ -1,155 +0,0 @@
|
|||||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
|
||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
||||||
#ifndef GOTTHARD2MODULEDATANEW_H
|
|
||||||
#define GOTTHARD2MODULEDATANEW_H
|
|
||||||
#include "gotthardModuleDataNew.h"
|
|
||||||
|
|
||||||
class gotthardDoubleModuleDataNew : public slsDetectorData<uint16_t> {
|
|
||||||
|
|
||||||
private:
|
|
||||||
const int nModules;
|
|
||||||
const int offset;
|
|
||||||
int iframe;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Implements the slsReceiverData structure for the gotthard read out by a module
|
|
||||||
i.e. using the slsReceiver (1x1280 pixels, 2 packets 1286 large etc.) \param c
|
|
||||||
crosstalk parameter for the output buffer
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
gotthardDoubleModuleDataNew(int off = 24 * 2, int nmod = 2)
|
|
||||||
: slsDetectorData<uint16_t>(1280 * nmod, 1, nmod * (1280 * 2 + off)),
|
|
||||||
nModules(nmod), offset(off), iframe(0) {
|
|
||||||
|
|
||||||
#ifdef BCHIP074_BCHIP075
|
|
||||||
cout << "This is a bchip074-bchip075 system " << endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t **dMask;
|
|
||||||
int **dMap;
|
|
||||||
int ix, iy;
|
|
||||||
int ypixels = 1;
|
|
||||||
int xpixels = 1280 * nmod;
|
|
||||||
int imod, ipix;
|
|
||||||
dMask = new uint16_t *[1];
|
|
||||||
dMap = new int *[1];
|
|
||||||
dMap[0] = new int[1280 * nmod];
|
|
||||||
dMask[0] = new uint16_t[1280 * nmod];
|
|
||||||
|
|
||||||
for (int ix = 0; ix < xpixels; ix++) {
|
|
||||||
imod = ix % 2;
|
|
||||||
if (imod == 0)
|
|
||||||
ipix = ix / 2;
|
|
||||||
else
|
|
||||||
ipix = 1280 - 1 - ix / 2;
|
|
||||||
if (imod == 0)
|
|
||||||
dMap[0][ix] = ipix * 2 + offset;
|
|
||||||
else
|
|
||||||
dMap[0][ix] = 1280 * 2 + 2 * offset +
|
|
||||||
ipix * 2; // dataSize-2-ix;//+2*offset;
|
|
||||||
// dMap[0][ix] = 2*ipix+offset*(imod+1)+1280*2*imod;
|
|
||||||
dMask[0][ix] = 0x0;
|
|
||||||
#ifdef BCHIP074_BCHIP075
|
|
||||||
int ibad = ix / 2 + 1280 * imod;
|
|
||||||
if ((ibad >= 128 * 4 && ibad < 128 * 5) ||
|
|
||||||
(ibad >= 9 * 128 && ibad < 10 * 128) ||
|
|
||||||
(ibad >= (1280 + 128 * 4) && ibad < ibad >= (1280 + 128 * 6)))
|
|
||||||
dataROIMask[0][ix] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
setDataMap(dMap);
|
|
||||||
setDataMask(dMask);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
Returns the frame number for the given dataset.
|
|
||||||
\param buff pointer to the dataset
|
|
||||||
\returns frame number
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int getFrameNumber(char *buff) {
|
|
||||||
if (offset >= sizeof(sls_detector_header))
|
|
||||||
return ((sls_detector_header *)buff)->frameNumber;
|
|
||||||
return iframe;
|
|
||||||
}; //*((int*)(buff+5))&0xffffff;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
gets the packets number (last packet is labelled with 0 and is replaced with
|
|
||||||
40) \param buff pointer to the memory \returns packet number
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int getPacketNumber(char *buff) {
|
|
||||||
if (offset >= sizeof(sls_detector_header))
|
|
||||||
return ((sls_detector_header *)buff)->packetNumber;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
Loops over a memory slot until a complete frame is found (i.e. all
|
|
||||||
packets 0 to nPackets, same frame number). purely virtual func \param
|
|
||||||
data pointer to the memory to be analyzed \param ndata reference to the
|
|
||||||
amount of data found for the frame, in case the frame is incomplete at
|
|
||||||
the end of the memory slot \param dsize size of the memory slot to be
|
|
||||||
analyzed \returns pointer to the beginning of the last good frame (might
|
|
||||||
be incomplete if ndata smaller than dataSize), or NULL if no frame is
|
|
||||||
found
|
|
||||||
|
|
||||||
*/
|
|
||||||
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
|
|
||||||
if (dsize < dataSize)
|
|
||||||
ndata = dsize;
|
|
||||||
else
|
|
||||||
ndata = dataSize;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual char *readNextFrame(ifstream &filebin) {
|
|
||||||
int ff = -1, np = -1;
|
|
||||||
return readNextFrame(filebin, ff, np);
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual char *readNextFrame(ifstream &filebin, int &ff) {
|
|
||||||
int np = -1;
|
|
||||||
return readNextFrame(filebin, ff, np);
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual char *readNextFrame(ifstream &filebin, int &ff, int &np) {
|
|
||||||
char *data = new char[dataSize];
|
|
||||||
char *d = readNextFrame(filebin, ff, np, data);
|
|
||||||
if (d == NULL) {
|
|
||||||
delete[] data;
|
|
||||||
data = NULL;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual char *readNextFrame(ifstream &filebin, int &ff, int &np,
|
|
||||||
char *data) {
|
|
||||||
char *retval = 0;
|
|
||||||
int nd;
|
|
||||||
int fnum = -1;
|
|
||||||
np = 0;
|
|
||||||
int pn;
|
|
||||||
|
|
||||||
// cout << dataSize << endl;
|
|
||||||
if (ff >= 0)
|
|
||||||
fnum = ff;
|
|
||||||
|
|
||||||
if (filebin.is_open()) {
|
|
||||||
if (filebin.read(data, dataSize)) {
|
|
||||||
ff = getFrameNumber(data);
|
|
||||||
np = getPacketNumber(data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,105 +0,0 @@
|
|||||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
|
||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
||||||
#ifndef GOTTHARDSHORTMODULEDATA_H
|
|
||||||
#define GOTTHARDSHORTMODULEDATA_H
|
|
||||||
#include "slsReceiverData.h"
|
|
||||||
|
|
||||||
class gotthardShortModuleData : public slsReceiverData<uint16_t> {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Implements the slsReceiverData structure for the gotthard short read out by a
|
|
||||||
module i.e. using the slsReceiver (1x256 pixels, 1 packet 256 large etc.)
|
|
||||||
\param c crosstalk parameter for the output buffer
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
gotthardShortModuleData(double c = 0)
|
|
||||||
: slsReceiverData<uint16_t>(xpixels, ypixels, npackets, buffersize),
|
|
||||||
xtalk(c) {
|
|
||||||
|
|
||||||
uint16_t **dMask;
|
|
||||||
int **dMap;
|
|
||||||
int ix, iy;
|
|
||||||
int offset = 2;
|
|
||||||
|
|
||||||
dMask = new uint16_t *[ypixels];
|
|
||||||
dMap = new int *[ypixels];
|
|
||||||
for (int i = 0; i < ypixels; i++) {
|
|
||||||
dMap[i] = new int[xpixels];
|
|
||||||
dMask[i] = new uint16_t[xpixels];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ix = 0; ix < ypixels; ++ix)
|
|
||||||
for (iy = 0; iy < xpixels; ++iy)
|
|
||||||
dMask[ix][iy] = 0x0;
|
|
||||||
|
|
||||||
for (ix = 0; ix < ypixels; ++ix)
|
|
||||||
for (iy = 0; iy < xpixels; ++iy) {
|
|
||||||
dMap[ix][iy] = offset;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDataMap(dMap);
|
|
||||||
setDataMask(dMask);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
Returns the frame number for the given dataset.
|
|
||||||
\param buff pointer to the dataset
|
|
||||||
\returns frame number
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int getFrameNumber(char *buff) { return (*(int *)buff); };
|
|
||||||
|
|
||||||
/**
|
|
||||||
gets the packets number (last packet is labelled with 0 and is replaced with
|
|
||||||
40) \param buff pointer to the memory \returns packet number
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int getPacketNumber(char *buff) { return 1; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
returns the pixel value as double correcting for the output buffer crosstalk
|
|
||||||
\param data pointer to the memory
|
|
||||||
\param ix coordinate in the x direction
|
|
||||||
\param iy coordinate in the y direction
|
|
||||||
\returns channel value as double
|
|
||||||
|
|
||||||
*/
|
|
||||||
double getValue(char *data, int ix, int iy = 0) {
|
|
||||||
// check how it is for gotthard
|
|
||||||
if (xtalk == 0)
|
|
||||||
return slsDetectorData<uint16_t>::getValue(data, ix, iy);
|
|
||||||
else
|
|
||||||
return slsDetectorData<uint16_t>::getValue(data, ix, iy) -
|
|
||||||
xtalk *
|
|
||||||
slsDetectorData<uint16_t>::getValue(data, ix - 1, iy);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** sets the output buffer crosstalk correction parameter
|
|
||||||
\param c output buffer crosstalk correction parameter to be set
|
|
||||||
\returns current value for the output buffer crosstalk correction parameter
|
|
||||||
|
|
||||||
*/
|
|
||||||
double setXTalk(double c) {
|
|
||||||
xtalk = c;
|
|
||||||
return xtalk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** gets the output buffer crosstalk parameter
|
|
||||||
\returns current value for the output buffer crosstalk correction parameter
|
|
||||||
*/
|
|
||||||
double getXTalk() { return xtalk; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
double xtalk; /**<output buffer crosstalk correction parameter */
|
|
||||||
const static int xpixels = 256;
|
|
||||||
const static int ypixels = 1;
|
|
||||||
const static int npackets = 1;
|
|
||||||
const static int buffersize = 518;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -0,0 +1,422 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
#ifndef JUNGFRAULGADSTRIXELSDATAQUAD_H
|
||||||
|
#define JUNGFRAULGADSTRIXELSDATAQUAD_H
|
||||||
|
#ifdef CINT
|
||||||
|
#include "sls/sls_detector_defs_CINT.h"
|
||||||
|
#else
|
||||||
|
#include "sls/sls_detector_defs.h"
|
||||||
|
#endif
|
||||||
|
#include "slsDetectorData.h"
|
||||||
|
|
||||||
|
// #define VERSION_V2
|
||||||
|
/**
|
||||||
|
@short structure for a Detector Packet or Image Header
|
||||||
|
@li frameNumber is the frame number
|
||||||
|
@li expLength is the subframe number (32 bit eiger) or real time exposure
|
||||||
|
time in 100ns (others)
|
||||||
|
@li packetNumber is the packet number
|
||||||
|
@li bunchId is the bunch id from beamline
|
||||||
|
@li timestamp is the time stamp with 10 MHz clock
|
||||||
|
@li modId is the unique module id (unique even for left, right, top, bottom)
|
||||||
|
@li xCoord is the x coordinate in the complete detector system
|
||||||
|
@li yCoord is the y coordinate in the complete detector system
|
||||||
|
@li zCoord is the z coordinate in the complete detector system
|
||||||
|
@li debug is for debugging purposes
|
||||||
|
@li roundRNumber is the round robin set number
|
||||||
|
@li detType is the detector type see :: detectorType
|
||||||
|
@li version is the version number of this structure format
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace strixelQuad {
|
||||||
|
constexpr int nc_rawimg = 1024; // for full images //256;
|
||||||
|
constexpr int nc_quad = 512;
|
||||||
|
constexpr int nr_rawimg = 512;
|
||||||
|
constexpr int nr_chip = 256;
|
||||||
|
constexpr int gr = 9;
|
||||||
|
|
||||||
|
//shift due to extra pixels
|
||||||
|
constexpr int shift_x = 2; //left
|
||||||
|
|
||||||
|
constexpr int nc_strixel = ( nc_quad - shift_x - 2*gr ) / 3; //164
|
||||||
|
constexpr int nr_strixel = ( nr_chip - 1 - gr ) * 3; //one half (-1 because double sided pixel) //738
|
||||||
|
constexpr int nr_center = 12; //double sided pixels to be skipped
|
||||||
|
|
||||||
|
// boundaries in ASIC coordinates (pixels at both bounds are included)
|
||||||
|
constexpr int xstart = 256 + gr; // 265
|
||||||
|
constexpr int xend = 255 + nc_quad - gr; // 758
|
||||||
|
constexpr int bottom_ystart = gr; // 9
|
||||||
|
constexpr int bottom_yend = nr_chip - 2; // 254
|
||||||
|
constexpr int top_ystart = nr_chip + 1; // 257
|
||||||
|
constexpr int top_yend = nr_chip*2 - gr - 1; // 502
|
||||||
|
|
||||||
|
// x shift because of 2-pixel strixels on one side
|
||||||
|
constexpr int shift = 2;
|
||||||
|
|
||||||
|
} // namespace strixelQuad
|
||||||
|
|
||||||
|
//to account for module rotation
|
||||||
|
enum rotation {
|
||||||
|
NORMAL = 0,
|
||||||
|
INVERSE = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const int rota = NORMAL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t bunchNumber; /**< is the frame number */
|
||||||
|
uint64_t pre; /**< something */
|
||||||
|
|
||||||
|
} jf_header; // Aldo's header
|
||||||
|
|
||||||
|
using namespace strixelQuad;
|
||||||
|
|
||||||
|
class jungfrauLGADStrixelsDataQuad : public slsDetectorData<uint16_t> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
int iframe;
|
||||||
|
int x0, y0, x1, y1, shifty;
|
||||||
|
struct {
|
||||||
|
uint16_t xmin;
|
||||||
|
uint16_t xmax;
|
||||||
|
uint16_t ymin;
|
||||||
|
uint16_t ymax;
|
||||||
|
int nc;
|
||||||
|
} globalROI;
|
||||||
|
|
||||||
|
//to account for the inverted routing of the two different quad halfs
|
||||||
|
enum location {
|
||||||
|
BOTTOM = 0,
|
||||||
|
TOP = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
int multiplicator = 3;
|
||||||
|
std::vector<int> mods{ 0, 1, 2 };
|
||||||
|
|
||||||
|
void reverseVector( std::vector<int>& v ) {
|
||||||
|
std::reverse( v.begin(), v.end() );
|
||||||
|
std::cout << "mods reversed ";
|
||||||
|
for ( auto i : v )
|
||||||
|
std::cout << i << " ";
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMappingShifts( const int rot, const int half ) {
|
||||||
|
|
||||||
|
x0 = xstart;
|
||||||
|
x1 = xend;
|
||||||
|
|
||||||
|
if (rot==NORMAL) {
|
||||||
|
x0 += shift;
|
||||||
|
} else {
|
||||||
|
x1-=shift;
|
||||||
|
reverseVector(mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (half==BOTTOM) {
|
||||||
|
y0 = bottom_ystart;
|
||||||
|
y1 = bottom_yend;
|
||||||
|
shifty = 0;
|
||||||
|
} else {
|
||||||
|
y0 = top_ystart;
|
||||||
|
y1 = top_yend;
|
||||||
|
reverseVector(mods);
|
||||||
|
shifty = nr_strixel + nr_center; //double-sided pixels in the center have to be jumped
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void remap( int xmin=0, int xmax=0, int ymin=0, int ymax=0 ) {
|
||||||
|
|
||||||
|
int ix, iy = 0;
|
||||||
|
// remapping loop
|
||||||
|
for (int ipy = y0; ipy <= y1; ipy++) {
|
||||||
|
for (int ipx = x0; ipx <= x1; ipx++) {
|
||||||
|
|
||||||
|
ix = int((ipx - x0) / multiplicator);
|
||||||
|
for (int m = 0; m < multiplicator; ++m) {
|
||||||
|
if ((ipx - x0) % multiplicator == m)
|
||||||
|
iy = (ipy - y0) * multiplicator + mods[m] + shifty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (iy< 40) cout << iy << " " << ix <<endl;
|
||||||
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
if ( ipx>=xmin && ipx<=xmax && ipy>=ymin && ipy <=ymax )
|
||||||
|
dataMap[iy][ix] =
|
||||||
|
sizeof(header) + (globalROI.nc * (ipy - globalROI.ymin) + (ipx - globalROI.xmin)) * 2;
|
||||||
|
} else {
|
||||||
|
dataMap[iy][ix] = sizeof(header) + (nc_rawimg * ipy + ipx) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void remapQuad(const int rot) {
|
||||||
|
|
||||||
|
setMappingShifts( rot, BOTTOM );
|
||||||
|
remap();
|
||||||
|
setMappingShifts( rot, TOP );
|
||||||
|
remap();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::tuple< uint16_t, uint16_t, uint16_t, uint16_t > adjustROItoLimits(uint16_t xmin,
|
||||||
|
uint16_t xmax,
|
||||||
|
uint16_t ymin,
|
||||||
|
uint16_t ymax,
|
||||||
|
uint16_t lim_roi_xmin,
|
||||||
|
uint16_t lim_roi_xmax,
|
||||||
|
uint16_t lim_roi_ymin,
|
||||||
|
uint16_t lim_roi_ymax) {
|
||||||
|
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
|
||||||
|
if ( xmin < lim_roi_xmin)
|
||||||
|
xmin_roi = lim_roi_xmin;
|
||||||
|
else
|
||||||
|
xmin_roi = xmin;
|
||||||
|
if ( xmax > lim_roi_xmax )
|
||||||
|
xmax_roi = lim_roi_xmax;
|
||||||
|
else
|
||||||
|
xmax_roi = xmax;
|
||||||
|
if ( ymin < lim_roi_ymin )
|
||||||
|
ymin_roi = lim_roi_ymin;
|
||||||
|
else
|
||||||
|
ymin_roi = ymin;
|
||||||
|
if ( ymax > lim_roi_ymax )
|
||||||
|
ymax_roi = lim_roi_ymax;
|
||||||
|
else
|
||||||
|
ymax_roi = ymax;
|
||||||
|
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector < std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > > mapSubROIs(uint16_t xmin,
|
||||||
|
uint16_t xmax,
|
||||||
|
uint16_t ymin,
|
||||||
|
uint16_t ymax) {
|
||||||
|
bool bottom = false;
|
||||||
|
bool top = false;
|
||||||
|
|
||||||
|
for ( int x=xmin; x!=xmax+1; ++x ) {
|
||||||
|
for ( int y=ymin; y!=ymax; ++y ) {
|
||||||
|
if ( xstart<=x && x<=xend && bottom_ystart<=y && y<=bottom_yend )
|
||||||
|
bottom = true;
|
||||||
|
if ( xstart<=x && x<=xend && top_ystart<=y && y<=top_yend )
|
||||||
|
top = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
|
||||||
|
std::vector < std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > > rois{};
|
||||||
|
|
||||||
|
if (bottom) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
xstart, xend, bottom_ystart, bottom_yend );
|
||||||
|
rois.push_back( std::make_tuple( BOTTOM, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (top) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
xstart, xend, top_ystart, top_yend );
|
||||||
|
rois.push_back( std::make_tuple( TOP, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rois;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remapROI(std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > roi, const int rot ) {
|
||||||
|
|
||||||
|
int half, xmin, xmax, ymin, ymax;
|
||||||
|
std::tie( half, xmin, xmax, ymin, ymax ) = roi;
|
||||||
|
|
||||||
|
setMappingShifts(rot, half);
|
||||||
|
|
||||||
|
std::cout << "remapping roi: "
|
||||||
|
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
|
||||||
|
<< ", y1: " << y1 << std::endl;
|
||||||
|
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]" << std::endl;
|
||||||
|
|
||||||
|
remap( xmin, xmax, ymin, ymax );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using header = sls::defs::sls_receiver_header;
|
||||||
|
|
||||||
|
jungfrauLGADStrixelsDataQuad(uint16_t xmin = 0, uint16_t xmax = 0,
|
||||||
|
uint16_t ymin = 0, uint16_t ymax = 0)
|
||||||
|
: slsDetectorData<uint16_t>(
|
||||||
|
nc_strixel,
|
||||||
|
nr_strixel * 2 + nr_center,
|
||||||
|
nc_strixel * ( nr_strixel * 2 + nr_center ) * 2 + sizeof(header)) {
|
||||||
|
std::cout << "Jungfrau strixels quad with full module data "
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
// Fill all strixels with dummy values
|
||||||
|
for (int ix = 0; ix != nc_strixel; ++ix) {
|
||||||
|
for (int iy = 0; iy != nr_strixel * 2 + nr_center; ++iy) {
|
||||||
|
dataMap[iy][ix] = sizeof(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalROI.xmin = xmin;
|
||||||
|
globalROI.xmax = xmax;
|
||||||
|
globalROI.ymin = ymin;
|
||||||
|
globalROI.ymax = ymax;
|
||||||
|
|
||||||
|
std::cout << "sizeofheader = " << sizeof(header) << std::endl;
|
||||||
|
std::cout << "Jungfrau strixels quad with full module data "
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
|
||||||
|
// get ROI raw image number of columns
|
||||||
|
globalROI.nc = xmax - xmin + 1;
|
||||||
|
std::cout << "nc_roi = " << globalROI.nc << std::endl;
|
||||||
|
|
||||||
|
dataSize =
|
||||||
|
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
|
||||||
|
std::cout << "datasize " << dataSize << std::endl;
|
||||||
|
|
||||||
|
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
|
||||||
|
//function to fill vector of rois from globalROI
|
||||||
|
|
||||||
|
for ( auto roi : rois )
|
||||||
|
remapROI(roi, rota);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
remapQuad( rota );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe = 0;
|
||||||
|
std::cout << "data struct created" << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value of the selected channel for the given dataset as
|
||||||
|
double. \param data pointer to the dataset (including headers etc) \param
|
||||||
|
ix pixel number in the x direction \param iy pixel number in the y
|
||||||
|
direction \returns data for the selected channel, with inversion if
|
||||||
|
required as double
|
||||||
|
|
||||||
|
*/
|
||||||
|
virtual double getValue(char *data, int ix, int iy = 0) {
|
||||||
|
|
||||||
|
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Returns the frame number for the given dataset. Purely virtual func.
|
||||||
|
\param buff pointer to the dataset
|
||||||
|
\returns frame number
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int getFrameNumber(char *buff) {
|
||||||
|
#ifdef ALDO // VH
|
||||||
|
return ((jf_header *)buff)->bunchNumber; // VH
|
||||||
|
#endif // VH
|
||||||
|
return ((header *)buff)->detHeader.frameNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Returns the packet number for the given dataset. purely virtual func
|
||||||
|
\param buff pointer to the dataset
|
||||||
|
\returns packet number number
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
int getPacketNumber(char *buff) {
|
||||||
|
#ifdef ALDO // VH
|
||||||
|
// uint32_t fakePacketNumber = 1000;
|
||||||
|
// return fakePacketNumber; //VH //TODO: Keep in mind in case of bugs!
|
||||||
|
// //This is definitely bad!
|
||||||
|
return 1000;
|
||||||
|
#endif // VH
|
||||||
|
return ((header *)buff)->detHeader.packetNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(std::ifstream &filebin) {
|
||||||
|
int ff = -1, np = -1;
|
||||||
|
return readNextFrame(filebin, ff, np);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(std::ifstream &filebin, int &ff) {
|
||||||
|
int np = -1;
|
||||||
|
return readNextFrame(filebin, ff, np);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(std::ifstream &filebin, int &ff, int &np) {
|
||||||
|
char *data = new char[dataSize];
|
||||||
|
char *d = readNextFrame(filebin, ff, np, data);
|
||||||
|
if (d == NULL) {
|
||||||
|
delete[] data;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(std::ifstream &filebin, int &ff, int &np, char *data) {
|
||||||
|
//char *retval = 0;
|
||||||
|
//int nd;
|
||||||
|
//int fnum = -1;
|
||||||
|
np = 0;
|
||||||
|
//int pn;
|
||||||
|
|
||||||
|
//std::cout << dataSize << std::endl;
|
||||||
|
//if (ff >= 0) {
|
||||||
|
// fnum = ff; }
|
||||||
|
|
||||||
|
if (filebin.is_open()) {
|
||||||
|
if (filebin.read(data, dataSize)) {
|
||||||
|
std::cout << "*";
|
||||||
|
ff = getFrameNumber(data);
|
||||||
|
np = getPacketNumber(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
std::cout << "#";
|
||||||
|
} else {
|
||||||
|
std::cout << "File not open" << std::endl;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Loops over a memory slot until a complete frame is found (i.e. all */
|
||||||
|
/* packets 0 to nPackets, same frame number). purely virtual func \param
|
||||||
|
*/
|
||||||
|
/* data pointer to the memory to be analyzed \param ndata reference to
|
||||||
|
* the */
|
||||||
|
/* amount of data found for the frame, in case the frame is incomplete at
|
||||||
|
*/
|
||||||
|
/* the end of the memory slot \param dsize size of the memory slot to be
|
||||||
|
*/
|
||||||
|
/* analyzed \returns pointer to the beginning of the last good frame
|
||||||
|
* (might */
|
||||||
|
/* be incomplete if ndata smaller than dataSize), or NULL if no frame is
|
||||||
|
*/
|
||||||
|
/* found */
|
||||||
|
|
||||||
|
/* *\/ */
|
||||||
|
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
|
||||||
|
if (dsize < dataSize)
|
||||||
|
ndata = dsize;
|
||||||
|
else
|
||||||
|
ndata = dataSize;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,432 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
#ifndef JUNGFRAULGADSTRIXELSDATAQUADH5_H
|
||||||
|
#define JUNGFRAULGADSTRIXELSDATAQUADH5_H
|
||||||
|
#ifdef CINT
|
||||||
|
#include "sls/sls_detector_defs_CINT.h"
|
||||||
|
#else
|
||||||
|
#include "sls/sls_detector_defs.h"
|
||||||
|
#endif
|
||||||
|
#include "slsDetectorData.h"
|
||||||
|
|
||||||
|
// This needs to be linked correctly
|
||||||
|
#include "HDF5File.cpp"
|
||||||
|
#include "HDF5File.h" //this includes hdf5.h and hdf5_hl.h
|
||||||
|
|
||||||
|
// #define VERSION_V2
|
||||||
|
/**
|
||||||
|
@short structure for a Detector Packet or Image Header
|
||||||
|
@li frameNumber is the frame number
|
||||||
|
@li expLength is the subframe number (32 bit eiger) or real time exposure
|
||||||
|
time in 100ns (others)
|
||||||
|
@li packetNumber is the packet number
|
||||||
|
@li bunchId is the bunch id from beamline
|
||||||
|
@li timestamp is the time stamp with 10 MHz clock
|
||||||
|
@li modId is the unique module id (unique even for left, right, top, bottom)
|
||||||
|
@li xCoord is the x coordinate in the complete detector system
|
||||||
|
@li yCoord is the y coordinate in the complete detector system
|
||||||
|
@li zCoord is the z coordinate in the complete detector system
|
||||||
|
@li debug is for debugging purposes
|
||||||
|
@li roundRNumber is the round robin set number
|
||||||
|
@li detType is the detector type see :: detectorType
|
||||||
|
@li version is the version number of this structure format
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace strixelQuad {
|
||||||
|
constexpr int nc_rawimg = 1024; // for full images //256;
|
||||||
|
constexpr int nc_quad = 512;
|
||||||
|
constexpr int nr_rawimg = 512;
|
||||||
|
constexpr int nr_chip = 256;
|
||||||
|
constexpr int gr = 9;
|
||||||
|
|
||||||
|
// shift due to extra pixels
|
||||||
|
constexpr int shift_x = 2; // left
|
||||||
|
|
||||||
|
constexpr int nc_strixel = (nc_quad - shift_x - 2 * gr) / 3; // 164
|
||||||
|
constexpr int nr_strixel =
|
||||||
|
(nr_chip - 1 - gr) * 3; // one half (-1 because double sided pixel) //738
|
||||||
|
constexpr int nr_center = 12; // double sided pixels to be skipped
|
||||||
|
|
||||||
|
// boundaries in ASIC coordinates (pixels at both bounds are included)
|
||||||
|
constexpr int xstart = 256 + gr; // 265
|
||||||
|
constexpr int xend = 255 + nc_quad - gr; // 758
|
||||||
|
constexpr int bottom_ystart = gr; // 9
|
||||||
|
constexpr int bottom_yend = nr_chip - 2; // 254
|
||||||
|
constexpr int top_ystart = nr_chip + 1; // 257
|
||||||
|
constexpr int top_yend = nr_chip * 2 - gr - 1; // 502
|
||||||
|
|
||||||
|
// x shift because of 2-pixel strixels on one side
|
||||||
|
constexpr int shift = 2;
|
||||||
|
|
||||||
|
} // namespace strixelQuad
|
||||||
|
|
||||||
|
// to account for module rotation
|
||||||
|
enum rotation { NORMAL = 0, INVERSE = 1 };
|
||||||
|
|
||||||
|
const int rota = NORMAL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t bunchNumber; /**< is the frame number */
|
||||||
|
uint64_t pre; /**< something */
|
||||||
|
|
||||||
|
} jf_header; // Aldo's header
|
||||||
|
|
||||||
|
using namespace strixelQuad;
|
||||||
|
|
||||||
|
class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData<uint16_t> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
int iframe;
|
||||||
|
int x0, y0, x1, y1, shifty;
|
||||||
|
struct {
|
||||||
|
uint16_t xmin;
|
||||||
|
uint16_t xmax;
|
||||||
|
uint16_t ymin;
|
||||||
|
uint16_t ymax;
|
||||||
|
int nc;
|
||||||
|
} globalROI;
|
||||||
|
|
||||||
|
// to account for the inverted routing of the two different quad halfs
|
||||||
|
enum location { BOTTOM = 0, TOP = 1 };
|
||||||
|
|
||||||
|
int multiplicator = 3;
|
||||||
|
std::vector<int> mods{0, 1, 2};
|
||||||
|
|
||||||
|
void reverseVector(std::vector<int> &v) {
|
||||||
|
std::reverse(v.begin(), v.end());
|
||||||
|
std::cout << "mods reversed ";
|
||||||
|
for (auto i : v)
|
||||||
|
std::cout << i << " ";
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMappingShifts(const int rot, const int half) {
|
||||||
|
|
||||||
|
x0 = xstart;
|
||||||
|
x1 = xend;
|
||||||
|
|
||||||
|
if (rot == NORMAL) {
|
||||||
|
x0 += shift;
|
||||||
|
} else {
|
||||||
|
x1 -= shift;
|
||||||
|
reverseVector(mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (half == BOTTOM) {
|
||||||
|
y0 = bottom_ystart;
|
||||||
|
y1 = bottom_yend;
|
||||||
|
shifty = 0;
|
||||||
|
} else {
|
||||||
|
y0 = top_ystart;
|
||||||
|
y1 = top_yend;
|
||||||
|
reverseVector(mods);
|
||||||
|
shifty = nr_strixel + nr_center; // double-sided pixels in the
|
||||||
|
// center have to be jumped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remap(int xmin = 0, int xmax = 0, int ymin = 0, int ymax = 0) {
|
||||||
|
|
||||||
|
int ix, iy = 0;
|
||||||
|
// remapping loop
|
||||||
|
for (int ipy = y0; ipy <= y1; ++ipy) {
|
||||||
|
for (int ipx = x0; ipx <= x1; ++ipx) {
|
||||||
|
|
||||||
|
ix = int((ipx - x0) / multiplicator);
|
||||||
|
for (int m = 0; m < multiplicator; ++m) {
|
||||||
|
if ((ipx - x0) % multiplicator == m)
|
||||||
|
iy = (ipy - y0) * multiplicator + mods[m] + shifty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (iy< 40) cout << iy << " " << ix <<endl;
|
||||||
|
if (xmin < xmax && ymin < ymax) { // if ROI
|
||||||
|
if (ipx >= xmin && ipx <= xmax && ipy >= ymin &&
|
||||||
|
ipy <= ymax)
|
||||||
|
dataMap[iy][ix] =
|
||||||
|
(globalROI.nc * (ipy - globalROI.ymin) +
|
||||||
|
(ipx - globalROI.xmin)) *
|
||||||
|
2;
|
||||||
|
} else { // if full Quad
|
||||||
|
dataMap[iy][ix] = (nc_rawimg * ipy + ipx) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remapQuad(const int rot) {
|
||||||
|
|
||||||
|
setMappingShifts(rot, BOTTOM);
|
||||||
|
remap();
|
||||||
|
setMappingShifts(rot, TOP);
|
||||||
|
remap();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<uint16_t, uint16_t, uint16_t, uint16_t>
|
||||||
|
adjustROItoLimits(uint16_t xmin, uint16_t xmax, uint16_t ymin,
|
||||||
|
uint16_t ymax, uint16_t lim_roi_xmin,
|
||||||
|
uint16_t lim_roi_xmax, uint16_t lim_roi_ymin,
|
||||||
|
uint16_t lim_roi_ymax) {
|
||||||
|
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
|
||||||
|
if (xmin < lim_roi_xmin)
|
||||||
|
xmin_roi = lim_roi_xmin;
|
||||||
|
else
|
||||||
|
xmin_roi = xmin;
|
||||||
|
if (xmax > lim_roi_xmax)
|
||||||
|
xmax_roi = lim_roi_xmax;
|
||||||
|
else
|
||||||
|
xmax_roi = xmax;
|
||||||
|
if (ymin < lim_roi_ymin)
|
||||||
|
ymin_roi = lim_roi_ymin;
|
||||||
|
else
|
||||||
|
ymin_roi = ymin;
|
||||||
|
if (ymax > lim_roi_ymax)
|
||||||
|
ymax_roi = lim_roi_ymax;
|
||||||
|
else
|
||||||
|
ymax_roi = ymax;
|
||||||
|
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The strixel Quad has a mirrored symmetry from the center axis
|
||||||
|
// So we need to distinguish between bottom and top half for remapping
|
||||||
|
std::vector<std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t>>
|
||||||
|
mapSubROIs(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax) {
|
||||||
|
bool bottom = false;
|
||||||
|
bool top = false;
|
||||||
|
|
||||||
|
for (int x = xmin; x != xmax + 1; ++x) {
|
||||||
|
for (int y = ymin; y != ymax; ++y) {
|
||||||
|
if (xstart <= x && x <= xend && bottom_ystart <= y &&
|
||||||
|
y <= bottom_yend)
|
||||||
|
bottom = true;
|
||||||
|
if (xstart <= x && x <= xend && top_ystart <= y &&
|
||||||
|
y <= top_yend)
|
||||||
|
top = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
|
||||||
|
std::vector<std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t>>
|
||||||
|
rois{};
|
||||||
|
|
||||||
|
if (bottom) {
|
||||||
|
std::tie(xmin_roi, xmax_roi, ymin_roi, ymax_roi) =
|
||||||
|
adjustROItoLimits(xmin, xmax, ymin, ymax, xstart, xend,
|
||||||
|
bottom_ystart, bottom_yend);
|
||||||
|
rois.push_back(std::make_tuple(BOTTOM, xmin_roi, xmax_roi, ymin_roi,
|
||||||
|
ymax_roi));
|
||||||
|
}
|
||||||
|
if (top) {
|
||||||
|
std::tie(xmin_roi, xmax_roi, ymin_roi, ymax_roi) =
|
||||||
|
adjustROItoLimits(xmin, xmax, ymin, ymax, xstart, xend,
|
||||||
|
top_ystart, top_yend);
|
||||||
|
rois.push_back(
|
||||||
|
std::make_tuple(TOP, xmin_roi, xmax_roi, ymin_roi, ymax_roi));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rois;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remapROI(std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t> roi,
|
||||||
|
const int rot) {
|
||||||
|
|
||||||
|
int half, xmin, xmax, ymin, ymax;
|
||||||
|
std::tie(half, xmin, xmax, ymin, ymax) = roi;
|
||||||
|
|
||||||
|
setMappingShifts(rot, half);
|
||||||
|
|
||||||
|
std::cout << "remapping roi: "
|
||||||
|
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
|
||||||
|
<< ", y1: " << y1 << std::endl;
|
||||||
|
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin
|
||||||
|
<< ", " << ymax << "]" << std::endl;
|
||||||
|
|
||||||
|
remap(xmin, xmax, ymin, ymax);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following functions are pure virtual in the base class. But I don't
|
||||||
|
// want them to be accessible here! Implement the functions as private (to
|
||||||
|
// satisfy the linker) int getFrameNumber(char* buff){return 0;} //This is
|
||||||
|
// actually needed because the cluster finder writes the framenumber
|
||||||
|
int getPacketNumber(char *buff) { return 0; } // Not provided
|
||||||
|
|
||||||
|
// Mark overwritten functions as override final
|
||||||
|
char *readNextFrame(std::ifstream &filebin) override final {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
using header = sls::defs::sls_receiver_header;
|
||||||
|
|
||||||
|
jungfrauLGADStrixelsDataQuadH5(uint16_t xmin = 0, uint16_t xmax = 0,
|
||||||
|
uint16_t ymin = 0, uint16_t ymax = 0)
|
||||||
|
: slsDetectorData<uint16_t>(
|
||||||
|
// nc_strixel,
|
||||||
|
// nr_strixel * 2 + nr_center,
|
||||||
|
// nc_strixel * ( nr_strixel * 2 + nr_center ) * 2
|
||||||
|
512 / 2, 1024 * 2, 512 * 1024 * 2) {
|
||||||
|
std::cout << "Jungfrau strixels quad with full module data "
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
// Fill all strixels with dummy values
|
||||||
|
// for (int ix = 0; ix != nc_strixel; ++ix) {
|
||||||
|
// for (int iy = 0; iy != nr_strixel * 2 + nr_center; ++iy) {
|
||||||
|
for (int ix = 0; ix != 512 / 2; ++ix) {
|
||||||
|
for (int iy = 0; iy != 1024 * 2; ++iy) {
|
||||||
|
// Set everything to dummy value
|
||||||
|
dataMap[iy][ix] = sizeof(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalROI.xmin = xmin;
|
||||||
|
globalROI.xmax = xmax;
|
||||||
|
globalROI.ymin = ymin;
|
||||||
|
globalROI.ymax = ymax;
|
||||||
|
|
||||||
|
// std::cout << "sizeofheader = " << sizeof(header) << std::endl;
|
||||||
|
std::cout << "Jungfrau strixels quad with full module data "
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
|
||||||
|
// get ROI raw image number of columns
|
||||||
|
globalROI.nc = xmax - xmin + 1;
|
||||||
|
std::cout << "nc_roi = " << globalROI.nc << std::endl;
|
||||||
|
|
||||||
|
dataSize = (xmax - xmin + 1) * (ymax - ymin + 1) * 2;
|
||||||
|
std::cout << "datasize " << dataSize << std::endl;
|
||||||
|
|
||||||
|
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
|
||||||
|
// function to fill vector of rois from globalROI
|
||||||
|
|
||||||
|
for (auto roi : rois)
|
||||||
|
remapROI(roi, rota);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
remapQuad(rota);
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe = 0;
|
||||||
|
std::cout << "data struct created" << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value of the selected channel for the given dataset as
|
||||||
|
double. \param data pointer to the dataset (including headers etc) \param
|
||||||
|
ix pixel number in the x direction \param iy pixel number in the y
|
||||||
|
direction \returns data for the selected channel, with inversion if
|
||||||
|
required as double
|
||||||
|
|
||||||
|
*/
|
||||||
|
virtual double getValue(char *data, int ix, int iy = 0) {
|
||||||
|
|
||||||
|
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(HDF5File &hfile) {
|
||||||
|
int fn = 0;
|
||||||
|
std::vector<hsize_t> h5offset(1);
|
||||||
|
return readNextFrame(hfile, fn, h5offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(HDF5File &hfile, int &fn) {
|
||||||
|
std::vector<hsize_t> h5offset(1);
|
||||||
|
return readNextFrame(hfile, fn, h5offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(HDF5File &hfile, int &fn,
|
||||||
|
std::vector<hsize_t> &h5offset) {
|
||||||
|
|
||||||
|
// Ensure dataSize is a valid size for allocation
|
||||||
|
if (dataSize <= 0) {
|
||||||
|
// Handle error case appropriately, e.g., log an error message
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *data = new char[dataSize];
|
||||||
|
char *readResult = readNextFrame(hfile, fn, h5offset, data);
|
||||||
|
|
||||||
|
// Check if reading failed
|
||||||
|
if (readResult == nullptr) {
|
||||||
|
delete[] data; // Free allocated memory
|
||||||
|
data = nullptr; // Set to nullptr to avoid dangling pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
return data; // returning data is equivalent to returning
|
||||||
|
// reinterpret_cast<char*>(data_ptr) as they both point to
|
||||||
|
// the same memory
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the most recent function. This is used in the cluster finder!
|
||||||
|
* The overloads are legacy!
|
||||||
|
* Note that caller has to allocate and deallocate memory for data!
|
||||||
|
* \param hfile object of type HDF5File (reader class)
|
||||||
|
* \param framenumber frame number as read from the HDF5 file
|
||||||
|
* \param h5offset vector defining offset parameters for HDF5 hyperslab
|
||||||
|
* selection (dimensions Z and S), incremented automatially
|
||||||
|
* \param data pointer to image buffer (converted to hold uint16_t by
|
||||||
|
* definition of HDF5File)
|
||||||
|
*/
|
||||||
|
char *readNextFrame(HDF5File &hfile, int &framenumber,
|
||||||
|
std::vector<hsize_t> &h5offset, char *data) {
|
||||||
|
|
||||||
|
if (framenumber >= 0) {
|
||||||
|
if (h5offset[0] % 10 == 0)
|
||||||
|
std::cout << "*";
|
||||||
|
|
||||||
|
// Storing the reinterpret_cast in the variable data_ptr ensures
|
||||||
|
// that I can pass it to a function that expects at uint16_t*
|
||||||
|
uint16_t *data_ptr = reinterpret_cast<uint16_t *>(
|
||||||
|
data); // now data_ptr points where data points (thus modifies
|
||||||
|
// the same memory)
|
||||||
|
|
||||||
|
framenumber = hfile.ReadImage(data_ptr, h5offset);
|
||||||
|
iframe = h5offset[0]; // iframe is a class member!
|
||||||
|
return data; // return reinterpret_cast<char*>(data_ptr); //
|
||||||
|
// Equivalent
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "#";
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
int getFrameNumber(char *buff) {
|
||||||
|
return iframe;
|
||||||
|
} // Provided via public method readNextFrame
|
||||||
|
// It is debatable if one might not instead want to provide the "real" frame
|
||||||
|
// number as read from the file here For now, this is the frame offset
|
||||||
|
// counter (that always has to start at 0 for each new file)
|
||||||
|
|
||||||
|
/* Loops over a memory slot until a complete frame is found (i.e. all */
|
||||||
|
/* packets 0 to nPackets, same frame number). purely virtual func \param
|
||||||
|
*/
|
||||||
|
/* data pointer to the memory to be analyzed \param ndata reference to
|
||||||
|
* the */
|
||||||
|
/* amount of data found for the frame, in case the frame is incomplete at
|
||||||
|
*/
|
||||||
|
/* the end of the memory slot \param dsize size of the memory slot to be
|
||||||
|
*/
|
||||||
|
/* analyzed \returns pointer to the beginning of the last good frame
|
||||||
|
* (might */
|
||||||
|
/* be incomplete if ndata smaller than dataSize), or NULL if no frame is
|
||||||
|
*/
|
||||||
|
/* found */
|
||||||
|
|
||||||
|
/* *\/ */
|
||||||
|
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
|
||||||
|
if (dsize < dataSize)
|
||||||
|
ndata = dsize;
|
||||||
|
else
|
||||||
|
ndata = dataSize;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -28,6 +28,10 @@
|
|||||||
@li version is the version number of this structure format
|
@li version is the version number of this structure format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace strixelSingleChip {
|
namespace strixelSingleChip {
|
||||||
constexpr int nc_rawimg = 1024; // for full images //256;
|
constexpr int nc_rawimg = 1024; // for full images //256;
|
||||||
constexpr int nr_rawimg = 512;
|
constexpr int nr_rawimg = 512;
|
||||||
@ -77,7 +81,7 @@ constexpr int c6g1_ystart = c6g2_yend + 1; // 448
|
|||||||
constexpr int c6g1_yend = c6g2_yend + 64 - gr; // 502
|
constexpr int c6g1_yend = c6g2_yend + 64 - gr; // 502
|
||||||
|
|
||||||
// y shift due to faulty bonding (relevant for M408)
|
// y shift due to faulty bonding (relevant for M408)
|
||||||
constexpr int bond_shift_y = 1; // CHANGE IF YOU CHANGE MODULE!
|
constexpr int bond_shift_y = 0; // CHANGE IF YOU CHANGE MODULE!
|
||||||
|
|
||||||
} // namespace strixelSingleChip
|
} // namespace strixelSingleChip
|
||||||
|
|
||||||
@ -97,6 +101,13 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
|||||||
int chip_x0;
|
int chip_x0;
|
||||||
int chip_y0;
|
int chip_y0;
|
||||||
int x0, y0, x1, y1, shifty;
|
int x0, y0, x1, y1, shifty;
|
||||||
|
struct {
|
||||||
|
uint16_t xmin;
|
||||||
|
uint16_t xmax;
|
||||||
|
uint16_t ymin;
|
||||||
|
uint16_t ymax;
|
||||||
|
int nc;
|
||||||
|
} globalROI;
|
||||||
|
|
||||||
int getMultiplicator(const int group) {
|
int getMultiplicator(const int group) {
|
||||||
int multiplicator;
|
int multiplicator;
|
||||||
@ -215,9 +226,113 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remapROI(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax) {
|
|
||||||
|
std::tuple< uint16_t, uint16_t, uint16_t, uint16_t > adjustROItoLimits(uint16_t xmin,
|
||||||
|
uint16_t xmax,
|
||||||
|
uint16_t ymin,
|
||||||
|
uint16_t ymax,
|
||||||
|
uint16_t lim_roi_xmin,
|
||||||
|
uint16_t lim_roi_xmax,
|
||||||
|
uint16_t lim_roi_ymin,
|
||||||
|
uint16_t lim_roi_ymax) {
|
||||||
|
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
|
||||||
|
if ( xmin < lim_roi_xmin)
|
||||||
|
xmin_roi = lim_roi_xmin;
|
||||||
|
else
|
||||||
|
xmin_roi = xmin;
|
||||||
|
if ( xmax > lim_roi_xmax )
|
||||||
|
xmax_roi = lim_roi_xmax;
|
||||||
|
else
|
||||||
|
xmax_roi = xmax;
|
||||||
|
if ( ymin < lim_roi_ymin )
|
||||||
|
ymin_roi = lim_roi_ymin;
|
||||||
|
else
|
||||||
|
ymin_roi = ymin;
|
||||||
|
if ( ymax > lim_roi_ymax )
|
||||||
|
ymax_roi = lim_roi_ymax;
|
||||||
|
else
|
||||||
|
ymax_roi = ymax;
|
||||||
|
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector < std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > > mapSubROIs(uint16_t xmin,
|
||||||
|
uint16_t xmax,
|
||||||
|
uint16_t ymin,
|
||||||
|
uint16_t ymax) {
|
||||||
|
bool chip_1_1 = false;
|
||||||
|
bool chip_1_2 = false;
|
||||||
|
bool chip_1_3 = false;
|
||||||
|
bool chip_6_1 = false;
|
||||||
|
bool chip_6_2 = false;
|
||||||
|
bool chip_6_3 = false;
|
||||||
|
|
||||||
|
for ( int x=xmin; x!=xmax+1; ++x ) {
|
||||||
|
for ( int y=ymin; y!=ymax; ++y ) {
|
||||||
|
if ( c1g1_xstart<=x && x<=c1_xend && (c1g1_ystart+bond_shift_y)<=y && y<=(c1g1_yend+bond_shift_y) )
|
||||||
|
chip_1_1 = true;
|
||||||
|
if ( c1g2_xstart<=x && x<=c1_xend && (c1g2_ystart+bond_shift_y)<=y && y<=(c1g2_yend+bond_shift_y) )
|
||||||
|
chip_1_2 = true;
|
||||||
|
if ( c1g3_xstart<=x && x<=c1_xend && (c1g3_ystart+bond_shift_y)<=y && y<=(c1g3_yend+bond_shift_y) )
|
||||||
|
chip_1_3 = true;
|
||||||
|
if ( c6_xstart<=x && x<=c6g1_xend && (c6g1_ystart-bond_shift_y)<=y && y<=(c6g1_yend-bond_shift_y) )
|
||||||
|
chip_6_1 = true;
|
||||||
|
if ( c6_xstart<=x && x<=c6g2_xend && (c6g2_ystart-bond_shift_y)<=y && y<=(c6g2_yend-bond_shift_y) )
|
||||||
|
chip_6_2 = true;
|
||||||
|
if ( c6_xstart<=x && x<=c6g3_xend && (c6g3_ystart-bond_shift_y)<=y && y<=(c6g3_yend-bond_shift_y) )
|
||||||
|
chip_6_3 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
|
||||||
|
//[ chip, group, xmin, xmax, ymin, ymax ]
|
||||||
|
std::vector < std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > > rois{};
|
||||||
|
|
||||||
|
if (chip_1_1) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c1g1_xstart, c1_xend, 0, c1g1_yend+bond_shift_y );
|
||||||
|
rois.push_back( std::make_tuple( 1, 1, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (chip_1_2) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c1g2_xstart, c1_xend, c1g2_ystart+bond_shift_y, c1g2_yend+bond_shift_y );
|
||||||
|
rois.push_back( std::make_tuple( 1, 2, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (chip_1_3) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c1g3_xstart, c1_xend, c1g3_ystart+bond_shift_y, c1g3_yend+bond_shift_y );
|
||||||
|
rois.push_back( std::make_tuple( 1, 3, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (chip_6_3) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c6_xstart, c6g3_xend, c6g3_ystart-bond_shift_y, c6g3_yend-bond_shift_y );
|
||||||
|
rois.push_back( std::make_tuple( 6, 3, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (chip_6_2) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c6_xstart, c6g2_xend, c6g2_ystart-bond_shift_y, c6g2_yend-bond_shift_y );
|
||||||
|
rois.push_back( std::make_tuple( 6, 2, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
if (chip_6_1) {
|
||||||
|
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
|
||||||
|
adjustROItoLimits( xmin, xmax, ymin, ymax,
|
||||||
|
c6_xstart, c6g1_xend, c6g1_ystart-bond_shift_y, 511 );
|
||||||
|
rois.push_back( std::make_tuple( 6, 1, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rois;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void remapROI(std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > roi) {
|
||||||
// determine group and chip selected by ROI
|
// determine group and chip selected by ROI
|
||||||
int group;
|
int group, xmin, xmax, ymin, ymax;
|
||||||
|
std::tie( mchip, group, xmin, xmax, ymin, ymax ) = roi;
|
||||||
|
/*
|
||||||
if (ymax <= c1g1_yend + bond_shift_y) {
|
if (ymax <= c1g1_yend + bond_shift_y) {
|
||||||
group = 1;
|
group = 1;
|
||||||
mchip = 1;
|
mchip = 1;
|
||||||
@ -243,18 +358,17 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
|||||||
group = -1;
|
group = -1;
|
||||||
mchip = -1;
|
mchip = -1;
|
||||||
}
|
}
|
||||||
int multiplicator = getMultiplicator(group);
|
*/
|
||||||
setMappingShifts(group);
|
int multiplicator = getMultiplicator(group);
|
||||||
|
setMappingShifts(group);
|
||||||
|
|
||||||
std::cout << "chip: " << mchip << ", group: " << group << ", m: " << multiplicator
|
std::cout << "remapping chip: " << mchip << ", group: " << group << ", m: " << multiplicator
|
||||||
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
|
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
|
||||||
<< ", y1: " << y1 << std::endl;
|
<< ", y1: " << y1 << std::endl;
|
||||||
|
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]" << std::endl;
|
||||||
// get ROI raw image number of columns
|
|
||||||
int nc_roi = xmax - xmin + 1;
|
|
||||||
std::cout << "nc_roi = " << nc_roi << std::endl;
|
|
||||||
|
|
||||||
// make sure loop bounds are correct
|
// make sure loop bounds are correct
|
||||||
|
/*
|
||||||
if (y0 < ymin)
|
if (y0 < ymin)
|
||||||
std::cout << "Error ymin" << std::endl;
|
std::cout << "Error ymin" << std::endl;
|
||||||
if (y1 > ymax)
|
if (y1 > ymax)
|
||||||
@ -264,24 +378,27 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
|||||||
std::cout << "Error xmin" << std::endl;
|
std::cout << "Error xmin" << std::endl;
|
||||||
if (x1 > xmax)
|
if (x1 > xmax)
|
||||||
std::cout << "Error xmax" << std::endl;
|
std::cout << "Error xmax" << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
// remapping loop
|
// remapping loop
|
||||||
int ix, iy = 0;
|
int ix, iy = 0;
|
||||||
for (int ipy = y0; ipy <= y1; ++ipy) {
|
for (int ipy = y0; ipy <= y1; ++ipy) {
|
||||||
for (int ipx = x0; ipx <= x1; ++ipx) {
|
for (int ipx = x0; ipx <= x1; ++ipx) {
|
||||||
|
|
||||||
ix = int((ipx - x0 /*-xmin*/) / multiplicator);
|
ix = int((ipx - x0 /*-xmin*/) / multiplicator);
|
||||||
for (int m = 0; m < multiplicator; m++) {
|
for (int m = 0; m < multiplicator; m++) {
|
||||||
if ((ipx - x0 /*-xmin*/) % multiplicator == m)
|
if ((ipx - x0 /*-xmin*/) % multiplicator == m)
|
||||||
iy = (ipy - y0 /*-ymin*/) * multiplicator + m + shifty;
|
iy = (ipy - y0 /*-ymin*/) * multiplicator + m + shifty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (iy< 40) cout << iy << " " << ix <<endl;
|
// if (iy< 40) cout << iy << " " << ix <<endl;
|
||||||
dataMap[iy][ix] =
|
if ( ipx>=xmin && ipx<=xmax && ipy>=ymin && ipy <=ymax )
|
||||||
sizeof(header) + (nc_roi * (ipy - ymin) + (ipx - xmin)) * 2;
|
dataMap[iy][ix] =
|
||||||
groupmap[iy][ix] = group - 1;
|
sizeof(header) + (globalROI.nc * (ipy - globalROI.ymin) + (ipx - globalROI.xmin)) * 2;
|
||||||
}
|
else dataMap[iy][ix] = sizeof(header);
|
||||||
}
|
groupmap[iy][ix] = group - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -307,16 +424,31 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalROI.xmin = xmin;
|
||||||
|
globalROI.xmax = xmax;
|
||||||
|
globalROI.ymin = ymin;
|
||||||
|
globalROI.ymax = ymax;
|
||||||
|
|
||||||
std::cout << "sizeofheader = " << sizeof(header) << std::endl;
|
std::cout << "sizeofheader = " << sizeof(header) << std::endl;
|
||||||
std::cout << "Jungfrau strixels 2X single chip with full module data "
|
std::cout << "Jungfrau strixels 2X single chip with full module data "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
if (xmin < xmax && ymin < ymax) {
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
|
||||||
dataSize =
|
// get ROI raw image number of columns
|
||||||
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
|
globalROI.nc = xmax - xmin + 1;
|
||||||
std::cout << "datasize " << dataSize << std::endl;
|
std::cout << "nc_roi = " << globalROI.nc << std::endl;
|
||||||
remapROI(xmin, xmax, ymin, ymax);
|
|
||||||
|
dataSize =
|
||||||
|
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
|
||||||
|
std::cout << "datasize " << dataSize << std::endl;
|
||||||
|
|
||||||
|
//[ chip, group, xmin, xmax, ymin, ymax ]
|
||||||
|
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
|
||||||
|
//function to fill vector of rois from globalROI
|
||||||
|
|
||||||
|
for ( auto roi : rois )
|
||||||
|
remapROI(roi);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#ifndef JUNGFRAUMODULEDATA_H
|
#ifndef JUNGFRAUMODULEDATA_H
|
||||||
#define JUNGFRAUMODULEDATA_H
|
#define JUNGFRAUMODULEDATA_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "sls/sls_detector_defs.h"
|
||||||
#include "slsDetectorData.h"
|
#include "slsDetectorData.h"
|
||||||
|
|
||||||
//#define VERSION_V2
|
//#define VERSION_V2
|
||||||
@ -27,7 +28,7 @@ typedef struct {
|
|||||||
uint64_t bunchNumber; /**< is the frame number */
|
uint64_t bunchNumber; /**< is the frame number */
|
||||||
uint64_t pre; /**< something */
|
uint64_t pre; /**< something */
|
||||||
|
|
||||||
} jf_header;
|
} jf_header; //Aldo's header!
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
||||||
@ -42,20 +43,56 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
|||||||
1286 large etc.) \param c crosstalk parameter for the output buffer
|
1286 large etc.) \param c crosstalk parameter for the output buffer
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef ALDO
|
||||||
|
using header = jf_header;
|
||||||
|
#else
|
||||||
|
using header = sls::defs::sls_receiver_header;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ZMQ
|
#ifndef ZMQ
|
||||||
#define off sizeof(jf_header)
|
#define off sizeof(header)
|
||||||
#endif
|
#endif
|
||||||
#ifdef ZMQ
|
#ifdef ZMQ
|
||||||
#define off 0
|
#define off 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
jungfrauModuleData()
|
jungfrauModuleData(uint16_t xmin=0, uint16_t xmax=0,
|
||||||
|
uint16_t ymin=0, uint16_t ymax=0)
|
||||||
: slsDetectorData<uint16_t>(1024, 512,
|
: slsDetectorData<uint16_t>(1024, 512,
|
||||||
1024* 512 * 2 + off) {
|
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] = off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
|
||||||
|
int nc_roi = xmax - xmin + 1;
|
||||||
|
int nr_roi = ymax - ymin + 1;
|
||||||
|
std::cout << "nc_roi = " << nc_roi << std::endl;
|
||||||
|
std::cout << "nr_roi = " << nr_roi << std::endl;
|
||||||
|
|
||||||
|
dataSize =
|
||||||
|
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + off;
|
||||||
|
std::cout << "datasize " << dataSize << std::endl;
|
||||||
|
|
||||||
|
for (int ix = xmin; ix < xmax+1; ++ix) {
|
||||||
|
for (int iy = ymin; iy < ymax+1; ++iy) {
|
||||||
|
dataMap[iy][ix] = off + (nc_roi * iy + ix) * 2;
|
||||||
|
#ifdef HIGHZ
|
||||||
|
dataMask[iy][ix] = 0x3fff;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (int ix = 0; ix < 1024; ++ix) {
|
||||||
|
for (int iy = 0; iy < 512; ++iy) {
|
||||||
dataMap[iy][ix] = off + (1024 * iy + ix) * 2;
|
dataMap[iy][ix] = off + (1024 * iy + ix) * 2;
|
||||||
#ifdef HIGHZ
|
#ifdef HIGHZ
|
||||||
dataMask[iy][ix] = 0x3fff;
|
dataMask[iy][ix] = 0x3fff;
|
||||||
@ -63,7 +100,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
iframe = 0;
|
iframe = 0;
|
||||||
@ -150,7 +187,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
|||||||
//int pn;
|
//int pn;
|
||||||
|
|
||||||
// cout << dataSize << endl;
|
// cout << dataSize << endl;
|
||||||
if (ff >= 0)
|
//if (ff >= 0)
|
||||||
//fnum = ff;
|
//fnum = ff;
|
||||||
|
|
||||||
if (filebin.is_open()) {
|
if (filebin.is_open()) {
|
||||||
|
226
slsDetectorCalibration/dataStructures/jungfrauSingleChipData.h
Normal file
226
slsDetectorCalibration/dataStructures/jungfrauSingleChipData.h
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
#ifndef JUNGFRAUSINGLECHIPDATA_H
|
||||||
|
#define JUNGFRAUSINGLECHIPDATA_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include "sls/sls_detector_defs.h"
|
||||||
|
#include "slsDetectorData.h"
|
||||||
|
|
||||||
|
//#define VERSION_V2
|
||||||
|
/**
|
||||||
|
@short structure for a Detector Packet or Image Header
|
||||||
|
@li frameNumber is the frame number
|
||||||
|
@li expLength is the subframe number (32 bit eiger) or real time exposure
|
||||||
|
time in 100ns (others)
|
||||||
|
@li packetNumber is the packet number
|
||||||
|
@li bunchId is the bunch id from beamline
|
||||||
|
@li timestamp is the time stamp with 10 MHz clock
|
||||||
|
@li modId is the unique module id (unique even for left, right, top, bottom)
|
||||||
|
@li xCoord is the x coordinate in the complete detector system
|
||||||
|
@li yCoord is the y coordinate in the complete detector system
|
||||||
|
@li zCoord is the z coordinate in the complete detector system
|
||||||
|
@li debug is for debugging purposes
|
||||||
|
@li roundRNumber is the round robin set number
|
||||||
|
@li detType is the detector type see :: detectorType
|
||||||
|
@li version is the version number of this structure format
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint64_t bunchNumber; /**< is the frame number */
|
||||||
|
uint64_t pre; /**< something */
|
||||||
|
|
||||||
|
} jf_header; //Aldo's header!
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
class jungfrauSingleChipData : public slsDetectorData<uint16_t> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
int iframe;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Implements the slsReceiverData structure for the moench02 prototype read
|
||||||
|
out by a module i.e. using the slsReceiver (160x160 pixels, 40 packets
|
||||||
|
1286 large etc.) \param c crosstalk parameter for the output buffer
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ALDO
|
||||||
|
using header = jf_header;
|
||||||
|
#else
|
||||||
|
using header = sls::defs::sls_receiver_header;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZMQ
|
||||||
|
#define off sizeof(header)
|
||||||
|
#endif
|
||||||
|
#ifdef ZMQ
|
||||||
|
#define off 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
jungfrauSingleChipData(uint16_t xmin=0, uint16_t xmax=0,
|
||||||
|
uint16_t ymin=0, uint16_t ymax=0)
|
||||||
|
: slsDetectorData<uint16_t>(256, 256,
|
||||||
|
256* 256 * 2 + off) {
|
||||||
|
|
||||||
|
for (int ix = 0; ix != 256; ++ix) {
|
||||||
|
for (int iy = 0; iy != 256; ++iy) {
|
||||||
|
dataMap[iy][ix] = off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmin < xmax && ymin < ymax) {
|
||||||
|
|
||||||
|
int nc_roi = xmax - xmin + 1;
|
||||||
|
int nr_roi = ymax - ymin + 1;
|
||||||
|
std::cout << "nc_roi = " << nc_roi << std::endl;
|
||||||
|
std::cout << "nr_roi = " << nr_roi << std::endl;
|
||||||
|
|
||||||
|
dataSize =
|
||||||
|
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + off;
|
||||||
|
std::cout << "datasize " << dataSize << std::endl;
|
||||||
|
|
||||||
|
for (int ix = xmin; ix < xmax+1; ++ix) {
|
||||||
|
for (int iy = ymin; iy < ymax+1; ++iy) {
|
||||||
|
dataMap[iy][ix] = off + (nc_roi * iy + ix) * 2;
|
||||||
|
#ifdef HIGHZ
|
||||||
|
dataMask[iy][ix] = 0x3fff;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (int ix = 0; ix < 256; ++ix) {
|
||||||
|
for (int iy = 0; iy < 256; ++iy) {
|
||||||
|
dataMap[iy][ix] = off + (256 * iy + ix) * 2;
|
||||||
|
#ifdef HIGHZ
|
||||||
|
dataMask[iy][ix] = 0x3fff;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
iframe = 0;
|
||||||
|
// cout << "data struct created" << endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value of the selected channel for the given dataset as
|
||||||
|
double. \param data pointer to the dataset (including headers etc) \param
|
||||||
|
ix pixel number in the x direction \param iy pixel number in the y
|
||||||
|
direction \returns data for the selected channel, with inversion if
|
||||||
|
required as double
|
||||||
|
|
||||||
|
*/
|
||||||
|
virtual double getValue(char *data, int ix, int iy = 0) {
|
||||||
|
|
||||||
|
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
|
||||||
|
/* if (ix==0 && iy==0) */
|
||||||
|
/* cout << val << endl; */
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Returns the frame number for the given dataset. Purely virtual func.
|
||||||
|
\param buff pointer to the dataset
|
||||||
|
\returns frame number
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* class jfrau_packet_header_t { */
|
||||||
|
/* public: */
|
||||||
|
/* unsigned char reserved[4]; */
|
||||||
|
/* unsigned char packetNumber[1]; */
|
||||||
|
/* unsigned char frameNumber[3]; */
|
||||||
|
/* unsigned char bunchid[8]; */
|
||||||
|
/* }; */
|
||||||
|
|
||||||
|
int getFrameNumber(char *buff) {
|
||||||
|
return ((jf_header *)buff)->bunchNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Returns the packet number for the given dataset. purely virtual func
|
||||||
|
\param buff pointer to the dataset
|
||||||
|
\returns packet number number
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
int getPacketNumber(char *buff) {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *readNextFrame(ifstream &filebin) {
|
||||||
|
int ff = -1, np = -1;
|
||||||
|
return readNextFrame(filebin, ff, np);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(ifstream &filebin, int &ff) {
|
||||||
|
int np = -1;
|
||||||
|
return readNextFrame(filebin, ff, np);
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(ifstream &filebin, int &ff, int &np) {
|
||||||
|
char *data = new char[dataSize];
|
||||||
|
char *d = readNextFrame(filebin, ff, np, data);
|
||||||
|
if (d == NULL) {
|
||||||
|
delete[] data;
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
char *readNextFrame(ifstream &filebin, int &ff, int &np,char *data) {
|
||||||
|
//char *retval = 0;
|
||||||
|
//int nd;
|
||||||
|
//int fnum = -1;
|
||||||
|
np = 0;
|
||||||
|
//int pn;
|
||||||
|
|
||||||
|
// cout << dataSize << endl;
|
||||||
|
//if (ff >= 0)
|
||||||
|
//fnum = ff;
|
||||||
|
|
||||||
|
if (filebin.is_open()) {
|
||||||
|
if (filebin.read(data, dataSize)) {
|
||||||
|
ff = getFrameNumber(data);
|
||||||
|
np = getPacketNumber(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Loops over a memory slot until a complete frame is found (i.e. all
|
||||||
|
packets 0 to nPackets, same frame number). purely virtual func \param
|
||||||
|
data pointer to the memory to be analyzed \param ndata reference to the
|
||||||
|
amount of data found for the frame, in case the frame is incomplete at
|
||||||
|
the end of the memory slot \param dsize size of the memory slot to be
|
||||||
|
analyzed \returns pointer to the beginning of the last good frame (might
|
||||||
|
be incomplete if ndata smaller than dataSize), or NULL if no frame is
|
||||||
|
found
|
||||||
|
|
||||||
|
*/
|
||||||
|
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
|
||||||
|
if (dsize < dataSize)
|
||||||
|
ndata = dsize;
|
||||||
|
else
|
||||||
|
ndata = dataSize;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -54,6 +54,10 @@ class interpolatingDetector : public singlePhotonDetector {
|
|||||||
pthread_mutex_init(fi, NULL);
|
pthread_mutex_init(fi, NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
pointer-based copy constructor (cloner)
|
||||||
|
\param orig detector to be copied
|
||||||
|
*/
|
||||||
interpolatingDetector(interpolatingDetector *orig)
|
interpolatingDetector(interpolatingDetector *orig)
|
||||||
: singlePhotonDetector(orig) {
|
: singlePhotonDetector(orig) {
|
||||||
// if (orig->interp)
|
// if (orig->interp)
|
||||||
@ -66,10 +70,28 @@ class interpolatingDetector : public singlePhotonDetector {
|
|||||||
fi = orig->fi;
|
fi = orig->fi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy constructor (deep copy)
|
||||||
|
* stricly, TODO: Implement Rule of Five!
|
||||||
|
* (copy op=, move ctor, and move op= would need to be defined)
|
||||||
|
*/
|
||||||
|
interpolatingDetector(interpolatingDetector const& other)
|
||||||
|
: singlePhotonDetector(other) {
|
||||||
|
|
||||||
|
interp = other.interp;
|
||||||
|
|
||||||
|
id = other.id;
|
||||||
|
fi = other.fi;
|
||||||
|
}
|
||||||
|
|
||||||
virtual interpolatingDetector *Clone() {
|
virtual interpolatingDetector *Clone() {
|
||||||
return new interpolatingDetector(this);
|
return new interpolatingDetector(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual interpolatingDetector *Copy() {
|
||||||
|
return new interpolatingDetector(*this);
|
||||||
|
}
|
||||||
|
|
||||||
virtual int setId(int i) {
|
virtual int setId(int i) {
|
||||||
id = i;
|
id = i;
|
||||||
// interp->setId(id);
|
// interp->setId(id);
|
||||||
|
@ -6,18 +6,86 @@
|
|||||||
|
|
||||||
set(JUNGFRAU_EXECUTABLES)
|
set(JUNGFRAU_EXECUTABLES)
|
||||||
|
|
||||||
find_package(fmt REQUIRED)
|
#find_package(fmt REQUIRED)
|
||||||
|
|
||||||
|
#nlohmann_json
|
||||||
|
#If the library was INSTALLED (i.e. sudo dnf install nlohmann-json3-dev), do stuff described in the repo under CMake -> External
|
||||||
|
#find_package(nlohmann_json 3.2.0 REQUIRED)
|
||||||
|
#find_package(nlohmann_json 3.11.2 REQUIRED)
|
||||||
|
#find_package(nlohmann_json 3.11.3 REQUIRED)
|
||||||
|
#
|
||||||
|
#If the library was not installed but just cloned from https://github.com/nlohmann/json.git (possible, because it is a header-only library),
|
||||||
|
# do stuff described in the repo under CMake -> Embedded
|
||||||
|
#set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||||
|
# If you only include this third party in PRIVATE source files, you do not
|
||||||
|
# need to install it when your main project gets installed.
|
||||||
|
# set(JSON_Install OFF CACHE INTERNAL "")
|
||||||
|
#add_subdirectory(nlohmann_json) #Put the actual path to json
|
||||||
|
#
|
||||||
|
#Alternative: Fetch and install it from remote
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
json
|
||||||
|
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
||||||
|
GIT_TAG v3.11.3 # Replace with the version you need
|
||||||
|
)
|
||||||
|
#FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) #Alternative (from the repo documentation)
|
||||||
|
FetchContent_MakeAvailable(json)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
fmt
|
||||||
|
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(fmt)
|
||||||
|
|
||||||
|
# HDF5 file writing
|
||||||
|
if (SLS_USE_HDF5)
|
||||||
|
find_package(HDF5 1.10 COMPONENTS CXX REQUIRED)
|
||||||
|
list (APPEND SOURCES
|
||||||
|
HDF5File.cpp
|
||||||
|
)
|
||||||
|
endif (SLS_USE_HDF5)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# jungfrauRawDataProcess
|
# jungfrauRawDataProcess
|
||||||
add_executable(jungfrauRawDataProcess jungfrauRawDataProcess.cpp)
|
add_executable(jungfrauRawDataProcess jungfrauRawDataProcess.cpp)
|
||||||
target_compile_definitions(jungfrauRawDataProcess PRIVATE MODULE)
|
target_compile_definitions(jungfrauRawDataProcess PRIVATE MODULE)
|
||||||
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcess)
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcess)
|
||||||
|
|
||||||
|
# jungfrauRawDataProcessChipAldo
|
||||||
|
add_executable(jungfrauRawDataProcessChipAldo jungfrauRawDataProcess_filetxt.cpp)
|
||||||
|
target_compile_definitions(jungfrauRawDataProcessChipAldo PRIVATE CHIP ALDO)
|
||||||
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessChipAldo)
|
||||||
|
|
||||||
# jungfrauRawDataProcessStrx
|
# jungfrauRawDataProcessStrx
|
||||||
add_executable(jungfrauRawDataProcessStrx jungfrauRawDataProcess_filetxt.cpp)
|
add_executable(jungfrauRawDataProcessStrx jungfrauRawDataProcess_filetxt.cpp)
|
||||||
target_compile_definitions(jungfrauRawDataProcessStrx PRIVATE JFSTRX)
|
target_compile_definitions(jungfrauRawDataProcessStrx PRIVATE JFSTRX)
|
||||||
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrx)
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrx)
|
||||||
|
|
||||||
|
# jungfrauRawDataProcessStrxQuad
|
||||||
|
add_executable(jungfrauRawDataProcessStrxQuad jungfrauRawDataProcess_filetxt.cpp)
|
||||||
|
target_compile_definitions(jungfrauRawDataProcessStrxQuad PRIVATE JFSTRXQ)
|
||||||
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuad)
|
||||||
|
|
||||||
|
# jungfrauRawDataProcessStrxQuadH5
|
||||||
|
# HDF5
|
||||||
|
if (SLS_USE_HDF5)
|
||||||
|
if (HDF5_FOUND)
|
||||||
|
add_executable(jungfrauRawDataProcessStrxQuadH5 jungfrauRawDataProcess_filetxtH5.cpp)
|
||||||
|
#target_compile_definitions(jungfrauRawDataProcessStrxQuadH5 PRIVATE JFSTRXQH5)
|
||||||
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuadH5)
|
||||||
|
target_include_directories(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
|
||||||
|
target_link_libraries(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_LIBRARIES})
|
||||||
|
|
||||||
|
add_executable(jungfrauRawDataProcessStrxQuadH5SC jungfrauRawDataProcess_filetxtH5_SC.cpp)
|
||||||
|
#target_compile_definitions(jungfrauRawDataProcessStrxQuadH5 PRIVATE JFSTRXQH5)
|
||||||
|
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuadH5SC)
|
||||||
|
target_include_directories(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
|
||||||
|
target_link_libraries(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_LIBRARIES})
|
||||||
|
endif ()
|
||||||
|
endif (SLS_USE_HDF5)
|
||||||
|
|
||||||
# jungfrauRawDataProcessStrxChip1
|
# jungfrauRawDataProcessStrxChip1
|
||||||
add_executable(jungfrauRawDataProcessStrxChip1 jungfrauRawDataProcess.cpp)
|
add_executable(jungfrauRawDataProcessStrxChip1 jungfrauRawDataProcess.cpp)
|
||||||
@ -58,6 +126,22 @@ list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxOldAldo)
|
|||||||
# others to be added if needed (might already be there in Makefile.cluster_finder TO BE CHECKED)
|
# others to be added if needed (might already be there in Makefile.cluster_finder TO BE CHECKED)
|
||||||
|
|
||||||
|
|
||||||
|
if (SLS_USE_HDF5)
|
||||||
|
if (HDF5_FOUND)
|
||||||
|
target_include_directories(jungfrauRawDataProcessStrxQuadH5 PRIVATE
|
||||||
|
${HDF5_INCLUDE_DIRS}
|
||||||
|
${CMAKE_INSTALL_PREFIX}/include
|
||||||
|
)
|
||||||
|
target_link_libraries(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_LIBRARIES})
|
||||||
|
|
||||||
|
target_include_directories(jungfrauRawDataProcessStrxQuadH5SC PRIVATE
|
||||||
|
${HDF5_INCLUDE_DIRS}
|
||||||
|
${CMAKE_INSTALL_PREFIX}/include
|
||||||
|
)
|
||||||
|
target_link_libraries(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_LIBRARIES})
|
||||||
|
|
||||||
|
endif ()
|
||||||
|
endif (SLS_USE_HDF5)
|
||||||
|
|
||||||
|
|
||||||
foreach(exe ${JUNGFRAU_EXECUTABLES})
|
foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||||
@ -67,11 +151,16 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
|||||||
../interpolations
|
../interpolations
|
||||||
../dataStructures
|
../dataStructures
|
||||||
../interpolations/etaVEL
|
../interpolations/etaVEL
|
||||||
../../slsSupportLib/include/
|
../../slsSupportLib/include/sls/
|
||||||
../../slsReceiverSoftware/include/
|
../../slsReceiverSoftware/include/
|
||||||
../tiffio/include
|
../tiffio/include
|
||||||
${fmt_INCLUDE_DIRS}
|
${fmt_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
# if (SLS_USE_HDF5)
|
||||||
|
# if (HDF5_FOUND)
|
||||||
|
# target_include_directories(${exe} PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
|
||||||
|
# endif ()
|
||||||
|
# endif (SLS_USE_HDF5)
|
||||||
|
|
||||||
target_link_libraries(${exe}
|
target_link_libraries(${exe}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@ -79,6 +168,7 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
|||||||
pthread
|
pthread
|
||||||
tiffio
|
tiffio
|
||||||
fmt::fmt
|
fmt::fmt
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
#-L/usr/lib64/
|
#-L/usr/lib64/
|
||||||
#-lm -lstdc++ -lrt
|
#-lm -lstdc++ -lrt
|
||||||
|
|
||||||
@ -86,7 +176,11 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
|||||||
slsProjectWarnings
|
slsProjectWarnings
|
||||||
slsProjectOptions
|
slsProjectOptions
|
||||||
)
|
)
|
||||||
|
# if (SLS_USE_HDF5)
|
||||||
|
# if (HDF5_FOUND)
|
||||||
|
# target_link_libraries(${exe} PRIVATE ${HDF5_LIBRARIES})
|
||||||
|
# endif ()
|
||||||
|
# endif (SLS_USE_HDF5)
|
||||||
|
|
||||||
set_target_properties(${exe} PROPERTIES
|
set_target_properties(${exe} PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||||
@ -98,4 +192,8 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
|||||||
|
|
||||||
endforeach(exe ${JUNGFRAU_EXECUTABLES})
|
endforeach(exe ${JUNGFRAU_EXECUTABLES})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
|
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
|
@ -11,7 +11,7 @@
|
|||||||
#define RAWDATA
|
#define RAWDATA
|
||||||
|
|
||||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||||
!defined JFSTRXCHIP6
|
!defined JFSTRXCHIP6 && !defined CHIP
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
#include "jungfrauHighZSingleChipData.h"
|
#include "jungfrauHighZSingleChipData.h"
|
||||||
#endif
|
#endif
|
||||||
@ -20,6 +20,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHIP
|
||||||
|
#include "jungfrauSingleChipData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JFSTRX
|
#ifdef JFSTRX
|
||||||
#include "jungfrauLGADStrixelsData_new.h"
|
#include "jungfrauLGADStrixelsData_new.h"
|
||||||
#endif
|
#endif
|
||||||
@ -41,6 +45,9 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
std::string getRootString( const std::string& filepath ) {
|
std::string getRootString( const std::string& filepath ) {
|
||||||
size_t pos1 = filepath.find_last_of("/");
|
size_t pos1 = filepath.find_last_of("/");
|
||||||
@ -61,20 +68,24 @@ std::string getRootString( const std::string& filepath ) {
|
|||||||
std::string createFileName( const std::string& dir, const std::string& fprefix="run", const std::string& fsuffix="", const std::string& fext="raw", int aindex=0, int mindex=0, int findex=0, int outfilecounter=-1 ) {
|
std::string createFileName( const std::string& dir, const std::string& fprefix="run", const std::string& fsuffix="", const std::string& fext="raw", int aindex=0, int mindex=0, int findex=0, int outfilecounter=-1 ) {
|
||||||
if (outfilecounter >= 0)
|
if (outfilecounter >= 0)
|
||||||
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}_f{:05d}.{:s}", dir, fprefix, mindex, findex, aindex, outfilecounter, fext);
|
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}_f{:05d}.{:s}", dir, fprefix, mindex, findex, aindex, outfilecounter, fext);
|
||||||
else if (fsuffix.length()!=0)
|
else if (fsuffix.length()!=0) {
|
||||||
return fmt::format("{:s}/{:s}_{:s}.{:s}", dir, fprefix, fsuffix, fext);
|
if (fsuffix == "master")
|
||||||
|
return fmt::format("{:s}/{:s}_master_{:d}.{:s}", dir, fprefix, aindex, fext);
|
||||||
|
else
|
||||||
|
return fmt::format("{:s}/{:s}_{:s}.{:s}", dir, fprefix, fsuffix, fext);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}.{:s}", dir, fprefix, mindex, findex, aindex, fext);
|
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}.{:s}", dir, fprefix, mindex, findex, aindex, fext);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (argc < 5) {
|
if (argc < 6) {
|
||||||
std::cout
|
std::cout
|
||||||
<< "Usage is " << argv[0]
|
<< "Usage is " << argv[0]
|
||||||
<< "indir outdir fprefix(excluding slsDetector standard suffixes and extension) fextension "
|
<< "indir outdir [fprefix(excluding slsDetector standard suffixes and extension)] [fextension] "
|
||||||
"[runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
|
"[fmin] [fmax] [runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
|
||||||
"[nframes] [xmin xmax ymin ymax] [gainmap]"
|
"[nframes] [xmin xmax ymin ymax] [optional: bool read rxroi from data file header] [gainmap]"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout
|
std::cout
|
||||||
<< "threshold <0 means analog; threshold=0 means cluster finder; "
|
<< "threshold <0 means analog; threshold=0 means cluster finder; "
|
||||||
@ -106,94 +117,131 @@ int main(int argc, char *argv[]) {
|
|||||||
std::string outdir(argv[2]);
|
std::string outdir(argv[2]);
|
||||||
std::string fprefix(argv[3]);
|
std::string fprefix(argv[3]);
|
||||||
std::string fext(argv[4]);
|
std::string fext(argv[4]);
|
||||||
|
|
||||||
|
int fmin = 0;
|
||||||
|
if (argc >= 6)
|
||||||
|
fmin = atoi(argv[5]);
|
||||||
|
int fmax = fmin;
|
||||||
|
if (argc >= 7)
|
||||||
|
fmax = atoi(argv[6]);
|
||||||
|
|
||||||
int runmin = 0;
|
int runmin = 0;
|
||||||
|
|
||||||
// cout << "argc is " << argc << endl;
|
// cout << "argc is " << argc << endl;
|
||||||
if (argc >= 6) {
|
if (argc >= 8) {
|
||||||
runmin = atoi(argv[5]);
|
runmin = atoi(argv[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int runmax = runmin;
|
int runmax = runmin;
|
||||||
|
if (argc >= 9) {
|
||||||
if (argc >= 7) {
|
runmax = atoi(argv[8]);
|
||||||
runmax = atoi(argv[6]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pedfilename{};
|
std::string pedfilename{};
|
||||||
if (argc >= 8) {
|
if (argc >= 10) {
|
||||||
pedfilename = argv[7];
|
pedfilename = argv[9];
|
||||||
}
|
}
|
||||||
double thr = 0;
|
double thr = 0;
|
||||||
double thr1 = 1;
|
double thr1 = 1;
|
||||||
|
|
||||||
if (argc >= 9) {
|
if (argc >= 11) {
|
||||||
thr = atof(argv[8]);
|
thr = atof(argv[10]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nframes = 0;
|
int nframes = 0;
|
||||||
|
|
||||||
if (argc >= 10) {
|
if (argc >= 12) {
|
||||||
nframes = atoi(argv[9]);
|
nframes = atoi(argv[11]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readrxroifromdatafile = false;
|
||||||
|
if (argc >= 17)
|
||||||
|
readrxroifromdatafile = atoi(argv[16]);
|
||||||
|
|
||||||
|
// Receiver ROI
|
||||||
|
uint16_t rxroi_xmin = 0;
|
||||||
|
uint16_t rxroi_xmax = 0;
|
||||||
|
uint16_t rxroi_ymin = 0;
|
||||||
|
uint16_t rxroi_ymax = 0;
|
||||||
|
|
||||||
|
{ //protective scope so ifstream gets destroyed properly
|
||||||
|
|
||||||
|
auto jsonmastername = createFileName( indir, fprefix, "master", "json", runmin );
|
||||||
|
std::cout << "json master file " << jsonmastername << std::endl;
|
||||||
|
std::ifstream masterfile(jsonmastername); //, ios::in | ios::binary);
|
||||||
|
if (masterfile.is_open()) {
|
||||||
|
json j;
|
||||||
|
masterfile >> j;
|
||||||
|
rxroi_xmin = j["Receiver Roi"]["xmin"];
|
||||||
|
rxroi_xmax = j["Receiver Roi"]["xmax"];
|
||||||
|
rxroi_ymin = j["Receiver Roi"]["ymin"];
|
||||||
|
rxroi_ymax = j["Receiver Roi"]["ymax"];
|
||||||
|
masterfile.close();
|
||||||
|
std::cout << "Read Receiver ROI [" << rxroi_xmin << ", " << rxroi_xmax << ", "
|
||||||
|
<< rxroi_ymin << ", " << rxroi_ymax << "] from json master file" << std::endl;
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open master file " << jsonmastername << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define decoders...
|
// Define decoders...
|
||||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||||
!defined JFSTRXCHIP6
|
!defined JFSTRXCHIP6 && !defined CHIP
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
|
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
|
||||||
int nx = 256, ny = 256;
|
int nx = 256, ny = 256;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
jungfrauModuleData *decoder = new jungfrauModuleData();
|
jungfrauModuleData *decoder = new jungfrauModuleData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||||
int nx = 1024, ny = 512;
|
int nx = 1024, ny = 512;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHIP
|
||||||
|
std::cout << "Jungfrau pixel module single chip readout" << std::endl;
|
||||||
|
jungfrauSingleChipData *decoder = new jungfrauSingleChipData();
|
||||||
|
int nx = 256, ny = 256;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JFSTRX
|
#ifdef JFSTRX
|
||||||
cout << "Jungfrau strixel full module readout" << endl;
|
std::cout << "Jungfrau strixel full module readout" << std::endl;
|
||||||
// ROI
|
|
||||||
uint16_t xxmin = 0;
|
|
||||||
uint16_t xxmax = 0;
|
|
||||||
uint16_t yymin = 0;
|
|
||||||
uint16_t yymax = 0;
|
|
||||||
|
|
||||||
#ifndef ALDO
|
#ifndef ALDO
|
||||||
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
|
if (readrxroifromdatafile)
|
||||||
using header = sls::defs::sls_receiver_header;
|
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
|
||||||
// check if there is a roi in the header
|
using header = sls::defs::sls_receiver_header;
|
||||||
typedef struct {
|
// check if there is a roi in the header
|
||||||
uint16_t xmin;
|
typedef struct {
|
||||||
uint16_t xmax;
|
uint16_t xmin;
|
||||||
uint16_t ymin;
|
uint16_t xmax;
|
||||||
uint16_t ymax;
|
uint16_t ymin;
|
||||||
} receiverRoi_compact;
|
uint16_t ymax;
|
||||||
receiverRoi_compact croi;
|
} receiverRoi_compact;
|
||||||
std::string fsuffix{};
|
receiverRoi_compact croi;
|
||||||
auto filename = createFileName( indir, fprefix, fsuffix, fext, runmin );
|
std::string fsuffix{};
|
||||||
std::cout << "Reading header of file " << filename << " to check for ROI "
|
auto filename = createFileName( indir, fprefix, fsuffix, fext, runmin );
|
||||||
<< std::endl;
|
std::cout << "Reading header of file " << filename << " to check for ROI "
|
||||||
ifstream firstfile(filename, ios::in | ios::binary);
|
<< std::endl;
|
||||||
if (firstfile.is_open()) {
|
ifstream firstfile(filename, ios::in | ios::binary);
|
||||||
header hbuffer;
|
if (firstfile.is_open()) {
|
||||||
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
|
header hbuffer;
|
||||||
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
|
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
|
||||||
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
|
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
|
||||||
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
|
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
|
||||||
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
|
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
|
||||||
xxmin = croi.xmin;
|
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
|
||||||
xxmax = croi.xmax;
|
rxroi_xmin = croi.xmin;
|
||||||
yymin = croi.ymin;
|
rxroi_xmax = croi.xmax;
|
||||||
yymax = croi.ymax;
|
rxroi_ymin = croi.ymin;
|
||||||
} else
|
rxroi_ymax = croi.ymax;
|
||||||
std::cout << "reading error" << std::endl;
|
} else
|
||||||
firstfile.close();
|
std::cout << "reading error" << std::endl;
|
||||||
} else
|
firstfile.close();
|
||||||
std::cout << "Could not open " << filename << " for reading " << std::endl;
|
} else
|
||||||
} //end of protective scope
|
std::cout << "Could not open " << filename << " for reading " << std::endl;
|
||||||
|
} //end of protective scope
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
jungfrauLGADStrixelsData *decoder =
|
jungfrauLGADStrixelsData *decoder =
|
||||||
new jungfrauLGADStrixelsData(xxmin, xxmax, yymin, yymax);
|
new jungfrauLGADStrixelsData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||||
int nx = 1024 / 3, ny = 512 * 5;
|
int nx = 1024 / 3, ny = 512 * 5;
|
||||||
#endif
|
#endif
|
||||||
#ifdef JFSTRXCHIP1
|
#ifdef JFSTRXCHIP1
|
||||||
@ -218,19 +266,20 @@ int main(int argc, char *argv[]) {
|
|||||||
decoder->getDetectorSize(nx, ny);
|
decoder->getDetectorSize(nx, ny);
|
||||||
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
||||||
|
|
||||||
int xmin = 0, xmax = nx, ymin = 0, ymax = ny;
|
//Cluster finder ROI
|
||||||
if (argc >= 14) {
|
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
|
||||||
xmin = atoi(argv[10]);
|
if (argc >= 16) {
|
||||||
xmax = atoi(argv[11]);
|
xmin = atoi(argv[12]);
|
||||||
ymin = atoi(argv[12]);
|
xmax = atoi(argv[13]);
|
||||||
ymax = atoi(argv[13]);
|
ymin = atoi(argv[14]);
|
||||||
|
ymax = atoi(argv[15]);
|
||||||
}
|
}
|
||||||
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
|
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
char *gainfname = NULL;
|
char *gainfname = NULL;
|
||||||
if (argc > 14) {
|
if (argc > 17) {
|
||||||
gainfname = argv[14];
|
gainfname = argv[17];
|
||||||
std::cout << "Gain map file name is: " << gainfname << std::endl;
|
std::cout << "Gain map file name is: " << gainfname << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,6 +288,8 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << "input directory is " << indir << std::endl;
|
std::cout << "input directory is " << indir << std::endl;
|
||||||
std::cout << "output directory is " << outdir << std::endl;
|
std::cout << "output directory is " << outdir << std::endl;
|
||||||
std::cout << "input file prefix is " << fprefix << std::endl;
|
std::cout << "input file prefix is " << fprefix << std::endl;
|
||||||
|
std::cout << "fmin is " << fmin << std::endl;
|
||||||
|
std::cout << "fmax is " << fmax << std::endl;
|
||||||
std::cout << "runmin is " << runmin << std::endl;
|
std::cout << "runmin is " << runmin << std::endl;
|
||||||
std::cout << "runmax is " << runmax << std::endl;
|
std::cout << "runmax is " << runmax << std::endl;
|
||||||
if (pedfilename.length()!=0)
|
if (pedfilename.length()!=0)
|
||||||
@ -319,7 +370,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
mt->setFrameMode(ePedestal);
|
mt->setFrameMode(ePedestal);
|
||||||
|
|
||||||
ifstream pedefile(fname, ios::in | ios::binary);
|
std::ifstream pedefile(fname, ios::in | ios::binary);
|
||||||
// //open file
|
// //open file
|
||||||
if (pedefile.is_open()) {
|
if (pedefile.is_open()) {
|
||||||
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
|
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
|
||||||
@ -380,26 +431,27 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ifr = 0;
|
ifr = 0;
|
||||||
int ifile = 0;
|
int ioutfile = 0;
|
||||||
|
|
||||||
mt->setFrameMode(eFrame);
|
mt->setFrameMode(eFrame);
|
||||||
|
|
||||||
FILE *of = NULL;
|
FILE *of = NULL;
|
||||||
|
|
||||||
for (int irun = runmin; irun <= runmax; irun++) {
|
for (int irun = runmin; irun <= runmax; ++irun) {
|
||||||
|
for (int ifile = fmin; ifile <= fmax; ++ifile) {
|
||||||
std::cout << "DATA ";
|
std::cout << "DATA ";
|
||||||
std::string fsuffix{};
|
std::string fsuffix{};
|
||||||
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun );
|
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun, 0, ifile );
|
||||||
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun );
|
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, ifile );
|
||||||
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun );
|
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun, 0, ifile );
|
||||||
std::cout << fname << " ";
|
std::cout << fname << " ";
|
||||||
std::cout << imgfname << std::endl;
|
std::cout << imgfname << std::endl;
|
||||||
std::time(&end_time);
|
std::time(&end_time);
|
||||||
std::cout << std::ctime(&end_time) << std::endl;
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
// std::cout << fname << " " << outfname << " " << imgfname << std::endl;
|
// std::cout << fname << " " << outfname << " " << imgfname << std::endl;
|
||||||
ifstream filebin(fname, ios::in | ios::binary);
|
std::ifstream filebin(fname, ios::in | ios::binary);
|
||||||
// //open file
|
// //open file
|
||||||
ifile = 0;
|
ioutfile = 0;
|
||||||
if (filebin.is_open()) {
|
if (filebin.is_open()) {
|
||||||
if (thr <= 0 && cf != 0) { // cluster finder
|
if (thr <= 0 && cf != 0) { // cluster finder
|
||||||
if (of == NULL) {
|
if (of == NULL) {
|
||||||
@ -436,10 +488,10 @@ int main(int argc, char *argv[]) {
|
|||||||
std::cout << " " << ifr << " " << ff << std::endl;
|
std::cout << " " << ifr << " " << ff << std::endl;
|
||||||
if (nframes > 0) {
|
if (nframes > 0) {
|
||||||
if (ifr % nframes == 0) {
|
if (ifr % nframes == 0) {
|
||||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
|
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
|
||||||
mt->writeImage(imgfname.c_str(), thr1);
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
mt->clearImage();
|
mt->clearImage();
|
||||||
ifile++;
|
ioutfile++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// } else
|
// } else
|
||||||
@ -453,7 +505,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
if (nframes >= 0) {
|
if (nframes >= 0) {
|
||||||
if (nframes > 0)
|
if (nframes > 0)
|
||||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
|
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
|
||||||
std::cout << "Writing tiff to " << imgfname << " " << thr1
|
std::cout << "Writing tiff to " << imgfname << " " << thr1
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
mt->writeImage(imgfname.c_str(), thr1);
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
@ -469,9 +521,10 @@ int main(int argc, char *argv[]) {
|
|||||||
} else
|
} else
|
||||||
std::cout << "Could not open " << fname << " for reading "
|
std::cout << "Could not open " << fname << " for reading "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nframes < 0) {
|
if (nframes < 0) {
|
||||||
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", -1, 0, 0, -1 );
|
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", runmin, 0, fmin, -1 );
|
||||||
std::cout << "Writing tiff to " << imgfname << " " << thr1 << std::endl;
|
std::cout << "Writing tiff to " << imgfname << " " << thr1 << std::endl;
|
||||||
mt->writeImage(imgfname.c_str(), thr1);
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#define RAWDATA
|
#define RAWDATA
|
||||||
|
|
||||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
#if !defined JFSTRX && !defined JFSTRXQ && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||||
!defined JFSTRXCHIP6
|
!defined JFSTRXCHIP6 && !defined CHIP
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
#include "jungfrauHighZSingleChipData.h"
|
#include "jungfrauHighZSingleChipData.h"
|
||||||
#endif
|
#endif
|
||||||
@ -20,9 +20,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHIP
|
||||||
|
#include "jungfrauSingleChipData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JFSTRX
|
#ifdef JFSTRX
|
||||||
#include "jungfrauLGADStrixelsData_new.h"
|
#include "jungfrauLGADStrixelsData_new.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef JFSTRXQ
|
||||||
|
#include "jungfrauLGADStrixelsDataQuad.h"
|
||||||
|
#endif
|
||||||
#if defined JFSTRXCHIP1 || defined JFSTRXCHIP6
|
#if defined JFSTRXCHIP1 || defined JFSTRXCHIP6
|
||||||
#include "jungfrauLGADStrixelsDataSingleChip.h"
|
#include "jungfrauLGADStrixelsDataSingleChip.h"
|
||||||
#endif
|
#endif
|
||||||
@ -41,6 +48,9 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
std::string getRootString( const std::string& filepath ) {
|
std::string getRootString( const std::string& filepath ) {
|
||||||
size_t pos1;
|
size_t pos1;
|
||||||
@ -71,11 +81,11 @@ std::string createFileName( const std::string& dir, const std::string& fprefix="
|
|||||||
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
|
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (argc < 10) {
|
if (argc < 11) {
|
||||||
std::cout
|
std::cout
|
||||||
<< "Usage is " << argv[0]
|
<< "Usage is " << argv[0]
|
||||||
<< " filestxt outdir [pedfile (raw or tiff)] [xmin xmax ymin ymax] "
|
<< " filestxt outdir [json master] [pedfile (raw or tiff)] [xmin xmax ymin ymax] "
|
||||||
"[threshold] [nframes] "
|
"[threshold] [nframes] [optional: bool read rxroi from data file header]"
|
||||||
"NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
|
"NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout
|
std::cout
|
||||||
@ -105,19 +115,19 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
const std::string txtfilename(argv[1]);
|
const std::string txtfilename(argv[1]);
|
||||||
const std::string outdir(argv[2]);
|
const std::string outdir(argv[2]);
|
||||||
const std::string pedfilename(argv[3]);
|
const std::string jsonmastername(argv[3]);
|
||||||
|
const std::string pedfilename(argv[4]);
|
||||||
int xmin = atoi(argv[4]);
|
|
||||||
int xmax = atoi(argv[5]);
|
|
||||||
int ymin = atoi(argv[6]);
|
|
||||||
int ymax = atoi(argv[7]);
|
|
||||||
|
|
||||||
double thr = 0;
|
double thr = 0;
|
||||||
double thr1 = 1;
|
double thr1 = 1;
|
||||||
thr = atof(argv[8]);
|
thr = atof(argv[9]);
|
||||||
|
|
||||||
int nframes = 0;
|
int nframes = 0;
|
||||||
nframes = atoi(argv[9]);
|
nframes = atoi(argv[10]);
|
||||||
|
|
||||||
|
bool readrxroifromdatafile = false;
|
||||||
|
if (argc > 11)
|
||||||
|
readrxroifromdatafile = atoi(argv[11]);
|
||||||
|
|
||||||
//Get vector of filenames from input txt-file
|
//Get vector of filenames from input txt-file
|
||||||
std::vector<std::string> filenames{};
|
std::vector<std::string> filenames{};
|
||||||
@ -147,9 +157,33 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
std::cout << "###############" << std::endl;
|
std::cout << "###############" << std::endl;
|
||||||
|
|
||||||
|
// Receiver ROI
|
||||||
|
uint16_t rxroi_xmin = 0;
|
||||||
|
uint16_t rxroi_xmax = 0;
|
||||||
|
uint16_t rxroi_ymin = 0;
|
||||||
|
uint16_t rxroi_ymax = 0;
|
||||||
|
|
||||||
|
{ //protective scope so ifstream gets destroyed properly
|
||||||
|
|
||||||
|
std::ifstream masterfile(jsonmastername); //, ios::in | ios::binary);
|
||||||
|
if (masterfile.is_open()) {
|
||||||
|
json j;
|
||||||
|
masterfile >> j;
|
||||||
|
rxroi_xmin = j["Receiver Roi"]["xmin"];
|
||||||
|
rxroi_xmax = j["Receiver Roi"]["xmax"];
|
||||||
|
rxroi_ymin = j["Receiver Roi"]["ymin"];
|
||||||
|
rxroi_ymax = j["Receiver Roi"]["ymax"];
|
||||||
|
masterfile.close();
|
||||||
|
std::cout << "Read rxROI [" << rxroi_xmin << ", " << rxroi_xmax << ", "
|
||||||
|
<< rxroi_ymin << ", " << rxroi_ymax << "]" << std::endl;
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open master file " << jsonmastername << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Define decoders...
|
// Define decoders...
|
||||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
#if !defined JFSTRX && !defined JFSTRXQ && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||||
!defined JFSTRXCHIP6
|
!defined JFSTRXCHIP6 && !defined CHIP
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
|
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
|
||||||
int nx = 256, ny = 256;
|
int nx = 256, ny = 256;
|
||||||
@ -160,52 +194,60 @@ int main(int argc, char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CHIP
|
||||||
|
std::cout << "Jungfrau pixel module single chip readout" << std::endl;
|
||||||
|
jungfrauSingleChipData *decoder = new jungfrauSingleChipData();
|
||||||
|
int nx = 256, ny = 256;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JFSTRX
|
#ifdef JFSTRX
|
||||||
cout << "Jungfrau strixel full module readout" << endl;
|
std::cout << "Jungfrau strixel full module readout" << std::endl;
|
||||||
// ROI
|
|
||||||
uint16_t xxmin = 0;
|
|
||||||
uint16_t xxmax = 0;
|
|
||||||
uint16_t yymin = 0;
|
|
||||||
uint16_t yymax = 0;
|
|
||||||
|
|
||||||
#ifndef ALDO
|
#ifndef ALDO
|
||||||
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
|
if (readrxroifromdatafile)
|
||||||
using header = sls::defs::sls_receiver_header;
|
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
|
||||||
// check if there is a roi in the header
|
using header = sls::defs::sls_receiver_header;
|
||||||
typedef struct {
|
// check if there is a roi in the header
|
||||||
uint16_t xmin;
|
typedef struct {
|
||||||
uint16_t xmax;
|
uint16_t xmin;
|
||||||
uint16_t ymin;
|
uint16_t xmax;
|
||||||
uint16_t ymax;
|
uint16_t ymin;
|
||||||
} receiverRoi_compact;
|
uint16_t ymax;
|
||||||
receiverRoi_compact croi;
|
} receiverRoi_compact;
|
||||||
//std::string filepath(argv[9]); //This is a problem if the input files have different ROIs!
|
receiverRoi_compact croi;
|
||||||
std::cout << "Reading header of file " << filenames[0] << " to check for ROI "
|
//std::string filepath(argv[9]); //This is a problem if the input files have different ROIs!
|
||||||
<< std::endl;
|
std::cout << "Reading header of file " << filenames[0] << " to check for ROI "
|
||||||
ifstream firstfile(filenames[0], ios::in | ios::binary);
|
<< std::endl;
|
||||||
if (firstfile.is_open()) {
|
std::ifstream firstfile( filenames[0], ios::in | ios::binary);
|
||||||
header hbuffer;
|
if (firstfile.is_open()) {
|
||||||
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
|
header hbuffer;
|
||||||
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
|
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
|
||||||
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
|
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
|
||||||
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
|
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
|
||||||
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
|
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
|
||||||
xxmin = croi.xmin;
|
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
|
||||||
xxmax = croi.xmax;
|
rxroi_xmin = croi.xmin;
|
||||||
yymin = croi.ymin;
|
rxroi_xmax = croi.xmax;
|
||||||
yymax = croi.ymax;
|
rxroi_ymin = croi.ymin;
|
||||||
} else
|
rxroi_ymax = croi.ymax;
|
||||||
std::cout << "reading error" << std::endl;
|
} else
|
||||||
firstfile.close();
|
std::cout << "reading error" << std::endl;
|
||||||
} else
|
firstfile.close();
|
||||||
std::cout << "Could not open " << filenames[0] << " for reading " << std::endl;
|
} else
|
||||||
} //end of protective scope
|
std::cout << "Could not open " << filenames[0] << " for reading " << std::endl;
|
||||||
|
} //end of protective scope
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
jungfrauLGADStrixelsData *decoder =
|
jungfrauLGADStrixelsData *decoder =
|
||||||
new jungfrauLGADStrixelsData(xxmin, xxmax, yymin, yymax);
|
new jungfrauLGADStrixelsData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||||
int nx = 1024 / 3, ny = 512 * 5;
|
int nx = 1024 / 3, ny = 512 * 5;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef JFSTRXQ
|
||||||
|
std::cout << "Jungfrau strixel quad" << std::endl;
|
||||||
|
jungfrauLGADStrixelsDataQuad *decoder =
|
||||||
|
new jungfrauLGADStrixelsDataQuad(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||||
|
int nx = 1024 / 3, ny = 512 * 3;
|
||||||
|
#endif
|
||||||
#ifdef JFSTRXCHIP1
|
#ifdef JFSTRXCHIP1
|
||||||
std::cout << "Jungfrau strixel LGAD single chip 1" << std::endl;
|
std::cout << "Jungfrau strixel LGAD single chip 1" << std::endl;
|
||||||
jungfrauLGADStrixelsDataSingleChip *decoder =
|
jungfrauLGADStrixelsDataSingleChip *decoder =
|
||||||
@ -228,7 +270,16 @@ int main(int argc, char *argv[]) {
|
|||||||
decoder->getDetectorSize(nx, ny);
|
decoder->getDetectorSize(nx, ny);
|
||||||
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
||||||
|
|
||||||
|
//Cluster finder ROI
|
||||||
|
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
|
||||||
|
xmin = atoi(argv[5]);
|
||||||
|
xmax = atoi(argv[6]);
|
||||||
|
ymin = atoi(argv[7]);
|
||||||
|
ymax = atoi(argv[8]);
|
||||||
|
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
/* old
|
||||||
if ( xmin == xmax ) {
|
if ( xmin == xmax ) {
|
||||||
xmin = 0;
|
xmin = 0;
|
||||||
xmax = nx;
|
xmax = nx;
|
||||||
@ -239,6 +290,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
|
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
char *gainfname = NULL;
|
char *gainfname = NULL;
|
||||||
@ -410,7 +462,7 @@ int main(int argc, char *argv[]) {
|
|||||||
std::time(&end_time);
|
std::time(&end_time);
|
||||||
std::cout << std::ctime(&end_time) << std::endl;
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
ifstream filebin(filenames[ifile], ios::in | ios::binary);
|
std::ifstream filebin(filenames[ifile], ios::in | ios::binary);
|
||||||
// //open file
|
// //open file
|
||||||
ioutfile = 0;
|
ioutfile = 0;
|
||||||
if (filebin.is_open()) {
|
if (filebin.is_open()) {
|
||||||
|
@ -0,0 +1,457 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
#include "jungfrauLGADStrixelsDataQuadH5.h"
|
||||||
|
|
||||||
|
#include "multiThreadedCountingDetector.h"
|
||||||
|
#include "singlePhotonDetector.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Dataset paths according to different beamlines*/
|
||||||
|
std::string const data_datasetname_furka("/data/JF18T01V01/data");
|
||||||
|
std::string const index_datasetname_furka("/data/JF18T01V01/frame_index");
|
||||||
|
std::string const data_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/adc");
|
||||||
|
std::string const index_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/frameNumber");
|
||||||
|
|
||||||
|
std::string getRootString( std::string const& filepath ) {
|
||||||
|
size_t pos1;
|
||||||
|
if (filepath.find("/") == std::string::npos )
|
||||||
|
pos1 = 0;
|
||||||
|
else
|
||||||
|
pos1 = filepath.find_last_of("/")+1;
|
||||||
|
size_t pos2 = filepath.find_last_of(".");
|
||||||
|
//std::cout << "pos1 " << pos1 << " pos2 " << pos2 << " size " << filepath.length() << std::endl;
|
||||||
|
return filepath.substr( pos1, pos2-pos1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create file name string
|
||||||
|
// dir: directory
|
||||||
|
// fprefix: fileprefix (without extension)
|
||||||
|
// fsuffix: filesuffix (for output files, e.g. "ped")
|
||||||
|
// fext: file extension (e.g. "raw")
|
||||||
|
std::string createFileName( std::string const& dir, std::string const& fprefix="run",
|
||||||
|
std::string const& fsuffix="", std::string const& fext="raw", int const outfilecounter=-1 ) {
|
||||||
|
std::string return_string;
|
||||||
|
if (outfilecounter >= 0)
|
||||||
|
return_string = fmt::format("{:s}/{:s}_{:s}_f{:05d}", dir, fprefix, fsuffix, outfilecounter);
|
||||||
|
else if (fsuffix.length()!=0)
|
||||||
|
return_string = fmt::format("{:s}/{:s}_{:s}", dir, fprefix, fsuffix);
|
||||||
|
else
|
||||||
|
return_string = fmt::format("{:s}/{:s}", dir, fprefix);
|
||||||
|
|
||||||
|
if (fext.length()!=0)
|
||||||
|
return_string += "." + fext;
|
||||||
|
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
if (argc < 4) {
|
||||||
|
std::cout
|
||||||
|
<< "Usage is " << argv[0]
|
||||||
|
<< " filestxt outdir [pedfile (h5)] "
|
||||||
|
" optional: [int dataset path; 0 means Furka, 1 means XFEL; overwrites default given in HDF5File.h] "
|
||||||
|
" [bool validate h5 rank] "
|
||||||
|
" [xmin xmax ymin ymax] [threshold] [nframes] "
|
||||||
|
" NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
|
||||||
|
<< std::endl;
|
||||||
|
std::cout
|
||||||
|
<< "threshold <0 means analog; threshold=0 means cluster finder; "
|
||||||
|
"threshold>0 means photon counting"
|
||||||
|
<< std::endl;
|
||||||
|
std::cout
|
||||||
|
<< "nframes <0 means sum everything; nframes=0 means one file per "
|
||||||
|
"run; nframes>0 means one file every nframes"
|
||||||
|
<< std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const fifosize = 100; //1000;
|
||||||
|
int const nthreads = 10;
|
||||||
|
int const csize = 3; // 3
|
||||||
|
int const nsigma = 5;
|
||||||
|
int const nped = 10000;
|
||||||
|
|
||||||
|
int cf = 0;
|
||||||
|
|
||||||
|
std::string const txtfilename(argv[1]);
|
||||||
|
std::string const outdir(argv[2]);
|
||||||
|
std::string const pedfilename(argv[3]);
|
||||||
|
|
||||||
|
std::string datasetpath{};
|
||||||
|
std::string frameindexpath{};
|
||||||
|
if (argc > 4) {
|
||||||
|
switch (atoi(argv[4])) {
|
||||||
|
case 0:
|
||||||
|
datasetpath = data_datasetname_furka;
|
||||||
|
frameindexpath = index_datasetname_furka;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
datasetpath = data_datasetname_xfelSCS;
|
||||||
|
frameindexpath = index_datasetname_xfelSCS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validate_rank=true;
|
||||||
|
if (argc > 5)
|
||||||
|
validate_rank = atoi(argv[5]);
|
||||||
|
|
||||||
|
double thr = 0;
|
||||||
|
double thr1 = 1;
|
||||||
|
if (argc > 9)
|
||||||
|
thr = atof(argv[9]);
|
||||||
|
|
||||||
|
int nframes = 0;
|
||||||
|
if (argc > 10)
|
||||||
|
nframes = atoi(argv[10]);
|
||||||
|
|
||||||
|
//Get vector of filenames from input txt-file
|
||||||
|
std::vector<std::string> filenames{};
|
||||||
|
//filenames.reserve(512);
|
||||||
|
{ //Safety scope for ifstream
|
||||||
|
ifstream inputs( txtfilename, std::ios::in );
|
||||||
|
if (inputs.is_open()) {
|
||||||
|
std::cout << "Reading imput filenames from txt-file ..." << std::endl;
|
||||||
|
std::string line{};
|
||||||
|
while (!inputs.eof()) {
|
||||||
|
std::getline(inputs, line);
|
||||||
|
if(line.find(".h5") != std::string::npos) {
|
||||||
|
filenames.emplace_back(line);
|
||||||
|
std::cout << line << std::endl; //" line.max_size() " << line.max_size() << " filenames.capacity() " << filenames.capacity() << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputs.close();
|
||||||
|
std::cout << "---- Reached end of txt-file. ----" << std::endl;
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open " << txtfilename << std::endl;
|
||||||
|
if (filenames.size()>0) {
|
||||||
|
std::cout << filenames.size() << " filenames found in " << txtfilename << std::endl;
|
||||||
|
std::cout << "The files will be processed in the same order as found in the txt-file." << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "No files found in txt-file!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "###############" << std::endl;
|
||||||
|
|
||||||
|
// Define decoder
|
||||||
|
std::cout << "Jungfrau strixel quad h5" << std::endl;
|
||||||
|
jungfrauLGADStrixelsDataQuadH5* decoder = new jungfrauLGADStrixelsDataQuadH5();
|
||||||
|
//auto decoder = std::make_unique<jungfrauLGADStrixelsDataQuadH5>();
|
||||||
|
int nx = 1024 / 3, ny = 512 * 3;
|
||||||
|
|
||||||
|
//Cluster finder ROI
|
||||||
|
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
|
||||||
|
if (argc > 9) {
|
||||||
|
xmin = atoi(argv[6]);
|
||||||
|
xmax = atoi(argv[7]);
|
||||||
|
ymin = atoi(argv[8]);
|
||||||
|
ymax = atoi(argv[9]);
|
||||||
|
}
|
||||||
|
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
decoder->getDetectorSize(nx, ny);
|
||||||
|
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
||||||
|
|
||||||
|
std::time_t end_time;
|
||||||
|
|
||||||
|
std::cout << "output directory is " << outdir << std::endl;
|
||||||
|
if (pedfilename.length()!=0)
|
||||||
|
std::cout << "pedestal file is " << pedfilename << std::endl;
|
||||||
|
if (thr > 0)
|
||||||
|
std::cout << "threshold is " << thr << std::endl;
|
||||||
|
std::cout << "Nframes is " << nframes << std::endl;
|
||||||
|
|
||||||
|
uint32_t nnx, nny;
|
||||||
|
|
||||||
|
singlePhotonDetector* filter =
|
||||||
|
new singlePhotonDetector(decoder, 3, nsigma, 1, NULL, nped, 200, -1, -1, NULL, NULL);
|
||||||
|
//auto filter = std::make_unique<singlePhotonDetector>(decoder.get(), 3, nsigma, 1, nullptr, nped, 200, -1, -1, nullptr, nullptr);
|
||||||
|
|
||||||
|
thr = 0.15 * thr;
|
||||||
|
//filter->newDataSet(); //This only initializes the dataset for the first thread (the other threads are created via cloning)
|
||||||
|
// int dsize = decoder->getDataSize();
|
||||||
|
|
||||||
|
if (thr > 0) {
|
||||||
|
std::cout << "threshold is " << thr << std::endl;
|
||||||
|
filter->setThreshold(thr);
|
||||||
|
cf = 0;
|
||||||
|
|
||||||
|
} else
|
||||||
|
cf = 1;
|
||||||
|
|
||||||
|
filter->setROI(xmin, xmax, ymin, ymax);
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
char* buff;
|
||||||
|
|
||||||
|
multiThreadedCountingDetector* mt =
|
||||||
|
new multiThreadedCountingDetector(filter, nthreads, fifosize);
|
||||||
|
//auto mt = std::make_unique<multiThreadedCountingDetector>(filter.get(), nthreads, fifosize);
|
||||||
|
mt->setClusterSize(csize, csize);
|
||||||
|
mt->newDataSet(); //Initialize new dataset for each thread
|
||||||
|
|
||||||
|
#ifndef ANALOG
|
||||||
|
mt->setDetectorMode(ePhotonCounting);
|
||||||
|
std::cout << "Counting!" << std::endl;
|
||||||
|
if (thr > 0) {
|
||||||
|
cf = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//{
|
||||||
|
#ifdef ANALOG
|
||||||
|
mt->setDetectorMode(eAnalog);
|
||||||
|
std::cout << "Analog!" << std::endl;
|
||||||
|
cf = 0;
|
||||||
|
// thr1=thr;
|
||||||
|
#endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
mt->StartThreads();
|
||||||
|
mt->popFree(buff);
|
||||||
|
|
||||||
|
int ifr = 0; //frame counter of while loop
|
||||||
|
int framenumber = 0; //framenumber as read from file (detector)
|
||||||
|
std::vector<hsize_t> h5offset(1,0); //frame counter internal to HDF5File::ReadImage (provided for sanity check/debugging)
|
||||||
|
|
||||||
|
if (pedfilename.length()>1) {
|
||||||
|
|
||||||
|
std::cout << "PEDESTAL " << std::endl;
|
||||||
|
|
||||||
|
if (pedfilename.find(".tif") == std::string::npos) { //not a tiff file
|
||||||
|
std::string const fname(pedfilename);
|
||||||
|
std::cout << fname << std::endl;
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << "aaa " << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
mt->setFrameMode(ePedestal);
|
||||||
|
|
||||||
|
//HDF5File pedefile;
|
||||||
|
auto pedefile = std::make_unique<HDF5File>();
|
||||||
|
pedefile->SetFrameIndexPath(frameindexpath);
|
||||||
|
pedefile->SetImageDataPath(datasetpath);
|
||||||
|
// //open file
|
||||||
|
if ( pedefile->OpenResources(fname.c_str(),validate_rank) ) {
|
||||||
|
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
framenumber = 0;
|
||||||
|
|
||||||
|
while ( decoder->readNextFrame(*pedefile, framenumber, h5offset, buff) ) {
|
||||||
|
|
||||||
|
if ((ifr + 1) % 100 == 0) {
|
||||||
|
std::cout
|
||||||
|
<< " ****"
|
||||||
|
<< decoder->getValue(buff, 20, 20); // << std::endl;
|
||||||
|
}
|
||||||
|
mt->pushData(buff);
|
||||||
|
mt->nextThread();
|
||||||
|
mt->popFree(buff);
|
||||||
|
++ifr;
|
||||||
|
if (ifr % 100 == 0) {
|
||||||
|
std::cout << " ****" << ifr << " " << framenumber << " " << h5offset[0]
|
||||||
|
<< std::endl;
|
||||||
|
} // else
|
||||||
|
|
||||||
|
if (ifr >= 1000)
|
||||||
|
break;
|
||||||
|
//framenumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pedefile->CloseResources();
|
||||||
|
while (mt->isBusy()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Writing pedestal to " << getRootString(pedfilename) << "_ped.tiff" << std::endl;
|
||||||
|
auto imgfname = createFileName( outdir, getRootString(pedfilename), "ped", "");
|
||||||
|
mt->writePedestal(imgfname.c_str());
|
||||||
|
std::cout << "Writing pedestal rms to " << getRootString(pedfilename) << "_rms.tiff" << std::endl;
|
||||||
|
imgfname = createFileName( outdir, getRootString(pedfilename), "rms", "");
|
||||||
|
mt->writePedestalRMS(imgfname.c_str());
|
||||||
|
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open pedestal file " << fname
|
||||||
|
<< " for reading " << std::endl;
|
||||||
|
|
||||||
|
} else { //is a tiff file
|
||||||
|
|
||||||
|
std::vector<double> ped(nx * ny);
|
||||||
|
float* pp = ReadFromTiff(pedfilename.c_str(), 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.data());
|
||||||
|
std::cout << "Pedestal set from tiff file " << pedfilename
|
||||||
|
<< std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Could not open pedestal tiff file " << pedfilename
|
||||||
|
<< " for reading " << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifr = 0;
|
||||||
|
int ioutfile = 0;
|
||||||
|
|
||||||
|
mt->setFrameMode(eFrame);
|
||||||
|
|
||||||
|
FILE* of = nullptr;
|
||||||
|
|
||||||
|
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
|
||||||
|
for (unsigned int ifile = 0; ifile != filenames.size(); ++ifile) {
|
||||||
|
std::cout << "DATA " << filenames[ifile] << " " << std::endl;
|
||||||
|
auto imgfname( createFileName( outdir, getRootString(filenames[ifile]), "", "" ) );
|
||||||
|
std::string const cfname( createFileName( outdir, getRootString(filenames[ifile]), "", "clust" ) );
|
||||||
|
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
//HDF5File fileh5;
|
||||||
|
auto fileh5 = std::make_unique<HDF5File>();
|
||||||
|
fileh5->SetFrameIndexPath(frameindexpath);
|
||||||
|
fileh5->SetImageDataPath(datasetpath);
|
||||||
|
// //open file
|
||||||
|
ioutfile = 0;
|
||||||
|
if ( fileh5->OpenResources(filenames[ifile].c_str(), validate_rank) ) {
|
||||||
|
if (thr <= 0 && cf != 0) { // cluster finder
|
||||||
|
if (of == nullptr) {
|
||||||
|
of = fopen(cfname.c_str(), "w");
|
||||||
|
if (of) {
|
||||||
|
if (mt) {
|
||||||
|
mt->setFilePointer(of);
|
||||||
|
std::cout << "file pointer set " << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: mt is null." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//mt->setFilePointer(of);
|
||||||
|
//std::cout << "file pointer set " << std::endl;
|
||||||
|
//std::cout << "Here! " << framenumber << " ";
|
||||||
|
} else {
|
||||||
|
std::cout << "Could not open " << cfname
|
||||||
|
<< " for writing " << std::endl;
|
||||||
|
mt->setFilePointer(nullptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// //while read frame
|
||||||
|
framenumber = 0;
|
||||||
|
h5offset[0] = 0;
|
||||||
|
ifr = 0;
|
||||||
|
//std::cout << "Here! " << framenumber << " ";
|
||||||
|
while ( decoder->readNextFrame(*fileh5, framenumber, h5offset, buff) ) {
|
||||||
|
//std::cout << "Here! " << framenumber << " ";
|
||||||
|
// //push
|
||||||
|
if ((ifr + 1) % 1000 == 0) {
|
||||||
|
std::cout << " ****"
|
||||||
|
<< decoder->getValue(buff, 20, 20); // << std::endl;
|
||||||
|
}
|
||||||
|
mt->pushData(buff);
|
||||||
|
|
||||||
|
// // //pop
|
||||||
|
mt->nextThread();
|
||||||
|
mt->popFree(buff); /* In the last execution of the loop,
|
||||||
|
* this leaves buff outside of the Fifo!
|
||||||
|
* Free explicitely at the end! */
|
||||||
|
|
||||||
|
++ifr;
|
||||||
|
if (ifr % 1000 == 0)
|
||||||
|
std::cout << " " << ifr << " " << framenumber << " " << h5offset[0]
|
||||||
|
<< std::endl;
|
||||||
|
if (nframes > 0) {
|
||||||
|
if (ifr % nframes == 0) {
|
||||||
|
imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "", ioutfile );
|
||||||
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
|
mt->clearImage();
|
||||||
|
++ioutfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//framenumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cout << "aa --" << std::endl;
|
||||||
|
fileh5->CloseResources();
|
||||||
|
|
||||||
|
//std::cout << "bb --" << std::endl;
|
||||||
|
while (mt->isBusy()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cout << "cc --" << std::endl;
|
||||||
|
if (nframes >= 0) {
|
||||||
|
if (nframes > 0)
|
||||||
|
imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "", ioutfile );
|
||||||
|
std::cout << "Writing tiff to " << imgfname << " " << thr1 << ".tiff"
|
||||||
|
<< std::endl;
|
||||||
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
|
mt->clearImage();
|
||||||
|
if (of) {
|
||||||
|
fclose(of);
|
||||||
|
of = nullptr;
|
||||||
|
mt->setFilePointer(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open " << filenames[ifile] << " for reading "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
if (nframes < 0) {
|
||||||
|
//std::string fprefix( getRootString(filenames[0]) ); //Possibly, non-ideal name choice for file
|
||||||
|
auto imgfname( createFileName( outdir, getRootString(filenames[0]), "sum", "" ) );
|
||||||
|
std::cout << "Writing tiff to " << imgfname << " " << thr1 << ".tiff" << std::endl;
|
||||||
|
mt->writeImage(imgfname.c_str(), thr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//std::cout << "Calling delete..." << std::endl;
|
||||||
|
/* Info: Previously, 'delete mt' caused crash
|
||||||
|
(double calls of StopThread() in both destructors of
|
||||||
|
multiThreadedAnalogDetector and threadedAnalogDetector)
|
||||||
|
Now fixed! */
|
||||||
|
delete mt; // triggers cleanup of all threads and singlePhotonDetector instances (delete filter is obsolete)
|
||||||
|
delete decoder;
|
||||||
|
free(buff); // Free explicitly as it gets popped out of the Fifo at termination of while(readNextFrame)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,468 @@
|
|||||||
|
// 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 RAWDATA
|
||||||
|
|
||||||
|
|
||||||
|
#include "jungfrauLGADStrixelsDataQuadH5.h"
|
||||||
|
|
||||||
|
#include "multiThreadedCountingDetector.h"
|
||||||
|
#include "singlePhotonDetector.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <csignal>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*Dataset paths according to different beamlines*/
|
||||||
|
std::string const data_datasetname_furka("/data/JF18T01V01/data");
|
||||||
|
std::string const index_datasetname_furka("/data/JF18T01V01/frame_index");
|
||||||
|
std::string const data_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/adc");
|
||||||
|
std::string const index_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/frameNumber");
|
||||||
|
|
||||||
|
std::string getRootString( std::string const& filepath ) {
|
||||||
|
size_t pos1;
|
||||||
|
if (filepath.find("/") == std::string::npos )
|
||||||
|
pos1 = 0;
|
||||||
|
else
|
||||||
|
pos1 = filepath.find_last_of("/")+1;
|
||||||
|
size_t pos2 = filepath.find_last_of(".");
|
||||||
|
//std::cout << "pos1 " << pos1 << " pos2 " << pos2 << " size " << filepath.length() << std::endl;
|
||||||
|
return filepath.substr( pos1, pos2-pos1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create file name string
|
||||||
|
* \param dir directory
|
||||||
|
* \param fprefix fileprefix (without extension)
|
||||||
|
* \param fsuffix filesuffix (for output files, e.g. "ped")
|
||||||
|
* \param fext file extension (e.g. "raw")
|
||||||
|
*/
|
||||||
|
std::string createFileName( std::string const& dir, std::string const& fprefix="run",
|
||||||
|
std::string const& fsuffix="", std::string const& fext="raw", int const outfilecounter=-1 ) {
|
||||||
|
std::string return_string;
|
||||||
|
if (outfilecounter >= 0)
|
||||||
|
return_string = fmt::format("{:s}/{:s}_{:s}_f{:05d}", dir, fprefix, fsuffix, outfilecounter);
|
||||||
|
else if (fsuffix.length()!=0)
|
||||||
|
return_string = fmt::format("{:s}/{:s}_{:s}", dir, fprefix, fsuffix);
|
||||||
|
else
|
||||||
|
return_string = fmt::format("{:s}/{:s}", dir, fprefix);
|
||||||
|
|
||||||
|
if (fext.length()!=0)
|
||||||
|
return_string += "." + fext;
|
||||||
|
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjusts number of threads to be a multiple of number of storage cells
|
||||||
|
* \param requestedThreads number of threads requested by the user
|
||||||
|
* \param nSC number of storage cells
|
||||||
|
*/
|
||||||
|
int adjustThreads(int requestedThreads, int nSC) {
|
||||||
|
if (nSC <= 0) {
|
||||||
|
std::cerr << "Error: Number of S values must be greater than zero!" << std::endl;
|
||||||
|
return requestedThreads; // Return the original value as a fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the remainder
|
||||||
|
int remainder = requestedThreads % nSC;
|
||||||
|
|
||||||
|
// If remainder is non-zero, round up by adding the difference
|
||||||
|
int adjustedThreads = (remainder == 0) ? requestedThreads : requestedThreads + (nSC - remainder);
|
||||||
|
|
||||||
|
// Ensure at least `nSC` threads are used
|
||||||
|
if (adjustedThreads < nSC) {
|
||||||
|
adjustedThreads = nSC;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Adjusted thread count (rounded up): " << adjustedThreads << " (nearest multiple of "
|
||||||
|
<< nSC << ")" << std::endl;
|
||||||
|
|
||||||
|
return adjustedThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal handler for segmentation faults
|
||||||
|
void signal_handler(int signum) {
|
||||||
|
std::cerr << "Caught signal " << signum << ": Segmentation fault (core dump)" << std::endl;
|
||||||
|
// Handle the error (e.g., clean up, abort, etc.)
|
||||||
|
exit(signum); // Exit program with the signal code
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
if (argc < 4) {
|
||||||
|
std::cout
|
||||||
|
<< "Usage is " << argv[0]
|
||||||
|
<< " filestxt outdir [pedfile (h5)] "
|
||||||
|
" optional: [int dataset path; 0 means Furka, 1 means XFEL; overwrites default given in HDF5File.h] "
|
||||||
|
" [bool validate h5 rank] "
|
||||||
|
" [xmin xmax ymin ymax] [nframes] "
|
||||||
|
" NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
|
||||||
|
<< std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the signal handler for segmentation faults
|
||||||
|
signal(SIGSEGV, signal_handler);
|
||||||
|
|
||||||
|
int const fifosize = 100; //1000;
|
||||||
|
int const nthreads = 10;
|
||||||
|
int const csize = 3; // 3
|
||||||
|
int const nsigma = 5;
|
||||||
|
int const nped = 10000;
|
||||||
|
|
||||||
|
//int cf = 0;
|
||||||
|
|
||||||
|
std::string const txtfilename(argv[1]);
|
||||||
|
std::string const outdir(argv[2]);
|
||||||
|
std::string const pedfilename(argv[3]);
|
||||||
|
|
||||||
|
std::string datasetpath{};
|
||||||
|
std::string frameindexpath{};
|
||||||
|
if (argc > 4) {
|
||||||
|
switch (atoi(argv[4])) {
|
||||||
|
case 0:
|
||||||
|
datasetpath = data_datasetname_furka;
|
||||||
|
frameindexpath = index_datasetname_furka;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
datasetpath = data_datasetname_xfelSCS;
|
||||||
|
frameindexpath = index_datasetname_xfelSCS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validate_rank=true;
|
||||||
|
if (argc > 5)
|
||||||
|
validate_rank = atoi(argv[5]);
|
||||||
|
|
||||||
|
//Get vector of filenames from input txt-file
|
||||||
|
std::vector<std::string> filenames{};
|
||||||
|
|
||||||
|
{ //Safety scope for ifstream
|
||||||
|
ifstream inputs( txtfilename, std::ios::in );
|
||||||
|
if (inputs.is_open()) {
|
||||||
|
std::cout << "Reading imput filenames from txt-file ..." << std::endl;
|
||||||
|
std::string line{};
|
||||||
|
while (!inputs.eof()) {
|
||||||
|
std::getline(inputs, line);
|
||||||
|
if(line.find(".h5") != std::string::npos) {
|
||||||
|
filenames.emplace_back(line);
|
||||||
|
std::cout << line << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputs.close();
|
||||||
|
std::cout << "---- Reached end of txt-file. ----" << std::endl;
|
||||||
|
} else
|
||||||
|
std::cout << "Could not open " << txtfilename << std::endl;
|
||||||
|
if (filenames.size()>0) {
|
||||||
|
std::cout << filenames.size() << " filenames found in " << txtfilename << std::endl;
|
||||||
|
std::cout << "The files will be processed in the same order as found in the txt-file." << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "No files found in txt-file!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "###############" << std::endl;
|
||||||
|
|
||||||
|
// Define decoder
|
||||||
|
std::cout << "Jungfrau strixel quad h5" << std::endl;
|
||||||
|
jungfrauLGADStrixelsDataQuadH5* decoder = new jungfrauLGADStrixelsDataQuadH5();
|
||||||
|
//auto decoder = std::make_unique<jungfrauLGADStrixelsDataQuadH5>();
|
||||||
|
int nx = 1024 / 3, ny = 512 * 3;
|
||||||
|
|
||||||
|
//Cluster finder ROI
|
||||||
|
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
|
||||||
|
if (argc > 9) {
|
||||||
|
xmin = atoi(argv[6]);
|
||||||
|
xmax = atoi(argv[7]);
|
||||||
|
ymin = atoi(argv[8]);
|
||||||
|
ymax = atoi(argv[9]);
|
||||||
|
}
|
||||||
|
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
decoder->getDetectorSize(nx, ny);
|
||||||
|
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
||||||
|
|
||||||
|
std::time_t end_time;
|
||||||
|
|
||||||
|
std::cout << "Output directory is " << outdir << std::endl;
|
||||||
|
if (pedfilename.length()!=0)
|
||||||
|
std::cout << "Pedestal file is " << pedfilename << std::endl;
|
||||||
|
|
||||||
|
//uint32_t nnx, nny;
|
||||||
|
|
||||||
|
singlePhotonDetector* filter =
|
||||||
|
new singlePhotonDetector(decoder, 3, nsigma, 1, NULL, nped, 200, -1, -1, NULL, NULL);
|
||||||
|
//auto filter = std::make_unique<singlePhotonDetector>(decoder.get(), 3, nsigma, 1, nullptr, nped, 200, -1, -1, nullptr, nullptr);
|
||||||
|
|
||||||
|
filter->setROI(xmin, xmax, ymin, ymax);
|
||||||
|
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
// Validate number of threads for number of storage cells (if applicable)
|
||||||
|
int nThreads = nthreads;
|
||||||
|
int nSC = 1;
|
||||||
|
// Determine the dimensions of the dataset from the first datafile
|
||||||
|
auto firstfileh5 = std::make_unique<HDF5File>();
|
||||||
|
firstfileh5->SetFrameIndexPath(frameindexpath);
|
||||||
|
firstfileh5->SetImageDataPath(datasetpath);
|
||||||
|
//std::cout << "Debug: Attempting to open file " << filenames[0].c_str() << std::endl;
|
||||||
|
if ( firstfileh5->OpenResources(filenames[0].c_str(), validate_rank) ) {
|
||||||
|
|
||||||
|
// Validate number of threads
|
||||||
|
if( firstfileh5->GetRank() == 4 ) {
|
||||||
|
auto h5dims = firstfileh5->GetDatasetDimensions();
|
||||||
|
nSC = h5dims[1];
|
||||||
|
nThreads = adjustThreads(nthreads,nSC);
|
||||||
|
}
|
||||||
|
|
||||||
|
firstfileh5->CloseResources();
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Could not open data file " << filenames[0]
|
||||||
|
<< " for validating rank " << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiThreadedCountingDetector* mt =
|
||||||
|
new multiThreadedCountingDetector(filter, nThreads, fifosize, nSC);
|
||||||
|
//auto mt = std::make_unique<multiThreadedCountingDetector>(filter.get(), nthreads, fifosize);
|
||||||
|
mt->setClusterSize(csize, csize);
|
||||||
|
mt->newDataSet(); //Initialize new dataset for each thread
|
||||||
|
mt->setDetectorMode(ePhotonCounting);
|
||||||
|
|
||||||
|
char* buff;
|
||||||
|
|
||||||
|
mt->StartThreads();
|
||||||
|
mt->popFree(buff); // Get the first pointer to write image to
|
||||||
|
|
||||||
|
size_t ifr = 0; //frame counter of while loop
|
||||||
|
int framenumber = 0; //framenumber as read from file (detector)
|
||||||
|
std::vector<hsize_t> h5offset; //hyperslab offset internal to HDF5File::ReadImage
|
||||||
|
hsize_t h5rank;
|
||||||
|
|
||||||
|
if (pedfilename.length()>1) {
|
||||||
|
|
||||||
|
std::string froot = getRootString(pedfilename);
|
||||||
|
|
||||||
|
std::cout << "PEDESTAL " << pedfilename << std::endl;
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << "aaa " << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
mt->setFrameMode(ePedestal);
|
||||||
|
|
||||||
|
//HDF5File pedefile;
|
||||||
|
auto pedefile = std::make_unique<HDF5File>();
|
||||||
|
pedefile->SetFrameIndexPath(frameindexpath);
|
||||||
|
pedefile->SetImageDataPath(datasetpath);
|
||||||
|
// //open file
|
||||||
|
if ( pedefile->OpenResources(pedfilename.c_str(),validate_rank) ) {
|
||||||
|
|
||||||
|
// Initialize offset vector to 0
|
||||||
|
h5rank = pedefile->GetRank();
|
||||||
|
h5offset.resize(h5rank-2, 0);
|
||||||
|
framenumber = 0;
|
||||||
|
|
||||||
|
while ( decoder->readNextFrame(*pedefile, framenumber, h5offset, buff) ) {
|
||||||
|
|
||||||
|
if ((ifr + 1) % 100 == 0) {
|
||||||
|
std::cout
|
||||||
|
<< " ****"
|
||||||
|
<< decoder->getValue(buff, 20, 20); // << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int storageCell = 0;
|
||||||
|
hsize_t n_storageCells = 1;
|
||||||
|
if (h5rank == 4) {
|
||||||
|
storageCell = h5offset[1];
|
||||||
|
n_storageCells = pedefile->GetDatasetDimensions()[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// push buff into fifoData for a thread corresponding to the active storage cell
|
||||||
|
mt->pushData(buff, storageCell);
|
||||||
|
// increment (round-robin) the internal thread counter for that storage cell
|
||||||
|
mt->nextThread(storageCell);
|
||||||
|
// get a free memory address from fifoFree of the active storage cell for the next read operation
|
||||||
|
mt->popFree(buff, storageCell);
|
||||||
|
/* NOTE: the buff that was popped free from the current thread, will be (likely) pushed into
|
||||||
|
* the fifoData of a different thread in the next iteration of the loop! */
|
||||||
|
|
||||||
|
++ifr;
|
||||||
|
if (ifr % 100 == 0) {
|
||||||
|
std::cout << " ****" << ifr << " " << framenumber << " " << h5offset[0];
|
||||||
|
if (n_storageCells>1)
|
||||||
|
std::cout << " sc " << storageCell;
|
||||||
|
std::cout << "\n";
|
||||||
|
} // else
|
||||||
|
|
||||||
|
if (ifr >= 1000*n_storageCells)
|
||||||
|
break;
|
||||||
|
//framenumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pedefile->CloseResources();
|
||||||
|
while (mt->isBusy()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Writing pedestal to " << getRootString(pedfilename) << "_ped_SCxx.tiff" << std::endl;
|
||||||
|
auto imgfname = createFileName( outdir, getRootString(pedfilename), "ped", "" );
|
||||||
|
mt->writePedestal(imgfname.c_str());
|
||||||
|
std::cout << "Writing pedestal rms to " << getRootString(pedfilename) << "_rms_SCxx.tiff" << std::endl;
|
||||||
|
imgfname = createFileName( outdir, getRootString(pedfilename), "rms", "");
|
||||||
|
mt->writePedestalRMS(imgfname.c_str());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Could not open pedestal file " << pedfilename
|
||||||
|
<< " for reading " << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifr = 0;
|
||||||
|
//int ioutfile = 0;
|
||||||
|
|
||||||
|
mt->setFrameMode(eFrame);
|
||||||
|
|
||||||
|
std::vector<FILE*> of(nSC, nullptr);
|
||||||
|
|
||||||
|
for (unsigned int ifile = 0; ifile != filenames.size(); ++ifile) {
|
||||||
|
std::cout << "DATA " << filenames[ifile] << " " << std::endl;
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
|
||||||
|
//HDF5File fileh5;
|
||||||
|
auto fileh5 = std::make_unique<HDF5File>();
|
||||||
|
fileh5->SetFrameIndexPath(frameindexpath);
|
||||||
|
fileh5->SetImageDataPath(datasetpath);
|
||||||
|
|
||||||
|
// Open HDF5 file
|
||||||
|
if ( fileh5->OpenResources(filenames[ifile].c_str(), validate_rank) ) {
|
||||||
|
|
||||||
|
std::vector<std::string> cfnames(nSC);
|
||||||
|
for ( int s = 0; s < nSC; ++s ) {
|
||||||
|
std::string fsuffix = "SC" + std::to_string(s);
|
||||||
|
cfnames[s] = createFileName( outdir, getRootString(filenames[ifile]), fsuffix, "clust" );
|
||||||
|
}
|
||||||
|
|
||||||
|
//Open output files and set file pointers according to storage cells
|
||||||
|
for ( size_t f = 0; f < of.size(); ++f ) {
|
||||||
|
if (!of[f]) {
|
||||||
|
of[f] = fopen(cfnames[f].c_str(), "w");
|
||||||
|
if (of[f])
|
||||||
|
{
|
||||||
|
if (mt) {
|
||||||
|
mt->setFilePointer(of[f],f); // assumes f == sc
|
||||||
|
std::cout << "File pointer set for storage cell " << f << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: mt is null." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: could not open " << cfnames[f]
|
||||||
|
<< " for writing " << std::endl;
|
||||||
|
mt->setFilePointer(nullptr,f);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read frames
|
||||||
|
framenumber = 0;
|
||||||
|
std::fill(h5offset.begin(), h5offset.end(), 0);
|
||||||
|
ifr = 0;
|
||||||
|
|
||||||
|
while ( decoder->readNextFrame(*fileh5, framenumber, h5offset, buff) ) {
|
||||||
|
|
||||||
|
if ((ifr + 1) % 1000 == 0) {
|
||||||
|
std::cout << " ****"
|
||||||
|
<< decoder->getValue(buff, 20, 20); // << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int storageCell = 0;
|
||||||
|
hsize_t n_storageCells = 1;
|
||||||
|
if (h5rank == 4) {
|
||||||
|
storageCell = h5offset[1];
|
||||||
|
n_storageCells = fileh5->GetDatasetDimensions()[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// push buff into fifoData for a thread corresponding to the active storage cell
|
||||||
|
mt->pushData(buff, storageCell);
|
||||||
|
// increment (round-robin) the internal thread counter for that storage cell
|
||||||
|
mt->nextThread(storageCell);
|
||||||
|
// get a free memory address from fifoFree of the active storage cell for the next read operation
|
||||||
|
mt->popFree(buff, storageCell); /* In the last execution of the loop,
|
||||||
|
* this leaves buff outside of the Fifo!
|
||||||
|
* Free explicitely at the end! */
|
||||||
|
|
||||||
|
++ifr;
|
||||||
|
if (ifr % 1000 == 0) {
|
||||||
|
std::cout << " " << ifr << " " << framenumber << " " << h5offset[0];
|
||||||
|
if (n_storageCells>1) std::cout << " sc " << storageCell;
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//framenumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cout << "aa --" << std::endl;
|
||||||
|
fileh5->CloseResources();
|
||||||
|
|
||||||
|
//std::cout << "bb --" << std::endl;
|
||||||
|
while (mt->isBusy()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cout << "cc --" << std::endl;
|
||||||
|
|
||||||
|
auto imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "" );
|
||||||
|
std::cout << "Writing tiff to " << imgfname << "_SCxx.tiff" << std::endl;
|
||||||
|
mt->writeImage(imgfname.c_str());
|
||||||
|
mt->clearImage();
|
||||||
|
|
||||||
|
// Close output files
|
||||||
|
for ( size_t f = 0; f < of.size(); ++f ) {
|
||||||
|
if (of[f]) {
|
||||||
|
fclose(of[f]);
|
||||||
|
mt->setFilePointer(nullptr,f);
|
||||||
|
of[f] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time(&end_time);
|
||||||
|
std::cout << std::ctime(&end_time) << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Could not open " << filenames[ifile] << " for reading "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//std::cout << "Calling delete..." << std::endl;
|
||||||
|
/* Info: Previously, 'delete mt' caused crash
|
||||||
|
(double calls of StopThread() in both destructors of
|
||||||
|
multiThreadedAnalogDetector and threadedAnalogDetector)
|
||||||
|
Now fixed! */
|
||||||
|
delete mt; // triggers cleanup of all threads and singlePhotonDetector instances (delete filter is obsolete)
|
||||||
|
delete decoder;
|
||||||
|
free(buff); // Free explicitly as it gets popped out of the Fifo at termination of while(readNextFrame)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -336,7 +336,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
string fname;
|
string fname;
|
||||||
// int length;
|
// int length;
|
||||||
int *detimage = NULL;
|
int *detimage = nullptr;
|
||||||
int nnx, nny, nnsx, nnsy;
|
int nnx, nny, nnsx, nnsy;
|
||||||
// uint32_t imageSize = 0, nPixelsX = 0, nPixelsY = 0,
|
// uint32_t imageSize = 0, nPixelsX = 0, nPixelsY = 0,
|
||||||
// uint32_t dynamicRange = 0;
|
// uint32_t dynamicRange = 0;
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
//#include <mutex>
|
#include <mutex>
|
||||||
|
#include <algorithm>
|
||||||
|
#include<unordered_map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -47,12 +49,20 @@ class threadedAnalogDetector {
|
|||||||
|
|
||||||
if (mm) {
|
if (mm) {
|
||||||
// memset(mm,0, det->getDataSize());
|
// memset(mm,0, det->getDataSize());
|
||||||
|
/*
|
||||||
|
if (i == 0) { // debug
|
||||||
|
first_mm = mm;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fifoFree->push(mm);
|
fifoFree->push(mm);
|
||||||
|
//std::cout << "Allocated memory at: " << static_cast<void*>(mm) << " (fifoslot " << i << ")" << std::endl;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < fs)
|
if (i < fs)
|
||||||
cout << "Could allocate only " << i << " frames";
|
std::cout << "Could allocate only " << i << " frames";
|
||||||
|
|
||||||
busy = 0;
|
busy = 0;
|
||||||
stop = 1;
|
stop = 1;
|
||||||
@ -102,24 +112,50 @@ class threadedAnalogDetector {
|
|||||||
};
|
};
|
||||||
|
|
||||||
virtual ~threadedAnalogDetector() {
|
virtual ~threadedAnalogDetector() {
|
||||||
|
|
||||||
|
// std::cout << "#### Debug: Destructing threadedAnalogDetector! ####" << std::endl;
|
||||||
|
|
||||||
StopThread();
|
StopThread();
|
||||||
delete fifoFree;
|
|
||||||
delete fifoData;
|
if (fifoFree) { delete fifoFree; fifoFree = nullptr; }
|
||||||
|
if (fifoData) { delete fifoData; fifoData = nullptr; }
|
||||||
|
if (det) {
|
||||||
|
delete det; // Call destructor for singlePhotonDetector
|
||||||
|
det = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the thread was successfully started, false if there was
|
/** Returns true if the thread was successfully started, false if there was
|
||||||
* an error starting the thread */
|
* an error starting the thread */
|
||||||
virtual bool StartThread() {
|
virtual bool StartThread() {
|
||||||
stop = 0;
|
stop = 0;
|
||||||
cout << "Detector number " << det->getId() << endl;
|
std::cout << "Detector number " << det->getId() << std::endl;
|
||||||
cout << "common mode is " << det->getCommonModeSubtraction() << endl;
|
std::cout << "common mode is " << det->getCommonModeSubtraction() << std::endl;
|
||||||
cout << "ghos summation is " << det->getGhostSummation() << endl;
|
std::cout << "ghos summation is " << det->getGhostSummation() << std::endl;
|
||||||
|
|
||||||
return (pthread_create(&_thread, NULL, processData, this) == 0);
|
return (pthread_create(&_thread, NULL, processData, this) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void StopThread() {
|
virtual void StopThread() {
|
||||||
stop = 1;
|
stop = 1;
|
||||||
(void)pthread_join(_thread, NULL);
|
//std::cout << "Attempting to stop thread..." << std::endl;
|
||||||
|
|
||||||
|
// Free all remaining allocated memory in fifoFree
|
||||||
|
char *mm = nullptr;
|
||||||
|
while (fifoFree->pop(mm, true)) { // Use no_block to avoid waiting
|
||||||
|
//std::cout << "fifo Free: Freeing memory at: " << static_cast<void*>(mm) << std::endl;
|
||||||
|
free(mm); // Free the allocated memory
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_thread) {
|
||||||
|
//(void)pthread_join(_thread, NULL);
|
||||||
|
//std::cout << "Calling pthread_join for thread: " << det->getId() << std::endl;
|
||||||
|
pthread_join(_thread, NULL);
|
||||||
|
_thread = 0;
|
||||||
|
std::cout << "Thread " << det->getId() << " stopped and joined." << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "No thread to join." << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool pushData(char *&ptr) { return fifoData->push(ptr); }
|
virtual bool pushData(char *&ptr) { return fifoData->push(ptr); }
|
||||||
@ -266,6 +302,8 @@ class threadedAnalogDetector {
|
|||||||
char *data;
|
char *data;
|
||||||
int *ff;
|
int *ff;
|
||||||
|
|
||||||
|
//char* first_mm = nullptr; // For debug; to track first allocated block
|
||||||
|
|
||||||
static void *processData(void *ptr) {
|
static void *processData(void *ptr) {
|
||||||
threadedAnalogDetector *This = ((threadedAnalogDetector *)ptr);
|
threadedAnalogDetector *This = ((threadedAnalogDetector *)ptr);
|
||||||
return This->processData();
|
return This->processData();
|
||||||
@ -278,55 +316,118 @@ class threadedAnalogDetector {
|
|||||||
usleep(100);
|
usleep(100);
|
||||||
if (fifoData->isEmpty()) {
|
if (fifoData->isEmpty()) {
|
||||||
busy = 0;
|
busy = 0;
|
||||||
} else
|
} else {
|
||||||
busy = 1;
|
busy = 1;
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (busy == 1) {
|
if (busy == 1) {
|
||||||
|
// Check stop flag before making a blocking call
|
||||||
|
//if (stop) {
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Blocking call
|
||||||
fifoData->pop(data); // blocking!
|
fifoData->pop(data); // blocking!
|
||||||
|
|
||||||
|
// Process data if not stopping
|
||||||
|
//if (!stop) {
|
||||||
det->processData(data);
|
det->processData(data);
|
||||||
fifoFree->push(data);
|
fifoFree->push(data);
|
||||||
|
|
||||||
|
//}
|
||||||
// busy=0;
|
// busy=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class multiThreadedAnalogDetector {
|
class multiThreadedAnalogDetector {
|
||||||
public:
|
public:
|
||||||
multiThreadedAnalogDetector(analogDetector<uint16_t> *d, int n,
|
multiThreadedAnalogDetector(analogDetector<uint16_t> *d, int num_threads,
|
||||||
int fs = 1000)
|
int fs = 1000, int num_sc = 1)
|
||||||
: stop(0), nThreads(n), ithread(0) {
|
: stop(0), nThreads(num_threads), nSC(num_sc) {
|
||||||
|
|
||||||
|
/*
|
||||||
dd[0] = d;
|
dd[0] = d;
|
||||||
if (nThreads == 1)
|
if (nThreads == 1)
|
||||||
dd[0]->setId(100);
|
dd[0]->setId(100);
|
||||||
else
|
else
|
||||||
dd[0]->setId(0);
|
dd[0]->setId(0);
|
||||||
for (int i = 1; i < nThreads; i++) {
|
*/
|
||||||
dd[i] = d->Clone();
|
|
||||||
dd[i]->setId(i);
|
// Create separate detectorObjects for each SC (each owns its mutex)
|
||||||
|
std::vector< analogDetector<uint16_t>* > sc_detectors(nSC, nullptr);
|
||||||
|
sc_detectors[0] = d; // First storage cell uses the given detector
|
||||||
|
// std::cout << "#### Debug: Copied analogDetector object for storage cell 0! ####" << std::endl;
|
||||||
|
|
||||||
|
for (int sc = 1; sc < nSC; ++sc) {
|
||||||
|
sc_detectors[sc] = d->Copy(); // Ensure unique mutex for each SC
|
||||||
|
// std::cout << "#### Debug: Copied analogDetector object for storage cell " << sc << "! ####" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Distribute threads among storage cells
|
||||||
|
int threads_per_sc = nThreads / nSC;
|
||||||
|
int remaining_threads = nThreads % nSC; // additional safety measure if nThreads is not divisible by nSC
|
||||||
|
|
||||||
|
sc_to_threads.clear();
|
||||||
|
for (int s = 0, thread_idx = 0; s < nSC; ++s) {
|
||||||
|
// Remaining threads (if any) are assigned to the first storage cells
|
||||||
|
int current_sc_threads = threads_per_sc + (s < remaining_threads ? 1 : 0);
|
||||||
|
|
||||||
|
for (int t = 0; t < current_sc_threads; ++t, ++thread_idx) {
|
||||||
|
|
||||||
|
if (t == 0) {
|
||||||
|
dd[thread_idx] = sc_detectors[s]; // First thread gets main SC detector
|
||||||
|
} else {
|
||||||
|
dd[thread_idx] = sc_detectors[s]->Clone(); // Other threads get clones
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Assigned thread " << thread_idx << " to storage cell " << s << std::endl;
|
||||||
|
|
||||||
|
dd[thread_idx]->setId(thread_idx);
|
||||||
|
|
||||||
|
// Store which threads belong to which SC
|
||||||
|
sc_to_threads[s].push_back(thread_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nSC == 1 && nThreads == 1) {
|
||||||
|
dd[0]->setId(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize threadedAnalogDetector objects
|
||||||
for (int i = 0; i < nThreads; i++) {
|
for (int i = 0; i < nThreads; i++) {
|
||||||
cout << "**" << i << endl;
|
cout << "**" << i << endl;
|
||||||
dets[i] = new threadedAnalogDetector(dd[i], fs);
|
dets[i] = new threadedAnalogDetector(dd[i], fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
image = NULL;
|
// Set all thread counters to zero for each storage cell
|
||||||
|
thread_counters_by_sc.resize(nSC,0);
|
||||||
|
|
||||||
|
image = nullptr;
|
||||||
ff = NULL;
|
ff = NULL;
|
||||||
ped = NULL;
|
ped = NULL;
|
||||||
cout << "Ithread is " << ithread << endl;
|
//std::cout << "Ithread is " << ithread << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~multiThreadedAnalogDetector() {
|
virtual ~multiThreadedAnalogDetector() {
|
||||||
StopThreads();
|
// std::cout << "#### Debug: Destructing multiThreadedAnalogDetector! ####" << std::endl;
|
||||||
for (int i = 0; i < nThreads; i++)
|
//StopThreads(); // Superfluous, leads to double delete
|
||||||
delete dets[i];
|
|
||||||
/* for (int i=1; i<nThreads; i++) */
|
/* Reverse loop for destruction.
|
||||||
/* delete dd[i]; */
|
* Deletes clones first, then root object, which owns the mutex
|
||||||
// delete [] image;
|
* (ensure shared mutex is deleted last).
|
||||||
|
* Optional solution: reference counting (safer but more complex) */
|
||||||
|
for (int i = nThreads - 1; i >= 0; --i) {
|
||||||
|
delete dets[i]; //StopThread() called by each ~threadedAnalogDetector()
|
||||||
|
dets[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int setFrameMode(int fm) {
|
virtual int setFrameMode(int fm) {
|
||||||
@ -359,36 +460,52 @@ class multiThreadedAnalogDetector {
|
|||||||
dets[i]->newDataSet();
|
dets[i]->newDataSet();
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual int *getImage(int &nnx, int &nny, int &ns, int &nsy) {
|
// Storage cell sensitive
|
||||||
int *img;
|
virtual int *getImage(int &nnx, int &nny, int &ns, int &nsy, int sc = 0) {
|
||||||
|
//int *img;
|
||||||
// int nnx, nny, ns;
|
// int nnx, nny, ns;
|
||||||
// int nnx, nny, ns;
|
// int nnx, nny, ns;
|
||||||
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
|
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
|
||||||
if (image) {
|
|
||||||
delete[] image;
|
if (sc_images[sc]) {
|
||||||
image = NULL;
|
delete[] sc_images[sc];
|
||||||
|
sc_images[sc] = nullptr;
|
||||||
}
|
}
|
||||||
image = new int[nn];
|
|
||||||
|
// Allocate memory for image and zero-initialize
|
||||||
|
sc_images[sc] = new int[nn]();
|
||||||
// int nn=dets[0]->getImageSize(nnx, nny, ns);
|
// int nn=dets[0]->getImageSize(nnx, nny, ns);
|
||||||
// for (i=0; i<nn; i++) image[i]=0;
|
// for (i=0; i<nn; i++) image[i]=0;
|
||||||
|
|
||||||
for (int ii = 0; ii < nThreads; ii++) {
|
// Get the threads assigned to this storage cell
|
||||||
// cout << ii << " " << nn << " " << nnx << " " << nny << " " << ns
|
auto const& assigned_threads = sc_to_threads[sc];
|
||||||
// << endl;
|
|
||||||
img = dets[ii]->getImage();
|
// Only iterate over threads assigned to this storage cell
|
||||||
|
for (int thread_id : assigned_threads) {
|
||||||
|
|
||||||
|
int* tmp_img = dets[thread_id]->getImage();
|
||||||
|
if (!tmp_img) continue; // Skip if null
|
||||||
|
|
||||||
|
/* std::cout << "## Thread " << ii
|
||||||
|
<< " # image size " << nn
|
||||||
|
<< " # nnx " << nnx
|
||||||
|
<< " # nny " << nny
|
||||||
|
<< " # ns " << ns; */
|
||||||
|
|
||||||
|
// Sum images across threads
|
||||||
for (int i = 0; i < nn; i++) {
|
for (int i = 0; i < nn; i++) {
|
||||||
if (ii == 0)
|
|
||||||
// if (img[i]>0)
|
/* std::cout << " # pixel " << i
|
||||||
image[i] = img[i];
|
<< " # value " << tmp_img[i]
|
||||||
// else
|
<< " ## " << std::endl; */
|
||||||
// image[i]=0;
|
|
||||||
else // if (img[i]>0)
|
|
||||||
image[i] += img[i];
|
sc_images[sc][i] += tmp_img[i];
|
||||||
// if (img[i]) cout << "det " << ii << " pix " << i << " val
|
// if (img[i]) cout << "det " << ii << " pix " << i << " val
|
||||||
// " << img[i] << " " << image[i] << endl;
|
// " << img[i] << " " << image[i] << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return image;
|
return sc_images[sc];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void clearImage() {
|
virtual void clearImage() {
|
||||||
@ -398,7 +515,7 @@ class multiThreadedAnalogDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void *writeImage(const char *imgname, double t = 1) {
|
virtual void *writeImage(char const* base_imgname, double t = 1) {
|
||||||
/* #ifdef SAVE_ALL */
|
/* #ifdef SAVE_ALL */
|
||||||
/* for (int ii=0; ii<nThreads; ii++) { */
|
/* for (int ii=0; ii<nThreads; ii++) { */
|
||||||
/* char tit[10000];cout << "m" <<endl; */
|
/* char tit[10000];cout << "m" <<endl; */
|
||||||
@ -407,11 +524,30 @@ class multiThreadedAnalogDetector {
|
|||||||
/* } */
|
/* } */
|
||||||
/* #endif */
|
/* #endif */
|
||||||
int nnx, nny, ns, nsy;
|
int nnx, nny, ns, nsy;
|
||||||
getImage(nnx, nny, ns, nsy);
|
|
||||||
// int nnx, nny, ns;
|
|
||||||
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
|
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
|
||||||
float *gm = new float[nn];
|
|
||||||
if (gm) {
|
// Allocate teporary float buffer and zero-initialize
|
||||||
|
std::vector<float> gm(nn);
|
||||||
|
|
||||||
|
// Lambda for pixel conversion
|
||||||
|
auto convert_pixel = [t](int pixel) -> float {
|
||||||
|
return (t > 0) ? static_cast<float>(std::max(0, pixel)) / static_cast<float>(t) : pixel;
|
||||||
|
}; // t ... threshold
|
||||||
|
|
||||||
|
// Loop over each storage cell
|
||||||
|
for (auto const& [sc, _] : sc_to_threads) { // structured bindings [sc, _] only available with -std=c++17
|
||||||
|
std::string imgname(base_imgname);
|
||||||
|
if (nSC > 1) imgname += "_SC" + std::to_string(sc);
|
||||||
|
imgname += ".tiff";
|
||||||
|
|
||||||
|
//Retrieve the image for this storage cell
|
||||||
|
int *image = getImage(nnx, nny, ns, nsy, sc);
|
||||||
|
if (!image) continue; // Skip if null
|
||||||
|
|
||||||
|
// Convert image data to float
|
||||||
|
std::transform(image, image + nn, gm.begin(), convert_pixel);
|
||||||
|
|
||||||
|
/* old loop implementing same logic as convert_pixel
|
||||||
for (int ix = 0; ix < nn; ix++) {
|
for (int ix = 0; ix < nn; ix++) {
|
||||||
if (t) {
|
if (t) {
|
||||||
if (image[ix] < 0)
|
if (image[ix] < 0)
|
||||||
@ -424,11 +560,18 @@ class multiThreadedAnalogDetector {
|
|||||||
// if (image[ix]>0 && ix/nnx<350) cout << ix/nnx << " " <<
|
// if (image[ix]>0 && ix/nnx<350) cout << ix/nnx << " " <<
|
||||||
// ix%nnx << " " << image[ix]<< " " << gm[ix] << endl;
|
// ix%nnx << " " << image[ix]<< " " << gm[ix] << endl;
|
||||||
}
|
}
|
||||||
// cout << "image " << nnx << " " << nny << endl;
|
*/
|
||||||
WriteToTiff(gm, imgname, nnx, nny);
|
|
||||||
delete[] gm;
|
WriteToTiff(gm.data(), imgname.c_str(), nnx, nny);
|
||||||
} else
|
|
||||||
cout << "Could not allocate float image " << endl;
|
// Clean up memory for this storage cell
|
||||||
|
if (sc_images[sc]) {
|
||||||
|
delete[] sc_images[sc];
|
||||||
|
sc_images[sc] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +582,7 @@ class multiThreadedAnalogDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void StopThreads() {
|
virtual void StopThreads() {
|
||||||
|
std::cout << "Stopping all threads ..." << std::endl;
|
||||||
for (int i = 0; i < nThreads; i++)
|
for (int i = 0; i < nThreads; i++)
|
||||||
dets[i]->StopThread();
|
dets[i]->StopThread();
|
||||||
}
|
}
|
||||||
@ -453,76 +597,133 @@ class multiThreadedAnalogDetector {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool pushData(char *&ptr) { return dets[ithread]->pushData(ptr); }
|
/*
|
||||||
|
virtual std::vector<int> getThreadsForSc(int sc) {
|
||||||
|
return sc_to_threads[sc];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
virtual bool pushData(char *&ptr, int sc=0) {
|
||||||
|
//Additional logic implemented to accommodate storage cells
|
||||||
|
|
||||||
virtual bool popFree(char *&ptr) {
|
std::unique_lock<std::mutex> lock(map_mutex);
|
||||||
// cout << ithread << endl;
|
|
||||||
return dets[ithread]->popFree(ptr);
|
// Get assigned threads for this storage cell
|
||||||
|
auto& assigned_threads = sc_to_threads[sc];
|
||||||
|
auto& counter = thread_counters_by_sc[sc];
|
||||||
|
|
||||||
|
// Distribute workload among threads using round-robin
|
||||||
|
int selected_thread = assigned_threads[counter % assigned_threads.size()];
|
||||||
|
|
||||||
|
return dets[selected_thread]->pushData(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int nextThread() {
|
virtual bool popFree(char *&ptr, int sc=0) {
|
||||||
ithread++;
|
//Additional logic implemented to accommodate storage cells
|
||||||
if (ithread == nThreads)
|
|
||||||
ithread = 0;
|
std::unique_lock<std::mutex> lock(map_mutex);
|
||||||
return ithread;
|
|
||||||
|
// Get assigned threads for this storage cell
|
||||||
|
auto& assigned_threads = sc_to_threads[sc];
|
||||||
|
auto& counter = thread_counters_by_sc[sc];
|
||||||
|
|
||||||
|
// Distribute workload among threads using round-robin
|
||||||
|
int selected_thread = assigned_threads[counter % assigned_threads.size()];
|
||||||
|
|
||||||
|
return dets[selected_thread]->popFree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual double *getPedestal() {
|
virtual int nextThread(int sc=0) {
|
||||||
|
//Additional logic implemented to accommodate storage cells
|
||||||
|
|
||||||
|
auto& counter = thread_counters_by_sc[sc];
|
||||||
|
//counter++;
|
||||||
|
if (++counter == nThreads/nSC)
|
||||||
|
counter = 0;
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage cell sensitive
|
||||||
|
virtual double *getPedestal(int sc = 0) {
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
if (ped)
|
|
||||||
delete[] ped;
|
if (sc_pedestals.count(sc) && sc_pedestals[sc]) {
|
||||||
ped = new double[nx * ny];
|
delete[] sc_pedestals[sc];
|
||||||
|
sc_pedestals[sc] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate memory and initialize all values to zero
|
||||||
|
sc_pedestals[sc] = new double[nx * ny](); // parentheses initialize elements to zero
|
||||||
|
//std::fill(sc_pedestals[sc], sc_pedestals[sc] + (nx * ny), 0.0); // explicit zero initialization
|
||||||
double *p0 = new double[nx * ny];
|
double *p0 = new double[nx * ny];
|
||||||
|
|
||||||
for (int i = 0; i < nThreads; i++) {
|
// Get the threads assigned to this storage cell
|
||||||
|
auto const& assigned_threads = sc_to_threads[sc];
|
||||||
|
int num_threads = assigned_threads.size();
|
||||||
|
|
||||||
|
// Only iterate over threads assigned to this storage cell
|
||||||
|
for ( int thread_id : assigned_threads ) {
|
||||||
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
|
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
|
||||||
// cout << i << endl;
|
// cout << i << endl;
|
||||||
p0 = dets[i]->getPedestal(p0);
|
//p0 = dets[thread_id]->getPedestal(p0);
|
||||||
if (p0) {
|
dets[thread_id]->getPedestal(p0);
|
||||||
if (i == 0) {
|
|
||||||
|
|
||||||
|
if (p0) { /*
|
||||||
|
if (i == 0) {
|
||||||
|
// If first thread, initialize ped with first thread's values
|
||||||
for (int ib = 0; ib < nx * ny; ib++) {
|
for (int ib = 0; ib < nx * ny; ib++) {
|
||||||
ped[ib] = p0[ib] / ((double)nThreads);
|
ped[ib] = p0[ib] / ((double)nThreads);
|
||||||
// cout << p0[ib] << " ";
|
// cout << p0[ib] << " ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int ib = 0; ib < nx * ny; ib++) {
|
*/
|
||||||
ped[ib] += p0[ib] / ((double)nThreads);
|
// For subsequent threads, accumulate pedestal values
|
||||||
// cout << p0[ib] << " ";
|
// if ( i == 0 ) becomes superfluous if we zero-initialize earlier
|
||||||
}
|
for (int ib = 0; ib < nx * ny; ib++) {
|
||||||
|
sc_pedestals[sc][ib] += p0[ib] / ((double)num_threads);
|
||||||
|
// cout << p0[ib] << " ";
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] p0;
|
delete[] p0;
|
||||||
return ped;
|
return sc_pedestals[sc];
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual double *getPedestalRMS() {
|
// Storage cell sensitive
|
||||||
|
virtual double *getPedestalRMS(int sc = 0) {
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
// if (ped) delete [] ped;
|
|
||||||
double *rms = new double[nx * ny];
|
if (sc_pedestals_rms.count(sc) && sc_pedestals_rms[sc]) {
|
||||||
|
delete[] sc_pedestals_rms[sc];
|
||||||
|
sc_pedestals_rms[sc] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate memory and initialize all values to zero
|
||||||
|
sc_pedestals_rms[sc] = new double[nx * ny](); // Zero-initialize
|
||||||
|
//std::fill(sc_pedestals_rms[sc], sc_pedestals_rms[sc] + (nx * ny), 0.0); // explicit zero initialization
|
||||||
|
//double *rms = sc_pedestals_rms[sc];
|
||||||
double *p0 = new double[nx * ny];
|
double *p0 = new double[nx * ny];
|
||||||
|
|
||||||
for (int i = 0; i < nThreads; i++) {
|
// Get the threads assigned to this storage cell
|
||||||
|
auto const& assigned_threads = sc_to_threads[sc];
|
||||||
|
int num_threads = assigned_threads.size();
|
||||||
|
|
||||||
|
// Only iterate over threads assigned to this storage cell
|
||||||
|
for (int thread_id : assigned_threads) {
|
||||||
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
|
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
|
||||||
// cout << i << endl;
|
// cout << i << endl;
|
||||||
p0 = dets[i]->getPedestalRMS(p0);
|
//p0 = dets[thread_id]->getPedestalRMS(p0);
|
||||||
if (p0) {
|
dets[thread_id]->getPedestalRMS(p0);
|
||||||
if (i == 0) {
|
|
||||||
|
|
||||||
for (int ib = 0; ib < nx * ny; ib++) {
|
if (p0) {
|
||||||
rms[ib] = p0[ib] * p0[ib] / ((double)nThreads);
|
for (int ib = 0; ib < nx * ny; ib++) {
|
||||||
|
sc_pedestals_rms[sc][ib] += (p0[ib] * p0[ib]) / ((double)num_threads);
|
||||||
// cout << p0[ib] << " ";
|
// cout << p0[ib] << " ";
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int ib = 0; ib < nx * ny; ib++) {
|
|
||||||
rms[ib] += p0[ib] * p0[ib] / ((double)nThreads);
|
|
||||||
// cout << p0[ib] << " ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
delete[] p0;
|
delete[] p0;
|
||||||
|
|
||||||
@ -533,64 +734,117 @@ class multiThreadedAnalogDetector {
|
|||||||
/* rms[ib]=0; */
|
/* rms[ib]=0; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
return rms;
|
return sc_pedestals_rms[sc];
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual double *setPedestal(double *h = NULL) {
|
/**
|
||||||
|
* Sets pedestal for given storage cell
|
||||||
|
* \param h pedestal
|
||||||
|
* \param sc storage cell
|
||||||
|
* \returns NULL
|
||||||
|
*/
|
||||||
|
virtual double *setPedestal(double *h = NULL, int sc = 0) {
|
||||||
// int nb=0;
|
// int nb=0;
|
||||||
|
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
if (h == NULL)
|
if (h == NULL)
|
||||||
h = ped;
|
h = ped;
|
||||||
for (int i = 0; i < nThreads; i++) {
|
for (auto i : sc_to_threads[sc]) {
|
||||||
dets[i]->setPedestal(h);
|
dets[i]->setPedestal(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void *writePedestal(const char *imgname) {
|
// Storage cell sensitive
|
||||||
|
virtual void *writePedestal(char const* base_imgname) {
|
||||||
|
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
|
|
||||||
getPedestal();
|
//float *gm = new float[nx * ny];
|
||||||
float *gm = new float[nx * ny];
|
|
||||||
if (gm) {
|
// Loop over each storage cell
|
||||||
|
for ( auto const& entry : sc_to_threads ) {
|
||||||
|
int sc = entry.first;
|
||||||
|
std::string imgname = std::string(base_imgname);
|
||||||
|
if (nSC>1)
|
||||||
|
imgname += "_SC" + std::to_string(sc);
|
||||||
|
imgname += ".tiff";
|
||||||
|
|
||||||
|
getPedestal(sc); // Compute pedestal for this storage cell
|
||||||
|
std::vector<float> gm(nx * ny);
|
||||||
|
|
||||||
|
// Copy pedestal data into the float array
|
||||||
|
/*
|
||||||
for (int ix = 0; ix < nx * ny; ix++) {
|
for (int ix = 0; ix < nx * ny; ix++) {
|
||||||
gm[ix] = ped[ix];
|
gm[ix] = sc_pedestals[sc][ix];
|
||||||
}
|
}
|
||||||
WriteToTiff(gm, imgname, nx, ny);
|
*/
|
||||||
delete[] gm;
|
std::copy(sc_pedestals[sc], sc_pedestals[sc] + (nx * ny), gm.data());
|
||||||
} else
|
WriteToTiff(gm.data(), imgname.c_str(), nx, ny);
|
||||||
cout << "Could not allocate float image " << endl;
|
|
||||||
|
// Clean up memory
|
||||||
|
if(sc_pedestals[sc]) {
|
||||||
|
delete[] sc_pedestals[sc];
|
||||||
|
sc_pedestals[sc] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void *writePedestalRMS(const char *imgname) {
|
// Storage cell sensitive
|
||||||
|
virtual void *writePedestalRMS(char const* base_imgname) {
|
||||||
|
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
|
|
||||||
double *rms = getPedestalRMS();
|
//float *gm = new float[nx * ny];
|
||||||
float *gm = new float[nx * ny];
|
|
||||||
if (gm) {
|
// Loop over each stoarge cell
|
||||||
|
for ( auto const& entry : sc_to_threads ) {
|
||||||
|
int sc = entry.first;
|
||||||
|
std::string imgname = std::string(base_imgname);
|
||||||
|
if (nSC>1)
|
||||||
|
imgname += "_SC" + std::to_string(sc);
|
||||||
|
imgname += ".tiff";
|
||||||
|
|
||||||
|
double *rms = getPedestalRMS(sc); // Compute pedestal RMS for this storage cell
|
||||||
|
std::vector<float> gm(nx * ny);
|
||||||
|
|
||||||
|
// Copy rms data into the float array
|
||||||
|
/*
|
||||||
for (int ix = 0; ix < nx * ny; ix++) {
|
for (int ix = 0; ix < nx * ny; ix++) {
|
||||||
gm[ix] = rms[ix];
|
gm[ix] = rms[ix];
|
||||||
}
|
}
|
||||||
WriteToTiff(gm, imgname, nx, ny);
|
*/
|
||||||
delete[] gm;
|
std::copy(rms, rms + (nx * ny), gm.data());
|
||||||
delete[] rms;
|
WriteToTiff(gm.data(), imgname.c_str(), nx, ny);
|
||||||
} else
|
|
||||||
cout << "Could not allocate float image " << endl;
|
// Clean up memory
|
||||||
|
//delete[] rms; //This would cause double-free since the pointer is already handled by sc_pedestals_rms[sc]
|
||||||
|
if(sc_pedestals_rms[sc]) {
|
||||||
|
delete[] sc_pedestals_rms[sc];
|
||||||
|
sc_pedestals_rms[sc] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads pedestal and sets it for given storage cell
|
||||||
|
* \param imgname name of pedestal file
|
||||||
|
* \param nb obsolete
|
||||||
|
* \param emin obsolete
|
||||||
|
* \param emax obsolete
|
||||||
|
* \param sc storage cell
|
||||||
|
* \returns setPedestal(NULL, sc)
|
||||||
|
* */
|
||||||
virtual void *readPedestal(const char *imgname, int nb = -1,
|
virtual void *readPedestal(const char *imgname, int nb = -1,
|
||||||
double emin = 1, double emax = 0) {
|
double emin = 1, double emax = 0, int sc = 0) {
|
||||||
|
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
dets[0]->getDetectorSize(nx, ny);
|
dets[0]->getDetectorSize(nx, ny);
|
||||||
@ -610,36 +864,68 @@ class multiThreadedAnalogDetector {
|
|||||||
}
|
}
|
||||||
delete[] gm;
|
delete[] gm;
|
||||||
|
|
||||||
return setPedestal();
|
return setPedestal(NULL, sc);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** sets file pointer where to write the clusters to
|
/** Sets file pointer where to write the clusters to
|
||||||
\param f file pointer
|
\param f file pointer
|
||||||
\returns current file pointer
|
\param sc storage cell index
|
||||||
|
\returns current file pointer, or nullptr if invalid
|
||||||
*/
|
*/
|
||||||
virtual FILE *setFilePointer(FILE *f) {
|
virtual FILE *setFilePointer(FILE *f, int sc = 0) {
|
||||||
for (int i = 0; i < nThreads; i++) {
|
// Check if the storage cell exists
|
||||||
dets[i]->setFilePointer(f);
|
if (sc_to_threads.find(sc) == sc_to_threads.end() || sc_to_threads[sc].empty()) {
|
||||||
// dets[i]->setMutex(&fmutex);
|
std::cerr << "Error: Invalid storage cell index " << sc << std::endl;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return dets[0]->getFilePointer();
|
|
||||||
|
// Assign file pointer to all threads belonging to this storage cell
|
||||||
|
for (auto i : sc_to_threads[sc]) {
|
||||||
|
if(dets[i]) {
|
||||||
|
dets[i]->setFilePointer(f);
|
||||||
|
// dets[i]->setMutex(&fmutex);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Warning: dets[" << i << "] is null, skipping file pointer set." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return file pointer of the first thread in this storage cell
|
||||||
|
return dets[sc_to_threads[sc][0]] ? dets[sc_to_threads[sc][0]]->getFilePointer() : nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** gets file pointer where to write the clusters to
|
/** Gets file pointer where to write the clusters to
|
||||||
\returns current file pointer
|
\param sc storage cell index
|
||||||
|
\returns current file pointer, or nullptr if invalid
|
||||||
*/
|
*/
|
||||||
virtual FILE *getFilePointer() { return dets[0]->getFilePointer(); };
|
virtual FILE *getFilePointer(int sc = 0) {
|
||||||
|
// Ensure storage cell index is valid
|
||||||
|
if (sc_to_threads.find(sc) == sc_to_threads.end() || sc_to_threads[sc].empty()) {
|
||||||
|
std::cerr << "Error: Invalid storage cell index " << sc << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return file pointer of the first thread in this storage cell
|
||||||
|
return dets[sc_to_threads[sc][0]] ? dets[sc_to_threads[sc][0]]->getFilePointer() : nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool stop;
|
bool stop;
|
||||||
const int nThreads;
|
const int nThreads;
|
||||||
threadedAnalogDetector *dets[MAXTHREADS];
|
threadedAnalogDetector *dets[MAXTHREADS];
|
||||||
analogDetector<uint16_t> *dd[MAXTHREADS];
|
analogDetector<uint16_t> *dd[MAXTHREADS];
|
||||||
int ithread;
|
//int ithread{0}; // Thread index
|
||||||
int *image;
|
std::vector<int> thread_counters_by_sc{}; // Counters for threads for each storage cell
|
||||||
int *ff;
|
int* image;
|
||||||
double *ped;
|
int* ff;
|
||||||
pthread_mutex_t fmutex;
|
double* ped;
|
||||||
|
//pthread_mutex_t fmutex; //unused
|
||||||
|
std::unordered_map<int,std::vector<int>> sc_to_threads; // Maps storage cell -> vector of assigned thread ids
|
||||||
|
std::mutex map_mutex; // Ensure thread-safe access to the map
|
||||||
|
int nSC{1}; // Number of storage cells
|
||||||
|
|
||||||
|
std::unordered_map<int,int*> sc_images; // Store images per storage cell
|
||||||
|
std::unordered_map<int,double*> sc_pedestals; // Store pedestal arrays per storage cell
|
||||||
|
std::unordered_map<int,double*> sc_pedestals_rms; // Store pedestal RMS arrays per storage cell
|
||||||
|
// at the moment, these maps could be avoided, but this implementation is more robust in allowing future changes
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,8 +19,8 @@ using namespace std;
|
|||||||
|
|
||||||
class multiThreadedCountingDetector : public multiThreadedAnalogDetector {
|
class multiThreadedCountingDetector : public multiThreadedAnalogDetector {
|
||||||
public:
|
public:
|
||||||
multiThreadedCountingDetector(singlePhotonDetector *d, int n, int fs = 1000)
|
multiThreadedCountingDetector(singlePhotonDetector *d, int num_threads, int fs = 1000, int num_sc = 1)
|
||||||
: multiThreadedAnalogDetector(d, n, fs){};
|
: multiThreadedAnalogDetector(d, num_threads, fs, num_sc){};
|
||||||
// virtual
|
// virtual
|
||||||
// ~multiThreadedCountingDetector{multiThreadedAnalogDetector::~multiThreadedAnalogDetector();};
|
// ~multiThreadedCountingDetector{multiThreadedAnalogDetector::~multiThreadedAnalogDetector();};
|
||||||
virtual double setNSigma(double n) {
|
virtual double setNSigma(double n) {
|
||||||
|
@ -70,7 +70,6 @@ class multiThreadedInterpolatingDetector
|
|||||||
if (getInterpolation() == NULL)
|
if (getInterpolation() == NULL)
|
||||||
return multiThreadedAnalogDetector::getImage(nnx, nny, nsx, nsy);
|
return multiThreadedAnalogDetector::getImage(nnx, nny, nsx, nsy);
|
||||||
// if one interpolates, the whole image is stored in detector 0;
|
// if one interpolates, the whole image is stored in detector 0;
|
||||||
int *img;
|
|
||||||
// int nnx, nny, ns;
|
// int nnx, nny, ns;
|
||||||
// int nnx, nny, ns;
|
// int nnx, nny, ns;
|
||||||
int nn = dets[0]->getImageSize(nnx, nny, nsx, nsy);
|
int nn = dets[0]->getImageSize(nnx, nny, nsx, nsy);
|
||||||
@ -79,9 +78,9 @@ class multiThreadedInterpolatingDetector
|
|||||||
image = NULL;
|
image = NULL;
|
||||||
}
|
}
|
||||||
image = new int[nn];
|
image = new int[nn];
|
||||||
img = dets[0]->getImage();
|
int* tmp_img = dets[0]->getImage();
|
||||||
for (int i = 0; i < nn; i++) {
|
for (int i = 0; i < nn; i++) {
|
||||||
image[i] = img[i];
|
image[i] = tmp_img[i];
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,6 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
singlePhotonDetector(slsDetectorData<uint16_t> *d, int csize = 3,
|
singlePhotonDetector(slsDetectorData<uint16_t> *d, int csize = 3,
|
||||||
double nsigma = 5, int sign = 1,
|
double nsigma = 5, int sign = 1,
|
||||||
commonModeSubtraction *cm = NULL, int nped = 1000,
|
commonModeSubtraction *cm = NULL, int nped = 1000,
|
||||||
@ -60,10 +59,11 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
: analogDetector<uint16_t>(d, sign, cm, nped, nnx, nny, gm, gs),
|
: analogDetector<uint16_t>(d, sign, cm, nped, nnx, nny, gm, gs),
|
||||||
nDark(nd), eventMask(NULL), nSigma(nsigma), eMin(-1), eMax(-1),
|
nDark(nd), eventMask(NULL), nSigma(nsigma), eMin(-1), eMax(-1),
|
||||||
clusterSize(csize), clusterSizeY(csize), c2(1), c3(1), clusters(NULL),
|
clusterSize(csize), clusterSizeY(csize), c2(1), c3(1), clusters(NULL),
|
||||||
quad(UNDEFINED_QUADRANT), tot(0), quadTot(0) {
|
quad(UNDEFINED_QUADRANT), tot(0), quadTot(0), ownsMutex(true) { // The original object owns the mutex {
|
||||||
|
|
||||||
fm = new pthread_mutex_t;
|
//fm = new pthread_mutex_t;
|
||||||
pthread_mutex_init(fm, NULL);
|
//pthread_mutex_init(fm, NULL);
|
||||||
|
fm = new std::mutex();
|
||||||
|
|
||||||
eventMask = new eventType *[ny];
|
eventMask = new eventType *[ny];
|
||||||
// val=new double*[ny];
|
// val=new double*[ny];
|
||||||
@ -86,24 +86,31 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
nphFrame = 0;
|
nphFrame = 0;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
destructor. Deletes the cluster structure, the pdestalSubtraction and the
|
Destructor. Deletes the cluster structure, event mask, and destroys the mutex.
|
||||||
image array
|
|
||||||
*/
|
*/
|
||||||
virtual ~singlePhotonDetector() {
|
virtual ~singlePhotonDetector() {
|
||||||
delete[] clusters;
|
// std::cout << "#### Debug: Destructing singlePhotonDetector! ####" << std::endl;
|
||||||
for (int i = 0; i < ny; i++)
|
if (clusters) { delete[] clusters; clusters = nullptr; }
|
||||||
delete[] eventMask[i];
|
for (int i = 0; i < ny; i++) {
|
||||||
delete[] eventMask;
|
if (eventMask[i]) { delete[] eventMask[i]; eventMask[i] = nullptr; }
|
||||||
|
}
|
||||||
|
if (eventMask) { delete[] eventMask; eventMask = nullptr; }
|
||||||
|
if (ownsMutex) {
|
||||||
|
if (fm) {
|
||||||
|
//pthread_mutex_destroy(fm); // Destroy the mutex (not necessary with std::mutex)
|
||||||
|
delete fm; // Free the memory allocated for the mutex
|
||||||
|
fm = nullptr; // Set the pointer to nullptr to avoid dangling pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
copy constructor
|
pointer-based copy constructor (cloner)
|
||||||
\param orig detector to be copied
|
\param orig detector to be copied
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
singlePhotonDetector(singlePhotonDetector *orig)
|
singlePhotonDetector(singlePhotonDetector *orig)
|
||||||
: analogDetector<uint16_t>(orig) {
|
: analogDetector<uint16_t>(orig), fm(orig->fm), ownsMutex(false) {
|
||||||
|
|
||||||
nDark = orig->nDark;
|
nDark = orig->nDark;
|
||||||
myFile = orig->myFile;
|
myFile = orig->myFile;
|
||||||
@ -126,11 +133,12 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
c3 = sqrt(clusterSizeY * clusterSize);
|
c3 = sqrt(clusterSizeY * clusterSize);
|
||||||
|
|
||||||
clusters = new single_photon_hit[nx * ny];
|
clusters = new single_photon_hit[nx * ny];
|
||||||
|
//std::copy(orig->clusters, orig->clusters + (nx * ny), clusters); //possibly superfluous
|
||||||
|
|
||||||
// cluster=clusters;
|
// cluster=clusters;
|
||||||
|
|
||||||
setClusterSize(clusterSize);
|
setClusterSize(clusterSize);
|
||||||
fm = orig->fm;
|
//fm = orig->fm;
|
||||||
|
|
||||||
quad = UNDEFINED_QUADRANT;
|
quad = UNDEFINED_QUADRANT;
|
||||||
tot = 0;
|
tot = 0;
|
||||||
@ -143,13 +151,67 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
duplicates the detector structure
|
* copy constructor (deep copy), creates a new mutex
|
||||||
\returns new single photon detector with same parameters
|
* stricly, TODO: Implement Rule of Five!
|
||||||
|
* (copy op=, move ctor, and move op= would need to be defined)
|
||||||
*/
|
*/
|
||||||
virtual singlePhotonDetector *Clone() {
|
singlePhotonDetector(singlePhotonDetector const& other)
|
||||||
|
: analogDetector<uint16_t>(other), ownsMutex(true) {
|
||||||
|
|
||||||
|
//fm = new pthread_mutex_t; // create a new mutex
|
||||||
|
//pthread_mutex_init(fm, NULL);
|
||||||
|
fm = new std::mutex(); // New unique mutex per copy
|
||||||
|
|
||||||
|
nDark = other.nDark;
|
||||||
|
myFile = other.myFile;
|
||||||
|
|
||||||
|
eventMask = new eventType *[ny];
|
||||||
|
for (int i = 0; i < ny; i++) {
|
||||||
|
eventMask[i] = new eventType[nx];
|
||||||
|
//std::copy(other.eventMask[i], other.eventMask[i] + nx, eventMask[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
eMin = other.eMin;
|
||||||
|
eMax = other.eMax;
|
||||||
|
|
||||||
|
nSigma = other.nSigma;
|
||||||
|
clusterSize = other.clusterSize;
|
||||||
|
clusterSizeY = other.clusterSizeY;
|
||||||
|
|
||||||
|
c2 = sqrt((clusterSizeY + 1) / 2 * (clusterSize + 1) / 2);
|
||||||
|
c3 = sqrt(clusterSizeY * clusterSize);
|
||||||
|
|
||||||
|
clusters = new single_photon_hit[nx * ny];
|
||||||
|
//std::copy(other.clusters, other.clusters + (nx * ny), clusters);
|
||||||
|
|
||||||
|
setClusterSize(clusterSize);
|
||||||
|
|
||||||
|
quad = other.quad;
|
||||||
|
tot = other.tot;
|
||||||
|
quadTot = other.quadTot;
|
||||||
|
gmap = other.gmap;
|
||||||
|
nphTot = other.nphTot;
|
||||||
|
nphFrame = other.nphFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clones the detector structure
|
||||||
|
\returns new single photon detector with same parameters
|
||||||
|
that shares the mutex of the original
|
||||||
|
*/
|
||||||
|
virtual singlePhotonDetector* Clone() {
|
||||||
return new singlePhotonDetector(this);
|
return new singlePhotonDetector(this);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
Copies the detector structure
|
||||||
|
\returns new single photon detector with same parameters
|
||||||
|
that owns a new mutex
|
||||||
|
*/
|
||||||
|
virtual singlePhotonDetector* Copy() {
|
||||||
|
return new singlePhotonDetector(*this); // Calls the copy constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** sets/gets number of rms threshold to detect photons
|
/** sets/gets number of rms threshold to detect photons
|
||||||
\param n number of sigma to be set (0 or negative gets)
|
\param n number of sigma to be set (0 or negative gets)
|
||||||
\returns actual number of sigma parameter
|
\returns actual number of sigma parameter
|
||||||
@ -381,7 +443,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
|
|
||||||
// int ir, ic;
|
// int ir, ic;
|
||||||
eventType ee;
|
eventType ee;
|
||||||
double max = 0, tl = 0, tr = 0, bl = 0, br = 0, *v;
|
double max = 0, tl = 0, tr = 0, bl = 0, br = 0, v = 0;//, *v;
|
||||||
int cm = 0;
|
int cm = 0;
|
||||||
int good = 1;
|
int good = 1;
|
||||||
int ir, ic;
|
int ir, ic;
|
||||||
@ -403,7 +465,8 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
cm = 1;
|
cm = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
double *val = new double[ny * nx];
|
//double *val = new double[ny * nx];
|
||||||
|
std::vector<double> val( ny * nx );
|
||||||
|
|
||||||
for (int iy = ymin; iy < ymax; ++iy) {
|
for (int iy = ymin; iy < ymax; ++iy) {
|
||||||
for (int ix = xmin; ix < xmax; ++ix) {
|
for (int ix = xmin; ix < xmax; ++ix) {
|
||||||
@ -435,26 +498,34 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
(ix + ic) >= 0 && (ix + ic) < nx) {
|
(ix + ic) >= 0 && (ix + ic) < nx) {
|
||||||
|
|
||||||
|
|
||||||
if ((iy + ir) > iy && (ix + ic) > ix ) {
|
if ((iy + ir) > iy && (ix + ic) > ix ) {
|
||||||
|
|
||||||
val[(iy + ir) * nx + ix + ic] =
|
val[(iy + ir) * nx + ix + ic] =
|
||||||
subtractPedestal(data, ix + ic, iy + ir, cm);
|
subtractPedestal(data, ix + ic, iy + ir, cm);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
v = &(val[(iy + ir) * nx + ix + ic]);
|
//v = &(val[(iy + ir) * nx + ix + ic]);
|
||||||
tot += *v;
|
v = val[(iy + ir) * nx + ix + ic];
|
||||||
if (ir <= 0 && ic <= 0)
|
//tot += *v;
|
||||||
bl += *v;
|
tot += v;
|
||||||
if (ir <= 0 && ic >= 0)
|
if (ir <= 0 && ic <= 0)
|
||||||
br += *v;
|
bl += v;
|
||||||
if (ir >= 0 && ic <= 0)
|
//bl += *v;
|
||||||
tl += *v;
|
if (ir <= 0 && ic >= 0)
|
||||||
if (ir >= 0 && ic >= 0)
|
br += v;
|
||||||
tr += *v;
|
//br += *v;
|
||||||
if (*v > max) //{
|
if (ir >= 0 && ic <= 0)
|
||||||
max = *v;
|
tl += v;
|
||||||
//}
|
//tl += *v;
|
||||||
|
if (ir >= 0 && ic >= 0)
|
||||||
|
tr += v;
|
||||||
|
//tr += *v;
|
||||||
|
//if (*v > max) //{
|
||||||
|
//max = *v;
|
||||||
|
if (v > max)
|
||||||
|
max = v;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -524,19 +595,19 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
ic < (clusterSize / 2) + 1; ic++) {
|
ic < (clusterSize / 2) + 1; ic++) {
|
||||||
if ((iy + ir) >= 0 && (iy + ir) < ny &&
|
if ((iy + ir) >= 0 && (iy + ir) < ny &&
|
||||||
(ix + ic) >= 0 && (ix + ic) < nx) {
|
(ix + ic) >= 0 && (ix + ic) < nx) {
|
||||||
(clusters + nph)
|
(clusters + nph)
|
||||||
->set_data(val[(iy + ir) * nx + ix + ic],
|
->set_data(val[(iy + ir) * nx + ix + ic],
|
||||||
ic, ir);
|
ic, ir);
|
||||||
if (val[(iy + ir) * nx + ix + ic]>max)
|
if (val[(iy + ir) * nx + ix + ic]>max)
|
||||||
good=0;
|
good=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (good==0) {
|
if (good==0) {
|
||||||
(clusters + nph)->print();
|
(clusters + nph)->print();
|
||||||
cout << max << " " << val[iy * nx + ix] << endl;
|
cout << max << " " << val[iy * nx + ix] << endl;
|
||||||
}
|
}
|
||||||
//else (clusters + nph)->print();
|
//else (clusters + nph)->print();
|
||||||
if (eMin > 0 && tot < eMin)
|
if (eMin > 0 && tot < eMin)
|
||||||
good = 0;
|
good = 0;
|
||||||
if (eMax > 0 && tot > eMax)
|
if (eMax > 0 && tot > eMax)
|
||||||
@ -561,7 +632,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
// cout <<id << " **********************************"<< iframe << " " <<
|
// cout <<id << " **********************************"<< iframe << " " <<
|
||||||
// det->getFrameNumber(data) << " " << nphFrame << endl;
|
// det->getFrameNumber(data) << " " << nphFrame << endl;
|
||||||
writeClusters(det->getFrameNumber(data));
|
writeClusters(det->getFrameNumber(data));
|
||||||
delete[] val;
|
//delete[] val;
|
||||||
return image;
|
return image;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -667,13 +738,14 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
void writeClusters(int fn) {
|
void writeClusters(int fn) {
|
||||||
if (myFile) {
|
if (myFile) {
|
||||||
// cout << "++" << endl;
|
// cout << "++" << endl;
|
||||||
pthread_mutex_lock(fm);
|
//pthread_mutex_lock(fm); // This is dangerous! What if writeClusters() throws? Then the mutex is never unlocked!
|
||||||
|
std::lock_guard<std::mutex> lock(*fm); // safer, RAII-based locking
|
||||||
// cout <<"**********************************"<< fn << " " <<
|
// cout <<"**********************************"<< fn << " " <<
|
||||||
// nphFrame << endl;
|
// nphFrame << endl;
|
||||||
writeClusters(myFile, clusters, nphFrame, fn);
|
writeClusters(myFile, clusters, nphFrame, fn);
|
||||||
// for (int i=0; i<nphFrame; i++)
|
// for (int i=0; i<nphFrame; i++)
|
||||||
// (clusters+i)->write(myFile);
|
// (clusters+i)->write(myFile);
|
||||||
pthread_mutex_unlock(fm);
|
//pthread_mutex_unlock(fm); // unsafe
|
||||||
// cout << "--" << endl;
|
// cout << "--" << endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -711,7 +783,14 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
ema = eMax;
|
ema = eMax;
|
||||||
};
|
};
|
||||||
|
|
||||||
void setMutex(pthread_mutex_t *m) { fm = m; };
|
//void setMutex(pthread_mutex_t *m) { fm = m; };
|
||||||
|
void setMutex(std::mutex* m) {
|
||||||
|
if (ownsMutex && fm) {
|
||||||
|
delete fm; // Cleanup old mutex
|
||||||
|
}
|
||||||
|
fm = m;
|
||||||
|
ownsMutex = false;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int nDark; /**< number of frames to be used at the beginning of the dataset
|
int nDark; /**< number of frames to be used at the beginning of the dataset
|
||||||
@ -733,7 +812,9 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
|||||||
int nphFrame;
|
int nphFrame;
|
||||||
|
|
||||||
// double **val;
|
// double **val;
|
||||||
pthread_mutex_t *fm;
|
//pthread_mutex_t* fm; // Pointer to the shared mutex
|
||||||
|
std::mutex* fm; // Pointer to the shared (or unique) mutex (safer version)
|
||||||
|
bool ownsMutex; // Flag to indicate ownership
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
<enum>QTabWidget::North</enum>
|
<enum>QTabWidget::North</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>3</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="elideMode">
|
<property name="elideMode">
|
||||||
<enum>Qt::ElideLeft</enum>
|
<enum>Qt::ElideLeft</enum>
|
||||||
@ -178,309 +178,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_roi">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Region of Interest</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>X Min:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="8">
|
|
||||||
<widget class="QPushButton" name="btnClearRoi">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>35</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>35</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Clear ROI at detector level</p><p>#clearroi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Clear ROI </string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../include/icons.qrc">
|
|
||||||
<normaloff>:/icons/images/erase.png</normaloff>:/icons/images/erase.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QSpinBox" name="spinXmin">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>120</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>120</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Set ROI at detector level</p><p>#roi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>1279</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="7">
|
|
||||||
<spacer name="horizontalSpacer_5">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Set ROI at detector level</p><p>#roi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>X Max:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<spacer name="horizontalSpacer_4">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QSpinBox" name="spinXmax">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>120</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>120</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Set ROI at detector level</p><p>#roi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>1279</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Readout: </string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<spacer name="verticalSpacer_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="6">
|
|
||||||
<widget class="QPushButton" name="btnSetRoi">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>35</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>35</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Set ROI at detector level</p><p>#roi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Set ROI </string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../include/icons.qrc">
|
|
||||||
<normaloff>:/icons/images/refresh.png</normaloff>:/icons/images/refresh.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="5">
|
|
||||||
<spacer name="horizontalSpacer_6">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="4">
|
|
||||||
<widget class="QComboBox" name="comboReadout">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>160</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Select readout to set ROI at detector level</p><p>#roi#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_network">
|
<widget class="QWidget" name="tab_network">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -2238,11 +1935,6 @@ Exposure Time of a sub frame. Only for Eiger in 32 bit mode
|
|||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>spinSetAllTrimbits</tabstop>
|
<tabstop>spinSetAllTrimbits</tabstop>
|
||||||
<tabstop>comboReadout</tabstop>
|
|
||||||
<tabstop>spinXmin</tabstop>
|
|
||||||
<tabstop>spinXmax</tabstop>
|
|
||||||
<tabstop>btnSetRoi</tabstop>
|
|
||||||
<tabstop>btnClearRoi</tabstop>
|
|
||||||
<tabstop>comboDetector</tabstop>
|
<tabstop>comboDetector</tabstop>
|
||||||
<tabstop>spinControlPort</tabstop>
|
<tabstop>spinControlPort</tabstop>
|
||||||
<tabstop>spinStopPort</tabstop>
|
<tabstop>spinStopPort</tabstop>
|
||||||
|
@ -38,87 +38,21 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="1" column="2" colspan="3">
|
<item row="4" column="5">
|
||||||
<widget class="QComboBox" name="comboHV">
|
<widget class="QSpinBox" name="spinThreshold2">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>High Voltage</p><p> #highvoltage#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>0</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>90</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>110</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>120</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>150</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>180</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>200</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="lblSettings">
|
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>110</width>
|
<width>140</width>
|
||||||
<height>0</height>
|
<height>25</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>110</width>
|
<width>140</width>
|
||||||
<height>16777215</height>
|
<height>25</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@ -128,52 +62,42 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Settings of the detector. </p><p> #settings#</p></body></html></string>
|
<string><html><head/><body><p>Threshold energy of 2nd counter</p><p>#threshold#</p><p><br/></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="keyboardTracking">
|
||||||
<string>Settings:</string>
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> eV</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>-1</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="4" column="9">
|
||||||
<widget class="QLabel" name="lblComboHV">
|
<spacer name="horizontalSpacer_4">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>High Voltage</p><p> #highvoltage#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>High Voltage: </string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="2">
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Expanding</enum>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>40</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="4">
|
<item row="6" column="4">
|
||||||
<widget class="QCheckBox" name="chkCounter3">
|
<widget class="QCheckBox" name="chkCounter3">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -201,29 +125,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="4" column="7">
|
||||||
<widget class="QLabel" name="lblSpinHV">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>High Voltage. Range: 60 - 200V. Swich off high voltage by setting to 0.</p><p>-1 corresponds to different values from detectors.</p><p>#highvoltage#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>High Voltage: </string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="7">
|
|
||||||
<spacer name="horizontalSpacer_3">
|
<spacer name="horizontalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
@ -239,97 +141,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="2">
|
<item row="1" column="2" colspan="3">
|
||||||
<widget class="QCheckBox" name="chkCounter1">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Enable 1st counter</p><p>#counters#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>1</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="lblThreshold">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Threshold energy. The trim energy values need to be loaded first using &quot;trimen&quot;</p><p>#threshold#</p><p>#trimen#</p><p><br/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Threshold:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="lblDynamicRange">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Dynamic Range of pixel/channel of detector</p><p>#dr#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Dynamic Range:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2" colspan="3">
|
|
||||||
<widget class="QSpinBox" name="spinHV">
|
<widget class="QSpinBox" name="spinHV">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
@ -369,8 +181,8 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="3">
|
<item row="6" column="2">
|
||||||
<widget class="QCheckBox" name="chkCounter2">
|
<widget class="QCheckBox" name="chkCounter1">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -387,17 +199,222 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Enable 2nd counter</p><p>#counters#</p></body></html></string>
|
<string><html><head/><body><p>Enable 1st counter</p><p>#counters#</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>2</string>
|
<string>1</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2" colspan="3">
|
<item row="7" column="2">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="6">
|
||||||
|
<widget class="QSpinBox" name="spinThreshold3">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Threshold energy of 3rd counter</p><p>#threshold#</p><p><br/></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="keyboardTracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> eV</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2" colspan="3">
|
||||||
|
<widget class="QSpinBox" name="spinThreshold">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Threshold energy. The trim energy values need to be loaded first using &quot;trimen&quot;</p><p>#threshold#</p><p>#trimen#</p><p><br/></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="keyboardTracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> eV</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2" colspan="3">
|
||||||
|
<widget class="QComboBox" name="comboDynamicRange">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Dynamic Range of pixel/channel of detector</p><p>#dr#</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>1.67772e+07</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>65535</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>4095</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>255</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>7</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="lblCounter">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Enable counters</p><p>#counters#</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Counters:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2" colspan="3">
|
||||||
<widget class="QComboBox" name="comboSettings">
|
<widget class="QComboBox" name="comboSettings">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -542,7 +559,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="8">
|
<item row="4" column="8">
|
||||||
<widget class="QPushButton" name="btnSetThreshold">
|
<widget class="QPushButton" name="btnSetThreshold">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -626,130 +643,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="3" column="2" colspan="3">
|
||||||
<widget class="QLabel" name="lblGainMode">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>110</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Gain Mode of the detector</p><p>#gainmode#</p><p><br/></p><p>Fix G0 is to be used with utmost caution. Can damage the detector!</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Gain Mode:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="2" colspan="3">
|
|
||||||
<widget class="QSpinBox" name="spinThreshold">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Threshold energy. The trim energy values need to be loaded first using &quot;trimen&quot;</p><p>#threshold#</p><p>#trimen#</p><p><br/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="keyboardTracking">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string> eV</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="5">
|
|
||||||
<widget class="QSpinBox" name="spinThreshold2">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Threshold energy of 2nd counter</p><p>#threshold#</p><p><br/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="keyboardTracking">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string> eV</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2" colspan="3">
|
|
||||||
<widget class="QComboBox" name="comboGainMode">
|
<widget class="QComboBox" name="comboGainMode">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -813,21 +707,15 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="6">
|
<item row="6" column="3">
|
||||||
<widget class="QSpinBox" name="spinThreshold3">
|
<widget class="QCheckBox" name="chkCounter2">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>140</width>
|
<width>50</width>
|
||||||
<height>25</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@ -837,112 +725,18 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Threshold energy of 3rd counter</p><p>#threshold#</p><p><br/></p></body></html></string>
|
<string><html><head/><body><p>Enable 2nd counter</p><p>#counters#</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="keyboardTracking">
|
<property name="text">
|
||||||
<bool>false</bool>
|
<string>2</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="suffix">
|
<property name="checked">
|
||||||
<string> eV</string>
|
<bool>true</bool>
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100000</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="2" colspan="3">
|
<item row="5" column="0">
|
||||||
<widget class="QComboBox" name="comboDynamicRange">
|
<widget class="QLabel" name="lblDynamicRange">
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>140</width>
|
|
||||||
<height>25</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Cantarell</family>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Dynamic Range of pixel/channel of detector</p><p>#dr#</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>1.67772e+07</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>65535</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>4095</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>255</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>7</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="lblCounter">
|
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -965,30 +759,147 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Enable counters</p><p>#counters#</p></body></html></string>
|
<string><html><head/><body><p>Dynamic Range of pixel/channel of detector</p><p>#dr#</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Counters:</string>
|
<string>Dynamic Range:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="9">
|
<item row="2" column="0">
|
||||||
<spacer name="horizontalSpacer_4">
|
<widget class="QLabel" name="lblSettings">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Settings of the detector. </p><p> #settings#</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Settings:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>20</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="lblThreshold">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Threshold energy. The trim energy values need to be loaded first using &quot;trimen&quot;</p><p>#threshold#</p><p>#trimen#</p><p><br/></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Threshold:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="lblGainMode">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>110</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Gain Mode of the detector</p><p>#gainmode#</p><p><br/></p><p>Fix G0 is to be used with utmost caution. Can damage the detector!</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Gain Mode:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="lblSpinHV">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Cantarell</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>High Voltage. Range: 60 - 200V. Swich off high voltage by setting to 0.</p><p>-1 corresponds to different values from detectors.</p><p>#highvoltage#</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>High Voltage: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>comboHV</tabstop>
|
|
||||||
<tabstop>spinHV</tabstop>
|
<tabstop>spinHV</tabstop>
|
||||||
<tabstop>comboSettings</tabstop>
|
<tabstop>comboSettings</tabstop>
|
||||||
<tabstop>comboGainMode</tabstop>
|
<tabstop>comboGainMode</tabstop>
|
||||||
|
@ -38,9 +38,6 @@ class qTabAdvanced : public QWidget, private Ui::TabAdvancedObject {
|
|||||||
void SetRxrUDPMAC(bool force = false);
|
void SetRxrUDPMAC(bool force = false);
|
||||||
void ForceSetRxrUDPMAC();
|
void ForceSetRxrUDPMAC();
|
||||||
void SetRxrZMQPort(int port);
|
void SetRxrZMQPort(int port);
|
||||||
void GetROI();
|
|
||||||
void ClearROI();
|
|
||||||
void SetROI();
|
|
||||||
void SetAllTrimbits();
|
void SetAllTrimbits();
|
||||||
void SetNumStoragecells(int value);
|
void SetNumStoragecells(int value);
|
||||||
void SetSubExposureTime();
|
void SetSubExposureTime();
|
||||||
|
@ -192,7 +192,6 @@ void qDetectorMain::SetUpDetector(const std::string &config_file, int multiID) {
|
|||||||
actionLoadTrimbits->setEnabled(true);
|
actionLoadTrimbits->setEnabled(true);
|
||||||
actionSaveTrimbits->setEnabled(true);
|
actionSaveTrimbits->setEnabled(true);
|
||||||
break;
|
break;
|
||||||
case slsDetectorDefs::GOTTHARD:
|
|
||||||
case slsDetectorDefs::JUNGFRAU:
|
case slsDetectorDefs::JUNGFRAU:
|
||||||
case slsDetectorDefs::MOENCH:
|
case slsDetectorDefs::MOENCH:
|
||||||
case slsDetectorDefs::GOTTHARD2:
|
case slsDetectorDefs::GOTTHARD2:
|
||||||
@ -405,12 +404,12 @@ void qDetectorMain::ExecuteUtilities(QAction *action) {
|
|||||||
|
|
||||||
void qDetectorMain::ExecuteHelp(QAction *action) {
|
void qDetectorMain::ExecuteHelp(QAction *action) {
|
||||||
if (action == actionAbout) {
|
if (action == actionAbout) {
|
||||||
LOG(logINFO) << "About Common GUI for Jungfrau, Eiger, Mythen3, "
|
LOG(logDEBUG) << "About Common GUI for Jungfrau, Eiger, Mythen3, "
|
||||||
"Gotthard, Gotthard2 and Moench detectors";
|
"Gotthard2 and Moench detectors";
|
||||||
|
|
||||||
std::string clientVersion = "unknown";
|
std::string packageVersion = "unknown";
|
||||||
try {
|
try {
|
||||||
clientVersion = det->getClientVersion();
|
packageVersion = det->getPackageVersion();
|
||||||
}
|
}
|
||||||
CATCH_DISPLAY("Could not get client version.",
|
CATCH_DISPLAY("Could not get client version.",
|
||||||
"qDetectorMain::ExecuteHelp")
|
"qDetectorMain::ExecuteHelp")
|
||||||
@ -419,12 +418,12 @@ void qDetectorMain::ExecuteHelp(QAction *action) {
|
|||||||
qDefs::INFORMATION,
|
qDefs::INFORMATION,
|
||||||
"<p style=\"font-family:verdana;\">"
|
"<p style=\"font-family:verdana;\">"
|
||||||
|
|
||||||
"<b>SLS Detector Client version: " +
|
"<b>SLS Detector Package: v" +
|
||||||
clientVersion +
|
packageVersion +
|
||||||
"</b><br><br>"
|
"</b><br><br>"
|
||||||
|
|
||||||
"Common GUI to control the SLS Detectors: "
|
"Common GUI to control the SLS Detectors: "
|
||||||
"Jungfrau, Eiger, Mythen3, Gotthard, Gotthard2 and "
|
"Jungfrau, Eiger, Mythen3, Gotthard2 and "
|
||||||
"Moench.<br><br>"
|
"Moench.<br><br>"
|
||||||
|
|
||||||
"It can be operated in parallel with the command "
|
"It can be operated in parallel with the command "
|
||||||
|
@ -83,9 +83,7 @@ void qDrawPlot::SetupWidgetWindow() {
|
|||||||
fileSaveName = "Image";
|
fileSaveName = "Image";
|
||||||
}
|
}
|
||||||
|
|
||||||
gotthard25 = ((detType == slsDetectorDefs::GOTTHARD2 ||
|
gotthard25 = (detType == slsDetectorDefs::GOTTHARD2 && det->size() == 2);
|
||||||
detType == slsDetectorDefs::GOTTHARD) &&
|
|
||||||
det->size() == 2);
|
|
||||||
|
|
||||||
SetupPlots();
|
SetupPlots();
|
||||||
SetDataCallBack(true);
|
SetDataCallBack(true);
|
||||||
|
@ -28,9 +28,6 @@ void qTabAdvanced::SetupWidgetWindow() {
|
|||||||
spinSubDeadTime->setEnabled(true);
|
spinSubDeadTime->setEnabled(true);
|
||||||
comboSubDeadTimeUnit->setEnabled(true);
|
comboSubDeadTimeUnit->setEnabled(true);
|
||||||
break;
|
break;
|
||||||
case slsDetectorDefs::GOTTHARD:
|
|
||||||
tab_roi->setEnabled(true);
|
|
||||||
break;
|
|
||||||
case slsDetectorDefs::MYTHEN3:
|
case slsDetectorDefs::MYTHEN3:
|
||||||
tab_trimming->setEnabled(true);
|
tab_trimming->setEnabled(true);
|
||||||
lblDiscardBits->setEnabled(true);
|
lblDiscardBits->setEnabled(true);
|
||||||
@ -114,14 +111,6 @@ void qTabAdvanced::Initialization() {
|
|||||||
connect(spinRxrZMQPort, SIGNAL(valueChanged(int)), this,
|
connect(spinRxrZMQPort, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(SetRxrZMQPort(int)));
|
SLOT(SetRxrZMQPort(int)));
|
||||||
|
|
||||||
// roi
|
|
||||||
if (tab_roi->isEnabled()) {
|
|
||||||
connect(comboReadout, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(GetROI()));
|
|
||||||
connect(btnSetRoi, SIGNAL(clicked()), this, SLOT(SetROI()));
|
|
||||||
connect(btnClearRoi, SIGNAL(clicked()), this, SLOT(ClearROI()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// storage cells
|
// storage cells
|
||||||
if (lblNumStoragecells->isEnabled()) {
|
if (lblNumStoragecells->isEnabled()) {
|
||||||
connect(spinNumStoragecells, SIGNAL(valueChanged(int)), this,
|
connect(spinNumStoragecells, SIGNAL(valueChanged(int)), this,
|
||||||
@ -173,23 +162,16 @@ void qTabAdvanced::PopulateDetectors() {
|
|||||||
LOG(logDEBUG) << "Populating detectors";
|
LOG(logDEBUG) << "Populating detectors";
|
||||||
disconnect(comboDetector, SIGNAL(currentIndexChanged(int)), this,
|
disconnect(comboDetector, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(SetDetector()));
|
SLOT(SetDetector()));
|
||||||
disconnect(comboReadout, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(GetROI()));
|
|
||||||
|
|
||||||
comboDetector->clear();
|
comboDetector->clear();
|
||||||
comboReadout->clear();
|
|
||||||
auto res = det->getHostname();
|
auto res = det->getHostname();
|
||||||
for (auto &it : res) {
|
for (auto &it : res) {
|
||||||
comboDetector->addItem(QString(it.c_str()));
|
comboDetector->addItem(QString(it.c_str()));
|
||||||
comboReadout->addItem(QString(it.c_str()));
|
|
||||||
}
|
}
|
||||||
comboDetector->setCurrentIndex(0);
|
comboDetector->setCurrentIndex(0);
|
||||||
comboReadout->setCurrentIndex(0);
|
|
||||||
|
|
||||||
connect(comboDetector, SIGNAL(currentIndexChanged(int)), this,
|
connect(comboDetector, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(SetDetector()));
|
SLOT(SetDetector()));
|
||||||
connect(comboReadout, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(GetROI()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qTabAdvanced::GetControlPort() {
|
void qTabAdvanced::GetControlPort() {
|
||||||
@ -570,40 +552,6 @@ void qTabAdvanced::SetRxrZMQPort(int port) {
|
|||||||
&qTabAdvanced::GetRxrZMQPort)
|
&qTabAdvanced::GetRxrZMQPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
void qTabAdvanced::GetROI() {
|
|
||||||
LOG(logDEBUG) << "Getting ROI";
|
|
||||||
try {
|
|
||||||
slsDetectorDefs::ROI roi =
|
|
||||||
det->getROI({comboReadout->currentIndex()})[0];
|
|
||||||
spinXmin->setValue(roi.xmin);
|
|
||||||
spinXmax->setValue(roi.xmax);
|
|
||||||
}
|
|
||||||
CATCH_DISPLAY("Could not get ROI.", "qTabAdvanced::GetROI")
|
|
||||||
}
|
|
||||||
|
|
||||||
void qTabAdvanced::ClearROI() {
|
|
||||||
LOG(logINFO) << "Clearing ROI";
|
|
||||||
spinXmin->setValue(-1);
|
|
||||||
spinXmax->setValue(-1);
|
|
||||||
SetROI();
|
|
||||||
LOG(logDEBUG) << "ROIs cleared";
|
|
||||||
}
|
|
||||||
|
|
||||||
void qTabAdvanced::SetROI() {
|
|
||||||
|
|
||||||
slsDetectorDefs::ROI roi(spinXmin->value(), spinXmax->value());
|
|
||||||
|
|
||||||
// set roi
|
|
||||||
LOG(logINFO) << "Setting ROI: [" << roi.xmin << ", " << roi.xmax << "]";
|
|
||||||
try {
|
|
||||||
det->setROI(roi, {comboReadout->currentIndex()});
|
|
||||||
}
|
|
||||||
CATCH_DISPLAY("Could not set these ROIs.", "qTabAdvanced::SetROI")
|
|
||||||
|
|
||||||
// update corrected list
|
|
||||||
GetROI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void qTabAdvanced::GetAllTrimbits() {
|
void qTabAdvanced::GetAllTrimbits() {
|
||||||
LOG(logDEBUG) << "Getting all trimbits value";
|
LOG(logDEBUG) << "Getting all trimbits value";
|
||||||
disconnect(spinSetAllTrimbits, SIGNAL(valueChanged(int)), this,
|
disconnect(spinSetAllTrimbits, SIGNAL(valueChanged(int)), this,
|
||||||
@ -831,11 +779,6 @@ void qTabAdvanced::Refresh() {
|
|||||||
// update all network widgets
|
// update all network widgets
|
||||||
SetDetector();
|
SetDetector();
|
||||||
|
|
||||||
// roi
|
|
||||||
if (tab_roi->isEnabled()) {
|
|
||||||
GetROI();
|
|
||||||
}
|
|
||||||
|
|
||||||
// storage cells
|
// storage cells
|
||||||
if (lblNumStoragecells->isEnabled()) {
|
if (lblNumStoragecells->isEnabled()) {
|
||||||
GetNumStoragecells();
|
GetNumStoragecells();
|
||||||
|
@ -34,15 +34,6 @@ void qTabDeveloper::SetupWidgetWindow() {
|
|||||||
new qDacWidget(this, det, false, sls::ToString(it), it));
|
new qDacWidget(this, det, false, sls::ToString(it), it));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case slsDetectorDefs::GOTTHARD:
|
|
||||||
ind = slsDetectorDefs::TEMPERATURE_ADC;
|
|
||||||
adcWidgets.push_back(
|
|
||||||
new qDacWidget(this, det, false, sls::ToString(ind), ind));
|
|
||||||
ind = slsDetectorDefs::TEMPERATURE_FPGA;
|
|
||||||
adcWidgets.push_back(
|
|
||||||
new qDacWidget(this, det, false, sls::ToString(ind), ind));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case slsDetectorDefs::JUNGFRAU:
|
case slsDetectorDefs::JUNGFRAU:
|
||||||
ind = slsDetectorDefs::TEMPERATURE_ADC;
|
ind = slsDetectorDefs::TEMPERATURE_ADC;
|
||||||
adcWidgets.push_back(
|
adcWidgets.push_back(
|
||||||
|
@ -47,7 +47,6 @@ void qTabPlot::SetupWidgetWindow() {
|
|||||||
// enabling according to det type
|
// enabling according to det type
|
||||||
is1d = false;
|
is1d = false;
|
||||||
switch (det->getDetectorType().squash()) {
|
switch (det->getDetectorType().squash()) {
|
||||||
case slsDetectorDefs::GOTTHARD:
|
|
||||||
case slsDetectorDefs::MYTHEN3:
|
case slsDetectorDefs::MYTHEN3:
|
||||||
is1d = true;
|
is1d = true;
|
||||||
break;
|
break;
|
||||||
|
@ -18,8 +18,6 @@ qTabSettings::qTabSettings(QWidget *parent, Detector *detector)
|
|||||||
qTabSettings::~qTabSettings() {}
|
qTabSettings::~qTabSettings() {}
|
||||||
|
|
||||||
void qTabSettings::SetupWidgetWindow() {
|
void qTabSettings::SetupWidgetWindow() {
|
||||||
comboHV->hide();
|
|
||||||
lblComboHV->hide();
|
|
||||||
lblSpinHV->hide();
|
lblSpinHV->hide();
|
||||||
spinHV->hide();
|
spinHV->hide();
|
||||||
hvmin = HV_MIN;
|
hvmin = HV_MIN;
|
||||||
@ -100,9 +98,6 @@ void qTabSettings::SetupWidgetWindow() {
|
|||||||
} else if (detType == slsDetectorDefs::MOENCH) {
|
} else if (detType == slsDetectorDefs::MOENCH) {
|
||||||
lblSpinHV->show();
|
lblSpinHV->show();
|
||||||
spinHV->show();
|
spinHV->show();
|
||||||
} else if (detType == slsDetectorDefs::GOTTHARD) {
|
|
||||||
comboHV->show();
|
|
||||||
lblComboHV->show();
|
|
||||||
} else if (detType == slsDetectorDefs::GOTTHARD2) {
|
} else if (detType == slsDetectorDefs::GOTTHARD2) {
|
||||||
lblSpinHV->show();
|
lblSpinHV->show();
|
||||||
spinHV->show();
|
spinHV->show();
|
||||||
@ -189,8 +184,6 @@ void qTabSettings::ShowFixG0(bool expertMode) {
|
|||||||
|
|
||||||
void qTabSettings::Initialization() {
|
void qTabSettings::Initialization() {
|
||||||
// High voltage
|
// High voltage
|
||||||
connect(comboHV, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(SetHighVoltage()));
|
|
||||||
connect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
connect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
@ -231,12 +224,10 @@ void qTabSettings::Initialization() {
|
|||||||
|
|
||||||
void qTabSettings::GetHighVoltage() {
|
void qTabSettings::GetHighVoltage() {
|
||||||
// not enabled for eiger
|
// not enabled for eiger
|
||||||
if (!comboHV->isVisible() && !spinHV->isVisible())
|
if (!spinHV->isVisible())
|
||||||
return;
|
return;
|
||||||
LOG(logDEBUG) << "Getting High Voltage";
|
LOG(logDEBUG) << "Getting High Voltage";
|
||||||
disconnect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
disconnect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
||||||
disconnect(comboHV, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(SetHighVoltage()));
|
|
||||||
try {
|
try {
|
||||||
Result<int> retvals = det->getHighVoltage();
|
Result<int> retvals = det->getHighVoltage();
|
||||||
|
|
||||||
@ -258,55 +249,19 @@ void qTabSettings::GetHighVoltage() {
|
|||||||
master_retvals.tsquash("Inconsistent values for high voltage.");
|
master_retvals.tsquash("Inconsistent values for high voltage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// spinHV
|
if (retval != 0 && retval < hvmin && retval > HV_MAX) {
|
||||||
if (spinHV->isVisible()) {
|
throw RuntimeError(std::string("Unknown High Voltage: ") +
|
||||||
if (retval != 0 && retval < hvmin && retval > HV_MAX) {
|
std::to_string(retval));
|
||||||
throw RuntimeError(std::string("Unknown High Voltage: ") +
|
|
||||||
std::to_string(retval));
|
|
||||||
}
|
|
||||||
spinHV->setValue(retval);
|
|
||||||
}
|
|
||||||
// combo HV
|
|
||||||
else {
|
|
||||||
switch (retval) {
|
|
||||||
case 0:
|
|
||||||
comboHV->setCurrentIndex(HV_0);
|
|
||||||
break;
|
|
||||||
case 90:
|
|
||||||
comboHV->setCurrentIndex(HV_90);
|
|
||||||
break;
|
|
||||||
case 110:
|
|
||||||
comboHV->setCurrentIndex(HV_110);
|
|
||||||
break;
|
|
||||||
case 120:
|
|
||||||
comboHV->setCurrentIndex(HV_120);
|
|
||||||
break;
|
|
||||||
case 150:
|
|
||||||
comboHV->setCurrentIndex(HV_150);
|
|
||||||
break;
|
|
||||||
case 180:
|
|
||||||
comboHV->setCurrentIndex(HV_180);
|
|
||||||
break;
|
|
||||||
case 200:
|
|
||||||
comboHV->setCurrentIndex(HV_200);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw RuntimeError(std::string("Unknown High Voltage: ") +
|
|
||||||
std::to_string(retval));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
spinHV->setValue(retval);
|
||||||
}
|
}
|
||||||
CATCH_DISPLAY("Could not get high voltage.", "qTabSettings::GetHighVoltage")
|
CATCH_DISPLAY("Could not get high voltage.", "qTabSettings::GetHighVoltage")
|
||||||
connect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
connect(spinHV, SIGNAL(valueChanged(int)), this, SLOT(SetHighVoltage()));
|
||||||
connect(comboHV, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(SetHighVoltage()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qTabSettings::SetHighVoltage() {
|
void qTabSettings::SetHighVoltage() {
|
||||||
int val = (comboHV->isVisible() ? comboHV->currentText().toInt()
|
int val = spinHV->value();
|
||||||
: spinHV->value());
|
|
||||||
LOG(logINFO) << "Setting high voltage:" << val;
|
LOG(logINFO) << "Setting high voltage:" << val;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
det->setHighVoltage(val);
|
det->setHighVoltage(val);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ install(TARGETS slsProjectCSettings
|
|||||||
add_subdirectory(ctbDetectorServer)
|
add_subdirectory(ctbDetectorServer)
|
||||||
add_subdirectory(xilinx_ctbDetectorServer)
|
add_subdirectory(xilinx_ctbDetectorServer)
|
||||||
add_subdirectory(eigerDetectorServer)
|
add_subdirectory(eigerDetectorServer)
|
||||||
add_subdirectory(gotthardDetectorServer)
|
|
||||||
add_subdirectory(jungfrauDetectorServer)
|
add_subdirectory(jungfrauDetectorServer)
|
||||||
add_subdirectory(mythen3DetectorServer)
|
add_subdirectory(mythen3DetectorServer)
|
||||||
add_subdirectory(gotthard2DetectorServer)
|
add_subdirectory(gotthard2DetectorServer)
|
||||||
|
27
slsDetectorServers/compileAllServers.sh
Executable file → Normal file
27
slsDetectorServers/compileAllServers.sh
Executable file → Normal file
@ -1,20 +1,16 @@
|
|||||||
# 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
|
||||||
|
|
||||||
|
# empty branch = developer branch in updateAPIVersion.sh
|
||||||
|
branch=""
|
||||||
det_list=("ctbDetectorServer
|
det_list=("ctbDetectorServer
|
||||||
gotthardDetectorServer
|
|
||||||
gotthard2DetectorServer
|
gotthard2DetectorServer
|
||||||
jungfrauDetectorServer
|
jungfrauDetectorServer
|
||||||
mythen3DetectorServer
|
mythen3DetectorServer
|
||||||
moenchDetectorServer
|
moenchDetectorServer
|
||||||
xilinx_ctbDetectorServer"
|
xilinx_ctbDetectorServer"
|
||||||
)
|
)
|
||||||
usage="\nUsage: compileAllServers.sh [server|all(opt)] [update_api(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tupdate_api if true updates the api to version in VERSION file"
|
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
|
||||||
|
|
||||||
update_api=true
|
|
||||||
target=version
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# arguments
|
# arguments
|
||||||
if [ $# -eq 0 ]; then
|
if [ $# -eq 0 ]; then
|
||||||
@ -38,12 +34,15 @@ elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
|
|||||||
declare -a det=("${1}")
|
declare -a det=("${1}")
|
||||||
#echo "Compiling only $1"
|
#echo "Compiling only $1"
|
||||||
fi
|
fi
|
||||||
|
# branch
|
||||||
if [ $# -eq 2 ]; then
|
if [ $# -eq 2 ]; then
|
||||||
update_api=$2
|
# arg in list
|
||||||
if not $update_api ; then
|
if [[ $det_list == *$2* ]]; then
|
||||||
target=clean
|
echo -e "Invalid argument 2: $2. $usage"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
branch+=$2
|
||||||
|
#echo "with branch $branch"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "Too many arguments.$usage"
|
echo -e "Too many arguments.$usage"
|
||||||
@ -54,9 +53,6 @@ declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
|
|||||||
|
|
||||||
echo -e "list is ${det[@]}"
|
echo -e "list is ${det[@]}"
|
||||||
|
|
||||||
if $update_api; then
|
|
||||||
echo "updating api to $(cat ../VERSION)"
|
|
||||||
fi
|
|
||||||
# compile each server
|
# compile each server
|
||||||
idet=0
|
idet=0
|
||||||
for i in ${det[@]}
|
for i in ${det[@]}
|
||||||
@ -66,13 +62,14 @@ do
|
|||||||
echo -e "Compiling $dir [$file]"
|
echo -e "Compiling $dir [$file]"
|
||||||
cd $dir
|
cd $dir
|
||||||
make clean
|
make clean
|
||||||
if make $target; then
|
if make version API_BRANCH=$branch; then
|
||||||
deterror[$idet]="OK"
|
deterror[$idet]="OK"
|
||||||
else
|
else
|
||||||
deterror[$idet]="FAIL"
|
deterror[$idet]="FAIL"
|
||||||
fi
|
fi
|
||||||
mv bin/$dir bin/$file
|
mv bin/$dir bin/$file
|
||||||
git add -f bin/$file
|
git add -f bin/$file
|
||||||
|
cp bin/$file /tftpboot/
|
||||||
cd ..
|
cd ..
|
||||||
echo -e "\n\n"
|
echo -e "\n\n"
|
||||||
((++idet))
|
((++idet))
|
||||||
|
86
slsDetectorServers/compileAllServers_noAPIUpdate.sh
Normal file
86
slsDetectorServers/compileAllServers_noAPIUpdate.sh
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
|
||||||
|
# empty branch = developer branch in updateAPIVersion.sh
|
||||||
|
branch=""
|
||||||
|
det_list=("ctbDetectorServer"
|
||||||
|
"gotthard2DetectorServer"
|
||||||
|
"jungfrauDetectorServer"
|
||||||
|
"mythen3DetectorServer"
|
||||||
|
"moenchDetectorServer"
|
||||||
|
"xilinx_ctbDetectorServer"
|
||||||
|
)
|
||||||
|
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
|
||||||
|
|
||||||
|
# arguments
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
# no argument, all servers
|
||||||
|
declare -a det=${det_list[@]}
|
||||||
|
echo "Compiling all servers"
|
||||||
|
elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
|
||||||
|
# 'all' servers
|
||||||
|
if [[ $1 == "all" ]]; then
|
||||||
|
declare -a det=${det_list[@]}
|
||||||
|
echo "Compiling all servers"
|
||||||
|
else
|
||||||
|
# only one server
|
||||||
|
# arg not in list
|
||||||
|
if [[ $det_list != *$1* ]]; then
|
||||||
|
echo -e "Invalid argument 1: $1. $usage"
|
||||||
|
return -1
|
||||||
|
fi
|
||||||
|
declare -a det=("${1}")
|
||||||
|
#echo "Compiling only $1"
|
||||||
|
fi
|
||||||
|
# branch
|
||||||
|
if [ $# -eq 2 ]; then
|
||||||
|
# arg in list
|
||||||
|
if [[ $det_list == *$2* ]]; then
|
||||||
|
echo -e "Invalid argument 2: $2. $usage"
|
||||||
|
return -1
|
||||||
|
fi
|
||||||
|
branch+=$2
|
||||||
|
#echo "with branch $branch"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "Too many arguments.$usage"
|
||||||
|
return -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
|
||||||
|
|
||||||
|
echo -e "list is ${det[@]}"
|
||||||
|
|
||||||
|
# compile each server
|
||||||
|
idet=0
|
||||||
|
for i in ${det[@]}
|
||||||
|
do
|
||||||
|
dir=$i
|
||||||
|
file="${i}_developer"
|
||||||
|
echo -e "Compiling $dir [$file]"
|
||||||
|
cd $dir
|
||||||
|
make clean
|
||||||
|
if make API_BRANCH=$branch; then
|
||||||
|
deterror[$idet]="OK"
|
||||||
|
else
|
||||||
|
deterror[$idet]="FAIL"
|
||||||
|
fi
|
||||||
|
mv bin/$dir bin/$file
|
||||||
|
git add -f bin/$file
|
||||||
|
cp bin/$file /tftpboot/
|
||||||
|
cd ..
|
||||||
|
echo -e "\n\n"
|
||||||
|
((++idet))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "Results:"
|
||||||
|
idet=0
|
||||||
|
for i in ${det[@]}
|
||||||
|
do
|
||||||
|
printf "%s\t\t= %s\n" "$i" "${deterror[$idet]}"
|
||||||
|
((++idet))
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
23
slsDetectorServers/compileEigerServer.sh
Executable file → Normal file
23
slsDetectorServers/compileEigerServer.sh
Executable file → Normal file
@ -3,31 +3,21 @@
|
|||||||
deterror="OK"
|
deterror="OK"
|
||||||
dir="eigerDetectorServer"
|
dir="eigerDetectorServer"
|
||||||
file="${dir}_developer"
|
file="${dir}_developer"
|
||||||
|
branch=""
|
||||||
usage="\nUsage: compileAllServers.sh [update_api(opt)]. \n\t update_api if true updates the api to version in VERSION file"
|
|
||||||
|
|
||||||
update_api=true
|
|
||||||
target=version
|
|
||||||
|
|
||||||
# arguments
|
# arguments
|
||||||
if [ $# -eq 1 ]; then
|
if [ $# -eq 1 ]; then
|
||||||
update_api=$1
|
branch+=$1
|
||||||
if not $update_api ; then
|
#echo "with branch $branch"
|
||||||
target=clean
|
|
||||||
|
|
||||||
fi
|
|
||||||
elif [ ! $# -eq 0 ]; then
|
elif [ ! $# -eq 0 ]; then
|
||||||
echo -e "Only one optional argument allowed for update_api."
|
echo -e "Only one optional argument allowed for branch."
|
||||||
return -1
|
return -1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if $update_api; then
|
|
||||||
echo "updating api to $(cat ../VERSION)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "Compiling $dir [$file]"
|
echo -e "Compiling $dir [$file]"
|
||||||
cd $dir
|
cd $dir
|
||||||
if make $target; then
|
make clean
|
||||||
|
if make version API_BRANCH=$branch; then
|
||||||
deterror="OK"
|
deterror="OK"
|
||||||
else
|
else
|
||||||
deterror="FAIL"
|
deterror="FAIL"
|
||||||
@ -35,6 +25,7 @@ fi
|
|||||||
|
|
||||||
mv bin/$dir bin/$file
|
mv bin/$dir bin/$file
|
||||||
git add -f bin/$file
|
git add -f bin/$file
|
||||||
|
cp bin/$file /tftpboot/
|
||||||
cd ..
|
cd ..
|
||||||
echo -e "\n\n"
|
echo -e "\n\n"
|
||||||
printf "Result:\t\t= %s\n" "${deterror}"
|
printf "Result:\t\t= %s\n" "${deterror}"
|
||||||
|
@ -25,10 +25,11 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
|
version_branch=$(API_BRANCH)
|
||||||
version_name=APICTB
|
version_name=APICTB
|
||||||
version_path=slsDetectorServers/ctbDetectorServer
|
version_path=slsDetectorServers/ctbDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
BIN
slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer
Executable file
BIN
slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer
Executable file
Binary file not shown.
Binary file not shown.
@ -15,6 +15,7 @@
|
|||||||
#include "loadPattern.h"
|
#include "loadPattern.h"
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h> // usleep
|
#include <unistd.h> // usleep
|
||||||
#ifdef VIRTUAL
|
#ifdef VIRTUAL
|
||||||
@ -1095,26 +1096,17 @@ int setNumTransceiverSamples(int val) {
|
|||||||
int getNumTransceiverSamples() { return ntSamples; }
|
int getNumTransceiverSamples() { return ntSamples; }
|
||||||
|
|
||||||
int setExpTime(int64_t val) {
|
int setExpTime(int64_t val) {
|
||||||
if (val < 0) {
|
setPatternWaitInterval(0, val);
|
||||||
LOG(logERROR, ("Invalid exptime: %lld ns\n", (long long int)val));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
LOG(logINFO, ("Setting exptime %lld ns\n", (long long int)val));
|
|
||||||
val *= (1E-3 * clkFrequency[RUN_CLK]);
|
|
||||||
setPatternWaitTime(0, val);
|
|
||||||
|
|
||||||
// validate for tolerance
|
// validate for tolerance
|
||||||
int64_t retval = getExpTime();
|
int64_t retval = getExpTime();
|
||||||
val /= (1E-3 * clkFrequency[RUN_CLK]);
|
|
||||||
if (val != retval) {
|
if (val != retval) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t getExpTime() {
|
int64_t getExpTime() { return getPatternWaitInterval(0); }
|
||||||
return getPatternWaitTime(0) / (1E-3 * clkFrequency[RUN_CLK]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int setPeriod(int64_t val) {
|
int setPeriod(int64_t val) {
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
@ -2267,11 +2259,23 @@ void *start_timer(void *arg) {
|
|||||||
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||||
|
|
||||||
// Generate Data
|
// Generate Data
|
||||||
char imageData[imageSize];
|
char *imageData = (char *)malloc(imageSize);
|
||||||
memset(imageData, 0, imageSize);
|
memset(imageData, 0, imageSize);
|
||||||
|
|
||||||
|
if (imageData == NULL) {
|
||||||
|
LOG(logERROR, ("Can not allocate image Data RAM."
|
||||||
|
"Probable cause: Memory Leak.\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
||||||
*((uint16_t *)(imageData + i)) = i;
|
*((uint16_t *)(imageData + i)) = i;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < imageSize; i += 2 * sizeof(uint64_t)) {
|
||||||
|
*((uint64_t *)(imageData + i)) = 0xffffffffffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
// Send data
|
// Send data
|
||||||
uint64_t frameNr = 0;
|
uint64_t frameNr = 0;
|
||||||
@ -2328,6 +2332,8 @@ void *start_timer(void *arg) {
|
|||||||
setNextFrameNumber(frameNr + numFrames);
|
setNextFrameNumber(frameNr + numFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(imageData);
|
||||||
|
|
||||||
closeUDPSocket(0);
|
closeUDPSocket(0);
|
||||||
|
|
||||||
sharedMemory_setStatus(IDLE);
|
sharedMemory_setStatus(IDLE);
|
||||||
|
@ -25,10 +25,11 @@ version: clean versioning $(PROGS) #hv9m_blackfin_server
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
|
version_branch=$(API_BRANCH)
|
||||||
version_name=APIEIGER
|
version_name=APIEIGER
|
||||||
version_path=slsDetectorServers/eigerDetectorServer
|
version_path=slsDetectorServers/eigerDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user