Source code for dodal.devices.oav.utils

from collections.abc import Generator
from enum import IntEnum

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 OAVConfigParams
from dodal.devices.oav.pin_image_recognition import PinTipDetection
from dodal.devices.smargon import Smargon

Pixel = tuple[int, int]


class PinNotFoundException(Exception):
    pass


[docs] def bottom_right_from_top_left( top_left: np.ndarray, steps_x: int, steps_y: int, step_size_x: float, step_size_y: float, um_per_pix_x: float, um_per_pix_y: float, ) -> np.ndarray: return np.array( [ # step size is given in mm, pix in um int(steps_x * step_size_x * 1000 / um_per_pix_x + top_left[0]), int(steps_y * step_size_y * 1000 / um_per_pix_y + top_left[1]), ], dtype=np.dtype(int), )
[docs] class ColorMode(IntEnum): """ Enum to store the various color modes of the camera. We use RGB1. """ MONO = 0 BAYER = 1 RGB1 = 2 RGB2 = 3 RGB3 = 4 YUV444 = 5 YUV422 = 6 YUV421 = 7
[docs] class EdgeOutputArrayImageType(IntEnum): """ Enum to store the types of image to tweak the output array. We use Original. """ ORIGINAL = 0 GREYSCALE = 1 PREPROCESSED = 2 CANNY_EDGES = 3 CLOSED_EDGES = 4
[docs] 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)
[docs] 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, )
[docs] 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 PinNotFoundException(f"No pin found after {timeout} seconds") return found_tip # type: ignore