diff --git a/pyproject.toml b/pyproject.toml index 105f41f254..42e32c1c52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ dev = [ # Commented out due to dependency version conflict with pydantic 1.x # "copier", "myst-parser", - "ophyd_async[sim]", + "ophyd_async[sim]>=v0.13.6", "pipdeptree", "pre-commit", "psutil", diff --git a/src/dodal/devices/fast_grid_scan.py b/src/dodal/devices/fast_grid_scan.py index 58c56e589d..b06cb94ad6 100644 --- a/src/dodal/devices/fast_grid_scan.py +++ b/src/dodal/devices/fast_grid_scan.py @@ -1,5 +1,7 @@ import asyncio from abc import ABC, abstractmethod +from functools import partial +from math import isclose from typing import Generic, TypeVar import numpy as np @@ -307,10 +309,21 @@ async def prepare(self, value: ParamType): set_statuses = [] LOGGER.info("Applying gridscan parameters...") + # Create arguments for bps.mv for key, signal in self._movable_params.items(): param_value = value.__dict__[key] - set_statuses.append(await set_and_wait_for_value(signal, param_value)) # type: ignore + + matcher = partial(isclose, param_value, abs_tol=0.001) + matcher.__name__ = "does_parameter_match" # type: ignore # Remove when https://github.com/bluesky/ophyd-async/pull/1123 deployed + + set_statuses.append( + await set_and_wait_for_value( + signal, # type: ignore + param_value, + match_value=matcher, + ) + ) # Counter should always start at 0 set_statuses.append(await set_and_wait_for_value(self.position_counter, 0)) diff --git a/tests/devices/test_gridscan.py b/tests/devices/test_gridscan.py index bfbff7141c..456931fa1e 100644 --- a/tests/devices/test_gridscan.py +++ b/tests/devices/test_gridscan.py @@ -2,6 +2,7 @@ from asyncio import wait_for from contextlib import nullcontext from dataclasses import dataclass +from typing import Any from unittest.mock import AsyncMock, MagicMock, patch import numpy as np @@ -11,7 +12,12 @@ from bluesky.run_engine import RunEngine from ophyd.status import DeviceStatus, Status from ophyd_async.core import init_devices -from ophyd_async.testing import get_mock_put, set_mock_put_proceeds, set_mock_value +from ophyd_async.testing import ( + callback_on_mock_put, + get_mock_put, + set_mock_put_proceeds, + set_mock_value, +) from dodal.devices.fast_grid_scan import ( FastGridScanCommon, @@ -476,7 +482,9 @@ async def test_i02_1_gridscan_has_2d_behaviour( async def test_gridscan_prepare_writes_values_and_checks_readback( - grid_scan_devices_with_params_and_valid_state, + grid_scan_devices_with_params_and_valid_state: tuple[ + FastGridScanCommon, GridScanParamsCommon, Any + ], ): grid_scan_device, grid_scan_params, valid_state = ( grid_scan_devices_with_params_and_valid_state @@ -516,7 +524,9 @@ async def test_gridscan_prepare_writes_values_and_checks_readback( async def test_gridscan_prepare_checks_validity_after_writes( - grid_scan_devices_with_params_and_valid_state, + grid_scan_devices_with_params_and_valid_state: tuple[ + FastGridScanCommon, GridScanParamsCommon, Any + ], ): grid_scan_device, grid_scan_params, valid_state = ( grid_scan_devices_with_params_and_valid_state @@ -549,7 +559,9 @@ async def test_gridscan_prepare_checks_validity_after_writes( async def test_gridscan_prepare_times_out_for_validity_check( - grid_scan_devices_with_params_and_valid_state, + grid_scan_devices_with_params_and_valid_state: tuple[ + FastGridScanCommon, GridScanParamsCommon, Any + ], ): grid_scan_device, grid_scan_params, valid_state = ( grid_scan_devices_with_params_and_valid_state @@ -572,3 +584,22 @@ async def test_gridscan_prepare_times_out_for_validity_check( and cause.args[0] == f"{device_name}-scan_invalid didn't match 0.0 in 0.5s, last value 1.0" ) + + +async def test_gridscan_prepare_works_within_tolerance_on_the_readback( + grid_scan_devices_with_params_and_valid_state: tuple[ + FastGridScanCommon, GridScanParamsCommon, Any + ], +): + grid_scan_device, grid_scan_params, valid_state = ( + grid_scan_devices_with_params_and_valid_state + ) + + grid_scan_params.x_step_size_mm = 0.1111111 + + def return_rounded_value(value, *_, **__): + return round(value, 3) + + callback_on_mock_put(grid_scan_device.x_step_size, return_rounded_value) + + await grid_scan_device.prepare(grid_scan_params)