From 5ebd8a76da3c96d35bc7ef14abc8045cb210c525 Mon Sep 17 00:00:00 2001 From: Matt Einhorn Date: Sun, 14 Apr 2024 01:50:41 -0400 Subject: [PATCH 1/3] Separate image parameter to prevent magicgui slowdown. --- cellfinder/napari/detect/detect.py | 79 +++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/cellfinder/napari/detect/detect.py b/cellfinder/napari/detect/detect.py index 396f90b6..c70a4a01 100644 --- a/cellfinder/napari/detect/detect.py +++ b/cellfinder/napari/detect/detect.py @@ -39,6 +39,59 @@ def detect_widget() -> FunctionGui: """ progress_bar = ProgressBar() + # options that is filled in from the gui + options = {"signal_image": None, "background_image": None, "viewer": None} + + # signal and background images are separated out from the main magicgui + # parameter selections and are inserted as widget children in their own + # sub-containers of the root. Because if these image parameters are + # included in the root widget, every time *any* parameter updates, the gui + # freezes for a bit likely because magicgui is processing something for + # all the parameters when any parameter changes. And this processing takes + # particularly long for image parameters. Placing them as sub-containers + # alleviates this + @magicgui( + call_button=False, + persist=False, + scrollable=False, + labels=False, + auto_call=True, + ) + def signal_image_opt( + viewer: napari.Viewer, + signal_image: napari.layers.Image, + ): + """ + Run detection and classification. + + Parameters + ---------- + signal_image : napari.layers.Image + Image layer containing the labelled cells + """ + options["signal_image"] = signal_image + options["viewer"] = viewer + + @magicgui( + call_button=False, + persist=False, + scrollable=False, + labels=False, + auto_call=True, + ) + def background_image_opt( + background_image: napari.layers.Image, + ): + """ + Run detection and classification. + + Parameters + ---------- + background_image : napari.layers.Image + Image layer without labelled cells + """ + options["background_image"] = background_image + @magicgui( header=header_label_widget, detection_label=html_label_widget("Cell detection", tag="h3"), @@ -55,9 +108,6 @@ def widget( header, detection_label, data_options, - viewer: napari.Viewer, - signal_image: napari.layers.Image, - background_image: napari.layers.Image, voxel_size_z: float, voxel_size_y: float, voxel_size_x: float, @@ -86,10 +136,6 @@ def widget( Parameters ---------- - signal_image : napari.layers.Image - Image layer containing the labelled cells - background_image : napari.layers.Image - Image layer without labelled cells voxel_size_z : float Size of your voxels in the axial dimension voxel_size_y : float @@ -132,9 +178,14 @@ def widget( reset_button : Reset parameters to default """ + signal_image = options["signal_image"] + background_image = options["background_image"] + viewer = options["viewer"] + if signal_image is None or background_image is None: show_info("Both signal and background images must be specified.") return + data_inputs = DataInputs( signal_image.data, background_image.data, @@ -226,6 +277,20 @@ def restore_defaults(): # Insert progress bar before the run and reset buttons widget.insert(-3, progress_bar) + # add the signal and background image parameters + # make it look as if it's directly in the root container + signal_image_opt.margins = 0, 0, 0, 0 + # the parameters are updated using `auto_call` only. If False, magicgui + # passes these as args to widget(), which doesn't list them as args + signal_image_opt.gui_only = True + widget.insert(3, signal_image_opt) + widget.signal_image_opt.label = "Signal image" + + background_image_opt.margins = 0, 0, 0, 0 + background_image_opt.gui_only = True + widget.insert(4, background_image_opt) + widget.background_image_opt.label = "Background image" + scroll = QScrollArea() scroll.setWidget(widget._widget._qwidget) widget._widget._qwidget = scroll From bb44187bd3bcaa390fea6daaa16564845d68986a Mon Sep 17 00:00:00 2001 From: Matt Einhorn Date: Sun, 14 Apr 2024 02:17:32 -0400 Subject: [PATCH 2/3] Fix parameters not initialized. --- cellfinder/napari/detect/detect.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cellfinder/napari/detect/detect.py b/cellfinder/napari/detect/detect.py index c70a4a01..62d34776 100644 --- a/cellfinder/napari/detect/detect.py +++ b/cellfinder/napari/detect/detect.py @@ -178,6 +178,16 @@ def widget( reset_button : Reset parameters to default """ + # we must manually call so that the paramters of these functions are + # initialized and updated. Becuase, if the images are open in napari + # before we open cellfinder, then these functions may never be called, + # even though the image filenames are shown properly in the parameters + # in the gui. Likely auto_call doesn't make magicgui call the functions + # in this circumstance, only if the parameters are updated once + # cellfinder plugin is fully open and initialized + signal_image_opt() + background_image_opt() + signal_image = options["signal_image"] background_image = options["background_image"] viewer = options["viewer"] From 4f8e369f74d4f443cbd411d31d29299bfc850cd8 Mon Sep 17 00:00:00 2001 From: Matt Einhorn Date: Mon, 15 Apr 2024 13:37:40 -0400 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Igor Tatarnikov <61896994+IgorTatarnikov@users.noreply.github.com> --- cellfinder/napari/detect/detect.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cellfinder/napari/detect/detect.py b/cellfinder/napari/detect/detect.py index 62d34776..6bde5153 100644 --- a/cellfinder/napari/detect/detect.py +++ b/cellfinder/napari/detect/detect.py @@ -62,7 +62,7 @@ def signal_image_opt( signal_image: napari.layers.Image, ): """ - Run detection and classification. + magicgui widget for setting the signal_image parameter. Parameters ---------- @@ -83,7 +83,7 @@ def background_image_opt( background_image: napari.layers.Image, ): """ - Run detection and classification. + magicgui widget for setting the background image parameter. Parameters ---------- @@ -178,8 +178,8 @@ def widget( reset_button : Reset parameters to default """ - # we must manually call so that the paramters of these functions are - # initialized and updated. Becuase, if the images are open in napari + # we must manually call so that the parameters of these functions are + # initialized and updated. Because, if the images are open in napari # before we open cellfinder, then these functions may never be called, # even though the image filenames are shown properly in the parameters # in the gui. Likely auto_call doesn't make magicgui call the functions