From 566dfcd0dd29d441059302a4c48eaad55568a544 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:11:00 +0200 Subject: [PATCH 01/17] added new scatter controls, put them in groups and connected visibility/invisibility settings --- .../_new_plotter_widget.py | 31 +-- src/napari_clusters_plotter/plotter_inputs.ui | 217 +++++++++++------- 2 files changed, 140 insertions(+), 108 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index fd018d49..7573a938 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -118,7 +118,6 @@ def _setup_ui(self, napari_viewer): ) # Setting Visibility Defaults - self.control_widget.cmap_container.setVisible(False) self.control_widget.bins_settings_container.setVisible(False) self.control_widget.additional_options_container.setVisible(False) @@ -209,30 +208,6 @@ def _on_finish_draw(self, color_indices: np.ndarray): self.plot_needs_update.emit() - def _handle_advanced_options_widget_visibility(self): - """ - Control visibility of overlay colormap box and log scale checkbox - based on the selected hue axis and active artist. - """ - active_artist = self.plotting_widget.active_artist - # Control visibility of overlay colormap box and log scale checkbox - if self.hue_axis in self.categorical_columns: - self.control_widget.overlay_cmap_box.setEnabled(False) - self.control_widget.log_scale_checkbutton.setEnabled(False) - if isinstance(active_artist, Histogram2D): - # Enable if histogram to allow log scale of histogram itself - self.control_widget.log_scale_checkbutton.setEnabled(True) - else: - self.control_widget.overlay_cmap_box.setEnabled(True) - self.control_widget.log_scale_checkbutton.setEnabled(True) - - if isinstance(active_artist, Histogram2D): - self.control_widget.cmap_container.setVisible(True) - self.control_widget.bins_settings_container.setVisible(True) - else: - self.control_widget.cmap_container.setVisible(False) - self.control_widget.bins_settings_container.setVisible(False) - def _reset_axes_labels(self): """ Clear the x and y axis labels in the plotting widget. @@ -267,7 +242,6 @@ def _replot(self): overlay_cmap = self.colormap_reference[ (self.hue_axis in self.categorical_columns, self.plotting_type) ] - self._handle_advanced_options_widget_visibility() self._reset_axes_labels() active_artist = self.plotting_widget.active_artist active_artist.x_label_text = self.x_axis @@ -347,11 +321,16 @@ def _on_plot_type_changed(self): cat10_mod_cmap_first_transparent ) + self.control_widget.scatter_settings_container.setVisible(False) + self.control_widget.bins_settings_container.setVisible(True) + elif self.plotting_type == PlottingType.SCATTER.name: self.plotting_widget.active_artist = "SCATTER" self.plotting_widget.active_artist.overlay_colormap = ( cat10_mod_cmap ) + self.control_widget.scatter_settings_container.setVisible(True) + self.control_widget.bins_settings_container.setVisible(False) self.plot_needs_update.emit() def _on_overlay_colormap_changed(self): diff --git a/src/napari_clusters_plotter/plotter_inputs.ui b/src/napari_clusters_plotter/plotter_inputs.ui index d944858a..518003e4 100644 --- a/src/napari_clusters_plotter/plotter_inputs.ui +++ b/src/napari_clusters_plotter/plotter_inputs.ui @@ -23,7 +23,7 @@ - 0 + 1 @@ -116,6 +116,26 @@ + + + + + + + <html><head/><body><p>Continuous colormap to display a feature as colors over plotted data.</p><p>Use the eye button in the plotter controls to hide/show the overlay colors.</p><p>To enale this, select a non-categorical feature in the <span style=" font-weight:600;">Hue</span> Combobox.</p></body></html> + + + + + + + Overlay Colormap + + + + + + @@ -139,120 +159,130 @@ - - - - - - - <html><head/><body><p>Continuous colormap to display a feature as colors over plotted data.</p><p>Use the eye button in the plotter controls to hide/show the overlay colors.</p><p>To enale this, select a non-categorical feature in the <span style=" font-weight:600;">Hue</span> Combobox.</p></body></html> + + + + Scatter controls + + + + + + Activate frame highlighting - - + + - Overlay Colormap + Point size - - - - - - - true - - - - - - Number of Bins + + + + 1 - - - - true + + + + Qt::Horizontal - - - - - true - - - Auto - - - true - - - - - - - false - - - 1 - - - 10000 - - - 20 - - - - - + + QSizePolicy::Minimum + + + + 40 + 20 + + + - - - - - + + + + + 0 + 0 + + + + Histogram controls + + + + + + true + - Histogram Colormap + Auto + + + true - + <html><head/><body><p>Continuous colormap to display the histogram data (not the colors overlay).</p></body></html> - - - - - - - false - - - - + + + + false + + + 1 + + + 10000 + + + 20 + + + + + - Hide non-selected clusters + Histogram Colormap - - + + - + Number of Bins + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + @@ -260,6 +290,29 @@ + + + + false + + + + + + + + + + + + + Hide non-selected clusters + + + + + + From 4206b394128fc9fafd998cfd8854cbc41e55c6c8 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:23:18 +0200 Subject: [PATCH 02/17] connect frame highlighting functionality --- .../_new_plotter_widget.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 7573a938..b929a8c9 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -182,6 +182,10 @@ def _setup_callbacks(self): self._on_bin_auto_toggled ) + self.control_widget.checkBox_frame_highlighting.toggled.connect( + self._on_frame_highlighting_toggled + ) + def _on_finish_draw(self, color_indices: np.ndarray): """ Called when user finsihes drawing. Will change the hue combo box to the @@ -298,6 +302,9 @@ def _on_frame_changed(self, event: napari.utils.events.Event): Called when the frame changes. Updates the alpha values of the points. """ + if not self.frame_highlighting_activated: + return + if "frame" in self._get_features().columns: current_step = self.viewer.dims.current_step[0] alpha = np.asarray( @@ -358,8 +365,33 @@ def _on_bin_auto_toggled(self, state: bool): self.control_widget.n_bins_box.setEnabled(not state) self.plot_needs_update.emit() + def _on_frame_highlighting_toggled(self): + """ + Called when the frame highlighting checkbox is toggled. + Updates the visibility of the frame highlighting in the plot. + """ + # do nothing for histogram2d + if self.plotting_widget.active_artist == "HISTOGRAM2D": + return + + if self.frame_highlighting_activated: + self._on_frame_changed(None) + else: + self.plotting_widget.active_artist.alpha = np.ones( + len(self._get_features()), dtype=float + ) # Reset alpha to 1 for all points + # Connecting the widgets to actual object variables: # using getters and setters for flexibility + + @property + def frame_highlighting_activated(self): + return self.control_widget.checkBox_frame_highlighting.isChecked() + + @frame_highlighting_activated.setter + def frame_highlighting(self, val: bool): + self.control_widget.checkBox_frame_highlighting.setChecked(val) + @property def log_scale(self): return self.control_widget.log_scale_checkbutton.isChecked() From b84c6f825b7e437440292e39a825fc4c549b2630 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:39:25 +0200 Subject: [PATCH 03/17] Ensure correct frame highlighting for new layers --- src/napari_clusters_plotter/_new_plotter_widget.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index b929a8c9..51414171 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -533,6 +533,9 @@ def _on_update_layer_selection( f"Layer {layer.name} does not have events.features or events.properties" ) + # make sure we use the correct frame highlighting settings + self._on_frame_highlighting_toggled() + def _clean_up(self): """In case of empty layer selection""" From b8827a1fd3e1efdd4243b768a1dab9d1748511e7 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:39:36 +0200 Subject: [PATCH 04/17] added point size setting --- .../_new_plotter_widget.py | 30 +++++++++++++++++-- src/napari_clusters_plotter/plotter_inputs.ui | 3 ++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 51414171..94b0959f 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -186,6 +186,10 @@ def _setup_callbacks(self): self._on_frame_highlighting_toggled ) + self.control_widget.spinBox_point_size.valueChanged.connect( + self._on_point_size_changed + ) + def _on_finish_draw(self, color_indices: np.ndarray): """ Called when user finsihes drawing. Will change the hue combo box to the @@ -310,11 +314,11 @@ def _on_frame_changed(self, event: napari.utils.events.Event): alpha = np.asarray( self._get_features()["frame"] == current_step, dtype=float ) - size = np.ones(len(alpha)) * 50 + size = np.ones(len(alpha)) * self.scatter_point_size index_out_of_frame = alpha == 0 alpha[index_out_of_frame] = 0.25 - size[index_out_of_frame] = 35 + size[index_out_of_frame] = self.scatter_point_size * 0.5 self.plotting_widget.active_artist.alpha = alpha self.plotting_widget.active_artist.size = size @@ -371,7 +375,7 @@ def _on_frame_highlighting_toggled(self): Updates the visibility of the frame highlighting in the plot. """ # do nothing for histogram2d - if self.plotting_widget.active_artist == "HISTOGRAM2D": + if self.plotting_type == "HISTOGRAM2D": return if self.frame_highlighting_activated: @@ -381,9 +385,29 @@ def _on_frame_highlighting_toggled(self): len(self._get_features()), dtype=float ) # Reset alpha to 1 for all points + def _on_point_size_changed(self): + """ + Called when the point size is changed. + Updates the size of the points in the scatter plot. + """ + + if self.plotting_type != "SCATTER": + return + + self.plotting_widget.active_artist.size = self.scatter_point_size + self.plot_needs_update.emit() + # Connecting the widgets to actual object variables: # using getters and setters for flexibility + @property + def scatter_point_size(self): + return self.control_widget.spinBox_point_size.value() + + @scatter_point_size.setter + def scatter_point_size(self, val: int): + self.control_widget.spinBox_point_size.setValue(val) + @property def frame_highlighting_activated(self): return self.control_widget.checkBox_frame_highlighting.isChecked() diff --git a/src/napari_clusters_plotter/plotter_inputs.ui b/src/napari_clusters_plotter/plotter_inputs.ui index 518003e4..afebfc1e 100644 --- a/src/napari_clusters_plotter/plotter_inputs.ui +++ b/src/napari_clusters_plotter/plotter_inputs.ui @@ -184,6 +184,9 @@ 1 + + 30 + From defac88a843c127d7051e2573d82f88d5a22f5a8 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:07:07 +0200 Subject: [PATCH 05/17] use default values for alpha and size for better testing --- src/napari_clusters_plotter/_new_plotter_widget.py | 8 ++++++-- src/napari_clusters_plotter/_tests/test_plotter.py | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 94b0959f..90494ed2 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -45,6 +45,10 @@ def __init__(self, napari_viewer): self.layers_being_unselected = [] self._on_update_layer_selection(None) self._setup_callbacks() + + # some default values + self._out_of_frame_alpha = 0.25 + self._out_of_frame_size_factor = 0.5 self.plot_needs_update.connect(self._replot) @@ -317,8 +321,8 @@ def _on_frame_changed(self, event: napari.utils.events.Event): size = np.ones(len(alpha)) * self.scatter_point_size index_out_of_frame = alpha == 0 - alpha[index_out_of_frame] = 0.25 - size[index_out_of_frame] = self.scatter_point_size * 0.5 + alpha[index_out_of_frame] = self._out_of_frame_alpha + size[index_out_of_frame] = self.scatter_point_size * self._out_of_frame_size_factor self.plotting_widget.active_artist.alpha = alpha self.plotting_widget.active_artist.size = size diff --git a/src/napari_clusters_plotter/_tests/test_plotter.py b/src/napari_clusters_plotter/_tests/test_plotter.py index c6d56040..69ea20cc 100644 --- a/src/napari_clusters_plotter/_tests/test_plotter.py +++ b/src/napari_clusters_plotter/_tests/test_plotter.py @@ -510,8 +510,10 @@ def test_temporal_highlighting(make_napari_viewer, create_sample_layers): # check that the dots in the plotter widget update alpha and size # to highlight out-of and in-frame data points - assert plotter_widget.plotting_widget.active_artist.alpha.min() == 0.25 - assert plotter_widget.plotting_widget.active_artist.size.min() == 35 + oof_size = plotter_widget.scatter_point_size * plotter_widget._out_of_frame_size_factor + oof_alpha = plotter_widget._out_of_frame_alpha + assert plotter_widget.plotting_widget.active_artist.alpha.min() == oof_alpha + assert plotter_widget.plotting_widget.active_artist.size.min() == oof_size @pytest.mark.parametrize( From a7261c76d28766e20e02f5725d51295b6b2f3d4d Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:07:28 +0200 Subject: [PATCH 06/17] added test for new UI options --- .../_tests/test_plotter.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/napari_clusters_plotter/_tests/test_plotter.py b/src/napari_clusters_plotter/_tests/test_plotter.py index 69ea20cc..1fdfbc6c 100644 --- a/src/napari_clusters_plotter/_tests/test_plotter.py +++ b/src/napari_clusters_plotter/_tests/test_plotter.py @@ -555,6 +555,41 @@ def test_histogram_support(make_napari_viewer, create_sample_layers): plotter_widget.plotting_type = "SCATTER" +# only points is enough here +@pytest.mark.parametrize( + "create_sample_layers", + [ + create_multi_point_layer, + ], +) +def test_scatter_advanced_options(make_napari_viewer, create_sample_layers): + from napari_clusters_plotter import PlotterWidget + viewer = make_napari_viewer() + layer, layer2 = create_sample_layers() + + # add layers to viewer + viewer.add_layer(layer) + viewer.add_layer(layer2) + plotter_widget = PlotterWidget(viewer) + viewer.window.add_dock_widget(plotter_widget, area="right") + + plotter_widget.scatter_point_size = 10 + assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) + + plotter_widget.frame_highlighting_activated = True + assert ~ np.all( + plotter_widget.plotting_widget.active_artist.alpha == 1 + ) + + # select multiple layers and make sure that plot parameters are correct + viewer.layers.selection = (layer, layer2) + assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) + assert ~ np.all( + plotter_widget.plotting_widget.active_artist.alpha == 1 + ) + + + @pytest.mark.parametrize( "create_sample_layers", [ From 5ed1d7c44f5e07816b2c54f99b05e11532096633 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:07:42 +0200 Subject: [PATCH 07/17] make frame highlighting activated by default --- src/napari_clusters_plotter/plotter_inputs.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/napari_clusters_plotter/plotter_inputs.ui b/src/napari_clusters_plotter/plotter_inputs.ui index afebfc1e..0c0f66b3 100644 --- a/src/napari_clusters_plotter/plotter_inputs.ui +++ b/src/napari_clusters_plotter/plotter_inputs.ui @@ -170,6 +170,9 @@ Activate frame highlighting + + true + From 41e8e269be64205e8c07fbc60f09df962ba961a0 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:07:55 +0200 Subject: [PATCH 08/17] correct property setter --- src/napari_clusters_plotter/_new_plotter_widget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 90494ed2..939d9a0c 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -417,7 +417,7 @@ def frame_highlighting_activated(self): return self.control_widget.checkBox_frame_highlighting.isChecked() @frame_highlighting_activated.setter - def frame_highlighting(self, val: bool): + def frame_highlighting_activated(self, val: bool): self.control_widget.checkBox_frame_highlighting.setChecked(val) @property From 7433c318916487af0a403948ee69e9ed770377f5 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:08:14 +0200 Subject: [PATCH 09/17] remove unnecessary plot refresh --- src/napari_clusters_plotter/_new_plotter_widget.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 939d9a0c..ff0a247f 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -397,9 +397,7 @@ def _on_point_size_changed(self): if self.plotting_type != "SCATTER": return - self.plotting_widget.active_artist.size = self.scatter_point_size - self.plot_needs_update.emit() # Connecting the widgets to actual object variables: # using getters and setters for flexibility From 249572df759f491b80060724a2a51f723c681422 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:09:31 +0200 Subject: [PATCH 10/17] moved plot setting updates into replot The correcet place to trigger plot modifications is here, not in the functions that trigger the plot update. --- src/napari_clusters_plotter/_new_plotter_widget.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index ff0a247f..ff733d27 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -281,6 +281,11 @@ def _replot(self): active_artist.bins = self.bin_number active_artist.histogram_color_normalization_method = color_norm + else: + # make sure we use the correct frame highlighting settings + self._on_frame_highlighting_toggled() + self._on_point_size_changed() + # Then set color_indices and colormap properties in the active artist active_artist.overlay_colormap = overlay_cmap active_artist.color_indices = features[self.hue_axis].to_numpy() @@ -559,9 +564,6 @@ def _on_update_layer_selection( f"Layer {layer.name} does not have events.features or events.properties" ) - # make sure we use the correct frame highlighting settings - self._on_frame_highlighting_toggled() - def _clean_up(self): """In case of empty layer selection""" From 479a714cd860330ae0bb47c0382989cafa74924f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 11:13:37 +0000 Subject: [PATCH 11/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../_new_plotter_widget.py | 14 ++++++++------ .../_tests/test_plotter.py | 19 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index ff733d27..ea9daf73 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -45,7 +45,7 @@ def __init__(self, napari_viewer): self.layers_being_unselected = [] self._on_update_layer_selection(None) self._setup_callbacks() - + # some default values self._out_of_frame_alpha = 0.25 self._out_of_frame_size_factor = 0.5 @@ -327,7 +327,9 @@ def _on_frame_changed(self, event: napari.utils.events.Event): index_out_of_frame = alpha == 0 alpha[index_out_of_frame] = self._out_of_frame_alpha - size[index_out_of_frame] = self.scatter_point_size * self._out_of_frame_size_factor + size[index_out_of_frame] = ( + self.scatter_point_size * self._out_of_frame_size_factor + ) self.plotting_widget.active_artist.alpha = alpha self.plotting_widget.active_artist.size = size @@ -386,7 +388,7 @@ def _on_frame_highlighting_toggled(self): # do nothing for histogram2d if self.plotting_type == "HISTOGRAM2D": return - + if self.frame_highlighting_activated: self._on_frame_changed(None) else: @@ -399,7 +401,7 @@ def _on_point_size_changed(self): Called when the point size is changed. Updates the size of the points in the scatter plot. """ - + if self.plotting_type != "SCATTER": return self.plotting_widget.active_artist.size = self.scatter_point_size @@ -410,7 +412,7 @@ def _on_point_size_changed(self): @property def scatter_point_size(self): return self.control_widget.spinBox_point_size.value() - + @scatter_point_size.setter def scatter_point_size(self, val: int): self.control_widget.spinBox_point_size.setValue(val) @@ -418,7 +420,7 @@ def scatter_point_size(self, val: int): @property def frame_highlighting_activated(self): return self.control_widget.checkBox_frame_highlighting.isChecked() - + @frame_highlighting_activated.setter def frame_highlighting_activated(self, val: bool): self.control_widget.checkBox_frame_highlighting.setChecked(val) diff --git a/src/napari_clusters_plotter/_tests/test_plotter.py b/src/napari_clusters_plotter/_tests/test_plotter.py index 1fdfbc6c..310777ba 100644 --- a/src/napari_clusters_plotter/_tests/test_plotter.py +++ b/src/napari_clusters_plotter/_tests/test_plotter.py @@ -510,9 +510,14 @@ def test_temporal_highlighting(make_napari_viewer, create_sample_layers): # check that the dots in the plotter widget update alpha and size # to highlight out-of and in-frame data points - oof_size = plotter_widget.scatter_point_size * plotter_widget._out_of_frame_size_factor + oof_size = ( + plotter_widget.scatter_point_size + * plotter_widget._out_of_frame_size_factor + ) oof_alpha = plotter_widget._out_of_frame_alpha - assert plotter_widget.plotting_widget.active_artist.alpha.min() == oof_alpha + assert ( + plotter_widget.plotting_widget.active_artist.alpha.min() == oof_alpha + ) assert plotter_widget.plotting_widget.active_artist.size.min() == oof_size @@ -564,6 +569,7 @@ def test_histogram_support(make_napari_viewer, create_sample_layers): ) def test_scatter_advanced_options(make_napari_viewer, create_sample_layers): from napari_clusters_plotter import PlotterWidget + viewer = make_napari_viewer() layer, layer2 = create_sample_layers() @@ -577,17 +583,12 @@ def test_scatter_advanced_options(make_napari_viewer, create_sample_layers): assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) plotter_widget.frame_highlighting_activated = True - assert ~ np.all( - plotter_widget.plotting_widget.active_artist.alpha == 1 - ) + assert ~np.all(plotter_widget.plotting_widget.active_artist.alpha == 1) # select multiple layers and make sure that plot parameters are correct viewer.layers.selection = (layer, layer2) assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) - assert ~ np.all( - plotter_widget.plotting_widget.active_artist.alpha == 1 - ) - + assert ~np.all(plotter_widget.plotting_widget.active_artist.alpha == 1) @pytest.mark.parametrize( From 0f2a6a2f337dd67ac8cbd1e0ceaec3beaedca933 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 23:31:15 +0200 Subject: [PATCH 12/17] update docs --- docs/usage/imgs/Zeichnung.svg | 248 ++++++++++++------ .../imgs/plotter_overview3_annotated.png | Bin 28081 -> 24501 bytes .../imgs/plotter_overview4_annotated.png | Bin 0 -> 21884 bytes docs/usage/plotter_widget.md | 14 +- 4 files changed, 182 insertions(+), 80 deletions(-) create mode 100644 docs/usage/imgs/plotter_overview4_annotated.png diff --git a/docs/usage/imgs/Zeichnung.svg b/docs/usage/imgs/Zeichnung.svg index 083f5c64..444ed650 100644 --- a/docs/usage/imgs/Zeichnung.svg +++ b/docs/usage/imgs/Zeichnung.svg @@ -24,13 +24,13 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" - inkscape:zoom="1.4702523" - inkscape:cx="-404.35236" - inkscape:cy="555.34685" - inkscape:window-width="2560" - inkscape:window-height="1369" - inkscape:window-x="1912" - inkscape:window-y="-8" + inkscape:zoom="1.0396254" + inkscape:cx="-1334.6154" + inkscape:cy="806.54053" + inkscape:window-width="1920" + inkscape:window-height="1009" + inkscape:window-x="-8" + inkscape:window-y="100" inkscape:window-maximized="1" inkscape:current-layer="g7-5" showgrid="false">77889910101111111212Only visible when HISTOGRAM2D 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%0AoeXg& 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 D887Ca literal 28081 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 z zOb0t~X~4D;2OI}%hl;HksNEOYChEX$sT++_pj8ma7dY|%@9+}1qmG1BN9tpA!rf<( z0Bg$k@eJ!K0UC_Nh`@Sx5XcG(HFTCqlo$c#N|*v^R>ZE~P9|Q{D; zrnF@baJD)|K3j#;bH2u|A6&Re{00w{3oZY8(;(8N8Z8~wW+#})y_ zge!%J|wX!k3uF(T`xX7{Q=X?JvmNEa1BJV(`f09`n;DbUfnd z93mwN6=g%ycg6jw@=+l;kB!atBw=CXKq9#J%o!Ys74+uav(R98Qa0*#7Hkn>b4My) z$y^T;O*(K;v)B3uK4I$|ITp!?)MzQi^cp(i>T@Y)nyyc7D@u*J?_?a0Cg!b~Oe4Q= zd+MOPW?2`k+(Vyt*qFwCs3$kT|&vza^4<#=t|>|2C5J)4C- zDD%PkV=<>Jz|7n;Jl8S;HBPs_wp3h@L$_D;zrzQ+;=Uo~42D0F2JUJ_&GI1wlriAk zno|EgkD)_?O!YU-vhGg)%e$&y)ludg-~f2Z72XJ5PP9U0JAMNZ+7QgJe2 zw-(wEM3jFaUAG_WDl-`q|2Zu_clykx?&MKTw`>}@_+MdzgWUBbuj|G^9O6cLg9AfM z@nf7ks5qQ}!a{J89n*JYzGGx#!MpwE@l4d*f-rD&gj)IRt`v|iJT04@MM%|a+v-wv z`zvb-aO}F1?j6N!AiZCl3%omN4q8{VZ!ZsEHD8dkEW*(bmC~Ebc5>7qBii4hpSMrw zsvXd0?v3pQ;|>Wn51QZnB-=Wyq2vqgNPClIIEp&?BWKHde;Ac* z-=)d%x1RVHY;0laamK-eq*K-72?@`+nlFO=+rF-rwrAtHy(_Uq{FzuTmg*-LPaUXj z@BPUiDZjVmNcF_1IS8$Qw5+@gB0Z$`I^rOTEvNFjjYF>S*vd6opi*o58T9T2=B+P9 zJxycWD0=<;7CQAo<`9G8(OW^qE6t6?D;w@1tVC6*p+|r@*t^`0k<3tlDeY#qYTs7V z4^)w7GEy*6%GcuD?~#(-xW_;(XZ+hQ&vvaW-34r8Q`T>pXH{SxfM}>YuCy5JHyNLs zm9uyij%U~%lSl)a&y+c3g;ie0t#h~q7pP44@0pGIZS4tJve$>m!)BD<*$gz83jlu~ zeUvsBEbMLC-a5rix!E{A7x6=QQa$naaZeq7vqEU|b1v>}z}~`wc>KGg$|xV>aSgYv z=#I~fcU@rjJ-E)SU4kW|Hg=~-(QjW=PnSaV#jSqUOP5x;IWCjo zCVPsCUIdGShXM*P4r#vD?0f&D+8z}>$`)@4j*mm=EFDWL-8A~kM{xJ1zmk>v`%E>} zC{%T6HZ`Ub_^qF(?FVsr1%05S##7Cxm>c?`=T8JK#nmGUD)Z$v#-11Td_MTh6y5&x z)e*cUe2WcKIc)L6l@GEwj}K=}rVVM%52E|Vg_oAo-Olv}3)9`!ffg#_ws@=ej4Cg^ zN?cOS`<{FVI}=ISi>@TX+e^)suz^zPYkjzffvQiB^od=n08?6~U>H+F17H;E$n9L`gG z*4C2`yzV>}umRuoVlXd`0W(%eo|55jzX4@8S_mW-x*+C*^fekR#PV@f52uwDqP+Z7 z+-W}{#6><7v+8#^7N1ZT(dnz-@>}-`4kbGfARV8u>$S@ojS{;RJ!)3d4>H8+{ph$8 zKdFz8brV`#JjKV^*Ia&*SNJssp#Eg?HpLx6BI{%@S3++cLu`ZsM>$@5(p9NfAn8ANu)cnO@t~ zRJ+LAyw-1?{%TV-SlOs22p%}IW<8mh(Sb~Y7zStMuI8>8WvVnp)X;VSo%RhXoRMz1S)@svdsP}YUb6Lfpt?@yBZVnUk_yC{C13DVa=jrmYxs16_es`SPE$m|Qy-1nWZ}@6SmArt2;~Z-Il>~B z>!VV_y$CQTHIFcue_1^>tsUK?lWik0Dp)$X7!fTt1bg=k4z4#{??K#aQQ353??Y(` z&*4TN%!p08+HgBegH&=Qn`zqtk%1rkc$vc_agvrf`-t|gwY5k}>xJ)DkovS-PN!uZ z-1tigyMi2e(l-SK#S2wC<_wzz+uLD21%>BTd{y*z++Zs4)OBtV{{kPZUia#JPgg&L zd#6fCKXO_NIj=12`~H>TLZyXA)q@l^Sc`l4L3U`Cif3zqTZKKJ>#O0V*MGc~2?ol8 zejC_8eSetv-AplGXz)batnTg{+l}3dtyn&6 z4K)-w*k|u)^nO_WwIv6}pPqNS^wK%cF8PsM^PG7`NYDuu_~Ko-gOyP^OC$U*U{cTs$2H~T@(8SOl_Du=;igE>1E_h z-FP4Hf=K?;!|kC*ZPLUbuv=c=l~6}2j1AnY;;GNe*ocZ^qFf#@Ii(3uEnv=LHFRgH zEVFk#KBqTIRje1VFA<+q_O9A*{3#gLH2nEgA`tD}s;Vk?pYuh&g&BaBj9wA(Y~+wiu?a|(B?5pe zDm8U+iDtIi!D^|+FPF6dSn0I)7u_fjjyI&7!1IkCsEbi?-g7nUAb7RMytkUXj;TuJ zPt$mnbf!lT;n+KfGe6lWVcuLdjYkcdyc;r4TD?%uva%}GMhlkSz-T0wejaVVzM zxNNG}*DPZ)s3iTxC$4wjeg2+eVq)TEogMa)m35Gi3Db-AbCxSQ7Xte)Se*1 zJ;ToZUC@9d&3uKQEZS6$`MXN}U^zvKzoj(Lh6-QSHq=$<+t+^i7*6rIJ?Nm;C-x&C^1&OzZ;xYV5*wDj9s;luyc_# z00#TxBr6bW3q>~Qkz{IqGLaf@HbOnZ+}-(ldwU1pY@SXUTXnz*$YrcC$+}#t*`6m* zq45qq->J&M_zeQF=5^^3#X6&c<#It>NQi+H7V^#HpdDIaR0_?^u3`g{!aM+o#|fh% zi8+Gh5;ax}Uy8G{vsf?#ki^nu3b(~2q9H)^`@PZ$Mm75DLN6ieypt$(sWlcLeJu6X%((Wn#u2%>oG14= zDTai2|6(SxssyAILqK5D{trUiIlv)37GHdp68z|wqawpl-__sJ0qkpL9^kfhBm%v_ z{&pX&hhDT|c%ObV8?cNZ04n`DU;<8WyYg#J{SAD|h z6s`))eY>C(RVaSnHJT6J4t$C;j=>6A2}hkaFXj?6SA?vZFL~#7*ET-{r%gLoC`gAT z+vK>J)rMJx0>KNCmg;y5poqZtwM2Krke_Djhp%?@51v_8x`hz8a|moExy;el&o5+g znVXr-ox?*yj^lG3`>nj|PXrb9RKB!gEr***OU>}SvRi^Gea?z5UZWNz+`EFy33I-h z{$Sm}%evKv6x_E8_Zz8O)KomPx7uXi&&jFiNY>s8G^TdP_zs}SObK)GN?-&+JUEA! ztYdgt_cPC@u4j!+v?~{yK79d#&dqoCc7Pq{&S_LFjR{2f05!WneMtw`uQ0#xB2J{&WIyhYu#qg}Sgo}vI&Mt!oPt8=wwoR+3WM?`gO>3+2flW0wD>*Z4% z+}I?JKas&8kYBfN!V(Bnl;QGdF4fH0sAB*45S=}ze~NO8$D8G>#$z%5hH1Jyv>{w4 z@_e}-uPzBKU-_b$=s+^PizygBj?Ht1S^`B3ZJ+gp;|(UzY<*YwUV;2CDxS#K9MlVF zToWdb2K02OOi?=l@bTAc=5(%oruACg=$&bq<;m24sgrQ+*3@u{osxq@X{ohBV(T5U z5ga!H0yG0wZ}wDF^f^VHVIE{iWNv2r z4B}GxJXScp2V1rP7hfxW=QaP7dd`C~QMqp%6cHvIpjNux+sVAcoOUT;Iw6xZ^e*>D zxi-Hu=a!<(qJ~58-i#kHjoPB-&7fm~W9jHAHc$-Ia9~&RBe6lMH5VPet;}(Ta3Wd& zHA4XPLAwe=!4nhZbjkQ8B{)w!umTCNLj)+5_H4P{EZpyS7z1yC@{JRpLFyexMaG)^ zOvqN2YKZEj%4<*)ipGi1hMKb6&`oCrH2ZYmQXbj_$k+UJUKwM1kt6E>5Dlf>U1%nV zaW%vD5}gqauluJ}NBE63YUrc-8Zzu^Uu3DC%1bb+Q(_PZy zm{-?3$$c!EUp2k~6gLC?bfNJk^3@c@oKXR0dRgEIcWKn?CQI5d%9@L-HGwpKD!!td zlyDMi5)$VS61LosI@IoDPwQ;-sj3Mdb8c~BEy5sRwP?JJ{9ne(3$CY@?eohC@gp@( z)>C(uiZUITy;;}^*Rst;_fC&vnnpNkqj*_C>95c?nm=b+rD_)`R?CmI^7QH+$wKv# z@GR*PZ?1kwx-l0PWJ;)em(A|bG0;2FF$&LV9m>!D0fChN%!yyQ!Kh}+AEVz1Pj?(w ze+UU?*wuNWFRE4u1joYiwRb_W6~Kv_%#npHza-ReZ2Ir{fJqPMkz_L3vAYa^$7B#? zJvt9DbJ?DMO1OCcHuaL3nOV?no4B)cFx6IftS4hW4|>af7|>)cU;mPzjt53qC0CCk z#H8M`4Pg=q>5UNvd8e*H7%m%8rhC`z@o(}`H=Bo6w^yfgKt3)jJA2tt0ALSWmL30; z7>n;U9IJ3~am{(+)h9QV`v$Pq`MN7cx!rA2jqxhbC6U%!J;`w`;Sce&j zjT}6d)CkhAIB+?Aci+VW*T%2yQ(+98G%!=!5zdo3tE$Btl%F6Ox`17mlqnm|<$L3S z()I%d$N-!9)AjXYl4?LUf~rgwLdI^n))Rp$6Qh}Hp!ioR*ERPVHg8uuNpi^0`_VA^ zS-r`@1I(v5vTB4vMdU1D=B+t+ADVohqO;hT;_SR-3ylw7ltDBAT!T;~z??z99}J67kq1=K$v`YGlk1pJ?C-hH((2*}dHfuc6*VDMv! zNlJUh-wqUDl;IqolmN3PWvwyr@`hj6P|3FGDit zE*I1GyVP-8{2d63DxYF*t$*)JfVvQaicLN&P0)SkV6|MVo%ah~@w=cqY-77j2NPy` zKk^-vxHHa;Z1jvk7xKXE<^g5?{j^G)>Zwx*ZUu@vC;?>+{;UJqy#TaS!cl@eJOSWhkiyy^gRR0z92#O{6r1I*X2x-)3GH$r)opgA|x8rGWef<4$ zPrG)Vd(@<1vMiVLZb(=E;(5hhXbDoG_{my>hbymD9Wt(KV3HP;{62@xW=&7^8ec

