diff --git a/RELEASE.md b/RELEASE.md index c0e3d2f79..b2caa361a 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -34,7 +34,7 @@ This document describes the differences between v10.0.1 and v10.0.0 Python ------- - * receiver ROI can be set from Python using command ``rx_roi``(it supports any sequence of four ints e.g. a tuple (xmin, xmax, ymin, ymax) or a sequence of such for multiple ROIS) + * receiver ROI can be set from Python using command ``rx_roi``(it supports any sequence of four or two (for mythen3 and gotthard) ints e.g. a tuple (xmin, xmax, ymin, ymax) or a sequence of such for multiple ROIS) * one can clear all ROI's from Python using command ``rx_clearroi`` diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 625691847..db2f31b8b 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -324,8 +324,9 @@ class Detector(CppDetectorApi): 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]] \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): diff --git a/python/src/typecaster.h b/python/src/typecaster.h index b011cebda..e32591396 100644 --- a/python/src/typecaster.h +++ b/python/src/typecaster.h @@ -100,7 +100,8 @@ template <> struct type_caster { // Type caster for sls::defs::ROI from tuple template <> struct type_caster { - PYBIND11_TYPE_CASTER(sls::defs::ROI, _("Sequence[int, int, int, int]")); + 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) { @@ -118,7 +119,7 @@ template <> struct type_caster { return false; } - if (seq.size() != 4) + if (seq.size() != 4 && seq.size() != 2) return false; // Check if each element is an int for (auto item : seq) { @@ -129,8 +130,12 @@ template <> struct type_caster { value.xmin = seq[0].cast(); value.xmax = seq[1].cast(); - value.ymin = seq[2].cast(); - value.ymax = seq[3].cast(); + + if (seq.size() == 4) { + value.ymin = seq[2].cast(); + value.ymax = seq[3].cast(); + } + return true; } }; diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 830d257dd..18c6bf174 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -38,8 +38,18 @@ def pytest_collection_modifyitems(config, items): if "withdetectorsimulators" in item.keywords: item.add_marker(skip) +#helper fixture for servers @pytest.fixture -def test_with_simulators(): +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' @@ -47,7 +57,6 @@ def test_with_simulators(): with open(MAIN_LOG_FNAME, 'w') as fp: try: - servers = ['moench'] nmods = 2 for server in servers: for ninterfaces in range(1,2): diff --git a/python/tests/test_pythonAPI.py b/python/tests/test_pythonAPI.py index f906c04a4..9c9782801 100644 --- a/python/tests/test_pythonAPI.py +++ b/python/tests/test_pythonAPI.py @@ -6,8 +6,19 @@ from conftest import test_with_simulators from slsdet import Detector @pytest.mark.withdetectorsimulators +@pytest.mark.parametrize("servers", [["eiger"]], indirect=True) def test_rx_ROI(test_with_simulators): - """ Test setting and getting rx_ROI property of Detector class. """ + """ 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)] + +@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) @@ -27,4 +38,21 @@ def test_rx_ROI(test_with_simulators): 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)] + + diff --git a/tests/scripts/utils_for_test.py b/tests/scripts/utils_for_test.py index 476bc9eda..f73e819b8 100644 --- a/tests/scripts/utils_for_test.py +++ b/tests/scripts/utils_for_test.py @@ -217,6 +217,7 @@ def loadConfig(name, rx_hostname = 'localhost', settingsdir = None, log_file_fp d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1 d.rx_hostname = rx_hostname + d.udp_dstip = 'auto' if name != "eiger": @@ -235,7 +236,7 @@ def loadConfig(name, rx_hostname = 'localhost', settingsdir = None, log_file_fp d.settingspath = settingsdir + '/' + name + '/' d.trimen = [4500, 5400, 6400] if name == 'eiger' else [4000, 6000, 8000, 12000] d.setThresholdEnergy(4500, detectorSettings.STANDARD) - + d.frames = num_frames except Exception as e: