Compare commits

..

1 Commits

Author SHA1 Message Date
Erik Fröjdh
62488a8ce6 WIP 2025-10-29 09:19:28 +01:00
30 changed files with 1405 additions and 1743 deletions

View File

@@ -1,33 +0,0 @@
name: Build on local RHEL8
on:
push:
branches:
- developer
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "detectors-software-RH8"
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
source /home/gitea_runner/.bashrc
conda activate det
mkdir build && cd build
conda activate det
cmake .. -DSLS_USE_PYTHON=ON
make -j 2
cd ../pyctbgui
make
- name: Deploy to NFS update server
if: gitea.ref == 'refs/heads/developer'
run: |
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH8 <<< $'put build/bin'
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH8 <<< $'put pyctbgui'

View File

@@ -1,30 +0,0 @@
name: Build on local RHEL9
on:
push:
branches:
- developer
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "detectors-software-RH9"
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
mkdir build && cd build
cmake -DSLS_USE_PYTHON=ON -DPython_EXECUTABLE=/usr/bin/python3.13 -DPython_INCLUDE_DIR=/usr/include/python3.13 -DPython_LIBRARY=/usr/lib64/libpython3.13.so ..
make -j 2
cd ../pyctbgui
make
- name: Deploy to NFS update server
if: gitea.ref == 'refs/heads/developer'
run: |
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH9 <<< $'put build/bin'
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH9 <<< $'put pyctbgui'

View File

@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Build wheels - name: Build wheels
run: pipx run cibuildwheel==3.2.1 run: pipx run cibuildwheel==2.23.0
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:

View File

@@ -19,7 +19,7 @@ jobs:
with: with:
python-version: 3.12 python-version: 3.12
cache: 'pip' cache: 'pip'
- run: pip install pytest numpy colorama - run: pip install pytest numpy
- uses: awalsh128/cache-apt-pkgs-action@latest - uses: awalsh128/cache-apt-pkgs-action@latest
with: with:

View File

@@ -1,7 +1,7 @@
SLS Detector Package Major Release x.x.x released on xx.xx.202x SLS Detector Package Major Release x.x.x released on xx.xx.202x
=============================================================== ===============================================================
This document describes the differences between vx.x.x and v10.0.0 This document describes the differences between vx.x.x and vx.0.2
@@ -35,10 +35,6 @@ instead of the one included in our repo.
Experimental support for building the detector client (including python bindings) on macOS Experimental support for building the detector client (including python bindings) on macOS
``rx_dbitlist`` keeps the order of the passed bit list
Marked unused functions readDataFile/writeDataFile deprecated in file_utils.h
2 On-board Detector Server Compatibility 2 On-board Detector Server Compatibility
========================================== ==========================================

View File

@@ -2,8 +2,6 @@ python:
- 3.11 - 3.11
- 3.12 - 3.12
- 3.13 - 3.13
- 3.14
c_compiler: c_compiler:
- gcc # [linux] - gcc # [linux]
@@ -15,4 +13,4 @@ cxx_compiler:
- gxx # [linux] - gxx # [linux]
c_stdlib_version: # [linux] c_stdlib_version: # [linux]
- 2.17 # [linux] - 2.17 # [linux]

View File

@@ -9,11 +9,11 @@ package:
build: build:
number: 0 number: 0
script: script:
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv --config-settings=cmake.define.SLS_USE_SYSTEM_ZMQ=ON # [not win] - unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv # [not win]
requirements: requirements:
build: build:
- python - python {{python}}
- {{ compiler('c') }} - {{ compiler('c') }}
- {{ stdlib("c") }} - {{ stdlib("c") }}
- {{ compiler('cxx') }} - {{ compiler('cxx') }}
@@ -21,7 +21,7 @@ requirements:
host: host:
- cmake - cmake
- ninja - ninja
- python - python {{python}}
- pip - pip
- scikit-build-core - scikit-build-core
- pybind11 >=2.13.0 - pybind11 >=2.13.0
@@ -31,7 +31,7 @@ requirements:
- catch2 - catch2
run: run:
- python - python {{python}}
- numpy - numpy

View File

@@ -50,12 +50,6 @@ datetime.timedelta, DurationWrapper or by setting the time in seconds.
>>> d.getExptime() >>> d.getExptime()
[sls::DurationWrapper(total_seconds: 181.23 count: 181230000000)] [sls::DurationWrapper(total_seconds: 181.23 count: 181230000000)]
# In C++ it is possible to use chrono literals to set time more easily
# d.setExptime(7ms). However, this is not possible due to pythons syntax.
# instead we can create a unit that we use for conversion.
>>> ms = dt.timedelta(milliseconds = 1)
>>> d.exptime = 7.5*ms
------------------------------------ ------------------------------------

View File

