fix(flomni): warn on invalid beamline states before manual xray-eye frame; fix sample-remove slot handling
CI for csaxs_bec / test (push) Successful in 1m35s

xrayeye_update_frame() now checks all configured beamline states and, if any
are not valid, warns the user (the frame may be empty when the beam is down)
and asks before taking a frame. The automated alignment path is unaffected.

ftransfer_sample_change(): clarify the remove-only prompt to "sample currently
in the sample stage", and include tray slot 20 in the empty-slot scan
(range(1, 20) -> range(1, 21)) in both the remove and mount branches, matching
check_position_is_valid's 0-20 range.
This commit is contained in:
x12sa
2026-07-09 12:54:14 +02:00
parent 68a213b52f
commit 0b5666084a
@@ -878,7 +878,7 @@ class FlomniSampleTransferMixin:
raise FlomniError("There is no sample in the sample stage to remove. Aborting.")
empty_slots = []
for j in range(1, 20):
for j in range(1, 21):
if not dev.flomni_samples.is_sample_slot_used(j):
empty_slots.append(j)
if not empty_slots:
@@ -887,7 +887,10 @@ class FlomniSampleTransferMixin:
print(f"The following slots are empty: {empty_slots}.")
while True:
user_input = input(f"Where shall I put the sample? Default: [{empty_slots[0]}] ")
user_input = input(
"Where shall I put the sample currently in the sample stage? "
f"Default: [{empty_slots[0]}] "
)
if user_input.strip() == "":
user_input = empty_slots[0]
@@ -934,7 +937,7 @@ class FlomniSampleTransferMixin:
# continue
# if val.get("value") == 0:
# empty_slots.append(int(name.split("flomni_samples_sample_placed_sample")[1]))
for j in range(1, 20):
for j in range(1, 21):
if not dev.flomni_samples.is_sample_slot_used(j):
empty_slots.append(j)
if not empty_slots:
@@ -1801,7 +1804,45 @@ class Flomni(
umv(dev.fsamx, fsamx_in)
raise exc
def _check_beamline_states_valid(self):
"""Return (all_valid, invalid_labels).
Reads every configured beamline state (bec.beamline_states) and
collects the ones whose status is not "valid" (i.e. "invalid",
"warning" or "unknown"). Used to warn before taking a manual X-ray
eye frame: if e.g. the beam is down, the frame would come back empty
and the user is left confused about why they see nothing.
Returns all_valid=True (with an empty list) if the beamline-state
machinery isn't available at all, so this never blocks on a setup
that doesn't use beamline states.
"""
bec = builtins.__dict__.get("bec")
manager = getattr(bec, "beamline_states", None) if bec is not None else None
if manager is None:
return True, []
bad = []
for name in list(getattr(manager, "_states", {})):
try:
status = manager.get_status_by_name(name)
except Exception: # pylint: disable=broad-except
continue
if status is not None and status != "valid":
bad.append(f"{name}: {status}")
return (len(bad) == 0), bad
def xrayeye_update_frame(self, keep_shutter_open=False):
all_valid, bad_states = self._check_beamline_states_valid()
if not all_valid:
print(
"Attention: not all beamline states are valid:\n "
+ "\n ".join(bad_states)
+ "\nThe beam may be down, so the frame could come back empty."
)
if not self.OMNYTools.yesno("Take a frame anyway?", "n"):
print("Stopping.")
return
self.align.update_frame(keep_shutter_open)
def xrayeye_alignment_start(self, keep_shutter_open=False):