feat: trigger iterates steps in bg thread
CI for mx_bec / test (pull_request) Successful in 27s
CI for mx_bec / test (push) Successful in 31s

This commit was merged in pull request #1.
This commit is contained in:
2026-08-19 17:45:28 +02:00
committed by x06da
parent 35454fb2c9
commit 47dd811279
+49 -5
View File
@@ -2,14 +2,14 @@
from __future__ import annotations
import threading
from typing import Literal, cast
from bec_lib.logger import bec_logger
from ophyd import Component as Cpt
from ophyd import Kind, Signal
from ophyd import DeviceStatus, Kind, Signal
from ophyd_devices import EpicsMotorEC
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
from ophyd_devices.utils.psi_device_base_utils import Status
from mx_bec.devices.beam_profile import BeamProfile
@@ -20,6 +20,21 @@ class BeamSteerer(PSIDeviceBase):
"""Based on the beam profile, step towards the centre by moving the focussing mirrors.
Assumes everything is done at max zoom."""
def __init__(
self,
*,
name: str,
prefix: str = "",
scan_info: ScanInfo | None = None,
device_manager: DeviceManagerBase | None = None,
**kwargs,
):
super().__init__(
name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs
)
self._busy = threading.Lock()
self._abort = threading.Event()
# Config
hfm_step_per_x_px = Cpt(Signal, name="hfm_step_per_x_px", kind=Kind.config)
vfm_step_per_y_px = Cpt(Signal, name="hfm_step_per_y_px", kind=Kind.config)
@@ -93,8 +108,37 @@ class BeamSteerer(PSIDeviceBase):
return x_status
if y_status is not None:
return y_status
return Status(done=True)
return None
def _iterate_steps(self, status):
logger.info("Running beam steering...")
step_count = 1
try:
while (_step_status := self.step_towards_centre()) is not None:
logger.info(f"Beam steering iteration: {step_count}")
step_count += 1
if self._abort.is_set():
raise RuntimeError(f"{self.name}: aborted")
_step_status.wait()
except Exception as exc:
status.set_exception(exc)
else:
status.set_finished()
finally:
self._busy.release()
def trigger(self):
"""External interface for 'step_towards_centre'"""
return self.step_towards_centre()
"""External interface for to iterate stepping towards the centre until finished"""
if not self._busy.acquire(blocking=False):
raise RuntimeError(f"{self.name} is still busy")
self._abort.clear()
status = DeviceStatus(self, timeout=60, settle_time=0.0)
threading.Thread(
target=self._iterate_steps, args=(status,), daemon=True, name=f"{self.name}_trigger"
).start()
return status
def stop(self, *, success=False):
self._abort.set()
super().stop(success=success)