@@ -17,7 +17,7 @@ dependencies = [
[tool.cibuildwheel] [tool.cibuildwheel]
before-all = "uname -a" before-all = "uname -a"
build = "cp{311,312,313,314}-manylinux_x86_64" build = "cp{311,312,313}-manylinux_x86_64"
[tool.scikit-build.build] [tool.scikit-build.build]
verbose = true verbose = true

View File

@@ -33,6 +33,31 @@ def green(msg):
return f"{GREENC}{msg}{ENDC}" return f"{GREENC}{msg}{ENDC}"
QUALIFY_KINDS = {
cindex.CursorKind.NAMESPACE,
cindex.CursorKind.CLASS_DECL,
cindex.CursorKind.STRUCT_DECL,
cindex.CursorKind.CLASS_TEMPLATE,
cindex.CursorKind.ENUM_DECL,
cindex.CursorKind.UNION_DECL,
cindex.CursorKind.TYPE_ALIAS_DECL,
}
def qualified_name(cur: cindex.Cursor, include_leaf: bool = True) -> str:
"""
Build a fully-qualified name by following semantic_parent up to the TU.
If include_leaf is False, returns just the enclosing scope (namespaces, classes).
"""
parts = []
c = cur if include_leaf else cur.semantic_parent
while c and c.kind != cindex.CursorKind.TRANSLATION_UNIT:
name = c.spelling or c.displayname # displayname helps for anonymous namespaces
if name and (c.kind in QUALIFY_KINDS or c is cur):
parts.append(name)
c = c.semantic_parent
return "::".join(reversed(parts))
def check_libclang_version(required="12"): def check_libclang_version(required="12"):
# Use already-loaded libclang, or let cindex resolve it # Use already-loaded libclang, or let cindex resolve it
lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang")) lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang"))
@@ -76,8 +101,8 @@ def check_for_compile_commands_json(path):
print(msg) print(msg)
default_build_path = "/home/l_frojdh/sls/build/" default_build_path = Path("../../build/")
fpath = "../../slsDetectorSoftware/src/Detector.cpp" fpath = Path("../../slsDetectorSoftware/src/Detector.cpp")
m = [] m = []
@@ -87,25 +112,14 @@ ag2 = []
cn = [] cn = []
def get_arguments(node):
args = [a.type.spelling for a in node.get_arguments()]
args = [
"py::arg() = Positions{}" if item == "sls::Positions" else "py::arg()"
for item in args
]
args = ", ".join(args)
if args:
args = f", {args}"
return args
def get_arguments_with_default(node): def get_arguments_with_default(node):
args = [] args = []
for arg in node.get_arguments(): for arg in node.get_arguments():
tokens = [t.spelling for t in arg.get_tokens()] tokens = [t.spelling for t in arg.get_tokens()]
# print(tokens)
if "=" in tokens: if "=" in tokens:
if arg.type.spelling == "sls::Positions": # TODO! automate # if arg.type.spelling == "sls::Positions": # TODO! automate+
if arg.type.spelling == "Positions": # TODO! automate
args.append("py::arg() = Positions{}") args.append("py::arg() = Positions{}")
else: else:
args.append("py::arg()" + "".join(tokens[tokens.index("=") :])) args.append("py::arg()" + "".join(tokens[tokens.index("=") :]))
@@ -174,6 +188,10 @@ def visit(node):
m.append(child) m.append(child)
args = get_arguments_with_default(child) args = get_arguments_with_default(child)
fs = get_fdec(child) fs = get_fdec(child)
qualified_class = qualified_name(child.semantic_parent) # "ns1::ns2::Detector"
# lines.append(
# f'CppDetectorApi.def("{child.spelling}", {fs} &{qualified_class}::{child.spelling}{args});'
# )
lines.append( lines.append(
f'CppDetectorApi.def("{child.spelling}",{fs} &Detector::{child.spelling}{args});' f'CppDetectorApi.def("{child.spelling}",{fs} &Detector::{child.spelling}{args});'
) )
@@ -202,8 +220,11 @@ if __name__ == "__main__":
) )
cargs = parser.parse_args() cargs = parser.parse_args()
check_libclang_version("12") # check_libclang_version("12")
check_clang_format_version(12) # check_clang_format_version(12)
cargs.build_path = cargs.build_path.resolve()
print(f'Using build path: {cargs.build_path}')
check_for_compile_commands_json(cargs.build_path) check_for_compile_commands_json(cargs.build_path)
print("Parsing functions in Detector.h - ", end="", flush=True) print("Parsing functions in Detector.h - ", end="", flush=True)
@@ -212,11 +233,17 @@ if __name__ == "__main__":
db = cindex.CompilationDatabase.fromDirectory(cargs.build_path) db = cindex.CompilationDatabase.fromDirectory(cargs.build_path)
index = cindex.Index.create() index = cindex.Index.create()
args = db.getCompileCommands(fpath) args = db.getCompileCommands(fpath)
args = list(iter(args).__next__().arguments)[0:-1] args = list(iter(args).__next__().arguments)[0:-1]
args = args + "-x c++ --std=c++11".split() # print('\n\nUsing compile commands:', args)
# args = args + "-x c++ --std=c++17".split()
syspath = system_include_paths("clang++") syspath = system_include_paths("clang++")
incargs = ["-I" + inc for inc in syspath] incargs = ["-I" + inc for inc in syspath]
args = args + incargs args = args + incargs
args = [arg for arg in args if arg.startswith("-I") or arg.startswith("-D")]
# args = incargs
# print(f"\n\nUsing compile args: {' '.join(args)}")
tu = index.parse(fpath, args=args) tu = index.parse(fpath, args=args)
visit(tu.cursor) visit(tu.cursor)
print(green("OK")) print(green("OK"))
@@ -241,5 +268,5 @@ if __name__ == "__main__":
subprocess.run(["clang-format", "../src/detector.cpp", "-i"]) subprocess.run(["clang-format", "../src/detector.cpp", "-i"])
print(green(" OK")) print(green(" OK"))
print("Changes since last commit:") # print("Changes since last commit:")
subprocess.run(["git", "diff", "../src/detector.cpp"]) # subprocess.run(["git", "diff", "../src/detector.cpp"])

View File

@@ -79,4 +79,10 @@ def system_include_paths(compiler, cpp=True):
line = line.strip() line = line.strip()
paths.append(line) paths.append(line)
paths = [p.decode('utf-8') for p in paths] paths = [p.decode('utf-8') for p in paths]
# Only keep include paths from the conda prefix
# remove anything pointing to gcc
prefix = os.environ['CONDA_PREFIX']
paths = [p for p in paths if prefix in p]
paths = [p for p in paths if 'gcc' not in p]
return paths return paths

View File

