mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-16 14:57:13 +02:00
Compare commits
134 Commits
jf_h5reade
...
9.1.0
Author | SHA1 | Date | |
---|---|---|---|
37b2efb1ed | |||
7ac18fbad9 | |||
6839315a7c | |||
527915a2ca | |||
64aad1e196 | |||
d3f847100e | |||
e1224936ca | |||
f29ef9e345 | |||
00e3b196f6 | |||
0109973e68 | |||
ad995b381a | |||
53b84b17a6 | |||
16d404c21b | |||
34ce96ffa0 | |||
d5fa26ef9a | |||
77f20b4e97 | |||
a295208c12 | |||
36a6087e1d | |||
fb406a7c6c | |||
6e4380db43 | |||
903652bb72 | |||
1609706093 | |||
14d2d171bb | |||
dd8452b365 | |||
15a9fb86da | |||
222d2b3fad | |||
a57531312f | |||
85a03a1d72 | |||
fc197ed002 | |||
a5d242876b | |||
76ce5de89e | |||
dbb0dbcbcd | |||
87d40d418e | |||
c82712b587 | |||
9dd1509714 | |||
c8290598db | |||
ff6a2655a2 | |||
7b2e6ae4ab | |||
706f3a103c | |||
5de98b3db0 | |||
7494e41862 | |||
7607fdc9a7 | |||
1bfffb842d | |||
7c48ae9a49 | |||
bf82aeee8d | |||
84e83bf551 | |||
60ce31bb17 | |||
2947b65e02 | |||
1b41e39ad1 | |||
64fea22c2b | |||
9beaed7813 | |||
0aeb7e4417 | |||
4880f87791 | |||
97f0c1fe46 | |||
a86fd00e59 | |||
24894667b7 | |||
4b414bfddb | |||
15d357d9ab | |||
f95de054f9 | |||
0aef8113dd | |||
9785a41048 | |||
417e1a88a5 | |||
9c0dd0385d | |||
5ab64efe3e | |||
8f77e4d4fe | |||
41c5b75b10 | |||
bfe53c6693 | |||
f7997dd09a | |||
c64e87a2b6 | |||
5eeb8e29c1 | |||
09697fa325 | |||
90b4daef39 | |||
2082f1eee7 | |||
d3a636b563 | |||
50b9b6ca39 | |||
e86b57cdfc | |||
14e11e8b5b | |||
beafe86554 | |||
af3dc1e7f4 | |||
573177203b | |||
a3ca9ebce5 | |||
8174fc9691 | |||
d6eac6da71 | |||
56c7ae4852 | |||
9b9b09ceaf | |||
cfebaee2a5 | |||
4613c54f57 | |||
51f9d6f011 | |||
58ac7ac280 | |||
82edfa75d3 | |||
35ed926047 | |||
4023ed0775 | |||
b6ef3bc39e | |||
2035666792 | |||
1ff4d806e7 | |||
3861379653 | |||
91140bbb71 | |||
a5632fcbea | |||
d44329117d | |||
4a454aa698 | |||
0e43072db8 | |||
6c67025ea8 | |||
e5ee27dbfa | |||
601249cc71 | |||
ff60b8c379 | |||
37ce3d6f59 | |||
bf26533fd8 | |||
7106273521 | |||
1484d038de | |||
fb0090c79e | |||
adc68cd519 | |||
1566eef247 | |||
e7cd90db78 | |||
45414149fe | |||
48759f440e | |||
b367b7e431 | |||
f0b2a6f6f9 | |||
f761046bfc | |||
1a859b83db | |||
70bfc875a6 | |||
c0755308a4 | |||
ab5509e10c | |||
004cb26646 | |||
a4f47a5945 | |||
312f3f473d | |||
5871086cd6 | |||
6a0fe823b3 | |||
5912aae53e | |||
8833ccf5cc | |||
77c558a7be | |||
378fc301b8 | |||
87d6e16090 | |||
2ef021041c | |||
574127b5ac |
@ -1,29 +0,0 @@
|
||||
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
|
@ -1,27 +0,0 @@
|
||||
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
|
@ -1,4 +1,4 @@
|
||||
name: Native CMake Build
|
||||
name: CMake
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@ -14,13 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Configure and build using cmake
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
- run: pip install pytest numpy
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
|
||||
@ -33,15 +27,12 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build -j4 --config ${{env.BUILD_TYPE}}
|
||||
run: cmake --build ${{github.workspace}}/build -j2 --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: C++ unit tests
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest -C ${{env.BUILD_TYPE}} -j1
|
||||
|
||||
- name: Python unit tests
|
||||
working-directory: ${{github.workspace}}/build/bin
|
||||
run: |
|
||||
python -m pytest ${{github.workspace}}/python/tests
|
||||
|
||||
|
42
.github/workflows/conda_library.yaml
vendored
42
.github/workflows/conda_library.yaml
vendored
@ -1,42 +0,0 @@
|
||||
name: Build slsdetlib
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, ] # macos-12, windows-2019]
|
||||
python-version: ["3.12",]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
# The setup-miniconda action needs this to activate miniconda
|
||||
defaults:
|
||||
run:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install conda-build conda-verify pytest anaconda-client
|
||||
|
||||
- name: Disable upload
|
||||
run: conda config --set anaconda_upload no
|
||||
|
||||
- name: Build
|
||||
run: conda build conda-recipes/main-library --output-folder build_output
|
||||
|
||||
- name: Upload all Conda packages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: conda-packages
|
||||
path: build_output/** # Uploads all packages
|
42
.github/workflows/conda_python.yaml
vendored
42
.github/workflows/conda_python.yaml
vendored
@ -1,42 +0,0 @@
|
||||
name: slsdet
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, ] # macos-12, windows-2019]
|
||||
python-version: ["3.12",]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
# The setup-miniconda action needs this to activate miniconda
|
||||
defaults:
|
||||
run:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install conda-build conda-verify pytest anaconda-client
|
||||
|
||||
- name: Disable upload
|
||||
run: conda config --set anaconda_upload no
|
||||
|
||||
- name: Build
|
||||
run: conda build conda-recipes/python-client --output-folder build_output
|
||||
|
||||
- name: Upload all Conda packages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: conda-packages
|
||||
path: build_output/** # Uploads all packages
|
@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(slsDetectorPackage)
|
||||
|
||||
# Read VERSION file into project version
|
||||
@ -29,44 +29,20 @@ include(FetchContent)
|
||||
option(SLS_FETCH_ZMQ_FROM_GITHUB "Fetch zmq from github" OFF)
|
||||
option(SLS_FETCH_PYBIND11_FROM_GITHUB "Fetch pybind11 from github" OFF)
|
||||
|
||||
|
||||
|
||||
# Allow FetchContent_Populate to be called with a single argument
|
||||
# otherwise deprecated warning is issued
|
||||
# Note: From cmake 3.28 we can pass EXCLUDE_FROM_ALL to FetchContent_Declare
|
||||
# and avoid direct use of Populate
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30")
|
||||
cmake_policy(SET CMP0169 OLD)
|
||||
endif()
|
||||
|
||||
# Patch libzmq to set minimum cmake version to 3.15 to avoid warnings
|
||||
# with newer cmake versions
|
||||
# Patch is applied in the FetchContent_Declare
|
||||
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)
|
||||
# Opt in to pull down a zmq version from github instead of
|
||||
# using the bundled version
|
||||
# using the bundled verison
|
||||
FetchContent_Declare(
|
||||
libzmq
|
||||
GIT_REPOSITORY https://github.com/zeromq/libzmq.git
|
||||
GIT_TAG v${SLS_LIBZMQ_VERSION}
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR> patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq_cmake_version.patch
|
||||
UPDATE_DISCONNECTED 1
|
||||
GIT_TAG v4.3.4
|
||||
)
|
||||
else()
|
||||
# Standard behaviour use libzmq included in this repo (libs/libzmq)
|
||||
FetchContent_Declare(
|
||||
libzmq
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-${SLS_LIBZMQ_VERSION}.tar.gz
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-4.3.4.tar.gz
|
||||
URL_HASH MD5=cc20b769ac10afa352e5ed2769bb23b3
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR> patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq_cmake_version.patch
|
||||
UPDATE_DISCONNECTED 1
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -78,11 +54,6 @@ set(ENABLE_CPACK OFF CACHE BOOL "")
|
||||
set(ENABLE_CLANG OFF CACHE BOOL "")
|
||||
set(ENABLE_CURVE OFF CACHE BOOL "")
|
||||
set(ENABLE_DRAFTS OFF CACHE BOOL "")
|
||||
set(ENABLE_PRECOMPILED OFF CACHE BOOL "")
|
||||
set(WITH_DOC OFF CACHE BOOL "")
|
||||
set(WITH_DOCS OFF CACHE BOOL "")
|
||||
|
||||
|
||||
|
||||
# Using GetProperties and Populate to be able to exclude zmq
|
||||
# from install (not possible with FetchContent_MakeAvailable(libzmq))
|
||||
@ -220,7 +191,7 @@ endif()
|
||||
# to control options for the libraries
|
||||
if(NOT TARGET slsProjectOptions)
|
||||
add_library(slsProjectOptions INTERFACE)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_17)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET slsProjectWarnings)
|
||||
@ -333,8 +304,7 @@ if (SLS_USE_INTEGRATION_TESTS)
|
||||
endif (SLS_USE_INTEGRATION_TESTS)
|
||||
|
||||
if (SLS_USE_PYTHON)
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
||||
set(PYBIND11_FINDPYTHON ON) # Needed for RH8
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development)
|
||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
@ -359,15 +329,9 @@ if (SLS_USE_CTBGUI)
|
||||
add_subdirectory(pyctbgui)
|
||||
endif(SLS_USE_CTBGUI)
|
||||
|
||||
# Workaround for file note being copied to build directory
|
||||
# when issuing a python -m build
|
||||
# TODO! Proper fix
|
||||
if(EXISTS ".clang-tidy")
|
||||
configure_file( .clang-tidy
|
||||
${CMAKE_BINARY_DIR}/.clang-tidy
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if (SLS_BUILD_EXAMPLES)
|
||||
add_subdirectory(sample)
|
||||
|
158
RELEASE.txt
158
RELEASE.txt
@ -1,21 +1,15 @@
|
||||
SLS Detector Package Major Release x.x.x released on xx.xx.202x
|
||||
SLS Detector Package Minor Release 9.1.0 released on 28.03.2025
|
||||
===============================================================
|
||||
|
||||
This document describes the differences between vx.x.x and vx.0.2
|
||||
This document describes the differences between v9.1.0 and v9.0.0
|
||||
|
||||
|
||||
|
||||
CONTENTS
|
||||
--------
|
||||
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
|
||||
1 Changes
|
||||
1.1 New or Changed Features
|
||||
1.2 Resolved Features
|
||||
2 On-board Detector Server Compatibility
|
||||
3 Firmware Requirements
|
||||
4 Kernel Requirements
|
||||
@ -24,11 +18,131 @@ This document describes the differences between vx.x.x and vx.0.2
|
||||
|
||||
|
||||
|
||||
1 New, Changed or Resolved Features
|
||||
=====================================
|
||||
1 Changes
|
||||
==========
|
||||
|
||||
|
||||
|
||||
1.1 New or Changed Features
|
||||
============================
|
||||
|
||||
|
||||
Receiver
|
||||
--------
|
||||
|
||||
|
||||
* Frame Synchronizer (experimental)
|
||||
Added a new binary, similar to slsMultiReceiver, to collect images from
|
||||
several receivers and stream them out as a ZMQ multipart message
|
||||
(one part for each UDP port). No reconstuction of the image. Includeds start
|
||||
and end ZMQ messages as well for the start and end callback parameters.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
|
||||
* Command line - multi module and multi detector indices
|
||||
Help on this topic has been added to the 'Command line' topic.
|
||||
|
||||
|
||||
* Row and column index (UDP header or callback)
|
||||
Help on how this is determined from the hostname is added to the 'UDP
|
||||
Header' and the 'Quick Start Guide' topics. Also added to the help in '
|
||||
hostname' command line help. Please note that this can be overwritten by
|
||||
corresponding row and column commands.
|
||||
|
||||
|
||||
|
||||
1.2 Resolved Features
|
||||
======================
|
||||
|
||||
|
||||
Firmware
|
||||
---------
|
||||
|
||||
|
||||
* [Jungfrau] Column select and filter resistor
|
||||
Configuration fix for chip v1.1 for these parameters
|
||||
|
||||
|
||||
Firmware &/ On-board Detector Server
|
||||
------------------------------------
|
||||
|
||||
|
||||
* [Jungfrau] Timing Info Decoder
|
||||
Only allowed for hardware v2.0 now.
|
||||
|
||||
|
||||
* [Jungfrau] Auto Comparator Disable - chip v1.0
|
||||
Previously, this mode for chip v1.0 automatically disabled the on-chip
|
||||
gain switching compatator after a fixed portion of the exposure time.
|
||||
Now, one must set also the comparator disable time using 'compdisabletime'
|
||||
just as in chip v1.1.
|
||||
|
||||
|
||||
* [Mythen3] Default period on server start up is 0 now.
|
||||
|
||||
|
||||
Client
|
||||
-------
|
||||
|
||||
|
||||
* Command line - Multi detector index inside file
|
||||
Multi detector index '[index]-' was ignored silently in the config/parameter
|
||||
file since 5.0.0. Now, it will throw an exception. Please use the multi
|
||||
detector index on the 'config' or 'parameter' command instead.
|
||||
|
||||
|
||||
* [Mythen3] patternX command autocompletes the argument to a path now.
|
||||
|
||||
|
||||
Receiver
|
||||
--------
|
||||
|
||||
|
||||
* Multiple Receiver objects in multiple threads
|
||||
slsMultiReceiver uses child processes, but if user rewrote to use multiple
|
||||
receiver objects in multiple threads instead, a callback mutex is now
|
||||
implemented to handle the locking mechanism between threads for the callbacks.
|
||||
|
||||
|
||||
* Removed potentially unsafe str().c_str() calls.
|
||||
|
||||
|
||||
* slsMultiReceiver Ctrl + C
|
||||
Now cleans up properly upon Ctrl + C, including exiting the Arping thread.
|
||||
|
||||
|
||||
* slsMultiReceiver version
|
||||
--version or -v now gives the version of slsMultiReceiver.
|
||||
|
||||
|
||||
ZMQ
|
||||
---
|
||||
|
||||
|
||||
* [Moench] Reduced significant print out in zmq processing using energy
|
||||
threshold.
|
||||
|
||||
|
||||
* [Moench] Zmq dummy packet restreaming command did nothing
|
||||
Temporary solution was to move from 'stop' to 'rx_stop' as 'stop' did not
|
||||
go further if module is idle.
|
||||
|
||||
|
||||
* [Moench] Too many Zmq dummy packets- unclear end in acquire
|
||||
Give time to process dummy packet before restreaming it and wait more
|
||||
before restreaming to reduce amoutn of zmq dummy packets to process.
|
||||
|
||||
|
||||
Simulators
|
||||
-----------
|
||||
|
||||
|
||||
* [Jungfrau][Moench] Slightly faster transmistting time by removing sleeping
|
||||
only if there is a transmission delay
|
||||
|
||||
|
||||
|
||||
2 On-board Detector Server Compatibility
|
||||
@ -36,9 +150,10 @@ This document describes the differences between vx.x.x and vx.0.2
|
||||
|
||||
|
||||
Eiger 9.0.0
|
||||
Jungfrau 9.0.0
|
||||
Mythen3 9.0.0
|
||||
Jungfrau 9.1.0
|
||||
Mythen3 9.1.0
|
||||
Gotthard2 9.0.0
|
||||
Gotthard 9.0.0
|
||||
Moench 9.0.0
|
||||
|
||||
|
||||
@ -65,14 +180,17 @@ This document describes the differences between vx.x.x and vx.0.2
|
||||
|
||||
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
||||
|
||||
Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0)
|
||||
21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0)
|
||||
Jungfrau 09.02.2025 (v1.6, HW v1.0) (updated in 9.1.0)
|
||||
08.02.2025 (v2.6, HW v2.0) (updated in 9.1.0)
|
||||
|
||||
Mythen3 11.10.2024 (v1.5) (updated in 9.0.0)
|
||||
Mythen3 13.11.2024 (v2.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 9.0.0)
|
||||
Moench 26.10.2023 (v2.0) (updated in 8.0.2)
|
||||
|
||||
Gotthard 08.02.2018 (50um and 25um Master)
|
||||
09.02.2018 (25 um Slave)
|
||||
|
||||
|
||||
Detector Upgrade
|
||||
@ -86,6 +204,8 @@ This document describes the differences between vx.x.x and vx.0.2
|
||||
Gotthard2 via command <.rbf>
|
||||
Moench via command <.pof>
|
||||
|
||||
Gotthard cannot be upgraded remotely
|
||||
|
||||
Except Eiger,
|
||||
upgrade
|
||||
Using command 'programfpga' or
|
||||
|
@ -8,7 +8,7 @@ if [ ! -d "install" ]; then
|
||||
mkdir install
|
||||
fi
|
||||
cd build
|
||||
cmake .. -G Ninja \
|
||||
cmake .. \
|
||||
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
|
||||
-DCMAKE_INSTALL_PREFIX=install \
|
||||
-DSLS_USE_TEXTCLIENT=ON \
|
11
conda-recipe/build_pylib.sh
Executable file
11
conda-recipe/build_pylib.sh
Executable file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
echo "|<-------- starting python build"
|
||||
|
||||
cd python
|
||||
|
||||
# copy VERSION into slsdet for installation
|
||||
cp ../VERSION slsdet/VERSION
|
||||
|
||||
${PYTHON} setup.py install
|
14
conda-recipe/conda_build_config.yaml
Normal file
14
conda-recipe/conda_build_config.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
python:
|
||||
- 3.8
|
||||
- 3.9
|
||||
- 3.10
|
||||
- 3.11
|
||||
- 3.12
|
||||
- 3.13
|
||||
|
||||
|
||||
c_stdlib:
|
||||
- sysroot # [linux]
|
||||
|
||||
c_stdlib_version: # [linux]
|
||||
- 2.17 # [linux]
|
11
conda-recipe/copy_ctbgui.sh
Normal file
11
conda-recipe/copy_ctbgui.sh
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
mkdir $PREFIX/lib
|
||||
mkdir $PREFIX/bin
|
||||
mkdir $PREFIX/include
|
||||
|
||||
|
||||
|
||||
cp build/bin/ctbGui $PREFIX/bin/.
|
||||
cp build/bin/libctbRootLib.so $PREFIX/lib/.
|
||||
|
@ -4,6 +4,7 @@
|
||||
mkdir -p $PREFIX/lib
|
||||
mkdir -p $PREFIX/bin
|
||||
mkdir -p $PREFIX/include/sls
|
||||
# mkdir $PREFIX/include/slsDetectorPackage
|
||||
|
||||
#Shared and static libraries
|
||||
cp build/install/lib/* $PREFIX/lib/
|
||||
@ -14,10 +15,8 @@ cp build/install/bin/sls_detector_acquire_zmq $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_get $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_put $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_help $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector $PREFIX/bin/.
|
||||
cp build/install/bin/slsReceiver $PREFIX/bin/.
|
||||
cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
|
||||
cp build/install/bin/slsFrameSynchronizer $PREFIX/bin/.
|
||||
|
||||
|
||||
cp build/install/include/sls/* $PREFIX/include/sls
|
@ -1,10 +1,10 @@
|
||||
source:
|
||||
path: ../..
|
||||
|
||||
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: {{ version }}
|
||||
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }}
|
||||
|
||||
|
||||
source:
|
||||
path: ..
|
||||
|
||||
build:
|
||||
number: 0
|
||||
@ -15,17 +15,16 @@ build:
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{ stdlib("c") }}
|
||||
- {{stdlib('c')}}
|
||||
- {{compiler('cxx')}}
|
||||
- git
|
||||
- cmake
|
||||
- cmake<=3.28
|
||||
- ninja
|
||||
- qt 5.*
|
||||
|
||||
host:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- libgl-devel # [linux]
|
||||
- libgl-devel
|
||||
- libtiff
|
||||
- zlib
|
||||
|
||||
@ -41,13 +40,44 @@ outputs:
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{ stdlib("c") }}
|
||||
- {{compiler('cxx')}}
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
- name: slsdet
|
||||
script: build_pylib.sh
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- python
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- setuptools
|
||||
- pybind11=2.13
|
||||
|
||||
host:
|
||||
- python
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- setuptools
|
||||
- pybind11=2.13
|
||||
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- python
|
||||
- numpy
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
test:
|
||||
imports:
|
||||
- slsdet
|
||||
|
||||
|
||||
- name: slsdetgui
|
||||
script: copy_gui.sh
|
||||
@ -61,7 +91,7 @@ outputs:
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- qt 5.*
|
||||
|
||||
- expat
|
||||
|
||||
- name: moenchzmq
|
||||
script: copy_moench.sh
|
||||
@ -75,3 +105,5 @@ outputs:
|
||||
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- expat
|
||||
|
3
conda-recipe/run_test.sh
Executable file
3
conda-recipe/run_test.sh
Executable file
@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
ctest -j2
|
@ -1,13 +0,0 @@
|
||||
|
||||
c_compiler:
|
||||
- gcc # [linux]
|
||||
|
||||
c_stdlib:
|
||||
- sysroot # [linux]
|
||||
|
||||
cxx_compiler:
|
||||
- gxx # [linux]
|
||||
|
||||
|
||||
c_stdlib_version: # [linux]
|
||||
- 2.17 # [linux]
|
@ -1,16 +0,0 @@
|
||||
python:
|
||||
- 3.11
|
||||
- 3.12
|
||||
- 3.13
|
||||
|
||||
c_compiler:
|
||||
- gcc # [linux]
|
||||
|
||||
c_stdlib:
|
||||
- sysroot # [linux]
|
||||
|
||||
cxx_compiler:
|
||||
- gxx # [linux]
|
||||
|
||||
c_stdlib_version: # [linux]
|
||||
- 2.17 # [linux]
|
@ -1,45 +0,0 @@
|
||||
source:
|
||||
path: ../..
|
||||
|
||||
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||
package:
|
||||
name: slsdet
|
||||
version: {{ version }}
|
||||
|
||||
build:
|
||||
number: 0
|
||||
script:
|
||||
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv # [not win]
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- python {{python}}
|
||||
- {{ compiler('c') }}
|
||||
- {{ stdlib("c") }}
|
||||
- {{ compiler('cxx') }}
|
||||
|
||||
host:
|
||||
- cmake
|
||||
- ninja
|
||||
- python {{python}}
|
||||
- pip
|
||||
- scikit-build-core
|
||||
- pybind11 >=2.13.0
|
||||
- fmt
|
||||
- zeromq
|
||||
- nlohmann_json
|
||||
- catch2
|
||||
|
||||
run:
|
||||
- python {{python}}
|
||||
- numpy
|
||||
|
||||
|
||||
test:
|
||||
imports:
|
||||
- slsdet
|
||||
|
||||
|
||||
about:
|
||||
summary: An example project built with pybind11 and scikit-build.
|
||||
# license_file: LICENSE
|
@ -40,7 +40,6 @@ set(SPHINX_SOURCE_FILES
|
||||
src/pydetector.rst
|
||||
src/pyenums.rst
|
||||
src/pyexamples.rst
|
||||
src/pyPatternGenerator.rst
|
||||
src/servers.rst
|
||||
src/receiver_api.rst
|
||||
src/result.rst
|
||||
@ -54,7 +53,6 @@ set(SPHINX_SOURCE_FILES
|
||||
src/serverdefaults.rst
|
||||
src/quick_start_guide.rst
|
||||
src/troubleshooting.rst
|
||||
src/pattern.rst
|
||||
src/receivers.rst
|
||||
src/slsreceiver.rst
|
||||
src/udpheader.rst
|
||||
|
@ -21,7 +21,7 @@ print('\n\n\n\n SERVER CSV')
|
||||
|
||||
src = Path('@CMAKE_SOURCE_DIR@')/'slsDetectorServers/'
|
||||
detectors = ['Mythen3', 'Gotthard2', 'Eiger',
|
||||
'Jungfrau', 'Moench', 'Ctb']
|
||||
'Jungfrau', 'Moench', 'Gotthard', 'Ctb']
|
||||
|
||||
|
||||
for det in detectors:
|
||||
|
@ -320,6 +320,61 @@ 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
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
@ -359,7 +414,6 @@ Chip Test Board
|
||||
"Digital Flag": 0,
|
||||
"Digital Samples": 1000,
|
||||
"Dbit Offset": 0,
|
||||
"Dbit Reorder": 1,
|
||||
"Dbit Bitset": 0,
|
||||
"Transceiver Mask": "0x3",
|
||||
"Transceiver Flag": 0,
|
||||
|
@ -131,6 +131,42 @@ 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
|
||||
-----------
|
||||
|
||||
@ -360,3 +396,7 @@ How to get back mtd3 drive remotely (udpating kernel)
|
||||
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,8 +36,6 @@ Welcome to slsDetectorPackage's documentation!
|
||||
pydetector
|
||||
pyenums
|
||||
pyexamples
|
||||
pyPatternGenerator
|
||||
pattern
|
||||
|
||||
.. toctree::
|
||||
:caption: Command line
|
||||
|
@ -288,6 +288,56 @@ Moench
|
||||
| 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
|
||||
^^^^^^^^^^^^^^^
|
||||
@ -345,9 +395,6 @@ Chip Test Board
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| 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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
||||
|
@ -1,122 +0,0 @@
|
||||
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.
|
@ -1,34 +0,0 @@
|
||||
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:
|
@ -89,3 +89,18 @@ DACS
|
||||
:widths: 35, 35
|
||||
: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,11 +27,12 @@ Arguments
|
||||
-p, --port <port> : TCP communication port with client.
|
||||
-g, --nomodule : [Mythen3][Gotthard2]
|
||||
Generic or No Module mode. Skips detector type checks.
|
||||
-f, --phaseshift <value> : [Gotthard] only. Sets phase shift.
|
||||
-d, --devel : Developer mode. Skips firmware checks.
|
||||
-u, --update : Update mode. Skips firmware checks and initial detector setup.
|
||||
-i, --ignore-config : [Eiger][Jungfrau][Gotthard2][Moench]
|
||||
-i, --ignore-config : [Eiger][Jungfrau][Gotthard][Gotthard2][Moench]
|
||||
Ignore config file.
|
||||
-m, --master <master> : [Eiger][Mythen3][Gotthard2]
|
||||
-m, --master <master> : [Eiger][Mythen3][Gotthard][Gotthard2]
|
||||
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.
|
||||
-s, --stopserver : Stop server. Do not use as it is created by control server
|
||||
@ -64,7 +65,7 @@ One can start the on-board detector server automatically upon powering on the bo
|
||||
/home/root/executables/eigerDetectorServer &> /dev/null &
|
||||
exit 0
|
||||
|
||||
Jungfrau | Moench | CTB
|
||||
Jungfrau | Moench | CTB | Gotthard I
|
||||
.. code-block:: bash
|
||||
|
||||
# Edit inittab on board
|
||||
|
@ -385,6 +385,14 @@ 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.
|
||||
|
||||
|
||||
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
|
||||
--------
|
||||
|
@ -92,14 +92,14 @@ Detector Enum
|
||||
================ ========
|
||||
GENERIC 0
|
||||
EIGER 1
|
||||
GOTTHARD* 2
|
||||
GOTTHARD 2
|
||||
JUNGFRAU 3
|
||||
CHIPTESTBOARD 4
|
||||
MOENCH 5
|
||||
MYTHEN3 6
|
||||
GOTTHARD2 7
|
||||
================ ========
|
||||
* deprecated since v10.0.0
|
||||
|
||||
|
||||
|
||||
Previous Versions
|
||||
|
@ -22,6 +22,7 @@ Binaries
|
||||
|
||||
eigerDetectorServer_virtual
|
||||
jungfrauDetectorServer_virtual
|
||||
gotthardDetectorServer_virtual
|
||||
gotthard2DetectorServer_virtual
|
||||
mythen3DetectorServer_virtual
|
||||
moenchDetectorServer_virtual
|
||||
|
12
examples/gotthard.config
Executable file
12
examples/gotthard.config
Executable file
@ -0,0 +1,12 @@
|
||||
# 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
|
||||
|
@ -1,18 +0,0 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index dd3d8eb9..c0187747 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -1,11 +1,8 @@
|
||||
# CMake build script for ZeroMQ
|
||||
project(ZeroMQ)
|
||||
|
||||
-if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
|
||||
- cmake_minimum_required(VERSION 3.0.2)
|
||||
-else()
|
||||
- cmake_minimum_required(VERSION 2.8.12)
|
||||
-endif()
|
||||
+cmake_minimum_required(VERSION 3.15)
|
||||
+message(STATUS "Patched cmake version")
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckCCompilerFlag)
|
@ -12,6 +12,5 @@ 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_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,7 +10,6 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.plotPattern import PlotPattern
|
||||
|
||||
from slsdet import DurationWrapper
|
||||
|
||||
class PatternTab(QtWidgets.QWidget):
|
||||
|
||||
@ -62,10 +61,7 @@ class PatternTab(QtWidgets.QWidget):
|
||||
getattr(self.view, f"lineEditLoop{i}Wait").editingFinished.connect(partial(self.setPatLoopWaitAddress, i))
|
||||
getattr(self.view,
|
||||
f"spinBoxLoop{i}Repetition").editingFinished.connect(partial(self.setPatLoopRepetition, 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)
|
||||
getattr(self.view, f"spinBoxLoop{i}WaitTime").editingFinished.connect(partial(self.setPatLoopWaitTime, i))
|
||||
self.view.pushButtonCompiler.clicked.connect(self.setCompiler)
|
||||
self.view.pushButtonUncompiled.clicked.connect(self.setUncompiledPatternFile)
|
||||
self.view.pushButtonPatternFile.clicked.connect(self.setPatternFile)
|
||||
@ -95,8 +91,7 @@ class PatternTab(QtWidgets.QWidget):
|
||||
self.getPatLoopStartStopAddress(i)
|
||||
self.getPatLoopWaitAddress(i)
|
||||
self.getPatLoopRepetition(i)
|
||||
self.getPatLoopWaitClocks(i)
|
||||
self.getPatLoopWaitInterval(i)
|
||||
self.getPatLoopWaitTime(i)
|
||||
|
||||
# Pattern Tab functions
|
||||
|
||||
@ -187,67 +182,17 @@ class PatternTab(QtWidgets.QWidget):
|
||||
self.det.patnloop[level] = spinBox.value()
|
||||
self.getPatLoopRepetition(level)
|
||||
|
||||
def getPatLoopWaitClocks(self, level):
|
||||
def getPatLoopWaitTime(self, level):
|
||||
retval = self.det.patwaittime[level]
|
||||
spinBox = getattr(self.view, f"doubleSpinBoxLoop{level}WaitClocks")
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
||||
spinBox.editingFinished.disconnect()
|
||||
spinBox.setValue(retval)
|
||||
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)
|
||||
spinBox.editingFinished.connect(partial(self.setPatLoopWaitTime, level))
|
||||
|
||||
def setPatLoopWaitTime(self, level):
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
||||
self.det.patwaittime[level] = spinBox.value()
|
||||
self.getPatLoopWaitTime(level)
|
||||
|
||||
def setCompiler(self):
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(
|
||||
@ -505,7 +450,7 @@ class PatternTab(QtWidgets.QWidget):
|
||||
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"patwaittime {i} {getattr(self.view, f'doubleSpinBoxLoop{i}WaitClocks').text()}")
|
||||
commands.append(f"patwaittime {i} {getattr(self.view, f'spinBoxLoop{i}WaitTime').text()}")
|
||||
commands.append(f"patlimits {self.view.lineEditStartAddress.text()}, {self.view.lineEditStopAddress.text()}")
|
||||
# commands.append(f"patfname {self.view.lineEditPatternFile.text()}")
|
||||
return commands
|
||||
|
@ -22,7 +22,6 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.plotTab = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.rx_dbitoffset = None
|
||||
self.rx_dbitreorder = None
|
||||
self.rx_dbitlist = None
|
||||
|
||||
def refresh(self):
|
||||
@ -30,7 +29,6 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.updateDigitalBitEnable()
|
||||
self.updateIOOut()
|
||||
self.getDBitOffset()
|
||||
self.getDBitReorder()
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.signals.count):
|
||||
@ -51,7 +49,6 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
@ -90,79 +87,60 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitreorder, rx_dbitlist, isPlottedArray, romode,
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitlist, isPlottedArray, rx_dbitoffset, romode,
|
||||
nADCEnabled):
|
||||
|
||||
#transform raw waveform data into a processed numpy array
|
||||
#@param data: raw waveform data
|
||||
|
||||
start_digital_data = 0
|
||||
"""
|
||||
transform raw waveform data into a processed numpy array
|
||||
@param data: raw waveform data
|
||||
"""
|
||||
dbitoffset = rx_dbitoffset
|
||||
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
|
||||
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))
|
||||
bit_index = 0
|
||||
for idx, i in enumerate(rx_dbitlist):
|
||||
offset = 0
|
||||
arr = []
|
||||
for i in rx_dbitlist:
|
||||
# where numbits * numsamples is not a multiple of 8
|
||||
if bit_index % 8 != 0:
|
||||
bit_index += (8 - (bit_index % 8))
|
||||
if offset % 8 != 0:
|
||||
offset += (8 - (offset % 8))
|
||||
if not isPlottedArray[i]:
|
||||
bit_index += nbitsPerDBit
|
||||
samples_per_bit[idx, :] = np.nan
|
||||
continue
|
||||
offset += nbitsPerDBit
|
||||
return None
|
||||
waveform = np.zeros(dSamples)
|
||||
for iSample in range(dSamples):
|
||||
# all samples for digital bit together from slsReceiver
|
||||
index = int(bit_index / 8)
|
||||
iBit = bit_index % 8
|
||||
index = int(offset / 8)
|
||||
iBit = offset % 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()
|
||||
|
||||
waveform[iSample] = bit
|
||||
offset += 1
|
||||
arr.append(waveform)
|
||||
|
||||
return np.array(arr)
|
||||
|
||||
def processWaveformData(self, data, aSamples, dSamples):
|
||||
|
||||
#view function
|
||||
#plots processed waveform data
|
||||
#data: raw waveform data
|
||||
#dsamples: digital samples
|
||||
#asamples: analog samples
|
||||
|
||||
self.refresh()
|
||||
|
||||
"""
|
||||
view function
|
||||
plots processed waveform data
|
||||
data: raw waveform data
|
||||
dsamples: digital samples
|
||||
asamples: analog samples
|
||||
"""
|
||||
waveforms = {}
|
||||
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_dbitreorder, self.rx_dbitlist, isPlottedArray,
|
||||
self.mainWindow.romode.value,
|
||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitlist, isPlottedArray,
|
||||
self.rx_dbitoffset, self.mainWindow.romode.value,
|
||||
self.mainWindow.nADCEnabled)
|
||||
|
||||
irow = 0
|
||||
for idx, i in enumerate(self.rx_dbitlist):
|
||||
# bits enabled but not plotting
|
||||
waveform = digital_array[idx, :]
|
||||
if np.isnan(waveform[0]):
|
||||
waveform = digital_array[idx]
|
||||
if waveform is None:
|
||||
continue
|
||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
@ -173,10 +151,8 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
irow += 1
|
||||
else:
|
||||
self.mainWindow.digitalPlots[i].setY(0)
|
||||
|
||||
return waveforms
|
||||
|
||||
|
||||
def initializeAllDigitalPlots(self):
|
||||
self.mainWindow.plotDigitalWaveform = pg.plot()
|
||||
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
||||
@ -384,25 +360,14 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
||||
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):
|
||||
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
||||
|
||||
def setDbitReorder(self):
|
||||
self.det.rx_dbitreorder = self.view.checkBoxDBitReorder.isChecked()
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
commands = []
|
||||
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
||||
if len(dblist) > 0:
|
||||
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
||||
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()}")
|
||||
return commands
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6074,33 +6074,6 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<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">
|
||||
<widget class="QLabel" name="label_66">
|
||||
<property name="font">
|
||||
@ -6113,36 +6086,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
||||
<property name="sizePolicy">
|
||||
@ -6190,18 +6133,50 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_22">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<item row="0" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<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="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>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -1,33 +0,0 @@
|
||||
[tool.scikit-build.metadata.version]
|
||||
provider = "scikit_build_core.metadata.regex"
|
||||
input = "VERSION"
|
||||
regex = '^(?P<version>\d+(?:\.\d+)*(?:[\.\+\w]+)?)$'
|
||||
result = "{version}"
|
||||
|
||||
[build-system]
|
||||
requires = [ "scikit-build-core>=0.10", "pybind11", "numpy",]
|
||||
build-backend = "scikit_build_core.build"
|
||||
|
||||
[project]
|
||||
name = "slsdet"
|
||||
dynamic = ["version"]
|
||||
|
||||
[tool.cibuildwheel]
|
||||
before-all = "uname -a"
|
||||
|
||||
[tool.scikit-build.build]
|
||||
verbose = true
|
||||
|
||||
[tool.scikit-build.cmake]
|
||||
build-type = "Release"
|
||||
|
||||
[tool.scikit-build.install]
|
||||
components = [ "python",]
|
||||
|
||||
[tool.scikit-build.cmake.define]
|
||||
SLS_USE_RECEIVER = "OFF"
|
||||
SLS_USE_RECEIVER_BINARIES = "OFF"
|
||||
SLS_USE_TEXTCLIENT = "OFF"
|
||||
SLS_BUILD_SHARED_LIBRARIES = "OFF"
|
||||
SLS_USE_PYTHON = "ON"
|
||||
SLS_INSTALL_PYTHONEXT = "ON"
|
@ -20,14 +20,13 @@ target_link_libraries(_slsdet PUBLIC
|
||||
|
||||
|
||||
set_target_properties(_slsdet PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/slsdet
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
#Copy Python code
|
||||
set( PYTHON_FILES
|
||||
slsdet/__init__.py
|
||||
slsdet/adcs.py
|
||||
slsdet/bits.py
|
||||
slsdet/dacs.py
|
||||
slsdet/powers.py
|
||||
slsdet/decorators.py
|
||||
@ -38,8 +37,8 @@ set( PYTHON_FILES
|
||||
slsdet/enums.py
|
||||
slsdet/errors.py
|
||||
slsdet/gaincaps.py
|
||||
slsdet/gotthard.py
|
||||
slsdet/pattern.py
|
||||
slsdet/PatternGenerator.py
|
||||
slsdet/gotthard2.py
|
||||
slsdet/moench.py
|
||||
slsdet/proxy.py
|
||||
@ -72,18 +71,9 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
|
||||
if(SLS_INSTALL_PYTHONEXT)
|
||||
install(TARGETS _slsdet
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
LIBRARY DESTINATION slsdet
|
||||
COMPONENT python
|
||||
)
|
||||
install(
|
||||
FILES ${PYTHON_FILES}
|
||||
DESTINATION slsdet
|
||||
COMPONENT python
|
||||
)
|
||||
install(
|
||||
FILES ../VERSION
|
||||
DESTINATION slsdet
|
||||
COMPONENT python
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/python
|
||||
)
|
||||
|
||||
install(FILES ${PYTHON_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
|
||||
install(FILES ../VERSION DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
|
||||
endif()
|
@ -55,6 +55,7 @@ servers = [
|
||||
# "jungfrauDetectorServer",
|
||||
"mythen3DetectorServer",
|
||||
# "gotthard2DetectorServer",
|
||||
# "gotthardDetectorServer",
|
||||
# "ctbDetectorServer",
|
||||
# "moenchDetectorServer",
|
||||
]
|
||||
|
77
python/setup.py
Executable file
77
python/setup.py
Executable file
@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
"""
|
||||
Setup file for slsdet
|
||||
Build upon the pybind11 example found here: https://github.com/pybind/python_example
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from setuptools import setup, find_packages
|
||||
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
||||
|
||||
def read_version():
|
||||
try:
|
||||
version_file = os.path.join(os.path.dirname(__file__), 'slsdet', 'VERSION')
|
||||
with open(version_file, "r") as f:
|
||||
return f.read().strip()
|
||||
except:
|
||||
raise RuntimeError("VERSION file not found in slsdet package from setup.py.")
|
||||
|
||||
__version__ = read_version()
|
||||
|
||||
|
||||
def get_conda_path():
|
||||
"""
|
||||
Keep this a function if we need some fancier logic later
|
||||
"""
|
||||
print('Prefix: ', os.environ['CONDA_PREFIX'])
|
||||
return os.environ['CONDA_PREFIX']
|
||||
|
||||
|
||||
#TODO migrate to CMake build or fetch files from cmake?
|
||||
ext_modules = [
|
||||
Pybind11Extension(
|
||||
'_slsdet',
|
||||
['src/main.cpp',
|
||||
'src/enums.cpp',
|
||||
'src/current.cpp',
|
||||
'src/detector.cpp',
|
||||
'src/network.cpp',
|
||||
'src/pattern.cpp',
|
||||
'src/scan.cpp',
|
||||
'src/duration.cpp',
|
||||
'src/DurationWrapper.cpp',
|
||||
'src/pedestal.cpp',
|
||||
]
|
||||
|
||||
|
||||
,
|
||||
include_dirs=[
|
||||
os.path.join(get_conda_path(), 'include'),
|
||||
|
||||
],
|
||||
libraries=['SlsDetector', 'SlsSupport', 'SlsReceiver'],
|
||||
library_dirs=[
|
||||
os.path.join(get_conda_path(), 'lib'),
|
||||
],
|
||||
language='c++'
|
||||
),
|
||||
]
|
||||
|
||||
setup(
|
||||
name='slsdet',
|
||||
version=__version__,
|
||||
author='Erik Frojdh',
|
||||
author_email='erik.frojdh@psi.ch',
|
||||
url='https://github.com/slsdetectorgroup/slsDetectorPackage',
|
||||
description='Detector API for SLS Detector Group detectors',
|
||||
long_description='',
|
||||
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
|
||||
package_data={
|
||||
'slsdet': ['VERSION'],
|
||||
},
|
||||
ext_modules=ext_modules,
|
||||
cmdclass={"build_ext": build_ext},
|
||||
zip_safe=False,
|
||||
)
|
@ -1,226 +0,0 @@
|
||||
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,12 +9,12 @@ from .detector import Detector
|
||||
from .jungfrau import Jungfrau
|
||||
from .mythen3 import Mythen3
|
||||
from .gotthard2 import Gotthard2
|
||||
from .gotthard import Gotthard
|
||||
from .moench import Moench
|
||||
from .pattern import Pattern, patternParameters
|
||||
from .gaincaps import Mythen3GainCapsWrapper
|
||||
from .PatternGenerator import PatternGenerator
|
||||
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
xy = _slsdet.xy
|
||||
defs = _slsdet.slsDetectorDefs
|
||||
|
||||
@ -41,6 +41,3 @@ def read_version():
|
||||
|
||||
__version__ = read_version()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
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))
|
@ -4,7 +4,7 @@ from .detector import Detector, freeze
|
||||
from .utils import element_if_equal
|
||||
from .dacs import DetectorDacs, NamedDacs
|
||||
from .powers import DetectorPowers, NamedPowers
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
from .detector_property import DetectorProperty
|
||||
from functools import partial
|
||||
import numpy as np
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
from .detector import freeze
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
class Dac(DetectorProperty):
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
from ._slsdet import CppDetectorApi
|
||||
from ._slsdet import slsDetectorDefs
|
||||
from ._slsdet import IpAddr, MacAddr
|
||||
from _slsdet import CppDetectorApi
|
||||
from _slsdet import slsDetectorDefs
|
||||
from _slsdet import IpAddr, MacAddr
|
||||
|
||||
runStatus = slsDetectorDefs.runStatus
|
||||
timingMode = slsDetectorDefs.timingMode
|
||||
@ -15,7 +15,7 @@ defs = slsDetectorDefs
|
||||
|
||||
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
|
||||
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
|
||||
from ._slsdet import xy
|
||||
from _slsdet import xy
|
||||
from .gaincaps import Mythen3GainCapsWrapper
|
||||
from . import utils as ut
|
||||
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
|
||||
@ -274,7 +274,7 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
def serialnumber(self):
|
||||
"""Jungfrau][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
||||
"""Jungfrau][Gotthard][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
||||
return ut.lhex(self.getSerialNumber())
|
||||
|
||||
@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
|
||||
[Mythen3] Options: 8, 16, 32 \n
|
||||
[Jungfrau][Moench][Ctb][Mythen3][Gotthard2][Xilinx Ctb] 16
|
||||
[Jungfrau][Moench][Gotthard][Ctb][Mythen3][Gotthard2][Xilinx Ctb] 16
|
||||
"""
|
||||
return self.getDynamicRange()
|
||||
|
||||
@ -372,6 +372,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
[Eiger] Use threshold command to load settings
|
||||
[Jungfrau] GAIN0, HIGHGAIN0 \n
|
||||
[Gotthard] DYNAMICGAIN, HIGHGAIN, LOWGAIN, MEDIUMGAIN, VERYHIGHGAIN \n
|
||||
[Gotthard2] DYNAMICGAIN, FIXGAIN1, FIXGAIN2 \n
|
||||
[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
|
||||
@ -403,7 +404,7 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def framesl(self):
|
||||
"""
|
||||
[Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of frames left in acquisition.\n
|
||||
[Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of frames left in acquisition.\n
|
||||
|
||||
Note
|
||||
----
|
||||
@ -634,7 +635,7 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def periodl(self):
|
||||
"""
|
||||
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Period left for current frame.
|
||||
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Period left for current frame.
|
||||
|
||||
Note
|
||||
-----
|
||||
@ -656,7 +657,7 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def delay(self):
|
||||
"""
|
||||
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay after trigger, accepts either a value in seconds, DurationWrapper or datetime.timedelta
|
||||
[Gotthard][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
|
||||
|
||||
@ -698,7 +699,7 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def delayl(self):
|
||||
"""
|
||||
[Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay left after trigger during acquisition, accepts either a value in seconds, datetime.timedelta or DurationWrapper
|
||||
[Gotthard][Jungfrau][Moench][CTB][Mythen3][Gotthard2][Xilinx Ctb] Delay left after trigger during acquisition, accepts either a value in seconds, datetime.timedelta or DurationWrapper
|
||||
|
||||
Note
|
||||
-----
|
||||
@ -1443,6 +1444,8 @@ class Detector(CppDetectorApi):
|
||||
@udp_srcip.setter
|
||||
def udp_srcip(self, ip):
|
||||
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 = ut.make_ip(ip)
|
||||
ut.set_using_dict(self.setSourceUDPIP, ip)
|
||||
@ -1523,6 +1526,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
Note
|
||||
-----
|
||||
[Gotthard] 0, 90, 110, 120, 150, 180, 200 \n
|
||||
[Eiger][Mythen3][Gotthard2] 0 - 200 \n
|
||||
[Jungfrau][Moench][Ctb] 0, 60 - 200
|
||||
"""
|
||||
@ -1650,7 +1654,7 @@ class Detector(CppDetectorApi):
|
||||
def master(self):
|
||||
"""
|
||||
[Eiger][Gotthard2][Jungfrau][Moench] Sets (half) module to master and other(s) to slaves.\n
|
||||
[Gotthard2][Mythen3][Eiger][Jungfrau][Moench] Gets if the current (half) module is master.
|
||||
[Gotthard][Gotthard2][Mythen3][Eiger][Jungfrau][Moench] Gets if the current (half) module is master.
|
||||
"""
|
||||
return self.getMaster()
|
||||
|
||||
@ -1908,7 +1912,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
@property
|
||||
def adcreg(self):
|
||||
"""[Jungfrau][Moench][Ctb] Writes to an adc register
|
||||
"""[Jungfrau][Moench][Ctb][Gotthard] Writes to an adc register
|
||||
|
||||
Note
|
||||
-----
|
||||
@ -1937,7 +1941,7 @@ class Detector(CppDetectorApi):
|
||||
@element
|
||||
def triggersl(self):
|
||||
"""
|
||||
[Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of triggers left in acquisition.\n
|
||||
[Gotthard][Jungfrau][Moench][Mythen3][Gotthard2][CTB][Xilinx CTB] Number of triggers left in acquisition.\n
|
||||
|
||||
Note
|
||||
----
|
||||
@ -2202,7 +2206,7 @@ class Detector(CppDetectorApi):
|
||||
Note
|
||||
-----
|
||||
Default: AUTO_TIMING \n
|
||||
[Jungfrau][Moench][Ctb][Gotthard2][Xilinx Ctb] AUTO_TIMING, TRIGGER_EXPOSURE \n
|
||||
[Jungfrau][Moench][Gotthard][Ctb][Gotthard2][Xilinx Ctb] AUTO_TIMING, TRIGGER_EXPOSURE \n
|
||||
[Mythen3] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, TRIGGER_GATED \n
|
||||
[Eiger] AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER
|
||||
"""
|
||||
@ -2259,7 +2263,7 @@ class Detector(CppDetectorApi):
|
||||
def type(self):
|
||||
""" Returns detector type.
|
||||
Enum: detectorType
|
||||
[EIGER, JUNGFRAU, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD]
|
||||
[EIGER, JUNGFRAU, GOTTHARD, MOENCH, MYTHEN3, GOTTHARD2, CHIPTESTBOARD]
|
||||
|
||||
:setter: Not implemented
|
||||
"""
|
||||
@ -3463,16 +3467,6 @@ class Detector(CppDetectorApi):
|
||||
def rx_dbitoffset(self, 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
|
||||
@element
|
||||
def maxadcphaseshift(self):
|
||||
@ -3485,13 +3479,15 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
def adcphase(self):
|
||||
"""[Jungfrau][Moench][CTB] Sets phase shift of ADC clock.
|
||||
"""[Gotthard][Jungfrau][Moench][CTB] Sets phase shift of ADC clock.
|
||||
|
||||
Note
|
||||
-----
|
||||
[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.
|
||||
[Ctb] Absolute phase shift. Changing adcclk also resets adcphase and sets it to previous values.\n
|
||||
[Gotthard] Relative phase shift.
|
||||
|
||||
:getter: Not implemented for Gotthard
|
||||
"""
|
||||
return self.getADCPhase()
|
||||
|
||||
@ -3708,12 +3704,6 @@ class Detector(CppDetectorApi):
|
||||
"""
|
||||
[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
|
||||
-------
|
||||
>>> d.patwaittime[0] = 5
|
||||
@ -3723,85 +3713,41 @@ class Detector(CppDetectorApi):
|
||||
0: 5
|
||||
1: 20
|
||||
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)
|
||||
|
||||
|
||||
def create_patwaittime_property(level):
|
||||
docstring_template ="""
|
||||
Deprecated command. Use patwaittime instead.
|
||||
[Ctb][Mythen3][Xilinx Ctb] Wait time in clock cycles of loop level {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
|
||||
-------
|
||||
>>> d.patwaittime{level} = 5
|
||||
>>> d.patwaittime{level}
|
||||
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)
|
||||
def patwaittime0(self):
|
||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 0 time in clock cycles."""
|
||||
return self.getPatternWaitTime(0)
|
||||
|
||||
@patwaittime.setter
|
||||
def patwaittime(self, value):
|
||||
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
||||
nclk = ut.merge_args(level, value)
|
||||
ut.set_using_dict(self.setPatternWaitClocks, level, *nclk)
|
||||
else:
|
||||
ut.set_time_using_dict(self.setPatternWaitInterval, level, value)
|
||||
@patwaittime0.setter
|
||||
def patwaittime0(self, nclk):
|
||||
nclk = ut.merge_args(0, nclk)
|
||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
||||
|
||||
patwaittime.__doc__ = docstring_template.format(level=level)
|
||||
@property
|
||||
@element
|
||||
def patwaittime1(self):
|
||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 1 time in clock cycles."""
|
||||
return self.getPatternWaitTime(1)
|
||||
|
||||
return patwaittime
|
||||
@patwaittime1.setter
|
||||
def patwaittime1(self, nclk):
|
||||
nclk = ut.merge_args(1, nclk)
|
||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
||||
|
||||
patwaittime0 = create_patwaittime_property(0)
|
||||
patwaittime1 = create_patwaittime_property(1)
|
||||
patwaittime2 = create_patwaittime_property(2)
|
||||
@property
|
||||
@element
|
||||
def patwaittime2(self):
|
||||
"""[Ctb][Mythen3][Xilinx Ctb] Wait 2 time in clock cycles."""
|
||||
return self.getPatternWaitTime(2)
|
||||
|
||||
@patwaittime2.setter
|
||||
def patwaittime2(self, nclk):
|
||||
nclk = ut.merge_args(2, nclk)
|
||||
ut.set_using_dict(self.setPatternWaitTime, *nclk)
|
||||
|
||||
|
||||
@property
|
||||
@ -4092,6 +4038,27 @@ class Detector(CppDetectorApi):
|
||||
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>>>---------------------------
|
||||
|
@ -11,7 +11,7 @@ Created on Wed Dec 6 11:51:18 2017
|
||||
from .detector import Detector
|
||||
from .temperature import Temperature, DetectorTemperature
|
||||
from .dacs import DetectorDacs
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
@ -15,8 +15,8 @@ if dt === detectorType.EIGER:
|
||||
"""
|
||||
|
||||
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
for name, cls in _slsdet.slsDetectorDefs.__dict__.items():
|
||||
if isinstance(cls, type):
|
||||
exec(f'{name} = _slsdet.{cls.__qualname__}')
|
||||
exec(f'{name} = {cls.__module__}.{cls.__qualname__}')
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
gc = _slsdet.slsDetectorDefs.M3_GainCaps
|
||||
|
||||
|
||||
|
53
python/slsdet/gotthard.py
Normal file
53
python/slsdet/gotthard.py
Normal file
@ -0,0 +1,53 @@
|
||||
# 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
|
||||
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
|
@ -11,7 +11,7 @@ from .detector import Detector, freeze
|
||||
|
||||
# from .adcs import Adc, DetectorAdcs
|
||||
from .dacs import DetectorDacs
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
@ -11,7 +11,7 @@ from .detector import Detector, freeze
|
||||
|
||||
# from .adcs import Adc, DetectorAdcs
|
||||
from .dacs import DetectorDacs
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
@ -9,7 +9,7 @@ This file contains the specialization for the Moench detector
|
||||
|
||||
from .detector import Detector, freeze
|
||||
from .dacs import DetectorDacs
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
@ -11,7 +11,7 @@ from .detector import Detector, freeze
|
||||
|
||||
# from .adcs import Adc, DetectorAdcs
|
||||
from .dacs import DetectorDacs
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps
|
||||
from .detector_property import DetectorProperty
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
|
||||
from ._slsdet import Pattern
|
||||
from _slsdet import Pattern
|
||||
|
||||
|
||||
class patternParameters(_slsdet.patternParameters):
|
||||
|
@ -3,7 +3,7 @@
|
||||
from .detector_property import DetectorProperty
|
||||
from functools import partial
|
||||
import numpy as np
|
||||
from . import _slsdet
|
||||
import _slsdet
|
||||
from .detector import freeze
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
class Power(DetectorProperty):
|
||||
|
@ -3,7 +3,7 @@
|
||||
from .utils import element_if_equal
|
||||
from .enums import dacIndex
|
||||
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
|
||||
from ._slsdet import slsDetectorDefs
|
||||
from _slsdet import slsDetectorDefs
|
||||
detectorType = slsDetectorDefs.detectorType
|
||||
|
||||
|
||||
@ -275,13 +275,10 @@ class PatWaitTimeProxy:
|
||||
self.det = det
|
||||
|
||||
def __getitem__(self, key):
|
||||
return element_if_equal(self.det.getPatternWaitClocks(key))
|
||||
return element_if_equal(self.det.getPatternWaitTime(key))
|
||||
|
||||
def __setitem__(self, 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)
|
||||
set_proxy_using_dict(self.det.setPatternWaitTime, key, value)
|
||||
|
||||
def __repr__(self):
|
||||
max_levels = MAX_PATTERN_LEVELS
|
||||
|
@ -6,7 +6,7 @@ but not directly used in controlling the detector
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
from . import _slsdet #C++ lib
|
||||
import _slsdet #C++ lib
|
||||
import functools
|
||||
import datetime as dt
|
||||
import pathlib
|
||||
|
@ -1293,6 +1293,20 @@ void init_det(py::module &m) {
|
||||
(void (Detector::*)(defs::collectionMode, sls::Positions)) &
|
||||
Detector::setCollectionMode,
|
||||
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",
|
||||
(Result<int64_t>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getNumberOfBursts,
|
||||
@ -1664,14 +1678,6 @@ void init_det(py::module &m) {
|
||||
(void (Detector::*)(int, sls::Positions)) &
|
||||
Detector::setRxDbitOffset,
|
||||
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",
|
||||
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
||||
Detector::setDigitalIODelay,
|
||||
@ -1855,22 +1861,13 @@ void init_det(py::module &m) {
|
||||
Detector::setPatternWaitAddr,
|
||||
py::arg(), py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"getPatternWaitClocks",
|
||||
"getPatternWaitTime",
|
||||
(Result<uint64_t>(Detector::*)(int, sls::Positions) const) &
|
||||
Detector::getPatternWaitClocks,
|
||||
Detector::getPatternWaitTime,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("setPatternWaitClocks",
|
||||
CppDetectorApi.def("setPatternWaitTime",
|
||||
(void (Detector::*)(int, uint64_t, sls::Positions)) &
|
||||
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,
|
||||
Detector::setPatternWaitTime,
|
||||
py::arg(), py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getPatternMask",
|
||||
(Result<uint64_t>(Detector::*)(sls::Positions)) &
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <chrono>
|
||||
#include "py_headers.h"
|
||||
|
||||
#include "DurationWrapper.h"
|
||||
@ -20,25 +19,4 @@ void init_duration(py::module &m) {
|
||||
<< " count: " << self.count() << ")";
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
m.def(
|
||||
"test_return_DurationWrapper",
|
||||
[]() {
|
||||
DurationWrapper t(1.3);
|
||||
return t;
|
||||
},
|
||||
R"(
|
||||
Test function to return a DurationWrapper object. Ensures that the automatic conversion in typecaster.h works.
|
||||
)");
|
||||
|
||||
m.def(
|
||||
"test_duration_to_ns",
|
||||
[](const std::chrono::nanoseconds t) {
|
||||
//Duration wrapper is used to be able to convert from time in python to chrono::nanoseconds
|
||||
//return count to have something to test
|
||||
return t.count();
|
||||
},
|
||||
R"(
|
||||
Test function convert DurationWrapper or number to chrono::ns. Ensures that the automatic conversion in typecaster.h works.
|
||||
)"); // default value to test the default constructor
|
||||
}
|
||||
|
@ -121,9 +121,13 @@ void init_enums(py::module &m) {
|
||||
.value("VTHRESHOLD", slsDetectorDefs::dacIndex::VTHRESHOLD)
|
||||
.value("IO_DELAY", slsDetectorDefs::dacIndex::IO_DELAY)
|
||||
.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("VCASC_OUT", slsDetectorDefs::dacIndex::VCASC_OUT)
|
||||
.value("VIN_CM", slsDetectorDefs::dacIndex::VIN_CM)
|
||||
.value("VREF_COMP", slsDetectorDefs::dacIndex::VREF_COMP)
|
||||
.value("IB_TESTC", slsDetectorDefs::dacIndex::IB_TESTC)
|
||||
.value("VB_COMP", slsDetectorDefs::dacIndex::VB_COMP)
|
||||
.value("VDD_PROT", slsDetectorDefs::dacIndex::VDD_PROT)
|
||||
.value("VIN_COM", slsDetectorDefs::dacIndex::VIN_COM)
|
||||
|
@ -20,10 +20,8 @@ void init_pattern(py::module &m) {
|
||||
});
|
||||
|
||||
py::class_<sls::Pattern> Pattern(m, "Pattern");
|
||||
Pattern.def(py::init())
|
||||
.def("load", &sls::Pattern::load)
|
||||
.def("save", &sls::Pattern::save)
|
||||
.def("str", &sls::Pattern::str)
|
||||
.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
||||
Pattern.def(py::init());
|
||||
Pattern.def("load", &sls::Pattern::load);
|
||||
Pattern.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
|
||||
py::return_value_policy::reference);
|
||||
}
|
||||
|
@ -54,16 +54,11 @@ template <> struct type_caster<std::chrono::nanoseconds> {
|
||||
value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr())));
|
||||
return true;
|
||||
}
|
||||
// If invoked with an int we assume it is nanoseconds and convert, same as in chrono.h
|
||||
if (PyLong_Check(src.ptr())) {
|
||||
value = duration_cast<nanoseconds>(duration<int64_t>(PyLong_AsLongLong(src.ptr())));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Lastly if we were actually called with a DurationWrapper object we get
|
||||
// the number of nanoseconds and create a std::chrono::nanoseconds from it
|
||||
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
|
||||
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper");
|
||||
if (py::isinstance(src, py_cls)){
|
||||
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
|
||||
value = nanoseconds(cls->count());
|
||||
@ -82,7 +77,7 @@ template <> struct type_caster<std::chrono::nanoseconds> {
|
||||
* set the count from chrono::nanoseconds and return
|
||||
*/
|
||||
static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) {
|
||||
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
|
||||
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper");
|
||||
py::object* obj = new py::object;
|
||||
*obj = py_cls();
|
||||
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();
|
||||
|
@ -1,58 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from slsdet import DurationWrapper
|
||||
|
||||
#import the compiled extension to use test functions for the automatic conversion
|
||||
from slsdet import _slsdet
|
||||
|
||||
|
||||
def test_default_construction_of_DurationWrapper():
|
||||
"""Test default construction of DurationWrapper"""
|
||||
t = DurationWrapper()
|
||||
assert t.count() == 0
|
||||
assert t.total_seconds() == 0
|
||||
|
||||
def test_construction_of_DurationWrapper():
|
||||
"""Test construction of DurationWrapper with total_seconds"""
|
||||
t = DurationWrapper(5)
|
||||
assert t.count() == 5e9
|
||||
assert t.total_seconds() == 5
|
||||
|
||||
def test_set_count_on_DurationWrapper():
|
||||
"""Test set_count on DurationWrapper"""
|
||||
t = DurationWrapper()
|
||||
t.set_count(10)
|
||||
assert t.count() == 10
|
||||
assert t.total_seconds() == 10e-9
|
||||
t.set_count(0)
|
||||
assert t.count() == 0
|
||||
assert t.total_seconds() == 0
|
||||
|
||||
|
||||
def test_return_a_DurationWrapper_from_cpp():
|
||||
"""Test returning a DurationWrapper from C++"""
|
||||
t = _slsdet.test_return_DurationWrapper()
|
||||
assert t.count() == 1.3e9
|
||||
assert t.total_seconds() == 1.3
|
||||
|
||||
def test_call_a_cpp_function_with_a_duration_wrapper():
|
||||
"""C++ functions can accept a DurationWrapper"""
|
||||
t = DurationWrapper(5)
|
||||
assert _slsdet.test_duration_to_ns(t) == 5e9
|
||||
|
||||
def test_call_a_cpp_function_converting_number_to_DurationWrapper():
|
||||
"""int and float can be converted to std::chrono::nanoseconds"""
|
||||
assert _slsdet.test_duration_to_ns(0) == 0
|
||||
assert _slsdet.test_duration_to_ns(3) == 3e9
|
||||
assert _slsdet.test_duration_to_ns(1.3) == 1.3e9
|
||||
assert _slsdet.test_duration_to_ns(10e-9) == 10
|
||||
|
||||
def test_call_a_cpp_function_with_datetime_timedelta():
|
||||
"""datetime.timedelta can be converted to std::chrono::nanoseconds"""
|
||||
import datetime
|
||||
t = datetime.timedelta(seconds=5)
|
||||
assert _slsdet.test_duration_to_ns(t) == 5e9
|
||||
t = datetime.timedelta(seconds=0)
|
||||
assert _slsdet.test_duration_to_ns(t) == 0
|
||||
t = datetime.timedelta(seconds=1.3)
|
||||
assert _slsdet.test_duration_to_ns(t) == 1.3e9
|
@ -1,152 +0,0 @@
|
||||
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]
|
@ -1,50 +0,0 @@
|
||||
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 +0,0 @@
|
||||
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer
|
1
serverBin/ctbDetectorServerv9.1.0
Symbolic link
1
serverBin/ctbDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer
|
1
serverBin/eigerDetectorServerv9.0.0
Symbolic link
1
serverBin/eigerDetectorServerv9.0.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServerv9.0.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer
|
1
serverBin/gotthard2DetectorServerv9.0.0
Symbolic link
1
serverBin/gotthard2DetectorServerv9.0.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServerv9.0.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer
|
1
serverBin/gotthardDetectorServerv9.0.0
Symbolic link
1
serverBin/gotthardDetectorServerv9.0.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServerv9.0.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer
|
1
serverBin/jungfrauDetectorServerv9.1.0
Symbolic link
1
serverBin/jungfrauDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer
|
1
serverBin/moenchDetectorServerv9.0.0
Symbolic link
1
serverBin/moenchDetectorServerv9.0.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServerv9.0.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer
|
1
serverBin/mythen3DetectorServerv9.1.0
Symbolic link
1
serverBin/mythen3DetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer
|
1
serverBin/xilinx_ctbDetectorServerv9.1.0
Symbolic link
1
serverBin/xilinx_ctbDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.1.0
|
@ -3,14 +3,14 @@
|
||||
#ifndef ANALOGDETECTOR_H
|
||||
#define ANALOGDETECTOR_H
|
||||
|
||||
#include <mutex>
|
||||
//#include <mutex>
|
||||
|
||||
#include "commonModeSubtractionNew.h"
|
||||
#include "ghostSummation.h"
|
||||
#include "pedestalSubtraction.h"
|
||||
#include "sls/tiffIO.h"
|
||||
#include "slsDetectorData.h"
|
||||
#include "slsInterpolation.h"
|
||||
#include "sls/tiffIO.h"
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef ROOTSPECTRUM
|
||||
@ -90,8 +90,6 @@ template <class dataType> class analogDetector {
|
||||
ymin = 0;
|
||||
ymax = ny;
|
||||
fMode = ePedestal;
|
||||
dMode = eInterpolating;
|
||||
// std::cout << "dMode " << dMode << std::endl;
|
||||
thr = 0;
|
||||
myFile = NULL;
|
||||
#ifdef ROOTSPECTRUM
|
||||
@ -113,20 +111,15 @@ template <class dataType> class analogDetector {
|
||||
destructor. Deletes the pdestalSubtraction array and the image
|
||||
*/
|
||||
virtual ~analogDetector() {
|
||||
// std::cout << "#### Debug: Destructing analogDetector! ####"
|
||||
// << std::endl;
|
||||
for (int i = 0; i < ny; i++) {
|
||||
if (stat[i]) { delete[] stat[i]; stat[i] = nullptr; }
|
||||
// delete[] stat[i];
|
||||
delete[] stat[i];
|
||||
/* delete [] pedMean[i]; */
|
||||
/* delete [] pedVariance[i]; */
|
||||
}
|
||||
};
|
||||
/* delete [] pedMean; */
|
||||
/* delete [] pedVariance; */
|
||||
// delete[] stat;
|
||||
// delete[] image;
|
||||
if (stat) { delete[] stat; stat = nullptr; }
|
||||
if (image) { delete[] image; image = nullptr; }
|
||||
delete[] stat;
|
||||
delete[] image;
|
||||
#ifdef ROOTSPECTRUM
|
||||
delete hs;
|
||||
#ifdef ROOTCLUST
|
||||
@ -144,8 +137,6 @@ template <class dataType> class analogDetector {
|
||||
*/
|
||||
analogDetector(analogDetector *orig) {
|
||||
/* copy construction from orig*/
|
||||
// std::cout << "#### Debug: Calling analogDetector cloning method! ####"
|
||||
// << std::endl;
|
||||
det = orig->det;
|
||||
nx = orig->nx;
|
||||
ny = orig->ny;
|
||||
@ -161,8 +152,6 @@ template <class dataType> class analogDetector {
|
||||
thr = orig->thr;
|
||||
// nSigma=orig->nSigma;
|
||||
fMode = orig->fMode;
|
||||
dMode = orig->dMode;
|
||||
// std::cout << "dMode " << dMode << std::endl;
|
||||
myFile = orig->myFile;
|
||||
|
||||
stat = new pedestalSubtraction *[ny];
|
||||
@ -227,75 +216,12 @@ template <class dataType> class analogDetector {
|
||||
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!
|
||||
\returns a clone of the original analog detector
|
||||
*/
|
||||
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
|
||||
multithreading. \param i is to be set \returns current id
|
||||
@ -622,11 +548,6 @@ template <class dataType> class analogDetector {
|
||||
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)
|
||||
\param ix pixel x coordinate
|
||||
@ -645,11 +566,6 @@ template <class dataType> class analogDetector {
|
||||
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
|
||||
\param ix pixel x coordinate
|
||||
@ -1310,7 +1226,7 @@ template <class dataType> class analogDetector {
|
||||
/** gets number of samples for moving average pedestal calculation
|
||||
\returns actual number of samples
|
||||
*/
|
||||
int GetNPedestals(int ix, int iy) const {
|
||||
int GetNPedestals(int ix, int iy) {
|
||||
if (ix >= 0 && ix < nx && iy >= 0 && iy < ny)
|
||||
return stat[iy][ix].GetNPedestals();
|
||||
else
|
||||
|
@ -50,8 +50,6 @@ template <typename Element> class CircularFifo {
|
||||
mutable sem_t data_mutex;
|
||||
mutable sem_t free_mutex;
|
||||
unsigned int increment(unsigned int idx_) const;
|
||||
int id_;
|
||||
int thread_id_;
|
||||
};
|
||||
|
||||
template <typename Element> int CircularFifo<Element>::getDataValue() const {
|
||||
@ -76,18 +74,14 @@ template <typename Element> int CircularFifo<Element>::getFreeValue() const {
|
||||
template <typename Element>
|
||||
bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
|
||||
// check for fifo full
|
||||
if (no_block && isFull()) {
|
||||
//std::cout << "Full Fifo at push. Returning." << std::endl;
|
||||
return false; // No space, return immediately
|
||||
}
|
||||
if (no_block && isFull())
|
||||
return false;
|
||||
|
||||
//std::cout << "Thread " << thread_id_ <<" Push Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
|
||||
|
||||
sem_wait(&free_mutex); // Wait for space
|
||||
array[tail] = item_; // Add item to the buffer
|
||||
tail = increment(tail); // Move the tail pointer
|
||||
sem_post(&data_mutex); // Signal that there is new data
|
||||
return true; // Success
|
||||
sem_wait(&free_mutex);
|
||||
array[tail] = item_;
|
||||
tail = increment(tail);
|
||||
sem_post(&data_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Consumer only: Removes and returns item from the queue
|
||||
@ -100,18 +94,14 @@ bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
|
||||
template <typename Element>
|
||||
bool CircularFifo<Element>::pop(Element *&item_, bool no_block) {
|
||||
// check for fifo empty
|
||||
if (no_block && isEmpty()) {
|
||||
//std::cout << "Empty Fifo at pop. Returning." << std::endl;
|
||||
return false; // No data in fifo, return immediately
|
||||
}
|
||||
if (no_block && isEmpty())
|
||||
return false;
|
||||
|
||||
//std::cout << "Thread " << thread_id_ << " Pop Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
|
||||
|
||||
sem_wait(&data_mutex); // Wait for data
|
||||
item_ = array[head]; // Retreive item from the current head of the buffer
|
||||
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
|
||||
sem_wait(&data_mutex);
|
||||
item_ = array[head];
|
||||
head = increment(head);
|
||||
sem_post(&free_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Useful for testinng and Consumer check of status
|
||||
|
@ -1,482 +0,0 @@
|
||||
#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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,159 +0,0 @@
|
||||
#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]{};
|
||||
|
||||
};
|
@ -0,0 +1,155 @@
|
||||
// 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
|
105
slsDetectorCalibration/dataStructures/gotthardShortModuleData.h
Normal file
105
slsDetectorCalibration/dataStructures/gotthardShortModuleData.h
Normal file
@ -0,0 +1,105 @@
|
||||
// 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
|
@ -1,422 +0,0 @@
|
||||
// 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
|
@ -1,432 +0,0 @@
|
||||
// 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,10 +28,6 @@
|
||||
@li version is the version number of this structure format
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
|
||||
namespace strixelSingleChip {
|
||||
constexpr int nc_rawimg = 1024; // for full images //256;
|
||||
constexpr int nr_rawimg = 512;
|
||||
@ -81,7 +77,7 @@ constexpr int c6g1_ystart = c6g2_yend + 1; // 448
|
||||
constexpr int c6g1_yend = c6g2_yend + 64 - gr; // 502
|
||||
|
||||
// y shift due to faulty bonding (relevant for M408)
|
||||
constexpr int bond_shift_y = 0; // CHANGE IF YOU CHANGE MODULE!
|
||||
constexpr int bond_shift_y = 1; // CHANGE IF YOU CHANGE MODULE!
|
||||
|
||||
} // namespace strixelSingleChip
|
||||
|
||||
@ -101,13 +97,6 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
||||
int chip_x0;
|
||||
int chip_y0;
|
||||
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 multiplicator;
|
||||
@ -226,113 +215,9 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
void remapROI(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax) {
|
||||
// determine group and chip selected by ROI
|
||||
int group, xmin, xmax, ymin, ymax;
|
||||
std::tie( mchip, group, xmin, xmax, ymin, ymax ) = roi;
|
||||
/*
|
||||
int group;
|
||||
if (ymax <= c1g1_yend + bond_shift_y) {
|
||||
group = 1;
|
||||
mchip = 1;
|
||||
@ -358,17 +243,18 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
||||
group = -1;
|
||||
mchip = -1;
|
||||
}
|
||||
*/
|
||||
int multiplicator = getMultiplicator(group);
|
||||
setMappingShifts(group);
|
||||
|
||||
std::cout << "remapping chip: " << mchip << ", group: " << group << ", m: " << multiplicator
|
||||
std::cout << "chip: " << mchip << ", group: " << group << ", m: " << multiplicator
|
||||
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
|
||||
<< ", 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
|
||||
/*
|
||||
if (y0 < ymin)
|
||||
std::cout << "Error ymin" << std::endl;
|
||||
if (y1 > ymax)
|
||||
@ -378,7 +264,6 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
||||
std::cout << "Error xmin" << std::endl;
|
||||
if (x1 > xmax)
|
||||
std::cout << "Error xmax" << std::endl;
|
||||
*/
|
||||
|
||||
// remapping loop
|
||||
int ix, iy = 0;
|
||||
@ -392,10 +277,8 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
|
||||
}
|
||||
|
||||
// if (iy< 40) cout << iy << " " << ix <<endl;
|
||||
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);
|
||||
sizeof(header) + (nc_roi * (ipy - ymin) + (ipx - xmin)) * 2;
|
||||
groupmap[iy][ix] = group - 1;
|
||||
}
|
||||
}
|
||||
@ -424,31 +307,16 @@ 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 << "Jungfrau strixels 2X single chip 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;
|
||||
|
||||
//[ 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);
|
||||
remapROI(xmin, xmax, ymin, ymax);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#ifndef JUNGFRAUMODULEDATA_H
|
||||
#define JUNGFRAUMODULEDATA_H
|
||||
#include <cstdint>
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "slsDetectorData.h"
|
||||
|
||||
//#define VERSION_V2
|
||||
@ -28,7 +27,7 @@ typedef struct {
|
||||
uint64_t bunchNumber; /**< is the frame number */
|
||||
uint64_t pre; /**< something */
|
||||
|
||||
} jf_header; //Aldo's header!
|
||||
} jf_header;
|
||||
|
||||
using namespace std;
|
||||
class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
||||
@ -43,56 +42,20 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
||||
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)
|
||||
#define off sizeof(jf_header)
|
||||
#endif
|
||||
#ifdef ZMQ
|
||||
#define off 0
|
||||
#endif
|
||||
|
||||
|
||||
jungfrauModuleData(uint16_t xmin=0, uint16_t xmax=0,
|
||||
uint16_t ymin=0, uint16_t ymax=0)
|
||||
jungfrauModuleData()
|
||||
: slsDetectorData<uint16_t>(1024, 512,
|
||||
1024* 512 * 2 + off) {
|
||||
|
||||
for (int ix = 0; ix != 1024; ++ix) {
|
||||
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) {
|
||||
for (int ix = 0; ix < 1024; ix++) {
|
||||
for (int iy = 0; iy < 512; iy++) {
|
||||
dataMap[iy][ix] = off + (1024 * iy + ix) * 2;
|
||||
#ifdef HIGHZ
|
||||
dataMask[iy][ix] = 0x3fff;
|
||||
@ -100,7 +63,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
iframe = 0;
|
||||
@ -187,7 +150,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
|
||||
//int pn;
|
||||
|
||||
// cout << dataSize << endl;
|
||||
//if (ff >= 0)
|
||||
if (ff >= 0)
|
||||
//fnum = ff;
|
||||
|
||||
if (filebin.is_open()) {
|
||||
|
@ -1,226 +0,0 @@
|
||||
// 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,10 +54,6 @@ class interpolatingDetector : public singlePhotonDetector {
|
||||
pthread_mutex_init(fi, NULL);
|
||||
};
|
||||
|
||||
/**
|
||||
pointer-based copy constructor (cloner)
|
||||
\param orig detector to be copied
|
||||
*/
|
||||
interpolatingDetector(interpolatingDetector *orig)
|
||||
: singlePhotonDetector(orig) {
|
||||
// if (orig->interp)
|
||||
@ -70,28 +66,10 @@ class interpolatingDetector : public singlePhotonDetector {
|
||||
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() {
|
||||
return new interpolatingDetector(this);
|
||||
}
|
||||
|
||||
virtual interpolatingDetector *Copy() {
|
||||
return new interpolatingDetector(*this);
|
||||
}
|
||||
|
||||
virtual int setId(int i) {
|
||||
id = i;
|
||||
// interp->setId(id);
|
||||
|
@ -6,86 +6,18 @@
|
||||
|
||||
set(JUNGFRAU_EXECUTABLES)
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
find_package(fmt REQUIRED)
|
||||
|
||||
# jungfrauRawDataProcess
|
||||
add_executable(jungfrauRawDataProcess jungfrauRawDataProcess.cpp)
|
||||
target_compile_definitions(jungfrauRawDataProcess PRIVATE MODULE)
|
||||
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
|
||||
add_executable(jungfrauRawDataProcessStrx jungfrauRawDataProcess_filetxt.cpp)
|
||||
target_compile_definitions(jungfrauRawDataProcessStrx PRIVATE JFSTRX)
|
||||
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
|
||||
add_executable(jungfrauRawDataProcessStrxChip1 jungfrauRawDataProcess.cpp)
|
||||
@ -126,22 +58,6 @@ list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxOldAldo)
|
||||
# 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})
|
||||
@ -151,16 +67,11 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
../interpolations
|
||||
../dataStructures
|
||||
../interpolations/etaVEL
|
||||
../../slsSupportLib/include/sls/
|
||||
../../slsSupportLib/include/
|
||||
../../slsReceiverSoftware/include/
|
||||
../tiffio/include
|
||||
${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}
|
||||
PUBLIC
|
||||
@ -168,7 +79,6 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
pthread
|
||||
tiffio
|
||||
fmt::fmt
|
||||
nlohmann_json::nlohmann_json
|
||||
#-L/usr/lib64/
|
||||
#-lm -lstdc++ -lrt
|
||||
|
||||
@ -176,11 +86,7 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
slsProjectWarnings
|
||||
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
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
@ -192,8 +98,4 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
|
||||
endforeach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
|
@ -11,7 +11,7 @@
|
||||
#define RAWDATA
|
||||
|
||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||
!defined JFSTRXCHIP6 && !defined CHIP
|
||||
!defined JFSTRXCHIP6
|
||||
#ifndef MODULE
|
||||
#include "jungfrauHighZSingleChipData.h"
|
||||
#endif
|
||||
@ -20,10 +20,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CHIP
|
||||
#include "jungfrauSingleChipData.h"
|
||||
#endif
|
||||
|
||||
#ifdef JFSTRX
|
||||
#include "jungfrauLGADStrixelsData_new.h"
|
||||
#endif
|
||||
@ -45,9 +41,6 @@
|
||||
#include <ctime>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
||||
std::string getRootString( const std::string& filepath ) {
|
||||
size_t pos1 = filepath.find_last_of("/");
|
||||
@ -68,24 +61,20 @@ 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 ) {
|
||||
if (outfilecounter >= 0)
|
||||
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) {
|
||||
if (fsuffix == "master")
|
||||
return fmt::format("{:s}/{:s}_master_{:d}.{:s}", dir, fprefix, aindex, fext);
|
||||
else
|
||||
else if (fsuffix.length()!=0)
|
||||
return fmt::format("{:s}/{:s}_{:s}.{:s}", dir, fprefix, fsuffix, fext);
|
||||
}
|
||||
else
|
||||
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}.{:s}", dir, fprefix, mindex, findex, aindex, fext);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc < 6) {
|
||||
if (argc < 5) {
|
||||
std::cout
|
||||
<< "Usage is " << argv[0]
|
||||
<< "indir outdir [fprefix(excluding slsDetector standard suffixes and extension)] [fextension] "
|
||||
"[fmin] [fmax] [runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
|
||||
"[nframes] [xmin xmax ymin ymax] [optional: bool read rxroi from data file header] [gainmap]"
|
||||
<< "indir outdir fprefix(excluding slsDetector standard suffixes and extension) fextension "
|
||||
"[runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
|
||||
"[nframes] [xmin xmax ymin ymax] [gainmap]"
|
||||
<< std::endl;
|
||||
std::cout
|
||||
<< "threshold <0 means analog; threshold=0 means cluster finder; "
|
||||
@ -117,95 +106,58 @@ int main(int argc, char *argv[]) {
|
||||
std::string outdir(argv[2]);
|
||||
std::string fprefix(argv[3]);
|
||||
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;
|
||||
|
||||
// cout << "argc is " << argc << endl;
|
||||
if (argc >= 8) {
|
||||
runmin = atoi(argv[7]);
|
||||
if (argc >= 6) {
|
||||
runmin = atoi(argv[5]);
|
||||
}
|
||||
|
||||
int runmax = runmin;
|
||||
if (argc >= 9) {
|
||||
runmax = atoi(argv[8]);
|
||||
|
||||
if (argc >= 7) {
|
||||
runmax = atoi(argv[6]);
|
||||
}
|
||||
|
||||
std::string pedfilename{};
|
||||
if (argc >= 10) {
|
||||
pedfilename = argv[9];
|
||||
if (argc >= 8) {
|
||||
pedfilename = argv[7];
|
||||
}
|
||||
double thr = 0;
|
||||
double thr1 = 1;
|
||||
|
||||
if (argc >= 11) {
|
||||
thr = atof(argv[10]);
|
||||
if (argc >= 9) {
|
||||
thr = atof(argv[8]);
|
||||
}
|
||||
|
||||
int nframes = 0;
|
||||
|
||||
if (argc >= 12) {
|
||||
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;
|
||||
|
||||
if (argc >= 10) {
|
||||
nframes = atoi(argv[9]);
|
||||
}
|
||||
|
||||
// Define decoders...
|
||||
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
|
||||
!defined JFSTRXCHIP6 && !defined CHIP
|
||||
!defined JFSTRXCHIP6
|
||||
#ifndef MODULE
|
||||
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
|
||||
int nx = 256, ny = 256;
|
||||
#endif
|
||||
#ifdef MODULE
|
||||
jungfrauModuleData *decoder = new jungfrauModuleData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||
jungfrauModuleData *decoder = new jungfrauModuleData();
|
||||
int nx = 1024, ny = 512;
|
||||
#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
|
||||
std::cout << "Jungfrau strixel full module readout" << std::endl;
|
||||
cout << "Jungfrau strixel full module readout" << endl;
|
||||
// ROI
|
||||
uint16_t xxmin = 0;
|
||||
uint16_t xxmax = 0;
|
||||
uint16_t yymin = 0;
|
||||
uint16_t yymax = 0;
|
||||
|
||||
#ifndef ALDO
|
||||
if (readrxroifromdatafile)
|
||||
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
|
||||
using header = sls::defs::sls_receiver_header;
|
||||
// check if there is a roi in the header
|
||||
@ -228,10 +180,10 @@ int main(int argc, char *argv[]) {
|
||||
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
|
||||
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
|
||||
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
|
||||
rxroi_xmin = croi.xmin;
|
||||
rxroi_xmax = croi.xmax;
|
||||
rxroi_ymin = croi.ymin;
|
||||
rxroi_ymax = croi.ymax;
|
||||
xxmin = croi.xmin;
|
||||
xxmax = croi.xmax;
|
||||
yymin = croi.ymin;
|
||||
yymax = croi.ymax;
|
||||
} else
|
||||
std::cout << "reading error" << std::endl;
|
||||
firstfile.close();
|
||||
@ -241,7 +193,7 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
|
||||
jungfrauLGADStrixelsData *decoder =
|
||||
new jungfrauLGADStrixelsData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
|
||||
new jungfrauLGADStrixelsData(xxmin, xxmax, yymin, yymax);
|
||||
int nx = 1024 / 3, ny = 512 * 5;
|
||||
#endif
|
||||
#ifdef JFSTRXCHIP1
|
||||
@ -266,20 +218,19 @@ int main(int argc, char *argv[]) {
|
||||
decoder->getDetectorSize(nx, ny);
|
||||
std::cout << "Detector size is " << nx << " " << ny << std::endl;
|
||||
|
||||
//Cluster finder ROI
|
||||
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
|
||||
if (argc >= 16) {
|
||||
xmin = atoi(argv[12]);
|
||||
xmax = atoi(argv[13]);
|
||||
ymin = atoi(argv[14]);
|
||||
ymax = atoi(argv[15]);
|
||||
int xmin = 0, xmax = nx, ymin = 0, ymax = ny;
|
||||
if (argc >= 14) {
|
||||
xmin = atoi(argv[10]);
|
||||
xmax = atoi(argv[11]);
|
||||
ymin = atoi(argv[12]);
|
||||
ymax = atoi(argv[13]);
|
||||
}
|
||||
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
|
||||
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
|
||||
<< std::endl;
|
||||
|
||||
char *gainfname = NULL;
|
||||
if (argc > 17) {
|
||||
gainfname = argv[17];
|
||||
if (argc > 14) {
|
||||
gainfname = argv[14];
|
||||
std::cout << "Gain map file name is: " << gainfname << std::endl;
|
||||
}
|
||||
|
||||
@ -288,8 +239,6 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "input directory is " << indir << std::endl;
|
||||
std::cout << "output directory is " << outdir << 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 << "runmax is " << runmax << std::endl;
|
||||
if (pedfilename.length()!=0)
|
||||
@ -370,7 +319,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
mt->setFrameMode(ePedestal);
|
||||
|
||||
std::ifstream pedefile(fname, ios::in | ios::binary);
|
||||
ifstream pedefile(fname, ios::in | ios::binary);
|
||||
// //open file
|
||||
if (pedefile.is_open()) {
|
||||
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
|
||||
@ -431,27 +380,26 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
ifr = 0;
|
||||
int ioutfile = 0;
|
||||
int ifile = 0;
|
||||
|
||||
mt->setFrameMode(eFrame);
|
||||
|
||||
FILE *of = NULL;
|
||||
|
||||
for (int irun = runmin; irun <= runmax; ++irun) {
|
||||
for (int ifile = fmin; ifile <= fmax; ++ifile) {
|
||||
for (int irun = runmin; irun <= runmax; irun++) {
|
||||
std::cout << "DATA ";
|
||||
std::string fsuffix{};
|
||||
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun, 0, ifile );
|
||||
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, ifile );
|
||||
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun, 0, ifile );
|
||||
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun );
|
||||
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun );
|
||||
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun );
|
||||
std::cout << fname << " ";
|
||||
std::cout << imgfname << std::endl;
|
||||
std::time(&end_time);
|
||||
std::cout << std::ctime(&end_time) << std::endl;
|
||||
// std::cout << fname << " " << outfname << " " << imgfname << std::endl;
|
||||
std::ifstream filebin(fname, ios::in | ios::binary);
|
||||
ifstream filebin(fname, ios::in | ios::binary);
|
||||
// //open file
|
||||
ioutfile = 0;
|
||||
ifile = 0;
|
||||
if (filebin.is_open()) {
|
||||
if (thr <= 0 && cf != 0) { // cluster finder
|
||||
if (of == NULL) {
|
||||
@ -488,10 +436,10 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << " " << ifr << " " << ff << std::endl;
|
||||
if (nframes > 0) {
|
||||
if (ifr % nframes == 0) {
|
||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
|
||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
|
||||
mt->writeImage(imgfname.c_str(), thr1);
|
||||
mt->clearImage();
|
||||
ioutfile++;
|
||||
ifile++;
|
||||
}
|
||||
}
|
||||
// } else
|
||||
@ -505,7 +453,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
if (nframes >= 0) {
|
||||
if (nframes > 0)
|
||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
|
||||
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
|
||||
std::cout << "Writing tiff to " << imgfname << " " << thr1
|
||||
<< std::endl;
|
||||
mt->writeImage(imgfname.c_str(), thr1);
|
||||
@ -522,9 +470,8 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "Could not open " << fname << " for reading "
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
if (nframes < 0) {
|
||||
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", runmin, 0, fmin, -1 );
|
||||
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", -1, 0, 0, -1 );
|
||||
std::cout << "Writing tiff to " << imgfname << " " << thr1 << std::endl;
|
||||
mt->writeImage(imgfname.c_str(), thr1);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user