From 0f75672c0ad1ddc8b3f309f70cb56c1fd89ba09c Mon Sep 17 00:00:00 2001 From: Paddy Roddy Date: Thu, 27 Jul 2023 11:15:09 +0100 Subject: [PATCH] Keep label with widget --- btrack/napari/main.py | 4 +- btrack/napari/widgets/_general.py | 10 ++--- btrack/napari/widgets/_hypothesis.py | 65 +++++++++++----------------- btrack/napari/widgets/_motion.py | 20 ++++----- btrack/napari/widgets/create_ui.py | 28 ++++++++---- 5 files changed, 60 insertions(+), 67 deletions(-) diff --git a/btrack/napari/main.py b/btrack/napari/main.py index efdf978a..3e1094ea 100644 --- a/btrack/napari/main.py +++ b/btrack/napari/main.py @@ -46,8 +46,8 @@ def create_btrack_widget() -> Container: # First create our UI along with some default configs for the widgets all_configs = btrack.napari.config.create_default_configs() - btrack_widget = btrack.napari.BtrackWidget( - viewer=napari.current_viewer(), + btrack_widget = btrack.napari.widgets.BtrackWidget( + napari_viewer=napari.current_viewer(), ) # Set the cell_config defaults in the gui diff --git a/btrack/napari/widgets/_general.py b/btrack/napari/widgets/_general.py index 75ef4a8e..e906ae99 100644 --- a/btrack/napari/widgets/_general.py +++ b/btrack/napari/widgets/_general.py @@ -8,22 +8,20 @@ def create_input_widgets() -> dict[str, QtWidgets.QWidget]: # TODO: annotation=napari.layers.Labels, segmentation = QtWidgets.QComboBox() - segmentation.setName("segmentation") segmentation.setToolTip( "Select a 'Labels' layer to use for tracking.\n" "To use an 'Image' layer, first convert 'Labels' by right-clicking " "on it in the layers list, and clicking on 'Convert to Labels'" ) - widgets = {"segmentation": segmentation} + widgets = {"segmentation": ("segmentation", segmentation)} config = QtWidgets.QComboBox() config.addItems(["cell", "particle"]) - config.setName("config") config.setTooltip( "Select a loaded configuration.\n" "Note, this will update values set below." ) - widgets["config"] = config + widgets["config"] = ("config", config) return widgets @@ -49,8 +47,8 @@ def create_update_method_widgets() -> dict[str, QtWidgets.QWidget]: max_search_radius = QtWidgets.QSPinBox() max_search_radius.setRange(0, 1000) max_search_radius.setSingleStep(1) - max_search_radius.setWrapping(True) # noqa: FBT003 - max_search_radius.setTooltip = ( + max_search_radius.setWrapping(w=True) + max_search_radius.setTooltip( "The local spatial search radius (isotropic, pixels) used when the update " "method is 'APPROXIMATE'" ) diff --git a/btrack/napari/widgets/_hypothesis.py b/btrack/napari/widgets/_hypothesis.py index 785d718b..407382af 100644 --- a/btrack/napari/widgets/_hypothesis.py +++ b/btrack/napari/widgets/_hypothesis.py @@ -22,10 +22,9 @@ def _create_hypotheses_widgets() -> dict[str, QtWidgets.QWidget]: hypotheses_widgets = {} for hypothesis, tooltip in zip(hypotheses, tooltips): widget = QtWidgets.QCheckBox() - widget.setName(hypothesis) widget.setToolTip(tooltip) - widget.setCheckState(True) # noqa: FBT003 - hypotheses_widgets[hypothesis] = widget + widget.setCheckState(state=True) + hypotheses_widgets[hypothesis] = (hypothesis, widget) # P_FP is always required P_FP_hypothesis = hypotheses_widgets[0] @@ -65,10 +64,10 @@ def _create_scaling_factor_widgets() -> dict[str, QtWidgets.QWidget]: for value, name, label, tooltip in zip( widget_values, names, labels, tooltips ): - scaling_factor_widgets[name] = QtWidgets.QDoubleSpinBox() - scaling_factor_widgets[name].setName(label) - scaling_factor_widgets[name].setToolTip(tooltip) - scaling_factor_widgets[name].setValue(value) + widget = QtWidgets.QDoubleSpinBox() + widget.setToolTip(tooltip) + widget.setValue(value) + scaling_factor_widgets[name] = (label, widget) return scaling_factor_widgets @@ -77,31 +76,28 @@ def _create_threshold_widgets() -> dict[str, QtWidgets.QWidget]: """Create widgets for setting thresholds for the HypothesisModel""" distance_threshold = QtWidgets.QDoubleSpinBox() - distance_threshold.setName("distance threshold") distance_threshold.setToolTip( "A threshold distance from the edge of the field of view to add an " "initialization or termination hypothesis." ) distance_threshold.setValue(20.0) - widgets = {"theta_dist": distance_threshold} + widgets = {"theta_dist": ("distance threshold", distance_threshold)} time_threshold = QtWidgets.QDoubleSpinBox() - time_threshold.setName("time threshold") time_threshold.setToolTip( "A threshold time from the beginning or end of movie to add " "an initialization or termination hypothesis." ) time_threshold.setValue(5.0) - widgets["theta_time"] = time_threshold + widgets["theta_time"] = ("time threshold", time_threshold) apoptosis_threshold = QtWidgets.QSpinBox() - apoptosis_threshold.setName("apoptosis threshold") apoptosis_threshold.setToolTip( "Number of apoptotic detections to be considered a genuine event.\n" "Detections are counted consecutively from the back of the track" ) apoptosis_threshold.setValue(5) - widgets["apop_thresh"] = apoptosis_threshold + widgets["apop_thresh"] = ("apoptosis threshold", apoptosis_threshold) return widgets @@ -110,22 +106,20 @@ def _create_bin_size_widgets() -> dict[str, QtWidgets.QWidget]: """Create widget for setting bin sizes for the HypothesisModel""" distance_bin_size = QtWidgets.QDoubleSpinBox() - distance_bin_size.setName("distance bin size") distance_bin_size.setToolTip( "Isotropic spatial bin size for considering hypotheses.\n" "Larger bin sizes generate more hypothesese for each tracklet." ) distance_bin_size.setValue(40.0) - widgets = {"dist_thresh": distance_bin_size} + widgets = {"dist_thresh": ("distance bin size", distance_bin_size)} time_bin_size = QtWidgets.QDoubleSpinBox() - time_bin_size.setName("time bin size") time_bin_size.setToolTip( "Temporal bin size for considering hypotheses.\n" "Larger bin sizes generate more hypothesese for each tracklet." ) time_bin_size.setValue(2.0) - widgets["time_thresh"] = time_bin_size + widgets["time_thresh"] = ("time bin size", time_bin_size) return widgets @@ -134,39 +128,32 @@ def create_hypothesis_model_widgets() -> dict[str, QtWidgets.QWidget]: """Create widgets for setting parameters of the MotionModel""" hypothesis_model_label = QtWidgets.QLabel() - hypothesis_model_label.setName("Hypothesis model") # bold label - widgets = {"hypothesis": hypothesis_model_label} - - hypotheses_widgets = _create_hypotheses_widgets() - scaling_factor_widgets = _create_scaling_factor_widgets() - threshold_widgets = _create_threshold_widgets() - bin_size_widgets = _create_bin_size_widgets() + widgets = { + "hypothesis": ("Hypothesis model", hypothesis_model_label) + } + + widgets |= ( + _create_hypotheses_widgets() + | _create_scaling_factor_widgets() + | _create_threshold_widgets() + | _create_bin_size_widgets() + ) segmentation_miss_rate = QtWidgets.QDoubleSpinBox() - segmentation_miss_rate.setName("miss rate") segmentation_miss_rate.setToolTip( "Miss rate for the segmentation.\n" "e.g. 1/100 segmentations incorrect gives a segmentation miss rate of 0.01." ) segmentation_miss_rate.setValue(0.1) - widgets["segmentation_miss_rate"] = segmentation_miss_rate + widgets["segmentation_miss_rate"] = ("miss rate", segmentation_miss_rate) relax = QtWidgets.QCheckBox() - relax.setName("relax thresholds") relax.setToolTip( "Disable the time and distance thresholds.\n" "This means that tracks can initialize or terminate anywhere and" "at any time in the dataset." ) - relax.setCheckState(True) # noqa: FBT003 - widgets["relax"] = relax - - return [ - hypothesis_model_label, - *hypotheses_widgets, - *scaling_factor_widgets, - *threshold_widgets, - *bin_size_widgets, - segmentation_miss_rate, - relax, - ] + relax.setCheckState(state=True) + widgets["relax"] = ("relax thresholds", relax) + + return widgets diff --git a/btrack/napari/widgets/_motion.py b/btrack/napari/widgets/_motion.py index a8395f08..1f6d3b47 100644 --- a/btrack/napari/widgets/_motion.py +++ b/btrack/napari/widgets/_motion.py @@ -13,29 +13,26 @@ def _create_sigma_widgets() -> dict[str, QtWidgets.QWidget]: """Create widgets for setting the magnitudes of the MotionModel matrices""" P_sigma = QtWidgets.QDoubleSpinBox() - P_sigma.setName(f"max({_make_label_bold('P')})") P_sigma.setToolTip( "Magnitude of error in initial estimates.\n" "Used to scale the matrix P." ) P_sigma.setValue(150.0) - widgets = {"P_sigma": P_sigma} + widgets = {"P_sigma": (f"max({_make_label_bold('P')})", P_sigma)} G_sigma = QtWidgets.QDoubleSpinBox() - G_sigma.setName(f"max({_make_label_bold('G')})") G_sigma.setToolTip( "Magnitude of error in process.\n Used to scale the matrix G." ) G_sigma.setValue(15.0) - widgets["G_sigma"] = G_sigma + widgets["G_sigma"] = (f"max({_make_label_bold('G')})", G_sigma) R_sigma = QtWidgets.QDoubleSpinBox() - R_sigma.setName(f"max({_make_label_bold('R')})") R_sigma.setToolTip( "Magnitude of error in measurements.\n Used to scale the matrix R." ) R_sigma.setValue(5.0) - widgets["R_sigma"] = R_sigma + widgets["R_sigma"] = (f"max({_make_label_bold('R')})", R_sigma) return widgets @@ -44,23 +41,22 @@ def create_motion_model_widgets() -> dict[str, QtWidgets.QWidget]: """Create widgets for setting parameters of the MotionModel""" motion_model_label = QtWidgets.QLabel() - motion_model_label.setName(_make_label_bold("Motion model")) - widgets = {"motion_model": motion_model_label} + widgets = { + "motion_model": (_make_label_bold("Motion model"), motion_model_label) + } widgets |= _create_sigma_widgets() accuracy = QtWidgets.QDoubleSpinBox() - accuracy.setName("accuracy") accuracy.setToolTip("Integration limits for calculating probabilities") accuracy.setValue(7.5) - widgets["accuracy"] = accuracy + widgets["accuracy"] = ("accuracy", accuracy) max_lost_frames = QtWidgets.QSpinBox() - max_lost_frames.setName("max lost") max_lost_frames.setToolTip( "Number of frames without observation before marking as lost" ) max_lost_frames.setValue(5) - widgets["max_lost"] = max_lost_frames + widgets["max_lost"] = ("max lost", max_lost_frames) return widgets diff --git a/btrack/napari/widgets/create_ui.py b/btrack/napari/widgets/create_ui.py index 34accb61..c9b07332 100644 --- a/btrack/napari/widgets/create_ui.py +++ b/btrack/napari/widgets/create_ui.py @@ -67,48 +67,60 @@ def __init__(self, napari_viewer: Viewer) -> None: def _add_input_widgets(self): """Create input widgets and add to main layout""" - self._input_widgets = create_input_widgets() + labels_and_widgets = create_input_widgets() + self._input_widgets = { + key: value.widget for key, value in labels_and_widgets.items() + } self._widgets.update(self._input_widgets) widget = QtWidgets.QWidget() layout = QtWidgets.QFormLayout() - for label, widget in self._input_widgets: + for label, widget in labels_and_widgets.values(): layout.addRow(label, widget) widget.setLayout(layout) self._layout.addWidget(widget) def _add_update_method_widgets(self): """Create update method widgets and add to main layout""" - self._update_method_widgets = create_update_method_widgets() + labels_and_widgets = create_update_method_widgets() + self._update_method_widgets = { + key: value.widget for key, value in labels_and_widgets.items() + } self._widgets.update(self._update_method_widgets) widget = QtWidgets.QWidget() layout = QtWidgets.QFormLayout() - for label, widget in self._update_method_widgets: + for label, widget in labels_and_widgets.values(): layout.addRow(label, widget) widget.setLayout(layout) self._layout.addWidget(widget) def _add_motion_model_widgets(self): """Create motion model widgets and add to main layout""" - self._motion_model_widgets = create_motion_model_widgets() + labels_and_widgets = create_motion_model_widgets() + self._motion_model_widgets = { + key: value.widget for key, value in labels_and_widgets.items() + } self._widgets.update(self._motion_model_widgets) widget = QtWidgets.QWidget() layout = QtWidgets.QFormLayout() - for label, widget in self._motion_model_widgets: + for label, widget in labels_and_widgets.values(): layout.addRow(label, widget) widget.setLayout(layout) self._layout.addWidget(widget) def _add_hypothesis_model_widgets(self): """Create hypothesis model widgets and add to main layout""" - self._hypothesis_model_widgets = create_hypothesis_model_widgets() + labels_and_widgets = create_hypothesis_model_widgets() + self._hypothesis_model_widgets = { + key: value.widget for key, value in labels_and_widgets.items() + } self._widgets.update(self._hypothesis_model_widgets) widget = QtWidgets.QWidget() layout = QtWidgets.QFormLayout() - for label, widget in self._hypothesis_model_widgets: + for label, widget in labels_and_widgets.values(): layout.addRow(label, widget) widget.setLayout(layout) self._layout.addWidget(widget)