From 5322b3ebb4c65e1ddfebc5ea4fab70fe399812c1 Mon Sep 17 00:00:00 2001 From: AliceMazzoleni99 Date: Thu, 1 Oct 2026 12:15:50 +0200 Subject: [PATCH 01/12] Fix/matterhorn compilation on clang (#1584) * dont use this * moved explicit instantiation after definiting templated functions --- .../matterhornServer/src/BaseMatterhornServerImpl.hpp | 4 +++- .../slsDetectorServer_cpp/src/DetectorServerImpl.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/slsDetectorServers/matterhornServer/src/BaseMatterhornServerImpl.hpp b/slsDetectorServers/matterhornServer/src/BaseMatterhornServerImpl.hpp index 9d0e45d22..8131d7658 100644 --- a/slsDetectorServers/matterhornServer/src/BaseMatterhornServerImpl.hpp +++ b/slsDetectorServers/matterhornServer/src/BaseMatterhornServerImpl.hpp @@ -21,6 +21,8 @@ class BaseMatterhornServerImpl : public DetectorServerImpl< is_stop_server::value> { public: + using BaseServerImpl = + DetectorServerImpl::value>; BaseMatterhornServerImpl(); ~BaseMatterhornServerImpl() = default; @@ -93,7 +95,7 @@ void BaseMatterhornServerImpl::setupDetector() { // TODO: extend try { // stop server does not talk to the board - if constexpr (!this->stop_server) { + if constexpr (!BaseServerImpl::stop_server) { set_num_frames(1); set_num_triggers(1); set_counter_mask(0xF); // enable counter all counters by default diff --git a/slsDetectorServers/slsDetectorServer_cpp/src/DetectorServerImpl.cpp b/slsDetectorServers/slsDetectorServer_cpp/src/DetectorServerImpl.cpp index 959fa2080..abc47935f 100644 --- a/slsDetectorServers/slsDetectorServer_cpp/src/DetectorServerImpl.cpp +++ b/slsDetectorServers/slsDetectorServer_cpp/src/DetectorServerImpl.cpp @@ -5,9 +5,6 @@ namespace sls { -template class DetectorServerImpl; // forward declare -template class DetectorServerImpl; // forward declare - template DetectorServerImpl::DetectorServerImpl() { udpDetails[0].srcport = DEFAULT_UDP_SRC_PORTNO; @@ -114,4 +111,9 @@ DetectorServerImpl::get_detector_setup_status() const { return detectorSetupStatus; } +template class DetectorServerImpl; // explicit instantiation for stop + // server +template class DetectorServerImpl; // explicit instantiation for control + // server + } // namespace sls \ No newline at end of file From d4e4ff89ccbd8aa480b578de17004d95ca89d58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Thu, 1 Oct 2026 18:51:49 +0200 Subject: [PATCH 02/12] Generating of python bindings with libclang 17-23 (#1581) * update parsing to work with newer libclang * bumped clang-format to v17 for python bindings * removed support for clang 12 added 17-19 --- python/scripts/generate_functions.py | 116 ++++- python/src/detector.cpp | 633 +++++++++++++-------------- 2 files changed, 409 insertions(+), 340 deletions(-) diff --git a/python/scripts/generate_functions.py b/python/scripts/generate_functions.py index ab57f740f..b312f9b92 100644 --- a/python/scripts/generate_functions.py +++ b/python/scripts/generate_functions.py @@ -7,6 +7,9 @@ to be installed. When the Detector API is updated this file should be run manually. + +Tested with libclang 17-23. The output is formatted with +clang-format 17. """ import os from clang import cindex @@ -38,11 +41,11 @@ def find_libclang(): """Find libclang in the current Conda/Mamba environment.""" conda_prefix = os.environ.get("CONDA_PREFIX") if conda_prefix: - lib_dir = os.path.join(conda_prefix, "lib") - # Look for libclang*.so files - for f in os.listdir(lib_dir): - if f.startswith("libclang") and f.endswith(".so"): - return os.path.join(lib_dir, f) + # Match the name exactly, lib also holds libclang-cpp and libclang_rt.* + for name in ("libclang.so", "libclang.dylib"): + path = os.path.join(conda_prefix, "lib", name) + if os.path.exists(path): + return path # fallback: system-wide search path = ctypes.util.find_library("clang") @@ -52,7 +55,7 @@ def find_libclang(): raise FileNotFoundError("libclang not found in CONDA_PREFIX or system paths.") -def check_libclang_version(required="12"): +def check_libclang_version(supported): # Use already-loaded libclang, or let cindex resolve it lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang")) @@ -63,11 +66,13 @@ def check_libclang_version(required="12"): # Parse and check version match = re.search(r"version\s+(\d+)", version_str) - if not match or match.group(1) != required: - msg = red(f"libclang version {match.group(1) if match else '?'} found, but version {required} required. Bye!") + version = int(match.group(1)) if match else None + if version not in supported: + versions = ", ".join(str(v) for v in supported) + msg = red(f"libclang version {version or '?'} found, but one of {versions} required. Bye!") print(msg) sys.exit(1) - msg = green(f"Found libclang version {required}") + msg = green(f"Found libclang version {version}") print(msg) @@ -95,8 +100,25 @@ def check_for_compile_commands_json(path): print(msg) +def check_for_parse_errors(tu): + # Types that libclang fails to parse silently turn into int. Errors without + # a location come from compiler flags that clang does not know and are harmless + errors = [ + d + for d in tu.diagnostics + if d.severity >= cindex.Diagnostic.Error and d.location.file + ] + if errors: + print(red("FAILED")) + for d in errors: + print(red(f"{d.location.file}:{d.location.line}: {d.spelling}")) + print(red("Errors while parsing, the generated types can't be trusted. Bye!")) + sys.exit(1) + + default_build_path = "/home/l_frojdh/sls/build/" fpath = "../../slsDetectorSoftware/src/Detector.cpp" +supported_libclang_versions = (17, 18, 19, 20, 21, 22, 23) m = [] @@ -118,13 +140,64 @@ def get_arguments(node): return args +def qualified_name(decl): + """Name of a declaration including its enclosing scopes, e.g. sls::Positions""" + parts = [] + while decl is not None and decl.kind != cindex.CursorKind.TRANSLATION_UNIT: + if decl.spelling: + parts.append(decl.spelling) + decl = decl.semantic_parent + return "::".join(reversed(parts)) + + +def referenced_types(node): + """Declarations of the types named in the return type of a method or in a parameter""" + for child in node.get_children(): + if child.kind == cindex.CursorKind.TYPE_REF: + yield child.referenced + elif node.kind == child.kind == cindex.CursorKind.PARM_DECL: + # parameters of a function pointer + yield from referenced_types(child) + + +def type_spelling(node, type): + """ + Spelling of the return type of a method or the type of a parameter. + + libclang gives a type name as it is written in the source (Positions). + The generated file is outside the sls namespace, so we look up the + declarations and add the scope ourselves (sls::Positions). Names already + written with a scope (defs::xy) are left as they are. + """ + spelling = type.spelling + for decl in referenced_types(node): + unqualified = rf"(?()); CppDetectorApi.def("loadConfig", - (void (Detector::*)(const std::string &)) & + (void(Detector::*)(const std::string &)) & Detector::loadConfig, py::arg()); CppDetectorApi.def("loadParameters", - (void (Detector::*)(const std::string &)) & + (void(Detector::*)(const std::string &)) & Detector::loadParameters, py::arg()); CppDetectorApi.def("loadParameters", - (void (Detector::*)(const std::vector &)) & + (void(Detector::*)(const std::vector &)) & Detector::loadParameters, py::arg()); CppDetectorApi.def( @@ -53,15 +53,15 @@ void init_det(py::module &m) { Detector::getHostname, py::arg() = Positions{}); CppDetectorApi.def("setHostname", - (void (Detector::*)(const std::vector &)) & + (void(Detector::*)(const std::vector &)) & Detector::setHostname, py::arg()); CppDetectorApi.def("setVirtualDetectorServers", - (void (Detector::*)(int, uint16_t)) & + (void(Detector::*)(int, uint16_t)) & Detector::setVirtualDetectorServers, py::arg(), py::arg()); CppDetectorApi.def("getShmId", - (int (Detector::*)() const) & Detector::getShmId); + (int(Detector::*)() const) & Detector::getShmId); CppDetectorApi.def("getPackageVersion", (std::string(Detector::*)() const) & Detector::getPackageVersion); CppDetectorApi.def("getClientVersion", (std::string(Detector::*)() const) & @@ -108,8 +108,8 @@ void init_det(py::module &m) { (Result(Detector::*)(sls::Positions) const) & Detector::getDetectorType, py::arg() = Positions{}); - CppDetectorApi.def("size", (int (Detector::*)() const) & Detector::size); - CppDetectorApi.def("empty", (bool (Detector::*)() const) & Detector::empty); + CppDetectorApi.def("size", (int(Detector::*)() const) & Detector::size); + CppDetectorApi.def("empty", (bool(Detector::*)() const) & Detector::empty); CppDetectorApi.def("getModuleGeometry", (defs::xy(Detector::*)() const) & Detector::getModuleGeometry); CppDetectorApi.def("getModuleSize", @@ -126,7 +126,7 @@ void init_det(py::module &m) { CppDetectorApi.def("getDetectorSize", (defs::xy(Detector::*)() const) & Detector::getDetectorSize); CppDetectorApi.def("setDetectorSize", - (void (Detector::*)(const defs::xy)) & + (void(Detector::*)(const defs::xy)) & Detector::setDetectorSize, py::arg()); CppDetectorApi.def("getSettingsList", (std::vector( @@ -139,7 +139,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setSettings", - (void (Detector::*)(defs::detectorSettings, sls::Positions)) & + (void(Detector::*)(defs::detectorSettings, sls::Positions)) & Detector::setSettings, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getThresholdEnergy", @@ -151,16 +151,16 @@ void init_det(py::module &m) { (Result>(Detector::*)(sls::Positions) const) & Detector::getAllThresholdEnergy, py::arg() = Positions{}); - CppDetectorApi.def("setThresholdEnergy", - (void (Detector::*)(int, defs::detectorSettings, bool, - sls::Positions)) & - Detector::setThresholdEnergy, - py::arg(), py::arg() = defs::STANDARD, py::arg() = true, - py::arg() = Positions{}); CppDetectorApi.def( "setThresholdEnergy", - (void (Detector::*)(std::array, defs::detectorSettings, bool, - sls::Positions)) & + (void(Detector::*)(int, defs::detectorSettings, bool, sls::Positions)) & + Detector::setThresholdEnergy, + py::arg(), py::arg() = defs::STANDARD, py::arg() = true, + py::arg() = Positions{}); + CppDetectorApi.def( + "setThresholdEnergy", + (void(Detector::*)(std::array, defs::detectorSettings, bool, + sls::Positions)) & Detector::setThresholdEnergy, py::arg(), py::arg() = defs::STANDARD, py::arg() = true, py::arg() = Positions{}); @@ -171,17 +171,17 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setSettingsPath", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setSettingsPath, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "loadTrimbits", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::loadTrimbits, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "saveTrimbits", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::saveTrimbits, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getAllTrimbits", @@ -189,7 +189,7 @@ void init_det(py::module &m) { Detector::getAllTrimbits, py::arg() = Positions{}); CppDetectorApi.def("setAllTrimbits", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setAllTrimbits, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -198,14 +198,14 @@ void init_det(py::module &m) { Detector::getTrimEnergies, py::arg() = Positions{}); CppDetectorApi.def("setTrimEnergies", - (void (Detector::*)(std::vector, sls::Positions)) & + (void(Detector::*)(std::vector, sls::Positions)) & Detector::setTrimEnergies, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getGapPixelsinCallback", - (bool (Detector::*)() const) & + (bool(Detector::*)() const) & Detector::getGapPixelsinCallback); CppDetectorApi.def("setGapPixelsinCallback", - (void (Detector::*)(const bool)) & + (void(Detector::*)(const bool)) & Detector::setGapPixelsinCallback, py::arg()); CppDetectorApi.def("getFlipRows", @@ -213,7 +213,7 @@ void init_det(py::module &m) { Detector::getFlipRows, py::arg() = Positions{}); CppDetectorApi.def("setFlipRows", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setFlipRows, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getMaster", @@ -221,23 +221,23 @@ void init_det(py::module &m) { Detector::getMaster, py::arg() = Positions{}); CppDetectorApi.def("setMaster", - (void (Detector::*)(bool, int)) & Detector::setMaster, + (void(Detector::*)(bool, int)) & Detector::setMaster, py::arg(), py::arg()); CppDetectorApi.def("getSynchronization", (Result(Detector::*)(sls::Positions) const) & Detector::getSynchronization, py::arg() = Positions{}); - CppDetectorApi.def( - "setSynchronization", - (void (Detector::*)(bool)) & Detector::setSynchronization, py::arg()); + CppDetectorApi.def("setSynchronization", + (void(Detector::*)(bool)) & Detector::setSynchronization, + py::arg()); CppDetectorApi.def( "getBadChannels", - (void (Detector::*)(const std::string &, sls::Positions) const) & + (void(Detector::*)(const std::string &, sls::Positions) const) & Detector::getBadChannels, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setBadChannels", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setBadChannels, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -247,12 +247,12 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setBadChannels", - (void (Detector::*)(const std::vector, sls::Positions)) & + (void(Detector::*)(const std::vector, sls::Positions)) & Detector::setBadChannels, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setBadChannels", - (void (Detector::*)(const std::vector>)) & + (void(Detector::*)(const std::vector>)) & Detector::setBadChannels, py::arg()); CppDetectorApi.def("getRow", @@ -260,7 +260,7 @@ void init_det(py::module &m) { Detector::getRow, py::arg() = Positions{}); CppDetectorApi.def("setRow", - (void (Detector::*)(const int, sls::Positions)) & + (void(Detector::*)(const int, sls::Positions)) & Detector::setRow, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getColumn", @@ -268,7 +268,7 @@ void init_det(py::module &m) { Detector::getColumn, py::arg() = Positions{}); CppDetectorApi.def("setColumn", - (void (Detector::*)(const int, sls::Positions)) & + (void(Detector::*)(const int, sls::Positions)) & Detector::setColumn, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("isVirtualDetectorServer", @@ -277,13 +277,13 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "registerAcquisitionFinishedCallback", - (void (Detector::*)(void (*)(double, int, void *), void *)) & + (void(Detector::*)(void (*)(double, int, void *), void *)) & Detector::registerAcquisitionFinishedCallback, py::arg(), py::arg()); CppDetectorApi.def("registerDataCallback", - (void (Detector::*)(void (*)(sls::detectorData *, - uint64_t, uint32_t, void *), - void *)) & + (void(Detector::*)(void (*)(sls::detectorData *, + uint64_t, uint32_t, void *), + void *)) & Detector::registerDataCallback, py::arg(), py::arg()); CppDetectorApi.def("getNumberOfFrames", @@ -292,13 +292,13 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setNumberOfFrames", - (void (Detector::*)(int64_t)) & Detector::setNumberOfFrames, py::arg()); + (void(Detector::*)(int64_t)) & Detector::setNumberOfFrames, py::arg()); CppDetectorApi.def("getNumberOfTriggers", (Result(Detector::*)(sls::Positions) const) & Detector::getNumberOfTriggers, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfTriggers", - (void (Detector::*)(int64_t)) & + (void(Detector::*)(int64_t)) & Detector::setNumberOfTriggers, py::arg()); CppDetectorApi.def("getExptime", @@ -306,7 +306,7 @@ void init_det(py::module &m) { Detector::getExptime, py::arg() = Positions{}); CppDetectorApi.def("setExptime", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setExptime, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPeriod", @@ -314,7 +314,7 @@ void init_det(py::module &m) { Detector::getPeriod, py::arg() = Positions{}); CppDetectorApi.def("setPeriod", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setPeriod, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDelayAfterTrigger", @@ -322,7 +322,7 @@ void init_det(py::module &m) { Detector::getDelayAfterTrigger, py::arg() = Positions{}); CppDetectorApi.def("setDelayAfterTrigger", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setDelayAfterTrigger, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfFramesLeft", @@ -346,7 +346,7 @@ void init_det(py::module &m) { Detector::getDynamicRange, py::arg() = Positions{}); CppDetectorApi.def("setDynamicRange", - (void (Detector::*)(int)) & Detector::setDynamicRange, + (void(Detector::*)(int)) & Detector::setDynamicRange, py::arg()); CppDetectorApi.def("getDynamicRangeList", (std::vector(Detector::*)() const) & @@ -357,7 +357,7 @@ void init_det(py::module &m) { Detector::getTimingMode, py::arg() = Positions{}); CppDetectorApi.def("setTimingMode", - (void (Detector::*)(defs::timingMode, sls::Positions)) & + (void(Detector::*)(defs::timingMode, sls::Positions)) & Detector::setTimingMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTimingModeList", @@ -369,7 +369,7 @@ void init_det(py::module &m) { Detector::getReadoutSpeed, py::arg() = Positions{}); CppDetectorApi.def("setReadoutSpeed", - (void (Detector::*)(defs::speedLevel, sls::Positions)) & + (void(Detector::*)(defs::speedLevel, sls::Positions)) & Detector::setReadoutSpeed, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getReadoutSpeedList", @@ -380,7 +380,7 @@ void init_det(py::module &m) { Detector::getADCPhase, py::arg() = Positions{}); CppDetectorApi.def("setADCPhase", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setADCPhase, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getMaxADCPhaseShift", @@ -392,7 +392,7 @@ void init_det(py::module &m) { Detector::getADCPhaseInDegrees, py::arg() = Positions{}); CppDetectorApi.def("setADCPhaseInDegrees", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setADCPhaseInDegrees, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDBITPhase", @@ -400,7 +400,7 @@ void init_det(py::module &m) { Detector::getDBITPhase, py::arg() = Positions{}); CppDetectorApi.def("setDBITPhase", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setDBITPhase, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getMaxDBITPhaseShift", @@ -412,7 +412,7 @@ void init_det(py::module &m) { Detector::getDBITPhaseInDegrees, py::arg() = Positions{}); CppDetectorApi.def("setDBITPhaseInDegrees", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setDBITPhaseInDegrees, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getClockFrequency", @@ -424,7 +424,7 @@ void init_det(py::module &m) { Detector::getClockPhase, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setClockPhase", - (void (Detector::*)(int, int, sls::Positions)) & + (void(Detector::*)(int, int, sls::Positions)) & Detector::setClockPhase, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getMaxClockPhaseShift", @@ -436,7 +436,7 @@ void init_det(py::module &m) { Detector::getClockPhaseinDegrees, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setClockPhaseinDegrees", - (void (Detector::*)(int, int, sls::Positions)) & + (void(Detector::*)(int, int, sls::Positions)) & Detector::setClockPhaseinDegrees, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getClockDivider", @@ -444,7 +444,7 @@ void init_det(py::module &m) { Detector::getClockDivider, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setClockDivider", - (void (Detector::*)(int, int, sls::Positions)) & + (void(Detector::*)(int, int, sls::Positions)) & Detector::setClockDivider, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getHighVoltage", @@ -452,7 +452,7 @@ void init_det(py::module &m) { Detector::getHighVoltage, py::arg() = Positions{}); CppDetectorApi.def("setHighVoltage", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setHighVoltage, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPowerChip", @@ -460,7 +460,7 @@ void init_det(py::module &m) { Detector::getPowerChip, py::arg() = Positions{}); CppDetectorApi.def("setPowerChip", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setPowerChip, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getImageTestMode", @@ -468,7 +468,7 @@ void init_det(py::module &m) { Detector::getImageTestMode, py::arg() = Positions{}); CppDetectorApi.def("setImageTestMode", - (void (Detector::*)(const int, sls::Positions)) & + (void(Detector::*)(const int, sls::Positions)) & Detector::setImageTestMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTemperatureList", @@ -489,7 +489,7 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setDefaultDac", - (void (Detector::*)(defs::dacIndex, int, sls::Positions)) & + (void(Detector::*)(defs::dacIndex, int, sls::Positions)) & Detector::setDefaultDac, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -500,12 +500,12 @@ void init_det(py::module &m) { py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setDefaultDac", - (void (Detector::*)(defs::dacIndex, int, defs::detectorSettings, - sls::Positions)) & + (void(Detector::*)(defs::dacIndex, int, defs::detectorSettings, + sls::Positions)) & Detector::setDefaultDac, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("resetToDefaultDacs", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::resetToDefaultDacs, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -515,7 +515,7 @@ void init_det(py::module &m) { py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "setDAC", - (void (Detector::*)(defs::dacIndex, int, bool, sls::Positions)) & + (void(Detector::*)(defs::dacIndex, int, bool, sls::Positions)) & Detector::setDAC, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( @@ -525,7 +525,7 @@ void init_det(py::module &m) { py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setOnChipDAC", - (void (Detector::*)(defs::dacIndex, int, int, sls::Positions)) & + (void(Detector::*)(defs::dacIndex, int, int, sls::Positions)) & Detector::setOnChipDAC, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getExternalSignalFlags", @@ -535,7 +535,7 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setExternalSignalFlags", - (void (Detector::*)(int, defs::externalSignalFlag, sls::Positions)) & + (void(Detector::*)(int, defs::externalSignalFlag, sls::Positions)) & Detector::setExternalSignalFlags, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getParallelMode", @@ -543,7 +543,7 @@ void init_det(py::module &m) { Detector::getParallelMode, py::arg() = Positions{}); CppDetectorApi.def("setParallelMode", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setParallelMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getFilterResistor", @@ -551,7 +551,7 @@ void init_det(py::module &m) { Detector::getFilterResistor, py::arg() = Positions{}); CppDetectorApi.def("setFilterResistor", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setFilterResistor, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getCurrentSource", @@ -561,7 +561,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setCurrentSource", - (void (Detector::*)(defs::currentSrcParameters, sls::Positions)) & + (void(Detector::*)(defs::currentSrcParameters, sls::Positions)) & Detector::setCurrentSource, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDBITPipeline", @@ -569,7 +569,7 @@ void init_det(py::module &m) { Detector::getDBITPipeline, py::arg() = Positions{}); CppDetectorApi.def("setDBITPipeline", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setDBITPipeline, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getReadNRows", @@ -577,24 +577,24 @@ void init_det(py::module &m) { Detector::getReadNRows, py::arg() = Positions{}); CppDetectorApi.def("setReadNRows", - (void (Detector::*)(const int, sls::Positions)) & + (void(Detector::*)(const int, sls::Positions)) & Detector::setReadNRows, py::arg(), py::arg() = Positions{}); - CppDetectorApi.def("acquire", (void (Detector::*)()) & Detector::acquire); + CppDetectorApi.def("acquire", (void(Detector::*)()) & Detector::acquire); CppDetectorApi.def("clearAcquiringFlag", - (void (Detector::*)()) & Detector::clearAcquiringFlag); + (void(Detector::*)()) & Detector::clearAcquiringFlag); CppDetectorApi.def("startReceiver", - (void (Detector::*)()) & Detector::startReceiver); + (void(Detector::*)()) & Detector::startReceiver); CppDetectorApi.def("stopReceiver", - (void (Detector::*)()) & Detector::stopReceiver); + (void(Detector::*)()) & Detector::stopReceiver); CppDetectorApi.def("startDetector", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::startDetector, py::arg() = Positions{}); CppDetectorApi.def("startDetectorReadout", - (void (Detector::*)()) & Detector::startDetectorReadout); + (void(Detector::*)()) & Detector::startDetectorReadout); CppDetectorApi.def("stopDetector", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::stopDetector, py::arg() = Positions{}); CppDetectorApi.def( @@ -627,11 +627,11 @@ void init_det(py::module &m) { Detector::getNextFrameNumber, py::arg() = Positions{}); CppDetectorApi.def("setNextFrameNumber", - (void (Detector::*)(uint64_t, sls::Positions)) & + (void(Detector::*)(uint64_t, sls::Positions)) & Detector::setNextFrameNumber, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("sendSoftwareTrigger", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::sendSoftwareTrigger, py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( @@ -640,7 +640,7 @@ void init_det(py::module &m) { Detector::getScan, py::arg() = Positions{}); CppDetectorApi.def("setScan", - (void (Detector::*)(const defs::scanParameters)) & + (void(Detector::*)(const defs::scanParameters)) & Detector::setScan, py::arg()); CppDetectorApi.def( @@ -653,7 +653,7 @@ void init_det(py::module &m) { Detector::getNumberofUDPInterfaces, py::arg() = Positions{}); CppDetectorApi.def("setNumberofUDPInterfaces", - (void (Detector::*)(int)) & + (void(Detector::*)(int)) & Detector::setNumberofUDPInterfaces, py::arg()); CppDetectorApi.def("getSelectedUDPInterface", @@ -661,7 +661,7 @@ void init_det(py::module &m) { Detector::getSelectedUDPInterface, py::arg() = Positions{}); CppDetectorApi.def("selectUDPInterface", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::selectUDPInterface, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -670,7 +670,7 @@ void init_det(py::module &m) { Detector::getSourceUDPIP, py::arg() = Positions{}); CppDetectorApi.def("setSourceUDPIP", - (void (Detector::*)(const sls::IpAddr, sls::Positions)) & + (void(Detector::*)(const sls::IpAddr, sls::Positions)) & Detector::setSourceUDPIP, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -679,7 +679,7 @@ void init_det(py::module &m) { Detector::getSourceUDPIP2, py::arg() = Positions{}); CppDetectorApi.def("setSourceUDPIP2", - (void (Detector::*)(const sls::IpAddr, sls::Positions)) & + (void(Detector::*)(const sls::IpAddr, sls::Positions)) & Detector::setSourceUDPIP2, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -687,21 +687,19 @@ void init_det(py::module &m) { (Result(Detector::*)(sls::Positions) const) & Detector::getSourceUDPMAC, py::arg() = Positions{}); - CppDetectorApi.def( - "setSourceUDPMAC", - (void (Detector::*)(const sls::MacAddr, sls::Positions)) & - Detector::setSourceUDPMAC, - py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("setSourceUDPMAC", + (void(Detector::*)(const sls::MacAddr, sls::Positions)) & + Detector::setSourceUDPMAC, + py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getSourceUDPMAC2", (Result(Detector::*)(sls::Positions) const) & Detector::getSourceUDPMAC2, py::arg() = Positions{}); - CppDetectorApi.def( - "setSourceUDPMAC2", - (void (Detector::*)(const sls::MacAddr, sls::Positions)) & - Detector::setSourceUDPMAC2, - py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("setSourceUDPMAC2", + (void(Detector::*)(const sls::MacAddr, sls::Positions)) & + Detector::setSourceUDPMAC2, + py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDestinationUDPList", (Result(Detector::*)( const uint32_t, sls::Positions) const) & @@ -709,7 +707,7 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setDestinationUDPList", - (void (Detector::*)(const sls::UdpDestination, const int)) & + (void(Detector::*)(const sls::UdpDestination, const int)) & Detector::setDestinationUDPList, py::arg(), py::arg()); CppDetectorApi.def("getNumberofUDPDestinations", @@ -717,7 +715,7 @@ void init_det(py::module &m) { Detector::getNumberofUDPDestinations, py::arg() = Positions{}); CppDetectorApi.def("clearUDPDestinations", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::clearUDPDestinations, py::arg() = Positions{}); CppDetectorApi.def("getFirstUDPDestination", @@ -725,7 +723,7 @@ void init_det(py::module &m) { Detector::getFirstUDPDestination, py::arg() = Positions{}); CppDetectorApi.def("setFirstUDPDestination", - (void (Detector::*)(const int, sls::Positions)) & + (void(Detector::*)(const int, sls::Positions)) & Detector::setFirstUDPDestination, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -734,7 +732,7 @@ void init_det(py::module &m) { Detector::getDestinationUDPIP, py::arg() = Positions{}); CppDetectorApi.def("setDestinationUDPIP", - (void (Detector::*)(const sls::IpAddr, sls::Positions)) & + (void(Detector::*)(const sls::IpAddr, sls::Positions)) & Detector::setDestinationUDPIP, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -743,7 +741,7 @@ void init_det(py::module &m) { Detector::getDestinationUDPIP2, py::arg() = Positions{}); CppDetectorApi.def("setDestinationUDPIP2", - (void (Detector::*)(const sls::IpAddr, sls::Positions)) & + (void(Detector::*)(const sls::IpAddr, sls::Positions)) & Detector::setDestinationUDPIP2, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -751,27 +749,25 @@ void init_det(py::module &m) { (Result(Detector::*)(sls::Positions) const) & Detector::getDestinationUDPMAC, py::arg() = Positions{}); - CppDetectorApi.def( - "setDestinationUDPMAC", - (void (Detector::*)(const sls::MacAddr, sls::Positions)) & - Detector::setDestinationUDPMAC, - py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("setDestinationUDPMAC", + (void(Detector::*)(const sls::MacAddr, sls::Positions)) & + Detector::setDestinationUDPMAC, + py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getDestinationUDPMAC2", (Result(Detector::*)(sls::Positions) const) & Detector::getDestinationUDPMAC2, py::arg() = Positions{}); - CppDetectorApi.def( - "setDestinationUDPMAC2", - (void (Detector::*)(const sls::MacAddr, sls::Positions)) & - Detector::setDestinationUDPMAC2, - py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("setDestinationUDPMAC2", + (void(Detector::*)(const sls::MacAddr, sls::Positions)) & + Detector::setDestinationUDPMAC2, + py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDestinationUDPPort", (Result(Detector::*)(sls::Positions) const) & Detector::getDestinationUDPPort, py::arg() = Positions{}); CppDetectorApi.def("setDestinationUDPPort", - (void (Detector::*)(uint16_t, int)) & + (void(Detector::*)(uint16_t, int)) & Detector::setDestinationUDPPort, py::arg(), py::arg() = -1); CppDetectorApi.def("getDestinationUDPPort2", @@ -779,15 +775,15 @@ void init_det(py::module &m) { Detector::getDestinationUDPPort2, py::arg() = Positions{}); CppDetectorApi.def("setDestinationUDPPort2", - (void (Detector::*)(uint16_t, int)) & + (void(Detector::*)(uint16_t, int)) & Detector::setDestinationUDPPort2, py::arg(), py::arg() = -1); CppDetectorApi.def("reconfigureUDPDestination", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::reconfigureUDPDestination, py::arg() = Positions{}); CppDetectorApi.def("validateUDPConfiguration", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::validateUDPConfiguration, py::arg() = Positions{}); CppDetectorApi.def( @@ -800,7 +796,7 @@ void init_det(py::module &m) { Detector::getTenGiga, py::arg() = Positions{}); CppDetectorApi.def("setTenGiga", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setTenGiga, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTenGigaFlowControl", @@ -808,7 +804,7 @@ void init_det(py::module &m) { Detector::getTenGigaFlowControl, py::arg() = Positions{}); CppDetectorApi.def("setTenGigaFlowControl", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setTenGigaFlowControl, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTransmissionDelayFrame", @@ -816,7 +812,7 @@ void init_det(py::module &m) { Detector::getTransmissionDelayFrame, py::arg() = Positions{}); CppDetectorApi.def("setTransmissionDelayFrame", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setTransmissionDelayFrame, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTransmissionDelayLeft", @@ -824,7 +820,7 @@ void init_det(py::module &m) { Detector::getTransmissionDelayLeft, py::arg() = Positions{}); CppDetectorApi.def("setTransmissionDelayLeft", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setTransmissionDelayLeft, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTransmissionDelayRight", @@ -832,23 +828,23 @@ void init_det(py::module &m) { Detector::getTransmissionDelayRight, py::arg() = Positions{}); CppDetectorApi.def("setTransmissionDelayRight", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setTransmissionDelayRight, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTransmissionDelay", - (int (Detector::*)() const) & + (int(Detector::*)() const) & Detector::getTransmissionDelay); CppDetectorApi.def( "setTransmissionDelay", - (void (Detector::*)(int)) & Detector::setTransmissionDelay, py::arg()); + (void(Detector::*)(int)) & Detector::setTransmissionDelay, py::arg()); CppDetectorApi.def("getUDPDataStream", (Result(Detector::*)(const defs::portPosition, sls::Positions) const) & Detector::getUDPDataStream, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setUDPDataStream", - (void (Detector::*)(const defs::portPosition, const bool, - sls::Positions)) & + (void(Detector::*)(const defs::portPosition, const bool, + sls::Positions)) & Detector::setUDPDataStream, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxDisabledUDPPortIndices", @@ -868,26 +864,26 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setRxHostname", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setRxHostname, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setRxHostname", - (void (Detector::*)(const std::vector &)) & + (void(Detector::*)(const std::vector &)) & Detector::setRxHostname, py::arg()); CppDetectorApi.def("getRxPort", (Result(Detector::*)(sls::Positions) const) & Detector::getRxPort, py::arg() = Positions{}); - CppDetectorApi.def( - "setRxPort", (void (Detector::*)(uint16_t, int)) & Detector::setRxPort, - py::arg(), py::arg() = -1); + CppDetectorApi.def("setRxPort", + (void(Detector::*)(uint16_t, int)) & Detector::setRxPort, + py::arg(), py::arg() = -1); CppDetectorApi.def("getRxFifoDepth", (Result(Detector::*)(sls::Positions) const) & Detector::getRxFifoDepth, py::arg() = Positions{}); CppDetectorApi.def("setRxFifoDepth", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxFifoDepth, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxSilentMode", @@ -895,7 +891,7 @@ void init_det(py::module &m) { Detector::getRxSilentMode, py::arg() = Positions{}); CppDetectorApi.def("setRxSilentMode", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setRxSilentMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -905,7 +901,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setRxFrameDiscardPolicy", - (void (Detector::*)(defs::frameDiscardPolicy, sls::Positions)) & + (void(Detector::*)(defs::frameDiscardPolicy, sls::Positions)) & Detector::setRxFrameDiscardPolicy, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPartialFramesPadding", @@ -913,7 +909,7 @@ void init_det(py::module &m) { Detector::getPartialFramesPadding, py::arg() = Positions{}); CppDetectorApi.def("setPartialFramesPadding", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setPartialFramesPadding, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxUDPSocketBufferSize", @@ -921,7 +917,7 @@ void init_det(py::module &m) { Detector::getRxUDPSocketBufferSize, py::arg() = Positions{}); CppDetectorApi.def("setRxUDPSocketBufferSize", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxUDPSocketBufferSize, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxRealUDPSocketBufferSize", @@ -933,7 +929,7 @@ void init_det(py::module &m) { Detector::getRxLock, py::arg() = Positions{}); CppDetectorApi.def("setRxLock", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setRxLock, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -951,7 +947,7 @@ void init_det(py::module &m) { Detector::getRxArping, py::arg() = Positions{}); CppDetectorApi.def("setRxArping", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setRxArping, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxROI", @@ -959,18 +955,18 @@ void init_det(py::module &m) { Detector::getRxROI, py::arg() = -1); CppDetectorApi.def("setRxROI", - (void (Detector::*)(const std::vector &)) & + (void(Detector::*)(const std::vector &)) & Detector::setRxROI, py::arg()); CppDetectorApi.def("clearRxROI", - (void (Detector::*)()) & Detector::clearRxROI); + (void(Detector::*)()) & Detector::clearRxROI); CppDetectorApi.def( "getFileFormat", (Result(Detector::*)(sls::Positions) const) & Detector::getFileFormat, py::arg() = Positions{}); CppDetectorApi.def("setFileFormat", - (void (Detector::*)(defs::fileFormat, sls::Positions)) & + (void(Detector::*)(defs::fileFormat, sls::Positions)) & Detector::setFileFormat, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -980,7 +976,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setFilePath", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setFilePath, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -990,7 +986,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setFileNamePrefix", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setFileNamePrefix, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getAcquisitionIndex", @@ -998,7 +994,7 @@ void init_det(py::module &m) { Detector::getAcquisitionIndex, py::arg() = Positions{}); CppDetectorApi.def("setAcquisitionIndex", - (void (Detector::*)(int64_t, sls::Positions)) & + (void(Detector::*)(int64_t, sls::Positions)) & Detector::setAcquisitionIndex, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getFileWrite", @@ -1006,20 +1002,20 @@ void init_det(py::module &m) { Detector::getFileWrite, py::arg() = Positions{}); CppDetectorApi.def("setFileWrite", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setFileWrite, py::arg(), py::arg() = Positions{}); - CppDetectorApi.def("getMasterFileWrite", (bool (Detector::*)() const) & + CppDetectorApi.def("getMasterFileWrite", (bool(Detector::*)() const) & Detector::getMasterFileWrite); - CppDetectorApi.def( - "setMasterFileWrite", - (void (Detector::*)(bool)) & Detector::setMasterFileWrite, py::arg()); + CppDetectorApi.def("setMasterFileWrite", + (void(Detector::*)(bool)) & Detector::setMasterFileWrite, + py::arg()); CppDetectorApi.def("getFileOverWrite", (Result(Detector::*)(sls::Positions) const) & Detector::getFileOverWrite, py::arg() = Positions{}); CppDetectorApi.def("setFileOverWrite", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setFileOverWrite, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getFramesPerFile", @@ -1027,7 +1023,7 @@ void init_det(py::module &m) { Detector::getFramesPerFile, py::arg() = Positions{}); CppDetectorApi.def("setFramesPerFile", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setFramesPerFile, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxZmqDataStream", @@ -1035,7 +1031,7 @@ void init_det(py::module &m) { Detector::getRxZmqDataStream, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqDataStream", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setRxZmqDataStream, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxZmqFrequency", @@ -1043,7 +1039,7 @@ void init_det(py::module &m) { Detector::getRxZmqFrequency, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqFrequency", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxZmqFrequency, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxZmqTimer", @@ -1051,7 +1047,7 @@ void init_det(py::module &m) { Detector::getRxZmqTimer, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqTimer", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxZmqTimer, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxZmqStartingFrame", @@ -1059,7 +1055,7 @@ void init_det(py::module &m) { Detector::getRxZmqStartingFrame, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqStartingFrame", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxZmqStartingFrame, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxZmqPort", @@ -1067,7 +1063,7 @@ void init_det(py::module &m) { Detector::getRxZmqPort, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqPort", - (void (Detector::*)(uint16_t, int)) & + (void(Detector::*)(uint16_t, int)) & Detector::setRxZmqPort, py::arg(), py::arg() = -1); CppDetectorApi.def("getClientZmqPort", @@ -1075,7 +1071,7 @@ void init_det(py::module &m) { Detector::getClientZmqPort, py::arg() = Positions{}); CppDetectorApi.def("setClientZmqPort", - (void (Detector::*)(uint16_t, int)) & + (void(Detector::*)(uint16_t, int)) & Detector::setClientZmqPort, py::arg(), py::arg() = -1); CppDetectorApi.def( @@ -1084,23 +1080,23 @@ void init_det(py::module &m) { Detector::getClientZmqIp, py::arg() = Positions{}); CppDetectorApi.def("setClientZmqIp", - (void (Detector::*)(const sls::IpAddr, sls::Positions)) & + (void(Detector::*)(const sls::IpAddr, sls::Positions)) & Detector::setClientZmqIp, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getClientZmqHwm", - (int (Detector::*)() const) & Detector::getClientZmqHwm); + (int(Detector::*)() const) & Detector::getClientZmqHwm); CppDetectorApi.def( "setClientZmqHwm", - (void (Detector::*)(const int)) & Detector::setClientZmqHwm, py::arg()); + (void(Detector::*)(const int)) & Detector::setClientZmqHwm, py::arg()); CppDetectorApi.def("getRxZmqHwm", (Result(Detector::*)(sls::Positions) const) & Detector::getRxZmqHwm, py::arg() = Positions{}); CppDetectorApi.def("setRxZmqHwm", - (void (Detector::*)(const int)) & Detector::setRxZmqHwm, + (void(Detector::*)(const int)) & Detector::setRxZmqHwm, py::arg()); CppDetectorApi.def("streamRxDummyHeader", - (void (Detector::*)(sls::Positions) const) & + (void(Detector::*)(sls::Positions) const) & Detector::streamRxDummyHeader, py::arg() = Positions{}); CppDetectorApi.def("getSubExptime", @@ -1108,7 +1104,7 @@ void init_det(py::module &m) { Detector::getSubExptime, py::arg() = Positions{}); CppDetectorApi.def("setSubExptime", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setSubExptime, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getSubDeadTime", @@ -1116,7 +1112,7 @@ void init_det(py::module &m) { Detector::getSubDeadTime, py::arg() = Positions{}); CppDetectorApi.def("setSubDeadTime", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setSubDeadTime, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getOverFlowMode", @@ -1124,7 +1120,7 @@ void init_det(py::module &m) { Detector::getOverFlowMode, py::arg() = Positions{}); CppDetectorApi.def("setOverFlowMode", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setOverFlowMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRateCorrection", @@ -1132,11 +1128,11 @@ void init_det(py::module &m) { Detector::getRateCorrection, py::arg() = Positions{}); CppDetectorApi.def("setDefaultRateCorrection", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::setDefaultRateCorrection, py::arg() = Positions{}); CppDetectorApi.def("setRateCorrection", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setRateCorrection, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getInterruptSubframe", @@ -1144,7 +1140,7 @@ void init_det(py::module &m) { Detector::getInterruptSubframe, py::arg() = Positions{}); CppDetectorApi.def("setInterruptSubframe", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::setInterruptSubframe, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getMeasuredPeriod", @@ -1160,7 +1156,7 @@ void init_det(py::module &m) { Detector::getActive, py::arg() = Positions{}); CppDetectorApi.def("setActive", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::setActive, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPartialReset", @@ -1168,19 +1164,19 @@ void init_det(py::module &m) { Detector::getPartialReset, py::arg() = Positions{}); CppDetectorApi.def("setPartialReset", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setPartialReset, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("pulsePixel", - (void (Detector::*)(int, defs::xy, sls::Positions)) & + (void(Detector::*)(int, defs::xy, sls::Positions)) & Detector::pulsePixel, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("pulsePixelNMove", - (void (Detector::*)(int, defs::xy, sls::Positions)) & + (void(Detector::*)(int, defs::xy, sls::Positions)) & Detector::pulsePixelNMove, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("pulseChip", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::pulseChip, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getQuad", @@ -1188,14 +1184,14 @@ void init_det(py::module &m) { Detector::getQuad, py::arg() = Positions{}); CppDetectorApi.def("setQuad", - (void (Detector::*)(const bool)) & Detector::setQuad, + (void(Detector::*)(const bool)) & Detector::setQuad, py::arg()); CppDetectorApi.def("getTop", (Result(Detector::*)(sls::Positions) const) & Detector::getTop, py::arg() = Positions{}); CppDetectorApi.def( - "setTop", (void (Detector::*)(bool, sls::Positions)) & Detector::setTop, + "setTop", (void(Detector::*)(bool, sls::Positions)) & Detector::setTop, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getChipVersion", @@ -1207,7 +1203,7 @@ void init_det(py::module &m) { Detector::getThresholdTemperature, py::arg() = Positions{}); CppDetectorApi.def("setThresholdTemperature", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setThresholdTemperature, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTemperatureControl", @@ -1215,7 +1211,7 @@ void init_det(py::module &m) { Detector::getTemperatureControl, py::arg() = Positions{}); CppDetectorApi.def("setTemperatureControl", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setTemperatureControl, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTemperatureEvent", @@ -1223,7 +1219,7 @@ void init_det(py::module &m) { Detector::getTemperatureEvent, py::arg() = Positions{}); CppDetectorApi.def("resetTemperatureEvent", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::resetTemperatureEvent, py::arg() = Positions{}); CppDetectorApi.def("getAutoComparatorDisable", @@ -1231,7 +1227,7 @@ void init_det(py::module &m) { Detector::getAutoComparatorDisable, py::arg() = Positions{}); CppDetectorApi.def("setAutoComparatorDisable", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setAutoComparatorDisable, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getComparatorDisableTime", @@ -1239,7 +1235,7 @@ void init_det(py::module &m) { Detector::getComparatorDisableTime, py::arg() = Positions{}); CppDetectorApi.def("setComparatorDisableTime", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setComparatorDisableTime, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfAdditionalStorageCells", @@ -1247,7 +1243,7 @@ void init_det(py::module &m) { Detector::getNumberOfAdditionalStorageCells, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfAdditionalStorageCells", - (void (Detector::*)(int)) & + (void(Detector::*)(int)) & Detector::setNumberOfAdditionalStorageCells, py::arg()); CppDetectorApi.def("getStorageCellStart", @@ -1255,7 +1251,7 @@ void init_det(py::module &m) { Detector::getStorageCellStart, py::arg() = Positions{}); CppDetectorApi.def("setStorageCellStart", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setStorageCellStart, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getStorageCellDelay", @@ -1263,7 +1259,7 @@ void init_det(py::module &m) { Detector::getStorageCellDelay, py::arg() = Positions{}); CppDetectorApi.def("setStorageCellDelay", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setStorageCellDelay, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getGainModeList", @@ -1276,7 +1272,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setGainMode", - (void (Detector::*)(const defs::gainMode, sls::Positions)) & + (void(Detector::*)(const defs::gainMode, sls::Positions)) & Detector::setGainMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfFilterCells", @@ -1284,7 +1280,7 @@ void init_det(py::module &m) { Detector::getNumberOfFilterCells, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfFilterCells", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setNumberOfFilterCells, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1294,7 +1290,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setPedestalMode", - (void (Detector::*)(const defs::pedestalParameters, sls::Positions)) & + (void(Detector::*)(const defs::pedestalParameters, sls::Positions)) & Detector::setPedestalMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1304,7 +1300,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setTimingInfoDecoder", - (void (Detector::*)(defs::timingInfoDecoder, sls::Positions)) & + (void(Detector::*)(defs::timingInfoDecoder, sls::Positions)) & Detector::setTimingInfoDecoder, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1314,7 +1310,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setCollectionMode", - (void (Detector::*)(defs::collectionMode, sls::Positions)) & + (void(Detector::*)(defs::collectionMode, sls::Positions)) & Detector::setCollectionMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfBursts", @@ -1323,13 +1319,13 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setNumberOfBursts", - (void (Detector::*)(int64_t)) & Detector::setNumberOfBursts, py::arg()); + (void(Detector::*)(int64_t)) & Detector::setNumberOfBursts, py::arg()); CppDetectorApi.def("getBurstPeriod", (Result(Detector::*)(sls::Positions) const) & Detector::getBurstPeriod, py::arg() = Positions{}); CppDetectorApi.def("setBurstPeriod", - (void (Detector::*)(sls::ns, sls::Positions)) & + (void(Detector::*)(sls::ns, sls::Positions)) & Detector::setBurstPeriod, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfBurstsLeft", @@ -1343,28 +1339,28 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setInjectChannel", - (void (Detector::*)(const int, const int, sls::Positions)) & + (void(Detector::*)(const int, const int, sls::Positions)) & Detector::setInjectChannel, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getVetoPhoton", - (void (Detector::*)(const int, const std::string &, sls::Positions)) & + (void(Detector::*)(const int, const std::string &, sls::Positions)) & Detector::getVetoPhoton, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setVetoPhoton", - (void (Detector::*)(const int, const int, const int, - const std::string &, sls::Positions)) & + (void(Detector::*)(const int, const int, const int, const std::string &, + sls::Positions)) & Detector::setVetoPhoton, py::arg(), py::arg(), py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setVetoReference", - (void (Detector::*)(const int, const int, sls::Positions)) & + (void(Detector::*)(const int, const int, sls::Positions)) & Detector::setVetoReference, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setVetoFile", - (void (Detector::*)(const int, const std::string &, sls::Positions)) & + (void(Detector::*)(const int, const std::string &, sls::Positions)) & Detector::setVetoFile, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1373,7 +1369,7 @@ void init_det(py::module &m) { Detector::getBurstMode, py::arg() = Positions{}); CppDetectorApi.def("setBurstMode", - (void (Detector::*)(defs::burstMode, sls::Positions)) & + (void(Detector::*)(defs::burstMode, sls::Positions)) & Detector::setBurstMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getCDSGain", @@ -1381,7 +1377,7 @@ void init_det(py::module &m) { Detector::getCDSGain, py::arg() = Positions{}); CppDetectorApi.def("setCDSGain", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setCDSGain, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1391,7 +1387,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setTimingSource", - (void (Detector::*)(defs::timingSourceType, sls::Positions)) & + (void(Detector::*)(defs::timingSourceType, sls::Positions)) & Detector::setTimingSource, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getVeto", @@ -1399,7 +1395,7 @@ void init_det(py::module &m) { Detector::getVeto, py::arg() = Positions{}); CppDetectorApi.def("setVeto", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::setVeto, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1409,7 +1405,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setVetoStream", - (void (Detector::*)(const defs::streamingInterface, sls::Positions)) & + (void(Detector::*)(const defs::streamingInterface, sls::Positions)) & Detector::setVetoStream, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1420,8 +1416,8 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setVetoAlgorithm", - (void (Detector::*)(const defs::vetoAlgorithm, - const defs::streamingInterface, sls::Positions)) & + (void(Detector::*)(const defs::vetoAlgorithm, + const defs::streamingInterface, sls::Positions)) & Detector::setVetoAlgorithm, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1431,7 +1427,7 @@ void init_det(py::module &m) { py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setADCConfiguration", - (void (Detector::*)(const int, const int, const int, sls::Positions)) & + (void(Detector::*)(const int, const int, const int, sls::Positions)) & Detector::setADCConfiguration, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getCounterMask", @@ -1439,7 +1435,7 @@ void init_det(py::module &m) { Detector::getCounterMask, py::arg() = Positions{}); CppDetectorApi.def("setCounterMask", - (void (Detector::*)(uint32_t, sls::Positions)) & + (void(Detector::*)(uint32_t, sls::Positions)) & Detector::setCounterMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfGates", @@ -1447,7 +1443,7 @@ void init_det(py::module &m) { Detector::getNumberOfGates, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfGates", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setNumberOfGates, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1456,12 +1452,12 @@ void init_det(py::module &m) { Detector::getExptime, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setExptime", - (void (Detector::*)(int, sls::ns, sls::Positions)) & + (void(Detector::*)(int, sls::ns, sls::Positions)) & Detector::setExptime, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getExptimeForAllGates", - (Result>(Detector::*)(sls::Positions) const) & + (Result>(Detector::*)(sls::Positions) const) & Detector::getExptimeForAllGates, py::arg() = Positions{}); CppDetectorApi.def( @@ -1470,12 +1466,12 @@ void init_det(py::module &m) { Detector::getGateDelay, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setGateDelay", - (void (Detector::*)(int, sls::ns, sls::Positions)) & + (void(Detector::*)(int, sls::ns, sls::Positions)) & Detector::setGateDelay, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "getGateDelayForAllGates", - (Result>(Detector::*)(sls::Positions) const) & + (Result>(Detector::*)(sls::Positions) const) & Detector::getGateDelayForAllGates, py::arg() = Positions{}); CppDetectorApi.def("getChipStatusRegister", @@ -1483,7 +1479,7 @@ void init_det(py::module &m) { Detector::getChipStatusRegister, py::arg() = Positions{}); CppDetectorApi.def("setGainCaps", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setGainCaps, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getGainCaps", @@ -1496,7 +1492,7 @@ void init_det(py::module &m) { Detector::getPolarity, py::arg() = Positions{}); CppDetectorApi.def("setPolarity", - (void (Detector::*)(defs::polarity, sls::Positions)) & + (void(Detector::*)(defs::polarity, sls::Positions)) & Detector::setPolarity, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getInterpolation", @@ -1504,7 +1500,7 @@ void init_det(py::module &m) { Detector::getInterpolation, py::arg() = Positions{}); CppDetectorApi.def("setInterpolation", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setInterpolation, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPumpProbe", @@ -1512,7 +1508,7 @@ void init_det(py::module &m) { Detector::getPumpProbe, py::arg() = Positions{}); CppDetectorApi.def("setPumpProbe", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setPumpProbe, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getAnalogPulsing", @@ -1520,7 +1516,7 @@ void init_det(py::module &m) { Detector::getAnalogPulsing, py::arg() = Positions{}); CppDetectorApi.def("setAnalogPulsing", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setAnalogPulsing, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDigitalPulsing", @@ -1528,7 +1524,7 @@ void init_det(py::module &m) { Detector::getDigitalPulsing, py::arg() = Positions{}); CppDetectorApi.def("setDigitalPulsing", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setDigitalPulsing, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfAnalogSamples", @@ -1536,7 +1532,7 @@ void init_det(py::module &m) { Detector::getNumberOfAnalogSamples, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfAnalogSamples", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setNumberOfAnalogSamples, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getADCClock", @@ -1544,7 +1540,7 @@ void init_det(py::module &m) { Detector::getADCClock, py::arg() = Positions{}); CppDetectorApi.def("setADCClock", - (void (Detector::*)(defs::Hz, sls::Positions)) & + (void(Detector::*)(defs::Hz, sls::Positions)) & Detector::setADCClock, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRUNClock", @@ -1552,7 +1548,7 @@ void init_det(py::module &m) { Detector::getRUNClock, py::arg() = Positions{}); CppDetectorApi.def("setRUNClock", - (void (Detector::*)(defs::Hz, sls::Positions)) & + (void(Detector::*)(defs::Hz, sls::Positions)) & Detector::setRUNClock, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDBITClock", @@ -1560,7 +1556,7 @@ void init_det(py::module &m) { Detector::getDBITClock, py::arg() = Positions{}); CppDetectorApi.def("setDBITClock", - (void (Detector::*)(defs::Hz, sls::Positions)) & + (void(Detector::*)(defs::Hz, sls::Positions)) & Detector::setDBITClock, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getSYNCClock", @@ -1571,35 +1567,35 @@ void init_det(py::module &m) { (std::vector(Detector::*)() const) & Detector::getPowerList); CppDetectorApi.def("getPowerDAC", - (int (Detector::*)(defs::powerIndex) const) & + (int(Detector::*)(defs::powerIndex) const) & Detector::getPowerDAC, py::arg()); CppDetectorApi.def("setPowerDAC", - (void (Detector::*)(defs::powerIndex, int)) & + (void(Detector::*)(defs::powerIndex, int)) & Detector::setPowerDAC, py::arg(), py::arg()); CppDetectorApi.def("isPowerEnabled", - (bool (Detector::*)(defs::powerIndex) const) & + (bool(Detector::*)(defs::powerIndex) const) & Detector::isPowerEnabled, py::arg()); CppDetectorApi.def( "setPowerEnabled", - (void (Detector::*)(const std::vector &, bool)) & + (void(Detector::*)(const std::vector &, bool)) & Detector::setPowerEnabled, py::arg(), py::arg()); CppDetectorApi.def("getMeasuredPower", - (int (Detector::*)(defs::powerIndex) const) & + (int(Detector::*)(defs::powerIndex) const) & Detector::getMeasuredPower, py::arg()); CppDetectorApi.def("getMeasuredCurrent", - (int (Detector::*)(defs::powerIndex) const) & + (int(Detector::*)(defs::powerIndex) const) & Detector::getMeasuredCurrent, py::arg()); CppDetectorApi.def("getVoltageLimit", - (int (Detector::*)() const) & Detector::getVoltageLimit); + (int(Detector::*)() const) & Detector::getVoltageLimit); CppDetectorApi.def( "setVoltageLimit", - (void (Detector::*)(const int)) & Detector::setVoltageLimit, py::arg()); + (void(Detector::*)(const int)) & Detector::setVoltageLimit, py::arg()); CppDetectorApi.def("getSlowADCList", (std::vector(Detector::*)() const) & Detector::getSlowADCList); @@ -1613,7 +1609,7 @@ void init_det(py::module &m) { Detector::getADCVpp, py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def("setADCVpp", - (void (Detector::*)(int, bool, sls::Positions)) & + (void(Detector::*)(int, bool, sls::Positions)) & Detector::setADCVpp, py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def("getADCEnableMask", @@ -1621,7 +1617,7 @@ void init_det(py::module &m) { Detector::getADCEnableMask, py::arg() = Positions{}); CppDetectorApi.def("setADCEnableMask", - (void (Detector::*)(uint32_t, sls::Positions)) & + (void(Detector::*)(uint32_t, sls::Positions)) & Detector::setADCEnableMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTenGigaADCEnableMask", @@ -1629,7 +1625,7 @@ void init_det(py::module &m) { Detector::getTenGigaADCEnableMask, py::arg() = Positions{}); CppDetectorApi.def("setTenGigaADCEnableMask", - (void (Detector::*)(uint32_t, sls::Positions)) & + (void(Detector::*)(uint32_t, sls::Positions)) & Detector::setTenGigaADCEnableMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getTransceiverEnableMask", @@ -1637,7 +1633,7 @@ void init_det(py::module &m) { Detector::getTransceiverEnableMask, py::arg() = Positions{}); CppDetectorApi.def("setTransceiverEnableMask", - (void (Detector::*)(uint32_t, sls::Positions)) & + (void(Detector::*)(uint32_t, sls::Positions)) & Detector::setTransceiverEnableMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfDigitalSamples", @@ -1645,7 +1641,7 @@ void init_det(py::module &m) { Detector::getNumberOfDigitalSamples, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfDigitalSamples", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setNumberOfDigitalSamples, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getNumberOfTransceiverSamples", @@ -1653,7 +1649,7 @@ void init_det(py::module &m) { Detector::getNumberOfTransceiverSamples, py::arg() = Positions{}); CppDetectorApi.def("setNumberOfTransceiverSamples", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setNumberOfTransceiverSamples, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1662,7 +1658,7 @@ void init_det(py::module &m) { Detector::getReadoutMode, py::arg() = Positions{}); CppDetectorApi.def("setReadoutMode", - (void (Detector::*)(defs::readoutMode, sls::Positions)) & + (void(Detector::*)(defs::readoutMode, sls::Positions)) & Detector::setReadoutMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getExternalSamplingSource", @@ -1670,7 +1666,7 @@ void init_det(py::module &m) { Detector::getExternalSamplingSource, py::arg() = Positions{}); CppDetectorApi.def("setExternalSamplingSource", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setExternalSamplingSource, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getExternalSampling", @@ -1678,7 +1674,7 @@ void init_det(py::module &m) { Detector::getExternalSampling, py::arg() = Positions{}); CppDetectorApi.def("setExternalSampling", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setExternalSampling, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1688,7 +1684,7 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setRxDbitList", - (void (Detector::*)(const std::vector &, sls::Positions)) & + (void(Detector::*)(const std::vector &, sls::Positions)) & Detector::setRxDbitList, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxDbitOffset", @@ -1696,7 +1692,7 @@ void init_det(py::module &m) { Detector::getRxDbitOffset, py::arg() = Positions{}); CppDetectorApi.def("setRxDbitOffset", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setRxDbitOffset, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getRxDbitReorder", @@ -1704,11 +1700,11 @@ void init_det(py::module &m) { Detector::getRxDbitReorder, py::arg() = Positions{}); CppDetectorApi.def("setRxDbitReorder", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setRxDbitReorder, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setDigitalIODelay", - (void (Detector::*)(uint64_t, int, sls::Positions)) & + (void(Detector::*)(uint64_t, int, sls::Positions)) & Detector::setDigitalIODelay, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getLEDEnable", @@ -1716,11 +1712,11 @@ void init_det(py::module &m) { Detector::getLEDEnable, py::arg() = Positions{}); CppDetectorApi.def("setLEDEnable", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setLEDEnable, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setDacNames", - (void (Detector::*)(const std::vector)) & + (void(Detector::*)(const std::vector)) & Detector::setDacNames, py::arg()); CppDetectorApi.def("getDacNames", @@ -1733,7 +1729,7 @@ void init_det(py::module &m) { py::arg()); CppDetectorApi.def( "setDacName", - (void (Detector::*)(const defs::dacIndex, const std::string &)) & + (void(Detector::*)(const defs::dacIndex, const std::string &)) & Detector::setDacName, py::arg(), py::arg()); CppDetectorApi.def("getDacName", @@ -1741,18 +1737,18 @@ void init_det(py::module &m) { Detector::getDacName, py::arg()); CppDetectorApi.def("setAdcNames", - (void (Detector::*)(const std::vector)) & + (void(Detector::*)(const std::vector)) & Detector::setAdcNames, py::arg()); CppDetectorApi.def("getAdcNames", (std::vector(Detector::*)() const) & Detector::getAdcNames); CppDetectorApi.def("getAdcIndex", - (int (Detector::*)(const std::string &) const) & + (int(Detector::*)(const std::string &) const) & Detector::getAdcIndex, py::arg()); CppDetectorApi.def("setAdcName", - (void (Detector::*)(const int, const std::string &)) & + (void(Detector::*)(const int, const std::string &)) & Detector::setAdcName, py::arg(), py::arg()); CppDetectorApi.def("getAdcName", @@ -1760,18 +1756,18 @@ void init_det(py::module &m) { Detector::getAdcName, py::arg()); CppDetectorApi.def("setSignalNames", - (void (Detector::*)(const std::vector)) & + (void(Detector::*)(const std::vector)) & Detector::setSignalNames, py::arg()); CppDetectorApi.def("getSignalNames", (std::vector(Detector::*)() const) & Detector::getSignalNames); CppDetectorApi.def("getSignalIndex", - (int (Detector::*)(const std::string &) const) & + (int(Detector::*)(const std::string &) const) & Detector::getSignalIndex, py::arg()); CppDetectorApi.def("setSignalName", - (void (Detector::*)(const int, const std::string &)) & + (void(Detector::*)(const int, const std::string &)) & Detector::setSignalName, py::arg(), py::arg()); CppDetectorApi.def("getSignalName", @@ -1779,7 +1775,7 @@ void init_det(py::module &m) { Detector::getSignalName, py::arg()); CppDetectorApi.def("setPowerNames", - (void (Detector::*)(const std::vector)) & + (void(Detector::*)(const std::vector)) & Detector::setPowerNames, py::arg()); CppDetectorApi.def("getPowerNames", @@ -1792,7 +1788,7 @@ void init_det(py::module &m) { py::arg()); CppDetectorApi.def( "setPowerName", - (void (Detector::*)(const defs::powerIndex, const std::string &)) & + (void(Detector::*)(const defs::powerIndex, const std::string &)) & Detector::setPowerName, py::arg(), py::arg()); CppDetectorApi.def( @@ -1801,7 +1797,7 @@ void init_det(py::module &m) { Detector::getPowerName, py::arg()); CppDetectorApi.def("setSlowADCNames", - (void (Detector::*)(const std::vector)) & + (void(Detector::*)(const std::vector)) & Detector::setSlowADCNames, py::arg()); CppDetectorApi.def("getSlowADCNames", @@ -1814,7 +1810,7 @@ void init_det(py::module &m) { py::arg()); CppDetectorApi.def( "setSlowADCName", - (void (Detector::*)(const defs::dacIndex, const std::string &)) & + (void(Detector::*)(const defs::dacIndex, const std::string &)) & Detector::setSlowADCName, py::arg(), py::arg()); CppDetectorApi.def("getSlowADCName", @@ -1822,19 +1818,19 @@ void init_det(py::module &m) { Detector::getSlowADCName, py::arg()); CppDetectorApi.def("getRegisterDefinitionsCount", - (int (Detector::*)() const) & + (int(Detector::*)() const) & Detector::getRegisterDefinitionsCount); CppDetectorApi.def( "setRegisterDefinition", - (void (Detector::*)(const std::string &, sls::RegisterAddress)) & + (void(Detector::*)(const std::string &, sls::RegisterAddress)) & Detector::setRegisterDefinition, py::arg(), py::arg()); CppDetectorApi.def("hasRegisterDefinition", - (bool (Detector::*)(const std::string &) const) & + (bool(Detector::*)(const std::string &) const) & Detector::hasRegisterDefinition, py::arg()); CppDetectorApi.def("hasRegisterDefinition", - (bool (Detector::*)(sls::RegisterAddress) const) & + (bool(Detector::*)(sls::RegisterAddress) const) & Detector::hasRegisterDefinition, py::arg()); CppDetectorApi.def( @@ -1847,31 +1843,32 @@ void init_det(py::module &m) { Detector::getRegisterName, py::arg()); CppDetectorApi.def("clearRegisterDefinitions", - (void (Detector::*)()) & + (void(Detector::*)()) & Detector::clearRegisterDefinitions); CppDetectorApi.def( "setRegisterDefinitions", - (void (Detector::*)(const std::map &)) & + (void(Detector::*)( + const std::map &)) & Detector::setRegisterDefinitions, py::arg()); CppDetectorApi.def( "getRegisterDefinitions", - (std::map(Detector::*)() const) & + (std::map(Detector::*)() const) & Detector::getRegisterDefinitions); CppDetectorApi.def("getBitDefinitionsCount", - (int (Detector::*)() const) & + (int(Detector::*)() const) & Detector::getBitDefinitionsCount); CppDetectorApi.def( "setBitDefinition", - (void (Detector::*)(const std::string &, sls::BitAddress)) & + (void(Detector::*)(const std::string &, sls::BitAddress)) & Detector::setBitDefinition, py::arg(), py::arg()); CppDetectorApi.def("hasBitDefinition", - (bool (Detector::*)(const std::string &) const) & + (bool(Detector::*)(const std::string &) const) & Detector::hasBitDefinition, py::arg()); CppDetectorApi.def("hasBitDefinition", - (bool (Detector::*)(sls::BitAddress) const) & + (bool(Detector::*)(sls::BitAddress) const) & Detector::hasBitDefinition, py::arg()); CppDetectorApi.def("toRegisterNameBitString", @@ -1888,17 +1885,18 @@ void init_det(py::module &m) { Detector::getBitName, py::arg()); CppDetectorApi.def("clearBitDefinitions", - (void (Detector::*)()) & Detector::clearBitDefinitions); + (void(Detector::*)()) & Detector::clearBitDefinitions); CppDetectorApi.def( "setBitDefinitions", - (void (Detector::*)(const std::map &)) & + (void(Detector::*)(const std::map &)) & Detector::setBitDefinitions, py::arg()); - CppDetectorApi.def("getBitDefinitions", (std::map( - Detector::*)() const) & - Detector::getBitDefinitions); + CppDetectorApi.def( + "getBitDefinitions", + (std::map(Detector::*)() const) & + Detector::getBitDefinitions); CppDetectorApi.def("configureTransceiver", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::configureTransceiver, py::arg() = Positions{}); CppDetectorApi.def( @@ -1908,20 +1906,20 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setPattern", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::setPattern, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setPattern", - (void (Detector::*)(const sls::Pattern &, sls::Positions)) & + (void(Detector::*)(const sls::Pattern &, sls::Positions)) & Detector::setPattern, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("savePattern", - (void (Detector::*)(const std::string &)) & + (void(Detector::*)(const std::string &)) & Detector::savePattern, py::arg()); CppDetectorApi.def("loadDefaultPattern", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::loadDefaultPattern, py::arg() = Positions{}); CppDetectorApi.def("getPatternIOControl", @@ -1929,7 +1927,7 @@ void init_det(py::module &m) { Detector::getPatternIOControl, py::arg() = Positions{}); CppDetectorApi.def("setPatternIOControl", - (void (Detector::*)(uint64_t, sls::Positions)) & + (void(Detector::*)(uint64_t, sls::Positions)) & Detector::setPatternIOControl, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPatternWord", @@ -1937,7 +1935,7 @@ void init_det(py::module &m) { Detector::getPatternWord, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternWord", - (void (Detector::*)(int, uint64_t, sls::Positions)) & + (void(Detector::*)(int, uint64_t, sls::Positions)) & Detector::setPatternWord, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1946,7 +1944,7 @@ void init_det(py::module &m) { Detector::getPatternLoopAddresses, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternLoopAddresses", - (void (Detector::*)(int, int, int, sls::Positions)) & + (void(Detector::*)(int, int, int, sls::Positions)) & Detector::setPatternLoopAddresses, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}); @@ -1955,7 +1953,7 @@ void init_det(py::module &m) { Detector::getPatternLoopCycles, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternLoopCycles", - (void (Detector::*)(int, int, sls::Positions)) & + (void(Detector::*)(int, int, sls::Positions)) & Detector::setPatternLoopCycles, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPatternWaitAddr", @@ -1963,7 +1961,7 @@ void init_det(py::module &m) { Detector::getPatternWaitAddr, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternWaitAddr", - (void (Detector::*)(int, int, sls::Positions)) & + (void(Detector::*)(int, int, sls::Positions)) & Detector::setPatternWaitAddr, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1972,7 +1970,7 @@ void init_det(py::module &m) { Detector::getPatternWaitClocks, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternWaitClocks", - (void (Detector::*)(int, uint64_t, sls::Positions)) & + (void(Detector::*)(int, uint64_t, sls::Positions)) & Detector::setPatternWaitClocks, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( @@ -1981,7 +1979,7 @@ void init_det(py::module &m) { Detector::getPatternWaitInterval, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("setPatternWaitInterval", - (void (Detector::*)(int, sls::ns, sls::Positions)) & + (void(Detector::*)(int, sls::ns, sls::Positions)) & Detector::setPatternWaitInterval, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPatternMask", @@ -1989,7 +1987,7 @@ void init_det(py::module &m) { Detector::getPatternMask, py::arg() = Positions{}); CppDetectorApi.def("setPatternMask", - (void (Detector::*)(uint64_t, sls::Positions)) & + (void(Detector::*)(uint64_t, sls::Positions)) & Detector::setPatternMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getPatternBitMask", @@ -1997,11 +1995,11 @@ void init_det(py::module &m) { Detector::getPatternBitMask, py::arg() = Positions{}); CppDetectorApi.def("setPatternBitMask", - (void (Detector::*)(uint64_t, sls::Positions)) & + (void(Detector::*)(uint64_t, sls::Positions)) & Detector::setPatternBitMask, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("startPattern", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::startPattern, py::arg() = Positions{}); CppDetectorApi.def("getAdditionalJsonHeader", @@ -2011,8 +2009,8 @@ void init_det(py::module &m) { py::arg() = Positions{}); CppDetectorApi.def( "setAdditionalJsonHeader", - (void (Detector::*)(const std::map &, - sls::Positions)) & + (void(Detector::*)(const std::map &, + sls::Positions)) & Detector::setAdditionalJsonHeader, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getAdditionalJsonParameter", @@ -2022,8 +2020,8 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "setAdditionalJsonParameter", - (void (Detector::*)(const std::string &, const std::string &, - sls::Positions)) & + (void(Detector::*)(const std::string &, const std::string &, + sls::Positions)) & Detector::setAdditionalJsonParameter, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getADCPipeline", @@ -2031,35 +2029,35 @@ void init_det(py::module &m) { Detector::getADCPipeline, py::arg() = Positions{}); CppDetectorApi.def("setADCPipeline", - (void (Detector::*)(int, sls::Positions)) & + (void(Detector::*)(int, sls::Positions)) & Detector::setADCPipeline, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "programFPGA", - (void (Detector::*)(const std::string &, const bool, sls::Positions)) & + (void(Detector::*)(const std::string &, const bool, sls::Positions)) & Detector::programFPGA, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def( - "resetFPGA", (void (Detector::*)(sls::Positions)) & Detector::resetFPGA, + "resetFPGA", (void(Detector::*)(sls::Positions)) & Detector::resetFPGA, py::arg() = Positions{}); CppDetectorApi.def( "updateDetectorServer", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::updateDetectorServer, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "updateKernel", - (void (Detector::*)(const std::string &, sls::Positions)) & + (void(Detector::*)(const std::string &, sls::Positions)) & Detector::updateKernel, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("rebootController", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::rebootController, py::arg() = Positions{}); CppDetectorApi.def( "updateFirmwareAndServer", - (void (Detector::*)(const std::string &, const std::string &, - sls::Positions)) & + (void(Detector::*)(const std::string &, const std::string &, + sls::Positions)) & Detector::updateFirmwareAndServer, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getUpdateMode", @@ -2067,7 +2065,7 @@ void init_det(py::module &m) { Detector::getUpdateMode, py::arg() = Positions{}); CppDetectorApi.def("setUpdateMode", - (void (Detector::*)(const bool, sls::Positions)) & + (void(Detector::*)(const bool, sls::Positions)) & Detector::setUpdateMode, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("readRegister", @@ -2077,18 +2075,18 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "writeRegister", - (void (Detector::*)(sls::RegisterAddress, sls::RegisterValue, bool, - sls::Positions)) & + (void(Detector::*)(sls::RegisterAddress, sls::RegisterValue, bool, + sls::Positions)) & Detector::writeRegister, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "setBit", - (void (Detector::*)(sls::BitAddress, bool, sls::Positions)) & + (void(Detector::*)(sls::BitAddress, bool, sls::Positions)) & Detector::setBit, py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "clearBit", - (void (Detector::*)(sls::BitAddress, bool, sls::Positions)) & + (void(Detector::*)(sls::BitAddress, bool, sls::Positions)) & Detector::clearBit, py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( @@ -2103,18 +2101,18 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "writeRegister", - (void (Detector::*)(const std::string &, sls::RegisterValue, bool, - sls::Positions)) & + (void(Detector::*)(const std::string &, sls::RegisterValue, bool, + sls::Positions)) & Detector::writeRegister, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "setBit", - (void (Detector::*)(const std::string &, bool, sls::Positions)) & + (void(Detector::*)(const std::string &, bool, sls::Positions)) & Detector::setBit, py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "clearBit", - (void (Detector::*)(const std::string &, bool, sls::Positions)) & + (void(Detector::*)(const std::string &, bool, sls::Positions)) & Detector::clearBit, py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( @@ -2129,17 +2127,17 @@ void init_det(py::module &m) { py::arg(), py::arg() = Positions{}); CppDetectorApi.def( "writeRegister", - (void (Detector::*)(uint32_t, uint32_t, bool, sls::Positions)) & + (void(Detector::*)(uint32_t, uint32_t, bool, sls::Positions)) & Detector::writeRegister, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "setBit", - (void (Detector::*)(uint32_t, int, bool, sls::Positions)) & + (void(Detector::*)(uint32_t, int, bool, sls::Positions)) & Detector::setBit, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( "clearBit", - (void (Detector::*)(uint32_t, int, bool, sls::Positions)) & + (void(Detector::*)(uint32_t, int, bool, sls::Positions)) & Detector::clearBit, py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}); CppDetectorApi.def( @@ -2148,22 +2146,21 @@ void init_det(py::module &m) { Detector::getBit, py::arg(), py::arg(), py::arg() = Positions{}); CppDetectorApi.def("executeFirmwareTest", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::executeFirmwareTest, py::arg() = Positions{}); CppDetectorApi.def("executeBusTest", - (void (Detector::*)(sls::Positions)) & + (void(Detector::*)(sls::Positions)) & Detector::executeBusTest, py::arg() = Positions{}); - CppDetectorApi.def( - "writeAdcRegister", - (void (Detector::*)(uint32_t, uint32_t, sls::Positions)) & - Detector::writeAdcRegister, - py::arg(), py::arg(), py::arg() = Positions{}); - CppDetectorApi.def("getInitialChecks", (bool (Detector::*)() const) & + CppDetectorApi.def("writeAdcRegister", + (void(Detector::*)(uint32_t, uint32_t, sls::Positions)) & + Detector::writeAdcRegister, + py::arg(), py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("getInitialChecks", (bool(Detector::*)() const) & Detector::getInitialChecks); CppDetectorApi.def("setInitialChecks", - (void (Detector::*)(const bool)) & + (void(Detector::*)(const bool)) & Detector::setInitialChecks, py::arg()); CppDetectorApi.def("getADCInvert", @@ -2171,7 +2168,7 @@ void init_det(py::module &m) { Detector::getADCInvert, py::arg() = Positions{}); CppDetectorApi.def("setADCInvert", - (void (Detector::*)(uint32_t, sls::Positions)) & + (void(Detector::*)(uint32_t, sls::Positions)) & Detector::setADCInvert, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getControlPort", @@ -2179,7 +2176,7 @@ void init_det(py::module &m) { Detector::getControlPort, py::arg() = Positions{}); CppDetectorApi.def("setControlPort", - (void (Detector::*)(uint16_t, sls::Positions)) & + (void(Detector::*)(uint16_t, sls::Positions)) & Detector::setControlPort, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getStopPort", @@ -2187,7 +2184,7 @@ void init_det(py::module &m) { Detector::getStopPort, py::arg() = Positions{}); CppDetectorApi.def("setStopPort", - (void (Detector::*)(uint16_t, sls::Positions)) & + (void(Detector::*)(uint16_t, sls::Positions)) & Detector::setStopPort, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getDetectorLock", @@ -2195,7 +2192,7 @@ void init_det(py::module &m) { Detector::getDetectorLock, py::arg() = Positions{}); CppDetectorApi.def("setDetectorLock", - (void (Detector::*)(bool, sls::Positions)) & + (void(Detector::*)(bool, sls::Positions)) & Detector::setDetectorLock, py::arg(), py::arg() = Positions{}); CppDetectorApi.def( From ce632825d8b935ab36c2285279395835b8a60cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Thu, 1 Oct 2026 19:15:56 +0200 Subject: [PATCH 03/12] Heap allocation of image data in virtual servers (#1586) * virtual servers: allocate image data on the heap * exit on failure to allocate image data * replaced malloc with calloc * reverted comment * fixed memory leak in xctb --- .../ctbDetectorServer/slsDetectorFunctionList.c | 9 +++------ .../eigerDetectorServer/slsDetectorFunctionList.c | 8 ++++++-- .../jungfrauDetectorServer/slsDetectorFunctionList.c | 8 ++++++-- .../moenchDetectorServer/slsDetectorFunctionList.c | 8 ++++++-- .../xilinx_ctbDetectorServer/slsDetectorFunctionList.c | 9 +++++---- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 33f95fd42..cabf6f09f 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -2629,13 +2629,10 @@ void *start_timer(void *arg) { int packetsPerFrame = ceil((double)imageSize / (double)dataSize); // Generate Data - char *imageData = (char *)malloc(imageSize); - memset(imageData, 0, imageSize); - + char *imageData = (char *)calloc(imageSize, 1); if (imageData == NULL) { - LOG(logERROR, ("Can not allocate image Data RAM." - "Probable cause: Memory Leak.\n")); - return NULL; + LOG(logERROR, ("Could not allocate memory for virtual image\n")); + exit(EXIT_FAILURE); } /* for (int i = 0; i < imageSize; i += sizeof(uint16_t)) { diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index c204a1221..0b22df2be 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -2783,8 +2783,11 @@ void *start_timer(void *arg) { npixelsx, databytes)); // Generate data - char imageData[databytes * 2]; - memset(imageData, 0, databytes * 2); + char *imageData = (char *)calloc(databytes * 2, 1); + if (imageData == NULL) { + LOG(logERROR, ("Could not allocate memory for virtual image\n")); + exit(EXIT_FAILURE); + } { int npixels = NCHAN * NCHIP; const int pixelsPerPacket = (double)datasize / bytesPerPixel; @@ -3014,6 +3017,7 @@ void *start_timer(void *arg) { } setNextFrameNumber(frameNr + numFrames); } + free(imageData); closeUDPSocket(0); closeUDPSocket(1); diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 706778402..02c0c9144 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -3078,8 +3078,11 @@ void *start_timer(void *arg) { ((maxPacketsPerFrame / 2) * readNRows) / (maxRows / 2); // Generate data - char imageData[DATA_BYTES]; - memset(imageData, 0, DATA_BYTES); + char *imageData = (char *)calloc(DATA_BYTES, 1); + if (imageData == NULL) { + LOG(logERROR, ("Could not allocate memory for virtual image\n")); + exit(EXIT_FAILURE); + } { const int npixels = (NCHAN * NCHIP); const int pixelsPerPacket = dataSize / NUM_BYTES_PER_PIXEL; @@ -3252,6 +3255,7 @@ void *start_timer(void *arg) { } setNextFrameNumber(frameNr + numFrames); } + free(imageData); closeUDPSocket(0); if (numInterfaces == 2) { diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index 509c92a15..1b9d7b343 100644 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -1972,8 +1972,11 @@ void *start_timer(void *arg) { ((maxPacketsPerFrame / 2) * readNRows) / (maxRows / 2); // Generate data - char imageData[DATA_BYTES]; - memset(imageData, 0, DATA_BYTES); + char *imageData = (char *)calloc(DATA_BYTES, 1); + if (imageData == NULL) { + LOG(logERROR, ("Could not allocate memory for virtual image\n")); + exit(EXIT_FAILURE); + } { const int npixels = (NCHAN * NCHIP); const int pixelsPerPacket = dataSize / NUM_BYTES_PER_PIXEL; @@ -2101,6 +2104,7 @@ void *start_timer(void *arg) { } setNextFrameNumber(frameNr + numFrames); } + free(imageData); closeUDPSocket(0); if (numInterfaces == 2) { diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c index 573b68b48..d72fc5f74 100644 --- a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c @@ -1601,11 +1601,10 @@ void *start_timer(void *arg) { packetSize, packetsPerFrame)); // Generate Data - char *imageData = (char *)malloc(imageSize); - memset(imageData, 0, imageSize); + char *imageData = (char *)calloc(imageSize, 1); if (imageData == NULL) { - LOG(logERROR, ("Can not allocate image.\n")); - return NULL; + LOG(logERROR, ("Could not allocate memory for virtual image\n")); + exit(EXIT_FAILURE); } for (int i = 0; i < imageSize; i += sizeof(uint16_t)) { *((uint16_t *)(imageData + i)) = i; @@ -1672,6 +1671,8 @@ void *start_timer(void *arg) { } } setNextFrameNumber(frameNr + numFrames); + free(imageData); + closeUDPSocket(0); sharedMemory_setStatus(IDLE); From 4df80357974ccba385b2ab359e23ebdfb64eafc1 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 5 Oct 2026 11:02:39 +0200 Subject: [PATCH 04/12] Dev/jf chip1 2 part2 (#1589) * Jungfrau chip v1.2 Part 2 - Enable reset step reduction for v1.2 - Electron collection mode => reset and bypass cds - filter resistor: default value is the lower resistor - 1.1+: changing filter resistor updates asic ds timer (0x1f for lower, 0x5f for higher) - 1.2: default special dac values for G0 and G1 are pointing to different values - auto comp disable: disabled by default (as before but now explicitly set) - compdisabletime defaults (v1.0: 5us, v1.2: 2us) * storagecells for v1.2: not allowed in funcs * fixed for dev --- .../jungfrauDetectorServer/RegisterDefs.h | 11 +- .../bin/jungfrauDetectorServer_developer | Bin 320416 -> 321304 bytes .../slsDetectorFunctionList.c | 98 ++++++++++++++---- .../slsDetectorFunctionList.h | 5 + .../slsDetectorServer_defs.h | 7 +- .../src/slsDetectorServer_funcs.c | 2 +- .../tests/Caller/test-Caller-jungfrau.cpp | 4 +- slsSupportLib/include/sls/versionAPI.h | 2 +- 8 files changed, 102 insertions(+), 27 deletions(-) diff --git a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h index 6ea71da55..6a16724a1 100644 --- a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h +++ b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h @@ -301,7 +301,8 @@ #define CONFIG_V12_STRG_CLL_OFST (0) #define CONFIG_V12_STRG_CLL_MSK (0x0000FFFF << CONFIG_V12_STRG_CLL_OFST) - +#define CONFIG_V12_RST_STP_RDCTN_OFST (18) +#define CONFIG_V12_RST_STP_RDCTN_MSK (0x00000001 << CONFIG_V12_RST_STP_RDCTN_OFST) // CSM mode = high current (100%), low current (16%) #define CONFIG_V11_CRRNT_SRC_LOW_OFST (19) #define CONFIG_V11_CRRNT_SRC_LOW_MSK (0x00000001 << CONFIG_V11_CRRNT_SRC_LOW_OFST) @@ -412,6 +413,10 @@ #define DAQ_CRRNT_SRC_CLMN_SLCT_OFST (20) #define DAQ_CRRNT_SRC_CLMN_SLCT_MSK (0x0000003F << DAQ_CRRNT_SRC_CLMN_SLCT_OFST) #define DAQ_GAIN_MODE_MASK (DAQ_FRCE_SWTCH_GAIN_MSK | DAQ_FIX_GAIN_MSK | DAQ_CMP_RST_MSK) +#define DAQ_CDS_BYPASS_OFST (28) +#define DAQ_CDS_BYPASS_MSK (0x00000001 << DAQ_CDS_BYPASS_OFST) +#define DAQ_CDS_RESET_OFST (29) +#define DAQ_CDS_RESET_MSK (0x00000001 << DAQ_CDS_RESET_OFST) /** Chip Power Register */ #define CHIP_POWER_REG (0x5E << MEM_MAP_SHIFT) @@ -494,8 +499,8 @@ Time before end of exposure when comparator is disabled */ // tDS = (DST + 1) * 25ns #define ASIC_CTRL_DS_TMR_OFST (8) #define ASIC_CTRL_DS_TMR_MSK (0x000000FF << ASIC_CTRL_DS_TMR_OFST) -#define ASIC_CTRL_DS_TMR_VAL ((0x1F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK) -#define ASIC_CTRL_DS_TMR_CHIP1_1_VAL ((0xFF << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK) +#define ASIC_CTRL_DS_TMR_LOW_RES_VAL ((0x1F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK) +#define ASIC_CTRL_DS_TMR_HIGH_RES_VAL ((0x5F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK) /* ADC 0 Deserializer Control */ #define ADC_DSRLZR_0_REG (0xF0 << MEM_MAP_SHIFT) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 362047d6447285a520a576f1dca9b552fc665b1d..4f6b9ee94c975e1c2cc73c177f713fcd7a01cf49 100755 GIT binary patch delta 144712 zcmb5X4O|sf9{)cV5HE-}DiuCo(G*SXf@Js@ASxmX8u^sfHLa+uuxuAw>!Lj@weBu7 zmR8hWTeq~_yp|Q0OD(o;nQMkcg+|6Wbi=a3vRyRw{@>@!9T<1p-|zQ-z5L?5Kl42g zbIzGFXU?3N>wCBNrUSi4-7r1BNKup+EJuk>t5agqpdG5B@K0l-Y3&tl>551An6Zd$E2P7d zthYuxjHIhFbzhny%*c!?39byN9>ushswChrjxWyiMiNqt((kM&?TI=Qq7q%nR-}s2 z?T7#6)je4;5pTE0u&yHIJf-7sd5xREoE1VKh0Op{rxNVo~lke@}O``vSMah?|kAmyT7i zEIb_IxQsU(6~RiG(h)}m2`xJ>p+65Esn`F!aj__g=Qg8jYJ-R#s3#BuIHrRII#byA@+<^t~-j;i-Dr*l0{kj>-3KS!6GpmX5L!CG|N4-;}NhGny2CaAzQe zB93pDu0U$QIbTVLP09?+m0R|Ta$fGxotM{8QMb+Qtf+ue7u+q2uUV-hmK)

mk2L#YoQlyN<-)Du_V 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%0AS8vQuX`k|5NPg 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 CB&hTN diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 02c0c9144..7ccc5baa4 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -49,9 +49,15 @@ enum detectorSettings thisSettings = UNINITIALIZED; static enum CHIPINDEX chipIndex = v1_0; int highvoltage = 0; int dacValues[NDAC] = {}; -int defaultDacValues[] = DEFAULT_DAC_VALS; -int defaultDacValue_G0[] = SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS; -int defaultDacValue_HG0[] = SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS; +int defaultDacValues[NDAC] = DEFAULT_DAC_VALS; + +static int defaultDacList_G0[NSPECIALDACS] = SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS; +static int defaultDacList_HG0[NSPECIALDACS] = + SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS; +static int defaultDacList_v1_2[NSPECIALDACS] = SPECIAL_DEFAULT_V1_2_GAIN_VALS; +int *defaultDacValue_G0 = defaultDacList_G0; +int *defaultDacValue_HG0 = defaultDacList_HG0; + int32_t clkPhase[NUM_CLOCKS] = {}; int detPos[4] = {}; bool chipConfigured = false; @@ -67,6 +73,7 @@ bool has_current_src_normal = false; bool has_current_src_64bit_selection = false; bool has_current_src_reverse_bits_selection = false; bool has_storage_start_in_chip_config = false; +bool has_step_reduction = false; int isInitCheckDone() { return initCheckDone; } @@ -406,6 +413,8 @@ int setChipIndex(enum CHIPINDEX ind, char *mess) { return setChipVersionInFPGA(mess); } +enum CHIPINDEX getChipIndex() { return chipIndex; } + int validateChipIndex(enum CHIPINDEX ind, char *mess) { if (ind < 0 || ind >= NUM_CHIP_INDICES) { sprintf(mess, "Invalid chip index %d. Options: %s\n", (int)ind, @@ -437,6 +446,9 @@ void setChipIndexAllowedFeatures() { has_current_src_64bit_selection = false; has_current_src_reverse_bits_selection = false; has_storage_start_in_chip_config = false; + has_step_reduction = false; + defaultDacValue_G0 = defaultDacList_G0; + defaultDacValue_HG0 = defaultDacList_HG0; break; case v1_1: has_configure_chip = true; @@ -447,6 +459,9 @@ void setChipIndexAllowedFeatures() { has_current_src_64bit_selection = true; has_current_src_reverse_bits_selection = true; has_storage_start_in_chip_config = true; + has_step_reduction = false; + defaultDacValue_G0 = defaultDacList_G0; + defaultDacValue_HG0 = defaultDacList_HG0; break; case v1_2_NORMAL: case v1_2_LOW_NOISE: @@ -459,6 +474,9 @@ void setChipIndexAllowedFeatures() { has_current_src_64bit_selection = true; has_current_src_reverse_bits_selection = false; has_storage_start_in_chip_config = true; + has_step_reduction = true; + defaultDacValue_G0 = defaultDacList_v1_2; + defaultDacValue_HG0 = defaultDacList_v1_2; break; default: LOG(logERROR, ("Unknown chip index %d\n", (int)chipIndex)); @@ -617,6 +635,9 @@ void setupDetector() { clkPhase[i] = 0; } chipConfigured = false; + defaultDacValue_G0 = defaultDacList_G0; + defaultDacValue_HG0 = defaultDacList_HG0; + #ifdef VIRTUAL if (isControlServer) { sharedMemory_setStatus(IDLE); @@ -700,6 +721,10 @@ void setupDetector() { return; setGainMode(DEFAULT_GAINMODE); + autoCompDisable(DEFAULT_AUTO_COMP_DISABLE); + setComparatorDisableTime(chipIndex == v1_0 ? DEFAULT_COMP_DISABLE_TIME_v1_0 + : DEFAULT_COMP_DISABLE_TIME); + setNumFrames(DEFAULT_NUM_FRAMES); setNumTriggers(DEFAULT_NUM_CYCLES); setExpTime(DEFAULT_EXPTIME); @@ -725,6 +750,8 @@ void setupDetector() { setFilterResistor(DEFAULT_FILTER_RESISTOR); if (hasFilterCellsFeature()) setNumberOfFilterCells(DEFAULT_FILTER_CELL); + if (hasStepReductionFeature()) + enableStepReduction(); if (!isHardwareVersion_1_0()) { setFlipRows(DEFAULT_FLIP_ROWS); @@ -2225,6 +2252,8 @@ bool hasStorageCellStartInChipConfig() { return has_storage_start_in_chip_config; } +bool hasStepReductionFeature() { return has_step_reduction; } + bool isChipConfigured() { return chipConfigured; } void configureChip() { @@ -2292,16 +2321,31 @@ int64_t getComparatorDisableTime() { } void configureASICTimer() { + configureAsicPrechargeTimer(); + configureAsicDSTimer(); +} + +void configureAsicPrechargeTimer() { bus_w(ASIC_CTRL_REG, (bus_r(ASIC_CTRL_REG) & ~ASIC_CTRL_PRCHRG_TMR_MSK) | ASIC_CTRL_PRCHRG_TMR_VAL); + uint32_t retval = ((bus_r(ASIC_CTRL_REG) & ASIC_CTRL_PRCHRG_TMR_MSK) >> + ASIC_CTRL_PRCHRG_TMR_OFST); + LOG(logINFO, ("Configured ASIC Precharge Timer [0x%x]\n", retval)); +} - uint32_t val = ASIC_CTRL_DS_TMR_CHIP1_1_VAL; - // TODO: value of chipindex v1_2 value to be decided. - if (chipIndex == v1_0) { - val = ASIC_CTRL_DS_TMR_VAL; +void configureAsicDSTimer() { + // chipv1.0 => always low res val + // chipv1.1+ => depending on res filter + uint32_t val = ASIC_CTRL_DS_TMR_LOW_RES_VAL; + if (chipIndex != v1_0 && getFilterResistor() == 1) { + val = ASIC_CTRL_DS_TMR_HIGH_RES_VAL; } bus_w(ASIC_CTRL_REG, (bus_r(ASIC_CTRL_REG) & ~ASIC_CTRL_DS_TMR_MSK) | val); - LOG(logINFO, ("Configured ASIC Timer [0x%x]\n", bus_r(ASIC_CTRL_REG))); + uint32_t retval = ((bus_r(ASIC_CTRL_REG) & ASIC_CTRL_DS_TMR_MSK) >> + ASIC_CTRL_DS_TMR_OFST); + LOG(logINFO, ("Configured ASIC DS Timer [0x%x]\n", retval)); + + LOG(logINFO, ("asic reg:0x%x\n", bus_r(ASIC_CTRL_REG))); } int setReadoutSpeed(int val) { @@ -2652,22 +2696,26 @@ int getFilterResistor() { } int setFilterResistor(int value) { + if (value != 0 && value != 1) { + LOG(logERROR, ("Invalid value for Filter Resistor: %d\n", value)); + return FAIL; + } + // lower resistor if (value == 0) { LOG(logINFO, ("Setting Lower Filter Resistor\n")); bus_w(CONFIG_V11_REG, bus_r(CONFIG_V11_REG) | CONFIG_V11_FLTR_RSSTR_SMLR_MSK); - return OK; } // higher resistor else if (value == 1) { LOG(logINFO, ("Setting Higher Filter Resistor\n")); bus_w(CONFIG_V11_REG, bus_r(CONFIG_V11_REG) & ~CONFIG_V11_FLTR_RSSTR_SMLR_MSK); - return OK; } - LOG(logERROR, ("Could not set Filter Resistor. Invalid value %d\n", value)); - return FAIL; + + configureAsicDSTimer(); + return OK; } int getNumberOfFilterCells() { @@ -2681,8 +2729,8 @@ int getNumberOfFilterCells() { // flip all contents of register //TODO FIRMWARE FIX regval ^= BIT32_MASK; #endif - uint32_t retval = - (regval & CONFIG_V11_FLTR_CLL_MSK) >> CONFIG_V11_FLTR_CLL_OFST; + uint32_t retval = (regval & CONFIG_V11_STATUS_FLTR_CLL_MSK) >> + CONFIG_V11_STATUS_FLTR_CLL_OFST; // count number of bits = which icell return (__builtin_popcount(retval)); } @@ -2919,6 +2967,11 @@ void setPedestalMode(int enable, uint8_t frames, uint16_t loops) { } } +void enableStepReduction() { + LOG(logINFO, ("Enabling step reduction\n")); + bus_w(CONFIG_V11_REG, bus_r(CONFIG_V11_REG) | CONFIG_V12_RST_STP_RDCTN_MSK); +} + int setTimingInfoDecoder(enum timingInfoDecoder val) { switch (val) { case SWISSFEL: @@ -2962,11 +3015,17 @@ int getElectronCollectionMode() { void setElectronCollectionMode(int enable) { LOG(logINFO, ("Setting Collection Mode to %s\n", enable == 0 ? "Hole" : "Electron")); + + uint32_t val = bus_r(DAQ_REG); + uint32_t mask = + DAQ_ELCTRN_CLLCTN_MDE_MSK | DAQ_CDS_BYPASS_MSK | DAQ_CDS_RESET_MSK; if (enable) { - bus_w(DAQ_REG, bus_r(DAQ_REG) | DAQ_ELCTRN_CLLCTN_MDE_MSK); + val |= mask; + LOG(logINFO, ("\tCDS reset and bypassed\n")); } else { - bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_ELCTRN_CLLCTN_MDE_MSK); + val &= ~mask; } + bus_w(DAQ_REG, val); configureChip(); } @@ -3070,8 +3129,8 @@ void *start_timer(void *arg) { const int maxRows = MAX_ROWS_PER_READOUT; int readNRows = getReadNRows(); if (readNRows == -1) { - LOG(logERROR, - ("number of rows is -1. Assuming no partial readout (#rows).\n")); + LOG(logERROR, ("number of rows is -1. Assuming no partial readout " + "(#rows).\n")); readNRows = MAX_ROWS_PER_READOUT; } const int packetsPerFrame = @@ -3304,7 +3363,8 @@ int softwareTrigger(int block) { LOG(logINFO, ("Sending Software Trigger\n")); bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_SOFTWARE_TRIGGER_MSK); bus_w(CONTROL_REG, bus_r(CONTROL_REG) & ~CONTROL_SOFTWARE_TRIGGER_MSK); - // wait to make sure its out of this state and even 'wait for start frame' + // wait to make sure its out of this state and even 'wait for start + // frame' usleep(100); #ifndef VIRTUAL diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h index 64bd7f71e..e65ed3d37 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h @@ -63,6 +63,7 @@ int setChipVersionIntFromConfigFile(int val, char *mess); // for backward compatibility int setChipVersionStringFromConfigFile(char *cval, char *mess); int setChipIndex(enum CHIPINDEX ind, char *mess); +enum CHIPINDEX getChipIndex(); int validateChipIndex(enum CHIPINDEX ind, char *mess); void setChipIndexAllowedFeatures(); int setChipVersionInFPGA(char *mess); @@ -189,12 +190,15 @@ bool hasCurrentSourceNormalFeature(); bool hasCurrentSource64BitSelectionFeature(); bool hasCurrentSourceReverseBitsSelectionFeature(); bool hasStorageCellStartInChipConfig(); +bool hasStepReductionFeature(); bool isChipConfigured(); void configureChip(); int autoCompDisable(int on); int setComparatorDisableTime(int64_t val); int64_t getComparatorDisableTime(); void configureASICTimer(); +void configureAsicPrechargeTimer(); +void configureAsicDSTimer(); int setReadoutSpeed(int val); int getReadoutSpeed(int *retval); int setPhase(enum CLKINDEX ind, int val, int degrees); @@ -220,6 +224,7 @@ uint64_t getSelectCurrentSource(); int getPedestalMode(); void getPedestalParameters(uint8_t *frames, uint16_t *loops); void setPedestalMode(int enable, uint8_t frames, uint16_t loops); +void enableStepReduction(); int setTimingInfoDecoder(enum timingInfoDecoder val); int getTimingInfoDecoder(enum timingInfoDecoder *retval); int getElectronCollectionMode(); diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h index aaf8fd7fc..98e474212 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -37,6 +37,9 @@ #define CONFIG_FILE ("config_jungfrau.txt") /** Default Parameters */ +#define DEFAULT_AUTO_COMP_DISABLE (0) +#define DEFAULT_COMP_DISABLE_TIME_v1_0 (5 * 1000) // 5us +#define DEFAULT_COMP_DISABLE_TIME (2 * 1000) // 2us #define DEFAULT_NUM_FRAMES (100 * 1000 * 1000) #define DEFAULT_STARTING_FRAME_NUMBER (1) #define DEFAULT_NUM_CYCLES (1) @@ -55,7 +58,7 @@ #define DEFAULT_STRG_CLL_STRT_CHIP11 (0x3) #define DEFAULT_STRG_CLL_DLY (0) #define DEFAULT_FLIP_ROWS (0) -#define DEFAULT_FILTER_RESISTOR (1) // higher resistor +#define DEFAULT_FILTER_RESISTOR (0) // lower resistor #define DEFAULT_FILTER_CELL (0) #define DEFAULT_PEDESTAL_MODE (0) #define DEFAULT_PEDESTAL_FRAMES (1) @@ -236,6 +239,8 @@ enum MASTERINDEX { MASTER_HARDWARE, OW_MASTER, OW_SLAVE }; { 1450, 480, 420 } #define SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS \ { 1550, 450, 620 } +#define SPECIAL_DEFAULT_V1_2_GAIN_VALS \ + { 1500, 480, 460 } enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G }; enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS }; diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 1d6b51aef..cac509a27 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -2277,7 +2277,7 @@ int set_num_additional_storage_cells(int file_des) { #else // only set if (Server_VerifyLock() == OK) { - if (!hasStorageCellsFeature()) { + if (!hasStorageCellsFeature() || getChipIndex() > v1_1) { ret = FAIL; sprintf(mess, "Cannot set addl. number of storage cells for this " "chip version\n"); diff --git a/slsDetectorSoftware/tests/Caller/test-Caller-jungfrau.cpp b/slsDetectorSoftware/tests/Caller/test-Caller-jungfrau.cpp index 08bb564b0..19fdbad66 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller-jungfrau.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller-jungfrau.cpp @@ -277,8 +277,8 @@ TEST_CASE("extrastoragecells", "[.detectorintegration]") { auto det_type = det.getDetectorType().squash(); if (det_type == defs::JUNGFRAU) { auto chipVersion = chipVersionToX10(det.getChipVersion().squash()); - // chip version 1.0 and 1.2 - if (chipVersion == 10 || chipVersion == 12) { + // currently only chip version 1.0, later firmware for 1.2 + if (chipVersion == 10) { //} || chipVersion == 12) { auto prev_val = det.getNumberOfAdditionalStorageCells().tsquash( "inconsistent #additional storage cells to test"); { diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h index 73955104c..7828cff07 100644 --- a/slsSupportLib/include/sls/versionAPI.h +++ b/slsSupportLib/include/sls/versionAPI.h @@ -8,6 +8,6 @@ #define APIMOENCH "0.0.0 0x260424" #define APIEIGER "0.0.0 0x260807" #define APIXILINXCTB "0.0.0 0x260813" -#define APIJUNGFRAU "0.0.0 0x260902" +#define APIJUNGFRAU "0.0.0 0x261002" #define APIMYTHEN3 "0.0.0 0x260506" #define APIMATTERHORN "0.0.0 0x260529" From dd5b2360d6f55b76eaf9cfdd0a940876bb5d0159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Mon, 5 Oct 2026 12:10:23 +0200 Subject: [PATCH 05/12] Fix/fifo race (#1591) * fix race condition in Fifo::FreeAddress --- slsReceiverSoftware/src/Fifo.cpp | 5 ++++- slsReceiverSoftware/src/Fifo.h | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/slsReceiverSoftware/src/Fifo.cpp b/slsReceiverSoftware/src/Fifo.cpp index 1bec44e12..6740c8ae2 100644 --- a/slsReceiverSoftware/src/Fifo.cpp +++ b/slsReceiverSoftware/src/Fifo.cpp @@ -81,7 +81,10 @@ void Fifo::DestroyFifos() { fifoStream = nullptr; } -void Fifo::FreeAddress(char *&address) { fifoFree->push(address); } +void Fifo::FreeAddress(char *&address) { + std::lock_guard lock(fifoFreeMutex); + fifoFree->push(address); +} void Fifo::GetNewAddress(char *&address) { int temp = fifoFree->getDataValue(); diff --git a/slsReceiverSoftware/src/Fifo.h b/slsReceiverSoftware/src/Fifo.h index 729ce368b..fe9f3cf1e 100644 --- a/slsReceiverSoftware/src/Fifo.h +++ b/slsReceiverSoftware/src/Fifo.h @@ -16,6 +16,7 @@ #include "sls/sls_detector_defs.h" #include +#include namespace sls { @@ -52,6 +53,9 @@ class Fifo : private virtual slsDetectorDefs { int fifoDepth; std::atomic status_fifoBound; std::atomic status_fifoFree; + /** fifoFree has several producers, CircularFifo allows only one. + * Aligned to avoid false sharing with the members above */ + alignas(128) std::mutex fifoFreeMutex; }; } // namespace sls From 0e82aed80de72d545fc79e3eecbc43d33c8eb0a8 Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 6 Oct 2026 12:11:29 +0200 Subject: [PATCH 06/12] removed option sls_use_server from cmake --- CMakeLists.txt | 10 ++-------- slsDetectorServers/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ea532cee..7ce785e31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,7 +219,6 @@ option(SLS_BUILD_SHARED_LIBRARIES "Build shared libaries" OFF) option(SLS_USE_TEXTCLIENT "Text Client" ON) option(SLS_USE_DETECTOR "Detector libs" ON) option(SLS_USE_RECEIVER "Receiver" ON) -option(SLS_USE_SERVER "Server" ON) option(SLS_USE_RECEIVER_BINARIES "Receiver binaries" ON) option(SLS_USE_GUI "GUI" OFF) option(SLS_USE_SIMULATOR "Simulator" OFF) @@ -258,7 +257,6 @@ if(SLS_BUILD_ONLY_MATTERHORN) set(SLS_USE_DETECTOR ON CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER_BINARIES OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) - set(SLS_USE_SERVER ON CACHE BOOL "Enable building cpp server" FORCE) set(SLS_USE_MATTERHORN ON CACHE BOOL "Enable Matterhorn" FORCE) endif() @@ -438,11 +436,6 @@ if (SLS_USE_DETECTOR OR SLS_USE_TEXTCLIENT) add_subdirectory(slsDetectorSoftware) endif() -# TODO refactor with simulators -if (SLS_USE_SERVER) - add_subdirectory(slsDetectorServers/slsDetectorServer_cpp) -endif() - if (SLS_USE_RECEIVER) add_subdirectory(slsReceiverSoftware) endif (SLS_USE_RECEIVER) @@ -457,7 +450,8 @@ if (SLS_USE_SIMULATOR) endif (SLS_USE_SIMULATOR) # cant add_subdirectory twice -if (SLS_USE_MATTERHORN AND !SLS_USE_SIMULATOR) +if (SLS_USE_MATTERHORN AND NOT SLS_USE_SIMULATOR) + add_subdirectory(slsDetectorServers/slsDetectorServer_cpp) add_subdirectory(slsDetectorServers/matterhornServer) endif() diff --git a/slsDetectorServers/CMakeLists.txt b/slsDetectorServers/CMakeLists.txt index 3a04f2bf9..acf15467d 100644 --- a/slsDetectorServers/CMakeLists.txt +++ b/slsDetectorServers/CMakeLists.txt @@ -8,6 +8,8 @@ install(TARGETS slsProjectCSettings ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) + +add_subdirectory(slsDetectorServer_cpp) add_subdirectory(ctbDetectorServer) add_subdirectory(xilinx_ctbDetectorServer) add_subdirectory(eigerDetectorServer) From d18a8bf64f2fe296f58f9a1297fe8a1eb9ce528f Mon Sep 17 00:00:00 2001 From: Alice Date: Tue, 6 Oct 2026 12:14:06 +0200 Subject: [PATCH 07/12] Revert "removed option sls_use_server from cmake" This reverts commit 0e82aed80de72d545fc79e3eecbc43d33c8eb0a8. --- CMakeLists.txt | 10 ++++++++-- slsDetectorServers/CMakeLists.txt | 2 -- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ce785e31..5ea532cee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,7 @@ option(SLS_BUILD_SHARED_LIBRARIES "Build shared libaries" OFF) option(SLS_USE_TEXTCLIENT "Text Client" ON) option(SLS_USE_DETECTOR "Detector libs" ON) option(SLS_USE_RECEIVER "Receiver" ON) +option(SLS_USE_SERVER "Server" ON) option(SLS_USE_RECEIVER_BINARIES "Receiver binaries" ON) option(SLS_USE_GUI "GUI" OFF) option(SLS_USE_SIMULATOR "Simulator" OFF) @@ -257,6 +258,7 @@ if(SLS_BUILD_ONLY_MATTERHORN) set(SLS_USE_DETECTOR ON CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER_BINARIES OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) + set(SLS_USE_SERVER ON CACHE BOOL "Enable building cpp server" FORCE) set(SLS_USE_MATTERHORN ON CACHE BOOL "Enable Matterhorn" FORCE) endif() @@ -436,6 +438,11 @@ if (SLS_USE_DETECTOR OR SLS_USE_TEXTCLIENT) add_subdirectory(slsDetectorSoftware) endif() +# TODO refactor with simulators +if (SLS_USE_SERVER) + add_subdirectory(slsDetectorServers/slsDetectorServer_cpp) +endif() + if (SLS_USE_RECEIVER) add_subdirectory(slsReceiverSoftware) endif (SLS_USE_RECEIVER) @@ -450,8 +457,7 @@ if (SLS_USE_SIMULATOR) endif (SLS_USE_SIMULATOR) # cant add_subdirectory twice -if (SLS_USE_MATTERHORN AND NOT SLS_USE_SIMULATOR) - add_subdirectory(slsDetectorServers/slsDetectorServer_cpp) +if (SLS_USE_MATTERHORN AND !SLS_USE_SIMULATOR) add_subdirectory(slsDetectorServers/matterhornServer) endif() diff --git a/slsDetectorServers/CMakeLists.txt b/slsDetectorServers/CMakeLists.txt index acf15467d..3a04f2bf9 100644 --- a/slsDetectorServers/CMakeLists.txt +++ b/slsDetectorServers/CMakeLists.txt @@ -8,8 +8,6 @@ install(TARGETS slsProjectCSettings ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) - -add_subdirectory(slsDetectorServer_cpp) add_subdirectory(ctbDetectorServer) add_subdirectory(xilinx_ctbDetectorServer) add_subdirectory(eigerDetectorServer) From 3ed9d0a07bffa37310014309fe767a01d998d31e Mon Sep 17 00:00:00 2001 From: AliceMazzoleni99 Date: Tue, 6 Oct 2026 15:32:56 +0200 Subject: [PATCH 08/12] removed option sls_use_server (#1602) * removed option sls_use_server * refactor include logic to slsDetectorServers CMake --- CMakeLists.txt | 15 ++------------- slsDetectorServers/CMakeLists.txt | 23 +++++++++++++++-------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ea532cee..8657e2a68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,7 +219,6 @@ option(SLS_BUILD_SHARED_LIBRARIES "Build shared libaries" OFF) option(SLS_USE_TEXTCLIENT "Text Client" ON) option(SLS_USE_DETECTOR "Detector libs" ON) option(SLS_USE_RECEIVER "Receiver" ON) -option(SLS_USE_SERVER "Server" ON) option(SLS_USE_RECEIVER_BINARIES "Receiver binaries" ON) option(SLS_USE_GUI "GUI" OFF) option(SLS_USE_SIMULATOR "Simulator" OFF) @@ -258,7 +257,6 @@ if(SLS_BUILD_ONLY_MATTERHORN) set(SLS_USE_DETECTOR ON CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) set(SLS_USE_RECEIVER_BINARIES OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE) - set(SLS_USE_SERVER ON CACHE BOOL "Enable building cpp server" FORCE) set(SLS_USE_MATTERHORN ON CACHE BOOL "Enable Matterhorn" FORCE) endif() @@ -438,11 +436,6 @@ if (SLS_USE_DETECTOR OR SLS_USE_TEXTCLIENT) add_subdirectory(slsDetectorSoftware) endif() -# TODO refactor with simulators -if (SLS_USE_SERVER) - add_subdirectory(slsDetectorServers/slsDetectorServer_cpp) -endif() - if (SLS_USE_RECEIVER) add_subdirectory(slsReceiverSoftware) endif (SLS_USE_RECEIVER) @@ -452,14 +445,10 @@ if (SLS_USE_GUI) add_subdirectory(slsDetectorGui) endif (SLS_USE_GUI) -if (SLS_USE_SIMULATOR) +if (SLS_USE_SIMULATOR OR SLS_USE_MATTERHORN) add_subdirectory(slsDetectorServers) -endif (SLS_USE_SIMULATOR) +endif (SLS_USE_SIMULATOR OR SLS_USE_MATTERHORN) -# cant add_subdirectory twice -if (SLS_USE_MATTERHORN AND !SLS_USE_SIMULATOR) - add_subdirectory(slsDetectorServers/matterhornServer) -endif() if (SLS_USE_PYTHON) find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED) diff --git a/slsDetectorServers/CMakeLists.txt b/slsDetectorServers/CMakeLists.txt index 3a04f2bf9..2aafa0a78 100644 --- a/slsDetectorServers/CMakeLists.txt +++ b/slsDetectorServers/CMakeLists.txt @@ -8,12 +8,19 @@ install(TARGETS slsProjectCSettings ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) -add_subdirectory(ctbDetectorServer) -add_subdirectory(xilinx_ctbDetectorServer) -add_subdirectory(eigerDetectorServer) -add_subdirectory(jungfrauDetectorServer) -add_subdirectory(mythen3DetectorServer) -add_subdirectory(gotthard2DetectorServer) -add_subdirectory(moenchDetectorServer) -add_subdirectory(matterhornServer) +add_subdirectory(slsDetectorServer_cpp) + +if(SLS_USE_SIMULATOR) + add_subdirectory(ctbDetectorServer) + add_subdirectory(xilinx_ctbDetectorServer) + add_subdirectory(eigerDetectorServer) + add_subdirectory(jungfrauDetectorServer) + add_subdirectory(mythen3DetectorServer) + add_subdirectory(gotthard2DetectorServer) + add_subdirectory(moenchDetectorServer) +endif() + +if(SLS_USE_MATTERHORN OR SLS_USE_SIMULATOR) + add_subdirectory(matterhornServer) +endif() \ No newline at end of file From bf6c5f2c8a155ee8a262e4ea437f85f799ffcd73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Tue, 6 Oct 2026 20:09:56 +0200 Subject: [PATCH 09/12] port of RPM building and gitea workflows (#1601) --- .gitea/workflows/docker-rh8-build-rpm.yml | 97 +++++++++++++++++++ .gitea/workflows/docker-rh9-build-rpm.yml | 93 ++++++++++++++++++ CMakeLists.txt | 19 +++- cmake/SlsInstallExecutable.cmake | 30 ++++++ docs/src/installation.rst | 46 +++++++++ .../jungfrauExecutables/CMakeLists.txt | 4 +- .../moenchExecutables/CMakeLists.txt | 15 +-- slsDetectorGui/CMakeLists.txt | 6 +- .../ctbDetectorServer/CMakeLists.txt | 4 +- .../eigerDetectorServer/CMakeLists.txt | 4 +- .../gotthard2DetectorServer/CMakeLists.txt | 4 +- .../jungfrauDetectorServer/CMakeLists.txt | 3 +- .../matterhornServer/CMakeLists.txt | 8 +- .../moenchDetectorServer/CMakeLists.txt | 3 +- .../mythen3DetectorServer/CMakeLists.txt | 4 +- .../xilinx_ctbDetectorServer/CMakeLists.txt | 4 +- slsDetectorSoftware/CMakeLists.txt | 16 +-- slsReceiverSoftware/CMakeLists.txt | 16 +-- 18 files changed, 298 insertions(+), 78 deletions(-) create mode 100644 .gitea/workflows/docker-rh8-build-rpm.yml create mode 100644 .gitea/workflows/docker-rh9-build-rpm.yml create mode 100644 cmake/SlsInstallExecutable.cmake diff --git a/.gitea/workflows/docker-rh8-build-rpm.yml b/.gitea/workflows/docker-rh8-build-rpm.yml new file mode 100644 index 000000000..8ac0aa501 --- /dev/null +++ b/.gitea/workflows/docker-rh8-build-rpm.yml @@ -0,0 +1,97 @@ +name: Build RPMs on RHEL8 docker image + +on: + workflow_dispatch: + inputs: + deploy: + description: "Upload the RPMs to the Gitea package registry" + type: boolean + default: false + +permissions: + contents: read + +jobs: + build: + runs-on: "ubuntu-latest" + container: + image: gitea.psi.ch/detectors/rhel8-detectors-dev + steps: + - name: Clone repository + run: | + git lfs install --skip-smudge + echo Cloning ${{ github.ref_name }} + git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} . + + - name: Install build dependencies + run: | + dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \ + libpng-devel zlib-devel expat-devel libtiff-devel + + - name: Build with versioned binaries + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DSLS_USE_GUI=ON \ + -DSLS_USE_MOENCH=ON \ + -DSLS_INSTALL_VERSIONED_BINARIES=ON + cmake --build build -j 2 + + - name: Build RPMs + run: | + cpack --config build/CPackConfig.cmake -G RPM \ + -D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms + + - name: Inspect RPMs + run: | + for rpm in build/rpms/*.rpm; do + echo "::group::$rpm" + rpm -qpi "$rpm" + rpm -qpl "$rpm" + rpm -qpR "$rpm" + echo "::endgroup::" + done + + - name: Install RPMs and check versioned binaries + run: | + VERSION=$(cat VERSION) + dnf -y install build/rpms/*.rpm + for component in cli receiver zmq gui; do + rpm -q slsdetectorpackage-${VERSION}-${component} + done + for exe in sls_detector_get sls_detector_put slsReceiver \ + slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do + test -x /usr/bin/${exe}-${VERSION} + test ! -e /usr/bin/${exe} + done + sls_detector_get-${VERSION} --version + slsReceiver-${VERSION} --version + + - name: Upload RPMs to Gitea + if: ${{ inputs.deploy }} + env: + SERVICE: ${{ secrets.SERVICE }} + run: | + url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el8 + upload() { + curl --silent --show-error --output /tmp/upload-response \ + --write-out "%{http_code}" \ + --user "detectors-gitea:${SERVICE}" \ + --upload-file "$1" "$url/upload" + } + for rpm in build/rpms/*.rpm; do + echo "Uploading $rpm" + code=$(upload "$rpm") + if [ "$code" = 409 ]; then + echo "Already in the registry, replacing" + curl --silent --show-error --fail -X DELETE \ + --user "detectors-gitea:${SERVICE}" \ + "$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")" + code=$(upload "$rpm") + fi + if [ "$code" != 201 ]; then + echo "Upload failed with HTTP $code" + cat /tmp/upload-response + exit 1 + fi + done diff --git a/.gitea/workflows/docker-rh9-build-rpm.yml b/.gitea/workflows/docker-rh9-build-rpm.yml new file mode 100644 index 000000000..09778b0f0 --- /dev/null +++ b/.gitea/workflows/docker-rh9-build-rpm.yml @@ -0,0 +1,93 @@ +name: Build RPMs on RHEL9 docker image + +on: + workflow_dispatch: + inputs: + deploy: + description: "Upload the RPMs to the Gitea package registry" + type: boolean + default: false + +permissions: + contents: read + +jobs: + build: + runs-on: "ubuntu-latest" + container: + image: gitea.psi.ch/detectors/rhel9-detectors-dev + steps: + - uses: actions/checkout@v4 + + - name: Install build dependencies + run: | + dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \ + libpng-devel zlib-devel expat-devel libtiff-devel + + - name: Build with versioned binaries + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DSLS_USE_GUI=ON \ + -DSLS_USE_MOENCH=ON \ + -DSLS_INSTALL_VERSIONED_BINARIES=ON + cmake --build build -j 2 + + - name: Build RPMs + run: | + cpack --config build/CPackConfig.cmake -G RPM \ + -D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms + + - name: Inspect RPMs + run: | + for rpm in build/rpms/*.rpm; do + echo "::group::$rpm" + rpm -qpi "$rpm" + rpm -qpl "$rpm" + rpm -qpR "$rpm" + echo "::endgroup::" + done + + - name: Install RPMs and check versioned binaries + run: | + VERSION=$(cat VERSION) + dnf -y install build/rpms/*.rpm + for component in cli receiver zmq gui; do + rpm -q slsdetectorpackage-${VERSION}-${component} + done + for exe in sls_detector_get sls_detector_put slsReceiver \ + slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do + test -x /usr/bin/${exe}-${VERSION} + test ! -e /usr/bin/${exe} + done + sls_detector_get-${VERSION} --version + slsReceiver-${VERSION} --version + + - name: Upload RPMs to Gitea + if: ${{ inputs.deploy }} + env: + SERVICE: ${{ secrets.SERVICE }} + run: | + url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el9 + upload() { + curl --silent --show-error --output /tmp/upload-response \ + --write-out "%{http_code}" \ + --user "detectors-gitea:${SERVICE}" \ + --upload-file "$1" "$url/upload" + } + for rpm in build/rpms/*.rpm; do + echo "Uploading $rpm" + code=$(upload "$rpm") + if [ "$code" = 409 ]; then + echo "Already in the registry, replacing" + curl --silent --show-error --fail -X DELETE \ + --user "detectors-gitea:${SERVICE}" \ + "$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")" + code=$(upload "$rpm") + fi + if [ "$code" != 201 ]; then + echo "Upload failed with HTTP $code" + cat /tmp/upload-response + exit 1 + fi + done diff --git a/CMakeLists.txt b/CMakeLists.txt index 8657e2a68..c5a9cd54c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ endif() include(cmake/project_version.cmake) include(cmake/SlsAddFlag.cmake) include(cmake/helpers.cmake) +include(cmake/SlsInstallExecutable.cmake) find_package(Threads REQUIRED) @@ -234,7 +235,7 @@ option(SLS_DEVEL_HEADERS "install headers for devel" OFF) option(SLS_USE_MOENCH "compile zmq and post processing for Moench" OFF) option(SLS_USE_JUNGFRAU "compile post processing for Jungfrau" OFF) option(SLS_USE_MATTERHORN "compile matterhorn server" OFF) -option(SLS_INSTALL_VERSIONED_BINARIES "Add version number to binaries on install" OFF) #Needed for multi version RPM +option(SLS_INSTALL_VERSIONED_BINARIES "Add version number to installed executables and RPM package names" OFF) option(SLS_TREAT_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) #Convenience option to switch off defaults when building Moench binaries only @@ -520,14 +521,18 @@ set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DAQ software for PSI developed detectors") # RPM-specific settings +string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME) +if(SLS_INSTALL_VERSIONED_BINARIES) + string(APPEND CPACK_RPM_PACKAGE_NAME "-${PROJECT_VERSION}") +endif() set(CPACK_GENERATOR "RPM") -set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") +set(CPACK_RPM_FILE_NAME + "${PROJECT_NAME_LOWER}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm") set(CPACK_RPM_PACKAGE_LICENSE "LGPL-3.0") set(CPACK_RPM_PACKAGE_GROUP "Applications/System") set(CPACK_RPM_PACKAGE_RELEASE 1) # Adds %{?dist} to the RPM Release field set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) -set(CPACK_RPM_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") set(CPACK_RPM_COMPONENT_INSTALL ON) @@ -537,4 +542,10 @@ set(CPACK_RPM_GUI_PACKAGE_REQUIRES #control which RPMs are generated set(CPACK_COMPONENTS_ALL cli receiver zmq gui) -include(CPack) \ No newline at end of file +# Keep the project version only once in filenames; RPM expands its metadata. +foreach(component IN LISTS CPACK_COMPONENTS_ALL) + string(TOUPPER "${component}" component_upper) + set(CPACK_RPM_${component_upper}_FILE_NAME + "${PROJECT_NAME_LOWER}-${component}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm") +endforeach() +include(CPack) diff --git a/cmake/SlsInstallExecutable.cmake b/cmake/SlsInstallExecutable.cmake new file mode 100644 index 000000000..e8704d1ea --- /dev/null +++ b/cmake/SlsInstallExecutable.cmake @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: LGPL-3.0-or-other +# Copyright (C) 2026 Contributors to the SLS Detector Package + +function(sls_install_executable target) + cmake_parse_arguments(ARG "" "DESTINATION;COMPONENT;EXPORT" "" ${ARGN}) + if(NOT ARG_DESTINATION) + set(ARG_DESTINATION "${CMAKE_INSTALL_BINDIR}") + endif() + + set(install_args DESTINATION "${ARG_DESTINATION}") + if(ARG_COMPONENT) + list(APPEND install_args COMPONENT "${ARG_COMPONENT}") + endif() + + if(SLS_INSTALL_VERSIONED_BINARIES) + install(PROGRAMS "$" + ${install_args} + RENAME "$-${PROJECT_VERSION}${CMAKE_EXECUTABLE_SUFFIX}" + ) + else() + set(export_args) + if(ARG_EXPORT) + list(APPEND export_args EXPORT "${ARG_EXPORT}") + endif() + install(TARGETS ${target} + ${export_args} + RUNTIME ${install_args} + ) + endif() +endfunction() diff --git a/docs/src/installation.rst b/docs/src/installation.rst index 926248843..43506b25d 100644 --- a/docs/src/installation.rst +++ b/docs/src/installation.rst @@ -240,6 +240,52 @@ Example cmake options Comment For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. ` +3.2.3. Build RPM packages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +CPack builds separate RPMs for the command line tools (``cli``), receiver +executables (``receiver``), Moench processing tools (``zmq``), and GUI (``gui``). +Install ``rpm-build`` and the dependencies for the selected features, and build +on the target distribution or a matching container. + +For example, to package the command line tools, receiver and GUI: + +.. code-block:: bash + + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr -DSLS_USE_GUI=ON \ + -DSLS_INSTALL_VERSIONED_BINARIES=ON + cmake --build build -j4 + cpack --config build/CPackConfig.cmake -G RPM \ + -D 'CPACK_COMPONENTS_ALL=cli;receiver;gui' -B build + +Select only components enabled in the build. Add ``-DSLS_USE_MOENCH=ON`` and +the ``zmq`` component to package the Moench tools. + +``SLS_INSTALL_VERSIONED_BINARIES=ON`` includes the project version in the RPM +package names, for example ``slsdetectorpackage-10.1.0-cli`` and +``slsdetectorpackage-10.1.0-gui``. Installed executables also receive a version +suffix, such as ``sls_detector_get-10.1.0`` and ``slsDetectorGui-10.1.0``. This +allows RPMs for different project versions to be installed side by side. +RPM revisions of the same project version retain the same package names and +can be upgraded normally. + +RPM filenames include the version once, for example +``slsdetectorpackage-cli-10.1.0-1.fc44.x86_64.rpm``. The package's internal name +remains ``slsdetectorpackage-10.1.0-cli`` and its RPM version remains ``10.1.0``. + +The option also applies to Jungfrau processing tools and virtual detector +servers installed with ``cmake --install``. These are outside the current RPM +component selection. Executables in the build directory keep their original +names. With the option set to ``OFF`` (the default), installed executables and +RPM package names omit the project version. + +The RPM components contain executables; Python bindings, libraries and headers +are not included. A full ``cmake --install`` still installs libraries and +headers at their usual paths, so use separate prefixes for full installations +of different versions. + + 3.3. Build on old distributions using conda ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/slsDetectorCalibration/jungfrauExecutables/CMakeLists.txt b/slsDetectorCalibration/jungfrauExecutables/CMakeLists.txt index dc0f0690f..6f1fa6fd1 100644 --- a/slsDetectorCalibration/jungfrauExecutables/CMakeLists.txt +++ b/slsDetectorCalibration/jungfrauExecutables/CMakeLists.txt @@ -92,7 +92,5 @@ foreach(exe ${JUNGFRAU_EXECUTABLES}) set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) endif() - + sls_install_executable(${exe} DESTINATION bin) endforeach(exe ${JUNGFRAU_EXECUTABLES}) - -install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin) \ No newline at end of file diff --git a/slsDetectorCalibration/moenchExecutables/CMakeLists.txt b/slsDetectorCalibration/moenchExecutables/CMakeLists.txt index 55faa558d..8379f5eb9 100644 --- a/slsDetectorCalibration/moenchExecutables/CMakeLists.txt +++ b/slsDetectorCalibration/moenchExecutables/CMakeLists.txt @@ -92,19 +92,6 @@ foreach(exe ${MOENCH_EXECUTABLES}) set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) endif() - # Mainly for RPMs to enable side by side installations of different versions - if(SLS_INSTALL_VERSIONED_BINARIES) - install(PROGRAMS "$" - DESTINATION bin - RENAME "$-${PROJECT_VERSION}" - COMPONENT zmq - ) - else() - install(TARGETS ${exe} - DESTINATION bin - COMPONENT zmq - ) - endif() + sls_install_executable(${exe} DESTINATION bin COMPONENT zmq) endforeach(exe ${MOENCH_EXECUTABLES}) - diff --git a/slsDetectorGui/CMakeLists.txt b/slsDetectorGui/CMakeLists.txt index 992bfe3ef..b78ccdd95 100755 --- a/slsDetectorGui/CMakeLists.txt +++ b/slsDetectorGui/CMakeLists.txt @@ -119,8 +119,4 @@ if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE) set_property(TARGET slsDetectorGui PROPERTY INTERPROCEDURAL_OPTIMIZATION True) endif() -install(TARGETS slsDetectorGui - # EXPORT "${TARGETS_EXPORT_NAME}" #do not export gui - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT gui -) - +sls_install_executable(slsDetectorGui COMPONENT gui) diff --git a/slsDetectorServers/ctbDetectorServer/CMakeLists.txt b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt index 1a9c4b5af..438930ffa 100644 --- a/slsDetectorServers/ctbDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt @@ -44,6 +44,4 @@ set_target_properties(ctbDetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS ctbDetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +sls_install_executable(ctbDetectorServer_virtual) diff --git a/slsDetectorServers/eigerDetectorServer/CMakeLists.txt b/slsDetectorServers/eigerDetectorServer/CMakeLists.txt index dd0404aac..5abe8bdf8 100644 --- a/slsDetectorServers/eigerDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/eigerDetectorServer/CMakeLists.txt @@ -38,9 +38,7 @@ set_target_properties(eigerDetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS eigerDetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +sls_install_executable(eigerDetectorServer_virtual) configure_file(config_eiger.txt ${CMAKE_BINARY_DIR}/bin/config_eiger.txt COPYONLY) diff --git a/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt b/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt index 7a5201c0e..be01f273f 100644 --- a/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt +++ b/slsDetectorServers/gotthard2DetectorServer/CMakeLists.txt @@ -39,9 +39,7 @@ set_target_properties(gotthard2DetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS gotthard2DetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +sls_install_executable(gotthard2DetectorServer_virtual) configure_file(config_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/config_gotthard2.txt COPYONLY) configure_file(detid_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/detid_gotthard2.txt COPYONLY) diff --git a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt index 678cea963..55ff80edc 100644 --- a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt @@ -41,9 +41,8 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES #target_compile_options(jungfrauDetectorServer_virtual PRIVATE -m32) #target_link_options(jungfrauDetectorServer_virtual PRIVATE -m32) -install(TARGETS jungfrauDetectorServer_virtual +sls_install_executable(jungfrauDetectorServer_virtual EXPORT "${TARGETS_EXPORT_NAME}" - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) configure_file(config_jungfrau.txt ${CMAKE_BINARY_DIR}/bin/config_jungfrau.txt COPYONLY) diff --git a/slsDetectorServers/matterhornServer/CMakeLists.txt b/slsDetectorServers/matterhornServer/CMakeLists.txt index 34d539b08..e0a55f5e6 100644 --- a/slsDetectorServers/matterhornServer/CMakeLists.txt +++ b/slsDetectorServers/matterhornServer/CMakeLists.txt @@ -41,9 +41,7 @@ if(SLS_USE_SIMULATOR) RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) - install(TARGETS matterhornDetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) + sls_install_executable(matterhornDetectorServer_virtual) endif() # maybe better to have a else if build with simulators on one always uses the virtual server in MatterhornApp if(SLS_USE_MATTERHORN) @@ -91,9 +89,7 @@ if(SLS_USE_MATTERHORN) RUNTIME_OUTPUT_DIRECTORY ${RUNTIME_OUTPUT_DIRECTORY} ) - install(TARGETS matterhornDetectorServer - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) + sls_install_executable(matterhornDetectorServer) endif() if(SLS_USE_TESTS) diff --git a/slsDetectorServers/moenchDetectorServer/CMakeLists.txt b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt index dc664d7e4..2ee45681b 100644 --- a/slsDetectorServers/moenchDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt @@ -37,9 +37,8 @@ set_target_properties(moenchDetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS moenchDetectorServer_virtual +sls_install_executable(moenchDetectorServer_virtual EXPORT "${TARGETS_EXPORT_NAME}" - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) configure_file(detid_moench.txt ${CMAKE_BINARY_DIR}/bin/detid_moench.txt COPYONLY) diff --git a/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt b/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt index 10cffa217..6a942ddb4 100644 --- a/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt +++ b/slsDetectorServers/mythen3DetectorServer/CMakeLists.txt @@ -41,9 +41,7 @@ set_target_properties(mythen3DetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS mythen3DetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +sls_install_executable(mythen3DetectorServer_virtual) configure_file(DefaultPattern_mythen3.txt ${CMAKE_BINARY_DIR}/bin/DefaultPattern_mythen3.txt COPYONLY) configure_file(detid_mythen3.txt ${CMAKE_BINARY_DIR}/bin/detid_mythen3.txt COPYONLY) diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/CMakeLists.txt b/slsDetectorServers/xilinx_ctbDetectorServer/CMakeLists.txt index 284c9b6fc..2fee93ca8 100644 --- a/slsDetectorServers/xilinx_ctbDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/xilinx_ctbDetectorServer/CMakeLists.txt @@ -41,9 +41,7 @@ set_target_properties(xilinx_ctbDetectorServer_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS xilinx_ctbDetectorServer_virtual - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +sls_install_executable(xilinx_ctbDetectorServer_virtual) configure_file(chip_config_xilinx.txt ${CMAKE_BINARY_DIR}/bin/chip_config_xilinx.txt COPYONLY) configure_file(reset_chip_xilinx.txt ${CMAKE_BINARY_DIR}/bin/reset_chip_xilinx.txt COPYONLY) diff --git a/slsDetectorSoftware/CMakeLists.txt b/slsDetectorSoftware/CMakeLists.txt index 472205230..bccb64498 100755 --- a/slsDetectorSoftware/CMakeLists.txt +++ b/slsDetectorSoftware/CMakeLists.txt @@ -109,21 +109,9 @@ if(SLS_USE_TEXTCLIENT) set_property(TARGET ${val1} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) endif() - # Mainly for RPMs to enable side by side installations of different versions - if(SLS_INSTALL_VERSIONED_BINARIES) - install(PROGRAMS "$" - DESTINATION bin - RENAME "$-${PROJECT_VERSION}" - COMPONENT cli - ) - else() - install(TARGETS ${val1} - DESTINATION bin - COMPONENT cli - ) - endif() + sls_install_executable(${val1} DESTINATION bin COMPONENT cli) endforeach() - + endif(SLS_USE_TEXTCLIENT) diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt index be56105b5..8c00cd8eb 100755 --- a/slsReceiverSoftware/CMakeLists.txt +++ b/slsReceiverSoftware/CMakeLists.txt @@ -173,22 +173,12 @@ if (SLS_USE_RECEIVER_BINARIES) slsMultiReceiver slsFrameSynchronizer ) - if(SLS_INSTALL_VERSIONED_BINARIES) - message(STATUS "Versioned binaries will be installed") - foreach(target IN LISTS SLS_RECEIVER_BINARIES) - install(PROGRAMS "$" - DESTINATION ${CMAKE_INSTALL_BINDIR} - RENAME "$-${PROJECT_VERSION}" - COMPONENT receiver - ) - endforeach() - else() - install(TARGETS ${SLS_RECEIVER_BINARIES} + foreach(target IN LISTS SLS_RECEIVER_BINARIES) + sls_install_executable(${target} EXPORT "${TARGETS_EXPORT_NAME}" - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT receiver ) - endif() + endforeach() From 2b367cc37e609b3183b3fd1aeb0234ddb6b5c178 Mon Sep 17 00:00:00 2001 From: AliceMazzoleni99 Date: Thu, 8 Oct 2026 15:47:23 +0200 Subject: [PATCH 10/12] Fix/automate documentation (#1611) * also update developer * mofified for testing * fixed error message * temporarily disable all workflows * reference branch with /ref/head * force cherry-pick * allow empty commit * set write permissions * dont push update when updating version * Revert "temporarily disable all workflows" This reverts commit d8c67354d68e202b5ce893340a89931536dbcdb3. * use indices from relese list * removed versions.yaml * always sort the releases --- .github/workflows/build_documentation.yml | 27 ++-- docs/main_index/index.html.j2 | 11 +- docs/main_index/render_main_index.py | 145 +++++++++++----------- docs/main_index/versions.yaml | 77 ------------ etc/update_version.py | 13 +- 5 files changed, 103 insertions(+), 170 deletions(-) delete mode 100644 docs/main_index/versions.yaml diff --git a/.github/workflows/build_documentation.yml b/.github/workflows/build_documentation.yml index 458084c0a..f3bc49084 100644 --- a/.github/workflows/build_documentation.yml +++ b/.github/workflows/build_documentation.yml @@ -26,9 +26,9 @@ jobs: build-and-deploy: strategy: matrix: - patform: [ubuntu-latest] + platform: [ubuntu-latest] python-version: ["3.12"] - runs-on: ${{ matrix.patform }} + runs-on: ${{ matrix.platform }} defaults: run: @@ -74,24 +74,29 @@ jobs: cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DSLS_BUILD_DOCS=ON -DSLS_USE_HDF5=ON -DSLS_USE_PYTHON=ON .. make -j4 make docs - - # Update main index if this is a release - - name: Update version index + + + - name: Render Documentation index if: github.event_name == 'release' run: | - python docs/main_index/render_main_index.py \ - --version "${{ steps.version.outputs.version }}" \ - --date "$(date +'%d.%m.%Y')" - + gh release list --json tagName,publishedAt > releases.json + python docs/main_index/render_main_index.py --json_releases releases.json --new_version ${{ steps.version.outputs.version }} + - name: Checkout gh-pages uses: actions/checkout@v6 with: ref: gh-pages path: gh-pages + + - name: Copy documentation to versioned folder for developer branch + if: github.event_name == 'push' && github.ref == 'refs/heads/developer' + run: | + VERSION="${{ steps.version.outputs.version }}" + mkdir -p "gh-pages/${VERSION}" + cp -r build/docs/html/. "gh-pages/${VERSION}/" - - name: Copy documentation and Release notes to versioned folder - if: github.event_name == 'release' || (github.event_name == 'push') + if: github.event_name == 'release' run: | VERSION="${{ steps.version.outputs.version }}" mkdir -p "gh-pages/${VERSION}" diff --git a/docs/main_index/index.html.j2 b/docs/main_index/index.html.j2 index baf5c8dfd..5727064ea 100644 --- a/docs/main_index/index.html.j2 +++ b/docs/main_index/index.html.j2 @@ -99,7 +99,6 @@ {% for v in versions %} -{# Check if version >= 10.0.0 for .md vs .txt #} {% set version_parts = v["version"].split('.') | map('int') | list %} {% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and version_parts[1] > 0 and version_parts[2] > 0) %} {% set release_ext = '.md' if is_new_format else '.txt' %} @@ -151,10 +150,8 @@ -ery(function () { -hinxRtdTheme.Navigation.enable(true); - - \ No newline at end of file + + + diff --git a/docs/main_index/render_main_index.py b/docs/main_index/render_main_index.py index d2bbb2780..ce0c1ffff 100644 --- a/docs/main_index/render_main_index.py +++ b/docs/main_index/render_main_index.py @@ -1,98 +1,101 @@ """ -Render the index HTML from a Jinja2 template with version data. -Can also add new versions to the YAML data file. +Render the index HTML from a Jinja2 template with release data. + +The release data is a JSON list as produced by + gh release list --json tagName,publishedAt Usage: - # Just render from existing data - python render_main_index.py --template main_index.html.j2 --output main_index.html --data versions.yaml - - # Add a new version and render - python render_main_index.py --data versions.yaml --add-version 10.1.0 --type Minor --date "15.10.2025" --template main_index.html.j2 --output main_index.html + python render_main_index.py --data releases.json --template index.html.j2 --output index.html """ import argparse +import json from pathlib import Path from jinja2 import Template -import yaml import os +from datetime import date SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -def load_versions(data_path: Path): - """Load version data from YAML file.""" - with open(data_path, 'r') as f: - data = yaml.safe_load(f) - return data['versions'] +MIN_VERSION = (5, 0, 0) # releases older than this are not listed +MIN_DOCS_VERSION = (9, 0, 0) # releases older than this have no docs -def save_versions(data_path: Path, versions): - """Save version data to YAML file.""" - data = { - 'versions': versions - } - with open(data_path, 'w') as f: - yaml.dump(data, f, default_flow_style=False, sort_keys=False) - print(f"✓ Saved version data to {data_path}") +def parse_version(tag: str): + """Return (major, minor, patch) for a tag like '10.0.1', or None for e.g. '7.0.0.rc1'.""" + parts = tag.split('.') + if len(parts) != 3 or not all(p.isdigit() for p in parts): + return None + return tuple(int(p) for p in parts) -def extract_release_type(version: str) -> str: - """Extract release type from version string.""" - parts = version.split('.') - if len(parts) != 3: - return "Unknown" - major, minor, patch = map(int, parts) - if minor == 0 and patch == 0: - return "Major" - elif patch == 0: - return "Minor" - else: + +def release_type(version): + """Derive the release type from the version number.""" + _, minor, patch = version + if patch != 0: return "Bug Fix" + if minor != 0: + return "Minor" + return "Major" -def add_version(data_path: Path, version: str, release_type: str, date: str, has_docs: bool = True): - """Add a new version to the YAML data file.""" - versions = load_versions(data_path) - - # Add to table (check if not already present) - new_entry = { - 'version': version, - 'type': release_type, - 'date': date, - 'has_docs': has_docs - } - versions.insert(0, new_entry) - - print(f"✓ Added version {new_entry} to version data") - - save_versions(data_path, versions) +def read_release_json(data_path: Path): + """Load release data from JSON file, newest version first.""" + with open(data_path, 'r') as f: + releases = json.load(f) + versions = [] + for release in releases: + version = parse_version(release['tagName']) + if version is None or version < MIN_VERSION: + continue + versions.append({ + 'version': release['tagName'], + 'type': release_type(version), + 'date': release['publishedAt'].split('T')[0], + 'has_docs': version >= MIN_DOCS_VERSION, + '_key': version, + }) -def render_template(template_path: Path, output_path: Path, data_path: Path): + versions.sort(key=lambda v: v['_key'], reverse=True) + return versions + +def render_template(template_path: Path, output_path: Path, versions : list): """Render the Jinja2 template with version data.""" - versions = load_versions(data_path) - + with open(template_path, 'r') as f: template = Template(f.read()) - + html = template.render( versions=versions ) - + with open(output_path, 'w') as f: f.write(html) - + print(f"✓ Rendered {output_path}") +def add_version(version: str, versions : list): + """Add a version to the versions dict if it is not already present.""" + tuple_version = parse_version(version) + if version not in versions: + versions.insert(0,{ + 'version': version, + 'type': release_type(tuple_version), + 'date': date.today().strftime("%Y-%m-%d"), + 'has_docs': tuple_version >= MIN_DOCS_VERSION, + '_key': tuple_version, + }) + + versions.sort(key=lambda v: v['_key'], reverse=True) def main(): - parser = argparse.ArgumentParser(description='Manage versions and render main index HTML') - parser.add_argument('--data', type=Path, default=Path(SCRIPT_DIR + "/versions.yaml"), - help='Path to versions YAML data file') - - # Options for adding a new version - parser.add_argument('--version', type=str, - help='new version (e.g., 10.1.0)') - parser.add_argument('--date', type=str, - help='Release date (e.g., 15.10.2025)') + parser = argparse.ArgumentParser(description='Render main index HTML from release data') + parser.add_argument('--json_releases', type=Path, + help='Path to releases JSON data file') + parser.add_argument('--new_version', type=str, + help='New version to add to the releases data') + # Options for rendering parser.add_argument('--template', type=Path, default=Path(SCRIPT_DIR + "/index.html.j2"), help='Path to Jinja2 template file') @@ -100,17 +103,15 @@ def main(): help='Path to output HTML file') args = parser.parse_args() - - # Add new version if requested - if args.version: - if not args.date: - parser.error("--version requires --date") - release_type = extract_release_type(args.version) - add_version(args.data, args.version, release_type, args.date, has_docs=True) - + + versions = read_release_json(args.json_releases) + + if args.new_version: + add_version(args.new_version, versions) + # Render template if requested if args.template and args.output: - render_template(args.template, args.output, args.data) + render_template(args.template, args.output, versions) elif args.template or args.output: parser.error("--template and --output must be used together") diff --git a/docs/main_index/versions.yaml b/docs/main_index/versions.yaml deleted file mode 100644 index 7f46d545e..000000000 --- a/docs/main_index/versions.yaml +++ /dev/null @@ -1,77 +0,0 @@ -versions: -- version: 10.0.0 - type: Major - date: 10.09.2025 - has_docs: true -- version: 9.2.0 - type: Minor - date: 02.06.2025 - has_docs: true -- version: 9.1.1 - type: Bug Fix - date: 22.05.2025 - has_docs: true -- version: 9.1.0 - type: Minor - date: 28.03.2025 - has_docs: true -- version: 9.0.0 - type: Major - date: 26.11.2024 - has_docs: true -- version: 8.0.2 - type: Bug Fix - date: 18.09.2024 - has_docs: false -- version: 8.0.1 - type: Bug Fix - date: 16.01.2024 - has_docs: false -- version: 8.0.0 - type: Major - date: 13.11.2023 - has_docs: false -- version: 7.0.3 - type: Bug Fix - date: 14.11.2023 - has_docs: false -- version: 7.0.2 - type: Bug Fix - date: 12.07.2023 - has_docs: false -- version: 7.0.1 - type: Bug Fix - date: 24.03.2023 - has_docs: false -- version: 7.0.0 - type: Major - date: 24.02.2023 - has_docs: false -- version: 6.1.2 - type: Bug Fix - date: 25.11.2022 - has_docs: false -- version: 6.1.1 - type: Bug Fix - date: 04.01.2022 - has_docs: false -- version: 6.1.0 - type: Minor - date: 25.11.2021 - has_docs: false -- version: 6.0.0 - type: Major - date: 20.10.2021 - has_docs: false -- version: 5.1.0 - type: Minor - date: 22.03.2021 - has_docs: false -- version: 5.0.1 - type: Bug Fix - date: 25.11.2020 - has_docs: false -- version: 5.0.0 - type: Major - date: 18.11.2020 - has_docs: false \ No newline at end of file diff --git a/etc/update_version.py b/etc/update_version.py index b3878b18e..f312c276c 100644 --- a/etc/update_version.py +++ b/etc/update_version.py @@ -2,6 +2,7 @@ # Copyright (C) 2021 Contributors to the SLS Detector Package """ Script to update VERSION file with semantic versioning if provided as an argument, or with 0.0.0 if no argument is provided. +Script also updates VERSION in RELEASE.md and adds the new version to version.yaml """ import sys @@ -32,7 +33,7 @@ def write_version_to_file(version): version_file_path = Path(SCRIPT_DIR / "VERSION") with open(version_file_path, "w") as version_file: version_file.write(version) - print(f"Version {version} written to VERSION file.") + print(f"✓ Version {version} written to VERSION file.") def extract_release_type(version: str) -> str: @@ -59,9 +60,11 @@ def get_previous_version(data_path: Path, version : str) -> str: return prev_version + def main(): parser = argparse.ArgumentParser(description='Update version release notes') parser.add_argument('--version', required=True, type=str, help='version to write to VERSION file') + parser.add_argument('--prev_version', required=False, type=str, help='previous version to write to RELEASE.md file') parser.add_argument('--update_version_only', action="store_true", help='Only update version in VERSION file, do not generate release notes') args = parser.parse_args() @@ -69,8 +72,12 @@ def main(): write_version_to_file(version) if not args.update_version_only: + + if args.prev_version is None: + raise ValueError("Previous version must be provided when generating release notes. Use --prev_version to specify the previous version.") + release_type = extract_release_type(version) - prev_version = get_previous_version(ROOT_DIR / "docs/main_index/versions.yaml", version) + prev_version = args.prev_version # Read template template = Path(ROOT_DIR / "RELEASE.md").read_text() @@ -83,7 +90,7 @@ def main(): # Write output Path(ROOT_DIR / "RELEASE.md").write_text(output) - print(f"Generated RELEASE.md for version {version}") + print(f"✓ Generated RELEASE.md for version {version}") # Main script if __name__ == "__main__": From b98773f0045b5bc9ee5dc7921a0e79857439d6d8 Mon Sep 17 00:00:00 2001 From: AliceMazzoleni99 Date: Thu, 8 Oct 2026 18:48:10 +0200 Subject: [PATCH 11/12] forgot to use github token (#1616) * forgot to use github token * fix for minor version --- .github/workflows/build_documentation.yml | 2 ++ docs/main_index/index.html.j2 | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_documentation.yml b/.github/workflows/build_documentation.yml index f3bc49084..237d0af7b 100644 --- a/.github/workflows/build_documentation.yml +++ b/.github/workflows/build_documentation.yml @@ -81,6 +81,8 @@ jobs: run: | gh release list --json tagName,publishedAt > releases.json python docs/main_index/render_main_index.py --json_releases releases.json --new_version ${{ steps.version.outputs.version }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Checkout gh-pages uses: actions/checkout@v6 diff --git a/docs/main_index/index.html.j2 b/docs/main_index/index.html.j2 index 5727064ea..96ac8a674 100644 --- a/docs/main_index/index.html.j2 +++ b/docs/main_index/index.html.j2 @@ -100,7 +100,7 @@ {% for v in versions %} {% set version_parts = v["version"].split('.') | map('int') | list %} -{% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and version_parts[1] > 0 and version_parts[2] > 0) %} +{% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and (version_parts[1] > 0 or version_parts[2] > 0)) %} {% set release_ext = '.md' if is_new_format else '.txt' %}

{{ v["version"] }}

From 3dcdedf02c6a6ef5b154647c3c59956423038420 Mon Sep 17 00:00:00 2001 From: AliceMazzoleni99 Date: Fri, 9 Oct 2026 09:39:13 +0200 Subject: [PATCH 12/12] capture image view directly in lambda dont use late binding (#1614) --- pyctbgui/pyctbgui/services/Plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyctbgui/pyctbgui/services/Plot.py b/pyctbgui/pyctbgui/services/Plot.py index 688265484..de455720a 100644 --- a/pyctbgui/pyctbgui/services/Plot.py +++ b/pyctbgui/pyctbgui/services/Plot.py @@ -125,7 +125,7 @@ class PlotTab(QtWidgets.QWidget): nMaxX = lambda : self.transceiverTab.nTransceiverCols for index, image_view in enumerate(self.transceiverTab.transceiverImageViews): - frame = lambda : image_view.getImageItem().image + frame = lambda image_view=image_view: image_view.getImageItem().image image_view.scene.sigMouseMoved.connect(partial(self.showPlotValues, image_view, nMaxX, nMaxY, frame)) image_view.getHistogramWidget().item.sigLevelChangeFinished.connect(partial(self.handleHistogramChange, image_view))