8%Kj5oTtWM{~D#Bl~Sb zh<8)9-q67#dZkkwws)HR^cO}4Pz)@ZH7bOG?yf#;}i1Y`p-JlW?gP9m1sC+?-K7-5Kb3Tje% zLEGVcZ4&wZ@i_ zr6W?e)+N6illPx8Q(MvX8QQ`Xx20@tDCi$_j9!oWmO`FjDe7g_l(%67U>yXEyqZt# zfj`d3%wV+%z)aCSe%>}Z({!{-m2+ilXsg7hXbj%Ha+;L<{haDNOBF`zsZ;bS;QiG} z=R|fCz=OH1Vnclf>UNe51Q%B8WJ$}$j7hq}LCK-s6*%EuUPdq>x5YF5AA(Q;3ieCp zf-GTd&o z(bLAdzxVpJppW*K)Z)RZy0&fV*Lgbt`QQUpt~Tzj_q&&^^-}i(o{Ev5@B(UQ_j~WX z+RZvx*cO7wONoVdy|~Pq?}gw){K`?^k)mM|rr!`vyR^q@eXS*YPJbeExjj>NHoyY; zOm+$v3_eAA1EWUmc@8(?Eq*&!YzQ>&oF99eqiG)Qt%bm@on@u-pB!8!T{kV=stEVR znv(N9;GJlcn<%>LGw6-{5C@QRXTp0x@I3}R?>26EX+5dD!V z7RDmQv*(Me!L&^I^|}v9a$=<&E7|NnY|o{{uGX<3b}ZPVM%Elhc=`TRzVI(VLM;p_ zqEgd_bI5uM^*di)Tjbom{&QVyiKtj$G1h=KZZ-xK#T7ge{I%|^UG%EIe6Mo-n%ev| zsHl%yz}7iU?m729xysp9r_oluZoODyHgvB2vsTD+Pvhc^OAAe~5Q>{KEQ%WRa=>65 zf?&17rI3Uy)pO2@PhxhAfd{zw{pIj{HxQ+m1N=v36#l`u7uS zre4j1DKmVa0&G{P`iW&0-c1$jEUD)FgBoJZv%WHrR-5K zp!k3WNQ`tI2;n$1O3x4ipcbU8rddxXQ?oyUi1s?Inuz}5@O&4LdJk!;imr>PsH$#; z!)`K%8+fxjV^_JXLbR3FzGwUsl^z`*C6Me)2tayg0P8Fj9BsZL68rjsJ`Ek=T2?KqvnYcu#ymLt*qQ!Rg## zk61w?J42z|8#V2MSYyCY2wZPpzSikjV@bo2!h-L$9U&p1xABLB_f&mlbkug~7A`=B#J+$6VjJ!Fw^<+bMb6nu8@Bc#&9_~A3fXMV6m9m zl)k9+MVb$QbHKo5ke8T*1PxV(7*TB4zt$Ut-Xyy)1LZ70T9p%zxA0r&nX7l8GW`H` z!D6g3lQ-`-_Qi?F6pGL{o}NH@$1?`c6PSN?aA1l`4~^Uh$q)q(?>V8rZ>D) zpKdYweZ*P$^lW{kBe?%XyR{mO4T%nR+5JG$x(wDhvg1_(7;#s-6ZtWJf7o|VB3a*C z#UWbgbFd$jnn7_{0Ex4}{@I`;wr*z=rg}J3G+4JEMlGD+CMw~k?zeuC>@85NElrU6 zUuf=EAkePdqP0g&y?mhTD|4y0vY29(X_pBnu zN}+qBr#cVH4iBSaiGyl|fPT=}y$(oG|1)o%Xjxtt97Q>)=D9*n%~nIK|K7EypLL-& zX8w3D_W**74Nx&)4c1qzd>@w7_%QSq1r6mwxc%4_a3evu8jWUcqdvkt`qyk{Qyyks z=k2A_J`1nNW4gnC+@526xIKNH|3pP^Sa7-49Md?KNiDiu9{}78HE_6G0q5t$AwTSI z41Ba@dha!GdRHA@+MKvaxoth48&qbLp5=4#9-K`A-#1xMHVftE8~UxJ^}6CoVz6Zn2<B6&$2lL@J+}3XOD7~7 z9vFt|h>Z)rR;?K13GzDo6&_L0;EO)T-3AT&Iz2+^EQ^0u9rxQ98@25C0Z@_3?Cn3o zp8rnB(@)K!t%K3@ya^@eNt(`o!;IdynSy6%0G8-hN&fczyKR{QssXtRAc?E~{wJ-P z5wsL+XsF!UOT-Ffe1T2y*cy;-0o(sn4fH=16Wzj8uC6#rGuq97&#gU>msXJ~erw|Y Fe*pf5_J;rf diff --git a/docs/usage/imgs/plotter_overview4_annotated.png b/docs/usage/imgs/plotter_overview4_annotated.png new file mode 100644 index 0000000000000000000000000000000000000000..594e8f7066e155ead202d9c5d51bef500a0433e8 GIT binary patch literal 21884 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 literal 0 HcmV?d00001 diff --git a/docs/usage/plotter_widget.md b/docs/usage/plotter_widget.md index ad7c38e0..c08ad982 100644 --- a/docs/usage/plotter_widget.md +++ b/docs/usage/plotter_widget.md @@ -25,13 +25,23 @@ The core functionality of the plugin is available to you directly upon opening i ![Advanced settings](./imgs/plotter_overview3_annotated.png) +![Advanced settings](./imgs/plotter_overview4_annotated.png) + Under the `Advanced Options` tab, you have access to some more customization options for the visualization: 8. Change the colormap for the chosen overlay color. If a layer is colored by a non-categorical feature, this determines the colormap for the depiction. Only enabled if a non-categorical feature is selected in the `Hue` dropdown. 9. Apply a log-scale to the chosen feature 10. Switch plot type between `SCATTER` and `HISTOGRAM2D` -11. Colorap for 2D histogram (only enabled if `HISTOGRAM2D` is selected in 10.) -12. Change the size of the bins (only enabled if `HISTOGRAM2D` is selected in 10.) + +Depending on which plot type is selected, some additional options are available: + +11. For `SCATTER` plot: + - Enable the time-frame highlighting. This make give out-of-frame points a different alpha and size, making them appear slightly more transparent and smaller. This is useful to visualize the current time frame in a time-series dataset. To make use of this, enusre that the measurements in the layer's `layer.features` dataframe contain a `frame` column, which is used to determine the current time frame. + - Change the size of the points in the scatter plot. This can be useful for better visibility of the points in the plot in case there are a large number of points. + +12. For `HISTOGRAM2D` plot: + - Change the size of the bins (only enabled if `HISTOGRAM2D` is selected in 10.) Can be set to auto or a manual bin range can be set. + - A different colormap for the histogram can be selected. ## Visualizing layer features From a31cc9e1b45d21a36601cee3d3e00b8f584beb98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:32:32 +0000 Subject: [PATCH 13/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/usage/plotter_widget.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/plotter_widget.md b/docs/usage/plotter_widget.md index c08ad982..cbe8e8bd 100644 --- a/docs/usage/plotter_widget.md +++ b/docs/usage/plotter_widget.md @@ -35,7 +35,7 @@ Under the `Advanced Options` tab, you have access to some more customization opt Depending on which plot type is selected, some additional options are available: -11. For `SCATTER` plot: +11. For `SCATTER` plot: - Enable the time-frame highlighting. This make give out-of-frame points a different alpha and size, making them appear slightly more transparent and smaller. This is useful to visualize the current time frame in a time-series dataset. To make use of this, enusre that the measurements in the layer's `layer.features` dataframe contain a `frame` column, which is used to determine the current time frame. - Change the size of the points in the scatter plot. This can be useful for better visibility of the points in the plot in case there are a large number of points. From 7d4d16f3ea47d05e8d6a87a2af9c827a2da7aaa9 Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 23:49:52 +0200 Subject: [PATCH 14/17] Update docs/usage/plotter_widget.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/usage/plotter_widget.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/plotter_widget.md b/docs/usage/plotter_widget.md index cbe8e8bd..6f1ebbcd 100644 --- a/docs/usage/plotter_widget.md +++ b/docs/usage/plotter_widget.md @@ -36,7 +36,7 @@ Under the `Advanced Options` tab, you have access to some more customization opt Depending on which plot type is selected, some additional options are available: 11. For `SCATTER` plot: - - Enable the time-frame highlighting. This make give out-of-frame points a different alpha and size, making them appear slightly more transparent and smaller. This is useful to visualize the current time frame in a time-series dataset. To make use of this, enusre that the measurements in the layer's `layer.features` dataframe contain a `frame` column, which is used to determine the current time frame. + - Enable the time-frame highlighting. This make give out-of-frame points a different alpha and size, making them appear slightly more transparent and smaller. This is useful to visualize the current time frame in a time-series dataset. To make use of this, ensure that the measurements in the layer's `layer.features` dataframe contain a `frame` column, which is used to determine the current time frame. - Change the size of the points in the scatter plot. This can be useful for better visibility of the points in the plot in case there are a large number of points. 12. For `HISTOGRAM2D` plot: From b6a409e65c802e46fb614b7b2dfd3d8a3e1c4aec Mon Sep 17 00:00:00 2001 From: Johannes Soltwedel <38459088+jo-mueller@users.noreply.github.com> Date: Wed, 2 Jul 2025 23:52:47 +0200 Subject: [PATCH 15/17] Update src/napari_clusters_plotter/_new_plotter_widget.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/napari_clusters_plotter/_new_plotter_widget.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index ea9daf73..0967ee4d 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -395,6 +395,7 @@ def _on_frame_highlighting_toggled(self): self.plotting_widget.active_artist.alpha = np.ones( len(self._get_features()), dtype=float ) # Reset alpha to 1 for all points + self.plotting_widget.active_artist.size = self.scatter_point_size # Reset point size to default def _on_point_size_changed(self): """ From a44130618ca226e0d9ce2a702de1c02bb8483476 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:54:01 +0000 Subject: [PATCH 16/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/napari_clusters_plotter/_new_plotter_widget.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index 0967ee4d..ca60b64d 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -395,7 +395,9 @@ def _on_frame_highlighting_toggled(self): self.plotting_widget.active_artist.alpha = np.ones( len(self._get_features()), dtype=float ) # Reset alpha to 1 for all points - self.plotting_widget.active_artist.size = self.scatter_point_size # Reset point size to default + self.plotting_widget.active_artist.size = ( + self.scatter_point_size + ) # Reset point size to default def _on_point_size_changed(self): """ From cf01709ef00fe7f3992a50ac45c9126bc3862f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:57:45 +0200 Subject: [PATCH 17/17] removed point size setting feature --- .../_new_plotter_widget.py | 35 ++++--------------- .../_tests/test_plotter.py | 10 +++--- src/napari_clusters_plotter/plotter_inputs.ui | 35 +------------------ 3 files changed, 11 insertions(+), 69 deletions(-) diff --git a/src/napari_clusters_plotter/_new_plotter_widget.py b/src/napari_clusters_plotter/_new_plotter_widget.py index ca60b64d..b521ac78 100644 --- a/src/napari_clusters_plotter/_new_plotter_widget.py +++ b/src/napari_clusters_plotter/_new_plotter_widget.py @@ -190,10 +190,6 @@ def _setup_callbacks(self): self._on_frame_highlighting_toggled ) - self.control_widget.spinBox_point_size.valueChanged.connect( - self._on_point_size_changed - ) - def _on_finish_draw(self, color_indices: np.ndarray): """ Called when user finsihes drawing. Will change the hue combo box to the @@ -284,7 +280,6 @@ def _replot(self): else: # make sure we use the correct frame highlighting settings self._on_frame_highlighting_toggled() - self._on_point_size_changed() # Then set color_indices and colormap properties in the active artist active_artist.overlay_colormap = overlay_cmap @@ -323,12 +318,13 @@ def _on_frame_changed(self, event: napari.utils.events.Event): alpha = np.asarray( self._get_features()["frame"] == current_step, dtype=float ) - size = np.ones(len(alpha)) * self.scatter_point_size + default_size = self.plotting_widget.active_artist.default_size + size = np.ones(len(alpha)) * default_size index_out_of_frame = alpha == 0 alpha[index_out_of_frame] = self._out_of_frame_alpha size[index_out_of_frame] = ( - self.scatter_point_size * self._out_of_frame_size_factor + default_size * self._out_of_frame_size_factor ) self.plotting_widget.active_artist.alpha = alpha self.plotting_widget.active_artist.size = size @@ -392,34 +388,15 @@ def _on_frame_highlighting_toggled(self): if self.frame_highlighting_activated: self._on_frame_changed(None) else: - self.plotting_widget.active_artist.alpha = np.ones( + active_artist = self.plotting_widget.active_artist + active_artist.alpha = np.ones( len(self._get_features()), dtype=float ) # Reset alpha to 1 for all points - self.plotting_widget.active_artist.size = ( - self.scatter_point_size - ) # Reset point size to default - - def _on_point_size_changed(self): - """ - Called when the point size is changed. - Updates the size of the points in the scatter plot. - """ - - if self.plotting_type != "SCATTER": - return - self.plotting_widget.active_artist.size = self.scatter_point_size + active_artist.size = active_artist.default_size # Connecting the widgets to actual object variables: # using getters and setters for flexibility - @property - def scatter_point_size(self): - return self.control_widget.spinBox_point_size.value() - - @scatter_point_size.setter - def scatter_point_size(self, val: int): - self.control_widget.spinBox_point_size.setValue(val) - @property def frame_highlighting_activated(self): return self.control_widget.checkBox_frame_highlighting.isChecked() diff --git a/src/napari_clusters_plotter/_tests/test_plotter.py b/src/napari_clusters_plotter/_tests/test_plotter.py index 310777ba..bb9cb771 100644 --- a/src/napari_clusters_plotter/_tests/test_plotter.py +++ b/src/napari_clusters_plotter/_tests/test_plotter.py @@ -511,7 +511,7 @@ def test_temporal_highlighting(make_napari_viewer, create_sample_layers): # check that the dots in the plotter widget update alpha and size # to highlight out-of and in-frame data points oof_size = ( - plotter_widget.scatter_point_size + plotter_widget.plotting_widget.active_artist.default_size * plotter_widget._out_of_frame_size_factor ) oof_alpha = plotter_widget._out_of_frame_alpha @@ -579,16 +579,14 @@ def test_scatter_advanced_options(make_napari_viewer, create_sample_layers): plotter_widget = PlotterWidget(viewer) viewer.window.add_dock_widget(plotter_widget, area="right") - plotter_widget.scatter_point_size = 10 - assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) - plotter_widget.frame_highlighting_activated = True assert ~np.all(plotter_widget.plotting_widget.active_artist.alpha == 1) # select multiple layers and make sure that plot parameters are correct viewer.layers.selection = (layer, layer2) - assert np.all(plotter_widget.plotting_widget.active_artist.size == 10) - assert ~np.all(plotter_widget.plotting_widget.active_artist.alpha == 1) + active_artist = plotter_widget.plotting_widget.active_artist + assert ~np.all(active_artist.size == active_artist.default_size) + assert ~np.all(active_artist.alpha == 1) @pytest.mark.parametrize( diff --git a/src/napari_clusters_plotter/plotter_inputs.ui b/src/napari_clusters_plotter/plotter_inputs.ui index 0c0f66b3..ad8e86ba 100644 --- a/src/napari_clusters_plotter/plotter_inputs.ui +++ b/src/napari_clusters_plotter/plotter_inputs.ui @@ -23,7 +23,7 @@ - 1 + 0 @@ -175,39 +175,6 @@ - - - - Point size - - - - - - - 1 - - - 30 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 40 - 20 - - - -