From 26e7fddfc68b76870f54911f82c844ea3fb59c6d Mon Sep 17 00:00:00 2001 From: x01dc Date: Thu, 23 Jul 2026 15:25:20 +0200 Subject: [PATCH] fix(LamNI): ensure OSA is out before requesting the FZP-centre click Both align() and find_rotation_center() moved the FZP in and immediately asked the operator to click its centre, but only confirmed OSA was out afterwards (via loptics_out(), which runs after that click). If OSA was left in from a previous scan setup, it would still be in the beam path during the FZP reference click. Add an explicit losa_out() call right before lfzp_in() in both procedures; it's a cheap, skip-if-already-out no-op otherwise. Found while testing find_rotation_center() against the simulated LamNI. Co-Authored-By: Claude Sonnet 5 --- .../bec_ipython_client/plugins/LamNI/x_ray_eye_align.py | 8 ++++++++ tests/tests_bec_ipython_client/test_x_ray_eye_align.py | 1 + 2 files changed, 9 insertions(+) diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py index 9ddb38e..1624795 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py @@ -254,6 +254,10 @@ class XrayEyeAlign: self.alignment_images = [] # --- Step 0: FZP centre ------------------------------------------ + # OSA must be confirmed out before the FZP click is requested -- it + # otherwise stays wherever it was left by a previous scan setup until + # loptics_out() below, which only runs *after* this click. + self.lamni.losa_out() #self._disable_rt_feedback() # force_feedback_reset=True: this is the start of a fresh alignment # run, so the interferometer reference must always be freshly @@ -740,6 +744,10 @@ class XrayEyeAlign: # --- FZP reference (step 0) ----------------------------------- self.send_message("Getting things ready. Please wait...") + # OSA must be confirmed out before the FZP click is requested -- it + # otherwise stays wherever it was left by a previous scan setup until + # loptics_out() below, which only runs *after* this click. + self.lamni.losa_out() self.lamni.lfzp_in(force_feedback_reset=True) self.update_frame(keep_shutter_open) fzp_x, fzp_y = self._collect_click(0, "Submit centre of FZP.", label="FZP reference") diff --git a/tests/tests_bec_ipython_client/test_x_ray_eye_align.py b/tests/tests_bec_ipython_client/test_x_ray_eye_align.py index 0e4b58a..810ac84 100644 --- a/tests/tests_bec_ipython_client/test_x_ray_eye_align.py +++ b/tests/tests_bec_ipython_client/test_x_ray_eye_align.py @@ -155,6 +155,7 @@ def _make_calibration_align(client): align.lamni.xeyegui = mock.MagicMock() align.lamni.lfzp_in = mock.MagicMock() align.lamni.loptics_out = mock.MagicMock() + align.lamni.losa_out = mock.MagicMock() align.lamni.lamnigui_show_xeyealign = mock.MagicMock() # Replace the real Scans proxy (which would try to talk to a live scan # server) with a plain mock -- these tests only care that