Source code for dodal.devices.zebra_controlled_shutter
from enum import Enum
from bluesky.protocols import Movable
from ophyd_async.core import (
DEFAULT_TIMEOUT,
AsyncStatus,
StandardReadable,
wait_for_value,
)
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_w
[docs]
class ZebraShutterState(str, Enum):
CLOSE = "Close"
OPEN = "Open"
[docs]
class ZebraShutterControl(str, Enum):
MANUAL = "Manual"
AUTO = "Auto"
[docs]
class ZebraShutter(StandardReadable, Movable):
"""The shutter on most MX beamlines is controlled by the zebra.
Internally in the zebra there are two AND gates, one for manual control and one for
automatic control. A soft input (aliased to control_mode) will switch between
which of these AND gates to use. For the manual gate the shutter is then controlled
by a different soft input (aliased to _manual_position_setpoint). Both these AND
gates then feed into an OR gate, which then feeds to the shutter."""
def __init__(self, prefix: str, name: str):
self._manual_position_setpoint = epics_signal_w(
ZebraShutterState, prefix + "CTRL2"
)
self.control_mode = epics_signal_rw(ZebraShutterControl, prefix + "CTRL1")
with self.add_children_as_readables():
self.position_readback = epics_signal_r(ZebraShutterState, prefix + "STA")
super().__init__(name=name)
@AsyncStatus.wrap
async def set(self, value: ZebraShutterState):
if await self.control_mode.get_value() == ZebraShutterControl.AUTO:
raise UserWarning(
f"Tried to set shutter to {value.value} but the shutter is in auto mode."
)
await self._manual_position_setpoint.set(value)
return await wait_for_value(
signal=self.position_readback,
match=value,
timeout=DEFAULT_TIMEOUT,
)