feat(flomni): open frontend slit + drop filters on feye_in/feye_out
CI for csaxs_bec / test (push) Successful in 2m16s

feye_in now widens sl1xs/sl1ys by +0.3 mm and sets filter transmission
to 5% before moving the eye in, so there is enough flux/visibility on
the camera. feye_out restores the pre-open slit position (persisted
via a BEC global var so it survives a kernel restart) and fully
removes filters (fil_trans(1)) before checking whether the direct
beam disappeared. If the slit was manually re-adjusted while the eye
was in, feye_out now asks whether to keep the current size instead of
restoring the pre-eye value.

csaxs (for fil_trans) is threaded into Flomni via constructor
injection, gated on the existing "fttrx1 in dev" real-beamline check,
rather than exposing it as a global.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CpPtD7tCRwRZZnREhWcJi8
This commit is contained in:
x12sa
2026-09-16 10:55:35 +02:00
co-authored by Claude Sonnet 5
parent 1ef73f31e4
commit 82e9e8bee1
3 changed files with 50 additions and 2 deletions
@@ -1760,9 +1760,15 @@ class Flomni(
cSAXSBeamlineChecks,
flomniGuiTools,
):
def __init__(self, client):
# Backed by a BEC global var (Redis) so the pre-open slit position
# survives a kernel restart while the eye is still in.
_sl1xs_before_eye = _GlobalVarParam(None)
_sl1ys_before_eye = _GlobalVarParam(None)
def __init__(self, client, csaxs=None):
super().__init__()
self.client = client
self.csaxs = csaxs
self.device_manager = client.device_manager
self.special_angles = []
self.special_angle_repeats = 20
@@ -25,6 +25,36 @@ class FlomniOpticsMixin:
def feye_out(self):
dev.fsh.fshclose()
if self.csaxs is not None:
self.csaxs.fil_trans(1, print_only=False)
sl1xs_before = self._sl1xs_before_eye
sl1ys_before = self._sl1ys_before_eye
if sl1xs_before is not None and sl1ys_before is not None:
# if the slit was manually re-adjusted while the eye was in,
# offer to keep the current size instead of restoring the
# pre-eye value
current_sl1xs = dev.sl1xs.user_readback.get()
current_sl1ys = dev.sl1ys.user_readback.get()
expected_sl1xs = sl1xs_before + 0.3
expected_sl1ys = sl1ys_before + 0.3
tol = 0.01 # mm (10 microns)
manually_adjusted = not np.isclose(
current_sl1xs, expected_sl1xs, atol=tol
) or not np.isclose(current_sl1ys, expected_sl1ys, atol=tol)
if manually_adjusted and self.OMNYTools.yesno(
"sl1xs/sl1ys appear to have been adjusted manually while the "
"eye was in. Keep the current slit size instead of "
"restoring the pre-eye value?"
):
print("Keeping current slit size, not restoring pre-eye value.")
else:
umv(dev.sl1xs, sl1xs_before, dev.sl1ys, sl1ys_before)
self._sl1xs_before_eye = None
self._sl1ys_before_eye = None
self.foptics_in()
self.flomnigui_show_xeyealign()
self.xrayeye_update_frame()
@@ -34,6 +64,7 @@ class FlomniOpticsMixin:
print("Aborting. With visible parts of the direct beam on the xray eye, it cannot be removed.")
return
feyex_out = self._get_user_param_safe("feyex", "out")
umv(dev.feyex, feyex_out)
# move rotation stage to zero to avoid problems with wires
@@ -78,6 +109,14 @@ class FlomniOpticsMixin:
# both already in position → do nothing
pass
else:
if "sl1xs" in dev and "sl1ys" in dev:
self._sl1xs_before_eye = dev.sl1xs.user_readback.get()
self._sl1ys_before_eye = dev.sl1ys.user_readback.get()
scans.umv(dev.sl1xs, 0.3, dev.sl1ys, 0.3, relative=True)
if self.csaxs is not None:
self.csaxs.fil_trans(0.05, print_only=False)
# move both axes to the desired "in" positions
umv(dev.feyex, feyex_in, dev.feyey, feyey_in)
@@ -85,7 +85,10 @@ elif _args.session.lower() == "flomni":
from csaxs_bec.bec_ipython_client.plugins.flomni import Flomni
_session_name = "flomni"
flomni = Flomni(bec)
if "fttrx1" in dev:
flomni = Flomni(bec, csaxs=csaxs)
else:
flomni = Flomni(bec)
logger.success("flomni session loaded.")
print(r"""
██████╗ ███████╗ ██████╗ ███████╗██╗ ██████╗ ███╗ ███╗███╗ ██╗██╗