From f209271e0778359bf6af1c5c348e7ded1b18b414 Mon Sep 17 00:00:00 2001 From: Srishty Date: Wed, 24 Sep 2025 12:59:44 +0000 Subject: [PATCH 01/20] Add scint into beam + change Enum to be be more descriptive compared to just In and Out. --- src/dodal/devices/scintillator.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index c6c98491dd9..b54949acbec 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -8,9 +8,10 @@ class InOut(StrictEnum): - """Currently Hyperion only needs to move the scintillator out for data collection.""" + """Moves scintillator in and out of the beam""" - OUT = "Out" + OUT = "Out_Beam" + IN = "In_Beam" UNKNOWN = "Unknown" @@ -45,6 +46,9 @@ def __init__( self._scintillator_out_yz_mm = [ float(beamline_parameters[f"scin_{axis}_SCIN_OUT"]) for axis in ("y", "z") ] + self._scintillator_in_yz_mm = [ + float(beamline_parameters[f"scin_{axis}_SCIN_IN"]) for axis in ("y", "z") + ] self._yz_tolerance_mm = [ float(beamline_parameters[f"scin_{axis}_tolerance"]) for axis in ("y", "z") ] @@ -63,6 +67,18 @@ def _get_selected_position(self, y: float, z: float) -> InOut: ) ): return InOut.OUT + + elif all( + isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) + for axis_pos, axis_in_beam, axis_tolerance in zip( + current_pos, + self._scintillator_in_yz_mm, + self._yz_tolerance_mm, + strict=False, + ) + ): + return InOut.IN + else: return InOut.UNKNOWN @@ -82,5 +98,15 @@ async def _set_selected_position(self, position: InOut) -> None: ) await self.y_mm.set(self._scintillator_out_yz_mm[0]) await self.z_mm.set(self._scintillator_out_yz_mm[1]) + case InOut.IN: + if ( + self._aperture_scatterguard().selected_aperture.get_value() + != ApertureValue.PARKED + ): + raise ValueError( + "Cannot move scintillator out if aperture/scatterguard is not parked" + ) + await self.z_mm.set(self._scintillator_in_yz_mm[1]) + await self.y_mm.set(self._scintillator_in_yz_mm[0]) case _: raise ValueError(f"Cannot set scintillator to position {position}") From 1efa5fde538b8c2e74c774c21dff11b8eb6299b9 Mon Sep 17 00:00:00 2001 From: Srishty Date: Wed, 24 Sep 2025 13:14:45 +0000 Subject: [PATCH 02/20] Get rid of Enum change as this has to match what the PV is expecting --- src/dodal/devices/scintillator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index b54949acbec..3e4c324b0b7 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -8,10 +8,10 @@ class InOut(StrictEnum): - """Moves scintillator in and out of the beam""" + """Moves scintillator in and out of the beam.""" - OUT = "Out_Beam" - IN = "In_Beam" + OUT = "Out" + IN = "In" UNKNOWN = "Unknown" From 5b747e230fde3184691165037569050c78597230 Mon Sep 17 00:00:00 2001 From: Srishty Date: Wed, 24 Sep 2025 13:17:46 +0000 Subject: [PATCH 03/20] Add comments for what In and Out mean for the scint --- src/dodal/devices/scintillator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 3e4c324b0b7..c819d7fb085 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -9,9 +9,9 @@ class InOut(StrictEnum): """Moves scintillator in and out of the beam.""" - - OUT = "Out" - IN = "In" + + OUT = "Out" #Out of beam + IN = "In" #In to beam UNKNOWN = "Unknown" From f61d124e7e5d100feb2e35dc9a67345cd8adf9f1 Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 09:22:40 +0000 Subject: [PATCH 04/20] small change --- src/dodal/devices/scintillator.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index c819d7fb085..952c7f99820 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -9,9 +9,9 @@ class InOut(StrictEnum): """Moves scintillator in and out of the beam.""" - - OUT = "Out" #Out of beam - IN = "In" #In to beam + + OUT = "Out" # Out of beam + IN = "In" # In to beam UNKNOWN = "Unknown" @@ -67,7 +67,7 @@ def _get_selected_position(self, y: float, z: float) -> InOut: ) ): return InOut.OUT - + elif all( isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) for axis_pos, axis_in_beam, axis_tolerance in zip( @@ -78,7 +78,7 @@ def _get_selected_position(self, y: float, z: float) -> InOut: ) ): return InOut.IN - + else: return InOut.UNKNOWN @@ -104,7 +104,7 @@ async def _set_selected_position(self, position: InOut) -> None: != ApertureValue.PARKED ): raise ValueError( - "Cannot move scintillator out if aperture/scatterguard is not parked" + "Cannot move scintillator in if aperture/scatterguard is not parked" ) await self.z_mm.set(self._scintillator_in_yz_mm[1]) await self.y_mm.set(self._scintillator_in_yz_mm[0]) From 542db18dc3ceb5ad69c6f6fe29d086494ec42633 Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 10:42:51 +0000 Subject: [PATCH 05/20] add tests for scint in --- tests/devices/test_scintillator.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index 976dbbf997b..1541c370eff 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -49,6 +49,7 @@ async def scintillator_and_ap_sg( @pytest.mark.parametrize( "y, z, expected_position", [ + (100.855, 101.5115, InOut.IN), (-0.02, 0.1, InOut.OUT), (0.1, 0.1, InOut.UNKNOWN), (10.2, 15.6, InOut.UNKNOWN), @@ -87,6 +88,11 @@ async def test_given_aperture_scatterguard_parked_when_set_to_out_position_then_ assert await scintillator.y_mm.user_setpoint.get_value() == -0.02 assert await scintillator.z_mm.user_setpoint.get_value() == 0.1 + await scintillator.selected_pos.set(InOut.IN) + + assert await scintillator.y_mm.user_setpoint.get_value() == -100.855 + assert await scintillator.z_mm.user_setpoint.get_value() == 101.5115 + async def test_given_aperture_scatterguard_not_parked_when_set_to_out_position_then_exception_raised( scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], @@ -95,9 +101,10 @@ async def test_given_aperture_scatterguard_not_parked_when_set_to_out_position_t if position != ApertureValue.PARKED: scintillator, ap_sg = scintillator_and_ap_sg ap_sg.return_value.selected_aperture.get_value.return_value = position # type: ignore - with pytest.raises(ValueError): await scintillator.selected_pos.set(InOut.OUT) + with pytest.raises(ValueError): + await scintillator.selected_pos.set(InOut.IN) async def test_given_scintillator_already_out_when_moved_out_then_does_nothing( From 05453f9f3ca3fe66fd8f91c73ea0dae2dddfdbd1 Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 13:15:58 +0000 Subject: [PATCH 06/20] get rid of comment! --- tests/devices/test_scintillator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index 1541c370eff..a9c605d34f9 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -90,7 +90,7 @@ async def test_given_aperture_scatterguard_parked_when_set_to_out_position_then_ await scintillator.selected_pos.set(InOut.IN) - assert await scintillator.y_mm.user_setpoint.get_value() == -100.855 + assert await scintillator.y_mm.user_setpoint.get_value() == 100.855 assert await scintillator.z_mm.user_setpoint.get_value() == 101.5115 From 512a9421315aa3475920d61b65c002284816e15f Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 15:26:56 +0000 Subject: [PATCH 07/20] make changes to scintillator.py from comments --- src/dodal/devices/scintillator.py | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 952c7f99820..6fdec341b30 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -55,34 +55,41 @@ def __init__( super().__init__(name) - def _get_selected_position(self, y: float, z: float) -> InOut: - current_pos = [y, z] - if all( + def check_position( + self, current_pos: tuple[float, float], pos_to_check: tuple[float, float] + ): + return all( isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) for axis_pos, axis_in_beam, axis_tolerance in zip( current_pos, - self._scintillator_out_yz_mm, + pos_to_check, self._yz_tolerance_mm, strict=False, ) - ): + ) + + def _get_selected_position(self, y: float, z: float) -> InOut: + current_pos = [y, z] + if self.check_position(current_pos, self._scintillator_out_yz_mm): return InOut.OUT - elif all( - isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) - for axis_pos, axis_in_beam, axis_tolerance in zip( - current_pos, - self._scintillator_in_yz_mm, - self._yz_tolerance_mm, - strict=False, - ) - ): + elif self.check_position(current_pos, self._scintillator_in_yz_mm): return InOut.IN else: return InOut.UNKNOWN + def check_aperture_parked(self): + if ( + self._aperture_scatterguard().selected_aperture.get_value() + != ApertureValue.PARKED + ): + raise ValueError( + "Cannot move scintillator out if aperture/scatterguard is not parked" + ) + async def _set_selected_position(self, position: InOut) -> None: + self.check_aperture_parked() match position: case InOut.OUT: current_y = await self.y_mm.user_readback.get_value() @@ -99,13 +106,6 @@ async def _set_selected_position(self, position: InOut) -> None: await self.y_mm.set(self._scintillator_out_yz_mm[0]) await self.z_mm.set(self._scintillator_out_yz_mm[1]) case InOut.IN: - if ( - self._aperture_scatterguard().selected_aperture.get_value() - != ApertureValue.PARKED - ): - raise ValueError( - "Cannot move scintillator in if aperture/scatterguard is not parked" - ) await self.z_mm.set(self._scintillator_in_yz_mm[1]) await self.y_mm.set(self._scintillator_in_yz_mm[0]) case _: From aa826be018f76d48fa83f136a8779d65825f3e76 Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 15:38:59 +0000 Subject: [PATCH 08/20] make changes from comments to test_scintillator.py --- tests/devices/test_scintillator.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index a9c605d34f9..e20b8ac24c9 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -4,7 +4,7 @@ import pytest from ophyd_async.core import init_devices -from ophyd_async.testing import get_mock_put +from ophyd_async.testing import assert_value, get_mock_put from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters from dodal.devices.aperturescatterguard import ApertureScatterguard, ApertureValue @@ -85,13 +85,20 @@ async def test_given_aperture_scatterguard_parked_when_set_to_out_position_then_ await scintillator.selected_pos.set(InOut.OUT) - assert await scintillator.y_mm.user_setpoint.get_value() == -0.02 - assert await scintillator.z_mm.user_setpoint.get_value() == 0.1 + await assert_value(scintillator.y_mm.user_setpoint, -0.02) + await assert_value(scintillator.z_mm.user_setpoint, -0.1) + + +async def test_given_aperture_scatterguard_parked_when_set_to_in_position_then_returns_expected( + scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], +): + scintillator, ap_sg = scintillator_and_ap_sg + ap_sg.return_value.selected_aperture.get_value.return_value = ApertureValue.PARKED # type: ignore await scintillator.selected_pos.set(InOut.IN) - assert await scintillator.y_mm.user_setpoint.get_value() == 100.855 - assert await scintillator.z_mm.user_setpoint.get_value() == 101.5115 + await assert_value(scintillator.y_mm.user_setpoint, 100.855) + await assert_value(scintillator.z_mm.user_setpoint, 101.5115) async def test_given_aperture_scatterguard_not_parked_when_set_to_out_position_then_exception_raised( From ba13e0264c9c02dfe25c70c107cc84527eb60f8d Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 26 Sep 2025 15:49:32 +0000 Subject: [PATCH 09/20] fix typo --- tests/devices/test_scintillator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index e20b8ac24c9..df9e934dd5b 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -86,7 +86,7 @@ async def test_given_aperture_scatterguard_parked_when_set_to_out_position_then_ await scintillator.selected_pos.set(InOut.OUT) await assert_value(scintillator.y_mm.user_setpoint, -0.02) - await assert_value(scintillator.z_mm.user_setpoint, -0.1) + await assert_value(scintillator.z_mm.user_setpoint, 0.1) async def test_given_aperture_scatterguard_parked_when_set_to_in_position_then_returns_expected( From 9d71e548d55db51935796e4ee2cdcb23cdbf72dd Mon Sep 17 00:00:00 2001 From: Srishty Date: Tue, 30 Sep 2025 13:31:13 +0000 Subject: [PATCH 10/20] make all functions hidden --- src/dodal/devices/scintillator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 6fdec341b30..09faab2355a 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -55,7 +55,7 @@ def __init__( super().__init__(name) - def check_position( + def _check_position( self, current_pos: tuple[float, float], pos_to_check: tuple[float, float] ): return all( @@ -70,16 +70,16 @@ def check_position( def _get_selected_position(self, y: float, z: float) -> InOut: current_pos = [y, z] - if self.check_position(current_pos, self._scintillator_out_yz_mm): + if self._check_position(current_pos, self._scintillator_out_yz_mm): return InOut.OUT - elif self.check_position(current_pos, self._scintillator_in_yz_mm): + elif self._check_position(current_pos, self._scintillator_in_yz_mm): return InOut.IN else: return InOut.UNKNOWN - def check_aperture_parked(self): + def _check_aperture_parked(self): if ( self._aperture_scatterguard().selected_aperture.get_value() != ApertureValue.PARKED @@ -89,7 +89,7 @@ def check_aperture_parked(self): ) async def _set_selected_position(self, position: InOut) -> None: - self.check_aperture_parked() + self._check_aperture_parked() match position: case InOut.OUT: current_y = await self.y_mm.user_readback.get_value() From ec986c0d5dcb8eac18c27412ede4b4c25507efdf Mon Sep 17 00:00:00 2001 From: Srishty Date: Tue, 30 Sep 2025 13:43:40 +0000 Subject: [PATCH 11/20] Change current_pos to a tuple because it was causing lint failing in github CI --- src/dodal/devices/scintillator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 09faab2355a..01f2880275e 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -69,7 +69,7 @@ def _check_position( ) def _get_selected_position(self, y: float, z: float) -> InOut: - current_pos = [y, z] + current_pos = (y, z) if self._check_position(current_pos, self._scintillator_out_yz_mm): return InOut.OUT From c5be74bd1896fb25ea22e63b50dc26fe12b1f50f Mon Sep 17 00:00:00 2001 From: Srishty Date: Thu, 30 Oct 2025 17:40:46 +0000 Subject: [PATCH 12/20] Add opencv docs --- src/dodal/devices/oav/pin_image_recognition/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dodal/devices/oav/pin_image_recognition/utils.py b/src/dodal/devices/oav/pin_image_recognition/utils.py index d1f5fdc440d..fc8b47029a3 100644 --- a/src/dodal/devices/oav/pin_image_recognition/utils.py +++ b/src/dodal/devices/oav/pin_image_recognition/utils.py @@ -14,6 +14,12 @@ class ScanDirections(Enum): REVERSE = -1 +""" +See https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html +for description of functions below. +""" + + def identity(*args, **kwargs) -> Callable[[np.ndarray], np.ndarray]: return lambda arr: arr From 2aaf02fcb8049a200bbbf30d2274e716cc09a0ae Mon Sep 17 00:00:00 2001 From: Srishty Date: Fri, 31 Oct 2025 12:22:43 +0000 Subject: [PATCH 13/20] fix: add awaits --- src/dodal/devices/scintillator.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 01f2880275e..4ec6b604116 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -79,17 +79,17 @@ def _get_selected_position(self, y: float, z: float) -> InOut: else: return InOut.UNKNOWN - def _check_aperture_parked(self): + async def _check_aperture_parked(self): if ( - self._aperture_scatterguard().selected_aperture.get_value() + await self._aperture_scatterguard().selected_aperture.get_value() != ApertureValue.PARKED ): raise ValueError( - "Cannot move scintillator out if aperture/scatterguard is not parked" + f"Cannot move scintillator out if aperture/scatterguard is not parked. Position is currently {await self._aperture_scatterguard().selected_aperture.get_value()}" ) async def _set_selected_position(self, position: InOut) -> None: - self._check_aperture_parked() + await self._check_aperture_parked() match position: case InOut.OUT: current_y = await self.y_mm.user_readback.get_value() From fb5f26cbd4c693ed653e0272e5e7df0006ea27b8 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Thu, 6 Nov 2025 10:27:11 +0000 Subject: [PATCH 14/20] Better mock the aperture scatterguard --- tests/devices/test_scintillator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index df9e934dd5b..e164ca8da26 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -1,6 +1,6 @@ from collections.abc import AsyncGenerator from contextlib import ExitStack -from unittest.mock import MagicMock +from unittest.mock import AsyncMock, MagicMock import pytest from ophyd_async.core import init_devices @@ -32,6 +32,8 @@ async def scintillator_and_ap_sg( ) -> AsyncGenerator[tuple[Scintillator, MagicMock], None]: async with init_devices(mock=True): mock_ap_sg = MagicMock() + mock_ap_sg.return_value.selected_aperture.set = AsyncMock() + mock_ap_sg.return_value.selected_aperture.get_value = AsyncMock() scintillator = Scintillator( prefix="", name="test_scin", From 01d6f026b9e3053a9b0065c7fb74740f33316977 Mon Sep 17 00:00:00 2001 From: Srishty Date: Thu, 6 Nov 2025 14:30:41 +0000 Subject: [PATCH 15/20] fix: fix tests by changing expected type of current_pos in _check_position from tuple to list --- src/dodal/devices/scintillator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 4ec6b604116..0c069bba20d 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -56,7 +56,7 @@ def __init__( super().__init__(name) def _check_position( - self, current_pos: tuple[float, float], pos_to_check: tuple[float, float] + self, current_pos: list[float, float], pos_to_check: tuple[float, float] ): return all( isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) From 21b3eca354636eff99b87f7a9bbd8e1ca4d95599 Mon Sep 17 00:00:00 2001 From: Srishty Date: Mon, 17 Nov 2025 10:38:26 +0000 Subject: [PATCH 16/20] refactor: change error message so it's not specific to just out --- src/dodal/devices/scintillator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 0c069bba20d..37605671c50 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -85,7 +85,7 @@ async def _check_aperture_parked(self): != ApertureValue.PARKED ): raise ValueError( - f"Cannot move scintillator out if aperture/scatterguard is not parked. Position is currently {await self._aperture_scatterguard().selected_aperture.get_value()}" + f"Cannot move scintillator if aperture/scatterguard is not parked. Position is currently {await self._aperture_scatterguard().selected_aperture.get_value()}" ) async def _set_selected_position(self, position: InOut) -> None: From 4ac32aeeb7ac61ddd7c5f73dd7c85a2f79e5e7a8 Mon Sep 17 00:00:00 2001 From: Srishty Date: Mon, 17 Nov 2025 11:32:40 +0000 Subject: [PATCH 17/20] fix: check if already In before attempting to move scint --- src/dodal/devices/scintillator.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 37605671c50..8cfdd6d4104 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -96,13 +96,7 @@ async def _set_selected_position(self, position: InOut) -> None: current_z = await self.z_mm.user_readback.get_value() if self._get_selected_position(current_y, current_z) == InOut.OUT: return - if ( - self._aperture_scatterguard().selected_aperture.get_value() - != ApertureValue.PARKED - ): - raise ValueError( - "Cannot move scintillator out if aperture/scatterguard is not parked" - ) + await self._check_aperture_parked() await self.y_mm.set(self._scintillator_out_yz_mm[0]) await self.z_mm.set(self._scintillator_out_yz_mm[1]) case InOut.IN: From ebd1f6cfe961f233d210dbae2d429add08007c42 Mon Sep 17 00:00:00 2001 From: Srishty Date: Mon, 17 Nov 2025 11:42:15 +0000 Subject: [PATCH 18/20] add test --- src/dodal/devices/scintillator.py | 4 +++- tests/devices/test_scintillator.py | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 8cfdd6d4104..875c84bc042 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -89,7 +89,6 @@ async def _check_aperture_parked(self): ) async def _set_selected_position(self, position: InOut) -> None: - await self._check_aperture_parked() match position: case InOut.OUT: current_y = await self.y_mm.user_readback.get_value() @@ -100,6 +99,9 @@ async def _set_selected_position(self, position: InOut) -> None: await self.y_mm.set(self._scintillator_out_yz_mm[0]) await self.z_mm.set(self._scintillator_out_yz_mm[1]) case InOut.IN: + if self._get_selected_position(current_y, current_z) == InOut.IN: + return + await self._check_aperture_parked() await self.z_mm.set(self._scintillator_in_yz_mm[1]) await self.y_mm.set(self._scintillator_in_yz_mm[0]) case _: diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index e164ca8da26..be3d4521010 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -112,6 +112,15 @@ async def test_given_aperture_scatterguard_not_parked_when_set_to_out_position_t ap_sg.return_value.selected_aperture.get_value.return_value = position # type: ignore with pytest.raises(ValueError): await scintillator.selected_pos.set(InOut.OUT) + + +async def test_given_aperture_scatterguard_not_parked_when_set_to_in_position_then_exception_raised( + scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], +): + for position in ApertureValue: + if position != ApertureValue.PARKED: + scintillator, ap_sg = scintillator_and_ap_sg + ap_sg.return_value.selected_aperture.get_value.return_value = position # type: ignore with pytest.raises(ValueError): await scintillator.selected_pos.set(InOut.IN) From d4a74c1aadde0c77833945161093e392cb97b6b3 Mon Sep 17 00:00:00 2001 From: Srishty Date: Mon, 17 Nov 2025 14:36:35 +0000 Subject: [PATCH 19/20] fix: tests --- src/dodal/devices/scintillator.py | 8 +++---- tests/devices/test_scintillator.py | 36 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/dodal/devices/scintillator.py b/src/dodal/devices/scintillator.py index 875c84bc042..bfa4506b1e7 100644 --- a/src/dodal/devices/scintillator.py +++ b/src/dodal/devices/scintillator.py @@ -55,9 +55,7 @@ def __init__( super().__init__(name) - def _check_position( - self, current_pos: list[float, float], pos_to_check: tuple[float, float] - ): + def _check_position(self, current_pos: list[float], pos_to_check: list[float]): return all( isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance) for axis_pos, axis_in_beam, axis_tolerance in zip( @@ -69,7 +67,7 @@ def _check_position( ) def _get_selected_position(self, y: float, z: float) -> InOut: - current_pos = (y, z) + current_pos = [y, z] if self._check_position(current_pos, self._scintillator_out_yz_mm): return InOut.OUT @@ -99,6 +97,8 @@ async def _set_selected_position(self, position: InOut) -> None: await self.y_mm.set(self._scintillator_out_yz_mm[0]) await self.z_mm.set(self._scintillator_out_yz_mm[1]) case InOut.IN: + current_y = await self.y_mm.user_readback.get_value() + current_z = await self.z_mm.user_readback.get_value() if self._get_selected_position(current_y, current_z) == InOut.IN: return await self._check_aperture_parked() diff --git a/tests/devices/test_scintillator.py b/tests/devices/test_scintillator.py index be3d4521010..8264b03d182 100644 --- a/tests/devices/test_scintillator.py +++ b/tests/devices/test_scintillator.py @@ -103,40 +103,40 @@ async def test_given_aperture_scatterguard_parked_when_set_to_in_position_then_r await assert_value(scintillator.z_mm.user_setpoint, 101.5115) -async def test_given_aperture_scatterguard_not_parked_when_set_to_out_position_then_exception_raised( - scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], -): - for position in ApertureValue: - if position != ApertureValue.PARKED: - scintillator, ap_sg = scintillator_and_ap_sg - ap_sg.return_value.selected_aperture.get_value.return_value = position # type: ignore - with pytest.raises(ValueError): - await scintillator.selected_pos.set(InOut.OUT) - - -async def test_given_aperture_scatterguard_not_parked_when_set_to_in_position_then_exception_raised( - scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], +@pytest.mark.parametrize("scint_pos", [InOut.OUT, InOut.IN]) +async def test_given_aperture_scatterguard_not_parked_when_set_to_in_or_out_position_then_exception_raised( + scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], scint_pos ): for position in ApertureValue: if position != ApertureValue.PARKED: scintillator, ap_sg = scintillator_and_ap_sg ap_sg.return_value.selected_aperture.get_value.return_value = position # type: ignore with pytest.raises(ValueError): - await scintillator.selected_pos.set(InOut.IN) + await scintillator.selected_pos.set(scint_pos) -async def test_given_scintillator_already_out_when_moved_out_then_does_nothing( +@pytest.mark.parametrize( + "y, z, expected_position", + [ + (100.855, 101.5115, InOut.IN), + (-0.02, 0.1, InOut.OUT), + ], +) +async def test_given_scintillator_already_out_when_moved_in_or_out_then_does_nothing( scintillator_and_ap_sg: tuple[Scintillator, ApertureScatterguard], + expected_position, + y, + z, ): scintillator, ap_sg = scintillator_and_ap_sg - await scintillator.y_mm.set(0) - await scintillator.z_mm.set(0) + await scintillator.y_mm.set(y) + await scintillator.z_mm.set(z) get_mock_put(scintillator.y_mm.user_setpoint).reset_mock() get_mock_put(scintillator.z_mm.user_setpoint).reset_mock() ap_sg.return_value.selected_aperture.get_value.return_value = ApertureValue.LARGE # type: ignore - await scintillator.selected_pos.set(InOut.OUT) + await scintillator.selected_pos.set(expected_position) get_mock_put(scintillator.y_mm.user_setpoint).assert_not_called() get_mock_put(scintillator.z_mm.user_setpoint).assert_not_called() From 7d9e67652e18a6f7c05b96035bcdbee5584d2645 Mon Sep 17 00:00:00 2001 From: Srishty Date: Mon, 17 Nov 2025 14:57:00 +0000 Subject: [PATCH 20/20] remove whitespace --- src/dodal/devices/oav/pin_image_recognition/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dodal/devices/oav/pin_image_recognition/utils.py b/src/dodal/devices/oav/pin_image_recognition/utils.py index fc8b47029a3..72a16fcb4d0 100644 --- a/src/dodal/devices/oav/pin_image_recognition/utils.py +++ b/src/dodal/devices/oav/pin_image_recognition/utils.py @@ -15,7 +15,7 @@ class ScanDirections(Enum): """ -See https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html +See https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html for description of functions below. """