fix(flomni): skip feedback reset in ffzp_in when FZP already in

feedback_disable/enable_with_reset cycle re-zeros the interferometers
and moves off the current sample position. Only run it when the FZP
actually needs to move; add force_feedback_reset kwarg and _ffzp_is_in
helper.
This commit is contained in:
x12sa
2026-07-08 13:11:24 +02:00
parent 2bfba84512
commit ec21916d58
@@ -72,19 +72,50 @@ class FlomniOpticsMixin:
else:
print("FZP is already at the in position.")
def ffzp_in(self):
return need_move_optics
def ffzp_in(self, force_feedback_reset=False):
"""
move in the flomni zone plate.
This will disable rt feedback, move the FZP and re-enabled the feedback.
This will disable rt feedback, move the FZP and re-enable the feedback.
The FZP move requires rt feedback OFF, and moving the FZP invalidates
the interferometer zero, so feedback is re-enabled *with reset*
afterwards. That reset is expensive: it re-zeros the interferometers
and moves you away from wherever the sample currently sits, which is
undesirable when the FZP is already in and feedback is already running
(e.g. repeated alignment scans, or interleaving an alignment run into a
tomogram).
Therefore the disable/move/reset cycle is skipped entirely when the FZP
does not actually need to move. Pass ``force_feedback_reset=True`` to
force the full disable + reset cycle even if the FZP is already in.
"""
if "rtx" in dev and dev.rtx.enabled:
rtx_present = "rtx" in dev and dev.rtx.enabled
# Only disable feedback if we're going to move the FZP (or a reset was
# explicitly requested). If the FZP is already in and feedback is
# already running, leave it untouched -- disabling and
# re-enabling-with-reset would needlessly re-zero the interferometers.
needs_move = not self._ffzp_is_in()
do_cycle = needs_move or force_feedback_reset
if rtx_present and do_cycle:
dev.rtx.controller.feedback_disable()
self._ffzp_in()
if "rtx" in dev and dev.rtx.enabled:
if rtx_present and do_cycle:
dev.rtx.controller.feedback_enable_with_reset()
def _ffzp_is_in(self, tol=0.003):
"""True if both FZP axes (foptx, fopty) are within ``tol`` of their IN position."""
foptx_in = self._get_user_param_safe("foptx", "in")
fopty_in = self._get_user_param_safe("fopty", "in")
return np.isclose(dev.foptx.readback.get(), foptx_in, atol=tol) and np.isclose(
dev.fopty.readback.get(), fopty_in, atol=tol
)
def foptics_in(self):
"""
Move in the flomni optics, including the FZP and the OSA.
@@ -290,5 +321,4 @@ class FlomniOpticsMixin:
print(
f" Note: OSA is {(-diff)*1000:.1f} um away from its IN position (likely parked OUT)."
)
print(f" Remaining space if OSA is moved to its IN position: \033[1m{remaining_at_in:.1f}\033[0m")
print(f" Remaining space if OSA is moved to its IN position: \033[1m{remaining_at_in:.1f}\033[0m")