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
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ install_requires =
ophyd-async >= 0.3a5
bluesky >= 1.13.0a3
blueapi >= 0.4.3-a1
dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git
dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@57c30448e1e7ac8fb31c9f645441547819e4d163

[options.entry_points]
console_scripts =
Expand Down
2 changes: 1 addition & 1 deletion src/hyperion/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
from blueapi.core import BlueskyContext, MsgGenerator
from bluesky.callbacks.zmq import Publisher
from bluesky.run_engine import RunEngine
from dodal.common.exceptions import WarningException
from flask import Flask, request
from flask_restful import Api, Resource
from pydantic.dataclasses import dataclass

from hyperion.exceptions import WarningException
from hyperion.experiment_plans.experiment_registry import (
PLAN_REGISTRY,
PlanNotFound,
Expand Down
56 changes: 1 addition & 55 deletions src/hyperion/device_setup_plans/setup_oav.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
from functools import partial
from typing import Generator, Tuple

import bluesky.plan_stubs as bps
import numpy as np
from bluesky.utils import Msg
from dodal.devices.oav.oav_calculations import camera_coordinates_to_xyz
from dodal.devices.oav.oav_detector import OAV, OAVConfigParams
from dodal.devices.oav.oav_detector import OAV
from dodal.devices.oav.oav_errors import OAVError_ZoomLevelNotFound
from dodal.devices.oav.oav_parameters import OAVParameters
from dodal.devices.oav.pin_image_recognition import PinTipDetection
from dodal.devices.oav.utils import ColorMode
from dodal.devices.smargon import Smargon

from hyperion.exceptions import WarningException

Pixel = Tuple[int, int]
oav_group = "oav_setup"
# Helper function to make sure we set the waiting groups correctly
set_using_group = partial(bps.abs_set, group=oav_group)
Expand Down Expand Up @@ -94,49 +86,3 @@ def pre_centring_setup_oav(
"""
TODO: We require setting the backlight brightness to that in the json, we can't do this currently without a PV.
"""


def calculate_x_y_z_of_pixel(
current_x_y_z, current_omega, pixel: Pixel, oav_params: OAVConfigParams
) -> np.ndarray:
beam_distance_px: Pixel = oav_params.calculate_beam_distance(*pixel)

assert oav_params.micronsPerXPixel
assert oav_params.micronsPerYPixel
return current_x_y_z + camera_coordinates_to_xyz(
beam_distance_px[0],
beam_distance_px[1],
current_omega,
oav_params.micronsPerXPixel,
oav_params.micronsPerYPixel,
)


def get_move_required_so_that_beam_is_at_pixel(
smargon: Smargon, pixel: Pixel, oav_params: OAVConfigParams
) -> Generator[Msg, None, np.ndarray]:
"""Calculate the required move so that the given pixel is in the centre of the beam."""

current_motor_xyz = np.array(
[
(yield from bps.rd(smargon.x)),
(yield from bps.rd(smargon.y)),
(yield from bps.rd(smargon.z)),
],
dtype=np.float64,
)
current_angle = yield from bps.rd(smargon.omega)

return calculate_x_y_z_of_pixel(current_motor_xyz, current_angle, pixel, oav_params)


def wait_for_tip_to_be_found(
ophyd_pin_tip_detection: PinTipDetection,
) -> Generator[Msg, None, Pixel]:
yield from bps.trigger(ophyd_pin_tip_detection, wait=True)
found_tip = yield from bps.rd(ophyd_pin_tip_detection.triggered_tip)
if found_tip == ophyd_pin_tip_detection.INVALID_POSITION:
timeout = yield from bps.rd(ophyd_pin_tip_detection.validity_timeout)
raise WarningException(f"No pin found after {timeout} seconds")

return found_tip # type: ignore
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
2 changes: 1 addition & 1 deletion src/hyperion/experiment_plans/flyscan_xray_centre_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import bluesky.preprocessors as bpp
import numpy as np
from blueapi.core import BlueskyContext, MsgGenerator
from dodal.common.exceptions import WarningException
from dodal.devices.aperturescatterguard import (
ApertureScatterguard,
SingleAperturePosition,
Expand Down Expand Up @@ -50,7 +51,6 @@
from hyperion.device_setup_plans.xbpm_feedback import (
transmission_and_xbpm_feedback_for_collection_decorator,
)
from hyperion.exceptions import WarningException
from hyperion.log import LOGGER
from hyperion.parameters.constants import CONST
from hyperion.parameters.gridscan import ThreeDGridScan
Expand Down
2 changes: 1 addition & 1 deletion src/hyperion/experiment_plans/oav_grid_detection_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
from dodal.devices.oav.oav_detector import OAV
from dodal.devices.oav.pin_image_recognition import PinTipDetection
from dodal.devices.oav.pin_image_recognition.utils import NONE_VALUE
from dodal.devices.oav.utils import wait_for_tip_to_be_found
from dodal.devices.smargon import Smargon

from hyperion.device_setup_plans.setup_oav import (
pre_centring_setup_oav,
wait_for_tip_to_be_found,
)
from hyperion.log import LOGGER
from hyperion.parameters.constants import CONST
Expand Down
10 changes: 5 additions & 5 deletions src/hyperion/experiment_plans/pin_tip_centring_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
import numpy as np
from blueapi.core import BlueskyContext
from bluesky.utils import Msg
from dodal.common.exceptions import WarningException
from dodal.devices.backlight import Backlight
from dodal.devices.oav.oav_detector import OAV
from dodal.devices.oav.oav_parameters import OAV_CONFIG_JSON, OAVParameters
from dodal.devices.oav.pin_image_recognition import PinTipDetection
from dodal.devices.smargon import Smargon

from hyperion.device_setup_plans.setup_oav import (
from dodal.devices.oav.utils import (
Pixel,
get_move_required_so_that_beam_is_at_pixel,
pre_centring_setup_oav,
wait_for_tip_to_be_found,
)
from hyperion.exceptions import WarningException
from dodal.devices.smargon import Smargon

from hyperion.device_setup_plans.setup_oav import pre_centring_setup_oav
from hyperion.log import LOGGER
from hyperion.parameters.constants import CONST
from hyperion.utils.context import device_composite_from_context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import numpy as np
from bluesky.callbacks import CallbackBase
from dodal.devices.oav.oav_detector import OAVConfigParams
from dodal.devices.oav.utils import calculate_x_y_z_of_pixel
from event_model.documents import Event

from hyperion.device_setup_plans.setup_oav import calculate_x_y_z_of_pixel
from hyperion.log import LOGGER


Expand Down
2 changes: 1 addition & 1 deletion src/hyperion/external_interaction/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from hyperion.exceptions import WarningException
from dodal.common.exceptions import WarningException


class ISPyBDepositionNotMade(Exception):
Expand Down
2 changes: 1 addition & 1 deletion tests/system_tests/experiment_plans/test_fgs_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
BEAMLINE_PARAMETER_PATHS,
GDABeamlineParameters,
)
from dodal.common.exceptions import WarningException
from dodal.devices.aperturescatterguard import AperturePositions
from dodal.devices.smargon import Smargon
from ophyd.status import Status
Expand All @@ -23,7 +24,6 @@
from hyperion.device_setup_plans.xbpm_feedback import (
transmission_and_xbpm_feedback_for_collection_decorator,
)
from hyperion.exceptions import WarningException
from hyperion.experiment_plans.flyscan_xray_centre_plan import (
FlyScanXRayCentreComposite,
flyscan_xray_centre,
Expand Down
108 changes: 1 addition & 107 deletions tests/unit_tests/device_setup_plans/test_setup_oav.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
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.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.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 (
get_move_required_so_that_beam_is_at_pixel,
pre_centring_setup_oav,
wait_for_tip_to_be_found,
)
from hyperion.exceptions import WarningException

ZOOM_LEVELS_XML = "tests/test_data/test_jCameraManZoomLevels.xml"
OAV_CENTRING_JSON = "tests/test_data/test_OAVCentring.json"
Expand Down Expand Up @@ -49,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",
[
Expand All @@ -95,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
):
Expand All @@ -150,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
Expand Up @@ -11,6 +11,7 @@
from bluesky.utils import FailedStatus, Msg
from dodal.beamlines import i03
from dodal.common.beamlines.beamline_utils import clear_device
from dodal.common.exceptions import WarningException
from dodal.devices.detector.det_dim_constants import (
EIGER2_X_4M_DIMENSION,
EIGER_TYPE_EIGER2_X_4M,
Expand All @@ -27,7 +28,6 @@
read_hardware_for_ispyb_during_collection,
read_hardware_for_ispyb_pre_collection,
)
from hyperion.exceptions import WarningException
from hyperion.experiment_plans.flyscan_xray_centre_plan import (
FlyScanXRayCentreComposite,
flyscan_xray_centre,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from bluesky.run_engine import RunEngine
from bluesky.utils import Msg
from dodal.beamlines import i03
from dodal.common.exceptions import WarningException
from dodal.devices.backlight import Backlight
from dodal.devices.oav.oav_detector import 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 NONE_VALUE, SampleLocation
from dodal.devices.smargon import Smargon

from hyperion.exceptions import WarningException
from hyperion.experiment_plans.oav_grid_detection_plan import (
OavGridDetectionComposite,
get_min_and_max_y_of_pin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pytest
from bluesky.run_engine import RunEngine
from bluesky.utils import Msg
from dodal.common.exceptions import WarningException
from dodal.devices.detector.det_dim_constants import (
EIGER2_X_4M_DIMENSION,
EIGER_TYPE_EIGER2_X_4M,
Expand All @@ -23,7 +24,6 @@
read_hardware_for_ispyb_during_collection,
read_hardware_for_ispyb_pre_collection,
)
from hyperion.exceptions import WarningException
from hyperion.experiment_plans.flyscan_xray_centre_plan import (
FlyScanXRayCentreComposite,
)
Expand Down
Loading
Loading