Source code for dodal.devices.i03.beamstop
from asyncio import gather
from math import isclose
from ophyd_async.core import StandardReadable, StrictEnum
from ophyd_async.epics.motor import Motor
from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters
from dodal.common.signal_utils import create_hardware_backed_soft_signal
[docs]
class BeamstopPositions(StrictEnum):
"""
Beamstop positions.
GDA supports Standard/High/Low resolution positions, as well as parked and
robot load however all 3 resolution positions are the same. We also
do not use the robot load position in Hyperion.
Until we support moving the beamstop it is only necessary to check whether the
beamstop is in beam or not.
See Also:
https://github.com/DiamondLightSource/mx-bluesky/issues/484
Attributes:
DATA_COLLECTION: The beamstop is in beam ready for data collection
UNKNOWN: The beamstop is in some other position, check the device motor
positions to determine it.
"""
DATA_COLLECTION = "Data Collection"
UNKNOWN = "Unknown"
[docs]
class Beamstop(StandardReadable):
"""
Beamstop for I03.
Attributes:
x: beamstop x position in mm
y: beamstop y position in mm
z: beamstop z position in mm
selected_pos: Get the current position of the beamstop as an enum. Currently this
is read-only.
"""
def __init__(
self,
prefix: str,
beamline_parameters: GDABeamlineParameters,
name: str = "",
):
with self.add_children_as_readables():
self.x_mm = Motor(prefix + "X")
self.y_mm = Motor(prefix + "Y")
self.z_mm = Motor(prefix + "Z")
self.selected_pos = create_hardware_backed_soft_signal(
BeamstopPositions, self._get_selected_position
)
self._in_beam_xyz_mm = [
float(beamline_parameters[f"in_beam_{axis}_STANDARD"])
for axis in ("x", "y", "z")
]
self._xyz_tolerance_mm = [
float(beamline_parameters[f"bs_{axis}_tolerance"])
for axis in ("x", "y", "z")
]
super().__init__(name)
async def _get_selected_position(self) -> BeamstopPositions:
current_pos = await gather(
self.x_mm.user_readback.get_value(),
self.y_mm.user_readback.get_value(),
self.z_mm.user_readback.get_value(),
)
if all(
isclose(axis_pos, axis_in_beam, abs_tol=axis_tolerance)
for axis_pos, axis_in_beam, axis_tolerance in zip(
current_pos, self._in_beam_xyz_mm, self._xyz_tolerance_mm, strict=False
)
):
return BeamstopPositions.DATA_COLLECTION
else:
return BeamstopPositions.UNKNOWN