@@ -24,7 +24,6 @@ import datetime as dt
from functools import wraps from functools import wraps
from collections import namedtuple from collections import namedtuple
from collections.abc import Sequence
import socket import socket
import numpy as np import numpy as np
@@ -302,46 +301,6 @@ class Detector(CppDetectorApi):
def rx_arping(self, value): def rx_arping(self, value):
ut.set_using_dict(self.setRxArping, value) ut.set_using_dict(self.setRxArping, value)
@property
def rx_roi(self):
"""Gets the list of ROIs configured in the receiver.
Note
-----
Each ROI is represented as a tuple of (x_start, y_start, x_end, y_end). \n
If no ROIs are configured, returns [[-1,-1,-1,-1]].
"""
return self.getRxROI() #vector of Roi structs how represented?
@rx_roi.setter
def rx_roi(self, rois):
"""
Sets the list of ROIs in the receiver.
Can only set multiple ROIs at multi module level without gap pixels. If more than 1 ROI per
UDP port, it will throw. Setting number of udp interfaces will clear the
roi. Cannot be set for CTB or Xilinx CTB.
Note
-----
Each ROI should be represented as a sequence of 4 ints (x_start, y_start, x_end, y_end). \n
For mythen3 or gotthard2 pass a sequence of 2 ints (x_start, x_end) \n
For multiple ROI's pass a sequence of sequence \n
Example: [[0, 100, 50, 100], [260, 270, 50,100]] \n
"""
# TODO: maybe better to accept py::object in setRxROI and handle there?
if not isinstance(rois, Sequence):
raise TypeError(
"setRxROI failed: expected a tuple/list of ints x_min, x_max, y_min, y_max "
"or a sequence of such."
)
if(not isinstance(rois[0], Sequence)):
self.setRxROI([rois])
else:
self.setRxROI(rois)
def rx_clearroi(self):
"""Clears all the ROIs configured in the receiver."""
self.clearRxROI()
@property @property
@element @element

File diff suppressed because it is too large Load Diff

View File

@@ -12,11 +12,7 @@
#include <chrono> #include <chrono>
namespace py = pybind11; namespace py = pybind11;
void init_det(py::module &m) { void init_det(py::module &m) {
using sls::defs; using namespace sls; //TODO! qualify arguments and return types to avoid this
using sls::Detector;
using sls::ns;
using sls::Positions;
using sls::Result;
m.def("freeSharedMemory", (void (*)(const int, const int)) &sls::freeSharedMemory, py::arg() = 0, py::arg() = -1); m.def("freeSharedMemory", (void (*)(const int, const int)) &sls::freeSharedMemory, py::arg() = 0, py::arg() = -1);

View File

@@ -1,12 +1,11 @@
// SPDX-License-Identifier: LGPL-3.0-or-other // SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once #pragma once
#include <datetime.h>
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <datetime.h>
#include "DurationWrapper.h"
#include "sls/Result.h" #include "sls/Result.h"
#include "sls/sls_detector_defs.h" #include "DurationWrapper.h"
namespace py = pybind11; namespace py = pybind11;
namespace pybind11 { namespace pybind11 {
@@ -15,130 +14,84 @@ template <typename Type, typename Alloc>
struct type_caster<sls::Result<Type, Alloc>> struct type_caster<sls::Result<Type, Alloc>>
: list_caster<sls::Result<Type, Alloc>, Type> {}; : list_caster<sls::Result<Type, Alloc>, Type> {};
// Based on the typecaster in pybind11/chrono.h // Based on the typecaster in pybind11/chrono.h
template <> struct type_caster<std::chrono::nanoseconds> { template <> struct type_caster<std::chrono::nanoseconds> {
public: public:
PYBIND11_TYPE_CASTER(std::chrono::nanoseconds, PYBIND11_TYPE_CASTER(std::chrono::nanoseconds, const_name("DurationWrapper"));
const_name("DurationWrapper"));
// signed 25 bits required by the standard. // signed 25 bits required by the standard.
using days = std::chrono::duration<int_least32_t, std::ratio<86400>>; using days = std::chrono::duration<int_least32_t, std::ratio<86400>>;
/** /**
* Conversion part 1 (Python->C++): convert a PyObject into * Conversion part 1 (Python->C++): convert a PyObject into std::chrono::nanoseconds
* std::chrono::nanoseconds try datetime.timedelta, floats and our * try datetime.timedelta, floats and our DurationWrapper wrapper
* DurationWrapper wrapper */
*/
bool load(handle src, bool) { bool load(handle src, bool) {
using namespace std::chrono; using namespace std::chrono;
// Lazy initialise the PyDateTime import // Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) { if (!PyDateTimeAPI) {
PyDateTime_IMPORT; PyDateTime_IMPORT;
} }
if (!src) { if (!src) {
return false;
}
// If invoked with datetime.delta object, same as in chrono.h
if (PyDelta_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
days(PyDateTime_DELTA_GET_DAYS(src.ptr())) +
seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) +
microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))
);
return true;
}
// If invoked with a float we assume it is seconds and convert, same as
// in chrono.h
if (PyFloat_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
duration<double>(PyFloat_AsDouble(src.ptr())));
return true;
}
// If invoked with an int we assume it is nanoseconds and convert, same
// as in chrono.h
if (PyLong_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
duration<int64_t>(PyLong_AsLongLong(src.ptr())));
return true;
}
// Lastly if we were actually called with a DurationWrapper object we
// get the number of nanoseconds and create a std::chrono::nanoseconds
// from it
py::object py_cls =
py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)) {
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count());
return true;
}
return false;
}
/**
* Conversion part 2 (C++ -> Python)
* import the module to get a handle to the wrapped class
* Default construct an object of (wrapped) DurationWrapper
* set the count from chrono::nanoseconds and return
*/
static handle cast(std::chrono::nanoseconds src,
return_value_policy /* policy */, handle /* parent */) {
py::object py_cls =
py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object *obj = new py::object;
*obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();
dur->set_count(src.count());
return *obj;
}
};
// Type caster for sls::defs::ROI from tuple
template <> struct type_caster<sls::defs::ROI> {
PYBIND11_TYPE_CASTER(sls::defs::ROI, _("Sequence[int, int, int, int] or "
"Sequence[int, int]"));
// convert c++ ROI to python tuple
static handle cast(const sls::defs::ROI &roi, return_value_policy, handle) {
return py::make_tuple(roi.xmin, roi.xmax, roi.ymin, roi.ymax).release();
}
// convert from python to c++ ROI
bool load(handle roi, bool /*allow implicit conversion*/) {
// accept tuple, list, numpy array any sequence
py::sequence seq;
try {
seq = py::reinterpret_borrow<py::sequence>(roi);
} catch (...) {
return false;
}
if (seq.size() != 4 && seq.size() != 2)
return false;
// Check if each element is an int
for (auto item : seq) {
if (!py::isinstance<py::int_>(item)) {
return false; return false;
} }
// If invoked with datetime.delta object, same as in chrono.h
if (PyDelta_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
days(PyDateTime_DELTA_GET_DAYS(src.ptr())) +
seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) +
microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))
);
return true;
}
// If invoked with a float we assume it is seconds and convert, same as in chrono.h
if (PyFloat_Check(src.ptr())) {
value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr())));
return true;
}
// If invoked with an int we assume it is nanoseconds and convert, same as in chrono.h
if (PyLong_Check(src.ptr())) {
value = duration_cast<nanoseconds>(duration<int64_t>(PyLong_AsLongLong(src.ptr())));
return true;
}
// Lastly if we were actually called with a DurationWrapper object we get
// the number of nanoseconds and create a std::chrono::nanoseconds from it
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)){
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count());
return true;
}
return false;
} }
value.xmin = seq[0].cast<int>(); /**
value.xmax = seq[1].cast<int>(); * Conversion part 2 (C++ -> Python)
* import the module to get a handle to the wrapped class
if (seq.size() == 4) { * Default construct an object of (wrapped) DurationWrapper
value.ymin = seq[2].cast<int>(); * set the count from chrono::nanoseconds and return
value.ymax = seq[3].cast<int>(); */
static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) {
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object* obj = new py::object;
*obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();
dur->set_count(src.count());
return *obj;
} }
};
return true;
}
};
} // namespace detail } // namespace detail
} // namespace pybind11 } // namespace pybind11

