Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Move WarningException and some oav plans to dodal #1423

Merged
merged 10 commits into from
Jun 12, 2024
Prev Previous commit
Next Next commit
Move associated unit tests to dodal
olliesilvester committed May 30, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 625b09de0ca48c0e962a3f67c328c528cd754657
5 changes: 0 additions & 5 deletions src/hyperion/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
class WarningException(Exception):
"""An exception used when we want to warn GDA of a
problem but continue with UDC anyway"""

pass
110 changes: 1 addition & 109 deletions tests/unit_tests/device_setup_plans/test_setup_oav.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
from functools import partial
from unittest.mock import AsyncMock, MagicMock, patch
from unittest.mock import MagicMock

import numpy as np
import pytest
from bluesky import plan_stubs as bps
from bluesky.run_engine import RunEngine
from dodal.beamlines import i03
from dodal.common.exceptions import WarningException
from dodal.devices.oav.oav_detector import OAV, OAVConfigParams
from dodal.devices.oav.oav_parameters import OAVParameters
from dodal.devices.oav.pin_image_recognition import PinTipDetection
from dodal.devices.oav.pin_image_recognition.utils import SampleLocation
from dodal.devices.oav.utils import (
get_move_required_so_that_beam_is_at_pixel,
wait_for_tip_to_be_found,
)
from dodal.devices.smargon import Smargon
from ophyd.signal import Signal
from ophyd.sim import instantiate_fake_device
from ophyd.status import Status

from hyperion.device_setup_plans.setup_oav import (
@@ -51,31 +41,6 @@ def mock_parameters():
return OAVParameters("loopCentring", OAV_CENTRING_JSON)


def fake_smargon() -> Smargon:
smargon = i03.smargon(fake_with_ophyd_sim=True)
smargon.x.user_setpoint._use_limits = False
smargon.y.user_setpoint._use_limits = False
smargon.z.user_setpoint._use_limits = False
smargon.omega.user_setpoint._use_limits = False

def mock_set(motor, val):
motor.user_readback.sim_put(val) # type: ignore
return Status(done=True, success=True)

def patch_motor(motor):
return patch.object(motor, "set", partial(mock_set, motor))

with patch_motor(smargon.omega), patch_motor(smargon.x), patch_motor(
smargon.y
), patch_motor(smargon.z):
return smargon


@pytest.fixture
def smargon():
yield fake_smargon()


@pytest.mark.parametrize(
"zoom, expected_plugin",
[
@@ -97,47 +62,6 @@ def test_when_set_up_oav_with_different_zoom_levels_then_flat_field_applied_corr
assert oav.grid_snapshot.input_plugin.get() == expected_plugin


@pytest.mark.parametrize(
"px_per_um, beam_centre, angle, pixel_to_move_to, expected_xyz",
[
# Simple case of beam being in the top left and each pixel being 1 mm
([1000, 1000], [0, 0], 0, [100, 190], [100, 190, 0]),
([1000, 1000], [0, 0], -90, [50, 250], [50, 0, 250]),
([1000, 1000], [0, 0], 90, [-60, 450], [-60, 0, -450]),
# Beam offset
([1000, 1000], [100, 100], 0, [100, 100], [0, 0, 0]),
([1000, 1000], [100, 100], -90, [50, 250], [-50, 0, 150]),
# Pixels_per_micron different
([10, 50], [0, 0], 0, [100, 190], [1, 9.5, 0]),
([60, 80], [0, 0], -90, [50, 250], [3, 0, 20]),
],
)
def test_values_for_move_so_that_beam_is_at_pixel(
smargon: Smargon,
oav: OAV,
px_per_um,
beam_centre,
angle,
pixel_to_move_to,
expected_xyz,
):
oav.parameters.micronsPerXPixel = px_per_um[0]
oav.parameters.micronsPerYPixel = px_per_um[1]
oav.parameters.beam_centre_i = beam_centre[0]
oav.parameters.beam_centre_j = beam_centre[1]

smargon.omega.user_readback.sim_put(angle) # type: ignore

RE = RunEngine(call_returns_result=True)
pos = RE(
get_move_required_so_that_beam_is_at_pixel(
smargon, pixel_to_move_to, oav.parameters
)
).plan_result

assert pos == pytest.approx(expected_xyz)


def test_when_set_up_oav_then_only_waits_on_oav_to_finish(
mock_parameters: OAVParameters, oav: OAV, ophyd_pin_tip_detection: PinTipDetection
):
@@ -152,35 +76,3 @@ def my_plan():

RE = RunEngine()
RE(my_plan())


@pytest.mark.asyncio
async def test_given_tip_found_when_wait_for_tip_to_be_found_called_then_tip_immediately_returned():
mock_pin_tip_detect: PinTipDetection = instantiate_fake_device(
PinTipDetection, name="pin_detect"
)
await mock_pin_tip_detect.connect(mock=True)
mock_pin_tip_detect._get_tip_and_edge_data = AsyncMock(
return_value=SampleLocation(100, 100, np.array([]), np.array([]))
)
RE = RunEngine(call_returns_result=True)
result = RE(wait_for_tip_to_be_found(mock_pin_tip_detect))
assert result.plan_result == (100, 100) # type: ignore
mock_pin_tip_detect._get_tip_and_edge_data.assert_called_once()


@pytest.mark.asyncio
async def test_given_no_tip_when_wait_for_tip_to_be_found_called_then_exception_thrown():
mock_pin_tip_detect: PinTipDetection = instantiate_fake_device(
PinTipDetection, name="pin_detect"
)
await mock_pin_tip_detect.connect(mock=True)
await mock_pin_tip_detect.validity_timeout.set(0.2)
mock_pin_tip_detect._get_tip_and_edge_data = AsyncMock(
return_value=SampleLocation(
*PinTipDetection.INVALID_POSITION, np.array([]), np.array([])
)
)
RE = RunEngine(call_returns_result=True)
with pytest.raises(WarningException):
RE(wait_for_tip_to_be_found(mock_pin_tip_detect))
Original file line number Diff line number Diff line change
@@ -18,8 +18,6 @@
from hyperion.parameters.constants import CONST
from hyperion.parameters.gridscan import GridScanWithEdgeDetect, ThreeDGridScan

from ..device_setup_plans.test_setup_oav import fake_smargon


def _fake_grid_detection(
devices: Any,
@@ -30,7 +28,7 @@ def _fake_grid_detection(
box_size_um: float = 0.0,
):
oav = i03.oav(fake_with_ophyd_sim=True)
smargon = fake_smargon()
smargon = i03.smargon(fake_with_ophyd_sim=True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: This isn't equivalent as fake_smargon patched the motors too. Can you use the smargon() in conftest here?

oav.grid_snapshot.box_width.put(635.00986)

# first grid detection: x * y