Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate napari image parameter to prevent magicgui slowdown #401

Merged
merged 3 commits into from
Apr 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 82 additions & 7 deletions cellfinder/napari/detect/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
):
"""
magicgui widget for setting the signal_image parameter.

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,
):
"""
magicgui widget for setting the background image parameter.

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"),
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -132,9 +178,24 @@ def widget(
reset_button :
Reset parameters to default
"""
# 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
# 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"]

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,
Expand Down Expand Up @@ -226,6 +287,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
Expand Down
Loading