View File

@@ -1,85 +0,0 @@
import pytest
import sys
import traceback
from pathlib import Path
current_dir = Path(__file__).resolve().parents[2]
scripts_dir = current_dir / "tests" / "scripts"
sys.path.append(str(scripts_dir))
print(sys.path)
from utils_for_test import (
Log,
LogLevel,
cleanup,
startReceiver,
startDetectorVirtualServer,
loadConfig,
loadBasicSettings,
)
def pytest_addoption(parser):
parser.addoption(
"--with-detector-simulators", action="store_true", default=False, help="Run tests that require detector simulators"
)
def pytest_configure(config):
config.addinivalue_line("markers", "withdetectorsimulators: mark test as needing detector simulators to run")
def pytest_collection_modifyitems(config, items):
if config.getoption("--with-detector-simulators"):
return
skip = pytest.mark.skip(reason="need --with-detector-simulators option to run")
for item in items:
if "withdetectorsimulators" in item.keywords:
item.add_marker(skip)
#helper fixture for servers
@pytest.fixture
def servers(request):
try:
return request.param # comes from @pytest.mark.parametrize(..., indirect=True)
except AttributeError:
# fallback default if the test did not parametrize
return ['eiger', 'jungfrau', 'mythen3', 'gotthard2', 'ctb', 'moench', 'xilinx_ctb']
return request.param
@pytest.fixture
def test_with_simulators(servers):
""" Fixture to automatically setup virtual detector servers for testing. """
LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_PythonAPI_test'
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
with open(MAIN_LOG_FNAME, 'w') as fp:
try:
nmods = 2
for server in servers:
for ninterfaces in range(1,2):
if ninterfaces == 2 and server != 'jungfrau' and server != 'moench':
continue
msg = f'Starting Python API Tests for {server}'
if server == 'jungfrau' or server == 'moench':
msg += f' with {ninterfaces} interfaces'
Log(LogLevel.INFOBLUE, msg, fp)
cleanup(fp)
startDetectorVirtualServer(server, nmods, fp)
startReceiver(nmods, fp)
d = loadConfig(name=server, log_file_fp=fp, num_mods=nmods, num_frames=1, num_interfaces=ninterfaces)
loadBasicSettings(name=server, d=d, fp=fp)
yield # run test
cleanup(fp) # teardown
except Exception as e:
with open(MAIN_LOG_FNAME, 'a') as fp_error:
traceback.print_exc(file=fp_error)
Log(LogLevel.ERROR, f'Tests Failed.', fp)
cleanup(fp)

View File

@@ -1,48 +0,0 @@
import pytest
import sys
from conftest import test_with_simulators
from slsdet import Detector
@pytest.mark.withdetectorsimulators
@pytest.mark.parametrize("servers", [["moench"]], indirect=True)
def test_rx_ROI_moench(test_with_simulators, servers):
""" Test setting and getting rx_ROI property of Detector class for moench. """
d = Detector()
d.rx_roi = (0, 10, 10, 20)
roi = d.rx_roi
assert roi == [(0, 10, 10, 20)]
d.rx_roi = [5,15,15,25]
assert d.rx_roi == [(5,15,15,25)]
d.rx_roi = [[0,10,0,20], [5,20,410,420]]
roi = d.rx_roi
assert roi == [(0,10,0,20), (5,20,410,420)]
d.rx_clearroi()
roi = d.rx_roi
assert roi == [(-1,-1,-1,-1)]
@pytest.mark.withdetectorsimulators
@pytest.mark.parametrize("servers", [["mythen3"]], indirect=True)
def test_rx_ROI_mythen(test_with_simulators, servers):
""" Test setting and getting rx_ROI property of Detector class for mythen. """
d = Detector()
d.rx_roi = (0, 10)
roi = d.rx_roi
assert roi == [(0, 10, -1, -1)]
#d.rx_roi = [[5,15, 0, 1]] # not allowed for mythen3
d.rx_roi = [0,10, -1, -1]
assert d.rx_roi == [(0,10,-1,-1)]

