Merge branch 'developer' into dev/wrap
Build on RHEL9 docker image / build (push) Successful in 4m26s
Build on RHEL8 docker image / build (push) Successful in 4m55s
Run Simulator Tests on local RHEL9 / build (push) Successful in 18m20s
Run Simulator Tests on local RHEL8 / build (push) Successful in 21m55s

This commit is contained in:
Erik Fröjdh
2026-05-11 08:49:41 +02:00
committed by GitHub
94 changed files with 4021 additions and 1011 deletions
+1
View File
@@ -13,6 +13,7 @@ pybind11_add_module(_slsdet
src/DurationWrapper.cpp
src/pedestal.cpp
src/bit.cpp
src/frequency.cpp
)
target_link_libraries(_slsdet PUBLIC
+3
View File
@@ -34,6 +34,9 @@ scanParameters = _slsdet.scanParameters
currentSrcParameters = _slsdet.currentSrcParameters
DurationWrapper = _slsdet.DurationWrapper
pedestalParameters = _slsdet.pedestalParameters
Hz = _slsdet.Hz
kHz = _slsdet.kHz
MHz = _slsdet.MHz
import os
def read_version():
+32 -13
View File
@@ -14,11 +14,12 @@ powerIndex = slsDetectorDefs.powerIndex
detectorType = slsDetectorDefs.detectorType
streamingInterface = slsDetectorDefs.streamingInterface
defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from ._slsdet import xy, freeSharedMemory, getUserDetails
from ._slsdet import xy, Hz, freeSharedMemory, getUserDetails
from .gaincaps import Mythen3GainCapsWrapper
from . import utils as ut
from .proxy import JsonProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
@@ -3441,15 +3442,21 @@ class Detector(CppDetectorApi):
@element
def runclk(self):
"""
[Ctb] Sets Run clock frequency in MHz. \n
[Xilinx Ctb] Sets Run clock frequency in kHz.
"""
[Ctb][Xilinx Ctb] Sets Run clock frequency.
Example
--------
>>> d.runclk
>>> 10MHz
>>> d.runclk = MHz(5)
>>> d.runclk = Hz(5 * 1000 * 1000)
>>> d.runclk = kHz(2000)
"""
return self.getRUNClock()
@runclk.setter
def runclk(self, freq):
ut.set_using_dict(self.setRUNClock, freq)
ut.set_using_dict(self.setRUNClock, freq)
@property
@element
@@ -3526,10 +3533,16 @@ class Detector(CppDetectorApi):
@element
def dbitclk(self):
"""
[Ctb] Sets clock for latching the digital bits in MHz. \n
[Xilinx Ctb] clock for latching the digital bits in kHz.
"""
[Ctb][Xilinx Ctb] Sets clock for latching the digital bits.
Example
--------
>>> d.dbitclk
>>> 10MHz
>>> d.dbitclk = MHz(5)
>>> d.dbitclk = Hz(5 * 1000 * 1000)
>>> d.dbitclk = kHz(2000)
"""
return self.getDBITClock()
@dbitclk.setter
@@ -3657,10 +3670,16 @@ class Detector(CppDetectorApi):
@element
def adcclk(self):
"""
[Ctb] Sets ADC clock frequency in MHz. \n
[Xilinx Ctb] Sets ADC clock frequency in kHz.
"""
[Ctb][Xilinx Ctb] Sets ADC clock frequency.
Example
--------
>>> d.adcclk
>>> 10MHz
>>> d.adcclk = MHz(5)
>>> d.adcclk = Hz(5 * 1000 * 1000)
>>> d.adcclk = kHz(2000)
"""
return self.getADCClock()
@adcclk.setter
@@ -3671,7 +3690,7 @@ class Detector(CppDetectorApi):
@element
def syncclk(self):
"""
[Ctb] Sync clock in MHz.
[Ctb] Sync clock.
:setter: Not implemented
"""
@@ -3704,7 +3723,7 @@ class Detector(CppDetectorApi):
[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default
file
"""
return self.getPatterFileName()
return self.getPatternFileName()
def patternstart(self):
"""[Ctb][Mythen3][Xilinx Ctb] Starts pattern. """
+15 -15
View File
@@ -1529,23 +1529,31 @@ void init_det(py::module &m) {
Detector::setNumberOfAnalogSamples,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getADCClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getADCClock,
py::arg() = Positions{});
CppDetectorApi.def("setADCClock",
(void (Detector::*)(int, sls::Positions)) &
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setADCClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getRUNClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getRUNClock,
py::arg() = Positions{});
CppDetectorApi.def("setRUNClock",
(void (Detector::*)(int, sls::Positions)) &
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setRUNClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getDBITClock",
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getDBITClock,
py::arg() = Positions{});
CppDetectorApi.def("setDBITClock",
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setDBITClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getSYNCClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getSYNCClock,
py::arg() = Positions{});
CppDetectorApi.def("getPowerList",
@@ -1646,14 +1654,6 @@ void init_det(py::module &m) {
(void (Detector::*)(defs::readoutMode, sls::Positions)) &
Detector::setReadoutMode,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getDBITClock",
(Result<int>(Detector::*)(sls::Positions) const) &
Detector::getDBITClock,
py::arg() = Positions{});
CppDetectorApi.def("setDBITClock",
(void (Detector::*)(int, sls::Positions)) &
Detector::setDBITClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getExternalSamplingSource",
(Result<int>(Detector::*)(sls::Positions) const) &
Detector::getExternalSamplingSource,
@@ -1891,9 +1891,9 @@ void init_det(py::module &m) {
Detector::configureTransceiver,
py::arg() = Positions{});
CppDetectorApi.def(
"getPatterFileName",
"getPatternFileName",
(Result<std::string>(Detector::*)(sls::Positions) const) &
Detector::getPatterFileName,
Detector::getPatternFileName,
py::arg() = Positions{});
CppDetectorApi.def(
"setPattern",
+55
View File
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/*
This file contains Python bindings for the Hz and for conversion to other units from and to string.
*/
#include "py_headers.h"
#include <cmath>
#include "sls/ToString.h"
#include "sls/sls_detector_defs.h"
namespace py = pybind11;
constexpr double kHz = 1e3;
constexpr double MHz = 1e6;
void init_freq(py::module &m) {
py::class_<slsDetectorDefs::Hz> Hz(m, "Hz");
Hz.def(py::init<int>());
Hz.def_readwrite("value", &slsDetectorDefs::Hz::value);
Hz.def("__repr__", [](const slsDetectorDefs::Hz &f) {
return sls::ToString(f);
});
Hz.def("__str__", [](const slsDetectorDefs::Hz &f) {
return sls::ToString(f);
});
Hz.def(py::self == py::self);
Hz.def("__mul__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value * x);
}, py::is_operator());
Hz.def("__rmul__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value * x);
}, py::is_operator());
Hz.def("__truediv__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value / x);
}, py::is_operator());
Hz.def("__add__", [](const slsDetectorDefs::Hz &a,
const slsDetectorDefs::Hz &b) {
return slsDetectorDefs::Hz(a.value + b.value);
}, py::is_operator());
Hz.def("__sub__", [](const slsDetectorDefs::Hz &a,
const slsDetectorDefs::Hz &b) {
return slsDetectorDefs::Hz(a.value - b.value);
}, py::is_operator());
m.def("kHz", [](double v) {
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * kHz)));
});
m.def("MHz", [](double v) {
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * MHz)));
});
}
+2
View File
@@ -21,6 +21,7 @@ void init_source(py::module &);
void init_duration(py::module &);
void init_pedestal(py::module &);
void init_bit(py::module &);
void init_freq(py::module &);
PYBIND11_MODULE(_slsdet, m) {
m.doc() = R"pbdoc(
@@ -42,6 +43,7 @@ PYBIND11_MODULE(_slsdet, m) {
init_duration(m);
init_pedestal(m);
init_bit(m);
init_freq(m);
// init_experimental(m);
py::module io = m.def_submodule("io", "Submodule for io");
+37 -78
View File
@@ -58,39 +58,56 @@ DEFAULT_SIMULATOR_CONFIGS = [
SIMULATOR_IDS = [f"{det_type}_{num_interface}if_{num_mod}mod" for det_type, num_interface, num_mod in DEFAULT_SIMULATOR_CONFIGS]
'''
for more specific parameters
@pytest.mark.detectorintegration
@pytest.mark.parametrize(
"session_simulator",
[
("ctb", 1, 1),
("xilinx_ctb", 1, 1),
],
indirect=True,
)
def test_define_reg(session_simulator):
det_type, num_interfaces, num_mods, d = session_simulator
'''
@pytest.fixture(scope="session")
def session_simulator(request):
"""
Fixture to start the detector server once and clean up at the end.
Expects request.param = (det_type, num_interfaces, num_mods)
"""
det_type, num_interfaces, num_mods = request.param
fp = sys.stdout
try:
det_type, num_interfaces, num_mods = request.param
fp = sys.stdout
# set up: once per server
Log(LogLevel.INFOBLUE,
f'---- {det_type} | interfaces={num_interfaces} | modules={num_mods} ----', fp)
# set up: once per server
Log(LogLevel.INFOBLUE,
f'---- {det_type} | interfaces={num_interfaces} | modules={num_mods} ----', fp)
cleanup(fp)
startDetectorVirtualServer(det_type, num_mods, fp, True)
startReceiver(num_mods, fp, True)
cleanup(fp)
startDetectorVirtualServer(det_type, num_mods, fp, True, True)
startReceiver(num_mods, fp, True)
Log(LogLevel.INFOBLUE, f'Waiting for server to start up and connect', fp)
d = loadConfig(
name=det_type,
log_file_fp=fp,
num_mods=num_mods,
num_frames=1,
num_interfaces=num_interfaces,
)
Log(LogLevel.INFOBLUE, f'Waiting for server to start up and connect', fp)
d = loadConfig(
name=det_type,
log_file_fp=fp,
num_mods=num_mods,
num_frames=1,
num_interfaces=num_interfaces,
)
loadBasicSettings(name=det_type, d=d, fp=fp)
loadBasicSettings(name=det_type, d=d, fp=fp)
yield det_type, num_interfaces, num_mods, d
cleanup(fp)
yield det_type, num_interfaces, num_mods, d
cleanup(fp)
except Exception as e:
Log(LogLevel.ERROR, f'Tests Failed.', fp)
cleanup(fp)
def pytest_generate_tests(metafunc):
if "session_simulator" not in metafunc.fixturenames:
@@ -110,62 +127,4 @@ def pytest_generate_tests(metafunc):
indirect=True
)
'''
for more specific parameters
@pytest.mark.detectorintegration
@pytest.mark.parametrize(
"session_simulator",
[
("ctb", 1, 1),
("xilinx_ctb", 1, 1),
],
indirect=True,
)
def test_define_reg(session_simulator):
det_type, num_interfaces, num_mods, d = session_simulator
'''
#helper fixture for servers
@pytest.fixture(scope='module')
def setup_parameters(request): # only setup once per module if same parameters used for the scopes
try:
servers, nmods = request.param # comes from @pytest.mark.parametrize(..., indirect=True)
return servers, nmods
except AttributeError:
# fallback default if the test did not parametrize
return (['eiger', 'jungfrau', 'mythen3', 'gotthard2', 'ctb', 'moench', 'xilinx_ctb'], 2)
@pytest.fixture(scope='module')
def test_with_simulators(setup_parameters):
""" Fixture to automatically setup virtual detector servers for testing. """
fp = sys.stdout
servers, nmods = setup_parameters
print("servers:", servers)
print("nmods:", nmods)
try:
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:
traceback.print_exc(file=fp)
Log(LogLevel.ERROR, f'Tests Failed.', fp)
cleanup(fp)
+59
View File
@@ -0,0 +1,59 @@
import pytest
import sys
from conftest import session_simulator
from slsdet import Detector
from slsdet._slsdet import slsDetectorDefs
detectorType = slsDetectorDefs.detectorType
@pytest.mark.detectorintegration
def test_rx_ROI(session_simulator):
""" Test rx_ROI property of Detector class. """
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
if d.type == detectorType.CHIPTESTBOARD or d.type == detectorType.XILINX_CHIPTESTBOARD:
pytest.skip("Skipping ROI test for ctb/xilinx_ctb detector types.")
if(d.type == detectorType.MYTHEN3 or d.type == detectorType.GOTTHARD2):
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)]
d.rx_clearroi()
else:
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)]
if d.nmod > 1 and (d.type != detectorType.JUNGFRAU) or (d.numinterfaces == 2 and d.type != detectorType.EIGER):
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)] #in same file for jungfrau
d.rx_clearroi()
roi = d.rx_roi
assert roi == [(-1,-1,-1,-1)]
+205
View File
@@ -12,6 +12,9 @@ from utils_for_test import (
)
from slsdet import Detector
from slsdet._slsdet import slsDetectorDefs
detectorType = slsDetectorDefs.detectorType
@pytest.mark.detectorintegration
@@ -396,6 +399,193 @@ def test_patternstart(session_simulator, request):
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_runclk(session_simulator, request):
""" Test using runclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_runclk = d.getRUNClock()
d.runclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.runclk = 5e6
with pytest.raises(Exception) as exc_info:
d.runclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.runclk = Hz(5e6)
d.runclk = MHz(15)
assert d.runclk.value == 15_000_000
d.runclk = MHz(14.5)
assert d.runclk.value == 14_500_000
d.runclk = kHz(15000.5)
assert d.runclk.value == 15_000_500
# invalid values from server
# max is 300MHz
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.runclk = rc * c
assert d.runclk.value == 40_000_000
for i in range(len(d)):
d.setRUNClock(prev_runclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_adcclk(session_simulator, request):
""" Test using adcclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_adcclk = d.getADCClock()
d.adcclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.adcclk = 5e6
with pytest.raises(Exception) as exc_info:
d.adcclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.adcclk = Hz(5e6)
d.adcclk = MHz(15)
assert d.adcclk.value == 15_000_000
d.adcclk = MHz(14.5)
assert d.adcclk.value == 14_500_000
d.adcclk = kHz(15000.5)
assert d.adcclk.value == 15_000_500
# invalid values from server
# max is 300MHz for xilinx and 54 MHz for ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(66)
else:
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.adcclk = rc * c
assert d.adcclk.value == 40_000_000
for i in range(len(d)):
d.setADCClock(prev_adcclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_dbitclk(session_simulator, request):
""" Test using dbitclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_dbitclk = d.getDBITClock()
d.dbitclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.dbitclk = 5e6
with pytest.raises(Exception) as exc_info:
d.dbitclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.dbitclk = Hz(5e6)
d.dbitclk = MHz(15)
assert d.dbitclk.value == 15_000_000
d.dbitclk = MHz(14.5)
assert d.dbitclk.value == 14_500_000
d.dbitclk = kHz(15000.5)
assert d.dbitclk.value == 15_000_500
# invalid values from server
# max is 300MHz
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.dbitclk = rc * c
assert d.dbitclk.value == 40_000_000
for i in range(len(d)):
d.setDBITClock(prev_dbitclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_syncclk(session_simulator, request):
""" Test using syncclk for ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
if det_type in ['ctb']:
d.syncclk
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_v_limit(session_simulator, request):
"""Test v_limit."""
@@ -715,3 +905,18 @@ def test_dac(session_simulator, request):
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
@pytest.mark.parametrize("session_simulator",[("moench", 1, 2)],indirect=True)
def test_type(session_simulator):
d = Detector()
assert d.type == detectorType.MOENCH
@pytest.mark.detectorintegration
@pytest.mark.parametrize("session_simulator",[("moench", 1, 2), ("jungfrau", 1, 2)],indirect=True)
def test_numinterfaces(session_simulator):
d = Detector()
assert d.numinterfaces == 1
+12 -36
View File
@@ -17,46 +17,18 @@ sys.path.append(str(scripts_dir))
from slsdet import Detector, Ctb, freeSharedMemory
from utils_for_test import (
Log,
LogLevel,
cleanup,
startDetectorVirtualServer,
connectToVirtualServers,
SERVER_START_PORTNO
)
'''
scope = module =>Once per test file/module
to share expensive setup like startDetectorVirtualServer
'''
@pytest.fixture(scope="module")
def det_config():
return {
"name": "ctb",
"num_mods": 1
}
@pytest.fixture(scope="module", autouse=True)
def setup_simulator(det_config):
"""Fixture to start the detector server once and clean up at the end."""
fp = sys.stdout
cleanup(fp)
startDetectorVirtualServer(det_config["name"], det_config["num_mods"], fp)
Log(LogLevel.INFOBLUE, f'Waiting for server to start up and connect')
connectToVirtualServers(det_config["name"], det_config["num_mods"])
Log(LogLevel.INFOBLUE, f'Freeing shm before tests')
freeSharedMemory()
yield # tests run here
cleanup(fp)
from conftest import session_simulator
@pytest.mark.detectorintegration
def test_exptime_after_free_should_raise(setup_simulator):
@pytest.mark.parametrize("session_simulator",[("ctb", 1, 1)],indirect=True)
def test_exptime_after_free_should_raise(session_simulator):
Log(LogLevel.INFOBLUE, f'\nRunning test_exptime_after_free_should_raise')
@@ -78,7 +50,8 @@ def free_and_create_shm():
k.hostname = f"localhost:{SERVER_START_PORTNO}" # free and recreate shm, maps to local shm struct
@pytest.mark.detectorintegration
def test_exptime_after_not_passing_var_should_raise(setup_simulator):
@pytest.mark.parametrize("session_simulator",[("ctb", 1, 1)],indirect=True)
def test_exptime_after_not_passing_var_should_raise(session_simulator):
Log(LogLevel.INFOBLUE, f'\nRunning test_exptime_after_not_passing_var_should_raise')
@@ -102,7 +75,8 @@ def free_and_create_shm_passing_ctb_var(k):
k.hostname = f"localhost:{SERVER_START_PORTNO}" # free and recreate shm, maps to local shm struct
@pytest.mark.detectorintegration
def test_exptime_after_passing_ctb_var_should_raise(setup_simulator):
@pytest.mark.parametrize("session_simulator",[("ctb", 1, 1)],indirect=True)
def test_exptime_after_passing_ctb_var_should_raise(session_simulator):
Log(LogLevel.INFOBLUE, f'\nRunning test_exptime_after_passing_ctb_var_should_raise')
d = Ctb() # creates multi shm (assuming no shm exists)
@@ -125,7 +99,8 @@ def free_and_create_shm_returning_ctb():
return k
@pytest.mark.detectorintegration
def test_exptime_after_returning_ctb_should_raise(setup_simulator):
@pytest.mark.parametrize("session_simulator",[("ctb", 1, 1)],indirect=True)
def test_exptime_after_returning_ctb_should_raise(session_simulator):
Log(LogLevel.INFOBLUE, f'\nRunning test_exptime_after_returning_ctb_should_raise')
d = Ctb() # creates multi shm (assuming no shm exists)
@@ -148,7 +123,8 @@ def test_exptime_after_returning_ctb_should_raise(setup_simulator):
assert str(exc_info.value) == "Shared memory is invalid or freed. Close resources before access."
@pytest.mark.detectorintegration
def test_hostname_twice_acess_old_should_raise(setup_simulator):
@pytest.mark.parametrize("session_simulator",[("ctb", 1, 1)],indirect=True)
def test_hostname_twice_acess_old_should_raise(session_simulator):
Log(LogLevel.INFOBLUE, f'\nRunning test_hostname_twice_acess_old_should_raise')
d = Ctb() # creates multi shm (assuming no shm exists)
+48
View File
@@ -0,0 +1,48 @@
from slsdet import Hz, MHz, kHz
def test_Hz():
f = Hz(1)
assert f.value == 1
f = Hz(1 * 1000)
assert f.value == 1000
f = MHz(5)
assert f.value == 5_000_000
f = MHz(0.5)
assert f.value == 500_000
f = kHz(2.5)
assert f.value == 2500
f = kHz(5000)
assert f.value == 5_000_000
def test_rounding_exact():
f = MHz(1.234)
assert f.value == round(1_234_000)
def test_mul():
c = MHz(1)
assert (c * 2).value == 2_000_000
assert (c * 4).value == 4_000_000
def test_rmul():
c = MHz(1)
assert (2 * c).value == 2_000_000
assert (4 * c).value == 4_000_000
c = c * 2
assert c.value == 2_000_000
for rc in [1, 2, 4, 8]:
c = rc * c
assert c.value == 128_000_000
def test_div():
c = MHz(1)
assert (c / 2).value == 500_000
def test_eq():
assert MHz(1) == MHz(1)
assert MHz(1) != MHz(2)
assert MHz(1) == kHz(1000)
-51
View File
@@ -1,51 +0,0 @@
import pytest
import sys
from conftest import test_with_simulators
from slsdet import Detector
from utils_for_test import (
Log,
LogLevel,
)
@pytest.mark.detectorintegration
@pytest.mark.parametrize("setup_parameters", [(["moench"], 2)], indirect=True)
def test_rx_ROI_moench(test_with_simulators, setup_parameters):
""" 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.detectorintegration
@pytest.mark.parametrize("setup_parameters", [(["mythen3"], 1)], indirect=True)
def test_rx_ROI_mythen(test_with_simulators, setup_parameters):
""" 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)]