Source code for dodal.devices.i19.shutter

from enum import Enum

from bluesky.protocols import Movable
from ophyd_async.core import AsyncStatus, StandardReadable
from ophyd_async.epics.core import epics_signal_r

from dodal.devices.hutch_shutter import HutchShutter, ShutterDemand
from dodal.log import LOGGER


class HutchInvalidError(Exception):
    pass


[docs] class HutchState(str, Enum): EH1 = "EH1" EH2 = "EH2" INVALID = "INVALID"
[docs] class HutchConditionalShutter(StandardReadable, Movable[ShutterDemand]): """ I19-specific device to operate the hutch shutter. This device evaluates the hutch state value to work out which of the two I19 \ hutches is in use and then implements the HutchShutter device to operate the \ experimental shutter. As the two hutches are located in series, checking the hutch in use is necessary to \ avoid accidentally operating the shutter from one hutch while the other has beamtime. The hutch name should be passed to the device upon instantiation. If this does not \ coincide with the current hutch in use, a warning will be logged and the shutter \ will not be operated. This is to allow for testing of plans. An error will instead be raised if the hutch state reads as "INVALID". """ def __init__(self, prefix: str, hutch: HutchState, name: str = "") -> None: self.shutter = HutchShutter(prefix=prefix, name=name) bl_prefix = prefix.split("-")[0] self.hutch_state = epics_signal_r(str, f"{bl_prefix}-OP-STAT-01:EHStatus.VALA") self.hutch_request = hutch super().__init__(name) @AsyncStatus.wrap async def set(self, value: ShutterDemand): hutch_in_use = await self.hutch_state.get_value() LOGGER.info(f"Current hutch in use: {hutch_in_use}") if hutch_in_use == HutchState.INVALID: raise HutchInvalidError( "The hutch state is invalid. Contact the beamline staff." ) if hutch_in_use != self.hutch_request: # NOTE Warn but don't fail LOGGER.warning( f"{self.hutch_request} is not the hutch in use. Shutter will not be operated." ) else: await self.shutter.set(value)