View File

@@ -1,5 +1,5 @@
# Prepare MH02 configuration # Prepare MH02 configuration
reg 0xC00C 0x00040041 reg 0xC00C 0x00000041
reg 0xC010 0x01200004 reg 0xC010 0x01200004
# configure Matterhorn SPI # configure Matterhorn SPI
@@ -14,7 +14,7 @@ reg 0xC120 0x1
reg 0xC120 0x0 reg 0xC120 0x0
# set MSB LSB inversions and polarity for transceiver # set MSB LSB inversions and polarity for transceiver
reg 0xC120 0x1e0 reg 0xC120 0x61e0
# Enable MH02 PLL clock # Enable MH02 PLL clock
pattern enable_clock_pattern.pyat pattern enable_clock_pattern.pyat

View File

@@ -1,7 +1,7 @@
# turn off clock # turn off clock
clearbit 0xB018 15 setbit 0xC00C 16
setbit 0xB010 15 setbit 0xC014 0
sleep 1 sleep 1
# reset Matterhorn periphery # reset Matterhorn periphery
@@ -9,7 +9,8 @@ setbit 0xC014 1
sleep 1 sleep 1
# turn on clock # turn on clock
clearbit 0xB010 15 clearbit 0xC00C 16
setbit 0xC014 0
sleep 1 sleep 1
# reset rx transceiver datapath # reset rx transceiver datapath

View File

