Skip to content

Commit e34fab3

Browse files
Add channel-aware defocus reference status (#1225)
* Add channel-aware defocus plan * Implement channel-aware defocus calibration * Add visible defocus reference status Display the active defocus reference in the main Channel Settings table so users can see whether the zero-defocus plane is set and which channel/focus position established it. Update the autofocus popup channel selector to use CH labels while preserving channel_n keys internally, and publish captured autofocus references to the main GUI. Publish runtime zero-defocus reference updates from microscope channel preparation and clear the reference when manual focus moves invalidate it. Tests cover autofocus channel label conversion, main-GUI defocus reference updates, and model reference publication/clearing. * Fix autofocus test execute mock leakage Scope the mocked parent_controller.execute with patch.object in the autofocus calibration test so the package-scoped dummy_controller restores its real execute method after the assertion. This fixes the Windows CI order failure where camera view move_stage tests ran after the autofocus test and saw an empty command list because DummyController.execute had been replaced by a MagicMock. Confirmed the failure locally with the autofocus/camera-view ordering reproducer before the fix, then verified the reproducer and the affected controller test files pass in the navigate conda environment. * Prepare autofocus channel in feature init Move target-channel preparation out of Autofocus.run() and into the signal init hook so standalone autofocus and live-mode injected autofocus share the same channel-selection behavior. This addresses the PR review concern that live autofocus injection preserves target channel args but bypasses Autofocus.run(), which previously meant prepare_channel() was never called for the injected feature instance. Tests now verify that run() only orchestrates standalone autofocus loading while pre_func_signal() prepares either the requested channel or the next selected channel fallback. * Restore defocus reference after autofocus completion Autofocus stage moves publish a transient defocus_reference=None event through the model, which can clear the main Channel Settings label during Regular and Populate Defocus runs. Capture Reference already republished the saved reference after completion. Extend that restoration to other autofocus completions whenever an autofocus calibration reference exists, so the main GUI label does not remain at Not Set after Populate Defocus or Regular autofocus. Adds regression coverage for Populate Defocus and Regular autofocus completion preserving the saved defocus reference event. * add "Auto Defocus" option and warning info if selected channel is not activated * fix tests * fix(defocus): handle pre-existing values correctly * update doc * fix tests * Update test_channels_tab.py * docs: design PR 1225 GUI refresh * docs: refresh defocus GUI screenshots * docs: explain channel defocus calibration * docs: complete PR 1225 GUI plan --------- Co-authored-by: Annie Wang <annie.xd.wang@gmail.com>
1 parent 8fc54c3 commit e34fab3

28 files changed

Lines changed: 2110 additions & 80 deletions

‎.gitignore‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,5 @@ test.xml
299299
/docs/source/05_reference/_autosummary
300300
/docs/source/05_reference/_autosummary
301301
codex.md
302-
uv.lock
302+
uv.lock
303+
.worktrees/

‎docs/capture_gui.py‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,19 @@ def _build_controller_context() -> Dict[str, object]:
227227
root.withdraw()
228228
splash_screen = SplashScreen(root, _splash_image_path())
229229

230+
config_dir = SRC_DIR / "navigate" / "config"
230231
parser = create_parser()
231-
args = parser.parse_args(["-sh"])
232+
args = parser.parse_args(
233+
[
234+
"-sh",
235+
"--config-file",
236+
str(config_dir / "configuration.yaml"),
237+
"--experiment-file",
238+
str(config_dir / "experiment.yml"),
239+
"--gui-config-file",
240+
str(config_dir / "gui_configuration.yml"),
241+
]
242+
)
232243

233244
(
234245
configuration_path,
@@ -1590,10 +1601,22 @@ def _capture_popup_save_dialog_bdv_settings(
15901601
def _capture_popup_autofocus(
15911602
ctx: Dict[str, object], cli_args: argparse.Namespace
15921603
) -> str:
1593-
from navigate.view.popups.autofocus_setting_popup import AutofocusPopup
1604+
controller = ctx["controller"]
1605+
out_path, should_skip = _popup_capture_target(cli_args, "autofocus_settings")
1606+
if should_skip:
1607+
return out_path
1608+
1609+
_cleanup_controller_popup_attr(controller, "af_popup_controller")
1610+
controller.menu_controller.popup_autofocus_setting()
1611+
popup_controller = controller.af_popup_controller
1612+
popup_controller.widgets["calibration_action"].set("Auto Defocus")
1613+
popup = popup_controller.view.popup
15941614

1595-
popup_obj = AutofocusPopup(ctx["controller"].view)
1596-
return _capture_popup_obj(ctx, cli_args, popup_obj, "autofocus_settings")
1615+
try:
1616+
_prepare_for_capture(popup, cli_args)
1617+
return _capture_widget(popup, out_path, pad=2)
1618+
finally:
1619+
_cleanup_controller_popup_attr(controller, "af_popup_controller")
15971620

15981621

15991622
def _capture_popup_camera_map_settings(

‎docs/source/01_getting_started/06_acquiring_data.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Configure the Channel Settings
5454

5555
* Specify the camera :guilabel:`Exp. Time (ms)`. A good default value is ``100`` or ``200`` ms.
5656
* Specify the :guilabel:`Interval` to be ``1.0``. While this feature is not currently implemented, future releases will allow users to image different channels at different time intervals.
57-
* Specify the :guilabel:`Defocus` to be ``0``. This feature allows you to adjust for chromatic aberrations that result in focal shifts between each imaging channel.
57+
* Set :guilabel:`Defocus` to ``0`` unless the channel has a measured chromatic focus offset. Defocus is a per-channel offset from the zero-defocus focus position, not an absolute focus coordinate. At acquisition start, **navigate** derives that zero-defocus position from the current focus and the active channel's defocus, then applies each channel's offset. The status below the table reports the current reference; see :ref:`Autofocus Settings <ui_autofocus>` to measure channel offsets automatically.
5858

5959
---------------------------------------
6060

‎docs/source/02_user_guide/03_user_interface_walkthrough/03_acquisition_and_settings_notebooks.rst‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,13 @@ Use this section to define active imaging channels and per-channel acquisition v
6060
3. :guilabel:`Filter`: detection filter.
6161
4. :guilabel:`Exp. Time (ms)`: camera exposure time.
6262
5. :guilabel:`Interval`: channel cadence relative to other channels.
63-
6. :guilabel:`Defocus`: channel-specific focus offset.
63+
6. :guilabel:`Defocus`: channel-specific offset from the zero-defocus focus position.
64+
65+
At acquisition start, **navigate** derives the zero-defocus position from the
66+
current focus and the active channel's defocus. It then moves each channel to
67+
that reference position plus the channel's offset. :guilabel:`Defocus Reference`
68+
shows the reference channel and, when an acquisition reference is active, its
69+
focus position. Manual focus motion invalidates the active acquisition reference.
6470

6571
.. _ui_stack_settings:
6672

‎docs/source/02_user_guide/03_user_interface_walkthrough/06_popups_and_tools.rst‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ region of highest contrast (best focus). Spline-fit and test-significance
5252
buttons are already present in preparation for additional intelligent autofocus
5353
functionality in future updates.
5454

55+
The :guilabel:`Channel` must be active in Channel Settings. Choose a
56+
:guilabel:`Calibration` action before pressing :guilabel:`Start Autofocus`:
57+
58+
* :guilabel:`Regular` focuses the selected channel without calculating a channel
59+
offset.
60+
* :guilabel:`Capture Reference` focuses the selected channel, makes it the
61+
zero-defocus calibration channel, and retains its best-focus position for the
62+
current calibration sequence.
63+
* :guilabel:`Populate Defocus` focuses the selected channel and writes the
64+
difference from the previously captured reference into that channel's
65+
:guilabel:`Defocus` value. Capture a reference first.
66+
* :guilabel:`Auto Defocus` uses the selected channel as the reference, focuses
67+
every other active channel, and populates all active channel offsets in one
68+
sequence. Stop any acquisition before starting it.
69+
70+
The popup's :guilabel:`Reference` status reports the calibration reference.
71+
:guilabel:`Populate Defocus` requires the captured focus retained by the current
72+
popup session. The resulting per-channel :guilabel:`Defocus` values are stored
73+
with the experiment settings and are used during acquisition.
74+
5575
.. _ui_waveform_parameters:
5676

5777
Waveform Parameters

‎docs/source/images/ChannelsTab.png‎

-5.74 KB
Loading
-1.97 KB
Loading
11.5 KB
Loading

0 commit comments

Comments
 (0)