diff --git a/pyproject.toml b/pyproject.toml index 6560daf5ae0..159f8c2ee71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ dependencies = [ "scanspec>=0.7.3", "pyzmq==26.3.0", # Until we can move to RHEL 8 https://github.com/DiamondLightSource/mx-bluesky/issues/1139 "deepdiff", - "daq-config-server>=v1.0.0-rc.2", # For getting Configuration settings. + "daq-config-server>=v1.1.2", # For getting Configuration settings. ] dynamic = ["version"] diff --git a/src/dodal/devices/detector/det_dist_to_beam_converter.py b/src/dodal/devices/detector/det_dist_to_beam_converter.py index be169f543b2..4d3f453e095 100644 --- a/src/dodal/devices/detector/det_dist_to_beam_converter.py +++ b/src/dodal/devices/detector/det_dist_to_beam_converter.py @@ -1,8 +1,10 @@ from enum import Enum +from daq_config_server.client import ConfigServer +from daq_config_server.models import DetectorXYLookupTable + from dodal.devices.util.lookup_tables import ( linear_extrapolation_lut, - parse_lookup_table, ) @@ -14,7 +16,11 @@ class Axis(Enum): class DetectorDistanceToBeamXYConverter: def __init__(self, lookup_file: str): self.lookup_file: str = lookup_file - lookup_table_columns: list = parse_lookup_table(self.lookup_file) + config_server = ConfigServer(url="https://daq-config.diamond.ac.uk") + + lookup_table_columns: list = config_server.get_file_contents( + lookup_file, DetectorXYLookupTable + ).columns self._d_to_x = linear_extrapolation_lut( lookup_table_columns[0], lookup_table_columns[1] ) diff --git a/tests/conftest.py b/tests/conftest.py index b326effebac..8f5988600d7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import importlib +import json import os from collections.abc import AsyncGenerator from pathlib import Path @@ -6,6 +7,7 @@ from unittest.mock import patch import pytest +from daq_config_server.models import ConfigModel from ophyd_async.core import init_devices, set_mock_value from conftest import mock_attributes_table @@ -88,3 +90,31 @@ async def baton_in_commissioning_mode() -> AsyncGenerator[Baton]: set_mock_value(baton.commissioning, True) yield baton set_commissioning_signal(None) + + +def _fake_config_server_get_file_contents( + filepath: str | Path, + desired_return_type: type[str] | type[dict] | ConfigModel = str, + reset_cached_result: bool = True, +): + filepath = Path(filepath) + # Minimal logic required for unit tests + with filepath.open("r") as f: + contents = f.read() + if desired_return_type is str: + return contents + elif desired_return_type is dict: + return json.loads(contents) + elif issubclass(desired_return_type, ConfigModel): # type: ignore + return desired_return_type.model_validate(json.loads(contents)) + + +@pytest.fixture(autouse=True) +def mock_config_server(): + # Don't actually talk to central service during unit tests, and reset caches between test + + with patch( + "daq_config_server.client.ConfigServer.get_file_contents", + side_effect=_fake_config_server_get_file_contents, + ): + yield diff --git a/tests/devices/detector/test_data/test_det_dist_converter.txt b/tests/devices/detector/test_data/test_det_dist_converter.txt index 084853e4329..4ba3260e3d5 100644 --- a/tests/devices/detector/test_data/test_det_dist_converter.txt +++ b/tests/devices/detector/test_data/test_det_dist_converter.txt @@ -1,7 +1,7 @@ -#Table giving position of beam X and Y as a function of detector distance -#Units mm mm mm -# Eiger values -# distance beamY beamX (values from mosflm) -Units mm mm mm -200 153.61 162.45 -500 153.57 159.96 +{ + "column_names": ["detector_distances_mm", "beam_centre_x_mm", "beam_centre_y_mm"], + "rows": [ + [200.0, 153.61, 162.45], + [500.0, 153.57, 159.96] + ] +} diff --git a/tests/devices/detector/test_detector.py b/tests/devices/detector/test_detector.py index c27bfae9a85..5694d686653 100644 --- a/tests/devices/detector/test_detector.py +++ b/tests/devices/detector/test_detector.py @@ -46,14 +46,14 @@ def test_if_path_provided_check_is_dir(tmp_path: Path): @patch( - "dodal.devices.detector.det_dist_to_beam_converter.parse_lookup_table", + "dodal.devices.detector.det_dist_to_beam_converter.ConfigServer", ) @patch( "dodal.devices.detector.det_dist_to_beam_converter.linear_extrapolation_lut", MagicMock(), ) def test_correct_det_dist_to_beam_converter_path_passed_in( - mocked_parse_table, tmp_path: Path + mocked_config_server, tmp_path: Path ): params = DetectorParams( expected_energy_ev=100, @@ -73,10 +73,7 @@ def test_correct_det_dist_to_beam_converter_path_passed_in( assert params.beam_xy_converter.lookup_file == "a fake directory" -@patch( - "dodal.devices.detector.det_dist_to_beam_converter.parse_lookup_table", -) -def test_run_number_correct_when_not_specified(mocked_parse_table, tmp_path): +def test_run_number_correct_when_not_specified(tmp_path): params = DetectorParams( expected_energy_ev=100, exposure_time_s=1.0, @@ -94,10 +91,7 @@ def test_run_number_correct_when_not_specified(mocked_parse_table, tmp_path): assert params.run_number == 1 -@patch( - "dodal.devices.detector.det_dist_to_beam_converter.parse_lookup_table", -) -def test_run_number_correct_when_specified(mocked_parse_table, tmp_path): +def test_run_number_correct_when_specified(tmp_path): params = DetectorParams( expected_energy_ev=100, exposure_time_s=1.0, diff --git a/tests/devices/test_beam_converter.py b/tests/devices/test_beam_converter.py index 0d26cf7e283..0b3261f5060 100644 --- a/tests/devices/test_beam_converter.py +++ b/tests/devices/test_beam_converter.py @@ -2,6 +2,7 @@ from unittest.mock import Mock, patch import pytest +from daq_config_server.models import DetectorXYLookupTable from dodal.devices.detector.det_dist_to_beam_converter import ( Axis, @@ -9,18 +10,15 @@ ) # fmt: off -LOOKUP_TABLE_TEST_VALUES = [ - (100.0, 200.0), # distance - (150.0, 151.0), # x - (160.0, 165.0), # y -] +LOOKUP_TABLE_TEST_VALUES = DetectorXYLookupTable(rows=[[100.0, 150.0, 160.0], [200.0, 151.0, 165.0]]) + # fmt: on @pytest.fixture def fake_converter(): with patch( - "dodal.devices.detector.det_dist_to_beam_converter.parse_lookup_table", + "dodal.devices.detector.det_dist_to_beam_converter.ConfigServer.get_file_contents", return_value=LOOKUP_TABLE_TEST_VALUES, ): yield DetectorDistanceToBeamXYConverter("test.txt") diff --git a/tests/devices/test_data/test_lookup_table.txt b/tests/devices/test_data/test_lookup_table.txt index 16fa297a058..00f6357bfdc 100644 --- a/tests/devices/test_data/test_lookup_table.txt +++ b/tests/devices/test_data/test_lookup_table.txt @@ -1,5 +1,6 @@ -# Beam converter lookup table for testing - -Units det_dist beam_x beam_y -100.0 150.0 160.0 -200.0 151.0 165.0 +{ + "rows": [ + [100.0, 150.0, 160.0], + [200.0, 151.0, 165.0] + ] +} diff --git a/tests/devices/util/test_lookup_tables.py b/tests/devices/util/test_lookup_tables.py index 35a78a0f036..02fd3b90909 100644 --- a/tests/devices/util/test_lookup_tables.py +++ b/tests/devices/util/test_lookup_tables.py @@ -7,9 +7,6 @@ linear_interpolation_lut, parse_lookup_table, ) -from tests.devices.detector.test_data import ( - TEST_DET_DIST_CONVERTER_LUT, -) from tests.devices.test_data import ( TEST_BEAMLINE_UNDULATOR_TO_GAP_LUT, ) @@ -27,18 +24,6 @@ async def test_energy_to_distance_table_correct_format(): assert table.shape == (50, 2) -@mark.parametrize( - "lut_path, num_columns", - [(TEST_BEAMLINE_DCM_ROLL_CONVERTER_TXT, 2), (TEST_DET_DIST_CONVERTER_LUT, 3)], -) -def test_parse_lookup_table_returns_list_of_the_same_length_as_num_of_columns( - lut_path, num_columns -): - lut_values = parse_lookup_table(lut_path) - - assert isinstance(lut_values, list) and len(lut_values) == num_columns - - @mark.parametrize("s, expected_t", [(2.0, 1.0), (3.0, 1.5), (5.0, 4.0), (5.25, 6.0)]) def test_linear_interpolation(s, expected_t): lut_converter = linear_interpolation_lut(