Merge pull request #1219 from slsdetectorgroup/920/scikitbuild
Some checks failed
Native CMake Build / Configure and build using cmake (push) Failing after 2s

920/scikitbuild, typecaster and automated versioning
This commit is contained in:
2025-05-27 16:41:37 +02:00
committed by GitHub
63 changed files with 635 additions and 484 deletions

View File

@ -1,4 +1,4 @@
name: CMake name: Native CMake Build
on: [push, pull_request] on: [push, pull_request]
@ -14,7 +14,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Configure and build using cmake name: Configure and build using cmake
steps: 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 - uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
@ -27,12 +33,15 @@ jobs:
- name: Build - name: Build
# Build your program with the given configuration # 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 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 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
View 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
View 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

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.15)
project(slsDetectorPackage) project(slsDetectorPackage)
# Read VERSION file into project version # Read VERSION file into project version
@ -29,20 +29,40 @@ include(FetchContent)
option(SLS_FETCH_ZMQ_FROM_GITHUB "Fetch zmq from github" OFF) option(SLS_FETCH_ZMQ_FROM_GITHUB "Fetch zmq from github" OFF)
option(SLS_FETCH_PYBIND11_FROM_GITHUB "Fetch pybind11 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")
if(SLS_FETCH_ZMQ_FROM_GITHUB) if(SLS_FETCH_ZMQ_FROM_GITHUB)
# Opt in to pull down a zmq version from github instead of # Opt in to pull down a zmq version from github instead of
# using the bundled verison # using the bundled version
FetchContent_Declare( FetchContent_Declare(
libzmq libzmq
GIT_REPOSITORY https://github.com/zeromq/libzmq.git 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() else()
# Standard behaviour use libzmq included in this repo (libs/libzmq) # Standard behaviour use libzmq included in this repo (libs/libzmq)
FetchContent_Declare( FetchContent_Declare(
libzmq 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 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() endif()
@ -54,6 +74,11 @@ set(ENABLE_CPACK OFF CACHE BOOL "")
set(ENABLE_CLANG OFF CACHE BOOL "") set(ENABLE_CLANG OFF CACHE BOOL "")
set(ENABLE_CURVE OFF CACHE BOOL "") set(ENABLE_CURVE OFF CACHE BOOL "")
set(ENABLE_DRAFTS 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 # Using GetProperties and Populate to be able to exclude zmq
# from install (not possible with FetchContent_MakeAvailable(libzmq)) # from install (not possible with FetchContent_MakeAvailable(libzmq))
@ -191,7 +216,7 @@ endif()
# to control options for the libraries # to control options for the libraries
if(NOT TARGET slsProjectOptions) if(NOT TARGET slsProjectOptions)
add_library(slsProjectOptions INTERFACE) add_library(slsProjectOptions INTERFACE)
target_compile_features(slsProjectOptions INTERFACE cxx_std_11) target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
endif() endif()
if (NOT TARGET slsProjectWarnings) if (NOT TARGET slsProjectWarnings)
@ -329,9 +354,15 @@ if (SLS_USE_CTBGUI)
add_subdirectory(pyctbgui) add_subdirectory(pyctbgui)
endif(SLS_USE_CTBGUI) endif(SLS_USE_CTBGUI)
configure_file( .clang-tidy # Workaround for file note being copied to build directory
${CMAKE_BINARY_DIR}/.clang-tidy # 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) if (SLS_BUILD_EXAMPLES)
add_subdirectory(sample) add_subdirectory(sample)

View File

@ -1 +1 @@
9.1.1 9.2.0

View File

@ -1,11 +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
# copy VERSION into slsdet for installation
cp ../VERSION slsdet/VERSION
${PYTHON} setup.py install

View File

@ -1,14 +0,0 @@
python:
- 3.8
- 3.9
- 3.10
- 3.11
- 3.12
- 3.13
c_stdlib:
- sysroot # [linux]
c_stdlib_version: # [linux]
- 2.17 # [linux]

View File

@ -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/.

View File

@ -1,3 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
ctest -j2

View File

@ -8,7 +8,7 @@ if [ ! -d "install" ]; then
mkdir install mkdir install
fi fi
cd build cd build
cmake .. \ cmake .. -G Ninja \
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \ -DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
-DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_INSTALL_PREFIX=install \
-DSLS_USE_TEXTCLIENT=ON \ -DSLS_USE_TEXTCLIENT=ON \
@ -18,7 +18,7 @@ cmake .. \
-DSLS_USE_TESTS=ON \ -DSLS_USE_TESTS=ON \
-DSLS_USE_PYTHON=OFF \ -DSLS_USE_PYTHON=OFF \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DSLS_USE_HDF5=OFF\ -DSLS_USE_HDF5=OFF \
NCORES=$(getconf _NPROCESSORS_ONLN) NCORES=$(getconf _NPROCESSORS_ONLN)
echo "Building using: ${NCORES} cores" echo "Building using: ${NCORES} cores"

View File

@ -0,0 +1,13 @@
c_compiler:
- gcc # [linux]
c_stdlib:
- sysroot # [linux]
cxx_compiler:
- gxx # [linux]
c_stdlib_version: # [linux]
- 2.17 # [linux]

View File

@ -4,7 +4,6 @@
mkdir -p $PREFIX/lib mkdir -p $PREFIX/lib
mkdir -p $PREFIX/bin mkdir -p $PREFIX/bin
mkdir -p $PREFIX/include/sls mkdir -p $PREFIX/include/sls
# mkdir $PREFIX/include/slsDetectorPackage
#Shared and static libraries #Shared and static libraries
cp build/install/lib/* $PREFIX/lib/ cp build/install/lib/* $PREFIX/lib/
@ -15,8 +14,10 @@ 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_get $PREFIX/bin/.
cp build/install/bin/sls_detector_put $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_help $PREFIX/bin/.
cp build/install/bin/sls_detector $PREFIX/bin/.
cp build/install/bin/slsReceiver $PREFIX/bin/. cp build/install/bin/slsReceiver $PREFIX/bin/.
cp build/install/bin/slsMultiReceiver $PREFIX/bin/. cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
cp build/install/bin/slsFrameSynchronizer $PREFIX/bin/.
cp build/install/include/sls/* $PREFIX/include/sls cp build/install/include/sls/* $PREFIX/include/sls

View File

@ -1,10 +1,10 @@
source:
path: ../..
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
package: package:
name: sls_detector_software name: sls_detector_software
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }} version: {{ version }}
source:
path: ..
build: build:
number: 0 number: 0
@ -15,16 +15,17 @@ build:
requirements: requirements:
build: build:
- {{ compiler('c') }} - {{ compiler('c') }}
- {{stdlib('c')}} - {{ stdlib("c") }}
- {{compiler('cxx')}} - {{ compiler('cxx') }}
- cmake<=3.28 - git
- cmake
- ninja - ninja
- qt 5.* - qt 5.*
host: host:
- libstdcxx-ng - libstdcxx-ng
- libgcc-ng - libgcc-ng
- libgl-devel - libgl-devel # [linux]
- libtiff - libtiff
- zlib - zlib
- expat - expat
@ -41,44 +42,13 @@ outputs:
requirements: requirements:
build: build:
- {{ compiler('c') }} - {{ compiler('c') }}
- {{compiler('cxx')}} - {{ stdlib("c") }}
- libstdcxx-ng - {{ compiler('cxx') }}
- libgcc-ng
run: run:
- libstdcxx-ng - libstdcxx-ng
- libgcc-ng - libgcc-ng
- name: slsdet
script: build_pylib.sh
requirements:
build:
- python
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
- setuptools
- pybind11=2.13
host:
- python
- {{ pin_subpackage('slsdetlib', exact=True) }}
- setuptools
- pybind11=2.13
run:
- libstdcxx-ng
- libgcc-ng
- python
- numpy
- {{ pin_subpackage('slsdetlib', exact=True) }}
test:
imports:
- slsdet
- name: slsdetgui - name: slsdetgui
script: copy_gui.sh script: copy_gui.sh
@ -89,11 +59,10 @@ outputs:
- {{compiler('cxx')}} - {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }} - {{ pin_subpackage('slsdetlib', exact=True) }}
run: run:
- {{ pin_subpackage('slsdetlib', exact=True) }} - {{ pin_subpackage('slsdetlib', exact=True) }}
- qt 5.* - qt 5.*
- expat
- name: moenchzmq - name: moenchzmq
script: copy_moench.sh script: copy_moench.sh
@ -107,5 +76,3 @@ outputs:
run: run:
- {{ pin_subpackage('slsdetlib', exact=True) }} - {{ pin_subpackage('slsdetlib', exact=True) }}
- expat

View 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]

View 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

View 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)

33
pyproject.toml Normal file
View File

@ -0,0 +1,33 @@
[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.regex"
input = "VERSION"
regex = '^(?P<version>\d+(?:\.\d+)*(?:[\.\+\w]+)?)$'
result = "{version}"
[build-system]
requires = [ "scikit-build-core>=0.10", "pybind11", "numpy",]
build-backend = "scikit_build_core.build"
[project]
name = "slsdet"
dynamic = ["version"]
[tool.cibuildwheel]
before-all = "uname -a"
[tool.scikit-build.build]
verbose = true
[tool.scikit-build.cmake]
build-type = "Release"
[tool.scikit-build.install]
components = [ "python",]
[tool.scikit-build.cmake.define]
SLS_USE_RECEIVER = "OFF"
SLS_USE_RECEIVER_BINARIES = "OFF"
SLS_USE_TEXTCLIENT = "OFF"
SLS_BUILD_SHARED_LIBRARIES = "OFF"
SLS_USE_PYTHON = "ON"
SLS_INSTALL_PYTHONEXT = "ON"

View File

@ -20,7 +20,7 @@ target_link_libraries(_slsdet PUBLIC
set_target_properties(_slsdet PROPERTIES set_target_properties(_slsdet PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/slsdet
) )
#Copy Python code #Copy Python code
@ -75,10 +75,18 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
if(SLS_INSTALL_PYTHONEXT) if(SLS_INSTALL_PYTHONEXT)
install(TARGETS _slsdet install(TARGETS _slsdet
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/python LIBRARY DESTINATION slsdet
COMPONENT python
) )
install(
FILES ${PYTHON_FILES}
DESTINATION slsdet
COMPONENT python
)
install(
FILES ../VERSION
DESTINATION slsdet
COMPONENT python
)
install(FILES ${PYTHON_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
install(FILES ../VERSION DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
endif() endif()

View File

@ -1,77 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
"""
Setup file for slsdet
Build upon the pybind11 example found here: https://github.com/pybind/python_example
"""
import os
import sys
from setuptools import setup, find_packages
from pybind11.setup_helpers import Pybind11Extension, build_ext
def read_version():
try:
version_file = os.path.join(os.path.dirname(__file__), 'slsdet', 'VERSION')
with open(version_file, "r") as f:
return f.read().strip()
except:
raise RuntimeError("VERSION file not found in slsdet package from setup.py.")
__version__ = read_version()
def get_conda_path():
"""
Keep this a function if we need some fancier logic later
"""
print('Prefix: ', os.environ['CONDA_PREFIX'])
return os.environ['CONDA_PREFIX']
#TODO migrate to CMake build or fetch files from cmake?
ext_modules = [
Pybind11Extension(
'_slsdet',
['src/main.cpp',
'src/enums.cpp',
'src/current.cpp',
'src/detector.cpp',
'src/network.cpp',
'src/pattern.cpp',
'src/scan.cpp',
'src/duration.cpp',
'src/DurationWrapper.cpp',
'src/pedestal.cpp',
]
,
include_dirs=[
os.path.join(get_conda_path(), 'include'),
],
libraries=['SlsDetector', 'SlsSupport', 'SlsReceiver'],
library_dirs=[
os.path.join(get_conda_path(), 'lib'),
],
language='c++'
),
]
setup(
name='slsdet',
version=__version__,
author='Erik Frojdh',
author_email='erik.frojdh@psi.ch',
url='https://github.com/slsdetectorgroup/slsDetectorPackage',
description='Detector API for SLS Detector Group detectors',
long_description='',
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
package_data={
'slsdet': ['VERSION'],
},
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
zip_safe=False,
)

View File

@ -14,7 +14,7 @@ from .moench import Moench
from .pattern import Pattern, patternParameters from .pattern import Pattern, patternParameters
from .gaincaps import Mythen3GainCapsWrapper from .gaincaps import Mythen3GainCapsWrapper
import _slsdet from . import _slsdet
xy = _slsdet.xy xy = _slsdet.xy
defs = _slsdet.slsDetectorDefs defs = _slsdet.slsDetectorDefs
@ -41,3 +41,6 @@ def read_version():
__version__ = read_version() __version__ = read_version()

View File

@ -4,7 +4,7 @@ from .detector import Detector, freeze
from .utils import element_if_equal from .utils import element_if_equal
from .dacs import DetectorDacs, NamedDacs from .dacs import DetectorDacs, NamedDacs
from .powers import DetectorPowers, NamedPowers from .powers import DetectorPowers, NamedPowers
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -3,7 +3,7 @@
from .detector_property import DetectorProperty from .detector_property import DetectorProperty
from functools import partial from functools import partial
import numpy as np import numpy as np
import _slsdet from . import _slsdet
from .detector import freeze from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
class Dac(DetectorProperty): class Dac(DetectorProperty):

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
from _slsdet import CppDetectorApi from ._slsdet import CppDetectorApi
from _slsdet import slsDetectorDefs from ._slsdet import slsDetectorDefs
from _slsdet import IpAddr, MacAddr from ._slsdet import IpAddr, MacAddr
runStatus = slsDetectorDefs.runStatus runStatus = slsDetectorDefs.runStatus
timingMode = slsDetectorDefs.timingMode timingMode = slsDetectorDefs.timingMode
@ -15,7 +15,7 @@ defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from _slsdet import xy from ._slsdet import xy
from .gaincaps import Mythen3GainCapsWrapper from .gaincaps import Mythen3GainCapsWrapper
from . import utils as ut from . import utils as ut
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy

View File

@ -11,7 +11,7 @@ Created on Wed Dec 6 11:51:18 2017
from .detector import Detector from .detector import Detector
from .temperature import Temperature, DetectorTemperature from .temperature import Temperature, DetectorTemperature
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -15,8 +15,8 @@ if dt === detectorType.EIGER:
""" """
import _slsdet from . import _slsdet
for name, cls in _slsdet.slsDetectorDefs.__dict__.items(): for name, cls in _slsdet.slsDetectorDefs.__dict__.items():
if isinstance(cls, type): if isinstance(cls, type):
exec(f'{name} = {cls.__module__}.{cls.__qualname__}') exec(f'{name} = _slsdet.{cls.__qualname__}')

View File

@ -1,6 +1,6 @@
import _slsdet from . import _slsdet
gc = _slsdet.slsDetectorDefs.M3_GainCaps gc = _slsdet.slsDetectorDefs.M3_GainCaps

View File

@ -9,7 +9,7 @@ This file contains the specialization for the Moench detector
from .detector import Detector, freeze from .detector import Detector, freeze
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -9,7 +9,7 @@ This file contains the specialization for the Moench detector
from .detector import Detector, freeze from .detector import Detector, freeze
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
import _slsdet from . import _slsdet
from _slsdet import Pattern from ._slsdet import Pattern
class patternParameters(_slsdet.patternParameters): class patternParameters(_slsdet.patternParameters):

View File

@ -3,7 +3,7 @@
from .detector_property import DetectorProperty from .detector_property import DetectorProperty
from functools import partial from functools import partial
import numpy as np import numpy as np
import _slsdet from . import _slsdet
from .detector import freeze from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
class Power(DetectorProperty): class Power(DetectorProperty):

View File

@ -3,7 +3,7 @@
from .utils import element_if_equal from .utils import element_if_equal
from .enums import dacIndex from .enums import dacIndex
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
from _slsdet import slsDetectorDefs from ._slsdet import slsDetectorDefs
detectorType = slsDetectorDefs.detectorType detectorType = slsDetectorDefs.detectorType

View File

@ -6,7 +6,7 @@ but not directly used in controlling the detector
""" """
from collections import namedtuple from collections import namedtuple
import _slsdet #C++ lib from . import _slsdet #C++ lib
import functools import functools
import datetime as dt import datetime as dt
import pathlib import pathlib

View File

@ -1,3 +1,4 @@
#include <chrono>
#include "py_headers.h" #include "py_headers.h"
#include "DurationWrapper.h" #include "DurationWrapper.h"
@ -19,4 +20,25 @@ void init_duration(py::module &m) {
<< " count: " << self.count() << ")"; << " count: " << self.count() << ")";
return ss.str(); return ss.str();
}); });
m.def(
"test_return_DurationWrapper",
[]() {
DurationWrapper t(1.3);
return t;
},
R"(
Test function to return a DurationWrapper object. Ensures that the automatic conversion in typecaster.h works.
)");
m.def(
"test_duration_to_ns",
[](const std::chrono::nanoseconds t) {
//Duration wrapper is used to be able to convert from time in python to chrono::nanoseconds
//return count to have something to test
return t.count();
},
R"(
Test function convert DurationWrapper or number to chrono::ns. Ensures that the automatic conversion in typecaster.h works.
)"); // default value to test the default constructor
} }

View File

@ -54,11 +54,16 @@ template <> struct type_caster<std::chrono::nanoseconds> {
value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr()))); value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr())));
return true; return true;
} }
// If invoked with an int we assume it is nanoseconds and convert, same as in chrono.h
if (PyLong_Check(src.ptr())) {
value = duration_cast<nanoseconds>(duration<int64_t>(PyLong_AsLongLong(src.ptr())));
return true;
}
// Lastly if we were actually called with a DurationWrapper object we get // Lastly if we were actually called with a DurationWrapper object we get
// the number of nanoseconds and create a std::chrono::nanoseconds from it // the number of nanoseconds and create a std::chrono::nanoseconds from it
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper"); py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)){ if (py::isinstance(src, py_cls)){
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>(); sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count()); value = nanoseconds(cls->count());
@ -77,7 +82,7 @@ template <> struct type_caster<std::chrono::nanoseconds> {
* set the count from chrono::nanoseconds and return * set the count from chrono::nanoseconds and return
*/ */
static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) { static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) {
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper"); py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object* obj = new py::object; py::object* obj = new py::object;
*obj = py_cls(); *obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>(); sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();

View File

@ -0,0 +1,58 @@
import pytest
from slsdet import DurationWrapper
#import the compiled extension to use test functions for the automatic conversion
from slsdet import _slsdet
def test_default_construction_of_DurationWrapper():
"""Test default construction of DurationWrapper"""
t = DurationWrapper()
assert t.count() == 0
assert t.total_seconds() == 0
def test_construction_of_DurationWrapper():
"""Test construction of DurationWrapper with total_seconds"""
t = DurationWrapper(5)
assert t.count() == 5e9
assert t.total_seconds() == 5
def test_set_count_on_DurationWrapper():
"""Test set_count on DurationWrapper"""
t = DurationWrapper()
t.set_count(10)
assert t.count() == 10
assert t.total_seconds() == 10e-9
t.set_count(0)
assert t.count() == 0
assert t.total_seconds() == 0
def test_return_a_DurationWrapper_from_cpp():
"""Test returning a DurationWrapper from C++"""
t = _slsdet.test_return_DurationWrapper()
assert t.count() == 1.3e9
assert t.total_seconds() == 1.3
def test_call_a_cpp_function_with_a_duration_wrapper():
"""C++ functions can accept a DurationWrapper"""
t = DurationWrapper(5)
assert _slsdet.test_duration_to_ns(t) == 5e9
def test_call_a_cpp_function_converting_number_to_DurationWrapper():
"""int and float can be converted to std::chrono::nanoseconds"""
assert _slsdet.test_duration_to_ns(0) == 0
assert _slsdet.test_duration_to_ns(3) == 3e9
assert _slsdet.test_duration_to_ns(1.3) == 1.3e9
assert _slsdet.test_duration_to_ns(10e-9) == 10
def test_call_a_cpp_function_with_datetime_timedelta():
"""datetime.timedelta can be converted to std::chrono::nanoseconds"""
import datetime
t = datetime.timedelta(seconds=5)
assert _slsdet.test_duration_to_ns(t) == 5e9
t = datetime.timedelta(seconds=0)
assert _slsdet.test_duration_to_ns(t) == 0
t = datetime.timedelta(seconds=1.3)
assert _slsdet.test_duration_to_ns(t) == 1.3e9

26
slsDetectorServers/compileAllServers.sh Normal file → Executable file
View File

@ -1,8 +1,6 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
# empty branch = developer branch in updateAPIVersion.sh
branch=""
det_list=("ctbDetectorServer det_list=("ctbDetectorServer
gotthardDetectorServer gotthardDetectorServer
gotthard2DetectorServer gotthard2DetectorServer
@ -11,7 +9,12 @@ det_list=("ctbDetectorServer
moenchDetectorServer moenchDetectorServer
xilinx_ctbDetectorServer" xilinx_ctbDetectorServer"
) )
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'" usage="\nUsage: compileAllServers.sh [server|all(opt)] [update_api(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tupdate_api if true updates the api to version in VERSION file"
update_api=true
target=version
# arguments # arguments
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
@ -35,15 +38,12 @@ elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
declare -a det=("${1}") declare -a det=("${1}")
#echo "Compiling only $1" #echo "Compiling only $1"
fi fi
# branch
if [ $# -eq 2 ]; then if [ $# -eq 2 ]; then
# arg in list update_api=$2
if [[ $det_list == *$2* ]]; then if not $update_api ; then
echo -e "Invalid argument 2: $2. $usage" target=clean
return 1
fi fi
branch+=$2
#echo "with branch $branch"
fi fi
else else
echo -e "Too many arguments.$usage" echo -e "Too many arguments.$usage"
@ -54,6 +54,9 @@ declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
echo -e "list is ${det[@]}" echo -e "list is ${det[@]}"
if $update_api; then
echo "updating api to $(cat ../VERSION)"
fi
# compile each server # compile each server
idet=0 idet=0
for i in ${det[@]} for i in ${det[@]}
@ -63,14 +66,13 @@ do
echo -e "Compiling $dir [$file]" echo -e "Compiling $dir [$file]"
cd $dir cd $dir
make clean make clean
if make version API_BRANCH=$branch; then if make $target; then
deterror[$idet]="OK" deterror[$idet]="OK"
else else
deterror[$idet]="FAIL" deterror[$idet]="FAIL"
fi fi
mv bin/$dir bin/$file mv bin/$dir bin/$file
git add -f bin/$file git add -f bin/$file
cp bin/$file /tftpboot/
cd .. cd ..
echo -e "\n\n" echo -e "\n\n"
((++idet)) ((++idet))

View File

@ -1,87 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
# empty branch = developer branch in updateAPIVersion.sh
branch=""
det_list=("ctbDetectorServer"
"gotthardDetectorServer"
"gotthard2DetectorServer"
"jungfrauDetectorServer"
"mythen3DetectorServer"
"moenchDetectorServer"
"xilinx_ctbDetectorServer"
)
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
# arguments
if [ $# -eq 0 ]; then
# no argument, all servers
declare -a det=${det_list[@]}
echo "Compiling all servers"
elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
# 'all' servers
if [[ $1 == "all" ]]; then
declare -a det=${det_list[@]}
echo "Compiling all servers"
else
# only one server
# arg not in list
if [[ $det_list != *$1* ]]; then
echo -e "Invalid argument 1: $1. $usage"
return -1
fi
declare -a det=("${1}")
#echo "Compiling only $1"
fi
# branch
if [ $# -eq 2 ]; then
# arg in list
if [[ $det_list == *$2* ]]; then
echo -e "Invalid argument 2: $2. $usage"
return -1
fi
branch+=$2
#echo "with branch $branch"
fi
else
echo -e "Too many arguments.$usage"
return -1
fi
declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
echo -e "list is ${det[@]}"
# compile each server
idet=0
for i in ${det[@]}
do
dir=$i
file="${i}_developer"
echo -e "Compiling $dir [$file]"
cd $dir
make clean
if make API_BRANCH=$branch; then
deterror[$idet]="OK"
else
deterror[$idet]="FAIL"
fi
mv bin/$dir bin/$file
git add -f bin/$file
cp bin/$file /tftpboot/
cd ..
echo -e "\n\n"
((++idet))
done
echo -e "Results:"
idet=0
for i in ${det[@]}
do
printf "%s\t\t= %s\n" "$i" "${deterror[$idet]}"
((++idet))
done

23
slsDetectorServers/compileEigerServer.sh Normal file → Executable file
View File

@ -3,21 +3,31 @@
deterror="OK" deterror="OK"
dir="eigerDetectorServer" dir="eigerDetectorServer"
file="${dir}_developer" file="${dir}_developer"
branch=""
usage="\nUsage: compileAllServers.sh [update_api(opt)]. \n\t update_api if true updates the api to version in VERSION file"
update_api=true
target=version
# arguments # arguments
if [ $# -eq 1 ]; then if [ $# -eq 1 ]; then
branch+=$1 update_api=$1
#echo "with branch $branch" if not $update_api ; then
target=clean
fi
elif [ ! $# -eq 0 ]; then elif [ ! $# -eq 0 ]; then
echo -e "Only one optional argument allowed for branch." echo -e "Only one optional argument allowed for update_api."
return -1 return -1
fi fi
if $update_api; then
echo "updating api to $(cat ../VERSION)"
fi
echo -e "Compiling $dir [$file]" echo -e "Compiling $dir [$file]"
cd $dir cd $dir
make clean if make $target; then
if make version API_BRANCH=$branch; then
deterror="OK" deterror="OK"
else else
deterror="FAIL" deterror="FAIL"
@ -25,7 +35,6 @@ fi
mv bin/$dir bin/$file mv bin/$dir bin/$file
git add -f bin/$file git add -f bin/$file
cp bin/$file /tftpboot/
cd .. cd ..
echo -e "\n\n" echo -e "\n\n"
printf "Result:\t\t= %s\n" "${deterror}" printf "Result:\t\t= %s\n" "${deterror}"

View File

@ -25,11 +25,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APICTB version_name=APICTB
version_path=slsDetectorServers/ctbDetectorServer version_path=slsDetectorServers/ctbDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -25,11 +25,10 @@ version: clean versioning $(PROGS) #hv9m_blackfin_server
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIEIGER version_name=APIEIGER
version_path=slsDetectorServers/eigerDetectorServer version_path=slsDetectorServers/eigerDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIGOTTHARD2 version_name=APIGOTTHARD2
version_path=slsDetectorServers/gotthard2DetectorServer version_path=slsDetectorServers/gotthard2DetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -27,7 +27,7 @@ version_branch=$(API_BRANCH)
version_name=APIGOTTHARD version_name=APIGOTTHARD
version_path=slsDetectorServers/gotthardDetectorServer version_path=slsDetectorServers/gotthardDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIJUNGFRAU version_name=APIJUNGFRAU
version_path=slsDetectorServers/jungfrauDetectorServer version_path=slsDetectorServers/jungfrauDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIMOENCH version_name=APIMOENCH
version_path=slsDetectorServers/moenchDetectorServer version_path=slsDetectorServers/moenchDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -25,11 +25,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIMYTHEN3 version_name=APIMYTHEN3
version_path=slsDetectorServers/mythen3DetectorServer version_path=slsDetectorServers/mythen3DetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -36,11 +36,10 @@ version: clean versioning $(PROGS)
boot: $(OBJS) boot: $(OBJS)
version_branch=$(API_BRANCH)
version_name=APIXILINXCTB version_name=APIXILINXCTB
version_path=slsDetectorServers/xilinx_ctbDetectorServer version_path=slsDetectorServers/xilinx_ctbDetectorServer
versioning: versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;` cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS) $(PROGS): $(OBJS)

View File

@ -11,7 +11,7 @@ class Version {
private: private:
std::string version_; std::string version_;
std::string date_; std::string date_;
const std::string defaultBranch_ = "developer"; inline static const std::string defaultVersion_[] = {"developer", "0.0.0"};
public: public:
explicit Version(const std::string &s); explicit Version(const std::string &s);

View File

@ -8,6 +8,6 @@
#define APICTB "9.1.0 0x250204" #define APICTB "9.1.0 0x250204"
#define APIXILINXCTB "9.1.0 0x250204" #define APIXILINXCTB "9.1.0 0x250204"
#define APIJUNGFRAU "9.1.0 0x250318" #define APIJUNGFRAU "9.1.0 0x250318"
#define APILIB "9.1.0 0x250325" #define APILIB "9.2.0 0x250527"
#define APIMYTHEN3 "9.1.1 0x250409" #define APIMYTHEN3 "9.1.1 0x250409"
#define APIRECEIVER "9.1.1 0x250513" #define APIRECEIVER "9.1.1 0x250513"

View File

@ -21,7 +21,8 @@ Version::Version(const std::string &s) {
} }
bool Version::hasSemanticVersioning() const { bool Version::hasSemanticVersioning() const {
return version_ != defaultBranch_;
return (version_ != defaultVersion_[0]) && (version_ != defaultVersion_[1]);
} }
std::string Version::getVersion() const { return version_; } std::string Version::getVersion() const { return version_; }

View File

@ -14,6 +14,7 @@ target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Version.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-ZmqSocket.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-ZmqSocket.cpp
) )

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "catch.hpp"
#include "sls/Version.h"
namespace sls {
TEST_CASE("check if version is semantic", "[.version]") {
auto [version_string, has_semantic_version] =
GENERATE(std::make_tuple("developer 0x250512", false),
std::make_tuple("0.0.0 0x250512", false));
Version version(version_string);
CHECK(version.hasSemanticVersioning() == has_semantic_version);
}
} // namespace sls

View File

@ -20,6 +20,7 @@ from utils_for_test import (
cleanSharedmemory, cleanSharedmemory,
startProcessInBackground, startProcessInBackground,
startProcessInBackgroundWithLogFile, startProcessInBackgroundWithLogFile,
checkLogForErrors,
startDetectorVirtualServer, startDetectorVirtualServer,
loadConfig, loadConfig,
ParseArguments ParseArguments
@ -34,6 +35,9 @@ def startFrameSynchronizerPullSocket(name, fp):
fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt' fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt'
cmd = ['python', '-u', 'frameSynchronizerPullSocket.py'] cmd = ['python', '-u', 'frameSynchronizerPullSocket.py']
startProcessInBackgroundWithLogFile(cmd, fp, fname) startProcessInBackgroundWithLogFile(cmd, fp, fname)
time.sleep(1)
checkLogForErrors(fp, fname)
def startFrameSynchronizer(num_mods, fp): def startFrameSynchronizer(num_mods, fp):
@ -44,16 +48,14 @@ def startFrameSynchronizer(num_mods, fp):
time.sleep(1) time.sleep(1)
def acquire(fp): def acquire(fp, det):
Log(LogLevel.INFO, 'Acquiring') Log(LogLevel.INFO, 'Acquiring')
Log(LogLevel.INFO, 'Acquiring', fp) Log(LogLevel.INFO, 'Acquiring', fp)
d = Detector() det.acquire()
d.acquire()
def testFramesCaught(name, num_frames): def testFramesCaught(name, det, num_frames):
d = Detector() fnum = det.rx_framescaught[0]
fnum = d.rx_framescaught[0]
if fnum != num_frames: if fnum != num_frames:
raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}") raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}")
@ -61,7 +63,7 @@ def testFramesCaught(name, num_frames):
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp) Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp)
def testZmqHeadetTypeCount(name, num_mods, num_frames, fp): def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp):
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}") Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}")
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp) Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp)
@ -88,8 +90,7 @@ def testZmqHeadetTypeCount(name, num_mods, num_frames, fp):
continue continue
# test if file contents matches expected counts # test if file contents matches expected counts
d = Detector() num_ports_per_module = 1 if name == "gotthard2" else det.numinterfaces
num_ports_per_module = 1 if name == "gotthard2" else d.numinterfaces
total_num_frame_parts = num_ports_per_module * num_mods * num_frames total_num_frame_parts = num_ports_per_module * num_mods * num_frames
for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]: for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]:
if htype_counts[htype] != expected_count: if htype_counts[htype] != expected_count:
@ -111,10 +112,10 @@ def startTestsForAll(args, fp):
startDetectorVirtualServer(server, args.num_mods, fp) startDetectorVirtualServer(server, args.num_mods, fp)
startFrameSynchronizerPullSocket(server, fp) startFrameSynchronizerPullSocket(server, fp)
startFrameSynchronizer(args.num_mods, fp) startFrameSynchronizer(args.num_mods, fp)
loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames) d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
acquire(fp) acquire(fp, d)
testFramesCaught(server, args.num_frames) testFramesCaught(server, d, args.num_frames)
testZmqHeadetTypeCount(server, args.num_mods, args.num_frames, fp) testZmqHeadetTypeCount(server, d, args.num_mods, args.num_frames, fp)
Log(LogLevel.INFO, '\n') Log(LogLevel.INFO, '\n')
except Exception as e: except Exception as e:
raise RuntimeException(f'Synchronizer Tests failed') from e raise RuntimeException(f'Synchronizer Tests failed') from e

View File

@ -104,7 +104,7 @@ def startProcessInBackground(cmd, fp):
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name): def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name: str):
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name) Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name)
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp) Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp)
try: try:
@ -114,6 +114,22 @@ def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name):
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
def checkLogForErrors(fp, log_file_path: str):
try:
with open(log_file_path, 'r') as log_file:
for line in log_file:
if 'Error' in line:
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}")
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}", fp)
raise RuntimeException("Error found in log file")
except FileNotFoundError:
print(f"Log file not found: {log_file_path}")
raise
except Exception as e:
print(f"Exception while reading log: {e}")
raise
def runProcessWithLogFile(name, cmd, fp, log_file_name): def runProcessWithLogFile(name, cmd, fp, log_file_name):
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name) Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name)
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp) Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp)
@ -142,7 +158,7 @@ def startDetectorVirtualServer(name :str, num_mods, fp):
cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)] cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)]
if name == 'gotthard': if name == 'gotthard':
cmd += ['-m', '1'] cmd += ['-m', '1']
startProcessInBackground(cmd, fp) startProcessInBackgroundWithLogFile(cmd, fp, "/tmp/virtual_det_" + name + str(i) + ".txt")
match name: match name:
case 'jungfrau': case 'jungfrau':
time.sleep(7) time.sleep(7)
@ -207,6 +223,8 @@ def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1)
except Exception as e: except Exception as e:
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
return d
def ParseArguments(description, default_num_mods=1): def ParseArguments(description, default_num_mods=1):
parser = argparse.ArgumentParser(description) parser = argparse.ArgumentParser(description)

81
updateAPIVersion.py Normal file
View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2025 Contributors to the SLS Detector Package
"""
Script to update API VERSION file based on the version in VERSION file.
"""
import argparse
import sys
import os
import re
import time
from datetime import datetime
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
API_FILE = SCRIPT_DIR + "/slsSupportLib/include/sls/versionAPI.h"
VERSION_FILE = SCRIPT_DIR + "/VERSION"
parser = argparse.ArgumentParser(description = 'updates API version')
parser.add_argument('api_module_name', choices=["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"], help = 'module name to change api version options are: ["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"]')
parser.add_argument('api_dir', help = 'Relative or absolute path to the module code')
def update_api_file(new_api : str, api_module_name : str, api_file_name : str):
regex_pattern = re.compile(rf'#define\s+{api_module_name}\s+')
with open(api_file_name, "r") as api_file:
lines = api_file.readlines()
with open(api_file_name, "w") as api_file:
for line in lines:
if regex_pattern.match(line):
api_file.write(f'#define {api_module_name} "{new_api}"\n')
else:
api_file.write(line)
def get_latest_modification_date(directory : str):
latest_time = 0
latest_date = None
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".o"):
continue
full_path = os.path.join(root, file)
try:
mtime = os.path.getmtime(full_path)
if mtime > latest_time:
latest_time = mtime
except FileNotFoundError:
continue
latest_date = datetime.fromtimestamp(latest_time).strftime("%y%m%d")
return latest_date
def update_api_version(api_module_name : str, api_dir : str):
api_date = get_latest_modification_date(api_dir)
api_date = "0x"+str(api_date)
with open(VERSION_FILE, "r") as version_file:
api_version = version_file.read().strip()
api_version = api_version + " " + api_date #not sure if we should give an argument option version_branch
update_api_file(api_version, api_module_name, API_FILE)
print(f"updated {api_module_name} api version to: {api_version}")
if __name__ == "__main__":
args = parser.parse_args()
api_dir = SCRIPT_DIR + "/" + args.api_dir
update_api_version(args.api_module_name, api_dir)

View File

@ -1,65 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
usage="\nUsage: updateAPIVersion.sh [API_NAME] [API_DIR] [API_BRANCH(opt)]."
if [ $# -lt 2 ]; then
echo -e "Requires atleast 2 arguments. $usage"
return [-1]
fi
API_NAME=$1
PACKAGE_DIR=$PWD
API_DIR=$PACKAGE_DIR/$2
API_FILE=$PACKAGE_DIR/slsSupportLib/include/sls/versionAPI.h
CURR_DIR=$PWD
if [ ! -d "$API_DIR" ]; then
echo "[API_DIR] does not exist. $usage"
return [-1]
fi
#go to directory
cd $API_DIR
#deleting line from file
NUM=$(sed -n '/'$API_NAME' /=' $API_FILE)
#echo $NUM
if [ "$NUM" -gt 0 ]; then
sed -i ${NUM}d $API_FILE
fi
#find new API date
API_DATE="find . -printf \"%T@ %CY-%Cm-%Cd\n\"| sort -nr | cut -d' ' -f2- | egrep -v '(\.)o' | head -n 1"
API_DATE=`eval $API_DATE`
API_DATE=$(sed "s/-//g" <<< $API_DATE | awk '{print $1;}' )
#extracting only date
API_DATE=${API_DATE:2:6}
#prefix of 0x
API_DATE=${API_DATE/#/0x}
echo "date="$API_DATE
# API_VAL concatenates branch and date
API_VAL=""
# API branch is defined (3rd argument)
if [ $# -eq 3 ]; then
API_BRANCH=$3
echo "branch="$API_BRANCH
API_VAL+="\"$API_BRANCH $API_DATE\""
else
# API branch not defined (default is developer)
echo "branch=developer"
API_VAL+="\"developer $API_DATE\""
fi
#copy it to versionAPI.h
echo "#define "$API_NAME $API_VAL >> $API_FILE
#go back to original directory
cd $CURR_DIR

34
updateClientAPIVersion.py Normal file
View File

@ -0,0 +1,34 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2025 Contributors to the SLS Detector Package
"""
Script to update API VERSION for slsReceiverSoftware or slsDetectorSoftware
"""
import argparse
import os
from updateAPIVersion import update_api_version
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
parser = argparse.ArgumentParser(description = 'updates API version')
parser.add_argument('module_name', nargs="?", choices=["slsDetectorSoftware", "slsReceiverSoftware", "all"], default="all", help = 'module name to change api version options are: ["slsDetectorSoftware", "slsReceiverSoftware, "all"]')
if __name__ == "__main__":
args = parser.parse_args()
if args.module_name == "all":
client_names = ["APILIB", "APIRECEIVER"]
client_directories = [SCRIPT_DIR+"/slsDetectorSoftware", SCRIPT_DIR+"/slsReceiverSoftware"]
elif args.module_name == "slsDetectorSoftware":
client_names = ["APILIB"]
client_directories = [SCRIPT_DIR+"/slsDetectorSoftware"]
else:
client_names = ["APIRECEIVER"]
client_directories = [SCRIPT_DIR+"/slsReceiverSoftware"]
for client_name, client_directory in zip(client_names, client_directories):
update_api_version(client_name, client_directory)

View File

@ -1,59 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
branch=""
client_list=("slsDetectorSoftware" "slsReceiverSoftware")
usage="\nUsage: updateClientAPI.sh [all|slsDetectorSoftware|slsReceiverSoftware] [branch]. \n\tNo arguments means all with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
# arguments
if [ $# -eq 0 ]; then
declare -a client=${client_list[@]}
echo "API Versioning all"
elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
# 'all' client
if [[ $1 == "all" ]]; then
declare -a client=${client_list[@]}
echo "API Versioning all"
else
# only one server
if [[ $client_list != *$1* ]]; then
echo -e "Invalid argument 1: $1. $usage"
return -1
fi
declare -a client=("${1}")
#echo "Versioning only $1"
fi
if [ $# -eq 2 ]; then
if [[ $client_list == *$2* ]]; then
echo -e "Invalid argument 2: $2. $usage"
return -1
fi
branch+=$2
#echo "with branch $branch"
fi
else
echo -e "Too many arguments.$usage"
return -1
fi
#echo "list is: ${client[@]}"
# versioning each client
for i in ${client[@]}
do
dir=$i
case $dir in
slsDetectorSoftware)
declare -a name=APILIB
;;
slsReceiverSoftware)
declare -a name=APIRECEIVER
;;
*)
echo -n "unknown client argument $i"
return -1
;;
esac
echo -e "Versioning $dir [$name]"
./updateAPIVersion.sh $name $dir $branch
done

View File

@ -5,7 +5,12 @@ Script to update VERSION file with semantic versioning if provided as an argumen
""" """
import sys import sys
import re import os
from packaging.version import Version, InvalidVersion
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def get_version(): def get_version():
@ -15,20 +20,21 @@ def get_version():
version = sys.argv[1] version = sys.argv[1]
# Validate that the version argument matches semantic versioning format (X.Y.Z) try:
if not re.match(r'^\d+\.\d+\.\d+$', version): v = Version(version) # normalizcheck if version follows PEP 440 specification
print("Error: Version argument must be in semantic versioning format (X.Y.Z)") #replace -
return version.replace("-", ".")
except InvalidVersion as e:
print(f"Invalid version {version}. Version format must follow semantic versioning format of python PEP 440 version identification specification.")
sys.exit(1) sys.exit(1)
return version
def write_version_to_file(version): def write_version_to_file(version):
with open("VERSION", "w") as version_file: version_file_path = os.path.join(SCRIPT_DIR, "VERSION")
with open(version_file_path, "w") as version_file:
version_file.write(version) version_file.write(version)
print(f"Version {version} written to VERSION file.") print(f"Version {version} written to VERSION file.")
# Main script # Main script
if __name__ == "__main__": if __name__ == "__main__":