mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-14 13:57:13 +02:00
Compare commits
280 Commits
moench8.0.
...
dev/fix_m3
Author | SHA1 | Date | |
---|---|---|---|
dae88ad689 | |||
7c232cbd48 | |||
f4219ac879 | |||
e54ffa9904 | |||
d174d9a2ec | |||
c92830f854 | |||
e77fd8d85d | |||
cd0fb1b7bb | |||
50ab20317d | |||
d0a946a919 | |||
ed142aa34e | |||
1227574590 | |||
3ac7b579a0 | |||
feb1b0868e | |||
6d2f34ef1d | |||
b36a5b9933 | |||
d8ce5eabb8 | |||
ceecb0ca27 | |||
ac3670dcd2 | |||
1c7bc61531 | |||
58245a62a4 | |||
a464262558 | |||
995d3e0034 | |||
90d57cb6a9 | |||
30eab42294 | |||
1d0eeea7ee | |||
d7c012d306 | |||
1665937540 | |||
9343e3c667 | |||
b4c8fc1765 | |||
3ad4e01a5d | |||
015b4add65 | |||
9051dae787 | |||
68bdd75c9c | |||
a53873b695 | |||
77a39b4ef2 | |||
64be8b1e89 | |||
68bd9fb4f7 | |||
0d5d851585 | |||
eb3d51d20c | |||
9f4298ac15 | |||
fb79ba768c | |||
7bc48e3111 | |||
53b90d92d7 | |||
fb6ef8b818 | |||
8bb9de0de1 | |||
451b50dfed | |||
22f2662e3b | |||
ce3f555c08 | |||
dedab6010d | |||
62a5fda33f | |||
5073769403 | |||
aabec193ff | |||
d4a1044fce | |||
dca0edcfcc | |||
5a24a79bf7 | |||
91f9c4fa83 | |||
3940d6f56e | |||
f09879a46c | |||
1b0e891912 | |||
292d65491a | |||
36faec6ad3 | |||
062002243e | |||
98b1e287a4 | |||
adf0124ea3 | |||
e1f46d4747 | |||
d8c3fa0df3 | |||
27530fca31 | |||
cc7f13a10e | |||
625f4353fb | |||
2815913d10 | |||
5fa2402ec5 | |||
4d7d3c9138 | |||
c3f1d05033 | |||
0e4cb7cbcd | |||
bace9edf89 | |||
99735c3ee5 | |||
2571397c70 | |||
497c3abfc2 | |||
fca31cc432 | |||
8fe4a78feb | |||
ee170fa2e0 | |||
da760b2b93 | |||
2c8c2a46ea | |||
9625a8058c | |||
4d8bdae836 | |||
3297707ab7 | |||
598154645c | |||
9d8f9a9ba9 | |||
68f163b757 | |||
b8c5bb2045 | |||
b45df191e5 | |||
01cc745787 | |||
f9bc2eb126 | |||
4c86ad3198 | |||
5be0724f82 | |||
7c652498e4 | |||
721d536350 | |||
361437428d | |||
aadbfeaf2d | |||
f119d14e7c | |||
f8b12201f8 | |||
585c92be66 | |||
7c8639b8ae | |||
a138b5b365 | |||
9fde62ae30 | |||
29fe988583 | |||
6740d9b363 | |||
1d1b55b864 | |||
c32732b22e | |||
1e6b6fef0a | |||
5ab2c1693e | |||
0b3cd499a8 | |||
884e17f0c4 | |||
d0ccf236c0 | |||
396b955db7 | |||
5f14eb32aa | |||
cfec7c18ec | |||
04583acb21 | |||
95e11d668a | |||
772e58c743 | |||
470e2633c3 | |||
3312adddd1 | |||
46152d2419 | |||
b5c82783d6 | |||
dc85a48864 | |||
dc8a34592a | |||
96ae1a1cca | |||
3793e7b7d4 | |||
713e4f6822 | |||
fada23365e | |||
6dd0a5b0dd | |||
c3b197f209 | |||
9f49ac6457 | |||
0b3ead6353 | |||
8b3625fc01 | |||
0da508a8b7 | |||
608eb1a436 | |||
c0bc6fe25a | |||
a0d540fd72 | |||
46a46b65e5 | |||
4f62b1a05c | |||
45dadf8b90 | |||
e8e84a4e72 | |||
2f390971e6 | |||
b7e17d1320 | |||
c54b1cb6af | |||
ddb89bce34 | |||
f056f9d31b | |||
d9a50ad9f4 | |||
ce0450d498 | |||
7b531059a0 | |||
bc187bb198 | |||
eb8c34f53b | |||
d9a50705e4 | |||
f4626c2c81 | |||
e0a48e1e75 | |||
ec4eb1978e | |||
842b376801 | |||
13b2cada66 | |||
3c2f149c22 | |||
0a5b5aac4b | |||
6e5b058fc1 | |||
ace2b3a938 | |||
5a8213024e | |||
bd66228b30 | |||
e1c9754cd2 | |||
ff101e19cd | |||
e8ac048114 | |||
3c79e8d7b2 | |||
a74fb2bcd1 | |||
63bb79d727 | |||
8d87a6ee4e | |||
ab01940769 | |||
23aa9c2814 | |||
010f736e80 | |||
4dcbcad435 | |||
8f8a92b9c5 | |||
684eee984d | |||
297c3752e3 | |||
fa504e6675 | |||
b9b4f1ae35 | |||
3c2062f23e | |||
e7247f1fee | |||
905a509a17 | |||
b4dc1dde6c | |||
964ab19b42 | |||
ce8911de10 | |||
d1e5b0bc42 | |||
4b3ed22f76 | |||
aad1ab0cf4 | |||
117637863d | |||
e933a25453 | |||
f1f369b48c | |||
6b149244d3 | |||
436d180e93 | |||
c43a4030a5 | |||
6e826d2840 | |||
315d49f8df | |||
e92578f89d | |||
0e45ae189d | |||
e6e260d8ca | |||
fcc9b6ad54 | |||
0771461c01 | |||
ed6686d4a7 | |||
ec3d3e38a6 | |||
e47d3d4d15 | |||
f9dbffcb6e | |||
e83527adee | |||
dee86c63eb | |||
ce41e8aa34 | |||
7e2c8a37dc | |||
aeb59364c5 | |||
1f16f84fed | |||
0123169e35 | |||
ffd7cd1070 | |||
c6c7632ef7 | |||
b79759bcff | |||
d9e8e1c1c2 | |||
c57e835a41 | |||
b3d9af29fc | |||
4829429abd | |||
f1ffc6057a | |||
8f51215cb3 | |||
7b21ce34d6 | |||
e1497f9cb9 | |||
5088e5a205 | |||
06266f3905 | |||
5f805f8789 | |||
60868ae74e | |||
37e65634d4 | |||
6fcdba56a4 | |||
0b9fd0664e | |||
6add9aad5d | |||
76ab0228ac | |||
a1e69bba37 | |||
270ee48148 | |||
c679135138 | |||
0f88617477 | |||
04eed990c7 | |||
d2bfb91a16 | |||
5e024153bc | |||
e59de85a33 | |||
fd010b9aa5 | |||
45957391a6 | |||
f2f3817a7f | |||
f43bb8eea4 | |||
8a7ed30676 | |||
5b832cb6aa | |||
7fa5b5d70a | |||
6348ccd05b | |||
8144397b2c | |||
2dc0963c56 | |||
a44ba4dc35 | |||
007330caa7 | |||
492b4815a6 | |||
33b8e0817e | |||
ab7425a9d3 | |||
d8f925520e | |||
9f079b17a2 | |||
5b61ff24bb | |||
c6477e0ed6 | |||
38d7fb0c38 | |||
e848293916 | |||
15e8c0d9f1 | |||
588d11dedf | |||
782c8abd9a | |||
1d4a5d6d29 | |||
9c57571a41 | |||
b4533ac11f | |||
991a4115d4 | |||
ff107faae6 | |||
d57643434d | |||
de33aff077 | |||
c13049f144 | |||
ce7f01bdc4 | |||
bf523c0c5e | |||
1efd106c6a | |||
08dc8e3cbb | |||
96f7a1ecfb |
29
.gitea/workflows/rh8-native.yml
Normal file
29
.gitea/workflows/rh8-native.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Build on RHEL8
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel8-detectors-dev
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
echo Cloning ${{ github.ref_name }}
|
||||
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
|
||||
|
||||
- name: Build library
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||
make -j 2
|
||||
|
||||
- name: C++ unit tests
|
||||
working-directory: ${{gitea.workspace}}/build
|
||||
run: ctest
|
27
.gitea/workflows/rh9-native.yml
Normal file
27
.gitea/workflows/rh9-native.yml
Normal file
@ -0,0 +1,27 @@
|
||||
name: Build on RHEL9
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel9-detectors-dev
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Build library
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||
make -j 2
|
||||
|
||||
- name: C++ unit tests
|
||||
working-directory: ${{gitea.workspace}}/build
|
||||
run: ctest
|
@ -1,4 +1,4 @@
|
||||
name: CMake
|
||||
name: Native CMake Build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@ -14,10 +14,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Configure and build using cmake
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
- run: pip install pytest numpy
|
||||
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev
|
||||
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
|
||||
version: 1.0
|
||||
|
||||
- name: Configure CMake
|
||||
@ -27,12 +33,15 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build -j2 --config ${{env.BUILD_TYPE}}
|
||||
run: cmake --build ${{github.workspace}}/build -j4 --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
- name: C++ unit tests
|
||||
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
Normal file
42
.github/workflows/conda_library.yaml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
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
Normal file
42
.github/workflows/conda_python.yaml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
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 +0,0 @@
|
||||
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
|
@ -1,8 +1,16 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(slsDetectorPackage)
|
||||
set(PROJECT_VERSION 7.0.0)
|
||||
|
||||
# Read VERSION file into project version
|
||||
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
||||
file(READ "${VERSION_FILE}" VERSION_CONTENT)
|
||||
string(STRIP "${VERSION_CONTENT}" PROJECT_VERSION_STRING)
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION_STRING})
|
||||
|
||||
# Pass it to the compiler
|
||||
add_compile_definitions(SLS_DET_VERSION="${PROJECT_VERSION}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||
|
||||
@ -13,6 +21,7 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.24")
|
||||
endif()
|
||||
include(cmake/project_version.cmake)
|
||||
include(cmake/SlsAddFlag.cmake)
|
||||
include(cmake/helpers.cmake)
|
||||
|
||||
|
||||
|
||||
@ -21,20 +30,44 @@ 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 verison
|
||||
# using the bundled version
|
||||
FetchContent_Declare(
|
||||
libzmq
|
||||
GIT_REPOSITORY https://github.com/zeromq/libzmq.git
|
||||
GIT_TAG v4.3.4
|
||||
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
|
||||
)
|
||||
else()
|
||||
# Standard behaviour use libzmq included in this repo (libs/libzmq)
|
||||
FetchContent_Declare(
|
||||
libzmq
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-4.3.4.tar.gz
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-${SLS_LIBZMQ_VERSION}.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()
|
||||
|
||||
@ -46,6 +79,11 @@ 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))
|
||||
@ -148,7 +186,6 @@ set(SLS_INTERNAL_QWT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/qwt-6.1.5)
|
||||
set(ClangFormat_EXCLUDE_PATTERNS "build/"
|
||||
"libs/"
|
||||
"slsDetectorCalibration/"
|
||||
"ctbGui/"
|
||||
"manual/"
|
||||
"python/"
|
||||
"sample/"
|
||||
@ -157,11 +194,9 @@ find_package(ClangFormat)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (default Release)" FORCE)
|
||||
endif()
|
||||
|
||||
default_build_type("Release")
|
||||
set_std_fs_lib()
|
||||
message(STATUS "Extra linking to fs lib:${STD_FS_LIB}")
|
||||
|
||||
#Enable LTO if available
|
||||
include(CheckIPOSupported)
|
||||
@ -184,7 +219,7 @@ endif()
|
||||
# to control options for the libraries
|
||||
if(NOT TARGET slsProjectOptions)
|
||||
add_library(slsProjectOptions INTERFACE)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_17)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET slsProjectWarnings)
|
||||
@ -242,8 +277,8 @@ endif()
|
||||
if(SLS_USE_SANITIZER)
|
||||
target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer)
|
||||
target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined)
|
||||
# target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
# target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
#target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread -fno-omit-frame-pointer)
|
||||
#target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
endif()
|
||||
|
||||
|
||||
@ -297,19 +332,21 @@ if (SLS_USE_INTEGRATION_TESTS)
|
||||
endif (SLS_USE_INTEGRATION_TESTS)
|
||||
|
||||
if (SLS_USE_PYTHON)
|
||||
find_package (Python 3.6 COMPONENTS Interpreter Development)
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
||||
set(PYBIND11_FINDPYTHON ON) # Needed for RH8
|
||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
GIT_REPOSITORY https://github.com/pybind/pybind11
|
||||
GIT_TAG v2.11.0
|
||||
GIT_TAG v2.13.6
|
||||
)
|
||||
|
||||
else()
|
||||
# https://github.com/pybind/pybind11/releases
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
URL ${CMAKE_SOURCE_DIR}/libs/pybind11/v2.11.0.tar.gz
|
||||
URL_HASH MD5=90c4946e87c64d8d8fc0ae4edf35d780
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/pybind11/v2.13.6.tar.gz
|
||||
URL_HASH MD5=a04dead9c83edae6d84e2e343da7feeb
|
||||
)
|
||||
endif()
|
||||
FetchContent_MakeAvailable(pybind11)
|
||||
@ -318,12 +355,18 @@ if (SLS_USE_PYTHON)
|
||||
endif(SLS_USE_PYTHON)
|
||||
|
||||
if (SLS_USE_CTBGUI)
|
||||
add_subdirectory(ctbGui)
|
||||
add_subdirectory(pyctbgui)
|
||||
endif(SLS_USE_CTBGUI)
|
||||
|
||||
configure_file( .clang-tidy
|
||||
${CMAKE_BINARY_DIR}/.clang-tidy
|
||||
)
|
||||
# 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)
|
||||
@ -347,4 +390,4 @@ if(SLS_MASTER_PROJECT)
|
||||
set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}")
|
||||
set(PROJECT_LIBRARIES slsSupportShared slsDetectorShared slsReceiverShared)
|
||||
include(cmake/package_config.cmake)
|
||||
endif()
|
||||
endif()
|
124
README.md
124
README.md
@ -2,7 +2,11 @@
|
||||
Before building from source make sure that you have the [software wiki](https://slsdetectorgroup.github.io/devdoc/dependencies.html) installed. If installing using conda, conda will manage the dependencies. Avoid also installing packages with pip.
|
||||
|
||||
## Documentaion
|
||||
Detailed documentation can be found in the [software wiki](https://slsdetectorgroup.github.io/devdoc/index.html) and on the [official site](https://www.psi.ch/en/detectors/software).
|
||||
Detailed documentation including installation can be found in the [software wiki](https://slsdetectorgroup.github.io/devdoc/index.html).
|
||||
|
||||
Different releases can be found on the [official site](https://www.psi.ch/en/lxn/software-releases).
|
||||
|
||||
Firmware compatiblity can be found in [firmware page](https://github.com/slsdetectorgroup/slsDetectorFirmware)
|
||||
|
||||
## Installation
|
||||
|
||||
@ -42,33 +46,20 @@ conda search slsdet
|
||||
conda search slsdetgui
|
||||
```
|
||||
|
||||
### 2. Build from source
|
||||
## 2. Build from source
|
||||
|
||||
##### 2.1 Download Source Code from github
|
||||
### 2.1 Download Source Code from github
|
||||
```
|
||||
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 7.0.0
|
||||
```
|
||||
|
||||
**Pybind for Python**<br>
|
||||
* **v7.0.0+**:
|
||||
pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
||||
|
||||
* **Older versions**:
|
||||
pybind11 is a submodule. Must be cloned using "recursive" and updated when switching between versions using the following commands.
|
||||
|
||||
```
|
||||
# clone using recursive to get pybind11 submodule
|
||||
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
|
||||
|
||||
# update submodule when switching between releases
|
||||
cd slsDetectorPackage
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
##### 2.2 Build from source
|
||||
> **Note:** For v6.x.x of slsDetectorPackage and older, refer [pybind11 notes on cloning](#Pybind-and-Zeromq).
|
||||
|
||||
|
||||
###### Build using CMake
|
||||
### 2.2 Build from source
|
||||
|
||||
|
||||
### Build using CMake
|
||||
|
||||
```
|
||||
# outside slsDetecorPackage folder
|
||||
@ -94,26 +85,28 @@ Instead of the cmake command, one can use ccmake to get a list of options to con
|
||||
ccmake ..
|
||||
|
||||
# choose the options
|
||||
# first press [c] - configure
|
||||
# first press [c] - configure (unil you see [g])
|
||||
# then press [g] - generate
|
||||
```
|
||||
|
||||
|Example cmake options|Comment|
|
||||
|---|---|
|
||||
| -DSLS_USE_PYTHON=ON | Python |
|
||||
| -DPython_FIND_VIRTUALENV=ONLY | Python from only the conda environment |
|
||||
| -DZeroMQ_HINT=/usr/lib64 | Use system zmq instead |
|
||||
| -DPython_FIND_VIRTUALENV=ONLY | Python from only the conda env |
|
||||
| -DSLS_USE_GUI=ON | GUI |
|
||||
| -DSLS_USE_HDF5=ON | HDF5 |
|
||||
| -DSLS_USE_SIMULATOR=ON | Simulator |
|
||||
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmake option to hint library location](#Pybind-and-Zeromq).
|
||||
|
||||
###### Build using in-built cmk.sh script
|
||||
### Build using in-built cmk.sh script
|
||||
|
||||
```
|
||||
The binaries are generated in slsDetectorPackage/build/bin directory.
|
||||
|
||||
Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of threads>]
|
||||
[-k <CMake command>] [-l <Install directory>] [m] [n] [-p] [-q <Zmq hint directory>]
|
||||
[r] [s] [t] [u] [z]
|
||||
Usage: $0 [-b] [-c] [-d <HDF5 directory>] [-e] [-g] [-h] [-i]
|
||||
[-j <Number of threads>] [-k <CMake command>] [-l <Install directory>]
|
||||
[-m] [-n] [-p] [-r] [-s] [-t] [-u] [-z]
|
||||
-[no option]: only make
|
||||
-b: Builds/Rebuilds CMake files normal mode
|
||||
-c: Clean
|
||||
@ -128,14 +121,13 @@ Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of
|
||||
-m: Manuals
|
||||
-n: Manuals without compiling doxygen (only rst)
|
||||
-p: Builds/Rebuilds Python API
|
||||
-q: Zmq hint directory
|
||||
-r: Build/Rebuilds only receiver
|
||||
-s: Simulator
|
||||
-t: Build/Rebuilds only text client
|
||||
-u: Chip Test Gui
|
||||
-z: Moench zmq processor
|
||||
|
||||
|
||||
|
||||
# display all options
|
||||
./cmk.sh -?
|
||||
|
||||
@ -145,11 +137,14 @@ Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of
|
||||
# new build, python and compile in parallel:
|
||||
./cmk.sh -cbpj5
|
||||
|
||||
#To use the system zmq (/usr/lib64) instead
|
||||
./cmk.sh -cbj5 -q /usr/lib64
|
||||
#For rebuilding only certain sections
|
||||
./cmk.sh -tg #only text client and gui
|
||||
./cmk.sh -r #only receiver
|
||||
```
|
||||
|
||||
###### Build on old distributions
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmk script option to hint library location](#Pybind-and-Zeromq).
|
||||
|
||||
### Build on old distributions
|
||||
|
||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||
@ -166,7 +161,10 @@ cmake ../slsDetectorPackage -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
|
||||
make -j12
|
||||
```
|
||||
|
||||
###### Build slsDetectorGui (Qt5)
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
|
||||
|
||||
|
||||
### Build slsDetectorGui (Qt5)
|
||||
|
||||
1. Using pre-built binary on conda
|
||||
```
|
||||
@ -180,7 +178,14 @@ yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
```
|
||||
|
||||
3. Using conda
|
||||
3. Using system installation on RHEL8
|
||||
```
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
yum install expat-devel.x86_64
|
||||
```
|
||||
|
||||
4. Using conda
|
||||
```
|
||||
#Add channels for dependencies and our library
|
||||
conda config --add channels conda-forge
|
||||
@ -208,13 +213,15 @@ cd slsDetectorPackage
|
||||
./cmk.sh -cbgj9
|
||||
```
|
||||
|
||||
###### Build documentation from package
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
|
||||
|
||||
### Build documentation from package
|
||||
The documentation for the slsDetectorPackage is build using a combination
|
||||
of Doxygen, Sphinx and Breathe. The easiest way to install the dependencies
|
||||
is to use conda
|
||||
|
||||
```
|
||||
conda create -n myenv python sphinx_rtd_theme breathe
|
||||
conda create -n myenv python=3.12 sphinx sphinx_rtd_theme breathe doxygen numpy
|
||||
```
|
||||
|
||||
```
|
||||
@ -228,6 +235,47 @@ make rst # rst only, saves time in case the API did not change
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Pybind and Zeromq
|
||||
|
||||
### Pybind11 for Python
|
||||
**v8.0.0+**:
|
||||
pybind11 is built
|
||||
* by default from tar file in repo (libs/pybind/v2.1x.0.tar.gz)
|
||||
* or use advanced option SLS_FETCH_PYBIND11_FROM_GITHUB [link].
|
||||
* v9.0.0+: pybind11 (v2.13.6)
|
||||
* v8.x.x : pybind11 (v2.11.0)
|
||||
|
||||
**v7.x.x**:
|
||||
pybind11 packaged into ‘libs/pybind’. No longer a submodule. No need for “recursive” or “submodule update”.
|
||||
|
||||
**Older versions**:
|
||||
pybind11 is a submodule. Must be cloned using “recursive” and updated when switching between versions using the following commands.
|
||||
|
||||
```
|
||||
# Note: Only for v6.x.x versions and older
|
||||
|
||||
# clone using recursive to get pybind11 submodule
|
||||
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
|
||||
|
||||
# update submodule when switching between releases
|
||||
cd slsDetectorPackage
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
### Zeromq
|
||||
**v8.0.0+**:
|
||||
zeromq (v4.3.4) is built
|
||||
* by default from tar file in repo (libs/libzmq/libzmq-4.3.4.tar.gz)
|
||||
* or use advanced option SLS_FETCH_ZMQ_FROM_GITHUB [link].
|
||||
|
||||
**v7.x.x and older**:
|
||||
zeromq-devel must be installed and one can hint its location using
|
||||
* cmake option:’-DZeroMQ_HINT=/usr/lib64’ or
|
||||
* option ‘-q’ in cmk.sh script: : ./cmk.sh -cbj5 -q /usr/lib64
|
||||
* ‘zeromq’ dependency added when installing using conda
|
||||
|
||||
|
||||
## Support
|
||||
dhanya.thattil@psi.ch
|
||||
erik.frojdh@psi.ch
|
||||
erik.frojdh@psi.ch
|
57
RELEASE.txt
57
RELEASE.txt
@ -1,7 +1,7 @@
|
||||
SLS Detector Package Major Release 7.x.x released on xx.xx.2023
|
||||
SLS Detector Package Major Release x.x.x released on xx.xx.202x
|
||||
===============================================================
|
||||
|
||||
This document describes the differences between v7.x.x and v7.0.2
|
||||
This document describes the differences between vx.x.x and vx.0.2
|
||||
|
||||
|
||||
|
||||
@ -28,32 +28,30 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
=====================================
|
||||
|
||||
|
||||
- moench being made compatible with jungfrau 2.0 boards (jungfrau structure, away from ctb)
|
||||
- eiger febl and feb in versions
|
||||
- fix ctb slow adcs
|
||||
|
||||
|
||||
|
||||
|
||||
2 On-board Detector Server Compatibility
|
||||
==========================================
|
||||
|
||||
|
||||
Eiger 7.0.0
|
||||
Jungfrau 7.0.2
|
||||
Mythen3 7.0.0
|
||||
Gotthard2 7.0.0
|
||||
Gotthard 7.0.0
|
||||
Moench 7.0.0
|
||||
Ctb 7.0.0
|
||||
|
||||
Eiger 9.0.0
|
||||
Jungfrau 9.0.0
|
||||
Mythen3 9.0.0
|
||||
Gotthard2 9.0.0
|
||||
Moench 9.0.0
|
||||
|
||||
|
||||
On-board Detector Server Upgrade
|
||||
--------------------------------
|
||||
|
||||
From v6.1.0 (without tftp):
|
||||
Using command 'updatedetectorserver'
|
||||
From 5.0.0 (with tftp):
|
||||
Using command 'copydetectorserver'
|
||||
update only on-board detector server
|
||||
Using command 'updatedetectorserver'
|
||||
|
||||
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
Instructions available at
|
||||
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
|
||||
@ -65,21 +63,16 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
========================
|
||||
|
||||
|
||||
Eiger 20.02.2023 (v31)
|
||||
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
||||
|
||||
Jungfrau 04.11.2022 (v1.4, HW v1.0)
|
||||
03.11.2022 (v2.4, HW v2.0)
|
||||
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)
|
||||
|
||||
Mythen3 24.01.2023 (v1.4)
|
||||
Mythen3 11.10.2024 (v1.5) (updated in 9.0.0)
|
||||
|
||||
Gotthard2 23.11.2022 (v0.3)
|
||||
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
||||
|
||||
Gotthard 08.02.2018 (50um and 25um Master)
|
||||
09.02.2018 (25 um Slave)
|
||||
|
||||
Moench 05.12.2022 (v0.3)
|
||||
|
||||
Ctb 03.04.2023 (v1.2?)
|
||||
Moench 26.10.2023 (v2.0) (updated in 9.0.0)
|
||||
|
||||
|
||||
Detector Upgrade
|
||||
@ -92,15 +85,12 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
Mythen3 via command <.rbf>
|
||||
Gotthard2 via command <.rbf>
|
||||
Moench via command <.pof>
|
||||
Ctb via command <.pof>
|
||||
|
||||
Gotthard cannot be upgraded remotely
|
||||
|
||||
Except Eiger,
|
||||
upgrade
|
||||
Using command 'programfpga' or
|
||||
|
||||
udpate both server and firmware simultaneously
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
|
||||
@ -113,6 +103,7 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
4 Kernel Requirements
|
||||
======================
|
||||
|
||||
|
||||
Blackfin
|
||||
--------
|
||||
Latest version: Fri Oct 29 00:00:00 2021
|
||||
@ -120,10 +111,12 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
Older ones will work, but might have issues with programming firmware via
|
||||
the package.
|
||||
|
||||
|
||||
Nios
|
||||
-----
|
||||
Compatible version: Mon May 10 18:00:21 CEST 2021
|
||||
|
||||
|
||||
Kernel Upgrade
|
||||
---------------
|
||||
Eiger via bit files
|
||||
|
@ -25,7 +25,9 @@ mark_as_advanced(
|
||||
ClangFormat_BIN)
|
||||
|
||||
if(ClangFormat_FOUND)
|
||||
exec_program(${ClangFormat_BIN} ${CMAKE_CURRENT_SOURCE_DIR} ARGS --version OUTPUT_VARIABLE CLANG_VERSION_TEXT)
|
||||
execute_process(COMMAND ${ClangFormat_BIN} --version
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE CLANG_VERSION_TEXT)
|
||||
string(REGEX MATCH "([0-9]+)\\.[0-9]+\\.[0-9]+" CLANG_VERSION ${CLANG_VERSION_TEXT})
|
||||
if((${CLANG_VERSION} GREATER "9") OR (${CLANG_VERSION} EQUAL "9"))
|
||||
# A CMake script to find all source files and setup clang-format targets for them
|
||||
|
46
cmake/helpers.cmake
Normal file
46
cmake/helpers.cmake
Normal file
@ -0,0 +1,46 @@
|
||||
function(default_build_type val)
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE ${val} CACHE STRING "Build type (default ${val})" FORCE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(set_std_fs_lib)
|
||||
# from pybind11
|
||||
# Check if we need to add -lstdc++fs or -lc++fs or nothing
|
||||
if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 17)
|
||||
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||
elseif(MSVC)
|
||||
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||
else()
|
||||
file(
|
||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
"#include <filesystem>\nint main(int argc, char ** argv) {\n std::filesystem::path p(argv[0]);\n return p.string().length();\n}"
|
||||
)
|
||||
try_compile(
|
||||
STD_FS_NO_LIB_NEEDED ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17)
|
||||
try_compile(
|
||||
STD_FS_NEEDS_STDCXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17
|
||||
LINK_LIBRARIES stdc++fs)
|
||||
try_compile(
|
||||
STD_FS_NEEDS_CXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17
|
||||
LINK_LIBRARIES c++fs)
|
||||
endif()
|
||||
|
||||
if(${STD_FS_NEEDS_STDCXXFS})
|
||||
set(STD_FS_LIB stdc++fs PARENT_SCOPE)
|
||||
elseif(${STD_FS_NEEDS_CXXFS})
|
||||
set(STD_FS_LIB c++fs PARENT_SCOPE)
|
||||
elseif(${STD_FS_NO_LIB_NEEDED})
|
||||
set(STD_FS_LIB "" PARENT_SCOPE)
|
||||
else()
|
||||
message(WARNING "Unknown C++17 compiler - not passing -lstdc++fs")
|
||||
set(STD_FS_LIB "")
|
||||
endif()
|
||||
endfunction()
|
@ -1,6 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
echo "|<-------- starting python build"
|
||||
cd python
|
||||
${PYTHON} setup.py install
|
@ -1,7 +0,0 @@
|
||||
python:
|
||||
- 3.8
|
||||
- 3.9
|
||||
- 3.10
|
||||
- 3.11
|
||||
- 3.12
|
||||
|
@ -1,11 +0,0 @@
|
||||
# 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/.
|
||||
|
@ -1,126 +0,0 @@
|
||||
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }}
|
||||
|
||||
source:
|
||||
- path: ..
|
||||
|
||||
build:
|
||||
number: 0
|
||||
binary_relocation: True
|
||||
rpaths:
|
||||
- lib/
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- cmake
|
||||
- qt 5.*
|
||||
- xorg-libx11
|
||||
- xorg-libice
|
||||
- xorg-libxext
|
||||
- xorg-libsm
|
||||
- xorg-libxau
|
||||
- xorg-libxrender
|
||||
- xorg-libxfixes
|
||||
- {{ cdt('mesa-libgl-devel') }} # [linux]
|
||||
- {{ cdt('mesa-libegl-devel') }} # [linux]
|
||||
- {{ cdt('mesa-dri-drivers') }} # [linux]
|
||||
- {{ cdt('libselinux') }} # [linux]
|
||||
- {{ cdt('libxdamage') }} # [linux]
|
||||
- {{ cdt('libxxf86vm') }} # [linux]
|
||||
- expat
|
||||
|
||||
host:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- xorg-libx11
|
||||
- xorg-libice
|
||||
- xorg-libxext
|
||||
- xorg-libsm
|
||||
- xorg-libxau
|
||||
- xorg-libxrender
|
||||
- xorg-libxfixes
|
||||
- expat
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
|
||||
outputs:
|
||||
- name: slsdetlib
|
||||
script: copy_lib.sh
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('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.11
|
||||
|
||||
host:
|
||||
- python
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- pybind11=2.11
|
||||
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- python
|
||||
- numpy
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
|
||||
test:
|
||||
imports:
|
||||
- slsdet
|
||||
|
||||
- name: slsdetgui
|
||||
script: copy_gui.sh
|
||||
requirements:
|
||||
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- qt 5.*
|
||||
- expat
|
||||
|
||||
- name: moenchzmq
|
||||
script: copy_moench.sh
|
||||
requirements:
|
||||
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- expat
|
@ -1,3 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
ctest -j2
|
@ -1,10 +1,14 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
mkdir build
|
||||
mkdir install
|
||||
if [ ! -d "build" ]; then
|
||||
mkdir build
|
||||
fi
|
||||
if [ ! -d "install" ]; then
|
||||
mkdir install
|
||||
fi
|
||||
cd build
|
||||
cmake .. \
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
|
||||
-DCMAKE_INSTALL_PREFIX=install \
|
||||
-DSLS_USE_TEXTCLIENT=ON \
|
||||
@ -14,7 +18,7 @@ cmake .. \
|
||||
-DSLS_USE_TESTS=ON \
|
||||
-DSLS_USE_PYTHON=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSLS_USE_HDF5=OFF\
|
||||
-DSLS_USE_HDF5=OFF \
|
||||
|
||||
NCORES=$(getconf _NPROCESSORS_ONLN)
|
||||
echo "Building using: ${NCORES} cores"
|
13
conda-recipes/main-library/conda_build_config.yaml
Normal file
13
conda-recipes/main-library/conda_build_config.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
c_compiler:
|
||||
- gcc # [linux]
|
||||
|
||||
c_stdlib:
|
||||
- sysroot # [linux]
|
||||
|
||||
cxx_compiler:
|
||||
- gxx # [linux]
|
||||
|
||||
|
||||
c_stdlib_version: # [linux]
|
||||
- 2.17 # [linux]
|
@ -4,18 +4,20 @@
|
||||
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/
|
||||
|
||||
#Binaries
|
||||
cp build/install/bin/sls_detector_acquire $PREFIX/bin/.
|
||||
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
|
79
conda-recipes/main-library/meta.yaml
Executable file
79
conda-recipes/main-library/meta.yaml
Executable file
@ -0,0 +1,79 @@
|
||||
source:
|
||||
path: ../..
|
||||
|
||||
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: {{ version }}
|
||||
|
||||
build:
|
||||
number: 0
|
||||
binary_relocation: True
|
||||
rpaths:
|
||||
- lib/
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{ stdlib("c") }}
|
||||
- {{ compiler('cxx') }}
|
||||
- git
|
||||
- cmake
|
||||
- ninja
|
||||
- qt 5.*
|
||||
|
||||
host:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- libgl-devel # [linux]
|
||||
- libtiff
|
||||
- zlib
|
||||
- expat
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
|
||||
outputs:
|
||||
- name: slsdetlib
|
||||
script: copy_lib.sh
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{ stdlib("c") }}
|
||||
- {{ compiler('cxx') }}
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
|
||||
- name: slsdetgui
|
||||
script: copy_gui.sh
|
||||
requirements:
|
||||
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- qt 5.*
|
||||
|
||||
|
||||
- name: moenchzmq
|
||||
script: copy_moench.sh
|
||||
requirements:
|
||||
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
|
||||
run:
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
16
conda-recipes/python-client/conda_build_config.yaml
Normal file
16
conda-recipes/python-client/conda_build_config.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
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]
|
45
conda-recipes/python-client/meta.yaml
Normal file
45
conda-recipes/python-client/meta.yaml
Normal file
@ -0,0 +1,45 @@
|
||||
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
|
@ -1,90 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
find_package(ROOT CONFIG REQUIRED COMPONENTS Core Gui)
|
||||
find_package(TIFF REQUIRED)
|
||||
|
||||
target_include_directories(ROOT::Core INTERFACE "${ROOT_INCLUDE_DIRS}")
|
||||
add_library(ROOT::Flags_CXX IMPORTED INTERFACE)
|
||||
separate_arguments(ROOT_CXX_FLAGS)
|
||||
target_compile_options(ROOT::Flags_CXX INTERFACE ${ROOT_CXX_FLAGS})
|
||||
separate_arguments(ROOT_DEFINITIONS)
|
||||
target_compile_definitions(ROOT::Flags_CXX INTERFACE ${ROOT_DEFINITIONS})
|
||||
|
||||
# This fixes a bug in the linker flags
|
||||
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
||||
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
||||
|
||||
# Stuck into using old property method due to separate -L and -l arguments
|
||||
# (A full path to -l is better!)
|
||||
set_property(TARGET ROOT::Flags_CXX PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${ROOT_EXE_LINKER_FLAGS})
|
||||
set_property(TARGET ROOT::Core PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}")
|
||||
|
||||
|
||||
add_executable(ctbGui
|
||||
ctbGui.cpp
|
||||
ctbMain.cpp
|
||||
ctbDacs.cpp
|
||||
ctbPowers.cpp
|
||||
ctbSlowAdcs.cpp
|
||||
ctbSignals.cpp
|
||||
ctbAdcs.cpp
|
||||
ctbPattern.cpp
|
||||
ctbAcquisition.cpp
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/tiffio/src/tiffIO.cpp
|
||||
)
|
||||
|
||||
|
||||
#TODO! Replace with target
|
||||
target_include_directories(ctbGui PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/dataStructures
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/interpolations
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/tiffio/include/
|
||||
)
|
||||
|
||||
# Headders needed for ROOT dictionary generation
|
||||
set( HEADERS
|
||||
ctbDefs.h
|
||||
ctbMain.h
|
||||
ctbDacs.h
|
||||
ctbPattern.h
|
||||
ctbSignals.h
|
||||
ctbAdcs.h
|
||||
ctbAcquisition.h
|
||||
ctbPowers.h
|
||||
ctbSlowAdcs.h
|
||||
)
|
||||
|
||||
#set(ROOT_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# ROOT dictionary generation
|
||||
root_generate_dictionary(ctbDict ${HEADERS} LINKDEF ctbLinkDef.h)
|
||||
add_library(ctbRootLib SHARED ctbDict.cxx)
|
||||
target_include_directories(ctbRootLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(ctbRootLib PUBLIC
|
||||
ROOT::Core
|
||||
slsDetectorShared
|
||||
${ROOT_LIBRARIES}
|
||||
${ROOT_EXE_LINKER_FLAGS}
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
ctbRootLib PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
target_link_libraries(ctbGui PUBLIC
|
||||
slsDetectorShared
|
||||
ctbRootLib
|
||||
${TIFF_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties(ctbGui PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
|
||||
)
|
||||
|
@ -1,46 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h
|
||||
SRC= $(INCS:.h=.cpp) ctbDict.cpp
|
||||
LINKDEF=ctbLinkDef.h
|
||||
ZMQLIB=../slsReceiverSoftware/include
|
||||
LIBRARYCBF=$(CBFLIBDIR)/lib/*.o
|
||||
|
||||
INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations
|
||||
LDFLAG=-L../build/bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11
|
||||
#
|
||||
MAIN=ctbGui.cpp
|
||||
|
||||
DESTDIR?=../build/bin
|
||||
|
||||
|
||||
OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o)
|
||||
|
||||
all: $(DESTDIR)/ctbGui
|
||||
|
||||
|
||||
doc:
|
||||
cd manual && make DESTDIR=$(DESTDIR)
|
||||
|
||||
htmldoc:
|
||||
cd manual && make html DESTDIR=$(DESTDIR)
|
||||
|
||||
ctbDict.cpp: $(INCS) $(LINKDEF)
|
||||
rootcint -f ctbDict.cpp -c $(INCS) $(LINKDEF)
|
||||
|
||||
%.o : %.cpp
|
||||
echo $@
|
||||
g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR)
|
||||
#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS)
|
||||
|
||||
|
||||
|
||||
$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF)
|
||||
g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp
|
||||
mv ctbGui $(DESTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS)
|
||||
|
@ -1,48 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h
|
||||
SRC= $(INCS:.h=.cpp) ctbDict.cpp
|
||||
LINKDEF=ctbLinkDef.h
|
||||
#ctbActions.h
|
||||
ZMQLIB=../slsReceiverSoftware/include
|
||||
LIBRARYCBF=$(CBFLIBDIR)/lib/*.o
|
||||
|
||||
INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations
|
||||
|
||||
LDFLAG=-L../build/bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11
|
||||
#
|
||||
MAIN=ctbGui.cpp
|
||||
|
||||
DESTDIR?=../build/bin
|
||||
|
||||
|
||||
OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o)
|
||||
|
||||
all: $(DESTDIR)/ctbGui
|
||||
|
||||
|
||||
doc:
|
||||
cd manual && make DESTDIR=$(DESTDIR)
|
||||
|
||||
htmldoc:
|
||||
cd manual && make html DESTDIR=$(DESTDIR)
|
||||
|
||||
ctbDict.cpp: $(INCS) $(LINKDEF)
|
||||
rootcling -f ctbDict.cpp -c $(INCS) $(LINKDEF)
|
||||
|
||||
%.o : %.cpp
|
||||
echo $@
|
||||
g++ -DMYROOT `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR)
|
||||
#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS)
|
||||
|
||||
|
||||
|
||||
$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF)
|
||||
g++ -DMYROOT `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp
|
||||
mv ctbGui $(DESTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,248 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBACQUISITION_H
|
||||
#define CTBACQUISITION_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbPattern.h"
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TThread;
|
||||
class TGraph;
|
||||
class TMultiGraph;
|
||||
class THStack;
|
||||
class TGButtonGroup;
|
||||
class TGRadioButton;
|
||||
class TGComboBox;
|
||||
class TTimer;
|
||||
class TCanvas;
|
||||
class TH2F;
|
||||
class TH1F;
|
||||
class TGLabel;
|
||||
class TGTextButton;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
class detectorData;
|
||||
};
|
||||
|
||||
template <class dataType> class slsDetectorData;
|
||||
|
||||
class singlePhotonDetector;
|
||||
//class singlePhotonDetector;
|
||||
class commonModeSubtraction;
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
using namespace std;
|
||||
|
||||
class ctbAcquisition : public TGGroupFrame {
|
||||
|
||||
|
||||
enum {DESERIALIZER, MOENCH04, MOENCH02, MOENCH03, IMAGE32B, IMAGE16B, ADCSAR2, MYTHEN301, MYTHEN302};
|
||||
|
||||
|
||||
private:
|
||||
TGTextEntry *eOutdir;
|
||||
TGTextEntry *eFname;
|
||||
TGNumberEntry *eFindex;
|
||||
TGCheckButton *cFileSave;
|
||||
|
||||
|
||||
TGNumberEntry *eSerOff;
|
||||
TGNumberEntry *eDynRange;
|
||||
TGNumberEntry *eNumCount;
|
||||
|
||||
|
||||
TGNumberEntry *ePixX;
|
||||
TGNumberEntry *ePixY;
|
||||
|
||||
TGNumberEntry *eFitADC;
|
||||
TGNumberEntry *eBitPlot;
|
||||
TGNumberEntry *eMinRaw;
|
||||
TGNumberEntry *eMaxRaw;
|
||||
TGNumberEntry *eMinPedSub;
|
||||
TGNumberEntry *eMaxPedSub;
|
||||
TGCheckButton *cMinMaxRaw;
|
||||
TGCheckButton *cMinMaxPedSub;
|
||||
|
||||
|
||||
|
||||
|
||||
TGNumberEntry *eMeasurements;
|
||||
|
||||
|
||||
|
||||
TGTextButton *bStatus;
|
||||
// TGTextButton
|
||||
TGCheckButton *cCompile;
|
||||
TGTextButton *cLoad;
|
||||
// TGCheckButton *cRun;
|
||||
|
||||
TThread *acqThread;
|
||||
|
||||
|
||||
THStack *adcStack;
|
||||
THStack *bitStack;
|
||||
THStack *countsStack;
|
||||
|
||||
|
||||
TH1F *adcHisto[NADCS];
|
||||
TH1F *countsHisto[NADCS];
|
||||
|
||||
TH1F *bitHisto[NSIGNALS];
|
||||
float bitOffset[NSIGNALS];
|
||||
|
||||
// int enableFlag[NADCS+4];
|
||||
int roMode;
|
||||
|
||||
int dBitOffset;
|
||||
|
||||
|
||||
|
||||
TH1F *adcFit;
|
||||
TH1F *bitPlot;
|
||||
TH1F *countsFit;
|
||||
|
||||
|
||||
|
||||
TH2F *h2DMapAn; // for 2D detectors
|
||||
TH2F *h2DMapDig; // for 2D detectors
|
||||
TH1F *h1DMap; //for 1D detectors
|
||||
|
||||
// TH2F *h2Scan; // for 2D detectors
|
||||
// TMultiGraph *mgAdcs;
|
||||
// TH1I *plotAdc[NADCS];
|
||||
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
int plotFlag[NADCS];
|
||||
int bitPlotFlag[NSIGNALS];
|
||||
|
||||
int ip;
|
||||
// int nChannels;
|
||||
// int chanEnable;
|
||||
//int nADCs;
|
||||
|
||||
std::vector <int> dbitlist;
|
||||
std::vector <int> adclist;
|
||||
|
||||
TGButtonGroup *bgPlot;// = new TGVButtonGroup(main_frame);
|
||||
TGRadioButton *rbPlotOff;
|
||||
TGRadioButton *rbWaveform;
|
||||
TGRadioButton *rbDistribution;
|
||||
TGRadioButton *rb2D;
|
||||
// TGRadioButton *rbScan;
|
||||
TGComboBox *cbDetType;
|
||||
TGCheckButton *cbGetPedestal;
|
||||
TGCheckButton *cbSubtractPedestal;
|
||||
TGCheckButton *cbCommonMode;
|
||||
TGTextButton *bResetPedestal;
|
||||
|
||||
TGLabel *lClickX;
|
||||
TGLabel *lClickY;
|
||||
TGLabel *lClickValue;
|
||||
|
||||
|
||||
TCanvas *myCanvas;
|
||||
TTimer *plotTimer;
|
||||
|
||||
char patternFile[10000];
|
||||
char patternCompiler[10000];
|
||||
|
||||
int globalPlot;
|
||||
int adcPlot;
|
||||
int dbitPlot;
|
||||
int tenG;
|
||||
|
||||
int nAnalogSamples, nDigitalSamples;
|
||||
// int iScanStep;
|
||||
|
||||
slsDetectorData<uint16_t> *dataStructure;
|
||||
singlePhotonDetector *photonFinder;
|
||||
//singlePhotonDetector *photonFinder;
|
||||
commonModeSubtraction *commonMode;
|
||||
int cmSub;
|
||||
|
||||
int stop;
|
||||
|
||||
uint64_t dBitMask;
|
||||
|
||||
int deserializer;
|
||||
|
||||
public:
|
||||
ctbAcquisition(TGVerticalFrame*, sls::Detector*);
|
||||
void setOutdir();
|
||||
void setFname();
|
||||
void setMeasurements();
|
||||
void setFsave(Bool_t);
|
||||
void changePlot(Int_t);
|
||||
void changeDetector(Int_t);
|
||||
void changePlot();
|
||||
void changeDetector();
|
||||
void setFindex();
|
||||
void Draw();
|
||||
void setCanvas(TCanvas*);
|
||||
|
||||
void toggleAcquisition();
|
||||
void loadPattern();
|
||||
static void* ThreadHandle(void *arg);
|
||||
void update();
|
||||
void acquisitionFinished();
|
||||
// string getParameters();
|
||||
|
||||
void setGraph (int i ,int en, Pixel_t col);
|
||||
void setBitGraph (int i ,int en, Pixel_t col);
|
||||
void startAcquisition();
|
||||
static void progressCallback(double,void*);
|
||||
static void dataCallback(sls::detectorData*, long unsigned int, unsigned int, void*);
|
||||
int StopFlag;
|
||||
|
||||
int plotData(sls::detectorData*, int);
|
||||
|
||||
void setPatternFile(const char* t);
|
||||
|
||||
void setPatternCompiler(const char* t);
|
||||
|
||||
void setAnalogSamples(int);
|
||||
void setDigitalSamples(int);
|
||||
|
||||
void setADCEnable(Int_t);
|
||||
void setDbitEnable(Int_t);
|
||||
void setReadoutMode(int);
|
||||
void updateChans();
|
||||
|
||||
void resetPedestal();
|
||||
|
||||
void ToggleCommonMode(Bool_t);
|
||||
void TogglePedSub(Bool_t);
|
||||
void ChangeHistoLimitsPedSub(Long_t );
|
||||
void ChangeHistoLimitsRaw(Long_t);
|
||||
void ChangeHistoLimitsPedSub( );
|
||||
void ChangeHistoLimitsRaw();
|
||||
void ChangeHistoLimitsPedSub(Bool_t );
|
||||
void ChangeHistoLimitsRaw(Bool_t);
|
||||
|
||||
|
||||
void ChangeSerialOffset();
|
||||
void ChangeSerialOffset(Long_t);
|
||||
void ChangeNumberOfChannels();
|
||||
void ChangeNumberOfChannels(Long_t);
|
||||
void ChangeDynamicRange();
|
||||
void ChangeDynamicRange(Long_t);
|
||||
void ChangeImagePixels();
|
||||
void ChangeImagePixels(Long_t);
|
||||
|
||||
void canvasClicked();
|
||||
void FitADC();
|
||||
void plotBit();
|
||||
ClassDef(ctbAcquisition,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,616 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <TGColorSelect.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbAdc::ctbAdc(TGVerticalFrame *page, int i, sls::Detector *det)
|
||||
: TGHorizontalFrame(page, 800,800), id(i), myDet(det) {
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
char tit[100];
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "ADC%d", id);
|
||||
|
||||
sAdcLabel= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame(sAdcLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcLabel->MapWindow();
|
||||
sAdcLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sAdcInvert= new TGCheckButton(hframe, "Inv");
|
||||
hframe->AddFrame( sAdcInvert,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcInvert->MapWindow();
|
||||
sAdcInvert->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledInvert(Bool_t)");
|
||||
|
||||
|
||||
sAdcEnable= new TGCheckButton(hframe, "En");
|
||||
hframe->AddFrame( sAdcEnable,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcEnable->MapWindow();
|
||||
// sAdcEnable->SetOn(kTRUE);
|
||||
// sAdcEnable->SetEnabled(kFALSE);
|
||||
sAdcEnable->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledEnable(Bool_t)");
|
||||
|
||||
|
||||
|
||||
sAdcPlot= new TGCheckButton(hframe, "Plot");
|
||||
hframe->AddFrame( sAdcPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcPlot->MapWindow();
|
||||
|
||||
|
||||
sAdcPlot->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledPlot(Bool_t)");
|
||||
|
||||
|
||||
|
||||
fColorSel = new TGColorSelect(hframe, id+1, 0);
|
||||
|
||||
fColorSel->Connect("ColorSelected(Pixel_t)","ctbAdc",this,"ColorChanged(Pixel_t)");
|
||||
hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop |
|
||||
kLHintsLeft, 2, 0, 2, 2));
|
||||
|
||||
|
||||
fColorSel->SetColor(TColor::Number2Pixel(id+1));
|
||||
// sprintf(tit,"adc%d",id);
|
||||
// gADC=new TGraph();
|
||||
// gADC->SetName(tit);
|
||||
// gADC->SetLineColor(id+1);
|
||||
// gADC->SetMarkerColor(id+1);
|
||||
|
||||
|
||||
|
||||
};
|
||||
Pixel_t ctbAdc::getColor(){
|
||||
return fColorSel->GetColor();
|
||||
}
|
||||
Bool_t ctbAdc::getEnabled(){
|
||||
return getPlot();
|
||||
}
|
||||
Bool_t ctbAdc::getPlot(){
|
||||
return sAdcPlot->IsOn();
|
||||
}
|
||||
Bool_t ctbAdc::getInverted(){
|
||||
return sAdcInvert->IsOn();
|
||||
}
|
||||
|
||||
Bool_t ctbAdc::getEnable(){
|
||||
return sAdcEnable->IsOn();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setInverted(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcInvert->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sAdcInvert->SetOn(kFALSE,kTRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdc::setEnable(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcEnable->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sAdcEnable->SetOn(kFALSE,kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setAdcAlias(char *tit, int plot, int color) {
|
||||
if (tit)
|
||||
sAdcLabel->SetText(tit);
|
||||
if (plot>0)
|
||||
sAdcPlot->SetOn(kTRUE,kTRUE);
|
||||
else if (plot==0)
|
||||
sAdcPlot->SetOn(kFALSE,kTRUE);
|
||||
if (color>=0)
|
||||
fColorSel->SetColor(color);
|
||||
fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
}
|
||||
|
||||
|
||||
string ctbAdc::getAdcAlias() {
|
||||
|
||||
char line[1000];
|
||||
sprintf(line,"ADC%d %s %d %lx\n",id,sAdcLabel->GetText()->Data(),sAdcPlot->IsOn(),fColorSel->GetColor());
|
||||
return string(line);
|
||||
}
|
||||
|
||||
void ctbAdc::update() {
|
||||
|
||||
|
||||
//Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdc::ToggledPlot(Bool_t b){
|
||||
|
||||
// Long_t mask=b<<id;
|
||||
// ToggledAdcPlot(mask);
|
||||
cout << "Colsel " << id << " enable " << b << endl;
|
||||
if (b)
|
||||
fColorSel->SetEnabled(kTRUE);
|
||||
else
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
|
||||
// fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ToggledInvert(Bool_t b){
|
||||
|
||||
|
||||
// fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcInvert(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ToggledEnable(Bool_t b){
|
||||
|
||||
|
||||
fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ColorChanged(Pixel_t) {
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcPlot(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcInvert(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcInvert(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcEnable(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setEnabled(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcPlot->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sAdcPlot->SetOn(kFALSE,kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setPlot(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcPlot->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sAdcPlot->SetOn(kFALSE,kTRUE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctbAdcs::ctbAdcs(TGVerticalFrame *page, sls::Detector *det)
|
||||
: TGGroupFrame(page,"Adcs",kVerticalFrame), myDet(det) {
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
|
||||
|
||||
TGHorizontalFrame* hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
|
||||
int idac=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hhframe->MapWindow();
|
||||
|
||||
TGVerticalFrame *vframe;
|
||||
|
||||
|
||||
|
||||
|
||||
for (idac=0; idac<NADCS; idac++) {
|
||||
if (idac%16==0) {
|
||||
|
||||
|
||||
vframe=new TGVerticalFrame(hhframe, 400,800);
|
||||
hhframe->AddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
vframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
sAdc[idac]=new ctbAdc(vframe,idac,myDet);
|
||||
|
||||
|
||||
sAdc[idac]->Connect("ToggledAdcPlot(Int_t)","ctbAdcs",this,"ToggledAdcPlot(Int_t)");
|
||||
sAdc[idac]->Connect("ToggledAdcInvert(Int_t)","ctbAdcs",this,"ToggledAdcInvert(Int_t)");
|
||||
sAdc[idac]->Connect("ToggledAdcEnable(Int_t)","ctbAdcs",this,"ToggledAdcEnable(Int_t)");
|
||||
|
||||
}
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
bCheckHalf[0]=new TGTextButton(hframe, "All 0-15");
|
||||
hframe->AddFrame(bCheckHalf[0],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckHalf[0]->MapWindow();
|
||||
bCheckHalf[0]->Connect("Clicked()","ctbAdcs",this,"CheckHalf0()");
|
||||
|
||||
|
||||
bRemoveHalf[0]=new TGTextButton(hframe, "None 0-15");
|
||||
hframe->AddFrame(bRemoveHalf[0],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveHalf[0]->MapWindow();
|
||||
bRemoveHalf[0]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf0()");
|
||||
|
||||
|
||||
bCheckHalf[1]=new TGTextButton(hframe, "All 16-23");
|
||||
hframe->AddFrame(bCheckHalf[1],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckHalf[1]->MapWindow();
|
||||
bCheckHalf[1]->Connect("Clicked()","ctbAdcs",this,"CheckHalf1()");
|
||||
// bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()");
|
||||
|
||||
|
||||
bRemoveHalf[1]=new TGTextButton(hframe, "None 16-23");
|
||||
hframe->AddFrame(bRemoveHalf[1],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveHalf[1]->MapWindow();
|
||||
bRemoveHalf[1]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf1()");
|
||||
// bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()");
|
||||
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
bCheckAll=new TGTextButton(hframe, "All");
|
||||
hframe->AddFrame(bCheckAll,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckAll->MapWindow();
|
||||
bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()");
|
||||
|
||||
|
||||
bRemoveAll=new TGTextButton(hframe, "None");
|
||||
hframe->AddFrame(bRemoveAll,new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveAll->MapWindow();
|
||||
bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()");
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,50);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
TGLabel *label= new TGLabel(hframe, "Inversion mask: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eInversionMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eInversionMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eInversionMask->MapWindow();
|
||||
eInversionMask->Resize(150,30);
|
||||
eInversionMask->SetState(kFALSE);
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,50);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
label= new TGLabel(hframe, "Enable mask: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eEnableMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eEnableMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eEnableMask->MapWindow();
|
||||
eEnableMask->Resize(150,30);
|
||||
eEnableMask->SetState(kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ctbAdcs::setEnable(int reg) {
|
||||
|
||||
try {
|
||||
if (reg > -1) {
|
||||
myDet->setADCEnableMask(reg);
|
||||
}
|
||||
auto retval = myDet->getADCEnableMask().tsquash("Different values");
|
||||
eEnableMask->SetHexNumber(retval);
|
||||
return retval;
|
||||
} CATCH_DISPLAY ("Could not set/get adc enablemask.", "ctbAdcs::setEnable")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ctbAdcs::setInvert(int reg) {
|
||||
|
||||
try {
|
||||
if (reg > -1) {
|
||||
myDet->setADCInvert(reg);
|
||||
}
|
||||
auto retval = myDet->getADCInvert().tsquash("Different values");
|
||||
eInversionMask->SetHexNumber(retval);
|
||||
return retval;
|
||||
} CATCH_DISPLAY ("Could not set/get adc enablemask.", "ctbAdcs::setEnable")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdcs::update() {
|
||||
Int_t invreg;
|
||||
Int_t disreg;
|
||||
|
||||
disreg=setEnable();
|
||||
invreg=setInvert();
|
||||
|
||||
for (int is=0; is<NADCS; is++) {
|
||||
sAdc[is]->setAdcAlias(NULL,-1,-1);
|
||||
if (invreg & (1<<is) )
|
||||
sAdc[is]->setInverted(kTRUE);
|
||||
else
|
||||
sAdc[is]->setInverted(kFALSE);
|
||||
|
||||
if (disreg & (1<<is) )
|
||||
sAdc[is]->setEnable(kTRUE);
|
||||
else
|
||||
sAdc[is]->setEnable(kFALSE);
|
||||
}
|
||||
|
||||
Emit("AdcEnable(Int_t)", disreg);
|
||||
|
||||
}
|
||||
string ctbAdcs::getAdcParameters() {
|
||||
ostringstream line;
|
||||
line << "reg "<< hex << setInvert() << "# ADC invert reg" << dec << endl;
|
||||
line << "reg "<< hex << setEnable() << " # ADC enable reg"<< dec << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::CheckAll() {
|
||||
for (int is=0; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveAll() {
|
||||
for (int is=0; is<NADCS; is++) {
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdcs::CheckHalf0() {
|
||||
for (int is=0; is<NADCS/2; is++) {
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveHalf0() {
|
||||
for (int is=0; is<NADCS/2; is++){
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void ctbAdcs::CheckHalf1() {
|
||||
for (int is=NADCS/2; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveHalf1() {
|
||||
for (int is=NADCS/2; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ctbAdcs::setAdcAlias(string line) {
|
||||
|
||||
int is=-1, plot=0, color=-1;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"ADC%d %s %d %x",&is,tit,&plot, &color);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (narg!=3)
|
||||
color=-1;
|
||||
if (is>=0 && is<NADCS) {
|
||||
sAdc[is]->setAdcAlias(tit,plot,color);
|
||||
}
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbAdcs::getAdcAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int is=0; is<NADCS; is++)
|
||||
line << sAdc[is]->getAdcAlias();
|
||||
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcPlot(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdcs::AdcEnable(Int_t b){
|
||||
Emit("AdcEnable(Int_t)", b);
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcEnable(Int_t b){
|
||||
|
||||
Int_t oreg=setEnable();
|
||||
Int_t m=1<<b;
|
||||
|
||||
if (sAdc[b]->getEnable())
|
||||
oreg|=m;
|
||||
else
|
||||
oreg&=~m;
|
||||
|
||||
setEnable(oreg);
|
||||
|
||||
Emit("AdcEnable(Int_t)", oreg);
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcInvert(Int_t b){
|
||||
|
||||
Int_t oreg=setInvert();
|
||||
Int_t m=1<<b;
|
||||
|
||||
|
||||
if (sAdc[b]->getInverted())
|
||||
oreg|=m;
|
||||
else
|
||||
oreg&=~m;
|
||||
|
||||
setInvert(oreg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Pixel_t ctbAdcs::getColor(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getColor();
|
||||
return static_cast<Pixel_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getEnabled(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getEnabled();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getEnable(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getEnable();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getPlot(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getPlot();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
157
ctbGui/ctbAdcs.h
157
ctbGui/ctbAdcs.h
@ -1,157 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
|
||||
#ifndef CTBADCS_H
|
||||
#define CTBADCS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NADCS 32
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
class TGColorSelect;
|
||||
class TColor;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
class TGraph;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbAdc : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
TGLabel *sAdcLabel;
|
||||
TGCheckButton *sAdcEnable;
|
||||
TGCheckButton *sAdcPlot;
|
||||
TGCheckButton *sAdcInvert;
|
||||
|
||||
TGColorSelect *fColorSel;
|
||||
|
||||
// TGraph *gADC;
|
||||
|
||||
int id;
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbAdc(TGVerticalFrame *page, int i, sls::Detector *det);
|
||||
|
||||
|
||||
void setAdcAlias(char *tit, int plot, int color);
|
||||
string getAdcAlias();
|
||||
void ToggledAdcPlot(Int_t b);
|
||||
void ToggledAdcEnable(Int_t b);
|
||||
void ToggledAdcInvert(Int_t b);
|
||||
|
||||
|
||||
void ToggledPlot(Bool_t b);
|
||||
void ToggledEnable(Bool_t b);
|
||||
void ToggledInvert(Bool_t b);
|
||||
void ColorChanged(Pixel_t);
|
||||
void setEnabled(Bool_t b);
|
||||
Bool_t getEnabled();
|
||||
// TGraph *getGraph();
|
||||
void update();
|
||||
|
||||
Pixel_t getColor();
|
||||
|
||||
Bool_t getEnable();
|
||||
void setEnable(Bool_t);
|
||||
void setPlot(Bool_t);
|
||||
Bool_t getInverted();
|
||||
Bool_t getPlot();
|
||||
void setInverted(Bool_t);
|
||||
|
||||
ClassDef(ctbAdc,0)
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ctbAdcs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbAdc *sAdc[NADCS];
|
||||
sls::Detector *myDet;
|
||||
|
||||
|
||||
TGTextButton *bCheckAll;
|
||||
TGTextButton *bRemoveAll;
|
||||
TGTextButton *bCheckHalf[2];
|
||||
TGTextButton *bRemoveHalf[2];
|
||||
TGNumberEntry *eInversionMask;
|
||||
TGNumberEntry *eEnableMask;
|
||||
|
||||
|
||||
/* TGTextButton *bPlotSelected; */
|
||||
/* TGNumberEntry *eMinX; */
|
||||
/* TGNumberEntry *eMaxX; */
|
||||
/* TGNumberEntry *eMinY; */
|
||||
/* TGNumberEntry *eMaxY; */
|
||||
|
||||
|
||||
|
||||
/* TGTextButton *bGetPixel; */
|
||||
/* TGNumberEntry *ePixelX; */
|
||||
/* TGNumberEntry *ePixelY; */
|
||||
/* TGLabel *lPixelValue; */
|
||||
|
||||
public:
|
||||
|
||||
ctbAdcs(TGVerticalFrame *page, sls::Detector *det);
|
||||
int setAdcAlias(string line);
|
||||
string getAdcAlias();
|
||||
string getAdcParameters();
|
||||
void ToggledAdcPlot(Int_t);
|
||||
void ToggledAdcInvert(Int_t);
|
||||
void ToggledAdcEnable(Int_t);
|
||||
void AdcEnable(Int_t b);
|
||||
// TGraph *getGraph(int i);
|
||||
void CheckAll();
|
||||
void RemoveAll();
|
||||
void update();
|
||||
|
||||
int setInvert(int reg=-1);
|
||||
int setEnable(int reg=-1);
|
||||
|
||||
|
||||
Pixel_t getColor(int i);
|
||||
Bool_t getEnabled(int i);
|
||||
Bool_t getPlot(int i);
|
||||
Bool_t getEnable(int i);
|
||||
|
||||
void CheckHalf0();
|
||||
void RemoveHalf0();
|
||||
|
||||
void CheckHalf1();
|
||||
void RemoveHalf1();
|
||||
|
||||
|
||||
ClassDef(ctbAdcs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,235 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <TGTextEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGButton.h>
|
||||
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
ctbDac::ctbDac(TGGroupFrame *page, int idac, sls::Detector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) {
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
MapWindow();
|
||||
|
||||
char tit[100];
|
||||
|
||||
|
||||
sprintf(tit, "DAC %d:",idac);
|
||||
|
||||
dacsLabel= new TGCheckButton(hframe, tit);// new TGLabel(hframe, tit);
|
||||
dacsLabel->SetOn(kTRUE, kTRUE);
|
||||
|
||||
dacsLabel->Connect("Toggled(Bool_t)","ctbDac",this,"setOn(Bool_t)");
|
||||
|
||||
|
||||
hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsLabel->MapWindow();
|
||||
dacsLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
dacsEntry = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELLimitMinMax,
|
||||
0, 65535);
|
||||
|
||||
hframe->AddFrame(dacsEntry,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsEntry->MapWindow();
|
||||
dacsEntry->Resize(150,30);
|
||||
|
||||
|
||||
dacsUnit= new TGCheckButton(hframe, "mV");
|
||||
// if (idac!=slsDetectorDefs::ADC_VPP) {
|
||||
hframe->AddFrame( dacsUnit,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsUnit->MapWindow();
|
||||
if (idac==slsDetectorDefs::ADC_VPP) {
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
hframe->HideFrame(dacsUnit);
|
||||
dacsUnit->MapWindow();
|
||||
cout << "hiding!" << endl;
|
||||
}
|
||||
if (idac==slsDetectorDefs::HIGH_VOLTAGE) {
|
||||
dacsUnit->SetText("V");
|
||||
dacsUnit->SetOn(kTRUE,kTRUE);
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "xxx");
|
||||
dacsValue= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsValue->MapWindow();
|
||||
dacsValue->SetTextJustify(kTextLeft);
|
||||
|
||||
TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry();
|
||||
e->Connect("ReturnPressed()","ctbDac",this,"setValue()");
|
||||
// e->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)");
|
||||
dacsEntry->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)");
|
||||
// cout << "(((((((((((((((((((((((((((((((" << dacsEntry->GetListOfSignals()->At(0)->IsA() << endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbDac::setLabel(char *tit, int mv) {
|
||||
if(tit)
|
||||
dacsLabel->SetText(tit);
|
||||
if (mv==1)
|
||||
dacsUnit->SetOn(kTRUE,kTRUE);
|
||||
else if (mv==0)
|
||||
dacsUnit->SetOn(kFALSE,kTRUE);
|
||||
// else if (mv==2) {
|
||||
// ;}
|
||||
// else if (mv==3)
|
||||
// ;
|
||||
return id;
|
||||
|
||||
}
|
||||
|
||||
string ctbDac::getLabel() {
|
||||
ostringstream line;
|
||||
line << dacsLabel->GetText() << " " << dacsUnit->IsOn() << endl;
|
||||
// line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
int ctbDac::getMoenchDacId() {
|
||||
slsDetectorDefs::dacIndex moenchDacIndices[8] = {slsDetectorDefs::VBP_COLBUF, slsDetectorDefs::VIPRE, slsDetectorDefs::VIN_CM, slsDetectorDefs::VB_SDA, slsDetectorDefs::VCASC_SFP, slsDetectorDefs::VOUT_CM, slsDetectorDefs::VIPRE_CDS, slsDetectorDefs::IBIAS_SFP};
|
||||
|
||||
if (id >= 8) {
|
||||
return id;
|
||||
}
|
||||
return static_cast<int>(moenchDacIndices[id]);
|
||||
}
|
||||
|
||||
void ctbDac::setValue(Long_t a) {setValue();}
|
||||
|
||||
void ctbDac::setValue() {
|
||||
cout << "setting dac! "<< id << " value " << dacsEntry->GetIntNumber() << " units " << dacsUnit->IsOn() << endl;
|
||||
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
myDet->setDAC(static_cast<slsDetectorDefs::dacIndex>(sid), dacsEntry->GetIntNumber(), dacsUnit->IsOn());
|
||||
} CATCH_DISPLAY ("Could not set dac " + to_string(id) + ".", "ctbDac::setValue")
|
||||
|
||||
getValue();
|
||||
}
|
||||
|
||||
void ctbDac::setOn(Bool_t b) {
|
||||
// cout << "setting dac! "<< id << endl;
|
||||
if ( dacsLabel->IsOn()) {
|
||||
setValue();
|
||||
} else {
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
myDet->setDAC(static_cast<slsDetectorDefs::dacIndex>(sid), -100, false);
|
||||
} CATCH_DISPLAY ("Could not power off dac " + to_string(id) + ".", "ctbDac::setOn")
|
||||
}
|
||||
getValue();
|
||||
}
|
||||
|
||||
int ctbDac::getValue() {
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
int val = myDet->getDAC(static_cast<slsDetectorDefs::dacIndex>(sid), dacsUnit->IsOn()).tsquash("Different values");
|
||||
cout << "dac " << id << " " << val << endl;
|
||||
dacsValue->SetText(to_string(val).c_str());
|
||||
if (val >= 0) {
|
||||
dacsLabel->SetOn(kTRUE);
|
||||
} else {
|
||||
dacsLabel->SetOn(kFALSE);
|
||||
}
|
||||
return val;
|
||||
} CATCH_DISPLAY ("Could not get dac " + to_string(id) + ".", "ctbDac::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ctbDacs::ctbDacs(TGVerticalFrame *page, sls::Detector *det) : TGGroupFrame(page,"DACs",kVerticalFrame) , myDet(det){
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
for (int idac=0; idac<NDACS; idac++) {
|
||||
|
||||
dacs[idac]=new ctbDac(this, idac, myDet);
|
||||
|
||||
}
|
||||
dacs[NDACS]=new ctbDac(this, slsDetectorDefs::ADC_VPP, myDet);
|
||||
dacs[NDACS+1]=new ctbDac(this, slsDetectorDefs::HIGH_VOLTAGE, myDet);
|
||||
dacs[NDACS]->setLabel((char*)"ADC Vpp",2);
|
||||
dacs[NDACS+1]->setLabel((char*)"High Voltage",3);
|
||||
}
|
||||
|
||||
|
||||
int ctbDacs::setDacAlias(string line) {
|
||||
int is=-1, mv=0;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"DAC%d %s %d",&is,tit,&mv);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NDACS)
|
||||
dacs[is]->setLabel(tit,mv);
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbDacs::getDacAlias() {
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NDACS; i++)
|
||||
line << dacs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbDacs::getDacParameters() {
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NDACS; i++) {
|
||||
//line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
line << "dac:" << i << " " << dacs[i]->getValue() << endl;
|
||||
}
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbDacs::update() {
|
||||
for (int idac=0; idac<NDACS+1; idac++) {
|
||||
dacs[idac]->getValue();
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
#ifndef CTBDACS_H
|
||||
#define CTBDACS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NDACS 18
|
||||
//#define NDACS 16
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
class ctbDac : public TGHorizontalFrame {
|
||||
|
||||
|
||||
protected:
|
||||
// TGLabel *dacsLabel;
|
||||
TGNumberEntry *dacsEntry;
|
||||
TGCheckButton *dacsUnit;
|
||||
TGCheckButton *dacsLabel;
|
||||
TGLabel *dacsValue;
|
||||
int id;
|
||||
|
||||
sls::Detector* myDet;
|
||||
public:
|
||||
ctbDac(TGGroupFrame*, int , sls::Detector*);
|
||||
void setValue();
|
||||
void setValue(Long_t);
|
||||
int getValue();
|
||||
void setOn(Bool_t);
|
||||
|
||||
int setLabel(char *tit, int mv);
|
||||
string getLabel();
|
||||
int getMoenchDacId();
|
||||
|
||||
|
||||
ClassDef(ctbDac,0)
|
||||
};
|
||||
|
||||
class ctbDacs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbDac *dacs[NDACS+2];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
ctbDacs(TGVerticalFrame *page, sls::Detector*);
|
||||
|
||||
int setDacAlias(string line);
|
||||
// int setDacAlias(string line);
|
||||
string getDacAlias();
|
||||
string getDacParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbDacs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,86 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
//#include "sls/sls_detector_exceptions.h"
|
||||
//#include "sls/ansi.h"
|
||||
#define RED "\x1b[31m"
|
||||
#define RESET "\x1b[0m"
|
||||
#define BOLD "\x1b[1m"
|
||||
#define cprintf(code, format, ...) printf(code format RESET, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define CATCH_DISPLAY(m, s) catch(...) { ctbDefs::DisplayExceptions(m, s); }
|
||||
#define CATCH_HANDLE(...) catch(...) { ctbDefs::HandleExceptions(__VA_ARGS__); }
|
||||
|
||||
class ctbDefs {
|
||||
public:
|
||||
/**
|
||||
* Empty Constructor
|
||||
*/
|
||||
ctbDefs(){};
|
||||
|
||||
// convert double seconds to chrono ns
|
||||
static std::chrono::nanoseconds ConvertDoubleStoChronoNS(double timeS) {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::nanoseconds;
|
||||
return duration_cast<nanoseconds>(duration<double>(timeS));
|
||||
}
|
||||
|
||||
// convert chrono ns to doubel s
|
||||
static double ConvertChronoNStoDoubleS(std::chrono::nanoseconds timeNs) {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
return duration_cast<duration<double>>(timeNs).count();
|
||||
}
|
||||
|
||||
static void DisplayExceptions(std::string emsg, std::string src) {
|
||||
try {
|
||||
throw;
|
||||
} /* catch (const sls::SocketError &e) {
|
||||
throw;
|
||||
} catch (const sls::SharedMemoryError &e) {
|
||||
throw;
|
||||
} */catch (const std::exception &e) {
|
||||
ExceptionMessage(emsg, e.what(), src);
|
||||
}
|
||||
};
|
||||
|
||||
template <class CT> struct NonDeduced { using type = CT; };
|
||||
template <class S, typename RT, typename... CT>
|
||||
static void HandleExceptions(const std::string emsg, const std::string src, S* s,
|
||||
RT (S::*somefunc)(CT...),
|
||||
typename NonDeduced<CT>::type... Args) {
|
||||
try {
|
||||
throw;
|
||||
} /*catch (const sls::SocketError &e) {
|
||||
throw;
|
||||
} catch (const sls::SharedMemoryError &e) {
|
||||
throw;
|
||||
} */catch (const std::exception &e) {
|
||||
|
||||
ExceptionMessage(emsg, e.what(), src);
|
||||
(s->*somefunc)(Args...);
|
||||
}
|
||||
};
|
||||
|
||||
static void ExceptionMessage(std::string message,
|
||||
std::string exceptionMessage,
|
||||
std::string source) {
|
||||
// because sls_detector_exceptions cannot be included
|
||||
if (exceptionMessage.find("hared memory") != std::string::npos) {
|
||||
throw;
|
||||
}
|
||||
if (exceptionMessage.find("annot connect") != std::string::npos) {
|
||||
throw;
|
||||
}
|
||||
cprintf(RED, "Warning (%s): %s [Caught Exception: %s]\n", source.c_str(), message.c_str(), exceptionMessage.c_str());
|
||||
//return Message(qDefs::WARNING, message + std::string("\nCaught exception:\n") + exceptionMessage, source);
|
||||
};
|
||||
|
||||
};
|
@ -1,159 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TColor.h>
|
||||
|
||||
#include <TStyle.h>
|
||||
#include <TROOT.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
//#include "sls_receiver_defs.h"
|
||||
#include "ctbMain.h"
|
||||
#include "ctbDefs.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
string afname, cfname, pfname;
|
||||
int id=0;
|
||||
|
||||
int af=0, cf=0, pf=0;
|
||||
|
||||
|
||||
cout << " *** " << argc << endl;
|
||||
for (int ia=0; ia<argc; ia++) {
|
||||
if (strcmp(argv[ia],"-alias")==0) {
|
||||
if (ia+1<argc) {
|
||||
afname=argv[ia+1];
|
||||
ia++;
|
||||
af=1;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[ia],"-config")==0) {
|
||||
if (ia+1<argc) {
|
||||
cfname=argv[ia+1];
|
||||
ia++;
|
||||
cf=1;
|
||||
}
|
||||
|
||||
|
||||
} else if (strcmp(argv[ia],"-par")==0) {
|
||||
if (ia+1<argc) {
|
||||
pfname=argv[ia+1];
|
||||
ia++;
|
||||
pf=1;
|
||||
}
|
||||
|
||||
|
||||
} else if (strcmp(argv[ia],"-id")==0) {
|
||||
if (ia+1<argc) {
|
||||
id=atoi(argv[ia+1]);
|
||||
ia++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cout << " *** " << endl;
|
||||
sls::Detector *myDet = nullptr;
|
||||
try {
|
||||
/****** Create detector ****************/
|
||||
myDet=new sls::Detector(id);
|
||||
cout << "Created multi detector id " << id << endl;
|
||||
|
||||
if (cf) {
|
||||
myDet->loadConfig(cfname);
|
||||
cout << "Config file loaded successfully" << endl;
|
||||
} else {
|
||||
cout << "No config file specified" << endl;
|
||||
}
|
||||
cout << "hostname " << myDet->getHostname() << endl;
|
||||
|
||||
if (pf) {
|
||||
myDet->loadParameters(pfname);
|
||||
cout << "Loaded parameter file successfully" << endl;
|
||||
} else{
|
||||
cout << "No parameter file specified" << endl;
|
||||
}
|
||||
} CATCH_DISPLAY ("Could not create detector/ load config/parameters.", "ctbGui::main")
|
||||
|
||||
/***********Create GUI stuff *******************/
|
||||
TApplication theApp("App",&argc,argv);
|
||||
|
||||
|
||||
gStyle->SetDrawBorder(0);
|
||||
gStyle->SetCanvasColor(kWhite);
|
||||
gStyle->SetCanvasDefH(800);
|
||||
gStyle->SetCanvasDefW(800);
|
||||
gStyle->SetCanvasBorderMode(0);
|
||||
gStyle->SetPadBorderMode(0);
|
||||
gStyle->SetPaintTextFormat("5.2f");
|
||||
gStyle->SetLineWidth(2);
|
||||
gStyle->SetTextSize(1.1);
|
||||
gStyle->SetLabelSize(0.04,"xy");
|
||||
gStyle->SetTitleSize(0.05,"xy");
|
||||
gStyle->SetTitleOffset(1.0,"x");
|
||||
gStyle->SetTitleOffset(1.1,"y");
|
||||
gStyle->SetPadTopMargin(0.15);
|
||||
gStyle->SetPadRightMargin(0.15);
|
||||
gStyle->SetPadBottomMargin(0.15);
|
||||
gStyle->SetPadLeftMargin(0.15);
|
||||
gStyle->SetLegendBorderSize(1);
|
||||
gStyle->SetFrameBorderMode(0);
|
||||
gStyle->SetFrameFillColor(kWhite);
|
||||
// gStyle->SetLegendFillColor(kWhite);
|
||||
gStyle->SetTitleFillColor(kWhite);
|
||||
gStyle->SetFillColor(kWhite);
|
||||
gStyle->SetStatFontSize(0.03);
|
||||
gStyle->SetStatBorderSize(1);
|
||||
gStyle->SetStatFormat("6.4g");
|
||||
gStyle->SetStatX(0.95);
|
||||
gStyle->SetStatY(0.95);
|
||||
gStyle->SetStatW(0.2);
|
||||
gStyle->SetStatH(0.2);
|
||||
gStyle->SetTitleX(0.1);
|
||||
gStyle->SetTitleY(0.95);
|
||||
gStyle->SetTitleBorderSize(0);
|
||||
gStyle->SetTitleFontSize(0.05);
|
||||
gROOT->SetStyle("Default");
|
||||
|
||||
|
||||
TColor::InitializeColors();
|
||||
const Int_t NRGBs = 5;
|
||||
const Int_t NCont = 90;
|
||||
|
||||
Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
|
||||
Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 };
|
||||
Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
|
||||
Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 };
|
||||
TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
|
||||
gStyle->SetNumberContours(NCont);
|
||||
|
||||
|
||||
gROOT->ForceStyle();
|
||||
ctbMain *mf=new ctbMain(gClient->GetRoot(), myDet);
|
||||
|
||||
cout << " *** " << argc << endl;
|
||||
for (int ia=0; ia<argc; ia++)
|
||||
cout << argv[ia] << endl;
|
||||
|
||||
|
||||
cout << " *** " << endl;
|
||||
|
||||
if (af)
|
||||
mf->loadAlias(afname);
|
||||
else
|
||||
cout << "no alias specified" << endl;
|
||||
|
||||
theApp.Run();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#pragma link C++ class ctbMain;
|
||||
#pragma link C++ class ctbDacs;
|
||||
#pragma link C++ class ctbDac;
|
||||
#pragma link C++ class ctbSignals;
|
||||
#pragma link C++ class ctbSignal;
|
||||
#pragma link C++ class ctbAdc;
|
||||
#pragma link C++ class ctbAdcs;
|
||||
#pragma link C++ class ctbLoop;
|
||||
#pragma link C++ class ctbWait;
|
||||
#pragma link C++ class ctbPattern;
|
||||
#pragma link C++ class ctbAcquisition;
|
||||
#pragma link C++ class ctbPower;
|
||||
#pragma link C++ class ctbPowers;
|
||||
#pragma link C++ class ctbSlowAdc;
|
||||
#pragma link C++ class ctbSlowAdcs;
|
@ -1,588 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
#include <TApplication.h>
|
||||
#include <TGCanvas.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <TGMenu.h>
|
||||
#include <TGDockableFrame.h>
|
||||
//#include <TGMenuBar.h>
|
||||
//#include <TGPopupMenu.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "sls/Detector.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "ctbMain.h"
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbSlowAdcs.h"
|
||||
#include "ctbPowers.h"
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbPattern.h"
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbAcquisition.h"
|
||||
//#include "ctbActions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbMain::ctbMain(const TGWindow *p, sls::Detector *det)
|
||||
: TGMainFrame(p,800,800), pwrs(NULL), senses(NULL) {
|
||||
|
||||
myDet=det;
|
||||
|
||||
Connect("CloseWindow()", "ctbMain", this, "CloseWindow()");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// fMenuDock = new TGDockableFrame(this);
|
||||
// AddFrame(fMenuDock, new TGLayoutHints(kLHintsExpandX, 0, 0, 1, 0));
|
||||
// fMenuDock->SetWindowName("GuiTest Menu");
|
||||
|
||||
fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX);
|
||||
fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);
|
||||
fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight);
|
||||
|
||||
fMenuFile = new TGPopupMenu(gClient->GetRoot());
|
||||
int im=0;
|
||||
|
||||
fMenuFile->AddEntry("Open Alias", im++);
|
||||
fMenuFile->AddEntry("Save Alias", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Parameters", im++);
|
||||
fMenuFile->AddEntry("Save Parameters", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Configuration", im++);
|
||||
fMenuFile->AddEntry("Save Configuration", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Pattern", im++);
|
||||
fMenuFile->AddEntry("Save Pattern", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Exit", im++);
|
||||
|
||||
fMenuFile->Connect("Activated(Int_t)", "ctbMain", this,
|
||||
"HandleMenu(Int_t)");
|
||||
|
||||
|
||||
i_dacs=-1;
|
||||
i_pwrs=-1;
|
||||
i_senses=-1;
|
||||
i_sig=-1;
|
||||
i_adcs=-1;
|
||||
i_pat=-1;
|
||||
i_acq=-1;
|
||||
|
||||
int i_page=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TGVerticalFrame *vframe=new TGVerticalFrame(this, 800,1200); //main frame
|
||||
|
||||
|
||||
|
||||
fMenuBar = new TGMenuBar(vframe, 1, 1, kHorizontalFrame);
|
||||
fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&Test", fMenuTest, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout);
|
||||
|
||||
vframe->AddFrame(fMenuBar, fMenuBarLayout);
|
||||
|
||||
TGHorizontalFrame* hpage=new TGHorizontalFrame(vframe, 800,1200); //horizontal frame. Inside there should be the tab and the canvas
|
||||
mtab=new TGTab(hpage, 1500, 1200); //tab!
|
||||
// page=new TGVerticalFrame(mtab, 1500,1200);
|
||||
|
||||
cout << "DACS" << endl;
|
||||
|
||||
TGCompositeFrame *tf = mtab->AddTab("DACs");
|
||||
TGVerticalFrame *page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
dacs=new ctbDacs(page, myDet);
|
||||
i_dacs=i_page++;
|
||||
|
||||
|
||||
cout << "power " << endl;
|
||||
tf = mtab->AddTab("Power Supplies");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
pwrs=new ctbPowers(page, myDet);
|
||||
|
||||
i_pwrs=i_page++;
|
||||
|
||||
cout << "sense " << endl;
|
||||
tf = mtab->AddTab("Sense");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
senses=new ctbSlowAdcs(page, myDet);
|
||||
|
||||
i_senses=i_page++;
|
||||
|
||||
|
||||
|
||||
cout << "signals " << endl;
|
||||
tf = mtab->AddTab("Signals");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
sig=new ctbSignals(page, myDet);
|
||||
sig->Connect("ToggledSignalPlot(Int_t)","ctbMain",this,"setSignalPlot(Int_t)");
|
||||
|
||||
i_sig=i_page++;
|
||||
|
||||
cout << "adcs " << endl;
|
||||
tf = mtab->AddTab("ADCs");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
adcs=new ctbAdcs(page, myDet);
|
||||
adcs->Connect("ToggledAdcPlot(Int_t)","ctbMain",this,"setADCPlot(Int_t)");
|
||||
adcs->Connect("AdcEnable(Int_t)","ctbMain",this,"setADCEnable(Int_t)");
|
||||
i_adcs=i_page++;
|
||||
|
||||
|
||||
cout << "pattern" << endl;
|
||||
|
||||
tf = mtab->AddTab("Pattern");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
pat=new ctbPattern(page, myDet);
|
||||
pat->Connect("patternFileChanged(const char*)","ctbMain",this,"setPatternFile(const char*)");
|
||||
pat->Connect("patternCompilerChanged(const char*)","ctbMain",this,"setPatternCompiler(const char*)");
|
||||
pat->Connect("analogSamplesChanged(const int)","ctbMain",this,"setAnalogSamples(int)");
|
||||
pat->Connect("digitalSamplesChanged(const int)","ctbMain",this,"setDigitalSamples(int)");
|
||||
pat->Connect("readoutModeChanged(int)","ctbMain",this,"setReadoutMode(int)");
|
||||
|
||||
i_pat=i_page++;
|
||||
|
||||
cout << "acquisition" << endl;
|
||||
|
||||
tf = mtab->AddTab("Acquisition");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
acq=new ctbAcquisition(page, myDet);
|
||||
|
||||
|
||||
i_acq=i_page++;
|
||||
|
||||
|
||||
// cout << "actions" << endl;
|
||||
// tf = mtab->AddTab("Actions");
|
||||
// page=new TGVerticalFrame(tf, 1500,1200);
|
||||
// tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
// actions=new ctbActions(page, myDet);
|
||||
|
||||
|
||||
// i_actions=i_page++;
|
||||
|
||||
|
||||
|
||||
cout << "tabs finished" << endl;
|
||||
|
||||
hpage->AddFrame(mtab,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
|
||||
vframe->AddFrame(hpage,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
|
||||
AddFrame(vframe,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
vframe->MapWindow();
|
||||
hpage->MapWindow();
|
||||
mtab->MapWindow();
|
||||
page->MapWindow();
|
||||
|
||||
// Sets window name and shows the main frame
|
||||
cout << "dockabel" << endl;
|
||||
TGDockableFrame *fdock=new TGDockableFrame(hpage);
|
||||
hpage->AddFrame(fdock, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
fdock->MapWindow();
|
||||
|
||||
cout << "canvas" << endl;
|
||||
// // Creates widgets of the example
|
||||
|
||||
|
||||
fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",fdock,800,800);//hpage,800,800);
|
||||
//fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",this,800,800);//hpage,800,800);
|
||||
// fEcanvas->Resize();
|
||||
// fEcanvas->GetCanvas()->Update();
|
||||
//AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
|
||||
// // hpage->
|
||||
fdock->AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
|
||||
|
||||
fEcanvas->MapWindow();
|
||||
|
||||
acq->setCanvas(getCanvas());
|
||||
|
||||
|
||||
|
||||
hpage->MapSubwindows();
|
||||
mtab->Connect("Selected(Int_t)","ctbMain",this,"tabSelected(Int_t)");
|
||||
|
||||
|
||||
|
||||
cout << "connect mtab" << endl;
|
||||
|
||||
try{
|
||||
setReadoutMode(pat->getReadoutMode());
|
||||
} CATCH_DISPLAY ("Could not get readout flags", "ctbPattern::getReadoutMode")
|
||||
|
||||
setADCEnable(adcs->setEnable());
|
||||
setAnalogSamples(pat->getAnalogSamples());
|
||||
setDigitalSamples(pat->getDigitalSamples());
|
||||
|
||||
tabSelected(0);
|
||||
|
||||
SetWindowName("CTB Gui");
|
||||
MapSubwindows();
|
||||
Resize(1500,1200);
|
||||
|
||||
MapWindow();
|
||||
}
|
||||
|
||||
void ctbMain::CloseWindow() {
|
||||
gApplication->Terminate();
|
||||
}
|
||||
|
||||
TCanvas* ctbMain::getCanvas() {
|
||||
return fEcanvas->GetCanvas();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbMain::HandleMenu(Int_t id)
|
||||
{
|
||||
// Handle menu items.
|
||||
|
||||
|
||||
|
||||
|
||||
switch (id) {
|
||||
|
||||
case 0: // fMenuFile->AddEntry("Open Alias", im++);
|
||||
cout << "Open Alias" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadAlias(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // fMenuFile->AddEntry("Save Alias", im++);
|
||||
cout << "Save Alias" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi);
|
||||
printf("Save file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
saveAlias(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
case 2: //fMenuFile->AddEntry("Open Parameters", im++);
|
||||
cout << "Open Parameters" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadParameters(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // fMenuFile->AddEntry("Open Configuration", im++);
|
||||
cout << "Open configuration" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadConfiguration(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: //fMenuFile->AddEntry("Open Pattern", im++);
|
||||
cout << "Open pattern" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadParameters(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: //fMenuFile->AddEntry("Save Pattern", im++);
|
||||
cout << "Save pattern" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
savePattern(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // fMenuFile->AddEntry("Exit", im++);
|
||||
CloseWindow();
|
||||
|
||||
default:
|
||||
printf("Menu item %d selected\n", id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbMain::setADCPlot(Int_t i) {
|
||||
|
||||
// cout << "ADC " << i << " plot or color toggled" << endl;
|
||||
// acq->setGraph(i,adcs->getGraph(i));
|
||||
acq->setGraph(i,adcs->getEnabled(i),adcs->getColor(i));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ctbMain::setSignalPlot(Int_t i) {
|
||||
|
||||
// cout << "ADC " << i << " plot or color toggled" << endl;
|
||||
// acq->setGraph(i,adcs->getGraph(i));
|
||||
acq->setBitGraph(i,sig->getPlot(i),sig->getColor(i));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbMain::loadConfiguration(string fname) {
|
||||
try{
|
||||
myDet->loadConfig(fname);
|
||||
} CATCH_DISPLAY ("Could not load config.", "ctbMain::loadConfiguration")
|
||||
}
|
||||
|
||||
void ctbMain::loadParameters(string fname) {
|
||||
try{
|
||||
myDet->loadParameters(fname);
|
||||
} CATCH_DISPLAY ("Could not load parameters.", "ctbMain::loadParameters")
|
||||
}
|
||||
|
||||
void ctbMain::savePattern(string fname) {
|
||||
try{
|
||||
myDet->savePattern(fname);
|
||||
} CATCH_DISPLAY ("Could not save pattern.", "ctbMain::savePattern")
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbMain::loadAlias(string fname) {
|
||||
|
||||
|
||||
string line;
|
||||
char aaaa[1000];
|
||||
int i;
|
||||
ifstream myfile (fname.c_str());
|
||||
if (myfile.is_open())
|
||||
{
|
||||
while ( getline (myfile,line) )
|
||||
{
|
||||
// cout << line ;
|
||||
if (sscanf(line.c_str(),"BIT%d",&i)>0) {
|
||||
//cout << "*******" << line<< endl;
|
||||
sig->setSignalAlias(line);
|
||||
// cout << line ;
|
||||
} else if (sscanf(line.c_str(),"DAC%d",&i)>0) {
|
||||
dacs->setDacAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"ADC%d",&i)>0) {
|
||||
adcs->setAdcAlias(line);
|
||||
// cout << "---------" << line<< endl;
|
||||
} // else
|
||||
// cout << "<<<<<<<" << line << endl;
|
||||
else if (sscanf(line.c_str(),"PAT%s",aaaa)>0) {
|
||||
pat->setPatternAlias(line);
|
||||
// cout << "---------" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"V%s",aaaa)>0) {
|
||||
if (pwrs) pwrs->setPwrAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"SENSE%d",&i)>0) {
|
||||
if (senses) senses->setSlowAdcAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
}
|
||||
|
||||
}
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
else cout << "Unable to open file";
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbMain::saveAlias(string fname) {
|
||||
|
||||
|
||||
string line;
|
||||
ofstream myfile (fname.c_str());
|
||||
if (myfile.is_open())
|
||||
{
|
||||
//while ( getline (myfile,line) )
|
||||
// {
|
||||
// cout << line ;
|
||||
//if (sscanf(line.c_str(),"BIT%d",&i)>0) {
|
||||
//cout << "*******" << line<< endl;
|
||||
myfile << sig->getSignalAlias();
|
||||
// cout << line ;
|
||||
// } else if (sscanf(line.c_str(),"DAC%d",&i)>0) {
|
||||
myfile << dacs->getDacAlias();
|
||||
if (pwrs) myfile << pwrs->getPwrAlias();
|
||||
if (senses) myfile << senses->getSlowAdcAlias();
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
// } else if (sscanf(line.c_str(),"ADC%d",&i)>0) {
|
||||
myfile << adcs->getAdcAlias();
|
||||
// cout << "---------" << line<< endl;
|
||||
// } // else
|
||||
// cout << "<<<<<<<" << line << endl;
|
||||
myfile << pat->getPatternAlias();
|
||||
|
||||
//}
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
else cout << "Unable to open file";
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbMain::tabSelected(Int_t i) {
|
||||
|
||||
// cout << "Selected tab " << i << endl;
|
||||
// cout << "Current tab is " << mtab->GetCurrent() << endl;
|
||||
|
||||
if (i==i_dacs) dacs->update();
|
||||
else if (i==i_pwrs) pwrs->update();
|
||||
else if (i==i_senses) ;//senses->update();
|
||||
else if (i==i_sig) sig->update();
|
||||
else if (i==i_adcs) adcs->update();
|
||||
else if (i==i_pat) pat->update();
|
||||
else if (i==i_acq) acq->update();
|
||||
else if (i==i_acq) acq->update();
|
||||
// else if (i==i_actions) actions->update();
|
||||
else cout << "Unknown tab " << i << endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setPatternFile(const char* t) {
|
||||
acq->setPatternFile(t);
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setPatternCompiler(const char* t) {
|
||||
acq->setPatternCompiler(t);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setAnalogSamples(const int n) {
|
||||
acq->setAnalogSamples(n);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setDigitalSamples(const int n) {
|
||||
acq->setDigitalSamples(n);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setReadoutMode(int flags) {
|
||||
acq->setReadoutMode(flags);
|
||||
}
|
||||
|
||||
void ctbMain::setADCEnable(Int_t reg){
|
||||
acq->setADCEnable(reg);
|
||||
}
|
130
ctbGui/ctbMain.h
130
ctbGui/ctbMain.h
@ -1,130 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBMAIN_H
|
||||
#define CTBMAIN_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
class TGMenuBar;
|
||||
class TGPopupMenu;
|
||||
class TGDockableFrame;
|
||||
class TGLayoutHints;
|
||||
class TGCanvas;
|
||||
class TCanvas;
|
||||
|
||||
class ctbDacs;
|
||||
class ctbSlowAdcs;
|
||||
class ctbPowers;
|
||||
|
||||
|
||||
class ctbSignals;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
class ctbPattern;
|
||||
class ctbAdcs;
|
||||
class ctbAcquisition;
|
||||
//class ctbActions;
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbMain : public TGMainFrame {
|
||||
private:
|
||||
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
|
||||
|
||||
TRootEmbeddedCanvas *fEcanvas;
|
||||
TRootEmbeddedCanvas *fModulecanvas;
|
||||
TGButtonGroup *br;
|
||||
|
||||
TGTab *mtab;
|
||||
|
||||
|
||||
ctbDacs *dacs;
|
||||
int i_dacs;
|
||||
|
||||
ctbPowers *pwrs;
|
||||
int i_pwrs;
|
||||
|
||||
ctbSlowAdcs *senses;
|
||||
int i_senses;
|
||||
|
||||
|
||||
ctbSignals *sig;
|
||||
int i_sig;
|
||||
|
||||
|
||||
ctbAdcs *adcs;
|
||||
int i_adcs;
|
||||
|
||||
|
||||
ctbPattern *pat;
|
||||
int i_pat;
|
||||
|
||||
ctbAcquisition *acq;
|
||||
int i_acq;
|
||||
|
||||
// ctbActions *actions;
|
||||
int i_actions;
|
||||
|
||||
TGDockableFrame *fMenuDock;
|
||||
|
||||
TGMenuBar *fMenuBar;
|
||||
TGPopupMenu *fMenuFile, *fMenuTest, *fMenuView, *fMenuHelp;
|
||||
TGPopupMenu *fCascadeMenu, *fCascade1Menu, *fCascade2Menu;
|
||||
TGPopupMenu *fMenuNew1, *fMenuNew2;
|
||||
TGLayoutHints *fMenuBarLayout, *fMenuBarItemLayout, *fMenuBarHelpLayout;
|
||||
TGCanvas *myCanvas;
|
||||
|
||||
|
||||
public:
|
||||
ctbMain(const TGWindow *p, sls::Detector *det);
|
||||
|
||||
|
||||
int loadAlias(string fname);
|
||||
int saveAlias(string fname);
|
||||
void loadParameters(string fname);
|
||||
void savePattern(string fname);
|
||||
void loadConfiguration(string fname);
|
||||
void tabSelected(Int_t);
|
||||
int setADCPlot(Int_t);
|
||||
int setSignalPlot(Int_t);
|
||||
void CloseWindow();
|
||||
|
||||
void setPatternFile(const char* t);
|
||||
|
||||
void setPatternCompiler(const char* t);
|
||||
void setAnalogSamples(const int);
|
||||
void setDigitalSamples(const int);
|
||||
void setReadoutMode(int);
|
||||
void setADCEnable(Int_t);
|
||||
|
||||
void HandleMenu(Int_t);
|
||||
TCanvas* getCanvas();
|
||||
ClassDef(ctbMain,0)
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBPATTERN_H
|
||||
#define CTBPATTERN_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NLOOPS 3
|
||||
#define NWAITS 3
|
||||
#define NADCS 32
|
||||
#define PATLEN 1024
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
class TGTextEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class energyCalibration;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
class ctbLoop : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TGNumberEntry *eLoopStartAddr;
|
||||
TGNumberEntry *eLoopStopAddr;
|
||||
TGNumberEntry *eLoopNumber;
|
||||
|
||||
int id;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbLoop(TGGroupFrame *page, int i,sls::Detector *det);
|
||||
|
||||
void setNLoops();
|
||||
void update();
|
||||
|
||||
ClassDef(ctbLoop,0)
|
||||
};
|
||||
|
||||
class ctbWait : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TGNumberEntry *eWaitAddr;
|
||||
TGNumberEntry *eWaitTime;
|
||||
|
||||
int id;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbWait(TGGroupFrame *page, int i,sls::Detector *det);
|
||||
|
||||
void setWaitTime();
|
||||
void update();
|
||||
|
||||
ClassDef(ctbWait,0)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ctbPattern : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
|
||||
TGNumberEntry *eAdcClkFreq;
|
||||
TGNumberEntry *eRunClkFreq;
|
||||
TGNumberEntry *eDBitClkFreq;
|
||||
TGNumberEntry *eAdcClkPhase;
|
||||
TGNumberEntry *eDBitClkPhase;
|
||||
//TGNumberEntry *eRunClkPhase;
|
||||
|
||||
TGNumberEntry *eStartAddr;
|
||||
TGNumberEntry *eStopAddr;
|
||||
TGNumberEntry *eFrames;
|
||||
TGNumberEntry *ePeriod;
|
||||
TGNumberEntry *eTriggers;
|
||||
// TGNumberEntry *eMeasurements;
|
||||
TGNumberEntry *eAdcPipeline;
|
||||
TGNumberEntry *eDBitPipeline;
|
||||
|
||||
ctbLoop *eLoop[NLOOPS];
|
||||
ctbWait *eWait[NWAITS];
|
||||
|
||||
TGTextEntry *patternCompiler;
|
||||
TGTextEntry *patternFile;
|
||||
|
||||
TGTextButton *browseCompiler;
|
||||
TGTextButton *browseFile;
|
||||
|
||||
|
||||
TGNumberEntry *eAnalogSamples;
|
||||
TGNumberEntry *eDigitalSamples;
|
||||
|
||||
TGCheckButton *cbAnalog;
|
||||
TGCheckButton *cbDigital;
|
||||
|
||||
char pat[PATLEN*8];
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
|
||||
ctbPattern(TGVerticalFrame *page, sls::Detector *det);
|
||||
|
||||
void update();
|
||||
void setAdcFreq();
|
||||
void setRunFreq();
|
||||
void setDBitFreq();
|
||||
void setAdcPhase();
|
||||
void setDBitPhase();
|
||||
// void setRunPhase();
|
||||
void setAdcPipeline();
|
||||
void setDBitPipeline();
|
||||
void setFrames();
|
||||
void setTriggers();
|
||||
// void setMeasurements();
|
||||
void setPeriod();
|
||||
|
||||
|
||||
void chooseCompiler();
|
||||
void choosePattern();
|
||||
|
||||
string getCompiler();
|
||||
string getPatternFile();
|
||||
|
||||
void setPatternAlias(string);
|
||||
string getPatternAlias();
|
||||
|
||||
|
||||
int getAnalogSamples();
|
||||
void setAnalogSamples();
|
||||
int getDigitalSamples();
|
||||
void setDigitalSamples();
|
||||
void setReadoutMode(Bool_t);
|
||||
int getReadoutMode();
|
||||
|
||||
|
||||
void setFile();
|
||||
void setCompiler();
|
||||
void patternFileChanged(const char*);
|
||||
void patternCompilerChanged(const char*);
|
||||
void analogSamplesChanged(const int t);
|
||||
void digitalSamplesChanged(const int t);
|
||||
void readoutModeChanged(int);
|
||||
|
||||
|
||||
ClassDef(ctbPattern,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,225 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ctbDefs.h"
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbPowers.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbPower::ctbPower(TGGroupFrame* f, int i, sls::Detector* d)
|
||||
: ctbDac(f, i, d)
|
||||
{
|
||||
cout << "****************************************************************power " << i << endl;
|
||||
dacsUnit->SetOn(kTRUE);
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
|
||||
switch(i) {
|
||||
case slsDetectorDefs::V_POWER_IO:
|
||||
dacsLabel->SetText("VIO");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_A:
|
||||
dacsLabel->SetText("VA");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_B:
|
||||
dacsLabel->SetText("VB");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_C:
|
||||
dacsLabel->SetText("VC");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_D:
|
||||
dacsLabel->SetText("VD");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_CHIP:
|
||||
dacsLabel->SetText("VCHIP");
|
||||
dacsLabel->SetEnabled(kFALSE);
|
||||
break;
|
||||
default:
|
||||
dacsLabel->SetText("Bad index");
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry();
|
||||
e->Disconnect ("ReturnPressed()");
|
||||
e->Disconnect ("ValueSet(Long_t)");
|
||||
|
||||
e->Connect("ReturnPressed()","ctbPower",this,"setValue()");
|
||||
dacsEntry->Connect("ValueSet(Long_t)","ctbPower",this,"setValue(Long_t)");
|
||||
};
|
||||
|
||||
|
||||
string ctbPower::getLabel() {
|
||||
|
||||
ostringstream line;
|
||||
switch (id) {
|
||||
case slsDetectorDefs::V_POWER_IO:
|
||||
line << "VIO";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_A:
|
||||
line << "VA";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_B:
|
||||
line << "VB";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_C:
|
||||
line << "VC";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_D:
|
||||
line << "VD";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_CHIP:
|
||||
line << "VCHIP";
|
||||
break;
|
||||
default:
|
||||
line << "VBAD";
|
||||
break;
|
||||
|
||||
}
|
||||
line << " " << dacsLabel->GetText() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
void ctbPower::setValue(Long_t a) {ctbPower::setValue();}
|
||||
|
||||
void ctbPower::setValue() {
|
||||
cout << "***************************Setting power " << dacsEntry->GetIntNumber() << " " << id << " " << 1 << endl;
|
||||
|
||||
try {
|
||||
myDet->setVoltage(static_cast<slsDetectorDefs::dacIndex>(id), dacsEntry->GetIntNumber());
|
||||
} CATCH_DISPLAY ("Could not set power " + to_string(id) + ".", "ctbPower::setValue")
|
||||
|
||||
getValue();
|
||||
}
|
||||
|
||||
|
||||
int ctbPower::getValue() {
|
||||
try {
|
||||
|
||||
int val = myDet->getVoltage(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "****************************Getting power " << val << " " << id << " " << 1 << endl;
|
||||
|
||||
dacsValue->SetText(to_string(val).c_str());
|
||||
if (val > 0) {
|
||||
if (id != static_cast<int>(slsDetectorDefs::V_POWER_CHIP))
|
||||
dacsLabel->SetOn(kTRUE);
|
||||
} else {
|
||||
dacsLabel->SetOn(kFALSE);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
} CATCH_DISPLAY ("Could not get power " + to_string(id) + ".", "ctbPower::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ctbPowers::ctbPowers(TGVerticalFrame* page, sls::Detector* det) : TGGroupFrame(page,"Power Supplies",kVerticalFrame) , myDet(det){
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
for (int idac=0; idac<NPOWERS; idac++) {
|
||||
dacs[idac]=new ctbPower(this, slsDetectorDefs::V_POWER_A+idac, myDet);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ctbPowers::setPwrAlias(string line) {
|
||||
|
||||
int is=-1;
|
||||
char tit[100];
|
||||
|
||||
if (sscanf(line.c_str(),"VA %s",tit)) {
|
||||
dacs[0]->setLabel(tit,1);
|
||||
is=0;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VB %s",tit)) {
|
||||
dacs[1]->setLabel(tit,1);
|
||||
is=1;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VC %s",tit)) {
|
||||
dacs[2]->setLabel(tit,1);
|
||||
is=2;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VD %s",tit)) {
|
||||
dacs[3]->setLabel(tit,1);
|
||||
is=3;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VIO %s",tit)) {
|
||||
dacs[4]->setLabel(tit,1);
|
||||
is=4;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VCHIP %s",tit)) {
|
||||
dacs[5]->setLabel(tit,1);
|
||||
is=5;
|
||||
}
|
||||
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbPowers::getPwrAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NPOWERS; i++)
|
||||
line << dacs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbPowers::getPwrParameters() {
|
||||
|
||||
ostringstream line;
|
||||
line << "v_a" << " " << dacs[0]->getValue() << " mv" << endl;
|
||||
line << "v_b" << " " << dacs[1]->getValue() << " mv" << endl;
|
||||
line << "v_c" << " " << dacs[2]->getValue() << " mv" << endl;
|
||||
line << "v_d" << " " << dacs[3]->getValue() << " mv" << endl;
|
||||
line << "v_io" << " " << dacs[4]->getValue() << " mv" << endl;
|
||||
line << "v_chip" << " " << dacs[5]->getValue() << " mv" << endl;
|
||||
// for (int i=0; i<POWERS; i++) {
|
||||
// //line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
// line << "dac:" << i << " " << dacs[i]->getValue() << endl;
|
||||
// }
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbPowers::update() {
|
||||
for (int idac=0; idac<NPOWERS; idac++) {
|
||||
dacs[idac]->getValue();
|
||||
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBPOWERS_H
|
||||
#define CTBPOWERS_H
|
||||
|
||||
#include <TGFrame.h>
|
||||
|
||||
#define NPOWERS 6
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
class ctbPower : public ctbDac {
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ctbPower(TGGroupFrame* f, int i, sls::Detector* d);
|
||||
|
||||
string getLabel();
|
||||
|
||||
int getValue();
|
||||
void setValue();
|
||||
void setValue(Long_t);
|
||||
|
||||
ClassDef(ctbPower,0)
|
||||
};
|
||||
|
||||
|
||||
class ctbPowers : public TGGroupFrame
|
||||
{
|
||||
private:
|
||||
|
||||
ctbPower *dacs[NPOWERS];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
//ctbPowers();
|
||||
ctbPowers(TGVerticalFrame*, sls::Detector*);
|
||||
|
||||
int setPwrAlias(string);
|
||||
string getPwrAlias();
|
||||
string getPwrParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbPowers,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,543 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <TColor.h>
|
||||
#include <TGColorSelect.h>
|
||||
|
||||
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
//#define DEFAULTFN "run_0.encal"
|
||||
|
||||
|
||||
ctbSignal::ctbSignal(TGFrame *page, int i, sls::Detector *det)
|
||||
: TGHorizontalFrame(page, 800,50), myDet(det), id(i), hsig(NULL) {
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
char tit[100];
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "BIT%d ",id);
|
||||
|
||||
sLabel= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( sLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sLabel->MapWindow();
|
||||
sLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
sOutput= new TGCheckButton(hframe, "Out");
|
||||
hframe->AddFrame( sOutput,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sOutput->MapWindow();
|
||||
|
||||
|
||||
sOutput->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledOutput(Bool_t)");
|
||||
|
||||
sDbitList= new TGCheckButton(hframe, "DB List");
|
||||
hframe->AddFrame( sDbitList,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sDbitList->MapWindow();
|
||||
|
||||
sDbitList->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledDbitList(Bool_t)");
|
||||
|
||||
|
||||
sPlot= new TGCheckButton(hframe, "Plot");
|
||||
hframe->AddFrame( sPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sPlot->MapWindow();
|
||||
|
||||
sPlot->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledPlot(Bool_t)");
|
||||
|
||||
fColorSel = new TGColorSelect(hframe, id+1, 0);
|
||||
fColorSel->Connect("ColorSelected(Pixel_t)","ctbSignal",this,"ColorChanged(Pixel_t)");
|
||||
hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop |
|
||||
kLHintsLeft, 2, 0, 2, 2));
|
||||
|
||||
|
||||
fColorSel->SetColor(TColor::Number2Pixel(id+1));
|
||||
|
||||
|
||||
ToggledOutput(kFALSE);
|
||||
|
||||
|
||||
ToggledPlot(kFALSE);
|
||||
|
||||
// if (id==63) {
|
||||
// sOutput->SetOn(kTRUE);
|
||||
// sOutput->SetEnabled(kFALSE);
|
||||
// }
|
||||
// #ifdef CTB
|
||||
// if (id==62) {
|
||||
// sOutput->SetOn(kTRUE);
|
||||
// sOutput->SetEnabled(kFALSE);
|
||||
// }
|
||||
|
||||
// // if (id>=32 && id<48)
|
||||
// // fixOutput(1);
|
||||
// // else if (id>=48 && id<64)
|
||||
// // fixOutput(0);
|
||||
|
||||
// #endif
|
||||
}
|
||||
int ctbSignal::setSignalAlias(char *tit, int plot, int col) {
|
||||
|
||||
if (tit)
|
||||
sLabel->SetText(tit);
|
||||
|
||||
if (plot>0) {
|
||||
sPlot->SetOn(kTRUE,kTRUE);
|
||||
} else if (plot==0)
|
||||
sPlot->SetOn(kFALSE,kTRUE);
|
||||
|
||||
if (col>=0)
|
||||
fColorSel->SetColor(col);//TColor::Number2Pixel(col+1));
|
||||
|
||||
fColorSel->SetEnabled(sPlot->IsOn());
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
string ctbSignal::getSignalAlias() {
|
||||
|
||||
|
||||
ostringstream oss;
|
||||
oss << "BIT" << dec << id << " " << sLabel->GetText()->Data() << " " << sPlot->IsOn() << hex << " " << fColorSel->GetColor() << endl;
|
||||
return oss.str();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
int ctbSignal::setOutput(Long64_t r) {
|
||||
|
||||
|
||||
// cout << hex << r << dec <<endl;
|
||||
|
||||
Long64_t mask=((Long64_t)1<<id);
|
||||
|
||||
if (r&mask)
|
||||
sOutput->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sOutput->SetOn(kFALSE,kTRUE);
|
||||
|
||||
return sOutput->IsOn();
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::fixOutput(int i) {
|
||||
|
||||
if (i) {
|
||||
sPlot->SetOn(kFALSE);
|
||||
//sClock->SetOn(kFALSE,kTRUE);
|
||||
sOutput->SetOn(kTRUE);
|
||||
// sPlot->SetEnabled(kFALSE);
|
||||
// sClock->SetEnabled(kTRUE);
|
||||
} else {
|
||||
sOutput->SetOn(kFALSE,kTRUE);
|
||||
// sClock->SetOn(kFALSE);
|
||||
// sClock->SetEnabled(kFALSE);
|
||||
sPlot->SetEnabled(kTRUE);
|
||||
}
|
||||
sOutput->SetEnabled(kFALSE);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::setDbitList(Long64_t r) {
|
||||
|
||||
if (r)
|
||||
sDbitList->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sDbitList->SetOn(kFALSE,kFALSE);
|
||||
|
||||
return sDbitList->IsOn();
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::isDbitList() { return sDbitList->IsOn();}
|
||||
int ctbSignal::isOutput() { return sOutput->IsOn();}
|
||||
int ctbSignal::isPlot() { return sPlot->IsOn();}
|
||||
Pixel_t ctbSignal::getColor(){return fColorSel->GetColor();}
|
||||
|
||||
void ctbSignal::ToggledOutput(Bool_t b) {
|
||||
ToggledSignalOutput(id);
|
||||
if (b) {
|
||||
// sClock->SetEnabled(kTRUE);
|
||||
sPlot->SetOn(kFALSE);
|
||||
// sPlot->SetEnabled(kFALSE);
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
} else {
|
||||
// sClock->SetEnabled(kFALSE);
|
||||
// sClock->SetOn(kFALSE);
|
||||
sPlot->SetEnabled(kTRUE);
|
||||
if ( sPlot->IsOn())
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
else
|
||||
fColorSel->SetEnabled(kTRUE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledDbitList(Bool_t b){
|
||||
Long_t mask=id;
|
||||
ToggledSignalDbitList(mask);
|
||||
}
|
||||
|
||||
|
||||
void ctbSignal::ToggledPlot(Bool_t b){
|
||||
Long_t mask=b<<id;
|
||||
ToggledSignalPlot(mask);
|
||||
fColorSel->SetEnabled(b);
|
||||
}
|
||||
|
||||
void ctbSignal::ColorChanged(Pixel_t p){
|
||||
ToggledSignalPlot(id);
|
||||
}
|
||||
|
||||
|
||||
void ctbSignal::ToggledSignalOutput(Int_t b) {
|
||||
cout << "Toggle signal " << id << " " << b << " " << sOutput->IsOn() <<endl;;
|
||||
Emit("ToggledSignalOutput(Int_t)", id);
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledSignalDbitList(Int_t b){
|
||||
cout << "Toggle dbitlist " << id << " " << b << endl;;
|
||||
Emit("ToggledSignalDbitList(Int_t)", id);
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledSignalPlot(Int_t b){
|
||||
Emit("ToggledSignalPlot(Int_t)", id);
|
||||
}
|
||||
|
||||
|
||||
ctbSignals::ctbSignals(TGVerticalFrame *page, sls::Detector *det)
|
||||
: TGGroupFrame(page,"IO Signals",kVerticalFrame), myDet(det) {
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe;
|
||||
|
||||
TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hhframe->MapWindow();
|
||||
|
||||
TGVerticalFrame *vframe;
|
||||
|
||||
|
||||
|
||||
|
||||
int idac=0;
|
||||
for (idac=0; idac<NSIGNALS; idac++) {
|
||||
if (idac%((NSIGNALS+2)/2)==0) {
|
||||
vframe=new TGVerticalFrame(hhframe, 400,800);
|
||||
hhframe->AddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
vframe->MapWindow();
|
||||
}
|
||||
|
||||
|
||||
signals[idac]=new ctbSignal(vframe,idac,myDet);
|
||||
signals[idac]->Connect("ToggledSignalOutput(Int_t)","ctbSignals",this,"ToggledOutReg(Int_t)");
|
||||
signals[idac]->Connect("ToggledSignalDbitList(Int_t)","ctbSignals",this,"ToggledDbitList(Int_t)");
|
||||
signals[idac]->Connect("ToggledSignalPlot(Int_t)","ctbSignals",this,"ToggledPlot(Int_t)");
|
||||
|
||||
vframe->AddFrame(signals[idac],new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
signals[idac]->MapWindow();
|
||||
|
||||
|
||||
}
|
||||
|
||||
hframe=new TGHorizontalFrame(vframe, 800,50);
|
||||
vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
TGLabel *label= new TGLabel(hframe, "IO Control Register: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eIOCntrlRegister = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eIOCntrlRegister,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eIOCntrlRegister->MapWindow();
|
||||
eIOCntrlRegister->Resize(150,30);
|
||||
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(vframe, 800,50);
|
||||
vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
label= new TGLabel(hframe, "DBit Offset: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eDbitOffset = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eDbitOffset,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eDbitOffset->MapWindow();
|
||||
eDbitOffset->Resize(150,30);
|
||||
|
||||
|
||||
TGTextEntry *e= eDbitOffset->TGNumberEntry::GetNumberEntry();
|
||||
e->Connect("ReturnPressed()","ctbSignals",this,"setDbitOffset()");
|
||||
|
||||
e->Connect("ValueSet(Long_t)","ctbSignals",this,"setDbitOffset(Long_t)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbSignals::setSignalAlias(string line) {
|
||||
|
||||
int is=-1, plot=0, col=-1;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"BIT%d %s %d %d",&is,tit,&plot,&col);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NIOSIGNALS) {
|
||||
signals[is]->setSignalAlias(tit,plot,col);
|
||||
}
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbSignals::getSignalAlias() {
|
||||
|
||||
ostringstream oss;
|
||||
for (int is=0; is<NIOSIGNALS; is++)
|
||||
oss << signals[is]->getSignalAlias() << endl;
|
||||
|
||||
|
||||
return oss.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbSignals::update() {
|
||||
try {
|
||||
|
||||
Long64_t oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
cout << hex << oreg << dec << endl;
|
||||
|
||||
for (int idac=0; idac<NIOSIGNALS; idac++) {
|
||||
signals[idac]->setOutput(oreg);
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get patternIOcontrol.", "ctbSignals::update")
|
||||
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
// enable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
eDbitOffset->SetNumber(0);
|
||||
}
|
||||
|
||||
// ctb
|
||||
else {
|
||||
try {
|
||||
|
||||
auto dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
// enable all
|
||||
if (dbitlist.empty()) {
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// disable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(0);
|
||||
}
|
||||
// enable selected
|
||||
for (const auto &value : dbitlist) {
|
||||
signals[value]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get receiver dbit list.", "ctbSignals::update")
|
||||
|
||||
try {
|
||||
auto val = myDet->getRxDbitOffset().tsquash("Different values");
|
||||
eDbitOffset->SetNumber(val);
|
||||
} CATCH_DISPLAY ("Could not get receiver dbit offset.", "ctbSignals::update")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string ctbSignals::getSignalParameters() {
|
||||
|
||||
try {
|
||||
|
||||
auto val = myDet->getPatternIOControl().tsquash("Different values");
|
||||
ostringstream line;
|
||||
line << "patioctrl " << hex << val << dec << endl;
|
||||
return line.str();
|
||||
|
||||
} CATCH_DISPLAY ("Could not get patternIOcontrol.", "ctbSignals::getSignalParameters")
|
||||
|
||||
return ("");
|
||||
}
|
||||
|
||||
void ctbSignals::ToggledOutReg(Int_t mask) {
|
||||
try {
|
||||
|
||||
Long64_t oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
Long64_t m=((Long64_t)1)<<mask;
|
||||
cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg;
|
||||
|
||||
if (signals[mask]->isOutput()) {
|
||||
cout << " or " << m ;
|
||||
oreg|=m;
|
||||
} else {
|
||||
cout << " not " << ~m ;
|
||||
oreg&=~m;
|
||||
}
|
||||
cout << " after " << oreg << endl;
|
||||
|
||||
myDet->setPatternIOControl(static_cast<uint64_t>(oreg));
|
||||
oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl;
|
||||
|
||||
eIOCntrlRegister->SetText(to_string(oreg).c_str());
|
||||
|
||||
} CATCH_DISPLAY ("Could not get/set patternIOcontrol.", "ctbSignals::ToggledOutReg")
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbSignals::ToggledDbitList(Int_t mask){
|
||||
try {
|
||||
|
||||
auto dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
|
||||
// anyway all enabled
|
||||
if ((dbitlist.empty()) && (signals[mask]->isDbitList())) {
|
||||
;
|
||||
}
|
||||
// set the dbitlist
|
||||
else {
|
||||
std::vector <int> new_dbitlist;
|
||||
for (int is=0; is<64; is++) {
|
||||
if (signals[is]->isDbitList()){
|
||||
new_dbitlist.push_back(is);
|
||||
cout << is << " " << new_dbitlist.size() - 1 << endl;
|
||||
}
|
||||
}
|
||||
if (new_dbitlist.size() > 64)
|
||||
new_dbitlist.clear();
|
||||
myDet->setRxDbitList(new_dbitlist);
|
||||
// get list again
|
||||
dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
}
|
||||
|
||||
// enable all
|
||||
if (dbitlist.empty()) {
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// disable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(0);
|
||||
}
|
||||
// enable selected
|
||||
for (const auto &value : dbitlist) {
|
||||
signals[value]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get/set receiver dbit list.", "ctbSignals::ToggledDbitList")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbSignals::ToggledPlot(Int_t b) {
|
||||
|
||||
Emit("ToggledSignalPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbSignals::ToggledSignalPlot(Int_t b) {
|
||||
|
||||
Emit("ToggledSignalPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Pixel_t ctbSignals::getColor(int i){
|
||||
if (i>=0 && i<NSIGNALS)
|
||||
return signals[i]->getColor();
|
||||
return static_cast<Pixel_t>(-1);
|
||||
}
|
||||
|
||||
int ctbSignals::getPlot(int i){
|
||||
if (i>=0 && i<NSIGNALS)
|
||||
return signals[i]->isPlot();
|
||||
return -1;
|
||||
};
|
||||
|
||||
void ctbSignals::setDbitOffset(Long_t) {
|
||||
setDbitOffset();
|
||||
}
|
||||
|
||||
void ctbSignals::setDbitOffset(){
|
||||
try {
|
||||
myDet->setRxDbitOffset(eDbitOffset->GetNumber());
|
||||
} CATCH_DISPLAY ("Could not set receiver dbit offset.", "ctbSignals::setDbitOffset")
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBSIGNALS_H
|
||||
#define CTBSIGNALS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NSIGNALS 64
|
||||
|
||||
#define NIOSIGNALS 64 //for moench board was 52
|
||||
|
||||
|
||||
#define ADCLATCH 63
|
||||
#define DIGSIGLATCH 62
|
||||
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TH1I;
|
||||
class TGTextButton;
|
||||
class TGColorSelect;
|
||||
|
||||
|
||||
|
||||
class TGNumberEntry;
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
class ctbSignal;
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbSignal : public TGHorizontalFrame {
|
||||
|
||||
// RQ_OBJECT("ctbSignal")
|
||||
|
||||
private:
|
||||
|
||||
TGLabel *sLabel;
|
||||
TGCheckButton *sOutput;
|
||||
TGCheckButton *sDbitList;
|
||||
TGCheckButton *sPlot;
|
||||
TGLabel *sValue;
|
||||
TGNumberEntry *sEntry;
|
||||
TGColorSelect *fColorSel;
|
||||
|
||||
sls::Detector *myDet;
|
||||
Int_t id;
|
||||
|
||||
TH1I *hsig;
|
||||
|
||||
public:
|
||||
|
||||
ctbSignal(TGFrame *page, int i, sls::Detector *det);
|
||||
int setSignalAlias(char *tit, int plot, int col);
|
||||
string getSignalAlias();
|
||||
|
||||
TH1I *getPlot() {return hsig;};
|
||||
int setOutput(Long64_t);
|
||||
int fixOutput(int);
|
||||
int setDbitList(Long64_t);
|
||||
|
||||
void ToggledOutput(Bool_t);
|
||||
void ToggledDbitList(Bool_t);
|
||||
void ToggledPlot(Bool_t);
|
||||
void ColorChanged(Pixel_t);
|
||||
|
||||
int isDbitList();
|
||||
int isOutput();
|
||||
int isPlot();
|
||||
Pixel_t getColor();
|
||||
|
||||
|
||||
void ToggledSignalOutput(Int_t); //*SIGNAL*
|
||||
void ToggledSignalDbitList(Int_t); //*SIGNAL*
|
||||
void ToggledSignalPlot(Int_t); //*SIGNAL*
|
||||
|
||||
|
||||
|
||||
ClassDef(ctbSignal,0)
|
||||
};
|
||||
|
||||
class ctbSignals : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbSignal *signals[NSIGNALS];
|
||||
|
||||
TGNumberEntry *eIOCntrlRegister;
|
||||
TGNumberEntry *eDbitOffset;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbSignals(TGVerticalFrame *page, sls::Detector *det);
|
||||
int setSignalAlias(string line);
|
||||
string getSignalAlias();
|
||||
|
||||
int getPlot(int);
|
||||
Pixel_t getColor(int);
|
||||
|
||||
void update();
|
||||
// void saveParameters();
|
||||
string getSignalParameters();
|
||||
|
||||
//void setDbitList(Int_t);
|
||||
void setDbitOffset(Long_t);
|
||||
void setDbitOffset();
|
||||
|
||||
void ToggledOutReg(Int_t);
|
||||
void ToggledDbitList(Int_t);
|
||||
void ToggledPlot(Int_t);
|
||||
void ToggledSignalPlot(Int_t); //*SIGNAL*
|
||||
|
||||
ClassDef(ctbSignals,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,184 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <TGTextEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGButton.h>
|
||||
|
||||
#include "ctbSlowAdcs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
|
||||
ctbSlowAdc::ctbSlowAdc(TGGroupFrame *page, int idac, sls::Detector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) {
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
MapWindow();
|
||||
|
||||
char tit[100];
|
||||
|
||||
|
||||
sprintf(tit, "SENSE %d:",idac-1000);
|
||||
|
||||
dacsLabel= new TGLabel(hframe, tit);// new TGLabel(hframe, tit);
|
||||
|
||||
|
||||
|
||||
hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsLabel->MapWindow();
|
||||
dacsLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "xxx");
|
||||
dacsValue= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsValue->MapWindow();
|
||||
dacsValue->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
TGTextButton *b= new TGTextButton(hframe, "Update");
|
||||
hframe->AddFrame( b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
b->MapWindow();
|
||||
b->SetTextJustify(kTextLeft);
|
||||
|
||||
b->Connect("Clicked()","ctbSlowAdc",this,"getValue()");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdc::setLabel(char *tit) {
|
||||
if(tit)
|
||||
dacsLabel->SetText(tit);
|
||||
|
||||
return id;
|
||||
|
||||
}
|
||||
|
||||
string ctbSlowAdc::getLabel() {
|
||||
ostringstream line;
|
||||
line << dacsLabel->GetText() << endl;
|
||||
|
||||
// line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl;
|
||||
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdc::getValue() {
|
||||
try {
|
||||
std::string s;
|
||||
|
||||
// temp
|
||||
if (id == static_cast<int>(slsDetectorDefs::SLOW_ADC_TEMP)) {
|
||||
|
||||
int val = myDet->getTemperature(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "slow adc temp" << " " << val << endl;
|
||||
|
||||
s = to_string(val) + " " + to_string(0x00b0) + "C";//<2F>C
|
||||
dacsValue->SetText(s.c_str());
|
||||
return val;
|
||||
}
|
||||
|
||||
// mv
|
||||
else {
|
||||
|
||||
int val = myDet->getSlowADC(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "slow adc " << id << " " << val << endl;
|
||||
|
||||
s = to_string(val) + " mV";
|
||||
dacsValue->SetText(s.c_str());
|
||||
return val;
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get slow dac " + to_string(id) + ".", "ctbSlowAdc::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctbSlowAdcs::ctbSlowAdcs(TGVerticalFrame *page, sls::Detector *det) : TGGroupFrame(page,"Sense",kVerticalFrame) , myDet(det){
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
|
||||
for (int idac=0; idac<NSLOWADCS + 1; idac++) {
|
||||
|
||||
adcs[idac]=new ctbSlowAdc(this, idac+1000, myDet);
|
||||
|
||||
}
|
||||
adcs[NSLOWADCS]->setLabel((char*)"Temperature");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdcs::setSlowAdcAlias(string line) {
|
||||
|
||||
int is=-1, mv=0;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"SENSE%d %s %d",&is,tit,&mv);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NSLOWADCS)
|
||||
adcs[is]->setLabel(tit);
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbSlowAdcs::getSlowAdcAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NSLOWADCS; i++)
|
||||
line << adcs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbSlowAdcs::getAdcParameters() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NSLOWADCS; i++) {
|
||||
//line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
line << "adc:" << i << " " << adcs[i]->getValue() << endl;
|
||||
}
|
||||
line << "adc:-1" << adcs[NSLOWADCS]->getValue() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbSlowAdcs::update() {
|
||||
for (int idac=0; idac<NSLOWADCS+1; idac++) {
|
||||
adcs[idac]->getValue();
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
#ifndef CTBSLOWADCS_H
|
||||
#define CTBSLOWADCS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
//#define NDACS 16
|
||||
#define NSLOWADCS 8
|
||||
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TGTextButton;
|
||||
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbSlowAdc : public TGHorizontalFrame {
|
||||
|
||||
|
||||
protected:
|
||||
// TGLabel *dacsLabel;
|
||||
// TGNumberEntry *dacsEntry;
|
||||
// TGCheckButton *dacsUnit;
|
||||
TGLabel *dacsLabel;
|
||||
TGLabel *dacsValue;
|
||||
int id;
|
||||
|
||||
sls::Detector* myDet;
|
||||
public:
|
||||
ctbSlowAdc(TGGroupFrame*, int , sls::Detector*);
|
||||
int getValue();
|
||||
|
||||
int setLabel(char *tit);
|
||||
string getLabel();
|
||||
|
||||
|
||||
|
||||
ClassDef(ctbSlowAdc,0)
|
||||
};
|
||||
|
||||
|
||||
class ctbSlowAdcs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
|
||||
|
||||
ctbSlowAdc *adcs[NSLOWADCS+1];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
ctbSlowAdcs(TGVerticalFrame *page, sls::Detector*);
|
||||
|
||||
int setSlowAdcAlias(string line);
|
||||
// int setDacAlias(string line);
|
||||
string getSlowAdcAlias();
|
||||
string getAdcParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbSlowAdcs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -40,6 +40,7 @@ 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
|
||||
@ -53,11 +54,18 @@ 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
|
||||
src/udpconfig.rst
|
||||
src/udpdetspec.rst
|
||||
src/fileformat.rst
|
||||
src/slsreceiverheaderformat.rst
|
||||
src/masterfileattributes.rst
|
||||
src/binaryfileformat.rst
|
||||
src/hdf5fileformat.rst
|
||||
src/zmqjsonheaderformat.rst
|
||||
)
|
||||
|
||||
foreach(filename ${SPHINX_SOURCE_FILES})
|
||||
|
@ -890,7 +890,7 @@ EXCLUDE_SYMLINKS = NO
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS = */docs/* */tests/* */python/* */manual */slsDetectorServers/* */libs/* */integrationTests *README* */slsDetectorGui/* */ctbGui/* */slsDetectorCalibration/*
|
||||
EXCLUDE_PATTERNS = */docs/* */tests/* */python/* */manual */slsDetectorServers/* */libs/* */integrationTests *README* */slsDetectorGui/* */ctbGui/* */slsDetectorCalibration/* *TobiSchluter*
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
|
@ -63,4 +63,4 @@ html_static_path = ['static']
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_stylesheet('css/extra.css') # may also be an URL
|
||||
app.add_css_file('css/extra.css') # may also be an URL
|
||||
|
@ -21,7 +21,7 @@ print('\n\n\n\n SERVER CSV')
|
||||
|
||||
src = Path('@CMAKE_SOURCE_DIR@')/'slsDetectorServers/'
|
||||
detectors = ['Mythen3', 'Gotthard2', 'Eiger',
|
||||
'Jungfrau', 'Moench', 'Gotthard', 'Ctb']
|
||||
'Jungfrau', 'Moench', 'Ctb']
|
||||
|
||||
|
||||
for det in detectors:
|
||||
|
384
docs/src/binaryfileformat.rst
Normal file
384
docs/src/binaryfileformat.rst
Normal file
@ -0,0 +1,384 @@
|
||||
Binary File Format
|
||||
====================
|
||||
|
||||
This is the default file format that can be configured using command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat binary
|
||||
|
||||
|
||||
Master File
|
||||
--------------
|
||||
|
||||
* File Name: [fpath]/[fname]_master_[findex].json :ref:`Details here<file name format>`
|
||||
|
||||
* It is in json format and created for every acquisition.
|
||||
|
||||
* It contains :ref:`attributes<master file attributes>` relevant to the acquisition. This can vary with detector type shown in :ref:`master json file examples <json master file examples>` here.
|
||||
|
||||
* It shows the :ref:`**SLS Receiver Header** <sls receiver header format>` format used in data files.
|
||||
|
||||
* Enabled/disabled using command `fmaster <commandline.html#term-fmaster-0-1>`_.
|
||||
|
||||
|
||||
Data File
|
||||
----------
|
||||
|
||||
* File Name: [fpath]/[fname]_dx_fy_[findex].raw :ref:`Details here<file name format>`
|
||||
|
||||
* It store multiple frames sequentially, with total number of frames determined by `rx_framesperfile <commandline.html#term-rx_framesperfile-n_frames>`_ parameter.
|
||||
|
||||
* Each frame includes a :ref:`**sls_receiver_header** <sls receiver header format>` structure, followed by the actual frame data.
|
||||
|
||||
|
||||
|
||||
.. _json master file examples:
|
||||
|
||||
JSON Master File Examples
|
||||
---------------------------------------------------
|
||||
|
||||
Eiger
|
||||
^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 15:46:30 2024",
|
||||
"Detector Type": "Eiger",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 262144,
|
||||
"Pixels": {
|
||||
"x": 512,
|
||||
"y": 256
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Dynamic Range": 16,
|
||||
"Ten Giga": 0,
|
||||
"Exptime": "1s",
|
||||
"Period": "1s",
|
||||
"Threshold Energy": -1,
|
||||
"Sub Exptime": "2.62144ms",
|
||||
"Sub Period": "2.62144ms",
|
||||
"Quad": 0,
|
||||
"Number of rows": 256,
|
||||
"Rate Corrections": "[0]",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Jungfrau
|
||||
^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 13:03:53 2024",
|
||||
"Detector Type": "Jungfrau",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 1048576,
|
||||
"Pixels": {
|
||||
"x": 1024,
|
||||
"y": 512
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1000,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "10us",
|
||||
"Period": "2ms",
|
||||
"Number of UDP Interfaces": 1,
|
||||
"Number of rows": 512,
|
||||
"Frames in File": 10,
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Gotthard2
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:18:17 2024",
|
||||
"Detector Type": "Gotthard2",
|
||||
"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": 10,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "0ns",
|
||||
"Period": "0ns",
|
||||
"Burst Mode": "burst_internal",
|
||||
"Frames in File": 10,
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
Mythen3
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:39:14 2024",
|
||||
"Detector Type": "Mythen3",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 15360,
|
||||
"Pixels": {
|
||||
"x": 3840,
|
||||
"y": 1
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Dynamic Range": 32,
|
||||
"Ten Giga": 1,
|
||||
"Period": "2ms",
|
||||
"Counter Mask": "0x7",
|
||||
"Exptime1": "0.1s",
|
||||
"Exptime2": "0.1s",
|
||||
"Exptime3": "0.1s",
|
||||
"GateDelay1": "0ns",
|
||||
"GateDelay2": "0ns",
|
||||
"GateDelay3": "0ns",
|
||||
"Gates": 1,
|
||||
"Threshold Energies": "[-1, -1, -1]",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Moench
|
||||
^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:41:32 2024",
|
||||
"Detector Type": "Moench",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 320000,
|
||||
"Pixels": {
|
||||
"x": 400,
|
||||
"y": 400
|
||||
},
|
||||
"Max Frames Per File": 100000,
|
||||
"Frame Discard Policy": "discardpartial",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "10us",
|
||||
"Period": "2ms",
|
||||
"Number of UDP Interfaces": 1,
|
||||
"Number of rows": 400,
|
||||
"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
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 15:32:59 2024",
|
||||
"Detector Type": "ChipTestBoard",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 48018,
|
||||
"Pixels": {
|
||||
"x": 3,
|
||||
"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": "0ns",
|
||||
"Period": "0.18s",
|
||||
"Ten Giga": 0,
|
||||
"ADC Mask": "0x2202",
|
||||
"Analog Flag": 1,
|
||||
"Analog Samples": 8003,
|
||||
"Digital Flag": 0,
|
||||
"Digital Samples": 1000,
|
||||
"Dbit Offset": 0,
|
||||
"Dbit Reorder": 1,
|
||||
"Dbit Bitset": 0,
|
||||
"Transceiver Mask": "0x3",
|
||||
"Transceiver Flag": 0,
|
||||
"Transceiver Samples": 1,
|
||||
"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"
|
||||
}
|
||||
}
|
@ -4,11 +4,54 @@ Command line interface
|
||||
Usage
|
||||
-------------
|
||||
|
||||
Commands can be used either with sls_detector_get or sls_detector_put
|
||||
The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
|
||||
|
||||
Module index
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Modules are indexed based on their order in the hostname command. They are used to configure a specific module within a detector and are followed by a ':' in syntax.
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Applies to all modules of detector 0
|
||||
sls_detector_put exptime 5s
|
||||
|
||||
# Applies to only the 4th module
|
||||
sls_detector_put 3:exptime 5s
|
||||
|
||||
|
||||
Detector index
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
This index is useful when configuring multiple detectors from a single host. Each detector uses a unique shared memory identified by a detector index, derived again from the hostname command. It is followed by a '-'.
|
||||
|
||||
.. code-block::
|
||||
|
||||
# For detector with index 2 in shared memory
|
||||
sls_detector_put 2-hostname bchip133+bchip123+bchip456
|
||||
|
||||
# Without '-', the detector index defaults to 0
|
||||
sls_detector_put hostname bchip133+bchip123+bchip456
|
||||
|
||||
# Accessing all modules with detector index 2
|
||||
sls_detector_put 2-exptime
|
||||
|
||||
# Starting acquisition only for detector with index 2
|
||||
sls_detector_put 2-start
|
||||
|
||||
# Applies only to the 2nd detector, 4th module
|
||||
sls_detector_put 1-3:exptime 5s
|
||||
|
||||
|
||||
Command Execution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Commands can be executed using:
|
||||
|
||||
* **sls_detector_put**: setting values
|
||||
* **sls_detector_get**: getting values
|
||||
* **sls_detector**: automatically infers based on the number of arguments.
|
||||
* **sls_detector_help**: gets help on the specific command
|
||||
* **sls_detector_acquire**: initiates acquisition with the detector. This command blocks until the entire acquisition process is completed.
|
||||
|
||||
.. code-block::
|
||||
|
||||
sls_detector_get vrf
|
||||
|
||||
Help
|
||||
--------
|
||||
@ -24,6 +67,19 @@ Help
|
||||
# get help for a particular command
|
||||
sls_detector_get -h fpath
|
||||
sls_detector_help fpath
|
||||
|
||||
# list of deprecated commands
|
||||
list deprecated
|
||||
|
||||
|
||||
Autocompletion
|
||||
---------------
|
||||
|
||||
bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the main package folder to enable auto completion of commands and arguments for the command line on that shell.
|
||||
|
||||
.. code-block::
|
||||
|
||||
source bash_autocomplete.sh
|
||||
|
||||
|
||||
Commands
|
||||
@ -32,14 +88,14 @@ Commands
|
||||
.. include:: ../commands.rst
|
||||
|
||||
|
||||
Depreciated commands
|
||||
Deprecated commands
|
||||
------------------------
|
||||
|
||||
.. note ::
|
||||
All the dac commands are preceded with the **dac** command. Use command **daclist** to get correct list of dac command arguments for current detector.
|
||||
|
||||
.. csv-table:: Depreciated commands
|
||||
:file: ../depreciated.csv
|
||||
.. csv-table:: Deprecated commands
|
||||
:file: ../deprecated.csv
|
||||
:widths: 35, 35
|
||||
:header-rows: 1
|
||||
|
||||
|
@ -20,8 +20,8 @@ the shared libraries these are needed:
|
||||
Python bindings
|
||||
-----------------------
|
||||
|
||||
* Python > 3.6
|
||||
* pybind11 2.11.0 (packaged in libs)
|
||||
* Python >= 3.8
|
||||
* pybind11 2.13.6 (packaged in libs)
|
||||
|
||||
.. note ::
|
||||
|
||||
|
@ -13,7 +13,6 @@ containing results from all modules. (:ref:`Result class<Result Class>`)
|
||||
|
||||
Here are some :ref:`examples <Cplusplus Api Examples>` on how to use the API.
|
||||
|
||||
.. _Cplusplus Api Examples:
|
||||
.. doxygenclass:: sls::Detector
|
||||
:members:
|
||||
:undoc-members:
|
62
docs/src/fileformat.rst
Normal file
62
docs/src/fileformat.rst
Normal file
@ -0,0 +1,62 @@
|
||||
File format
|
||||
================================
|
||||
|
||||
If `fwrite <commandline.html#term-fwrite-0-1>`_ is enabled, the receiver will write data to files.
|
||||
|
||||
Number of Files
|
||||
----------------
|
||||
|
||||
Every acquisition will create a master file and data files.
|
||||
|
||||
An acquisition can have multiple data files for a single frame. The number of files is determined by the number of UDP ports per module and the number of modules.
|
||||
|
||||
* Every modules has its own receiver process. Every receiver process can have 1 or 2 UDP ports.
|
||||
* Each UDP port will create its own file. Therefore, each receiver can write 1 or 2 files.
|
||||
* So, for example a detector with 4 modules with 2 UDP ports each will create a total of 8 files with file names containing UDP port index **'_d0'** to **'_d7'**.
|
||||
|
||||
A new file containing **'_f[file_index]'** in file name is also created when reaching the maximum frames per file. Configured using `rx_framesperfile <commandline.html#term-rx_framesperfile-n_frames>`_.
|
||||
|
||||
.. _file name format:
|
||||
|
||||
Naming
|
||||
-------
|
||||
| Master File Name: [fpath]/[fname]_master_[findex].[ext]
|
||||
|
||||
|
||||
| Data File Name: [fpath]/[fname]_dx_fy_[findex].[ext]
|
||||
|
||||
* fpath: file path set using command `fpath <commandline.html#term-fpath-path>`_. Default: '/'
|
||||
* fname: file name prefix using command `fname <commandline.html#term-fname-name>`_. Default: "run"
|
||||
* findex: acquisition index using command `findex <commandline.html#term-findex-n_value>`_. Automatically incremented for every acquisition with `sls_detector_acquire <commandline.html#term-acquire>`_ (if `fwrite <commandline.html#term-fwrite-0-1>`_ enabled).
|
||||
* x: unique udp port index. New file per UDP port.
|
||||
* y: file index. New file created after reaching max frames per file.
|
||||
* ext: file extension. Default: "raw"(data file) or "json"(master file)
|
||||
|
||||
|
||||
Some file name examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# first file
|
||||
path-to-file/run_d0_f0_0.raw
|
||||
|
||||
# first file for second UDP port
|
||||
path-to-file/run_d1_f0_0.raw
|
||||
|
||||
# second file after reaching max frames in first file
|
||||
path-to-file/run_d0_f1_0.raw
|
||||
|
||||
# second acquisition, first file
|
||||
path-to-file/run_d0_f0_1.raw
|
||||
|
||||
|
||||
Formats
|
||||
--------
|
||||
|
||||
There are 2 file formats supported by the receiver:
|
||||
|
||||
* Binary - extension .json (master file) or .raw (data files)
|
||||
* HDF5 - extension .h5
|
||||
|
||||
The default is binary. HDF5 can be enabled by compiling the package with HDF5 option enabled. The file format is set using the command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
@ -98,7 +98,7 @@ Upgrade
|
||||
|
||||
* 6.1.2 server has a fix for seamless fpga programming
|
||||
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command 'updatedetectorserver' or 'copydetectorserver'.
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command `updatedetectorserver <commandline.html#term-updatedetectorserver-server_name-with-full-path>`_.
|
||||
|
||||
* Then use command 'programfpga' to only update firmware or use command 'update' to update firmware and server to the latest release.
|
||||
|
||||
@ -131,42 +131,6 @@ Program from console
|
||||
|
||||
|
||||
|
||||
Gotthard I
|
||||
-----------
|
||||
|
||||
Download
|
||||
^^^^^^^^^^^^^
|
||||
- detector server corresponding to package in slsDetectorPackage/serverBin
|
||||
|
||||
- `pof files <https://github.com/slsdetectorgroup/slsDetectorFirmware>`__
|
||||
|
||||
|
||||
.. _firmware upgrade using blaster for blackfin:
|
||||
|
||||
Upgrade
|
||||
^^^^^^^^
|
||||
.. warning ::
|
||||
| Gotthard firmware cannot be upgraded remotely and requires the use of USB-Blaster.
|
||||
| It is generally updated by us.
|
||||
|
||||
#. Download `Altera Quartus software or Quartus programmer <https://fpgasoftware.intel.com/20.1/?edition=standard&platform=linux&product=qprogrammer#tabs-4>`__.
|
||||
|
||||
|
||||
#. Start Quartus programmer, click on Hardware Setup. In the "Currently selected hardware" window, select USB-Blaster.
|
||||
|
||||
#. In the Mode combo box, select "Active Serial Programming".
|
||||
|
||||
#. Plug the end of your USB-Blaster with the adaptor provided to the connector 'AS config' on the Gotthard board.
|
||||
|
||||
#. Click on 'Add file'. Select programming (pof) file provided by us.
|
||||
|
||||
#. Check "Program/Configure" and "Verify". Push the start button. Wait until the programming process is finished.
|
||||
|
||||
#. In case of error messages, check the polarity of cable (that pin1 corresponds) and that the correct programming connector is selected.
|
||||
|
||||
#. Reboot the detector.
|
||||
|
||||
|
||||
Mythen III
|
||||
-----------
|
||||
|
||||
@ -257,7 +221,7 @@ Upgrade
|
||||
|
||||
* 6.1.2 server has a fix for seamless fpga programming
|
||||
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command 'updatedetectorserver' or 'copydetectorserver'.
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command `updatedetectorserver <commandline.html#term-updatedetectorserver-server_name-with-full-path>`_.
|
||||
|
||||
* Then use command 'programfpga' to only update firmware or use command 'update' to update firmware and server to the latest release.
|
||||
|
||||
@ -396,7 +360,3 @@ 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>`.
|
@ -11,7 +11,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CmdProxy.h"
|
||||
#include "Caller.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
@ -37,8 +37,8 @@ int main() {
|
||||
|
||||
std::cout << "Generating command line documentation!\n";
|
||||
|
||||
sls::CmdProxy proxy(nullptr);
|
||||
auto commands = proxy.GetProxyCommands();
|
||||
sls::Caller caller(nullptr);
|
||||
auto commands = caller.getAllCommands();
|
||||
|
||||
std::ofstream fs("commands.rst");
|
||||
fs << ".. glossary::\n";
|
||||
@ -46,7 +46,7 @@ int main() {
|
||||
for (const auto &cmd : commands) {
|
||||
std::ostringstream os;
|
||||
std::cout << cmd << '\n';
|
||||
proxy.Call(cmd, {}, -1, slsDetectorDefs::HELP_ACTION, os);
|
||||
caller.call(cmd, {}, -1, slsDetectorDefs::HELP_ACTION, os);
|
||||
|
||||
auto tmp = os.str().erase(0, cmd.size());
|
||||
auto usage = tmp.substr(0, tmp.find_first_of('\n'));
|
||||
@ -55,9 +55,9 @@ int main() {
|
||||
fs << '\t' << cmd << usage << help << "\n";
|
||||
}
|
||||
|
||||
std::ofstream fs2("depreciated.csv");
|
||||
std::ofstream fs2("deprecated.csv");
|
||||
fs2 << "Old, New\n";
|
||||
auto cmds = proxy.GetDepreciatedCommands();
|
||||
auto cmds = caller.GetDeprecatedCommands();
|
||||
for (auto it : cmds) {
|
||||
fs2 << it.first << ", " << it.second << '\n';
|
||||
}
|
||||
|
89
docs/src/hdf5fileformat.rst
Normal file
89
docs/src/hdf5fileformat.rst
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
|
||||
HDF5 File Format
|
||||
================================
|
||||
|
||||
Compilation
|
||||
-------------
|
||||
|
||||
#. Compile the package with HDF5 option enabled
|
||||
|
||||
#. Using cmk script: ./cmk.sh -hj9 -d [path of hdf5 dir] (-d is optional and for custom installation folder)
|
||||
|
||||
#. Enable using cmake option **-DSLS_USE_HDF5=ON** and **-DCMAKE_INSTALL_PREFIX=/path/to/custom/hdf/installation** (optional).
|
||||
|
||||
|
||||
Setup
|
||||
-------
|
||||
|
||||
#. Start Receiver process
|
||||
|
||||
#. Load config file
|
||||
|
||||
#. Set file format using command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat hdf5
|
||||
|
||||
|
||||
Master File
|
||||
-------------
|
||||
|
||||
* File Name: [fpath]/[fname]_master_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
* It contains :ref:`attributes<master file attributes>` relevant to the acquisition. This can vary with detector type.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/ # Root level
|
||||
|---> entry # entry group
|
||||
| |---> data # data group
|
||||
| |---> column # dataset of each sls_receiver_header member
|
||||
| |---> data
|
||||
| |---> detector header version
|
||||
| |---> detector specific 1
|
||||
| |---> detector specific 2
|
||||
| |---> detector specific 3
|
||||
| |---> detector specific 4
|
||||
| |---> detector type
|
||||
| |---> exp length or sub exposure time
|
||||
| |---> frame number
|
||||
| |---> mod id
|
||||
| |---> packets caught
|
||||
| |---> packets caught bit mask
|
||||
| |---> row
|
||||
| |---> timestamp
|
||||
| |---> instrument # instrument group
|
||||
| |---> beam # beam group
|
||||
| |---> detector # detector group
|
||||
| |---> Master File Attribute 1 # dataset of each master file attribute
|
||||
| |---> Master File Attribute 2
|
||||
| |---> Master File Attribute 3
|
||||
| |---> Master File Attribute ..
|
||||
| |---> sample # sample group
|
||||
|
||||
|
||||
If more than 1 data file per frame:
|
||||
* The dataset of each :ref:`**SLS Receiver Header** <sls receiver header format>` member is a virtual dataset.
|
||||
* **data** dataset is a virtual dataset.
|
||||
|
||||
|
||||
More details regarding master file attributes can be found :ref:`here<master file attributes>`.
|
||||
|
||||
Data File
|
||||
-----------
|
||||
|
||||
* File Name: [fpath]/[fname]_dx_fy_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
|
||||
Virtual Data File
|
||||
------------------
|
||||
|
||||
* File Name: [fpath]/[fname]_virtual_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
* For multiple modules, a virtual file linking data from all the modules is created. The individual files are expected to be present.
|
||||
|
||||
* It is linked in the master file.
|
||||
|
||||
|
@ -12,7 +12,7 @@ Welcome to slsDetectorPackage's documentation!
|
||||
For further documentation, visit the official page: https://www.psi.ch/en/detectors/documentation
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 3
|
||||
:caption: Installation:
|
||||
|
||||
installation
|
||||
@ -36,10 +36,12 @@ Welcome to slsDetectorPackage's documentation!
|
||||
pydetector
|
||||
pyenums
|
||||
pyexamples
|
||||
pyPatternGenerator
|
||||
pattern
|
||||
|
||||
.. toctree::
|
||||
:caption: Command line
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
commandline
|
||||
quick_start_guide
|
||||
@ -79,8 +81,25 @@ Welcome to slsDetectorPackage's documentation!
|
||||
:caption: Receiver
|
||||
:maxdepth: 2
|
||||
|
||||
receivers
|
||||
slsreceiver
|
||||
receivers
|
||||
|
||||
|
||||
.. toctree::
|
||||
:caption: Receiver Files
|
||||
:maxdepth: 3
|
||||
|
||||
fileformat
|
||||
slsreceiverheaderformat
|
||||
masterfileattributes
|
||||
binaryfileformat
|
||||
hdf5fileformat
|
||||
|
||||
.. toctree::
|
||||
:caption: Receiver ZMQ Stream
|
||||
:maxdepth: 2
|
||||
|
||||
zmqjsonheaderformat
|
||||
|
||||
.. toctree::
|
||||
:caption: Troubleshooting
|
||||
|
@ -1,9 +1,4 @@
|
||||
.. warning ::
|
||||
|
||||
Before building from source make sure that you have the
|
||||
:doc:`dependencies <../dependencies>` installed. If installing using conda, conda will
|
||||
manage the dependencies. Avoid also installing packages with pip.
|
||||
|
||||
|
||||
|
||||
.. _Installation:
|
||||
|
||||
@ -11,18 +6,47 @@
|
||||
Installation
|
||||
===============
|
||||
|
||||
Install binaries using conda
|
||||
-------------------------------
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
:backlinks: top
|
||||
|
||||
|
||||
Overview
|
||||
--------------
|
||||
|
||||
The ``slsDetectorPackage`` provides core detector software implemented in C++, along with Python bindings packaged as the ``slsdet`` Python extension module. Choose the option that best fits your environment and use case.
|
||||
|
||||
:ref:`conda pre-built binaries`:
|
||||
Install pre-built binaries for the C++ client, receiver, GUI and the Python API (``slsdet``), simplifying setup across platforms.
|
||||
|
||||
:ref:`pip`:
|
||||
Install only the Python extension module, either by downloading the pre-built library from PyPI or by building the extension locally from source. Available only from v9.2.0 onwards.
|
||||
|
||||
:ref:`build from source`:
|
||||
Compile the entire package yourself, including both the C++ core and the Python bindings, for maximum control and customization. However, make sure that you have the :doc:`dependencies <../dependencies>` installed. If installing using conda, conda will manage the dependencies. Avoid installing packages with pip and conda simultaneously.
|
||||
|
||||
|
||||
|
||||
|
||||
.. _conda pre-built binaries:
|
||||
|
||||
1. Install pre-built binaries using conda (Recommended)
|
||||
--------------------------------------------------------
|
||||
|
||||
Conda is not only useful to manage python environments but can also
|
||||
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
||||
are from the developer branch. Please use released tags for stability.
|
||||
|
||||
We have three different packages available:
|
||||
|
||||
* **slsdetlib** shared libraries and command line utilities
|
||||
* **slsdetgui** GUI
|
||||
* **slsdet** Python bindings
|
||||
We have four different packages available:
|
||||
============== =============================================
|
||||
Package Description
|
||||
============== =============================================
|
||||
slsdetlib shared libraries and command line utilities
|
||||
slsdetgui GUI
|
||||
slsdet Python bindings
|
||||
moenchzmq moench
|
||||
============== =============================================
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -38,7 +62,7 @@ We have three different packages available:
|
||||
|
||||
#ready to use
|
||||
sls_detector_get exptime
|
||||
etc ...
|
||||
...
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
@ -50,14 +74,33 @@ We have three different packages available:
|
||||
conda search slsdet
|
||||
# gui
|
||||
conda search slsdetgui
|
||||
# moench
|
||||
conda search moenchzmq
|
||||
|
||||
|
||||
.. _pip:
|
||||
|
||||
2. Pip
|
||||
-------
|
||||
The Python extension module ``slsdet`` can be installed using pip. This is available from v9.2.0 onwards.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
#Install the Python extension module from PyPI
|
||||
pip install slsdet
|
||||
|
||||
# or install the python extension locally from source
|
||||
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 9.2.0
|
||||
cd slsDetectorPackage
|
||||
pip install .
|
||||
|
||||
|
||||
Build from source
|
||||
-------------------
|
||||
.. _build from source:
|
||||
|
||||
1. Download Source Code from github
|
||||
3. Build from source
|
||||
-------------------------
|
||||
|
||||
3.1. Download Source Code from github
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
@ -72,11 +115,13 @@ Build from source
|
||||
|
||||
|
||||
|
||||
2. Build from Source
|
||||
3.2. Build from Source
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Build using CMake
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
One can either build using cmake or use the in-built cmk.sh script.
|
||||
|
||||
3.2.1. Build using CMake
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -103,7 +148,7 @@ Instead of the cmake command, one can use ccmake to get a list of options to con
|
||||
ccmake ..
|
||||
|
||||
# choose the options
|
||||
# first press [c] - configure (maybe multiple times till you see [g])
|
||||
# first press [c] - configure (until you see [g])
|
||||
# then press [g] - generate
|
||||
|
||||
|
||||
@ -122,8 +167,8 @@ Example cmake options Comment
|
||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||
|
||||
|
||||
Build using in-built cmk.sh script
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
3.2.2. Build using in-built cmk.sh script
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
@ -172,8 +217,8 @@ Build using in-built cmk.sh script
|
||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||
|
||||
|
||||
Build on old distributions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
3.3. Build on old distributions using conda
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||
@ -197,10 +242,11 @@ using this compiler
|
||||
|
||||
|
||||
|
||||
Build slsDetectorGui (Qt5)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
3.4. Build slsDetectorGui (Qt5)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Using pre-built binary on conda
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
conda create -n myenv slsdetgui=7.0.0
|
||||
@ -208,13 +254,22 @@ Build slsDetectorGui (Qt5)
|
||||
|
||||
|
||||
2. Using system installation on RHEL7
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
|
||||
3. Using system installation on RHEL8
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
yum install expat-devel.x86_64
|
||||
|
||||
4. Using conda
|
||||
|
||||
3. Using conda
|
||||
.. code-block:: bash
|
||||
|
||||
#Add channels for dependencies and our library
|
||||
@ -248,8 +303,8 @@ Build slsDetectorGui (Qt5)
|
||||
|
||||
|
||||
|
||||
Build this documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
3.5. Build this documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The documentation for the slsDetectorPackage is build using a combination
|
||||
of Doxygen, Sphinx and Breathe. The easiest way to install the dependencies
|
||||
@ -271,17 +326,19 @@ is to use conda
|
||||
make rst # rst only, saves time in case the API did not change
|
||||
|
||||
|
||||
Pybind and Zeromq
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
4. Pybind and Zeromq
|
||||
-------------------------
|
||||
|
||||
.. _pybind for different slsDetectorPackage versions:
|
||||
|
||||
|
||||
| **Pybind for Python**
|
||||
| v8.0.0+:
|
||||
| pybind11 (v2.11.0) is built
|
||||
| * by default from tar file in repo (libs/pybind/v2.11.0.tar.gz)
|
||||
| **Pybind11 for Python**
|
||||
| v8.0.0+:
|
||||
| pybind11 is built
|
||||
| * by default from tar file in repo (libs/pybind/v2.1x.0.tar.gz)
|
||||
| * or use advanced option SLS_FETCH_PYBIND11_FROM_GITHUB [`link <https://github.com/pybind/pybind11>`__].
|
||||
| * v9.0.0+: pybind11 (v2.13.6)
|
||||
| * v8.x.x : pybind11 (v2.11.0)
|
||||
|
|
||||
| v7.x.x:
|
||||
| pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
||||
@ -312,7 +369,7 @@ Pybind and Zeromq
|
||||
| * or use advanced option SLS_FETCH_ZMQ_FROM_GITHUB [`link <https://github.com/zeromq/libzmq.git>`__].
|
||||
|
|
||||
| v7.x.x and older:
|
||||
| zeromq must be installed and one can hint its location using
|
||||
| zeromq-devel must be installed and one can hint its location using
|
||||
| * cmake option:'-DZeroMQ_HINT=/usr/lib64' or
|
||||
| * option '-q' in cmk.sh script: : ./cmk.sh -cbj5 -q /usr/lib64
|
||||
| * 'zeromq' dependency added when installing using conda
|
||||
|
362
docs/src/masterfileattributes.rst
Normal file
362
docs/src/masterfileattributes.rst
Normal file
@ -0,0 +1,362 @@
|
||||
|
||||
.. _master file attributes:
|
||||
|
||||
Master File Attributes
|
||||
=======================
|
||||
|
||||
These attributes are the same in binary and HDF5 file, but vary depending on detector type.
|
||||
|
||||
|
||||
Eiger
|
||||
^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dynamic Range | Bits per pixel |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | 10GbE enable for data |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Threshold Energy | Threshold energy |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Sub Exptime | Sub exposure time in 32 bit mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Sub Period | Sub period between frames in 32 bit mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Quad | Quad enable (hardware) |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Rate Corrections | Rate Corrections |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
|
||||
Jungfrau
|
||||
^^^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of UDP | Number of UDP Interfaces enabled per module |
|
||||
| Interfaces | |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Gotthard II
|
||||
^^^^^^^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| 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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Mythen3
|
||||
^^^^^^^
|
||||
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dynamic Range | Bits per pixel |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | 10GbE enable for data |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Counter Mask | Mask of counters enabled |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime1 | Exposure time of counter 1 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime2 | Exposure time of counter 2 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime3 | Exposure time of counter 3 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay1 | Gate delay of counter 1 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay2 | Gate delay of counter 2 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay3 | Gate delay of counter 3 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Gates | Number of gates |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Threshold energies | Threshold energy of all 3 counters |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
|
||||
Moench
|
||||
^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of UDP | Number of UDP Interfaces enabled per module |
|
||||
| Interfaces | |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| 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
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | Ten giga enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| ADC Mask | Mask of channels enabled in ADC |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Analog Flag | Analog readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Analog Samples | Number of analog samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Digital Flag | Digital readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Digital Samples | Number of digital samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| 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 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Flag | Transceiver readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Samples | Number of transceiver samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
122
docs/src/pattern.rst
Normal file
122
docs/src/pattern.rst
Normal file
@ -0,0 +1,122 @@
|
||||
Pattern
|
||||
========================
|
||||
|
||||
This is a test and development feature implemented only for Ctb, Xilinx_Ctb and Mythen3.
|
||||
|
||||
A pattern is a sequence of 64-bit words which is executed using a clock on the FPGA. Each of the 64 bits is connected to a pin or internal signal of the FPGA. The purpose of a pattern is to provide a way to change these 64 signals with precise timing. Commands run by the detector server could manipulate the same signals as the pattern, but they cannot enforce a change in a specific clock cycle.
|
||||
|
||||
**Usage**
|
||||
|
||||
A pattern is written to memory on the FPGA using the patword command.
|
||||
|
||||
.. code-block::
|
||||
|
||||
patword 0x0000 0x000000000000000A
|
||||
patword 0x0001 0x000000000000000B
|
||||
patword 0x0002 0x000000000000000C
|
||||
patword 0x0003 0x000000000000000D
|
||||
patword 0x0004 0x000000000000000E
|
||||
|
||||
The example above writes a five-word pattern into FPGA memory. The first argument is the memory address, the second argument is the content to be written into this address. Before executing a pattern one has to set the address limits of the pattern:
|
||||
|
||||
.. code-block::
|
||||
|
||||
patlimits 0x0000 0x0004
|
||||
|
||||
This instructs the firmware to execute the commands from address 0 to 4 (including 0 and 4). The execution can be started from the pyctbgui or with the commands
|
||||
|
||||
.. code-block::
|
||||
|
||||
start [Ctb, Xilinx_Ctb]
|
||||
patternstart [Mythen3]
|
||||
|
||||
The maximal number of patword addresses is 8192. However, it is possible to extend the length of the pattern sequence using loops and wait commands. Loops can be configured with the following commands:
|
||||
|
||||
.. code-block::
|
||||
|
||||
patloop 0 0x0001 0x0003
|
||||
patnloop 0 7
|
||||
|
||||
The first argument of both commands is the ID of the loop. Ctb and Xilinx_Ctb can have 6 loops (ID 0-5), Mythen3 can have 4 loop definitions. The commands above configure the loop with ID 0 to run 7 times and jump from the patword with address 3 to the patword with address 1. Important: If patnloop is set to 1, the addresses 0x1-0x3 will execute exactly once; if it is set to 0, the pattern addresses will be skipped.
|
||||
|
||||
The same idea is used to introduce wait times. The example below causes the patword at address 0x0002 to be active for 9 clock cycles before the execution continues.
|
||||
|
||||
.. code-block::
|
||||
|
||||
patwait 0 0x0002
|
||||
patwaittime 0 9
|
||||
|
||||
Waits can be placed inside a loop and loops can be nested.
|
||||
|
||||
**patioctrl**
|
||||
|
||||
The function of each bit in the sequence of 64-bit words depends on the connected detector and firmware version. Some of the 64 bits might connect directly to pads of a chip. The patioctrl command is used to configure the direction of some of these signals (not all of them !! See tables below). Signals where the corresponding bit in the argument of patioctrl is set to 1 will be driven from the FPGA.
|
||||
|
||||
**patsetbit and patmask**
|
||||
|
||||
The functions patsetbit and patmask can be used to ignore a specific bit of the pattern.
|
||||
Example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
patmask 0x0101
|
||||
patsetbit 0x0001
|
||||
|
||||
Patmask configures bit 0 and 8 of the pattern to be set to their value in patsetbit. These bits will be ignored during pattern execution and will always be 0 (bit 8) and 1 (bit 0).
|
||||
|
||||
The mappings of bit positions in the pattern word to signals/pads of the FPGA are listed below for the three detector types where patterns are used. In the case of the two CTB's, connections of the signals to actual pads of a chip depend on the layout of the used detector adapter board. Therefore, each type of detector adapter board adds an additional mapping layer.
|
||||
|
||||
**CTB Pattern Bit Mapping**
|
||||
|
||||
.. table::
|
||||
|
||||
+----+---+------+----+----------+-------------------+----------------+
|
||||
| 63 | 62| 61-57| 56 | 55-48 | 47-32 | 31-0 |
|
||||
+----+---+------+----+----------+-------------------+----------------+
|
||||
| A | D| --- | T | EXTIO | DO, stream source | DIO |
|
||||
+----+---+------+----+----------+-------------------+----------------+
|
||||
|
||||
DIO: Driving the 32 FPGA pins corresponding to the lowest 32 bits of the patioctrl command. If bits in patioctrl are 0, the same bit positions in DIO will switch to input pins and connect to dbit sampling. Additionally, some of these 32 bits have an automatic override by detector-specific statemachines which is active whenever one of these statemachines is running (currently bits 7,8,11,14 and 20).
|
||||
|
||||
DO: Directly connected to 16 FPGA pins. Output only. Not influenced by patioctrl. Also connected to bit 47-32 in all Ctb dbit samples. All of them can be used as dbit sample trigger. In addition, every bit of DO can be selected as trigger for sending out a udp packet with samples to the receiver.
|
||||
|
||||
EXTIO: Similar to DIO, but not used as input to the fpga. With the corresponding patioctrl bits set to 0 these pins will switch to a high impedance mode and be ignored by the firmware.
|
||||
|
||||
T: trigger output
|
||||
|
||||
D: enable signal for digital sampling
|
||||
|
||||
A: adc enable
|
||||
|
||||
**Xilinx_CTB Pattern Bit Mapping**
|
||||
|
||||
.. table::
|
||||
|
||||
+-------+----------------+
|
||||
| 63-32 | 31-0 |
|
||||
+-------+----------------+
|
||||
| --- | DIO |
|
||||
+-------+----------------+
|
||||
|
||||
DIO: Driving the 32 FPGA pins corresponding to the lowest 32 bits of the patioctrl command. If bits in patioctrl are 0, the same bit positions in DIO will switch to input pins and connect to dbit sampling. Additionally, some of these 32 bits have an automatic override by detector-specific statemachines which is active whenever these sm's are running (currently bits 7,8,11,14 and 20).
|
||||
|
||||
|
||||
**Mythen3 Pattern Bit Mapping**
|
||||
|
||||
.. table::
|
||||
|
||||
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||
| 63-33 | 32 | 31-25 | 24 | 23 | 22 | 21 | 20 | 19 |
|
||||
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||
| --- | signARD| --- | CHSclk | cnt_rst | sto_rst | STATLOAD | STO | SIN |
|
||||
+-------+--------+-------+--------+------------+----------+----------+-----+-----+
|
||||
|
||||
.. table::
|
||||
|
||||
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||
| 18 | 17 | 16-14 | 13 | 12 | 11 | 10 | 9-0 |
|
||||
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||
| SR_MODE | clk | EN | PULSE | RD | CHSIN | ANAMode | TBLOAD |
|
||||
+---------+-----+-------+-------+----+-------+---------+--------+
|
||||
|
||||
For Mythen3 the pattern word only connects to output pins of the FPGA when the pattern is running. Afterwards the signals will switch back to other logic in the FPGA. Both CTB's hold the last executed pattern word until a new pattern is started.
|
34
docs/src/pyPatternGenerator.rst
Normal file
34
docs/src/pyPatternGenerator.rst
Normal file
@ -0,0 +1,34 @@
|
||||
PatternGenerator
|
||||
=====================================================
|
||||
|
||||
Python class to generate patterns for the Chip Test Board.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from slsdet import PatternGenerator
|
||||
|
||||
p = PatternGenerator()
|
||||
p.SB(5)
|
||||
p.PW()
|
||||
p.SB(8,9)
|
||||
p.PW()
|
||||
p.CB(5)
|
||||
|
||||
Created a pattern like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
patword 0x0000 0x0000000000000020
|
||||
patword 0x0001 0x0000000000000320
|
||||
patword 0x0002 0x0000000000000300
|
||||
patioctrl 0x0000000000000000
|
||||
patlimits 0x0000 0x0002
|
||||
...
|
||||
|
||||
.. py:currentmodule:: slsdet
|
||||
|
||||
.. autoclass:: PatternGenerator
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
@ -6,7 +6,7 @@ Getting Started
|
||||
Which Python?
|
||||
--------------------
|
||||
|
||||
We require at least Python 3.6 and strongly recommended that you don't use the system
|
||||
We require at least Python 3.8 and strongly recommended that you don't use the system
|
||||
Python installation. The examples in this documentation uses `conda
|
||||
<https://docs.conda.io/en/latest/miniconda.html>`_ since it provides good support
|
||||
also for non Python packages but there are also other alternatives like, pyenv.
|
||||
|
@ -128,6 +128,10 @@ For Multiple Modules
|
||||
# set file path
|
||||
fpath /tmp
|
||||
|
||||
.. note ::
|
||||
The **hostname** and **detsize** command in a multi module system can affect the row and column values in the udp/zmq header. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
|
||||
|
||||
|
||||
Gui
|
||||
----
|
||||
|
||||
|
@ -1,25 +1,25 @@
|
||||
Receivers
|
||||
Custom Receiver
|
||||
=================
|
||||
|
||||
Receiver processes can be run on same or different machines as the client, receives the data from the detector (via UDP packets).
|
||||
When using the slsReceiver/ slsMultiReceiver, they can be further configured by the client control software (via TCP/IP) to set file name, file path, progress of acquisition etc.
|
||||
The receiver essentially listens to UDP data packets sent out by the detector.
|
||||
|
||||
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
||||
|
||||
|
||||
To know more about detector receiver configuration, please check out :ref:`detector udp header and udp commands in the config file <detector udp header>`
|
||||
| Please note the following when using a custom receiver:
|
||||
|
||||
Custom Receiver
|
||||
----------------
|
||||
* **udp_dstmac** must be configured in the config file. This parameter is not required when using an in-built receiver.
|
||||
|
||||
| When using custom receiver with our package, ensure that **udp_dstmac** is also configured in the config file. This parameter is not required when using slsReceiver.
|
||||
* Cannot use "auto" for **udp_dstip**.
|
||||
|
||||
| Cannot use "auto" for **udp_dstip**.
|
||||
* No **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
||||
|
||||
| Also ensure that there are no **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
||||
|
||||
|
||||
The main difference is the lack of **rx_** commands or file commands (eg. **f**write, **f**path) and the **udp_dstmac** is required in config file.
|
||||
|
||||
Example of a custom receiver config file
|
||||
|
||||
* The main difference is the lack of **rx_** commands or file commands (eg. fwrite, fpath) and the udp_dstmac is required in config file.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# detector hostname
|
||||
|
@ -89,18 +89,3 @@ 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,25 +27,24 @@ 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][Gotthard][Gotthard2][Moench]
|
||||
-i, --ignore-config : [Eiger][Jungfrau][Gotthard2][Moench]
|
||||
Ignore config file.
|
||||
-m, --master <master> : [Eiger][Mythen3][Gotthard][Gotthard2]
|
||||
-m, --master <master> : [Eiger][Mythen3][Gotthard2]
|
||||
Set Master to 0 or 1. Precedence over config file. Only for virtual servers except Eiger.
|
||||
-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
|
||||
|
||||
|
||||
.. _Automatic start servers:
|
||||
|
||||
Automatic start
|
||||
------------------
|
||||
|
||||
One can start the on-board detector server automatically upon powering on the board.
|
||||
|
||||
#. Create a soft link to the binary on board
|
||||
:
|
||||
#. Create a soft link to the binary on board:
|
||||
.. code-block:: bash
|
||||
|
||||
ln -sf someDetectorServervx.x.x someDetectorServer
|
||||
@ -65,7 +64,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 | Gotthard I
|
||||
Jungfrau | Moench | CTB
|
||||
.. code-block:: bash
|
||||
|
||||
# Edit inittab on board
|
||||
@ -87,8 +86,7 @@ One can start the on-board detector server automatically upon powering on the bo
|
||||
/root/xxxDetectorServer >> /dev/null &
|
||||
|
||||
|
||||
#. Sync, reboot and verify
|
||||
:
|
||||
#. Sync, reboot and verify:
|
||||
.. code-block:: bash
|
||||
|
||||
sync
|
||||
|
@ -1,4 +1,5 @@
|
||||
.. _Detector Server Upgrade:
|
||||
|
||||
Upgrade
|
||||
========
|
||||
|
||||
|
@ -1,16 +1,55 @@
|
||||
slsReceiver/ slsMultiReceiver
|
||||
In-built Receiver
|
||||
================================
|
||||
|
||||
| One has to start the slsReceiver before loading config file or using any receiver commands (prefix: **rx_** )
|
||||
|
||||
|
||||
The receiver essentially listens to UDP data packets sent out by the detector. It's main features are:
|
||||
|
||||
- **Listening**: Receives UDP data from the detector.
|
||||
- **Writing to File**: Optionally writes received data to disk.
|
||||
- **Streaming via ZMQ**: Optionally streams out the data using ZeroMQ.
|
||||
|
||||
Each of these operations runs asynchronously and in parallel for each UDP port.
|
||||
|
||||
|
||||
.. note ::
|
||||
|
||||
* Can be run on the same or different machine as the client.
|
||||
* Can be configured by the client. (set file name/ discard policy, get progress etc.)
|
||||
* Has to be started before the client runs any receiver specific command.
|
||||
|
||||
|
||||
Receiver Variants
|
||||
-----------------
|
||||
There are three main receiver types. How to start them is described :ref:`below<Starting up the Receiver>`.
|
||||
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
| Receiver Type | slsReceiver | slsMultiReceiver |slsFrameSynchronizer |
|
||||
+======================+====================+=========================================+================================+
|
||||
| Modules Supported | 1 | Multiple | Multiple |
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
| Internal Architecture| Threads per porttt | Multiple child processes of slsReceiver | Multi-threading of slsReceiver |
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
| ZMQ Streaming | Disabled by default| Disabled by default | Enabled, not optional |
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
| ZMQ Synchronization | No | No | Yes, across ports |
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
| Image Reconstruction | No | No | No |
|
||||
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
.. _Starting up the Receiver:
|
||||
|
||||
Starting up the Receiver
|
||||
-------------------------
|
||||
For a Single Module
|
||||
.. code-block:: bash
|
||||
|
||||
slsReceiver # default port 1954
|
||||
|
||||
# default port 1954
|
||||
slsReceiver
|
||||
|
||||
# custom port 2012
|
||||
slsReceiver -t2012
|
||||
slsReceiver -t2012 # custom port 2012
|
||||
|
||||
|
||||
For Multiple Modules
|
||||
@ -18,57 +57,66 @@ For Multiple Modules
|
||||
|
||||
# each receiver (for each module) requires a unique tcp port (if all on same machine)
|
||||
|
||||
# using slsReceiver in multiple consoles
|
||||
# option 1 (one for each module)
|
||||
slsReceiver
|
||||
slsReceiver -t1955
|
||||
|
||||
# slsMultiReceiver [starting port] [number of receivers]
|
||||
# option 2
|
||||
slsMultiReceiver 2012 2
|
||||
|
||||
# slsMultiReceiver [starting port] [number of receivers] [print each frame header for debugging]
|
||||
slsMultiReceiver 2012 2 1
|
||||
# option 3
|
||||
slsFrameSynchronizer 2012 2
|
||||
|
||||
|
||||
|
||||
Client Commands
|
||||
-----------------
|
||||
|
||||
| One can remove **udp_dstmac** from the config file, as the slsReceiver fetches this from the **udp_ip**.
|
||||
* Client commands to the receiver begin with **rx_** or **f_** (file commands).
|
||||
|
||||
| One can use "auto" for **udp_dstip** if one wants to use default ip of **rx_hostname**.
|
||||
* **rx_hostname** has to be the first command to the receiver so the client knows which receiver process to communicate with.
|
||||
|
||||
| The first command to the receiver (**rx_** commands) should be **rx_hostname**. The following are the different ways to establish contact.
|
||||
* Can use 'auto' for **udp_dstip** if using 1GbE interface or the :ref:`virtual simulators<Virtual Detector Servers>`.
|
||||
|
||||
|
||||
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
||||
|
||||
|
||||
The following are the different ways to establish contact using **rx_hostname** command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# default receiver tcp port (1954)
|
||||
# ---single module---
|
||||
|
||||
# default receiver port at 1954
|
||||
rx_hostname xxx
|
||||
|
||||
# custom receiver port
|
||||
rx_hostname xxx:1957 # option 1
|
||||
|
||||
rx_tcpport 1957 # option 2
|
||||
rx_hostname xxx
|
||||
|
||||
# custom receiver port
|
||||
rx_hostname xxx:1957
|
||||
|
||||
# custom receiver port
|
||||
rx_tcpport 1954
|
||||
rx_hostname xxx
|
||||
# ---multi module---
|
||||
|
||||
# multi modules with custom ports
|
||||
rx_hostname xxx:1955+xxx:1956+
|
||||
|
||||
|
||||
# multi modules using increasing tcp ports when using multi detector command
|
||||
# using increasing tcp ports
|
||||
rx_tcpport 1955
|
||||
rx_hostname xxx
|
||||
|
||||
# or specify multi modules with custom ports on same rxr pc
|
||||
0:rx_tcpport 1954
|
||||
# custom ports
|
||||
rx_hostname xxx:1955+xxx:1958+ # option 1
|
||||
|
||||
0:rx_tcpport 1954 # option 2
|
||||
1:rx_tcpport 1955
|
||||
2:rx_tcpport 1956
|
||||
rx_hostname xxx
|
||||
|
||||
# multi modules with custom ports on different rxr pc
|
||||
# custom ports on different receiver machines
|
||||
0:rx_tcpport 1954
|
||||
0:rx_hostname xxx
|
||||
1:rx_tcpport 1955
|
||||
1:rx_hostname yyy
|
||||
1:rx_hostname yyyrxr
|
||||
|
||||
|
||||
| Example commands:
|
||||
@ -91,245 +139,32 @@ Client Commands
|
||||
sls_detector_get -h rx_framescaught
|
||||
|
||||
|
||||
ZMQ: Json Header Format
|
||||
------------------------
|
||||
Example of a config file using in-built receiver
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
**Change in field names from slsDetectorPackage v6.x.x to v7.0.0**
|
||||
# detector hostname
|
||||
hostname bchip052+bchip053+
|
||||
|
||||
* detSpec1 <- bunchId
|
||||
* detSpec2 <- reserved
|
||||
* detSpec3 <- debug
|
||||
* detSpec4 <- roundRNumber
|
||||
# udp destination port (receiver)
|
||||
# sets increasing destination udp ports starting at 50004
|
||||
udp_dstport 50004
|
||||
|
||||
# udp destination ip (receiver)
|
||||
0:udp_dstip 10.0.1.100
|
||||
1:udp_dstip 10.0.2.100
|
||||
|
||||
**Format**
|
||||
# udp source ip (same subnet as udp_dstip)
|
||||
0:udp_srcip 10.0.1.184
|
||||
1:udp_srcip 10.0.2.184
|
||||
|
||||
.. code-block:: bash
|
||||
# udp destination mac - not required (picked up from udp_dstip)
|
||||
#udp_dstmac 22:47:d5:48:ad:ef
|
||||
|
||||
{
|
||||
"jsonversion": unsigned int,
|
||||
"bitmode": unsigned int,
|
||||
"fileIndex": unsigned long int,
|
||||
"detshape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"shape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"size": unsigned int,
|
||||
"acqIndex": unsigned long int,
|
||||
"frameIndex": unsigned long int,
|
||||
"progress": double,
|
||||
"fname": string,
|
||||
"data": unsigned int,
|
||||
"completeImage": unsigned int,
|
||||
# connects to receivers at increasing tcp port starting at 1954
|
||||
rx_hostname mpc3434
|
||||
# same as rx_hostname mpc3434:1954+mpc3434:1955+
|
||||
|
||||
"frameNumber": unsigned long long int,
|
||||
"expLength": unsigned int,
|
||||
"packetNumber": unsigned int,
|
||||
"detSpec1": unsigned long int,
|
||||
"timestamp": unsigned long int,
|
||||
"modId": unsigned int,
|
||||
"row": unsigned int,
|
||||
"column": unsigned int,
|
||||
"detSpec2": unsigned int,
|
||||
"detSpec3": unsigned int,
|
||||
"detSpec4": unsigned int,
|
||||
"detType": unsigned int,
|
||||
"version": unsigned int,
|
||||
|
||||
"flipRows": unsigned int,
|
||||
"quad": unsigned int,
|
||||
"addJsonHeader": {
|
||||
string : string
|
||||
}
|
||||
}
|
||||
|
||||
+--------------+----------------------------------------------+
|
||||
| Field | Description |
|
||||
+--------------+----------------------------------------------+
|
||||
| jsonversion | Version of the json header. |
|
||||
| | Value at 4 for v6.x.x and v7.x.x |
|
||||
+--------------+----------------------------------------------+
|
||||
| bitmode | Bits per pixel [4|8|16|32] |
|
||||
+--------------+----------------------------------------------+
|
||||
| fileIndex | Current file acquisition index |
|
||||
+--------------+----------------------------------------------+
|
||||
| detshape | Geometry of the entire detector |
|
||||
+--------------+----------------------------------------------+
|
||||
| shape | Geometry of the current port streamed out |
|
||||
+--------------+----------------------------------------------+
|
||||
| size | Size of image of current port in bytesout |
|
||||
+--------------+----------------------------------------------+
|
||||
| acqIndex | Frame number from the detector (redundant) |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameIndex | Frame number of current acquisition |
|
||||
| | (Starting at 0) |
|
||||
+--------------+----------------------------------------------+
|
||||
| progress | Progress of current acquisition in % |
|
||||
+--------------+----------------------------------------------+
|
||||
| fname | Current file name |
|
||||
+--------------+----------------------------------------------+
|
||||
| data | 1 if there is data following |
|
||||
| | 0 if dummy header |
|
||||
+--------------+----------------------------------------------+
|
||||
| completeImage| 1 if no missing packets for this frame |
|
||||
| | in this port, else 0 |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameNumber | Frame number |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| expLength | subframe number (32 bit eiger) |
|
||||
| | or real time exposure time in 100ns (others) |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| packetNumber | Number of packets caught for that frame |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec1 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| timestamp | Timestamp with 10 MHz clock |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| modId | Module Id |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| row | Row number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| column | Column number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec2 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec3 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec4 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detType | Detector type enum |
|
||||
| detSpec3 | See :ref:`Detector enum<Detector Enum>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| version | Detector header version. At 2 |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| flipRows | 1 if rows should be flipped. |
|
||||
| | Usually for Eiger bottom. |
|
||||
+--------------+----------------------------------------------+
|
||||
| quad | 1 if its an Eiger quad. |
|
||||
+--------------+----------------------------------------------+
|
||||
| addJsonHeader| Optional custom parameters that is required |
|
||||
| | for processing code. |
|
||||
+--------------+----------------------------------------------+
|
||||
|
||||
|
||||
SLS Receiver Header Format
|
||||
--------------------------
|
||||
|
||||
It is 112 bytes and consists of:
|
||||
* 48 bytes of the SLS Detector Header (described in :ref:`the current detector header <detector udp header>`)
|
||||
* 64 bytes of packet mask
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
struct sls_receiver_header {
|
||||
sls_detector_header detHeader; /**< is the detector header */
|
||||
sls_bitset packetsMask; /**< is the packets caught bit mask */
|
||||
};
|
||||
|
||||
|
||||
.. note ::
|
||||
|
||||
| The packetNumber in the SLS Receiver Header will be modified to number of packets caught by receiver for that frame. For eg. Jungfrau will have 128 packets per frame. If it is less, then this is a partial frame due to missing packets.
|
||||
|
||||
| Furthermore, the bit mask will specify which packets have been received.
|
||||
|
||||
|
||||
|
||||
|
||||
File format
|
||||
--------------
|
||||
|
||||
Master file is in json format.
|
||||
|
||||
The file name format is [fpath]/[fname]_dx_fy_[findex].raw, where x is module index and y is file index. **fname** is file name prefix and by default "run". **fpath** is '/' by default.
|
||||
|
||||
|
||||
Each acquisition will have an increasing acquisition index or findex (if file write enabled). This can be retrieved by using **findex** command.
|
||||
|
||||
|
||||
Each acquisition can have multiple files (the file index number **y**), with **rx_framesperfile** being the maximum number of frames per file. The default varies for each detector type.
|
||||
|
||||
|
||||
Some file name examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# first file
|
||||
path-to-file/run_d0_f0_0.raw
|
||||
|
||||
# second file after reaching max frames in first file
|
||||
path-to-file/run_d0_f1_0.raw
|
||||
|
||||
# second acquisition, first file
|
||||
path-to-file/run_d0_f0_1.raw
|
||||
|
||||
|
||||
Each acquisition will create a master file that can be enabled/disabled using **fmaster**. This should have parameters relevant to the acquisition.
|
||||
|
||||
|
||||
**Binary file format**
|
||||
|
||||
This is the default file format.
|
||||
|
||||
|
||||
Each data file will consist of frames, each consisting of slsReceiver Header followed by data for 1 frame.
|
||||
|
||||
|
||||
Master file is of ASCII format and will also include the format of the slsReceiver Header.
|
||||
|
||||
|
||||
**HDF5 file formats**
|
||||
|
||||
#. Compile the package with HDF5 option enabled
|
||||
|
||||
#. Using cmk script: ./cmk.sh -hj9 -d [path of hdf5 dir]
|
||||
|
||||
#. Enable using cmake **-DCMAKE_INSTALL_PREFIX=/path/to/hdf/installation** and **-DSLS_USE_HDF5=ON**
|
||||
|
||||
#. Start Receiver process
|
||||
|
||||
#. Load config file
|
||||
|
||||
#. Set file format from client or in config file
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat hdf5
|
||||
|
||||
|
||||
| For multiple, modules, a virtual file linking all the modules is created. Both the data files and virtual files are linked in the master file.
|
||||
|
||||
|
||||
Performance
|
||||
|
40
docs/src/slsreceiverheaderformat.rst
Normal file
40
docs/src/slsreceiverheaderformat.rst
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
.. _sls receiver header format:
|
||||
|
||||
SLS Receiver Header Format
|
||||
====================================================
|
||||
|
||||
It is 112 bytes and consists of:
|
||||
* 48 bytes of the SLS Detector Header
|
||||
* 64 bytes of packet mask
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
struct sls_receiver_header {
|
||||
sls_detector_header detHeader; /**< is the detector header */
|
||||
sls_bitset packetsMask; /**< is the packets caught bit mask */
|
||||
};
|
||||
|
||||
|
||||
|
||||
| **sls_detector_header** (described in :ref:`the current detector header <detector udp header>`)
|
||||
|
||||
| The **packetNumber** from detector UDP header is modified in **sls_receiver_header** to number of packets caught by receiver for that frame and the bit mask for each packet caught is the **packetsMask**. The packetsMask is a total of 512 bits due to the largest number of packets per frame among our detectors.
|
||||
|
||||
| For eg. Jungfrau has 128 packets per frame. If **packetNumeber** is 128, then this frame is complete. If it is 127 or less, it is a partial frame due to missing packets. If one would still like to use it, the **packetsMask** will specify which packet has been received or is missing.
|
@ -22,6 +22,8 @@ Common
|
||||
* Check transeiver and fibers are compatible (all MMF 850nm or all SMF 1030nm)
|
||||
* Check fiber
|
||||
* Check fiber polarity (if short range, unplug the link anywhere, and look at the light/dark pattern: dark has to mate with light)
|
||||
* For Jungfrau, check if the blue sfp light is blinking rapidly (even when it is not sending data). If so, most likely the link is down and something is wrong with the board. If it connected to a switch, then you do not see it with the ethtool command if link is down. One option is to connect it directly to a pc to see if link is down.
|
||||
* With nc, try "nc -u -p 50001 -l" in receiving pc, and from another pc try "echo hallo | nc -u 10.1.2.172 50001" to send something to the recieving pc interface to see if the link is up and see if the other nc console receives the hallo.
|
||||
|
||||
#. Detector is not acquiring (Not Eiger)
|
||||
* Take an acquisition with many images and using the following steps instead of acquire:
|
||||
@ -47,11 +49,20 @@ Common
|
||||
* Ensure that the interfaces (on NIC and the switch) used in receiver pc have MTU 9000 (jumbo frames) enabled.
|
||||
|
||||
|
||||
#. Check if 'rx_frames' counter in 'ifconfig' do not increment for interface.
|
||||
#. Check if 'rx packets' counter in 'ifconfig' do not increment for interface.
|
||||
* If no, check switch configuration if present. Port counters of switch can also help to identify problem.
|
||||
* If yes, but receiver software does not see it:
|
||||
|
||||
* Check no firewall (eg. firewalld) is present or add rules
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Stop and disable firewall
|
||||
service firewalld stop
|
||||
systemctl disable firewalld
|
||||
# Check status
|
||||
service firewalld status
|
||||
|
||||
* Check that selinux is disabled ( or add rules)
|
||||
|
||||
#. Source UDP IP in config file (Not Eiger)
|
||||
@ -374,13 +385,13 @@ 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
|
||||
----------
|
||||
|
||||
Mythen3
|
||||
--------
|
||||
|
||||
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.
|
||||
Detector status is waiting even in auto timing mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Check if the control board or the flat band cable is connected properly. If not, connect them properly and try again.
|
||||
|
||||
|
||||
Jungfrau
|
||||
|
@ -1,4 +1,4 @@
|
||||
.. _detector udp header:
|
||||
.. _detector udp header config:
|
||||
|
||||
|
||||
Config file
|
||||
|
@ -3,7 +3,7 @@
|
||||
Format
|
||||
=======
|
||||
|
||||
The UDP data format for the packets consist of a common header for all detectors, followed by the data for that one packet.
|
||||
The UDP data format for the packets consist of a common header of 48 bytes for all detectors, followed by the data for that one packet.
|
||||
|
||||
|
||||
Current Version
|
||||
@ -11,6 +11,25 @@ Current Version
|
||||
|
||||
**v2.0 (slsDetectorPackage v7.0.0+)**
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
|
||||
.. table:: <---------------------------------------------------- 8 bytes per row --------------------------------------------->
|
||||
:align: center
|
||||
:widths: 30,30,30,15,15
|
||||
@ -54,15 +73,17 @@ Description
|
||||
|
||||
* **modId**: module ID picked up from det_id_[detector type].txt on the detector cpu.
|
||||
|
||||
* **row**: row position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command.
|
||||
* **row**: row position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
|
||||
|
||||
* **column**: column position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command.
|
||||
* **column**: column position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
|
||||
|
||||
* **detType**: detector type from enum of detectorType in the package.
|
||||
|
||||
* **version**: current version of the detector header (0x2).
|
||||
|
||||
|
||||
.. _detector enum:
|
||||
|
||||
Detector Enum
|
||||
--------------
|
||||
|
||||
@ -71,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
|
||||
|
@ -1,4 +1,5 @@
|
||||
.. _Virtual Detector Servers:
|
||||
|
||||
Simulators
|
||||
===========
|
||||
|
||||
@ -22,7 +23,6 @@ Binaries
|
||||
|
||||
eigerDetectorServer_virtual
|
||||
jungfrauDetectorServer_virtual
|
||||
gotthardDetectorServer_virtual
|
||||
gotthard2DetectorServer_virtual
|
||||
mythen3DetectorServer_virtual
|
||||
moenchDetectorServer_virtual
|
||||
|
137
docs/src/zmqjsonheaderformat.rst
Normal file
137
docs/src/zmqjsonheaderformat.rst
Normal file
@ -0,0 +1,137 @@
|
||||
ZMQ: Json Header Format
|
||||
========================
|
||||
|
||||
|
||||
**Change in field names from slsDetectorPackage v6.x.x to v7.0.0**
|
||||
|
||||
* detSpec1 <- bunchId
|
||||
* detSpec2 <- reserved
|
||||
* detSpec3 <- debug
|
||||
* detSpec4 <- roundRNumber
|
||||
|
||||
|
||||
**Format**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"jsonversion": unsigned int,
|
||||
"bitmode": unsigned int,
|
||||
"fileIndex": unsigned long int,
|
||||
"detshape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"shape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"size": unsigned int,
|
||||
"acqIndex": unsigned long int,
|
||||
"frameIndex": unsigned long int,
|
||||
"progress": double,
|
||||
"fname": string,
|
||||
"data": unsigned int,
|
||||
"completeImage": unsigned int,
|
||||
|
||||
"frameNumber": unsigned long long int,
|
||||
"expLength": unsigned int,
|
||||
"packetNumber": unsigned int,
|
||||
"detSpec1": unsigned long int,
|
||||
"timestamp": unsigned long int,
|
||||
"modId": unsigned int,
|
||||
"row": unsigned int,
|
||||
"column": unsigned int,
|
||||
"detSpec2": unsigned int,
|
||||
"detSpec3": unsigned int,
|
||||
"detSpec4": unsigned int,
|
||||
"detType": unsigned int,
|
||||
"version": unsigned int,
|
||||
|
||||
"flipRows": unsigned int,
|
||||
"quad": unsigned int,
|
||||
"addJsonHeader": {
|
||||
string : string
|
||||
}
|
||||
}
|
||||
|
||||
+--------------+----------------------------------------------+
|
||||
| Field | Description |
|
||||
+--------------+----------------------------------------------+
|
||||
| jsonversion | Version of the json header. |
|
||||
| | Value at 4 for v6.x.x and v7.x.x |
|
||||
+--------------+----------------------------------------------+
|
||||
| bitmode | Bits per pixel [4|8|16|32] |
|
||||
+--------------+----------------------------------------------+
|
||||
| fileIndex | Current file acquisition index |
|
||||
+--------------+----------------------------------------------+
|
||||
| detshape | Geometry of the entire detector |
|
||||
+--------------+----------------------------------------------+
|
||||
| shape | Geometry of the current port streamed out |
|
||||
+--------------+----------------------------------------------+
|
||||
| size | Size of image of current port in bytesout |
|
||||
+--------------+----------------------------------------------+
|
||||
| acqIndex | Frame number from the detector (redundant) |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameIndex | Frame number of current acquisition |
|
||||
| | (Starting at 0) |
|
||||
+--------------+----------------------------------------------+
|
||||
| progress | Progress of current acquisition in % |
|
||||
+--------------+----------------------------------------------+
|
||||
| fname | Current file name |
|
||||
+--------------+----------------------------------------------+
|
||||
| data | 1 if there is data following |
|
||||
| | 0 if dummy header |
|
||||
+--------------+----------------------------------------------+
|
||||
| completeImage| 1 if no missing packets for this frame |
|
||||
| | in this port, else 0 |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameNumber | Frame number |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| expLength | subframe number (32 bit eiger) |
|
||||
| | or real time exposure time in 100ns (others) |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| packetNumber | Number of packets caught for that frame |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec1 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| timestamp | Timestamp with 10 MHz clock |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| modId | Module Id |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| row | Row number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| column | Column number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec2 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec3 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec4 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detType | Detector type enum |
|
||||
| detSpec3 | See :ref:`Detector enum<detector enum>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| version | Detector header version. At 2 |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| flipRows | 1 if rows should be flipped. |
|
||||
| | Usually for Eiger bottom. |
|
||||
+--------------+----------------------------------------------+
|
||||
| quad | 1 if its an Eiger quad. |
|
||||
+--------------+----------------------------------------------+
|
||||
| addJsonHeader| Optional custom parameters that is required |
|
||||
| | for processing code. |
|
||||
+--------------+----------------------------------------------+
|
||||
|
@ -1,12 +0,0 @@
|
||||
# detector hostname
|
||||
hostname bchip007
|
||||
|
||||
# receiver pc hostname of 1Gb IP of the machine
|
||||
rx_hostname my_receiver_hostname
|
||||
|
||||
# output directory
|
||||
fpath /bigRAID/datadir_gotthard/rec_test_data
|
||||
|
||||
# high voltage
|
||||
highvoltage 120
|
||||
|
18
libs/libzmq/libzmq_cmake_version.patch
Normal file
18
libs/libzmq/libzmq_cmake_version.patch
Normal file
@ -0,0 +1,18 @@
|
||||
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)
|
Binary file not shown.
BIN
libs/pybind11/v2.13.6.tar.gz
Normal file
BIN
libs/pybind11/v2.13.6.tar.gz
Normal file
Binary file not shown.
@ -316,7 +316,8 @@ struct GenericStringRef {
|
||||
|
||||
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
|
||||
|
||||
GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
|
||||
// Removed to fix failing build in GCC 14
|
||||
// GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
|
||||
|
||||
//! implicit conversion to plain CharType pointer
|
||||
operator const Ch *() const { return s; }
|
||||
|
@ -9,4 +9,9 @@ slsDetectorPackage/8.0.0_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.1_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||
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
|
||||
slsDetectorPackage/9.1.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/9.2.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
|
35
pyctbgui/.github/workflows/build-and-test-inplace.yml
vendored
Normal file
35
pyctbgui/.github/workflows/build-and-test-inplace.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Build inplace, run tests and linting
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [ "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ".[dev]"
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
- name: Build C extension
|
||||
run: |
|
||||
make
|
||||
- name: Run tests using pytest
|
||||
run: |
|
||||
make test
|
||||
- name: check code formatting
|
||||
run: |
|
||||
make check_format
|
||||
- name: lint the code with ruff
|
||||
run: |
|
||||
make lint
|
133
pyctbgui/.gitignore
vendored
Normal file
133
pyctbgui/.gitignore
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
nohup.out
|
||||
.idea/
|
||||
tests/.tmp
|
||||
run_*
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
18
pyctbgui/.pre-commit-config.yaml
Normal file
18
pyctbgui/.pre-commit-config.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/google/yapf
|
||||
rev: v0.40.1
|
||||
hooks:
|
||||
- id: yapf
|
||||
name: yapf
|
||||
language: python
|
||||
entry: yapf
|
||||
args: [-i,--style,pyproject.toml]
|
||||
types: [python]
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.0.285
|
||||
hooks:
|
||||
- id: ruff
|
11
pyctbgui/CtbGui
Executable file
11
pyctbgui/CtbGui
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
from PyQt5 import QtWidgets
|
||||
import sys
|
||||
|
||||
from pyctbgui.ui import MainWindow
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
main = MainWindow()
|
||||
main.show()
|
||||
app.exec_()
|
2
pyctbgui/MANIFEST.in
Normal file
2
pyctbgui/MANIFEST.in
Normal file
@ -0,0 +1,2 @@
|
||||
include pyctbgui/ui/*.ui
|
||||
recursive-include src *.c *.h
|
39
pyctbgui/Makefile
Normal file
39
pyctbgui/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
# TODO! Add support for making the pkg?
|
||||
# Which tests should we have?
|
||||
|
||||
default: ext
|
||||
|
||||
ext: ## [DEFAULT] build c extension in place
|
||||
rm -rf build/ pyctbgui/_decoder.cpython*
|
||||
python setup.py build_ext --inplace
|
||||
|
||||
clean: ## Remove the build folder and the shared library
|
||||
rm -rf build/ pyctbgui/_decoder.cpython*
|
||||
|
||||
test: ## Run unit tests using pytest
|
||||
python -m pytest -v tests/unit
|
||||
|
||||
test_gui: ## Run E2E tests using pytest
|
||||
python -m pytest -v tests/gui
|
||||
|
||||
setup_gui_test: ## Setup the environment for the E2E tests
|
||||
ctbDetectorServer_virtual > /tmp/simulator.log 2>&1 &
|
||||
slsReceiver > /tmp/slsReceiver.log 2>&1 &
|
||||
sleep 3
|
||||
sls_detector_put config tests/gui/data/simulator.config
|
||||
|
||||
killall: ## Kill all the processes started by setup_gui_test
|
||||
killall slsReceiver ctbDetectorServer_virtual
|
||||
|
||||
|
||||
lint: ## run ruff linter to check formatting errors
|
||||
@ruff check tests pyctbgui *.py && echo "Ruff checks passed ✅"
|
||||
|
||||
format: ## format code inplace using style in pyproject.toml
|
||||
yapf --style pyproject.toml -m -r -i tests pyctbgui *.py
|
||||
|
||||
check_format: ## Check if source is formatted properly
|
||||
yapf --style pyproject.toml -r -d tests pyctbgui *.py
|
||||
|
||||
help: # from compiler explorer
|
||||
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
31
pyctbgui/README.md
Normal file
31
pyctbgui/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# New Chip Test Board Gui using Python
|
||||
Prototype for a new python based GUI for the Chip Test Board
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
git clone https://github.com/slsdetectorgroup/pyctbgui.git
|
||||
cd pyctbgui
|
||||
make #compiles the c extension inplace
|
||||
./CtbGui
|
||||
```
|
||||
|
||||
|
||||
## Display help for the Makefile
|
||||
|
||||
```
|
||||
$ make help
|
||||
check_format Check if source is formatted properly
|
||||
clean Remove the build folder and the shared library
|
||||
ext [DEFAULT] build c extension in place
|
||||
format format code inplace using style in pyproject.toml
|
||||
lint run ruff linter to check formatting errors
|
||||
test Run unit tests using pytest
|
||||
```
|
||||
|
||||
|
||||
## setup pre-commit hooks
|
||||
```
|
||||
pre-commit install
|
||||
```
|
73
pyctbgui/client.py
Normal file
73
pyctbgui/client.py
Normal file
@ -0,0 +1,73 @@
|
||||
import json
|
||||
import zmq
|
||||
import numpy as np
|
||||
|
||||
from slsdet import Detector
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
det = Detector()
|
||||
|
||||
zmqIp = det.zmqip
|
||||
zmqport = det.zmqport
|
||||
zmq_stream = det.rx_zmqstream
|
||||
|
||||
|
||||
def zmq_receiver():
|
||||
context = zmq.Context()
|
||||
socket = context.socket(zmq.SUB)
|
||||
socket.connect(f"tcp://{zmqIp}:{zmqport}")
|
||||
socket.subscribe("")
|
||||
|
||||
while True:
|
||||
msg = socket.recv_multipart()
|
||||
if len(msg) == 2:
|
||||
header, data = msg
|
||||
jsonHeader = json.loads(header)
|
||||
print(jsonHeader)
|
||||
print(f'Data size: {len(data)}')
|
||||
data_array = np.array(np.frombuffer(data, dtype=np.uint16))
|
||||
break
|
||||
return data_array
|
||||
|
||||
|
||||
def analog(data_array):
|
||||
adc_numbers = [
|
||||
9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26,
|
||||
25, 24
|
||||
]
|
||||
|
||||
n_pixels_per_sc = 5000
|
||||
|
||||
sc_width = 25
|
||||
analog_frame = np.zeros((400, 400))
|
||||
order_sc = np.zeros((400, 400))
|
||||
|
||||
for n_pixel in range(n_pixels_per_sc):
|
||||
#these_dbits = int(digital_data[n_pixel])
|
||||
|
||||
for i_sc, adc_nr in enumerate(adc_numbers):
|
||||
# ANALOG
|
||||
col = ((adc_nr % 16) * sc_width) + (n_pixel % sc_width)
|
||||
if i_sc < 16:
|
||||
row = 199 - int(n_pixel / sc_width)
|
||||
else:
|
||||
row = 200 + int(n_pixel / sc_width)
|
||||
|
||||
index_min = n_pixel * 32 + i_sc
|
||||
|
||||
pixel_value = data_array[index_min]
|
||||
analog_frame[row, col] = pixel_value
|
||||
order_sc[row, col] = i_sc
|
||||
return analog_frame
|
||||
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
data = analog(data_array=zmq_receiver())
|
||||
im = ax.imshow(data)
|
||||
ax.invert_yaxis()
|
||||
fig.colorbar(im)
|
||||
plt.show()
|
||||
# pg.image(data, title="test")
|
||||
|
||||
# if __name__ == '__main__':
|
||||
# pg.QtWidgets.QApplication.exec_()
|
2
pyctbgui/pyctbgui/__init__.py
Normal file
2
pyctbgui/pyctbgui/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .utils.defines import Defines as defs
|
||||
from .utils import bit_utils, alias_utility
|
420
pyctbgui/pyctbgui/services/ADC.py
Normal file
420
pyctbgui/pyctbgui/services/ADC.py
Normal file
@ -0,0 +1,420 @@
|
||||
import logging
|
||||
import typing
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import LegendItem
|
||||
|
||||
from pyctbgui.utils import decoder
|
||||
from pyctbgui.utils.bit_utils import bit_is_set, manipulate_bit
|
||||
from pyctbgui.utils.defines import Defines
|
||||
import pyctbgui.utils.pixelmap as pm
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
from slsdet import detectorType
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from pyctbgui.services import AcquisitionTab, PlotTab
|
||||
|
||||
|
||||
class AdcTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
super().__init__(parent, *args, **kwargs)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "adc.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab: PlotTab | None = None
|
||||
self.acquisitionTab: AcquisitionTab | None = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.logger = logging.getLogger('AdcTab')
|
||||
self.tengiga = True
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
self.acquisitionTab = self.mainWindow.acquisitionTab
|
||||
for i in range(Defines.adc.count):
|
||||
self.setADCButtonColor(i, self.plotTab.getRandomColor())
|
||||
self.initializeAllAnalogPlots()
|
||||
|
||||
self.legend = self.mainWindow.plotAnalogWaveform.getPlotItem().legend
|
||||
self.legend.clear()
|
||||
# subscribe to toggle legend
|
||||
self.plotTab.subscribeToggleLegend(self.updateLegend)
|
||||
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.checkBoxADC0_15Inv.setDisabled(True)
|
||||
self.view.checkBoxADC16_31Inv.setDisabled(True)
|
||||
self.view.lineEditADCInversion.setDisabled(True)
|
||||
self.view.labelADCInversion.setDisabled(True)
|
||||
|
||||
def initializeAllAnalogPlots(self):
|
||||
self.mainWindow.plotAnalogWaveform = pg.plot()
|
||||
self.mainWindow.plotAnalogWaveform.addLegend(colCount=Defines.colCount)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotAnalogWaveform, 1)
|
||||
self.mainWindow.analogPlots = {}
|
||||
waveform = np.zeros(1000)
|
||||
for i in range(Defines.adc.count):
|
||||
pen = pg.mkPen(color=self.getADCButtonColor(i), width=1)
|
||||
legendName = getattr(self.view, f"labelADC{i}").text()
|
||||
self.mainWindow.analogPlots[i] = self.mainWindow.plotAnalogWaveform.plot(waveform,
|
||||
pen=pen,
|
||||
name=legendName)
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
self.mainWindow.plotAnalogImage = pg.ImageView()
|
||||
self.mainWindow.nAnalogRows = 0
|
||||
self.mainWindow.nAnalogCols = 0
|
||||
self.mainWindow.analog_frame = np.zeros((self.mainWindow.nAnalogRows, self.mainWindow.nAnalogCols))
|
||||
self.mainWindow.plotAnalogImage.getView().invertY(False)
|
||||
self.mainWindow.plotAnalogImage.setImage(self.mainWindow.analog_frame)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotAnalogImage, 2)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.adc.count):
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
getattr(self.view, f"checkBoxADC{i}Inv").stateChanged.connect(partial(self.setADCInv, i))
|
||||
getattr(self.view, f"checkBoxADC{i}En").stateChanged.connect(partial(self.setADCEnable, i))
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").stateChanged.connect(partial(self.setADCEnablePlot, i))
|
||||
getattr(self.view, f"pushButtonADC{i}").clicked.connect(partial(self.selectADCColor, i))
|
||||
self.view.checkBoxADC0_15En.stateChanged.connect(partial(self.setADCEnableRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31En.stateChanged.connect(
|
||||
partial(self.setADCEnableRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.connect(
|
||||
partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.connect(
|
||||
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
|
||||
def refresh(self):
|
||||
self.updateADCNames()
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.updateADCInv()
|
||||
self.updateADCEnable()
|
||||
|
||||
# ADCs Tab functions
|
||||
|
||||
def getEnabledPlots(self):
|
||||
"""
|
||||
return plots that are shown (checkBoxADC#Plot is checked)
|
||||
"""
|
||||
enabledPlots = []
|
||||
self.legend.clear()
|
||||
for i in range(Defines.adc.count):
|
||||
if getattr(self.view, f'checkBoxADC{i}Plot').isChecked():
|
||||
plotName = getattr(self.view, f"labelADC{i}").text()
|
||||
enabledPlots.append((self.mainWindow.analogPlots[i], plotName))
|
||||
return enabledPlots
|
||||
|
||||
def updateLegend(self):
|
||||
"""
|
||||
update the legend for the ADC waveform plot
|
||||
should be called after checking or unchecking plot checkbox
|
||||
"""
|
||||
if not self.mainWindow.showLegend:
|
||||
self.legend.clear()
|
||||
else:
|
||||
for plot, name in self.getEnabledPlots():
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
def updateADCNames(self):
|
||||
"""
|
||||
get adc names from detector and update them in the UI
|
||||
"""
|
||||
for i, adc_name in enumerate(self.det.getAdcNames()):
|
||||
getattr(self.view, f"labelADC{i}").setText(adc_name)
|
||||
|
||||
def processWaveformData(self, data: bytes, aSamples: int) -> dict[str, np.ndarray]:
|
||||
"""
|
||||
view function
|
||||
plots processed waveform data
|
||||
@param data: raw waveform data
|
||||
@param aSamples: analog samples
|
||||
@return: waveform dict returned to handle it for saving the output
|
||||
"""
|
||||
|
||||
waveforms = {}
|
||||
analog_array = self._processWaveformData(data, aSamples, self.mainWindow.nADCEnabled)
|
||||
idx = 0
|
||||
for i in range(Defines.adc.count):
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBoxEn = getattr(self.view, f"checkBoxADC{i}En")
|
||||
|
||||
if checkBoxEn.isChecked() and checkBoxPlot.isChecked():
|
||||
waveform = analog_array[:, idx]
|
||||
idx += 1
|
||||
self.mainWindow.analogPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelADC{i}").text()
|
||||
waveforms[plotName] = waveform
|
||||
return waveforms
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data: bytes, aSamples: int, nADCEnabled: int) -> np.ndarray:
|
||||
"""
|
||||
model function
|
||||
processes raw waveform data
|
||||
@param data: raw waveform data
|
||||
@param aSamples: analog samples
|
||||
@param nADCEnabled: number of enabled ADCs
|
||||
@return: processed waveform data
|
||||
"""
|
||||
analog_array = np.array(np.frombuffer(data, dtype=np.uint16, count=nADCEnabled * aSamples))
|
||||
return analog_array.reshape(-1, nADCEnabled)
|
||||
|
||||
def processImageData(self, data, aSamples):
|
||||
"""
|
||||
process the raw receiver data for analog image
|
||||
data: raw analog image
|
||||
aSamples: analog samples
|
||||
"""
|
||||
# get zoom state
|
||||
viewBox = self.mainWindow.plotAnalogImage.getView()
|
||||
state = viewBox.getState()
|
||||
try:
|
||||
self.mainWindow.analog_frame = self._processImageData(data, aSamples, self.mainWindow.nADCEnabled)
|
||||
self.plotTab.ignoreHistogramSignal = True
|
||||
self.mainWindow.plotAnalogImage.setImage(self.mainWindow.analog_frame.T)
|
||||
except Exception:
|
||||
self.logger.exception('Exception Caught')
|
||||
self.mainWindow.statusbar.setStyleSheet("color:red")
|
||||
message = f'Warning: Invalid size for Analog Image. Expected' \
|
||||
f' {self.mainWindow.nAnalogRows * self.mainWindow.nAnalogCols} ' \
|
||||
f'size, got {self.mainWindow.analog_frame.size} instead.'
|
||||
self.acquisitionTab.updateCurrentFrame('Invalid Image')
|
||||
|
||||
self.mainWindow.statusbar.showMessage(message)
|
||||
print(message)
|
||||
|
||||
self.plotTab.setFrameLimits(self.mainWindow.analog_frame)
|
||||
|
||||
# keep the zoomed in state (not 1st image)
|
||||
if self.mainWindow.firstAnalogImage:
|
||||
self.mainWindow.firstAnalogImage = False
|
||||
else:
|
||||
viewBox.setState(state)
|
||||
return self.mainWindow.analog_frame.T
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processImageData(self, data, aSamples, nADCEnabled):
|
||||
analog_array = np.array(np.frombuffer(data, dtype=np.uint16, count=nADCEnabled * aSamples))
|
||||
return decoder.decode(analog_array, pm.moench04_analog())
|
||||
|
||||
def getADCEnableReg(self):
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.tengiga = self.det.tengiga
|
||||
retval = self.det.adcenable10g
|
||||
if not self.tengiga:
|
||||
retval = self.det.adcenable
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
self.view.lineEditADCEnable.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
return retval
|
||||
|
||||
def setADCEnableReg(self):
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
try:
|
||||
mask = int(self.view.lineEditADCEnable.text(), 16)
|
||||
if self.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnable(self, i, mask):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(mask, i))
|
||||
checkBox.stateChanged.connect(partial(self.setADCEnable, i))
|
||||
|
||||
def updateADCEnable(self):
|
||||
retval = self.getADCEnableReg()
|
||||
self.mainWindow.nADCEnabled = bin(retval).count('1')
|
||||
for i in range(Defines.adc.count):
|
||||
self.getADCEnable(i, retval)
|
||||
self.getADCEnablePlot(i)
|
||||
self.getADCEnableColor(i)
|
||||
self.plotTab.addSelectedAnalogPlots(i)
|
||||
self.getADCEnableRange(retval)
|
||||
self.getADCEnablePlotRange()
|
||||
|
||||
def setADCEnable(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
try:
|
||||
if self.tengiga:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable10g, i)
|
||||
self.det.adcenable10g = enableMask
|
||||
else:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable, i)
|
||||
self.det.adcenable = enableMask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnableRange(self, mask):
|
||||
self.view.checkBoxADC0_15En.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31En.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15En.setChecked((mask & Defines.adc.BIT0_15_MASK) == Defines.adc.BIT0_15_MASK)
|
||||
self.view.checkBoxADC16_31En.setChecked((mask & Defines.adc.BIT16_31_MASK) == Defines.adc.BIT16_31_MASK)
|
||||
self.view.checkBoxADC0_15En.stateChanged.connect(partial(self.setADCEnableRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31En.stateChanged.connect(
|
||||
partial(self.setADCEnableRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCEnableRange(self, start_nr, end_nr):
|
||||
mask = self.getADCEnableReg()
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}En")
|
||||
for i in range(start_nr, end_nr):
|
||||
mask = manipulate_bit(checkBox.isChecked(), mask, i)
|
||||
try:
|
||||
if self.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnablePlot(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBoxPlot.setEnabled(checkBox.isChecked())
|
||||
|
||||
def setADCEnablePlot(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
pushButton.setEnabled(checkBox.isChecked())
|
||||
|
||||
self.getADCEnablePlotRange()
|
||||
self.plotTab.addSelectedAnalogPlots(i)
|
||||
self.updateLegend()
|
||||
|
||||
def getADCEnablePlotRange(self):
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15Plot.setEnabled(
|
||||
all(getattr(self.view, f"checkBoxADC{i}Plot").isEnabled() for i in range(Defines.adc.half)))
|
||||
self.view.checkBoxADC16_31Plot.setEnabled(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").isEnabled()
|
||||
for i in range(Defines.adc.half, Defines.adc.count)))
|
||||
self.view.checkBoxADC0_15Plot.setChecked(
|
||||
all(getattr(self.view, f"checkBoxADC{i}Plot").isChecked() for i in range(Defines.adc.half)))
|
||||
self.view.checkBoxADC16_31Plot.setChecked(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").isChecked()
|
||||
for i in range(Defines.adc.half, Defines.adc.count)))
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.connect(
|
||||
partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCEnablePlotRange(self, start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}Plot")
|
||||
enable = checkBox.isChecked()
|
||||
for i in range(start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBox.setChecked(enable)
|
||||
self.plotTab.addAllSelectedAnalogPlots()
|
||||
|
||||
def getADCEnableColor(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
pushButton.setEnabled(checkBox.isEnabled() and checkBox.isChecked())
|
||||
|
||||
def selectADCColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
self.plotTab.showPalette(pushButton)
|
||||
pen = pg.mkPen(color=self.getADCButtonColor(i), width=1)
|
||||
self.mainWindow.analogPlots[i].setPen(pen)
|
||||
|
||||
def getADCButtonColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
return self.plotTab.getActiveColor(pushButton)
|
||||
|
||||
def setADCButtonColor(self, i, color):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
return self.plotTab.setActiveColor(pushButton, color)
|
||||
|
||||
def getADCInvReg(self):
|
||||
retval = self.det.adcinvert
|
||||
self.view.lineEditADCInversion.editingFinished.disconnect()
|
||||
self.view.lineEditADCInversion.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
return retval
|
||||
|
||||
def setADCInvReg(self):
|
||||
self.view.lineEditADCInversion.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcinvert = int(self.view.lineEditADCInversion.text(), 16)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Inversion Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
self.updateADCInv()
|
||||
|
||||
def getADCInv(self, i, inv):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Inv")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(inv, i))
|
||||
checkBox.stateChanged.connect(partial(self.setADCInv, i))
|
||||
|
||||
def updateADCInv(self):
|
||||
retval = self.getADCInvReg()
|
||||
for i in range(Defines.adc.count):
|
||||
self.getADCInv(i, retval)
|
||||
self.getADCInvRange(retval)
|
||||
|
||||
def setADCInv(self, i):
|
||||
out = self.det.adcinvert
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Inv")
|
||||
mask = manipulate_bit(checkBox.isChecked(), out, i)
|
||||
self.det.adcinvert = mask
|
||||
|
||||
retval = self.getADCInvReg()
|
||||
self.getADCInv(i, retval)
|
||||
self.getADCInvRange(retval)
|
||||
|
||||
def getADCInvRange(self, inv):
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15Inv.setChecked((inv & Defines.adc.BIT0_15_MASK) == Defines.adc.BIT0_15_MASK)
|
||||
self.view.checkBoxADC16_31Inv.setChecked((inv & Defines.adc.BIT16_31_MASK) == Defines.adc.BIT16_31_MASK)
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.connect(
|
||||
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCInvRange(self, start_nr, end_nr):
|
||||
out = self.det.adcinvert
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}Inv")
|
||||
mask = getattr(Defines.adc, f"BIT{start_nr}_{end_nr - 1}_MASK")
|
||||
if checkBox.isChecked():
|
||||
self.det.adcinvert = out | mask
|
||||
else:
|
||||
self.det.adcinvert = out & ~mask
|
||||
|
||||
self.updateADCInv()
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}",
|
||||
f"adcinvert {self.view.lineEditADCInversion.text()}",
|
||||
]
|
||||
else:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}"
|
||||
]
|
755
pyctbgui/pyctbgui/services/Acquisition.py
Normal file
755
pyctbgui/pyctbgui/services/Acquisition.py
Normal file
@ -0,0 +1,755 @@
|
||||
import json
|
||||
import typing
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import time
|
||||
import zmq
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import logging
|
||||
|
||||
from slsdet import readoutMode, runStatus, detectorType
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
# only used for type hinting. To avoid circular dependencies these
|
||||
# won't be imported in runtime
|
||||
from pyctbgui.services import SignalsTab, TransceiverTab, AdcTab, PlotTab
|
||||
|
||||
|
||||
class AcquisitionTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
self.__isWaveform = None
|
||||
super().__init__(parent)
|
||||
self.currentMeasurement = None
|
||||
self.dsamples = None
|
||||
self.stoppedFlag = None
|
||||
self.asamples = None
|
||||
self.tsamples = None
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "acquisition.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.signalsTab: SignalsTab = None
|
||||
self.transceiverTab: TransceiverTab = None
|
||||
self.adcTab: AdcTab = None
|
||||
self.plotTab: PlotTab = None
|
||||
self.writeNumpy: bool = False
|
||||
self.outputDir: Path = Path('/')
|
||||
self.outputFileNamePrefix: str = ''
|
||||
self.numpyFileManagers: dict[str, NumpyFileManager] = {}
|
||||
|
||||
self.logger = logging.getLogger('AcquisitionTab')
|
||||
|
||||
def setup_ui(self):
|
||||
self.signalsTab = self.mainWindow.signalsTab
|
||||
self.transceiverTab = self.mainWindow.transceiverTab
|
||||
self.adcTab = self.mainWindow.adcTab
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
self.toggleStartButton(False)
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.labelRunF.setDisabled(True)
|
||||
self.view.labelADCF.setDisabled(True)
|
||||
self.view.labelADCPhase.setDisabled(True)
|
||||
self.view.labelADCPipeline.setDisabled(True)
|
||||
self.view.labelDBITF.setDisabled(True)
|
||||
self.view.labelDBITPhase.setDisabled(True)
|
||||
self.view.labelDBITPipeline.setDisabled(True)
|
||||
self.view.spinBoxRunF.setDisabled(True)
|
||||
self.view.spinBoxADCF.setDisabled(True)
|
||||
self.view.spinBoxADCPhase.setDisabled(True)
|
||||
self.view.spinBoxADCPipeline.setDisabled(True)
|
||||
self.view.spinBoxDBITF.setDisabled(True)
|
||||
self.view.spinBoxDBITPhase.setDisabled(True)
|
||||
self.view.spinBoxDBITPipeline.setDisabled(True)
|
||||
|
||||
def connect_ui(self):
|
||||
# For Acquistions Tab
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite)
|
||||
self.view.checkBoxFileWriteNumpy.stateChanged.connect(self.setFileWriteNumpy)
|
||||
self.view.lineEditFileName.editingFinished.connect(self.setFileName)
|
||||
self.view.lineEditFilePath.editingFinished.connect(self.setFilePath)
|
||||
self.view.pushButtonFilePath.clicked.connect(self.browseFilePath)
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.connect(self.setAccquisitionIndex)
|
||||
self.view.spinBoxFrames.editingFinished.connect(self.setFrames)
|
||||
self.view.spinBoxPeriod.editingFinished.connect(self.setPeriod)
|
||||
self.view.comboBoxPeriod.currentIndexChanged.connect(self.setPeriod)
|
||||
self.view.spinBoxTriggers.editingFinished.connect(self.setTriggers)
|
||||
|
||||
def refresh(self):
|
||||
self.getReadout()
|
||||
self.getTransceiver()
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getRunFrequency()
|
||||
self.getADCFrequency()
|
||||
self.getADCPhase()
|
||||
self.getADCPipeline()
|
||||
self.getDBITFrequency()
|
||||
self.getDBITPhase()
|
||||
self.getDBITPipeline()
|
||||
|
||||
self.getFileWrite()
|
||||
self.getFileName()
|
||||
self.getFilePath()
|
||||
self.getAccquisitionIndex()
|
||||
self.getFrames()
|
||||
self.getTriggers()
|
||||
self.getPeriod()
|
||||
self.updateDetectorStatus(self.det.status)
|
||||
|
||||
# Acquisition Tab functions
|
||||
|
||||
def getReadout(self):
|
||||
self.view.comboBoxROMode.currentIndexChanged.disconnect()
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
|
||||
self.mainWindow.romode = self.det.romode
|
||||
self.view.comboBoxROMode.setCurrentIndex(self.mainWindow.romode.value)
|
||||
match self.mainWindow.romode:
|
||||
case readoutMode.ANALOG_ONLY:
|
||||
self.view.spinBoxAnalog.setEnabled(True)
|
||||
self.view.labelAnalog.setEnabled(True)
|
||||
self.view.spinBoxDigital.setDisabled(True)
|
||||
self.view.labelDigital.setDisabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.DIGITAL_ONLY:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.ANALOG_AND_DIGITAL:
|
||||
self.view.spinBoxAnalog.setEnabled(True)
|
||||
self.view.labelAnalog.setEnabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.TRANSCEIVER_ONLY:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setDisabled(True)
|
||||
self.view.labelDigital.setDisabled(True)
|
||||
self.view.labelTransceiver.setEnabled(True)
|
||||
self.view.spinBoxTransceiver.setEnabled(True)
|
||||
case _:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setEnabled(True)
|
||||
self.view.spinBoxTransceiver.setEnabled(True)
|
||||
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.plotTab.showPlot()
|
||||
|
||||
def plotReferesh(self):
|
||||
self.read_zmq()
|
||||
|
||||
def setReadOut(self):
|
||||
self.view.comboBoxROMode.currentIndexChanged.disconnect()
|
||||
try:
|
||||
if self.view.comboBoxROMode.currentIndex() == 0:
|
||||
self.det.romode = readoutMode.ANALOG_ONLY
|
||||
elif self.view.comboBoxROMode.currentIndex() == 1:
|
||||
self.det.romode = readoutMode.DIGITAL_ONLY
|
||||
elif self.view.comboBoxROMode.currentIndex() == 2:
|
||||
self.det.romode = readoutMode.ANALOG_AND_DIGITAL
|
||||
elif self.view.comboBoxROMode.currentIndex() == 3:
|
||||
self.det.romode = readoutMode.TRANSCEIVER_ONLY
|
||||
else:
|
||||
self.det.romode = readoutMode.DIGITAL_AND_TRANSCEIVER
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Readout Mode Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.getReadout()
|
||||
|
||||
def getRunFrequency(self):
|
||||
self.view.spinBoxRunF.editingFinished.disconnect()
|
||||
self.view.spinBoxRunF.setValue(self.det.runclk)
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
|
||||
def setRunFrequency(self):
|
||||
self.view.spinBoxRunF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.runclk = self.view.spinBoxRunF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Run Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.getRunFrequency()
|
||||
|
||||
def getTransceiver(self):
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
self.tsamples = self.det.tsamples
|
||||
self.view.spinBoxTransceiver.setValue(self.tsamples)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
|
||||
def setTransceiver(self):
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.tsamples = self.view.spinBoxTransceiver.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Transceiver Samples Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.getTransceiver()
|
||||
|
||||
def getAnalog(self):
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
self.asamples = self.det.asamples
|
||||
self.view.spinBoxAnalog.setValue(self.asamples)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
|
||||
def setAnalog(self):
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.asamples = self.view.spinBoxAnalog.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Digital Samples Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.getAnalog()
|
||||
|
||||
def getDigital(self):
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
self.dsamples = self.det.dsamples
|
||||
self.view.spinBoxDigital.setValue(self.dsamples)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
|
||||
def setDigital(self):
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dsamples = self.view.spinBoxDigital.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Digital Samples Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.getDigital()
|
||||
|
||||
def getADCFrequency(self):
|
||||
self.view.spinBoxADCF.editingFinished.disconnect()
|
||||
self.view.spinBoxADCF.setValue(self.det.adcclk)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
|
||||
def setADCFrequency(self):
|
||||
self.view.spinBoxADCF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcclk = self.view.spinBoxADCF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.getADCFrequency()
|
||||
|
||||
def getADCPhase(self):
|
||||
self.view.spinBoxADCPhase.editingFinished.disconnect()
|
||||
self.view.spinBoxADCPhase.setValue(self.det.adcphase)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
|
||||
def setADCPhase(self):
|
||||
self.view.spinBoxADCPhase.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcphase = self.view.spinBoxADCPhase.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Phase Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
self.getADCPhase()
|
||||
|
||||
def getADCPipeline(self):
|
||||
self.view.spinBoxADCPipeline.editingFinished.disconnect()
|
||||
self.view.spinBoxADCPipeline.setValue(self.det.adcpipeline)
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
|
||||
def setADCPipeline(self):
|
||||
self.view.spinBoxADCPipeline.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcpipeline = self.view.spinBoxADCPipeline.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Pipeline Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
self.getADCPipeline()
|
||||
|
||||
def getDBITFrequency(self):
|
||||
self.view.spinBoxDBITF.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITF.setValue(self.det.dbitclk)
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
|
||||
def setDBITFrequency(self):
|
||||
self.view.spinBoxDBITF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitclk = self.view.spinBoxDBITF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
self.getDBITFrequency()
|
||||
|
||||
def getDBITPhase(self):
|
||||
self.view.spinBoxDBITPhase.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITPhase.setValue(self.det.dbitphase)
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
|
||||
def setDBITPhase(self):
|
||||
self.view.spinBoxDBITPhase.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitphase = self.view.spinBoxDBITPhase.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Phase Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
self.getDBITPhase()
|
||||
|
||||
def getDBITPipeline(self):
|
||||
self.view.spinBoxDBITPipeline.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITPipeline.setValue(self.det.dbitpipeline)
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
|
||||
def setDBITPipeline(self):
|
||||
self.view.spinBoxDBITPipeline.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitpipeline = self.view.spinBoxDBITPipeline.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Pipeline Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
self.getDBITPipeline()
|
||||
|
||||
def getFileWrite(self):
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.disconnect()
|
||||
self.view.checkBoxFileWriteRaw.setChecked(self.det.fwrite)
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite)
|
||||
|
||||
def setFileWrite(self):
|
||||
self.det.fwrite = self.view.checkBoxFileWriteRaw.isChecked()
|
||||
self.getFileWrite()
|
||||
|
||||
def setFileWriteNumpy(self):
|
||||
"""
|
||||
slot for saving the data in numpy (.npy) format
|
||||
"""
|
||||
self.writeNumpy = not self.writeNumpy
|
||||
|
||||
def getFileName(self):
|
||||
"""
|
||||
set the lineEditFilePath input widget to the filename value from the detector
|
||||
"""
|
||||
|
||||
self.view.lineEditFileName.editingFinished.disconnect()
|
||||
fileName = self.det.fname
|
||||
self.view.lineEditFileName.setText(fileName)
|
||||
self.outputFileNamePrefix = fileName
|
||||
self.view.lineEditFileName.editingFinished.connect(self.setFileName)
|
||||
|
||||
def setFileName(self):
|
||||
"""
|
||||
slot for setting the filename from the widget to the detector
|
||||
"""
|
||||
self.det.fname = self.view.lineEditFileName.text()
|
||||
self.getFileName()
|
||||
|
||||
def getFilePath(self):
|
||||
"""
|
||||
set the lineEditFilePath input widget to the path value from the detector
|
||||
"""
|
||||
self.view.lineEditFilePath.editingFinished.disconnect()
|
||||
path = self.det.fpath
|
||||
self.view.lineEditFilePath.setText(str(path))
|
||||
self.view.lineEditFilePath.editingFinished.connect(self.setFilePath)
|
||||
self.outputDir = path
|
||||
|
||||
def setFilePath(self):
|
||||
"""
|
||||
slot to set the directory of the output for the detector
|
||||
"""
|
||||
self.det.fpath = Path(self.view.lineEditFilePath.text())
|
||||
self.getFilePath()
|
||||
|
||||
def saveNumpyFile(self, data: np.ndarray | dict[str, np.ndarray], jsonHeader):
|
||||
"""
|
||||
save the acquisition data (waveform or image) in the specified path
|
||||
save waveform in multiple .npy files
|
||||
save image as npy file format
|
||||
@note: frame number can be up to 100,000 so the data arrays cannot be fully loaded to memory
|
||||
"""
|
||||
if not self.writeNumpy:
|
||||
return
|
||||
if self.outputDir == Path('/'):
|
||||
self.outputDir = Path('./')
|
||||
if self.outputFileNamePrefix == '':
|
||||
self.outputFileNamePrefix = 'run'
|
||||
|
||||
for device in data:
|
||||
if device not in self.numpyFileManagers:
|
||||
tmpPath = self.outputDir / f'{self.outputFileNamePrefix}_{device}_{jsonHeader["fileIndex"]}.npy'
|
||||
self.numpyFileManagers[device] = NumpyFileManager(tmpPath, 'w', data[device].shape, data[device].dtype)
|
||||
self.numpyFileManagers[device].writeOneFrame(data[device])
|
||||
|
||||
if 'progress' in jsonHeader and jsonHeader['progress'] >= 100:
|
||||
# close opened files after saving the last frame
|
||||
self.closeOpenedNumpyFiles(jsonHeader)
|
||||
|
||||
def closeOpenedNumpyFiles(self, jsonHeader):
|
||||
"""
|
||||
create npz file for waveform plots and close opened numpy files to persist their data
|
||||
"""
|
||||
if not self.writeNumpy:
|
||||
return
|
||||
if len(self.numpyFileManagers) == 0:
|
||||
return
|
||||
oneFile: bool = len(self.numpyFileManagers) == 1
|
||||
|
||||
filepaths = [npw.file.name for device, npw in self.numpyFileManagers.items()]
|
||||
filenames = list(self.numpyFileManagers.keys())
|
||||
ext = 'npy' if oneFile else 'npz'
|
||||
newPath = self.outputDir / f'{self.outputFileNamePrefix}_{jsonHeader["fileIndex"]}.{ext}'
|
||||
|
||||
if not oneFile:
|
||||
# if there is multiple .npy files group them in an .npz file
|
||||
self.numpyFileManagers.clear()
|
||||
NpzFileWriter.zipNpyFiles(newPath, filepaths, filenames, deleteOriginals=True, compressed=False)
|
||||
else:
|
||||
# rename files from "run_ADC0_0.npy" to "run_0.npy" if it is a single .npy file
|
||||
oldPath = self.outputDir / f'{self.outputFileNamePrefix}_' \
|
||||
f'{self.numpyFileManagers.popitem()[0]}_{jsonHeader["fileIndex"]}.{ext}'
|
||||
Path.rename(oldPath, newPath)
|
||||
|
||||
self.logger.info(f'Saving numpy data in {newPath} Finished')
|
||||
|
||||
def browseFilePath(self):
|
||||
response = QtWidgets.QFileDialog.getExistingDirectory(parent=self.mainWindow,
|
||||
caption="Select Path to Save Output File",
|
||||
directory=str(Path.cwd()),
|
||||
options=(QtWidgets.QFileDialog.ShowDirsOnly
|
||||
| QtWidgets.QFileDialog.DontResolveSymlinks)
|
||||
# filter='README (*.md *.ui)'
|
||||
)
|
||||
if response:
|
||||
self.view.lineEditFilePath.setText(response)
|
||||
self.setFilePath()
|
||||
|
||||
def getAccquisitionIndex(self):
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.disconnect()
|
||||
self.view.spinBoxAcquisitionIndex.setValue(self.det.findex)
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.connect(self.setAccquisitionIndex)
|
||||
|
||||
def setAccquisitionIndex(self):
|
||||
self.det.findex = self.view.spinBoxAcquisitionIndex.value()
|
||||
self.getAccquisitionIndex()
|
||||
|
||||
def getFrames(self):
|
||||
self.view.spinBoxFrames.editingFinished.disconnect()
|
||||
self.view.spinBoxFrames.setValue(self.det.frames)
|
||||
self.view.spinBoxFrames.editingFinished.connect(self.setFrames)
|
||||
|
||||
def setFrames(self):
|
||||
self.det.frames = self.view.spinBoxFrames.value()
|
||||
self.getFrames()
|
||||
|
||||
def getPeriod(self):
|
||||
self.view.spinBoxPeriod.editingFinished.disconnect()
|
||||
self.view.comboBoxPeriod.currentIndexChanged.disconnect()
|
||||
|
||||
# Converting to right time unit for period
|
||||
tPeriod = self.det.period
|
||||
if tPeriod < 100e-9:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(3)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-9)
|
||||
elif tPeriod < 100e-6:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(2)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-6)
|
||||
elif tPeriod < 100e-3:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(1)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-3)
|
||||
else:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(0)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod)
|
||||
|
||||
self.view.spinBoxPeriod.editingFinished.connect(self.setPeriod)
|
||||
self.view.comboBoxPeriod.currentIndexChanged.connect(self.setPeriod)
|
||||
|
||||
def setPeriod(self):
|
||||
if self.view.comboBoxPeriod.currentIndex() == 0:
|
||||
self.det.period = self.view.spinBoxPeriod.value()
|
||||
elif self.view.comboBoxPeriod.currentIndex() == 1:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-3)
|
||||
elif self.view.comboBoxPeriod.currentIndex() == 2:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-6)
|
||||
else:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-9)
|
||||
|
||||
self.getPeriod()
|
||||
|
||||
def getTriggers(self):
|
||||
self.view.spinBoxTriggers.editingFinished.disconnect()
|
||||
self.view.spinBoxTriggers.setValue(self.det.triggers)
|
||||
self.view.spinBoxTriggers.editingFinished.connect(self.setTriggers)
|
||||
|
||||
def setTriggers(self):
|
||||
self.det.triggers = self.view.spinBoxTriggers.value()
|
||||
self.getTriggers()
|
||||
|
||||
def updateDetectorStatus(self, status):
|
||||
self.mainWindow.labelDetectorStatus.setText(status.name)
|
||||
|
||||
def updateCurrentMeasurement(self):
|
||||
self.mainWindow.labelCurrentMeasurement.setText(str(self.currentMeasurement))
|
||||
# print(f"Meausrement {self.currentMeasurement}")
|
||||
|
||||
def updateCurrentFrame(self, val):
|
||||
self.mainWindow.labelFrameNumber.setText(str(val))
|
||||
|
||||
def updateAcquiredFrames(self, val):
|
||||
self.mainWindow.labelAcquiredFrames.setText(str(val))
|
||||
|
||||
def toggleAcquire(self):
|
||||
if self.mainWindow.pushButtonStart.isChecked():
|
||||
self.plotTab.showPatternViewer(False)
|
||||
self.acquire()
|
||||
else:
|
||||
self.stopAcquisition()
|
||||
|
||||
def toggleStartButton(self, started):
|
||||
if started:
|
||||
self.mainWindow.pushButtonStart.setChecked(True)
|
||||
self.mainWindow.pushButtonStart.setText('Stop')
|
||||
else:
|
||||
self.mainWindow.pushButtonStart.setChecked(False)
|
||||
self.mainWindow.pushButtonStart.setText('Start')
|
||||
|
||||
def stopAcquisition(self):
|
||||
self.det.stop()
|
||||
self.stoppedFlag = True
|
||||
|
||||
def checkBeforeAcquire(self):
|
||||
if self.plotTab.view.radioButtonImage.isChecked():
|
||||
# matterhorn image
|
||||
if self.plotTab.view.comboBoxPlot.currentText() == "Matterhorn":
|
||||
if self.mainWindow.romode not in [readoutMode.TRANSCEIVER_ONLY, readoutMode.DIGITAL_AND_TRANSCEIVER]:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Matterhorn image, please enable transceiver readout mode",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
if self.transceiverTab.getTransceiverEnableReg() != Defines.Matterhorn.tranceiverEnable:
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.mainWindow, "Plot type", "To read Matterhorn image, please set transceiver enable to " +
|
||||
str(Defines.Matterhorn.tranceiverEnable), QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
# moench04 image
|
||||
elif self.plotTab.view.comboBoxPlot.currentText() == "Moench04":
|
||||
if self.mainWindow.romode not in [readoutMode.ANALOG_ONLY, readoutMode.ANALOG_AND_DIGITAL]:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Moench 04 image, please enable analog readout mode",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
if self.mainWindow.nADCEnabled != 32:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Moench 04 image, please enable all 32 adcs",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
return True
|
||||
|
||||
def acquire(self):
|
||||
if not self.checkBeforeAcquire():
|
||||
self.toggleStartButton(False)
|
||||
return
|
||||
|
||||
self.stoppedFlag = False
|
||||
self.toggleStartButton(True)
|
||||
self.currentMeasurement = 0
|
||||
|
||||
# ensure zmq streaming is enabled
|
||||
if self.det.rx_zmqstream == 0:
|
||||
self.det.rx_zmqstream = 1
|
||||
|
||||
# some functions that must be updated for local values
|
||||
self.getTransceiver()
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.getReadout()
|
||||
self.signalsTab.getDBitOffset()
|
||||
self.adcTab.getADCEnableReg()
|
||||
self.signalsTab.updateDigitalBitEnable()
|
||||
self.transceiverTab.getTransceiverEnableReg()
|
||||
|
||||
self.startMeasurement()
|
||||
|
||||
def startMeasurement(self):
|
||||
try:
|
||||
self.updateCurrentMeasurement()
|
||||
self.updateCurrentFrame(0)
|
||||
self.updateAcquiredFrames(0)
|
||||
self.mainWindow.progressBar.setValue(0)
|
||||
|
||||
self.det.rx_start()
|
||||
self.det.start()
|
||||
time.sleep(Defines.Time_Wait_For_Packets_ms)
|
||||
self.checkEndofAcquisition()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Acquire Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
self.checkEndofAcquisition()
|
||||
|
||||
def checkEndofAcquisition(self):
|
||||
caught = self.det.rx_framescaught[0]
|
||||
self.updateAcquiredFrames(caught)
|
||||
status = self.det.getDetectorStatus()[0]
|
||||
self.updateDetectorStatus(status)
|
||||
measurementDone = False
|
||||
# print(f'status:{status}')
|
||||
match status:
|
||||
case runStatus.RUNNING:
|
||||
pass
|
||||
case runStatus.WAITING:
|
||||
pass
|
||||
case runStatus.TRANSMITTING:
|
||||
pass
|
||||
case _:
|
||||
measurementDone = True
|
||||
|
||||
# check for 500ms for no packets
|
||||
# needs more time for 1g streaming out done
|
||||
if measurementDone:
|
||||
time.sleep(Defines.Time_Wait_For_Packets_ms)
|
||||
if self.det.rx_framescaught[0] != caught:
|
||||
measurementDone = False
|
||||
|
||||
numMeasurments = self.view.spinBoxMeasurements.value()
|
||||
if measurementDone:
|
||||
|
||||
if self.det.rx_status == runStatus.RUNNING:
|
||||
self.det.rx_stop()
|
||||
if self.view.checkBoxFileWriteRaw.isChecked() or self.view.checkBoxFileWriteNumpy.isChecked():
|
||||
self.view.spinBoxAcquisitionIndex.stepUp()
|
||||
self.setAccquisitionIndex()
|
||||
# next measurement
|
||||
self.currentMeasurement += 1
|
||||
if self.currentMeasurement < numMeasurments and not self.stoppedFlag:
|
||||
self.startMeasurement()
|
||||
else:
|
||||
self.mainWindow.statusTimer.stop()
|
||||
self.toggleStartButton(False)
|
||||
else:
|
||||
self.mainWindow.statusTimer.start(Defines.Time_Status_Refresh_ms)
|
||||
|
||||
# For other functios
|
||||
# Reading data from zmq and decoding it
|
||||
def read_zmq(self):
|
||||
# print("in readzmq")
|
||||
try:
|
||||
msg = self.socket.recv_multipart(flags=zmq.NOBLOCK)
|
||||
if len(msg) != 2:
|
||||
if len(msg) != 1:
|
||||
print(f'len(msg) = {len(msg)}')
|
||||
return
|
||||
header, data = msg
|
||||
jsonHeader = json.loads(header)
|
||||
self.mainWindow.progressBar.setValue(int(jsonHeader['progress']))
|
||||
self.updateCurrentFrame(jsonHeader['frameIndex'])
|
||||
|
||||
# waveform
|
||||
waveforms = {}
|
||||
if self.plotTab.view.radioButtonWaveform.isChecked():
|
||||
# analog
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
waveforms |= self.adcTab.processWaveformData(data, self.asamples)
|
||||
# digital
|
||||
if self.mainWindow.romode.value in [1, 2, 4]:
|
||||
waveforms |= self.signalsTab.processWaveformData(data, self.asamples, self.dsamples)
|
||||
# transceiver
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
waveforms |= self.transceiverTab.processWaveformData(data, self.dsamples)
|
||||
# image
|
||||
else:
|
||||
# analog
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
waveforms['analog_image'] = self.adcTab.processImageData(data, self.asamples)
|
||||
# transceiver
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
waveforms['tx_image'] = self.transceiverTab.processImageData(data, self.dsamples)
|
||||
|
||||
self.saveNumpyFile(waveforms, jsonHeader)
|
||||
except zmq.ZMQError:
|
||||
pass
|
||||
except Exception:
|
||||
self.logger.exception("Exception caught")
|
||||
|
||||
def setup_zmq(self):
|
||||
self.det.rx_zmqstream = 1
|
||||
self.zmqIp = self.det.zmqip
|
||||
self.zmqport = self.det.zmqport
|
||||
self.zmq_stream = self.det.rx_zmqstream
|
||||
|
||||
self.context = zmq.Context()
|
||||
self.socket = self.context.socket(zmq.SUB)
|
||||
self.socket.connect(f"tcp://{self.zmqIp}:{self.zmqport}")
|
||||
self.socket.subscribe("")
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
return [
|
||||
f'romode {self.view.comboBoxROMode.currentText().lower()}',
|
||||
f'runclk {self.view.spinBoxRunF.value()}',
|
||||
f'adcclk {self.view.spinBoxADCF.value()}',
|
||||
f'adcphase {self.view.spinBoxADCPhase.value()}',
|
||||
f'adcpipeline {self.view.spinBoxADCPipeline.value()}',
|
||||
f'dbitclk {self.view.spinBoxDBITF.value()}',
|
||||
f'dbitphase {self.view.spinBoxDBITPhase.value()}',
|
||||
f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}',
|
||||
f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}',
|
||||
f'fname {self.view.lineEditFileName.text()}',
|
||||
f'fpath {self.view.lineEditFilePath.text()}',
|
||||
f'findex {self.view.spinBoxAcquisitionIndex.value()}',
|
||||
f'frames {self.view.spinBoxFrames.value()}',
|
||||
f'triggers {self.view.spinBoxTriggers.value()}',
|
||||
f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}',
|
||||
f'asamples {self.view.spinBoxAnalog.value()}',
|
||||
f'dsamples {self.view.spinBoxDigital.value()}',
|
||||
f'tsamples {self.view.spinBoxTransceiver.value()}',
|
||||
]
|
||||
else:
|
||||
return [
|
||||
f'romode {self.view.comboBoxROMode.currentText().lower()}',
|
||||
f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}',
|
||||
f'fname {self.view.lineEditFileName.text()}',
|
||||
f'fpath {self.view.lineEditFilePath.text()}',
|
||||
f'findex {self.view.spinBoxAcquisitionIndex.value()}',
|
||||
f'frames {self.view.spinBoxFrames.value()}',
|
||||
f'triggers {self.view.spinBoxTriggers.value()}',
|
||||
f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}',
|
||||
f'asamples {self.view.spinBoxAnalog.value()}',
|
||||
f'dsamples {self.view.spinBoxDigital.value()}',
|
||||
f'tsamples {self.view.spinBoxTransceiver.value()}',
|
||||
]
|
||||
|
183
pyctbgui/pyctbgui/services/DACs.py
Normal file
183
pyctbgui/pyctbgui/services/DACs.py
Normal file
@ -0,0 +1,183 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class DacTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "Dacs.ui", parent)
|
||||
self.view = parent
|
||||
|
||||
def setup_ui(self):
|
||||
for i in range(Defines.dac.count):
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
getattr(self.view, f"spinBoxDAC{i}").setValue(self.det.getDAC(dac)[0])
|
||||
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.checkBoxHighVoltage.setDisabled(True)
|
||||
self.view.spinBoxHighVoltage.setDisabled(True)
|
||||
self.view.labelHighVoltage.setDisabled(True)
|
||||
self.view.labelADCVppDacName.setDisabled(True)
|
||||
self.view.labelADCVpp.setDisabled(True)
|
||||
self.view.comboBoxADCVpp.setDisabled(True)
|
||||
elif self.det.highvoltage == 0:
|
||||
self.view.spinBoxHighVoltage.setDisabled(True)
|
||||
self.view.checkBoxHighVoltage.setChecked(False)
|
||||
|
||||
def connect_ui(self):
|
||||
n_dacs = len(self.det.daclist)
|
||||
for i in range(n_dacs):
|
||||
getattr(self.view, f"spinBoxDAC{i}").editingFinished.connect(partial(self.setDAC, i))
|
||||
getattr(self.view, f"checkBoxDAC{i}").stateChanged.connect(partial(self.setDACTristate, i))
|
||||
getattr(self.view, f"checkBoxDAC{i}mV").stateChanged.connect(partial(self.getDAC, i))
|
||||
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
|
||||
def refresh(self):
|
||||
self.updateDACNames()
|
||||
for i in range(Defines.dac.count):
|
||||
self.getDACTristate(i)
|
||||
self.getDAC(i)
|
||||
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
self.getADCVpp()
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
self.getHighVoltage()
|
||||
|
||||
def updateDACNames(self):
|
||||
for i, name in enumerate(self.det.getDacNames()):
|
||||
getattr(self.view, f"checkBoxDAC{i}").setText(name)
|
||||
|
||||
def getDACTristate(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
checkBox.stateChanged.disconnect()
|
||||
if (self.det.getDAC(dac)[0]) == -100:
|
||||
checkBox.setChecked(False)
|
||||
else:
|
||||
checkBox.setChecked(True)
|
||||
checkBox.stateChanged.connect(partial(self.setDACTristate, i))
|
||||
|
||||
def setDACTristate(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
if not checkBox.isChecked():
|
||||
self.setDAC(i)
|
||||
self.getDAC(i)
|
||||
|
||||
def getDAC(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
checkBoxmV = getattr(self.view, f"checkBoxDAC{i}mV")
|
||||
spinBox = getattr(self.view, f"spinBoxDAC{i}")
|
||||
label = getattr(self.view, f"labelDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBoxmV.stateChanged.disconnect()
|
||||
spinBox.editingFinished.disconnect()
|
||||
|
||||
# do not uncheck automatically
|
||||
if self.det.getDAC(dac)[0] != -100:
|
||||
checkBox.setChecked(True)
|
||||
|
||||
if checkBox.isChecked():
|
||||
spinBox.setEnabled(True)
|
||||
checkBoxmV.setEnabled(True)
|
||||
else:
|
||||
spinBox.setDisabled(True)
|
||||
checkBoxmV.setDisabled(True)
|
||||
|
||||
in_mv = checkBoxmV.isChecked() and checkBox.isChecked()
|
||||
dacValue = self.det.getDAC(dac, in_mv)[0]
|
||||
unit = "mV" if in_mv else ""
|
||||
label.setText(f"{dacValue} {unit}")
|
||||
spinBox.setValue(dacValue)
|
||||
|
||||
checkBox.stateChanged.connect(partial(self.setDACTristate, i))
|
||||
checkBoxmV.stateChanged.connect(partial(self.getDAC, i))
|
||||
spinBox.editingFinished.connect(partial(self.setDAC, i))
|
||||
|
||||
def setDAC(self, i):
|
||||
checkBoxDac = getattr(self.view, f"checkBoxDAC{i}")
|
||||
checkBoxmV = getattr(self.view, f"checkBoxDAC{i}mV")
|
||||
spinBox = getattr(self.view, f"spinBoxDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
|
||||
value = -100
|
||||
if checkBoxDac.isChecked():
|
||||
value = spinBox.value()
|
||||
in_mV = checkBoxDac.isChecked() and checkBoxmV.isChecked()
|
||||
self.det.setDAC(dac, value, in_mV)
|
||||
self.getDAC(i)
|
||||
|
||||
def getADCVpp(self):
|
||||
retval = self.det.adcvpp
|
||||
self.view.labelADCVpp.setText(f'Mode: {str(retval)}')
|
||||
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxADCVpp.setCurrentIndex(retval)
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
|
||||
def setADCVpp(self):
|
||||
self.det.adcvpp = self.view.comboBoxADCVpp.currentIndex()
|
||||
self.getADCVpp()
|
||||
|
||||
def getHighVoltage(self):
|
||||
retval = self.det.highvoltage
|
||||
self.view.labelHighVoltage.setText(str(retval))
|
||||
|
||||
self.view.spinBoxHighVoltage.editingFinished.disconnect()
|
||||
self.view.checkBoxHighVoltage.stateChanged.disconnect()
|
||||
|
||||
self.view.spinBoxHighVoltage.setValue(retval)
|
||||
if retval:
|
||||
self.view.checkBoxHighVoltage.setChecked(True)
|
||||
if self.view.checkBoxHighVoltage.isChecked():
|
||||
self.view.spinBoxHighVoltage.setEnabled(True)
|
||||
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
|
||||
def setHighVoltage(self):
|
||||
value = 0
|
||||
if self.view.checkBoxHighVoltage.isChecked():
|
||||
value = self.view.spinBoxHighVoltage.value()
|
||||
try:
|
||||
self.det.highvoltage = value
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "High Voltage Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
self.getHighVoltage()
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
"""
|
||||
save parameters for the current tab
|
||||
@return: list of commands
|
||||
"""
|
||||
commands = []
|
||||
for i in range(Defines.dac.count):
|
||||
# if checkbox disabled put -100 in dac units
|
||||
enabled = getattr(self.view, f"checkBoxDAC{i}").isChecked()
|
||||
if not enabled:
|
||||
commands.append(f"dac {i} -100")
|
||||
# else put the value in dac or mV units
|
||||
else:
|
||||
value = getattr(self.view, f"spinBoxDAC{i}").value()
|
||||
inMV = getattr(self.view, f"checkBoxDAC{i}mV").isChecked()
|
||||
unit = " mV" if inMV else ""
|
||||
commands.append(f"dac {i} {value}{unit}")
|
||||
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV")
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}")
|
||||
return commands
|
511
pyctbgui/pyctbgui/services/Pattern.py
Normal file
511
pyctbgui/pyctbgui/services/Pattern.py
Normal file
@ -0,0 +1,511 @@
|
||||
import os
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.plotPattern import PlotPattern
|
||||
|
||||
from slsdet import DurationWrapper
|
||||
|
||||
class PatternTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "pattern.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab = None
|
||||
|
||||
def setup_ui(self):
|
||||
# Pattern Tab
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
|
||||
for i in range(len(Defines.Colors)):
|
||||
self.view.comboBoxPatColor.addItem(Defines.Colors[i])
|
||||
self.view.comboBoxPatWaitColor.addItem(Defines.Colors[i])
|
||||
self.view.comboBoxPatLoopColor.addItem(Defines.Colors[i])
|
||||
for i in range(len(Defines.LineStyles)):
|
||||
self.view.comboBoxPatWaitLineStyle.addItem(Defines.LineStyles[i])
|
||||
self.view.comboBoxPatLoopLineStyle.addItem(Defines.LineStyles[i])
|
||||
self.updateDefaultPatViewerParameters()
|
||||
self.view.comboBoxPatColorSelect.setCurrentIndex(0)
|
||||
self.view.comboBoxPatWait.setCurrentIndex(0)
|
||||
self.view.comboBoxPatLoop.setCurrentIndex(0)
|
||||
self.view.spinBoxPatClockSpacing.setValue(self.clock_vertical_lines_spacing)
|
||||
self.view.checkBoxPatShowClockNumber.setChecked(self.show_clocks_number)
|
||||
self.view.doubleSpinBoxLineWidth.setValue(self.line_width)
|
||||
self.view.lineEditPatternFile.setText(self.det.patfname[0])
|
||||
# rest gets updated after connecting to slots
|
||||
# pattern viewer plot area
|
||||
self.figure, self.ax = plt.subplots()
|
||||
self.canvas = FigureCanvas(self.figure)
|
||||
self.toolbar = NavigationToolbar(self.canvas, self.view)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.toolbar)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.canvas)
|
||||
self.figure.clear()
|
||||
|
||||
def connect_ui(self):
|
||||
# For Pattern Tab
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
getattr(self.view,
|
||||
f"lineEditLoop{i}Start").editingFinished.connect(partial(self.setPatLoopStartStopAddress, i))
|
||||
getattr(self.view,
|
||||
f"lineEditLoop{i}Stop").editingFinished.connect(partial(self.setPatLoopStartStopAddress, i))
|
||||
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)
|
||||
self.view.pushButtonCompiler.clicked.connect(self.setCompiler)
|
||||
self.view.pushButtonUncompiled.clicked.connect(self.setUncompiledPatternFile)
|
||||
self.view.pushButtonPatternFile.clicked.connect(self.setPatternFile)
|
||||
self.view.pushButtonLoadPattern.clicked.connect(self.loadPattern)
|
||||
|
||||
self.view.comboBoxPatColorSelect.currentIndexChanged.connect(self.getPatViewerColors)
|
||||
self.view.comboBoxPatWait.currentIndexChanged.connect(self.getPatViewerWaitParameters)
|
||||
self.view.comboBoxPatLoop.currentIndexChanged.connect(self.getPatViewerLoopParameters)
|
||||
|
||||
self.view.comboBoxPatColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.spinBoxPatClockSpacing.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.checkBoxPatShowClockNumber.stateChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLineWidth.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.pushButtonViewPattern.clicked.connect(self.viewPattern)
|
||||
|
||||
def refresh(self):
|
||||
self.getPatLimitAddress()
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
self.getPatLoopStartStopAddress(i)
|
||||
self.getPatLoopWaitAddress(i)
|
||||
self.getPatLoopRepetition(i)
|
||||
self.getPatLoopWaitClocks(i)
|
||||
self.getPatLoopWaitInterval(i)
|
||||
|
||||
# Pattern Tab functions
|
||||
|
||||
def getPatLimitAddress(self):
|
||||
retval = self.det.patlimits
|
||||
self.view.lineEditStartAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStopAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStartAddress.setText("0x{:04x}".format(retval[0]))
|
||||
self.view.lineEditStopAddress.setText("0x{:04x}".format(retval[1]))
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
|
||||
def setPatLimitAddress(self):
|
||||
self.view.lineEditStartAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStopAddress.editingFinished.disconnect()
|
||||
try:
|
||||
start = int(self.view.lineEditStartAddress.text(), 16)
|
||||
stop = int(self.view.lineEditStopAddress.text(), 16)
|
||||
self.det.patlimits = [start, stop]
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Limit Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.getPatLimitAddress()
|
||||
|
||||
def getPatLoopStartStopAddress(self, level):
|
||||
retval = self.det.patloop[level]
|
||||
lineEditStart = getattr(self.view, f"lineEditLoop{level}Start")
|
||||
lineEditStop = getattr(self.view, f"lineEditLoop{level}Stop")
|
||||
lineEditStart.editingFinished.disconnect()
|
||||
lineEditStop.editingFinished.disconnect()
|
||||
lineEditStart.setText("0x{:04x}".format(retval[0]))
|
||||
lineEditStop.setText("0x{:04x}".format(retval[1]))
|
||||
lineEditStart.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
lineEditStop.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
|
||||
def setPatLoopStartStopAddress(self, level):
|
||||
lineEditStart = getattr(self.view, f"lineEditLoop{level}Start")
|
||||
lineEditStop = getattr(self.view, f"lineEditLoop{level}Stop")
|
||||
lineEditStart.editingFinished.disconnect()
|
||||
lineEditStop.editingFinished.disconnect()
|
||||
try:
|
||||
start = int(lineEditStart.text(), 16)
|
||||
stop = int(lineEditStop.text(), 16)
|
||||
self.det.patloop[level] = [start, stop]
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Loop Start Stop Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
lineEditStart.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
lineEditStop.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
self.getPatLoopStartStopAddress(level)
|
||||
|
||||
def getPatLoopWaitAddress(self, level):
|
||||
retval = self.det.patwait[level]
|
||||
lineEdit = getattr(self.view, f"lineEditLoop{level}Wait")
|
||||
lineEdit.editingFinished.disconnect()
|
||||
lineEdit.setText("0x{:04x}".format(retval))
|
||||
lineEdit.editingFinished.connect(partial(self.setPatLoopWaitAddress, level))
|
||||
|
||||
def setPatLoopWaitAddress(self, level):
|
||||
lineEdit = getattr(self.view, f"lineEditLoop{level}Wait")
|
||||
lineEdit.editingFinished.disconnect()
|
||||
try:
|
||||
addr = int(lineEdit.text(), 16)
|
||||
self.det.patwait[level] = addr
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Wait Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
lineEdit.editingFinished.connect(partial(self.setPatLoopWaitAddress, level))
|
||||
self.getPatLoopWaitAddress(level)
|
||||
|
||||
def getPatLoopRepetition(self, level):
|
||||
retval = self.det.patnloop[level]
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}Repetition")
|
||||
spinBox.editingFinished.disconnect()
|
||||
spinBox.setValue(retval)
|
||||
spinBox.editingFinished.connect(partial(self.setPatLoopRepetition, level))
|
||||
|
||||
def setPatLoopRepetition(self, level):
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}Repetition")
|
||||
self.det.patnloop[level] = spinBox.value()
|
||||
self.getPatLoopRepetition(level)
|
||||
|
||||
def getPatLoopWaitClocks(self, level):
|
||||
retval = self.det.patwaittime[level]
|
||||
spinBox = getattr(self.view, f"doubleSpinBoxLoop{level}WaitClocks")
|
||||
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)
|
||||
|
||||
|
||||
def setCompiler(self):
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(
|
||||
parent=self.mainWindow,
|
||||
caption="Select a compiler file",
|
||||
directory=str(Path.cwd()),
|
||||
# filter='README (*.md *.ui)'
|
||||
)
|
||||
if response[0]:
|
||||
self.view.lineEditCompiler.setText(response[0])
|
||||
|
||||
def setUncompiledPatternFile(self):
|
||||
filt = 'Pattern code(*.py *.c)'
|
||||
folder = Path(self.det.patfname[0]).parent
|
||||
if not folder:
|
||||
folder = Path.cwd()
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(parent=self.mainWindow,
|
||||
caption="Select an uncompiled pattern file",
|
||||
directory=str(folder),
|
||||
filter=filt)
|
||||
if response[0]:
|
||||
self.view.lineEditUncompiled.setText(response[0])
|
||||
|
||||
def setPatternFile(self):
|
||||
filt = 'Pattern file(*.pyat *.pat)'
|
||||
folder = Path(self.det.patfname[0]).parent
|
||||
if not folder:
|
||||
folder = Path.cwd()
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(parent=self.mainWindow,
|
||||
caption="Select a compiled pattern file",
|
||||
directory=str(folder),
|
||||
filter=filt)
|
||||
if response[0]:
|
||||
self.view.lineEditPatternFile.setText(response[0])
|
||||
|
||||
def compilePattern(self):
|
||||
compilerFile = self.view.lineEditCompiler.text()
|
||||
if not compilerFile:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Compile Fail", "No compiler selected. Please select one.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
|
||||
pattern_file = self.view.lineEditUncompiled.text()
|
||||
|
||||
# if old compile file exists, backup and remove to ensure old copy not loaded
|
||||
oldFile = Path(pattern_file + 'at')
|
||||
if oldFile.is_file():
|
||||
print("Moving old compiled pattern file to _bck")
|
||||
exit_status = os.system('mv ' + str(oldFile) + ' ' + str(oldFile) + '_bkup')
|
||||
if exit_status != 0:
|
||||
retval = QtWidgets.QMessageBox.question(
|
||||
self.mainWindow, "Backup Fail",
|
||||
"Could not make a backup of old compiled code. Proceed anyway to compile and overwrite?",
|
||||
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
||||
if retval == QtWidgets.QMessageBox.No:
|
||||
return ""
|
||||
|
||||
compileCommand = compilerFile + ' ' + pattern_file
|
||||
print(compileCommand)
|
||||
print("Compiling pattern code to .pat file")
|
||||
exit_status = os.system(compileCommand)
|
||||
if exit_status != 0:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Compile Fail", "Could not compile pattern.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
pattern_file += 'at'
|
||||
|
||||
return pattern_file
|
||||
|
||||
def getCompiledPatFname(self):
|
||||
if self.view.checkBoxCompile.isChecked():
|
||||
pattern_file = self.compilePattern()
|
||||
# pat name from pattern field
|
||||
else:
|
||||
pattern_file = self.view.lineEditPatternFile.text()
|
||||
if not pattern_file:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Fail",
|
||||
"No pattern file selected. Please select one.", QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
return pattern_file
|
||||
|
||||
def loadPattern(self):
|
||||
pattern_file = self.getCompiledPatFname()
|
||||
if not pattern_file:
|
||||
return
|
||||
# load pattern
|
||||
self.det.pattern = pattern_file
|
||||
self.view.lineEditPatternFile.setText(self.det.patfname[0])
|
||||
|
||||
def getPatViewerColors(self):
|
||||
colorLevel = self.view.comboBoxPatColorSelect.currentIndex()
|
||||
color = self.colors_plot[colorLevel]
|
||||
self.view.comboBoxPatColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
|
||||
def getPatViewerWaitParameters(self):
|
||||
waitLevel = self.view.comboBoxPatWait.currentIndex()
|
||||
color = self.colors_wait[waitLevel]
|
||||
line_style = self.linestyles_wait[waitLevel]
|
||||
alpha = self.alpha_wait[waitLevel]
|
||||
alpha_rect = self.alpha_wait_rect[waitLevel]
|
||||
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.disconnect()
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.disconnect()
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.disconnect()
|
||||
|
||||
self.view.comboBoxPatWaitColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatWaitLineStyle.setCurrentIndex(Defines.LineStyles.index(line_style))
|
||||
self.view.doubleSpinBoxWaitAlpha.setValue(alpha)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.setValue(alpha_rect)
|
||||
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
|
||||
def getPatViewerLoopParameters(self):
|
||||
loopLevel = self.view.comboBoxPatLoop.currentIndex()
|
||||
color = self.colors_loop[loopLevel]
|
||||
line_style = self.linestyles_loop[loopLevel]
|
||||
alpha = self.alpha_loop[loopLevel]
|
||||
alpha_rect = self.alpha_loop_rect[loopLevel]
|
||||
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.disconnect()
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.disconnect()
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.disconnect()
|
||||
|
||||
self.view.comboBoxPatLoopColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatLoopLineStyle.setCurrentIndex(Defines.LineStyles.index(line_style))
|
||||
self.view.doubleSpinBoxLoopAlpha.setValue(alpha)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.setValue(alpha_rect)
|
||||
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
|
||||
# only at start up
|
||||
def updateDefaultPatViewerParameters(self):
|
||||
self.colors_plot = Defines.Colors_plot.copy()
|
||||
self.colors_wait = Defines.Colors_wait.copy()
|
||||
self.linestyles_wait = Defines.Linestyles_wait.copy()
|
||||
self.alpha_wait = Defines.Alpha_wait.copy()
|
||||
self.alpha_wait_rect = Defines.Alpha_wait_rect.copy()
|
||||
self.colors_loop = Defines.Colors_loop.copy()
|
||||
self.linestyles_loop = Defines.Linestyles_loop.copy()
|
||||
self.alpha_loop = Defines.Alpha_loop.copy()
|
||||
self.alpha_loop_rect = Defines.Alpha_loop_rect.copy()
|
||||
self.clock_vertical_lines_spacing = Defines.Clock_vertical_lines_spacing
|
||||
self.show_clocks_number = Defines.Show_clocks_number
|
||||
self.line_width = Defines.Line_width
|
||||
|
||||
# print('default')
|
||||
# self.printPatViewerParameters()
|
||||
|
||||
def updatePatViewerParameters(self):
|
||||
colorLevel = self.view.comboBoxPatColorSelect.currentIndex()
|
||||
color = self.view.comboBoxPatColor.currentIndex()
|
||||
# self.colors_plot[colorLevel] = f'tab:{Defines.Colors[color].lower()}'
|
||||
self.colors_plot[colorLevel] = Defines.Colors[color]
|
||||
|
||||
waitLevel = self.view.comboBoxPatWait.currentIndex()
|
||||
color = self.view.comboBoxPatWaitColor.currentIndex()
|
||||
line_style = self.view.comboBoxPatWaitLineStyle.currentIndex()
|
||||
alpha = self.view.doubleSpinBoxWaitAlpha.value()
|
||||
alpha_rect = self.view.doubleSpinBoxWaitAlphaRect.value()
|
||||
|
||||
self.colors_wait[waitLevel] = Defines.Colors[color]
|
||||
self.linestyles_wait[waitLevel] = Defines.LineStyles[line_style]
|
||||
self.alpha_wait[waitLevel] = alpha
|
||||
self.alpha_wait_rect[waitLevel] = alpha_rect
|
||||
|
||||
loopLevel = self.view.comboBoxPatLoop.currentIndex()
|
||||
color = self.view.comboBoxPatLoopColor.currentIndex()
|
||||
line_style = self.view.comboBoxPatLoopLineStyle.currentIndex()
|
||||
alpha = self.view.doubleSpinBoxLoopAlpha.value()
|
||||
alpha_rect = self.view.doubleSpinBoxLoopAlphaRect.value()
|
||||
|
||||
self.colors_loop[loopLevel] = Defines.Colors[color]
|
||||
self.linestyles_loop[loopLevel] = Defines.LineStyles[line_style]
|
||||
self.alpha_loop[loopLevel] = alpha
|
||||
self.alpha_loop_rect[loopLevel] = alpha_rect
|
||||
|
||||
self.clock_vertical_lines_spacing = self.view.spinBoxPatClockSpacing.value()
|
||||
self.show_clocks_number = self.view.checkBoxPatShowClockNumber.isChecked()
|
||||
self.line_width = self.view.doubleSpinBoxLineWidth.value()
|
||||
|
||||
# for debugging
|
||||
# self.printPatViewerParameters()
|
||||
|
||||
def printPatViewerParameters(self):
|
||||
print('Pattern Viewer Parameters:')
|
||||
print(f'\tcolor1: {self.colors_plot[0]}, color2: {self.colors_plot[1]}')
|
||||
print(f"\twait color: {self.colors_wait}")
|
||||
print(f"\twait linestyles: {self.linestyles_wait}")
|
||||
print(f"\twait alpha: {self.alpha_wait}")
|
||||
print(f"\twait alpha rect: {self.alpha_wait_rect}")
|
||||
print(f"\tloop color: {self.colors_loop}")
|
||||
print(f"\tloop linestyles: {self.linestyles_loop}")
|
||||
print(f"\tloop alpha: {self.alpha_loop}")
|
||||
print(f"\tloop alpha rect: {self.alpha_loop_rect}")
|
||||
print(f'\tclock vertical lines spacing: {self.clock_vertical_lines_spacing}')
|
||||
print(f'\tshow clocks number: {self.show_clocks_number}')
|
||||
print(f'\tline width: {self.line_width}')
|
||||
print('\n')
|
||||
|
||||
def viewPattern(self):
|
||||
self.plotTab.showPatternViewer(True)
|
||||
pattern_file = self.getCompiledPatFname()
|
||||
if not pattern_file:
|
||||
return
|
||||
|
||||
signalNames = self.det.getSignalNames()
|
||||
p = PlotPattern(
|
||||
pattern_file,
|
||||
signalNames,
|
||||
self.colors_plot,
|
||||
self.colors_wait,
|
||||
self.linestyles_wait,
|
||||
self.alpha_wait,
|
||||
self.alpha_wait_rect,
|
||||
self.colors_loop,
|
||||
self.linestyles_loop,
|
||||
self.alpha_loop,
|
||||
self.alpha_loop_rect,
|
||||
self.clock_vertical_lines_spacing,
|
||||
self.show_clocks_number,
|
||||
self.line_width,
|
||||
)
|
||||
|
||||
plt.close(self.figure)
|
||||
self.mainWindow.gridLayoutPatternViewer.removeWidget(self.canvas)
|
||||
self.canvas.close()
|
||||
self.mainWindow.gridLayoutPatternViewer.removeWidget(self.toolbar)
|
||||
self.toolbar.close()
|
||||
|
||||
try:
|
||||
self.figure = p.patternPlot()
|
||||
self.canvas = FigureCanvas(self.figure)
|
||||
self.toolbar = NavigationToolbar(self.canvas, self.view)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.toolbar)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.canvas)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Viewer Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
commands = []
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
commands.append(f"patnloop {i} {getattr(self.view, f'spinBoxLoop{i}Repetition').text()}")
|
||||
commands.append(f"patloop {i} {getattr(self.view, f'lineEditLoop{i}Start').text()}, "
|
||||
f"{getattr(self.view, f'lineEditLoop{i}Stop').text()}")
|
||||
|
||||
commands.append(f"patwait {i} {getattr(self.view, f'lineEditLoop{i}Wait').text()}")
|
||||
commands.append(f"patwaittime {i} {getattr(self.view, f'doubleSpinBoxLoop{i}WaitClocks').text()}")
|
||||
commands.append(f"patlimits {self.view.lineEditStartAddress.text()}, {self.view.lineEditStopAddress.text()}")
|
||||
# commands.append(f"patfname {self.view.lineEditPatternFile.text()}")
|
||||
return commands
|
519
pyctbgui/pyctbgui/services/Plot.py
Normal file
519
pyctbgui/pyctbgui/services/Plot.py
Normal file
@ -0,0 +1,519 @@
|
||||
import logging
|
||||
from functools import partial
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, QtGui, uic
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyctbgui.utils import recordOrApplyPedestal
|
||||
from pyqtgraph import PlotWidget
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
|
||||
class PlotTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.frame_min: float = 0.0
|
||||
self.frame_max: float = 0.0
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "plot.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.signalsTab = None
|
||||
self.transceiverTab = None
|
||||
self.acquisitionTab = None
|
||||
self.adcTab = None
|
||||
self.cmin: float = 0.0
|
||||
self.cmax: float = 0.0
|
||||
self.colorRangeMode: Defines.colorRange = Defines.colorRange.all
|
||||
self.ignoreHistogramSignal: bool = False
|
||||
self.imagePlots: list[PlotWidget] = []
|
||||
# list of callback functions to notify tabs when we should hide their legend
|
||||
# follows the observer design pattern
|
||||
self.hideLegendObservers = []
|
||||
self.pedestalRecord: bool = False
|
||||
self.pedestalApply: bool = True
|
||||
self.__acqFrames = None
|
||||
self.logger = logging.getLogger('PlotTab')
|
||||
|
||||
def setup_ui(self):
|
||||
self.signalsTab = self.mainWindow.signalsTab
|
||||
self.transceiverTab = self.mainWindow.transceiverTab
|
||||
self.acquisitionTab = self.mainWindow.acquisitionTab
|
||||
self.adcTab = self.mainWindow.adcTab
|
||||
self.initializeColorMaps()
|
||||
|
||||
self.imagePlots = (
|
||||
self.mainWindow.plotAnalogImage,
|
||||
self.mainWindow.plotDigitalImage,
|
||||
self.mainWindow.plotTransceiverImage,
|
||||
)
|
||||
|
||||
def connect_ui(self):
|
||||
self.view.radioButtonNoPlot.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonWaveform.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonDistribution.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonImage.clicked.connect(self.plotOptions)
|
||||
self.view.comboBoxPlot.currentIndexChanged.connect(self.setPixelMap)
|
||||
self.view.comboBoxColorMap.currentIndexChanged.connect(self.setColorMap)
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.connect(self.setZMQHWM)
|
||||
self.view.spinBoxSerialOffset.editingFinished.connect(self.setSerialOffset)
|
||||
self.view.spinBoxNCount.editingFinished.connect(self.setNCounter)
|
||||
self.view.spinBoxDynamicRange.editingFinished.connect(self.setDynamicRange)
|
||||
self.view.spinBoxImageX.editingFinished.connect(self.setImageX)
|
||||
self.view.spinBoxImageY.editingFinished.connect(self.setImageY)
|
||||
|
||||
self.view.radioButtonPedestalRecord.toggled.connect(self.togglePedestalRecord)
|
||||
self.view.radioButtonPedestalApply.toggled.connect(self.togglePedestalApply)
|
||||
self.view.pushButtonPedestalReset.clicked.connect(self.resetPedestal)
|
||||
self.view.pushButtonSavePedestal.clicked.connect(self.savePedestal)
|
||||
self.view.pushButtonLoadPedestal.clicked.connect(self.loadPedestal)
|
||||
|
||||
self.view.checkBoxRaw.stateChanged.connect(self.setRawData)
|
||||
self.view.spinBoxRawMin.editingFinished.connect(self.setRawData)
|
||||
self.view.spinBoxRawMax.editingFinished.connect(self.setRawData)
|
||||
self.view.checkBoxPedestal.stateChanged.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxPedestalMin.editingFinished.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxPedestalMax.editingFinished.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxFit.editingFinished.connect(self.setFitADC)
|
||||
self.view.spinBoxPlot.editingFinished.connect(self.setPlotBit)
|
||||
self.view.pushButtonReferesh.clicked.connect(self.acquisitionTab.refresh)
|
||||
# color range widgets
|
||||
self.view.cminSpinBox.editingFinished.connect(self.setCmin)
|
||||
self.view.cmaxSpinBox.editingFinished.connect(self.setCmax)
|
||||
self.view.radioButtonAutomatic.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.all))
|
||||
self.view.radioButtonFixed.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.fixed))
|
||||
self.view.radioButtonCenter.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.center))
|
||||
|
||||
for plot in self.imagePlots:
|
||||
plot.scene.sigMouseMoved.connect(partial(self.showPlotValues, plot))
|
||||
plot.getHistogramWidget().item.sigLevelChangeFinished.connect(partial(self.handleHistogramChange, plot))
|
||||
|
||||
self.view.checkBoxShowLegend.stateChanged.connect(self.toggleLegend)
|
||||
|
||||
def refresh(self):
|
||||
self.getZMQHWM()
|
||||
|
||||
def initializeColorMaps(self):
|
||||
self.view.comboBoxColorMap.addItems(Defines.Color_map)
|
||||
self.view.comboBoxColorMap.setCurrentIndex(Defines.Color_map.index(Defines.Default_Color_Map))
|
||||
self.setColorMap()
|
||||
|
||||
def savePedestal(self):
|
||||
"""
|
||||
slot function to save pedestal values
|
||||
"""
|
||||
response = QtWidgets.QFileDialog.getSaveFileName(self.view, "Save Pedestal", str(self.det.fpath))
|
||||
recordOrApplyPedestal.savePedestal(Path(response[0]))
|
||||
self.logger.info(f'saved Pedestal in {response[0]}')
|
||||
|
||||
def loadPedestal(self):
|
||||
"""
|
||||
slot function to load pedestal values
|
||||
"""
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(self.view, "Load Pedestal", str(self.det.fpath))
|
||||
if response[0] == '':
|
||||
return
|
||||
recordOrApplyPedestal.reset(self)
|
||||
try:
|
||||
recordOrApplyPedestal.loadPedestal(Path(response[0]))
|
||||
except (IsADirectoryError, ValueError, EOFError):
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.view,
|
||||
"Loading Pedestal Failed",
|
||||
"Loading Pedestal failed make sure the file is in the valid .npy format",
|
||||
QtWidgets.QMessageBox.Ok,
|
||||
)
|
||||
self.logger.exception("Exception when loading pedestal")
|
||||
else:
|
||||
self.logger.info(f'loaded Pedestal from {response[0]}')
|
||||
self.updateLabelPedestalFrames(True)
|
||||
|
||||
def togglePedestalRecord(self):
|
||||
"""
|
||||
slot function for pedestal record radio button
|
||||
toggle pedestal record variable and disables the frames spinboxes in acquisition tab or plot tab depenging on
|
||||
the mode
|
||||
"""
|
||||
self.pedestalRecord = not self.pedestalRecord
|
||||
|
||||
def togglePedestalApply(self):
|
||||
"""
|
||||
slot function for pedestal apply radio button
|
||||
"""
|
||||
self.pedestalApply = not self.pedestalApply
|
||||
|
||||
def resetPedestal(self):
|
||||
"""
|
||||
slot function for resetting the pedestal
|
||||
"""
|
||||
recordOrApplyPedestal.reset(self)
|
||||
|
||||
def updateLabelPedestalFrames(self, loadedPedestal=False):
|
||||
"""
|
||||
updates labelPedestalFrames to the length of savedFrames
|
||||
"""
|
||||
if loadedPedestal:
|
||||
self.view.labelPedestalFrames.setText('using loaded pedestal file')
|
||||
else:
|
||||
self.view.labelPedestalFrames.setText(f'recorded frames: {recordOrApplyPedestal.getFramesCount()}')
|
||||
|
||||
def subscribeToggleLegend(self, fn_cbk):
|
||||
"""
|
||||
subscribe to the event of toggling the hide legend checkbox by subscribing
|
||||
with a callback function
|
||||
"""
|
||||
self.hideLegendObservers.append(fn_cbk)
|
||||
|
||||
def toggleLegend(self):
|
||||
"""
|
||||
notify subscribers for the showLegend checkbox event by executing their callbacks
|
||||
"""
|
||||
self.mainWindow.showLegend = not self.mainWindow.showLegend
|
||||
for notify_function in self.hideLegendObservers:
|
||||
notify_function()
|
||||
|
||||
def setCmin(self, value=None):
|
||||
"""
|
||||
slot for setting cmin from cminSpinBox
|
||||
also used as a normal function
|
||||
"""
|
||||
if value is None:
|
||||
self.cmin = self.view.cminSpinBox.value()
|
||||
else:
|
||||
self.cmin = value
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def setCmax(self, value=None):
|
||||
"""
|
||||
slot for setting cmax from cmaxSpinBox
|
||||
also used as a normal function
|
||||
"""
|
||||
if value is None:
|
||||
self.cmax = self.view.cmaxSpinBox.value()
|
||||
else:
|
||||
self.cmax = value
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def setColorRangeMode(self, mode):
|
||||
"""
|
||||
slot for setting the color range mode (all,fixed,3-97%)
|
||||
"""
|
||||
self.colorRangeMode = mode
|
||||
|
||||
# disable or enable cmin/cmax spinboxes
|
||||
enableSpinBoxes = mode == Defines.colorRange.fixed
|
||||
self.view.cminSpinBox.setEnabled(enableSpinBoxes)
|
||||
self.view.cmaxSpinBox.setEnabled(enableSpinBoxes)
|
||||
self.updateColorRange()
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def handleHistogramChange(self, plot):
|
||||
"""
|
||||
slot called after changing the color bar
|
||||
This is called even when pyqtgraph sets the image without any user intervention
|
||||
the class attribute ignore_histogram_signal is set to False before setting the image
|
||||
so that we can distinguish between the signal originates from pyqt or from the user
|
||||
"""
|
||||
if not self.ignoreHistogramSignal:
|
||||
self.cmin, self.cmax = plot.getHistogramWidget().item.getLevels()
|
||||
self.setCmin(self.cmin)
|
||||
self.setCmax(self.cmax)
|
||||
|
||||
self.ignoreHistogramSignal = False
|
||||
# self.setColorRangeMode(Defines.colorRange.fixed)
|
||||
|
||||
def setFrameLimits(self, frame):
|
||||
"""
|
||||
function called from AcquisitionTab::read_zmq to get the maximum and minimum
|
||||
values of the decoded frame and save them in frame_min/frame_max
|
||||
"""
|
||||
self.frame_min = np.min(frame)
|
||||
self.frame_max = np.max(frame)
|
||||
self.updateColorRange()
|
||||
|
||||
def updateColorRange(self):
|
||||
"""
|
||||
for mode:
|
||||
- all: sets cmin and cmax to the maximums/minimum values of the frame
|
||||
- 3-97%: limits cmax and cmin so that we ignore 3% from each end of the whole range
|
||||
- fixed: this function does not change cmin and cmax
|
||||
"""
|
||||
|
||||
if self.colorRangeMode == Defines.colorRange.all:
|
||||
self.cmin = self.frame_min
|
||||
self.cmax = self.frame_max
|
||||
elif self.colorRangeMode == Defines.colorRange.center:
|
||||
self.cmin = self.frame_min + 0.03 * (self.frame_max - self.frame_min)
|
||||
self.cmax = self.frame_max - 0.03 * (self.frame_max - self.frame_min)
|
||||
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def updateColorRangeUI(self):
|
||||
"""
|
||||
updates UI views should be called after every change to cmin or cmax
|
||||
"""
|
||||
for plot in self.imagePlots:
|
||||
plot.getHistogramWidget().item.setLevels(min=self.cmin, max=self.cmax)
|
||||
self.view.cminSpinBox.setValue(self.cmin)
|
||||
self.view.cmaxSpinBox.setValue(self.cmax)
|
||||
|
||||
def setColorMap(self):
|
||||
cm = pg.colormap.getFromMatplotlib(self.view.comboBoxColorMap.currentText())
|
||||
# print(f'color map:{self.comboBoxColorMap.currentText()}')
|
||||
self.mainWindow.plotAnalogImage.setColorMap(cm)
|
||||
self.mainWindow.plotDigitalImage.setColorMap(cm)
|
||||
self.mainWindow.plotTransceiverImage.setColorMap(cm)
|
||||
|
||||
def getZMQHWM(self):
|
||||
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.disconnect()
|
||||
|
||||
rx_zmq_hwm = self.det.getRxZmqHwm()[0]
|
||||
# ensure same value in client zmq
|
||||
self.det.setClientZmqHwm(rx_zmq_hwm)
|
||||
|
||||
# high readout, low HWM
|
||||
if -1 < rx_zmq_hwm < 25:
|
||||
self.view.comboBoxZMQHWM.setCurrentIndex(1)
|
||||
# low readout, high HWM
|
||||
else:
|
||||
self.view.comboBoxZMQHWM.setCurrentIndex(0)
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.connect(self.setZMQHWM)
|
||||
|
||||
def setZMQHWM(self):
|
||||
val = self.view.comboBoxZMQHWM.currentIndex()
|
||||
# low readout, high HWM
|
||||
if val == 0:
|
||||
self.det.setRxZmqHwm(Defines.Zmq_hwm_low_speed)
|
||||
self.det.setClientZmqHwm(Defines.Zmq_hwm_low_speed)
|
||||
# high readout, low HWM
|
||||
else:
|
||||
self.det.setRxZmqHwm(Defines.Zmq_hwm_high_speed)
|
||||
self.det.setClientZmqHwm(Defines.Zmq_hwm_high_speed)
|
||||
|
||||
self.getZMQHWM()
|
||||
|
||||
def addSelectedAnalogPlots(self, i):
|
||||
enable = getattr(self.adcTab.view, f"checkBoxADC{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.analogPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
def addAllSelectedAnalogPlots(self):
|
||||
for i in range(Defines.adc.count):
|
||||
self.addSelectedAnalogPlots(i)
|
||||
|
||||
def removeAllAnalogPlots(self):
|
||||
for i in range(Defines.adc.count):
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
cm = pg.colormap.get('CET-L9') # prepare a linear color map
|
||||
self.mainWindow.plotDigitalImage.setColorMap(cm)
|
||||
|
||||
def addSelectedDigitalPlots(self, i):
|
||||
enable = getattr(self.signalsTab.view, f"checkBoxBIT{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.digitalPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
def addAllSelectedDigitalPlots(self):
|
||||
for i in range(Defines.signals.count):
|
||||
self.addSelectedDigitalPlots(i)
|
||||
|
||||
def removeAllDigitalPlots(self):
|
||||
for i in range(Defines.signals.count):
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
def addSelectedTransceiverPlots(self, i):
|
||||
enable = getattr(self.transceiverTab.view, f"checkBoxTransceiver{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.transceiverPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.transceiverPlots[i].hide()
|
||||
|
||||
def addAllSelectedTransceiverPlots(self):
|
||||
for i in range(Defines.transceiver.count):
|
||||
self.addSelectedTransceiverPlots(i)
|
||||
|
||||
def removeAllTransceiverPlots(self):
|
||||
for i in range(Defines.transceiver.count):
|
||||
self.mainWindow.transceiverPlots[i].hide()
|
||||
|
||||
def showPlot(self):
|
||||
self.mainWindow.plotAnalogWaveform.hide()
|
||||
self.mainWindow.plotDigitalWaveform.hide()
|
||||
self.mainWindow.plotTransceiverWaveform.hide()
|
||||
self.mainWindow.plotAnalogImage.hide()
|
||||
self.mainWindow.plotDigitalImage.hide()
|
||||
self.mainWindow.plotTransceiverImage.hide()
|
||||
self.view.labelDigitalWaveformOption.setDisabled(True)
|
||||
self.view.radioButtonOverlay.setDisabled(True)
|
||||
self.view.radioButtonStripe.setDisabled(True)
|
||||
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotAnalogWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotAnalogImage.show()
|
||||
if self.mainWindow.romode.value in [1, 2, 4]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotDigitalWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotDigitalImage.show()
|
||||
self.view.labelDigitalWaveformOption.setEnabled(True)
|
||||
self.view.radioButtonOverlay.setEnabled(True)
|
||||
self.view.radioButtonStripe.setEnabled(True)
|
||||
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotTransceiverWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotTransceiverImage.show()
|
||||
|
||||
def plotOptions(self):
|
||||
|
||||
self.mainWindow.framePatternViewer.hide()
|
||||
self.showPlot()
|
||||
|
||||
# disable plotting
|
||||
self.mainWindow.read_timer.stop()
|
||||
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotAnalogWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Output [ADC]</span>")
|
||||
self.mainWindow.plotAnalogWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Analog Sample [#]</span>")
|
||||
self.mainWindow.plotDigitalWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Digital Bit</span>")
|
||||
self.mainWindow.plotDigitalWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Digital Sample [#]</span>")
|
||||
self.mainWindow.plotTransceiverWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Transceiver Bit</span>")
|
||||
self.mainWindow.plotTransceiverWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Transceiver Sample [#]</span>")
|
||||
|
||||
self.view.stackedWidgetPlotType.setCurrentIndex(0)
|
||||
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.view.stackedWidgetPlotType.setCurrentIndex(2)
|
||||
self.setPixelMap()
|
||||
|
||||
if self.view.radioButtonNoPlot.isChecked():
|
||||
self.view.labelPlotOptions.hide()
|
||||
self.view.stackedWidgetPlotType.hide()
|
||||
# enable plotting
|
||||
else:
|
||||
self.view.labelPlotOptions.show()
|
||||
self.view.stackedWidgetPlotType.show()
|
||||
self.mainWindow.read_timer.start(Defines.Time_Plot_Refresh_ms)
|
||||
|
||||
def setPixelMap(self):
|
||||
if self.view.comboBoxPlot.currentText() == "Matterhorn":
|
||||
self.mainWindow.nTransceiverRows = Defines.Matterhorn.nRows
|
||||
self.mainWindow.nTransceiverCols = Defines.Matterhorn.nCols
|
||||
elif self.view.comboBoxPlot.currentText() == "Moench04":
|
||||
self.mainWindow.nAnalogRows = Defines.Moench04.nRows
|
||||
self.mainWindow.nAnalogCols = Defines.Moench04.nCols
|
||||
|
||||
def showPatternViewer(self, enable):
|
||||
if enable:
|
||||
self.mainWindow.framePatternViewer.show()
|
||||
self.mainWindow.framePlot.hide()
|
||||
elif self.mainWindow.framePatternViewer.isVisible():
|
||||
self.mainWindow.framePatternViewer.hide()
|
||||
self.mainWindow.framePlot.show()
|
||||
self.showPlot()
|
||||
|
||||
def setSerialOffset(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setNCounter(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setDynamicRange(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setImageX(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setImageY(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setRawData(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO: raw data, min, max
|
||||
|
||||
def setPedestalSubtract(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO: pedestal, min, max
|
||||
|
||||
def setFitADC(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setPlotBit(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def getRandomColor(self):
|
||||
'''
|
||||
Returns a random color range (except white) in format string eg. "#aabbcc"
|
||||
'''
|
||||
randomColor = random.randrange(0, 0xffffaa, 0xaa)
|
||||
return "#{:06x}".format(randomColor)
|
||||
|
||||
def getActiveColor(self, button):
|
||||
return button.palette().color(QtGui.QPalette.Window)
|
||||
|
||||
def setActiveColor(self, button, str_color):
|
||||
button.setStyleSheet(":enabled {background-color: %s" % str_color + "} :disabled {background-color: grey}")
|
||||
|
||||
def showPalette(self, button):
|
||||
color = QtWidgets.QColorDialog.getColor()
|
||||
if color.isValid():
|
||||
self.setActiveColor(button, color.name())
|
||||
# get the RGB Values
|
||||
# print(color.getRgb())
|
||||
|
||||
def showPlotValues(self, sender, pos):
|
||||
x = sender.getImageItem().mapFromScene(pos).x()
|
||||
y = sender.getImageItem().mapFromScene(pos).y()
|
||||
val = 0
|
||||
nMaxY = self.mainWindow.nAnalogRows
|
||||
nMaxX = self.mainWindow.nAnalogCols
|
||||
frame = self.mainWindow.analog_frame
|
||||
if sender == self.mainWindow.plotDigitalImage:
|
||||
nMaxY = self.mainWindow.nDigitalRows
|
||||
nMaxX = self.mainWindow.nDigitalCols
|
||||
frame = self.mainWindow.digital_frame
|
||||
elif sender == self.mainWindow.plotTransceiverImage:
|
||||
nMaxY = self.mainWindow.nTransceiverRows
|
||||
nMaxX = self.mainWindow.nTransceiverCols
|
||||
frame = self.mainWindow.transceiver_frame
|
||||
if 0 <= x < nMaxX and 0 <= y < nMaxY and not np.array_equal(frame, []):
|
||||
val = frame[int(x), int(y)]
|
||||
message = f'[{x:.2f}, {y:.2f}] = {val:.2f}'
|
||||
sender.setToolTip(message)
|
||||
# print(message)
|
||||
else:
|
||||
sender.setToolTip('')
|
||||
|
||||
def saveParameters(self):
|
||||
commands = []
|
||||
if self.view.comboBoxZMQHWM.currentIndex() == 0:
|
||||
commands.append(f"zmqhwm {Defines.Zmq_hwm_low_speed}")
|
||||
else:
|
||||
commands.append(f"zmqhwm {Defines.Zmq_hwm_high_speed}")
|
||||
return commands
|
135
pyctbgui/pyctbgui/services/PowerSupplies.py
Normal file
135
pyctbgui/pyctbgui/services/PowerSupplies.py
Normal file
@ -0,0 +1,135 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "powerSupplies.ui", parent)
|
||||
self.view = parent
|
||||
|
||||
def refresh(self):
|
||||
self.updateVoltageNames()
|
||||
for i in Defines.powerSupplies:
|
||||
self.getVoltage(i)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getCurrent(i)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in Defines.powerSupplies:
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
self.view.pushButtonPowerOff.clicked.connect(self.powerOff)
|
||||
|
||||
def setup_ui(self):
|
||||
for i in Defines.powerSupplies:
|
||||
dac = getattr(dacIndex, f"V_POWER_{i}")
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
retval = self.det.getPower(dac)[0]
|
||||
spinBox.setValue(retval)
|
||||
if retval == 0:
|
||||
checkBox.setChecked(False)
|
||||
spinBox.setDisabled(True)
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
label = getattr(self.view, f"labelI{i}")
|
||||
label.setDisabled(True)
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.spinBoxVChip.setDisabled(True)
|
||||
|
||||
|
||||
def updateVoltageNames(self):
|
||||
retval = self.det.getPowerNames()
|
||||
getattr(self.view, "checkBoxVA").setText(retval[0])
|
||||
getattr(self.view, "checkBoxVB").setText(retval[1])
|
||||
getattr(self.view, "checkBoxVC").setText(retval[2])
|
||||
getattr(self.view, "checkBoxVD").setText(retval[3])
|
||||
getattr(self.view, "checkBoxVIO").setText(retval[4])
|
||||
|
||||
def getVoltage(self, i):
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
voltageIndex = getattr(dacIndex, f"V_POWER_{i}")
|
||||
label = getattr(self.view, f"labelV{i}")
|
||||
|
||||
spinBox.editingFinished.disconnect()
|
||||
checkBox.stateChanged.disconnect()
|
||||
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
retval = self.det.getPower(voltageIndex)[0]
|
||||
else:
|
||||
retval = self.det.getMeasuredPower(voltageIndex)[0]
|
||||
# spinBox.setValue(retval)
|
||||
if retval > 1:
|
||||
checkBox.setChecked(True)
|
||||
if checkBox.isChecked():
|
||||
spinBox.setEnabled(True)
|
||||
else:
|
||||
spinBox.setDisabled(True)
|
||||
label.setText(f'{str(retval)} mV')
|
||||
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getVChip()
|
||||
|
||||
# TODO: handle multiple events when pressing enter (twice)
|
||||
|
||||
def setVoltage(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
voltageIndex = getattr(dacIndex, f"V_POWER_{i}")
|
||||
spinBox.editingFinished.disconnect()
|
||||
|
||||
value = 0
|
||||
if checkBox.isChecked():
|
||||
value = spinBox.value()
|
||||
try:
|
||||
self.det.setPower(voltageIndex, value)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Voltage Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
|
||||
# TODO: (properly) disconnecting and connecting to handle multiple events (out of focus and pressing enter).
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
self.getVoltage(i)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getCurrent(i)
|
||||
|
||||
def getCurrent(self, i):
|
||||
label = getattr(self.view, f"labelI{i}")
|
||||
currentIndex = getattr(dacIndex, f"I_POWER_{i}")
|
||||
retval = self.det.getMeasuredCurrent(currentIndex)[0]
|
||||
label.setText(f'{str(retval)} mA')
|
||||
|
||||
def getVChip(self):
|
||||
self.view.spinBoxVChip.setValue(self.det.getPower(dacIndex.V_POWER_CHIP)[0])
|
||||
|
||||
def powerOff(self):
|
||||
for i in Defines.powerSupplies:
|
||||
# set all voltages to 0
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(False)
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
self.setVoltage(i)
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
commands = []
|
||||
for i in Defines.powerSupplies:
|
||||
enabled = getattr(self.view, f"checkBoxV{i}").isChecked()
|
||||
if enabled:
|
||||
value = getattr(self.view, f"spinBoxV{i}").value()
|
||||
commands.append(f"v_{i.lower()} {value}")
|
||||
else:
|
||||
commands.append(f"v_{i.lower()} 0")
|
||||
return commands
|
408
pyctbgui/pyctbgui/services/Signals.py
Normal file
408
pyctbgui/pyctbgui/services/Signals.py
Normal file
@ -0,0 +1,408 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import LegendItem
|
||||
|
||||
from pyctbgui.utils.bit_utils import bit_is_set, manipulate_bit
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
|
||||
class SignalsTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "signals.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.rx_dbitoffset = None
|
||||
self.rx_dbitreorder = None
|
||||
self.rx_dbitlist = None
|
||||
|
||||
def refresh(self):
|
||||
self.updateSignalNames()
|
||||
self.updateDigitalBitEnable()
|
||||
self.updateIOOut()
|
||||
self.getDBitOffset()
|
||||
self.getDBitReorder()
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.signals.count):
|
||||
getattr(self.view, f"checkBoxBIT{i}DB").stateChanged.connect(partial(self.setDigitalBitEnable, i))
|
||||
getattr(self.view, f"checkBoxBIT{i}Out").stateChanged.connect(partial(self.setIOOut, i))
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").stateChanged.connect(partial(self.setEnableBitPlot, i))
|
||||
getattr(self.view, f"pushButtonBIT{i}").clicked.connect(partial(self.selectBitColor, i))
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.connect(partial(self.setEnableBitPlotRange, 0,
|
||||
Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.connect(
|
||||
partial(self.setEnableBitPlotRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.connect(partial(self.setIOOutRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.connect(
|
||||
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
|
||||
|
||||
for i in range(Defines.signals.count):
|
||||
self.setDBitButtonColor(i, self.plotTab.getRandomColor())
|
||||
|
||||
self.initializeAllDigitalPlots()
|
||||
|
||||
self.legend = self.mainWindow.plotDigitalWaveform.getPlotItem().legend
|
||||
self.legend.clear()
|
||||
# subscribe to toggle legend
|
||||
self.plotTab.subscribeToggleLegend(self.updateLegend)
|
||||
|
||||
def getEnabledPlots(self):
|
||||
"""
|
||||
return plots that are shown (checkBoxTransceiver{i}Plot is checked)
|
||||
"""
|
||||
enabledPlots = []
|
||||
self.legend.clear()
|
||||
for i in range(Defines.signals.count):
|
||||
if getattr(self.view, f'checkBoxBIT{i}Plot').isChecked():
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
enabledPlots.append((self.mainWindow.digitalPlots[i], plotName))
|
||||
return enabledPlots
|
||||
|
||||
def updateLegend(self):
|
||||
"""
|
||||
update the legend for the signals waveform plot
|
||||
should be called after checking or unchecking plot checkbox
|
||||
"""
|
||||
if not self.mainWindow.showLegend:
|
||||
self.legend.clear()
|
||||
else:
|
||||
for plot, name in self.getEnabledPlots():
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitreorder, rx_dbitlist, isPlottedArray, romode,
|
||||
nADCEnabled):
|
||||
|
||||
#transform raw waveform data into a processed numpy array
|
||||
#@param data: raw waveform data
|
||||
|
||||
start_digital_data = 0
|
||||
if romode == 2:
|
||||
start_digital_data += nADCEnabled * 2 * aSamples
|
||||
digital_array = np.array(np.frombuffer(data, offset=start_digital_data, dtype=np.uint8))
|
||||
if rx_dbitreorder:
|
||||
samples_per_bit = np.empty((len(rx_dbitlist), dSamples), dtype=np.uint8) #stored per row all the corresponding signals of all samples
|
||||
nbitsPerDBit = dSamples
|
||||
if nbitsPerDBit % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
bit_index = 0
|
||||
for idx, i in enumerate(rx_dbitlist):
|
||||
# where numbits * numsamples is not a multiple of 8
|
||||
if bit_index % 8 != 0:
|
||||
bit_index += (8 - (bit_index % 8))
|
||||
if not isPlottedArray[i]:
|
||||
bit_index += nbitsPerDBit
|
||||
samples_per_bit[idx, :] = np.nan
|
||||
continue
|
||||
for iSample in range(dSamples):
|
||||
# all samples for digital bit together from slsReceiver
|
||||
index = int(bit_index / 8)
|
||||
iBit = bit_index % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
samples_per_bit[idx,iSample] = bit
|
||||
bit_index += 1
|
||||
return samples_per_bit
|
||||
else:
|
||||
nbitsPerSample = len(rx_dbitlist) if len(rx_dbitlist) % 8 == 0 else len(rx_dbitlist) + (8 - (len(rx_dbitlist) % 8))
|
||||
bits_per_sample = np.empty((dSamples, len(rx_dbitlist)), dtype=np.uint8) #store per row all selected bits of a sample
|
||||
for iSample in range(dSamples):
|
||||
bit_index = nbitsPerSample * iSample
|
||||
for idx, i in enumerate(rx_dbitlist):
|
||||
if not isPlottedArray[i]:
|
||||
bit_index += 1
|
||||
bits_per_sample[iSample, idx] = np.nan
|
||||
|
||||
index = int(bit_index/8)
|
||||
iBit = idx % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
bits_per_sample[iSample, idx] = bit
|
||||
bit_index += 1
|
||||
return bits_per_sample.T.copy()
|
||||
|
||||
|
||||
|
||||
def processWaveformData(self, data, aSamples, dSamples):
|
||||
|
||||
#view function
|
||||
#plots processed waveform data
|
||||
#data: raw waveform data
|
||||
#dsamples: digital samples
|
||||
#asamples: analog samples
|
||||
|
||||
self.refresh()
|
||||
|
||||
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,
|
||||
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]):
|
||||
continue
|
||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
waveforms[plotName] = waveform
|
||||
# TODO: left axis does not show 0 to 1, but keeps increasing
|
||||
if self.plotTab.view.radioButtonStripe.isChecked():
|
||||
self.mainWindow.digitalPlots[i].setY(irow * 2)
|
||||
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)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotDigitalWaveform, 3)
|
||||
self.mainWindow.digitalPlots = {}
|
||||
waveform = np.zeros(1000)
|
||||
for i in range(Defines.signals.count):
|
||||
pen = pg.mkPen(color=self.getDBitButtonColor(i), width=1)
|
||||
legendName = getattr(self.view, f"labelBIT{i}").text()
|
||||
self.mainWindow.digitalPlots[i] = self.mainWindow.plotDigitalWaveform.plot(waveform,
|
||||
pen=pen,
|
||||
name=legendName,
|
||||
stepMode="left")
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
self.mainWindow.plotDigitalImage = pg.ImageView()
|
||||
self.mainWindow.nDigitalRows = 0
|
||||
self.mainWindow.nDigitalCols = 0
|
||||
self.mainWindow.digital_frame = np.zeros((self.mainWindow.nDigitalRows, self.mainWindow.nDigitalCols))
|
||||
self.mainWindow.plotDigitalImage.setImage(self.mainWindow.digital_frame)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotDigitalImage, 4)
|
||||
|
||||
def updateSignalNames(self):
|
||||
for i, name in enumerate(self.det.getSignalNames()):
|
||||
getattr(self.view, f"labelBIT{i}").setText(name)
|
||||
|
||||
def getDigitalBitEnable(self, i, dbitList):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(i in list(dbitList))
|
||||
checkBox.stateChanged.connect(partial(self.setDigitalBitEnable, i))
|
||||
|
||||
def updateDigitalBitEnable(self):
|
||||
retval = self.det.rx_dbitlist
|
||||
self.rx_dbitlist = list(retval)
|
||||
self.mainWindow.nDBitEnabled = len(list(retval))
|
||||
for i in range(Defines.signals.count):
|
||||
self.getDigitalBitEnable(i, retval)
|
||||
self.getEnableBitPlot(i)
|
||||
self.getEnableBitColor(i)
|
||||
self.plotTab.addSelectedDigitalPlots(i)
|
||||
self.getDigitalBitEnableRange(retval)
|
||||
self.getEnableBitPlotRange()
|
||||
|
||||
def setDigitalBitEnable(self, i):
|
||||
bitList = self.det.rx_dbitlist
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
if checkBox.isChecked():
|
||||
bitList.append(i)
|
||||
else:
|
||||
bitList.remove(i)
|
||||
self.det.rx_dbitlist = bitList
|
||||
|
||||
self.updateDigitalBitEnable()
|
||||
|
||||
def getDigitalBitEnableRange(self, dbitList):
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31DB.setChecked(all(x in list(dbitList) for x in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63DB.setChecked(
|
||||
all(x in list(dbitList) for x in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setDigitalBitEnableRange(self, start_nr, end_nr):
|
||||
bitList = self.det.rx_dbitlist
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}DB")
|
||||
for i in range(start_nr, end_nr):
|
||||
if checkBox.isChecked():
|
||||
if i not in list(bitList):
|
||||
bitList.append(i)
|
||||
else:
|
||||
if i in list(bitList):
|
||||
bitList.remove(i)
|
||||
self.det.rx_dbitlist = bitList
|
||||
|
||||
self.updateDigitalBitEnable()
|
||||
|
||||
def getEnableBitPlot(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
checkBoxPlot.setEnabled(checkBox.isChecked())
|
||||
|
||||
def setEnableBitPlot(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
pushButton.setEnabled(checkBox.isChecked())
|
||||
|
||||
self.getEnableBitPlotRange()
|
||||
self.plotTab.addSelectedDigitalPlots(i)
|
||||
self.updateLegend()
|
||||
|
||||
def getEnableBitPlotRange(self):
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31Plot.setEnabled(
|
||||
all(getattr(self.view, f"checkBoxBIT{i}Plot").isEnabled() for i in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63Plot.setEnabled(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").isEnabled()
|
||||
for i in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31Plot.setChecked(
|
||||
all(getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63Plot.setChecked(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").isChecked()
|
||||
for i in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.connect(partial(self.setEnableBitPlotRange, 0,
|
||||
Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.connect(
|
||||
partial(self.setEnableBitPlotRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setEnableBitPlotRange(self, start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}Plot")
|
||||
enable = checkBox.isChecked()
|
||||
for i in range(start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
checkBox.setChecked(enable)
|
||||
self.plotTab.addAllSelectedDigitalPlots()
|
||||
|
||||
def getEnableBitColor(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
pushButton.setEnabled(checkBox.isEnabled() and checkBox.isChecked())
|
||||
|
||||
def selectBitColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
self.plotTab.showPalette(pushButton)
|
||||
pen = pg.mkPen(color=self.getDBitButtonColor(i), width=1)
|
||||
self.mainWindow.digitalPlots[i].setPen(pen)
|
||||
|
||||
def getDBitButtonColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
return self.plotTab.getActiveColor(pushButton)
|
||||
|
||||
def setDBitButtonColor(self, i, color):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
return self.plotTab.setActiveColor(pushButton, color)
|
||||
|
||||
def getIOOutReg(self):
|
||||
retval = self.det.patioctrl
|
||||
self.view.lineEditPatIOCtrl.editingFinished.disconnect()
|
||||
self.view.lineEditPatIOCtrl.setText("0x{:016x}".format(retval))
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
return retval
|
||||
|
||||
def setIOOutReg(self):
|
||||
self.view.lineEditPatIOCtrl.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.patioctrl = int(self.view.lineEditPatIOCtrl.text(), 16)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "IO Out Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
self.updateIOOut()
|
||||
|
||||
def updateCheckBoxIOOut(self, i, out):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Out")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(out, i))
|
||||
checkBox.stateChanged.connect(partial(self.setIOOut, i))
|
||||
|
||||
def updateIOOut(self):
|
||||
retval = self.getIOOutReg()
|
||||
for i in range(Defines.signals.count):
|
||||
self.updateCheckBoxIOOut(i, retval)
|
||||
self.getIOoutRange(retval)
|
||||
|
||||
def setIOOut(self, i):
|
||||
out = self.det.patioctrl
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Out")
|
||||
mask = manipulate_bit(checkBox.isChecked(), out, i)
|
||||
self.det.patioctrl = mask
|
||||
|
||||
retval = self.getIOOutReg()
|
||||
self.updateCheckBoxIOOut(i, retval)
|
||||
self.getIOoutRange(retval)
|
||||
|
||||
def getIOoutRange(self, out):
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31Out.setChecked((out & Defines.signals.BIT0_31_MASK) == Defines.signals.BIT0_31_MASK)
|
||||
self.view.checkBoxBIT32_63Out.setChecked((out
|
||||
& Defines.signals.BIT32_63_MASK) == Defines.signals.BIT32_63_MASK)
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.connect(partial(self.setIOOutRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.connect(
|
||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setIOOutRange(self, start_nr, end_nr):
|
||||
out = self.det.patioctrl
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}Out")
|
||||
mask = getattr(Defines.signals, f"BIT{start_nr}_{end_nr - 1}_MASK")
|
||||
if checkBox.isChecked():
|
||||
self.det.patioctrl = out | mask
|
||||
else:
|
||||
self.det.patioctrl = out & ~mask
|
||||
self.updateIOOut()
|
||||
|
||||
def getDBitOffset(self):
|
||||
self.view.spinBoxDBitOffset.editingFinished.disconnect()
|
||||
self.rx_dbitoffset = self.det.rx_dbitoffset
|
||||
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
|
47
pyctbgui/pyctbgui/services/SlowADCs.py
Normal file
47
pyctbgui/pyctbgui/services/SlowADCs.py
Normal file
@ -0,0 +1,47 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import uic, QtWidgets
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class SlowAdcTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "slowAdcs.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
|
||||
def setup_ui(self):
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.pushButtonTemp.setDisabled(True)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.slowAdc.count):
|
||||
getattr(self.view, f"pushButtonSlowAdc{i}").clicked.connect(partial(self.updateSlowAdc, i))
|
||||
self.view.pushButtonTemp.clicked.connect(self.updateTemperature)
|
||||
|
||||
def refresh(self):
|
||||
self.updateSlowAdcNames()
|
||||
for i in range(Defines.slowAdc.count):
|
||||
self.updateSlowAdc(i)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.updateTemperature()
|
||||
|
||||
def updateSlowAdcNames(self):
|
||||
for i, name in enumerate(self.mainWindow.det.getSlowADCNames()):
|
||||
getattr(self.view, f"labelSlowAdc{i}").setText(name)
|
||||
|
||||
def updateSlowAdc(self, i):
|
||||
slowADCIndex = getattr(dacIndex, f"SLOW_ADC{i}")
|
||||
label = getattr(self.view, f"labelSlowAdcValue{i}")
|
||||
slowadc = (self.det.getSlowADC(slowADCIndex))[0] / 1000
|
||||
label.setText(f'{slowadc:.2f} mV')
|
||||
|
||||
def updateTemperature(self):
|
||||
slowadc = self.det.getTemperature(dacIndex.SLOW_ADC_TEMP)
|
||||
self.view.labelTempValue.setText(f'{str(slowadc[0])} °C')
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user