@@ -2568,15 +2568,17 @@ std::vector<int> Module::getReceiverDbitList() const {
void Module::setReceiverDbitList(std::vector<int> list) { void Module::setReceiverDbitList(std::vector<int> list) {
LOG(logDEBUG1) << "Setting Receiver Dbit List"; LOG(logDEBUG1) << "Setting Receiver Dbit List";
if (list.size() > 64) {
throw RuntimeError("Dbit list size cannot be greater than 64\n");
}
for (auto &it : list) { for (auto &it : list) {
if (it < 0 || it > 63) { if (it < 0 || it > 63) {
throw RuntimeError("Dbit list value must be between 0 and 63\n"); throw RuntimeError("Dbit list value must be between 0 and 63\n");
} }
} }
auto r = stableRemoveDuplicates(list); std::sort(begin(list), end(list));
if(r) auto last = std::unique(begin(list), end(list));
LOG(logWARNING) << "Removed duplicated from receiver dbit list"; list.erase(last, list.end());
StaticVector<int, MAX_RX_DBIT> arg = list; StaticVector<int, MAX_RX_DBIT> arg = list;
sendToReceiver(F_SET_RECEIVER_DBIT_LIST, arg, nullptr); sendToReceiver(F_SET_RECEIVER_DBIT_LIST, arg, nullptr);

View File

@@ -138,8 +138,7 @@ TEST_CASE("Parse version and help", "[detector]") {
} }
} }
// TODO: fails on gitea CI due to uid issue, fix later TEST_CASE("Parse port and uid", "[detector]") {
TEST_CASE("Parse port and uid", "[.failsongitea][detector]") {
uid_t uid = getuid(); uid_t uid = getuid();
std::string uidStr = std::to_string(uid); std::string uidStr = std::to_string(uid);
uid_t invalidUid = uid + 1000; uid_t invalidUid = uid + 1000;

View File

@@ -64,8 +64,7 @@ class DataProcessorTest : public DataProcessor {
* num_transceiver_bytes = 2 both bytes have a value of 125 * num_transceiver_bytes = 2 both bytes have a value of 125
* num_digital_bytes is variable and is defined by number of samples * num_digital_bytes is variable and is defined by number of samples
* default num sample is 5 * default num sample is 5
* all bytes in digital data take a value of 0xFF (alternating bits between 0, * all bytes in digital data take a value of 255
* 1)
*/ */
class DataProcessorTestFixture { class DataProcessorTestFixture {
public: public:
@@ -107,7 +106,7 @@ class DataProcessorTestFixture {
num_random_offset_bytes); num_random_offset_bytes);
} }
void set_data(const std::bitset<8> pattern = 0xFF) { void set_data() {
delete[] data; delete[] data;
uint64_t max_bytes_per_bit = uint64_t max_bytes_per_bit =
num_samples % 8 == 0 ? num_samples / 8 : num_samples / 8 + 1; num_samples % 8 == 0 ? num_samples / 8 : num_samples / 8 + 1;
@@ -119,8 +118,7 @@ class DataProcessorTestFixture {
memset(data, dummy_value, num_analog_bytes); // set to dummy value memset(data, dummy_value, num_analog_bytes); // set to dummy value
memset(data + num_analog_bytes, 0, memset(data + num_analog_bytes, 0,
num_random_offset_bytes); // set to zero num_random_offset_bytes); // set to zero
memset(data + num_analog_bytes + num_random_offset_bytes, memset(data + num_analog_bytes + num_random_offset_bytes, 0xFF,
static_cast<uint8_t>(pattern.to_ulong()),
num_digital_bytes); // all digital bits are one num_digital_bytes); // all digital bits are one
memset(data + num_digital_bytes + num_analog_bytes + memset(data + num_digital_bytes + num_analog_bytes +
num_random_offset_bytes, num_random_offset_bytes,
@@ -172,7 +170,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Remove Trailing Bits",
TEST_CASE_METHOD(DataProcessorTestFixture, "Reorder all", TEST_CASE_METHOD(DataProcessorTestFixture, "Reorder all",
"[.dataprocessor][.reorder]") { "[.dataprocessor][.reorder]") {
// parameters: num_samples, expected_num_digital_bytes, // parameters: num_samples, expected_num_digital_bytes,
// expected_digital_part_for_each_bit // expected_digital_part
auto parameters = GENERATE( auto parameters = GENERATE(
std::make_tuple(5, 64, std::vector<uint8_t>{0b00011111}), std::make_tuple(5, 64, std::vector<uint8_t>{0b00011111}),
std::make_tuple(10, 2 * 64, std::vector<uint8_t>{0xFF, 0b00000011}), std::make_tuple(10, 2 * 64, std::vector<uint8_t>{0xFF, 0b00000011}),
@@ -266,13 +264,11 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
// expected_digital_part // expected_digital_part
auto parameters = GENERATE( auto parameters = GENERATE(
std::make_tuple(5, std::vector<int>{1, 4, 5}, 5, std::make_tuple(5, std::vector<int>{1, 4, 5}, 5,
std::vector<uint8_t>{0b00000010}), std::vector<uint8_t>{0b00000111}),
std::make_tuple(5, std::vector<int>{1, 5, 4}, 5,
std::vector<uint8_t>{0b00000100}),
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 10, std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 10,
std::vector<uint8_t>{0b11110000, 0b00000000}), std::vector<uint8_t>{0xFF, 0b00000001}),
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60}, 5, std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60}, 5,
std::vector<uint8_t>{0b11110000})); std::vector<uint8_t>{0xFF}));
size_t num_samples, expected_num_digital_bytes; size_t num_samples, expected_num_digital_bytes;
std::vector<uint8_t> expected_digital_part; std::vector<uint8_t> expected_digital_part;
@@ -285,7 +281,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
generaldata->SetCtbDbitReorder(false); generaldata->SetCtbDbitReorder(false);
set_num_samples(num_samples); set_num_samples(num_samples);
set_data(0b01010101); // set digital data to 0x55 to have alternating bits set_data();
size_t expected_size = size_t expected_size =
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes; num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
@@ -320,15 +316,11 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
// expected_digital_part // expected_digital_part
auto parameters = GENERATE( auto parameters = GENERATE(
std::make_tuple(5, std::vector<int>{1, 4, 5}, 3, std::make_tuple(5, std::vector<int>{1, 4, 5}, 3,
std::vector<uint8_t>{0x00, 0b00011111, 0x00}), std::vector<uint8_t>{0b00011111}),
std::make_tuple(5, std::vector<int>{1, 5, 4}, 3,
std::vector<uint8_t>{0x00, 0x00, 0b00011111}),
std::make_tuple(10, std::vector<int>{1, 4, 5}, 6, std::make_tuple(10, std::vector<int>{1, 4, 5}, 6,
std::vector<uint8_t>{0x00, 0x00, 0b11111111, 0b00000011, std::vector<uint8_t>{0xFF, 0b00000011}),
0x00, 0x00}),
std::make_tuple(8, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 9, std::make_tuple(8, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 9,
std::vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, std::vector<uint8_t>{0xFF}));
0xFF, 0xFF, 0x00}));
size_t num_samples, expected_num_digital_bytes; size_t num_samples, expected_num_digital_bytes;
std::vector<uint8_t> expected_digital_part; std::vector<uint8_t> expected_digital_part;
@@ -341,7 +333,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
generaldata->SetCtbDbitReorder(true); generaldata->SetCtbDbitReorder(true);
set_num_samples(num_samples); set_num_samples(num_samples);
set_data(0b01010101); set_data();
size_t expected_size = size_t expected_size =
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes; num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
@@ -351,8 +343,11 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
memset(expected_data, dummy_value, num_analog_bytes); memset(expected_data, dummy_value, num_analog_bytes);
memcpy(expected_data + num_analog_bytes, expected_digital_part.data(), for (size_t sample = 0; sample < bitlist.size(); ++sample) {
expected_digital_part.size()); memcpy(expected_data + num_analog_bytes +
expected_digital_part.size() * sample,
expected_digital_part.data(), expected_digital_part.size());
}
memset(expected_data + expected_num_digital_bytes + num_analog_bytes, memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
dummy_value, num_transceiver_bytes); dummy_value, num_transceiver_bytes);

View File

@@ -6,7 +6,6 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <numeric> #include <numeric>
#include <set>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
@@ -156,10 +155,6 @@ template <typename Container> bool hasDuplicates(Container c) {
return pos != c.end(); // if we found something there are duplicates return pos != c.end(); // if we found something there are duplicates
} }
/**
* @brief Sorts the container and removes duplicated elements
* returns true if elements were removed otherwiese false
*/
template <typename T> template <typename T>
typename std::enable_if<is_container<T>::value, bool>::type typename std::enable_if<is_container<T>::value, bool>::type
removeDuplicates(T &c) { removeDuplicates(T &c) {
@@ -172,29 +167,6 @@ removeDuplicates(T &c) {
return false; return false;
} }
/**
* @brief Removed duplicated entries while preserving the oder
* returns true if elements were removed otherwiese false
*/
template <typename T>
typename std::enable_if<is_container<T>::value, bool>::type
stableRemoveDuplicates(T &c) {
auto containerSize = c.size();
std::set<typename T::value_type> seen;
c.erase(
std::remove_if(c.begin(), c.end(),
[&](const typename T::value_type& val) {
return !seen.insert(val).second; // erase if already seen
}),
c.end()
);
if (c.size() != containerSize) {
return true;
}
return false;
}
} // namespace sls } // namespace sls
#endif // CONTAINER_UTILS_H #endif // CONTAINER_UTILS_H

View File

@@ -16,7 +16,6 @@ namespace sls {
* @param nch number of channels * @param nch number of channels
* @param offset start channel value * @param offset start channel value
*/ */
[[deprecated]]
int readDataFile(std::ifstream &infile, short int *data, int nch, int readDataFile(std::ifstream &infile, short int *data, int nch,
int offset = 0); int offset = 0);
@@ -24,7 +23,6 @@ int readDataFile(std::ifstream &infile, short int *data, int nch,
* @param data array of data value * @param data array of data value
* @param nch number of channels * @param nch number of channels
*/ */
[[deprecated]]
int readDataFile(std::string fname, short int *data, int nch); int readDataFile(std::string fname, short int *data, int nch);
std::vector<char> readBinaryFile(const std::string &fname, std::vector<char> readBinaryFile(const std::string &fname,
@@ -35,7 +33,6 @@ std::vector<char> readBinaryFile(const std::string &fname,
* @param data array of data values * @param data array of data values
* @param offset start channel number * @param offset start channel number
*/ */
[[deprecated]]
int writeDataFile(std::ofstream &outfile, int nch, short int *data, int writeDataFile(std::ofstream &outfile, int nch, short int *data,
int offset = 0); int offset = 0);
@@ -43,7 +40,6 @@ int writeDataFile(std::ofstream &outfile, int nch, short int *data,
* @param nch number of channels * @param nch number of channels
* @param data array of data values * @param data array of data values
*/ */
[[deprecated]]
int writeDataFile(std::string fname, int nch, short int *data); int writeDataFile(std::string fname, int nch, short int *data);
// mkdir -p path implemented by recursive calls // mkdir -p path implemented by recursive calls

View File

@@ -153,35 +153,13 @@ TEST_CASE("check for duplicates in vector of pairs") {
REQUIRE(hasDuplicates(vec) == true); REQUIRE(hasDuplicates(vec) == true);
} }
TEST_CASE("sorts the vector and remove duplicates") { TEST_CASE("remove duplicates from vector") {
std::vector<int> v{5, 6, 5, 3}; std::vector<int> v{5, 6, 5, 3};
auto r = removeDuplicates(v); auto r = removeDuplicates(v);
CHECK(r == true); // did indeed remove elements CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{3, 5, 6}); CHECK(v == std::vector<int>{3, 5, 6});
} }
TEST_CASE("remove duplicates but keep order") {
std::vector<int> v{5, 6, 5, 3};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{5, 6, 3});
}
TEST_CASE("remove duplicates but keep order, all elements the same ") {
std::vector<char> v{'c', 'c', 'c', 'c', 'c', 'c'};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<char>{'c'});
}
TEST_CASE("remove duplicates but keep order, pattern ") {
std::vector<int> v{8,1,2,8,8,3,2};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{8,1,2,3});
}
TEST_CASE("remove duplicated empty vector") { TEST_CASE("remove duplicated empty vector") {
std::vector<int> v; std::vector<int> v;
auto r = removeDuplicates(v); auto r = removeDuplicates(v);
@@ -189,11 +167,4 @@ TEST_CASE("remove duplicated empty vector") {
CHECK(v == std::vector<int>{}); CHECK(v == std::vector<int>{});
} }
TEST_CASE("remove duplicated empty vector using stable version") {
std::vector<int> v;
auto r = stableRemoveDuplicates(v);
CHECK(r == false); // no elements to remove
CHECK(v == std::vector<int>{});
}
} // namespace sls } // namespace sls

View File

@@ -113,7 +113,7 @@ def startTestsForAll(args, fp):
startDetectorVirtualServer(server, args.num_mods, fp) startDetectorVirtualServer(server, args.num_mods, fp)
startFrameSynchronizerPullSocket(server, fp) startFrameSynchronizerPullSocket(server, fp)
startFrameSynchronizer(args.num_mods, fp) startFrameSynchronizer(args.num_mods, fp)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, log_file_fp=fp, num_mods=args.num_mods, num_frames=args.num_frames) d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
loadBasicSettings(name=server, d=d, fp=fp) loadBasicSettings(name=server, d=d, fp=fp)
acquire(fp, d) acquire(fp, d)
testFramesCaught(server, d, args.num_frames) testFramesCaught(server, d, args.num_frames)

View File

@@ -18,11 +18,9 @@ from utils_for_test import (
RuntimeException, RuntimeException,
cleanup, cleanup,
startProcessInBackground, startProcessInBackground,
startReceiver,
startDetectorVirtualServer, startDetectorVirtualServer,
connectToVirtualServers, connectToVirtualServers,
loadBasicSettings, loadBasicSettings,
loadConfig,
runProcessWithLogFile runProcessWithLogFile
) )
@@ -30,6 +28,45 @@ LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_roi_test'
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt' MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
ROI_TEST_FNAME = LOG_PREFIX_FNAME + '_results_' ROI_TEST_FNAME = LOG_PREFIX_FNAME + '_results_'
def startReceiver(num_mods, fp):
if num_mods == 1:
cmd = ['slsReceiver']
else:
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
# in 10.0.0
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
startProcessInBackground(cmd, fp)
time.sleep(1)
def loadConfigForRoi(name, fp, num_mods = 1, num_interfaces = 1):
Log(LogLevel.INFO, 'Loading config')
Log(LogLevel.INFO, 'Loading config', fp)
try:
d = connectToVirtualServers(name, num_mods)
if name == 'jungfrau' or name == 'moench':
d.numinterfaces = num_interfaces
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
if name == 'eiger' or name == 'jungfrau' or name == 'moench':
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
d.rx_hostname = 'localhost'
d.udp_dstip = 'auto'
if name != "eiger":
d.udp_srcip = 'auto'
if name == 'jungfrau' or name == 'moench':
d.udp_dstip2 = 'auto'
d.powerchip = 1
d.frames = 5
except Exception as e:
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
return d
def startTestsForAll(fp): def startTestsForAll(fp):
servers = [ servers = [
'eiger', 'eiger',
@@ -52,7 +89,7 @@ def startTestsForAll(fp):
cleanup(fp) cleanup(fp)
startDetectorVirtualServer(server, nmods, fp) startDetectorVirtualServer(server, nmods, fp)
startReceiver(nmods, fp) startReceiver(nmods, fp)
d = loadConfig(name=server, log_file_fp = fp, num_mods=nmods, num_frames=5, num_interfaces=ninterfaces) d = loadConfigForRoi(name=server, fp=fp, num_mods=nmods, num_interfaces=ninterfaces)
loadBasicSettings(name=server, d=d, fp=fp) loadBasicSettings(name=server, d=d, fp=fp)
fname = ROI_TEST_FNAME + server + '.txt' fname = ROI_TEST_FNAME + server + '.txt'

View File

@@ -63,7 +63,7 @@ def startCmdTestsForAll(args, fp):
cleanup(fp) cleanup(fp)
startDetectorVirtualServer(name=server, num_mods=num_mods, fp=fp) startDetectorVirtualServer(name=server, num_mods=num_mods, fp=fp)
startReceiver(num_mods, fp) startReceiver(num_mods, fp)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, log_file_fp=fp, num_mods=num_mods) d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=num_mods)
loadBasicSettings(name=server, d=d, fp=fp) loadBasicSettings(name=server, d=d, fp=fp)
runProcessWithLogFile('Cmd Tests (' + args.markers + ') for ' + server, cmd, fp, fname) runProcessWithLogFile('Cmd Tests (' + args.markers + ') for ' + server, cmd, fp, fname)
except Exception as e: except Exception as e:

View File

@@ -16,6 +16,7 @@ SERVER_START_PORTNO=1900
init(autoreset=True) init(autoreset=True)
class LogLevel(Enum): class LogLevel(Enum):
INFO = 0 INFO = 0
INFORED = 1 INFORED = 1
@@ -192,51 +193,32 @@ def connectToVirtualServers(name, num_mods, ctb_object=False):
return d return d
def startReceiver(num_mods, fp):
if num_mods == 1:
cmd = ['slsReceiver']
else:
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
# in 10.0.0
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
startProcessInBackground(cmd, fp)
time.sleep(1)
def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1):
def loadConfig(name, rx_hostname = 'localhost', settingsdir = None, log_file_fp = None, num_mods = 1, num_frames = 1, num_interfaces = 1):
Log(LogLevel.INFO, 'Loading config') Log(LogLevel.INFO, 'Loading config')
Log(LogLevel.INFO, 'Loading config', log_file_fp) Log(LogLevel.INFO, 'Loading config', fp)
try: try:
d = connectToVirtualServers(name, num_mods) d = connectToVirtualServers(name, num_mods)
if name == 'jungfrau' or name == 'moench':
d.numinterfaces = num_interfaces
d.udp_dstport = DEFAULT_UDP_DST_PORTNO d.udp_dstport = DEFAULT_UDP_DST_PORTNO
if name == 'eiger' or name == 'jungfrau' or name == 'moench': if name == 'eiger':
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1 d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
d.rx_hostname = rx_hostname d.rx_hostname = rx_hostname
d.udp_dstip = 'auto' d.udp_dstip = 'auto'
if name != "eiger": if name != "eiger":
d.udp_srcip = 'auto' d.udp_srcip = 'auto'
if name == "jungfrau" or name == "moench":
d.udp_dstip2 = 'auto'
if name == "jungfrau" or name == "moench" or name == "xilinx_ctb": if name == "jungfrau" or name == "moench" or name == "xilinx_ctb":
d.powerchip = 1 d.powerchip = 1
if name == "xilinx_ctb": if name == "xilinx_ctb":
d.configureTransceiver() d.configureTransceiver()
if settingsdir is not None and name in ['eiger', 'mythen3']: if name == "eiger":
d.settingspath = settingsdir + '/' + name + '/' d.trimen = [4500, 5400, 6400]
d.trimen = [4500, 5400, 6400] if name == 'eiger' else [4000, 6000, 8000, 12000] d.settingspath = settingsdir + '/eiger/'
d.setThresholdEnergy(4500, detectorSettings.STANDARD) d.setThresholdEnergy(4500, detectorSettings.STANDARD)
d.frames = num_frames d.frames = num_frames
except Exception as e: except Exception as e:

View File

@@ -1,14 +1,39 @@
#!/bin/bash # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
#echo $#
#if [ $# = 0 ]; then
# f=$0
#else
# f=$1
#fi
#echo $f
if [ "x${BASH_ARGV[0]}" = "x" ]; then
#if [ "x$f" = "x" ]; then
if [ ! -f this_build_bin_path.sh ]; then
f=$0
echo "aaaa"
#thispath=$(dirname ${BASH_ARGV[0]})
thispath=$(dirname $f)
p=$(cd ${thispath};pwd);
THIS_PATH="$p/build/bin/"
# echo "ERROR: must cd where/this/package/is before calling this_path.sh"
# echo "Try sourcing it"
else
echo "bbb"
THIS_PATH="$PWD/build/bin/";
fi
else
thispath=$(dirname ${BASH_ARGV[0]})
p=$(cd ${thispath};pwd);
THIS_PATH="$p/build/bin/"
echo "ccc"
fi
# Since this script could be sourced, $0 is not sufficent, BASH_SOURCE[0] is necessary echo "this_path="$THIS_PATH
SCRIPT_LOCATION="$(realpath ${BASH_SOURCE[0]})" export PATH=$THIS_PATH:$PATH
SCRIPT_LOCATION="$(dirname ${SCRIPT_LOCATION})" export LD_LIBRARY_PATH=$THIS_PATH:$LD_LIBRARY_PATH
BUILDBIN_LOCATION="${SCRIPT_LOCATION}/build/bin" export PYTHONPATH=$THIS_PATH:$PYTHONPATH
if [ ! -d "${BUILDBIN_LOCATION}" ]; then echo "path="$PATH
echo Cannot find path ${BUILDBIN_LOCATION} echo "ld_library_path="$LD_LIBRARY_PATH
else echo "pythonpath="$PYTHON_PATH
echo Adding ${BUILDBIN_LOCATION} to PATH and PYTHONPATH
export PATH=${BUILDBIN_LOCATION}:${PATH}
export PYTHONPATH=${BUILDBIN_LOCATION}:${PYTHONPATH}
fi