Skip to content

fix(navigation): keep planned-coordinate grid fixed during acquisition#563

Merged
Alpaca233 merged 1 commit into
Cephla-Lab:masterfrom
Alpaca233:fix/live-scan-grid-follows-during-acquisition
Jun 24, 2026
Merged

fix(navigation): keep planned-coordinate grid fixed during acquisition#563
Alpaca233 merged 1 commit into
Cephla-Lab:masterfrom
Alpaca233:fix/live-scan-grid-follows-during-acquisition

Conversation

@Alpaca233

Copy link
Copy Markdown
Collaborator

Problem

During acquisition, the orange grid of planned FOV coordinates in the navigation viewer follows the current stage position instead of staying fixed on the well plate. It tends to appear by the 2nd–3rd acquisition, especially after switching between Current Position and Manual XY modes and changing magnification.

Root cause

The orange "live scan grid" is a positioning preview (WellplateMultiPointWidget.update_live_coordinatesset_live_scan_coordinates) wired to MovementUpdater.position_after_move only while manually navigating. It is supposed to be disconnected for the duration of an acquisition (HighContentScreeningGui.toggleAcquisitionStart). Two defects defeat that:

  1. toggle_live_scan_grid(on=True) connected the signal unconditionally. PyQt removes only one connection per disconnect(), so any double-enable left a dangling connection that the single acquisition-start disconnect could not clear. Duplicates accumulate across acquisitions — which is why it shows up by the 2nd–3rd run.
  2. update_live_coordinates never checked whether an acquisition was running, so a surviving connection redrew the grid on every stage move.

Fix

  • Make toggle_live_scan_grid idempotent (returns early if already in the requested state) so duplicate connections can never form.
  • Make update_live_coordinates a no-op while acquisition_in_progress() — defense in depth that directly enforces the invariant.

The current-position FOV box uses a separate position_after_move connection, so it still tracks the stage during acquisition; only the planned grid is pinned.

Tests

tests/control/test_live_scan_grid.py:

  • test_live_scan_grid_does_not_follow_stage_during_acquisition — the grid stays put during acquisition, and still follows during manual navigation.
  • test_toggle_live_scan_grid_is_idempotent — a redundant enable leaves no dangling connection after a single disable.

Both fail before the fix and pass after. Existing GUI tests still pass.

🤖 Generated with Claude Code

@Alpaca233 Alpaca233 requested a review from Copilot June 23, 2026 18:38
@Alpaca233 Alpaca233 force-pushed the fix/live-scan-grid-follows-during-acquisition branch from 7a98274 to 90e8a0b Compare June 23, 2026 18:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a navigation-viewer regression where the planned-coordinate “live scan grid” (orange overlay) incorrectly re-centers on stage motion during acquisitions, by preventing duplicate Qt signal connections and enforcing a runtime guard during acquisition.

Changes:

  • Make HighContentScreeningGui.toggle_live_scan_grid idempotent to avoid accumulating duplicate position_after_move connections.
  • Make WellplateMultiPointWidget.update_live_coordinates a no-op while multipointController.acquisition_in_progress() is true.
  • Add regression tests covering acquisition behavior and idempotent connect/disconnect behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
software/tests/control/test_live_scan_grid.py Adds regression tests for live scan grid behavior during acquisition and for idempotent signal wiring.
software/control/widgets.py Prevents live-grid updates during acquisition by early-returning in update_live_coordinates.
software/control/gui_hcs.py Prevents duplicate Qt signal connections by making toggle_live_scan_grid idempotent.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +36
def _build_gui(qtbot, monkeypatch):
monkeypatch.setattr(QMessageBox, "question", _confirm_exit)
scope = control.microscope.Microscope.build_from_global_config(True)
win = control.gui_hcs.HighContentScreeningGui(microscope=scope, is_simulation=True)
qtbot.add_widget(win)
The orange "live scan grid" (planned-coordinate overlay) re-centers on the
current stage position via WellplateMultiPointWidget.update_live_coordinates,
which is wired to MovementUpdater.position_after_move only while manually
navigating. It is meant to be disconnected for the duration of an acquisition.

Two defects let it follow the stage during a scan:

1. toggle_live_scan_grid(on=True) connected the signal unconditionally. PyQt
   removes only one connection per disconnect(), so any double-enable left a
   dangling connection that the single acquisition-start disconnect could not
   clear. Duplicates accumulated across acquisitions, so the grid started
   chasing the stage by the 2nd-3rd run.

2. update_live_coordinates never checked whether an acquisition was running,
   so a surviving connection redrew the grid on every stage move.

Fix: make toggle_live_scan_grid idempotent (so duplicate connections can never
form) and make update_live_coordinates a no-op while acquisition_in_progress().
The current-position FOV box uses a separate connection, so it still tracks the
stage; only the planned grid is pinned.

Adds regression tests covering both invariants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Alpaca233 Alpaca233 force-pushed the fix/live-scan-grid-follows-during-acquisition branch from 90e8a0b to e3289a2 Compare June 23, 2026 19:13
@Alpaca233 Alpaca233 merged commit 0306f19 into Cephla-Lab:master Jun 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants