Skip to content
Open
Show file tree
Hide file tree
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
248 changes: 170 additions & 78 deletions docs/usage/imgs/Zeichnung.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/usage/imgs/plotter_overview4_annotated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 12 additions & 2 deletions docs/usage/plotter_widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,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:

9. 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.
10. Apply a log-scale to the chosen feature
11. Switch plot type between `SCATTER` and `HISTOGRAM2D`
12. Colorap for 2D histogram (only enabled if `HISTOGRAM2D` is selected in 10.)
13. 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:

12. 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, 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.

13. 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

Expand Down
81 changes: 52 additions & 29 deletions src/napari_clusters_plotter/_new_plotter_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def __init__(self, napari_viewer):
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)

# Colormap reference to be indexed like this:
Expand Down Expand Up @@ -119,7 +123,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)

Expand Down Expand Up @@ -220,6 +223,9 @@ def _setup_callbacks(self):
self._on_bin_auto_toggled
)

self.control_widget.checkBox_frame_highlighting.toggled.connect(
self._on_frame_highlighting_toggled
)
self.control_widget.pushButton_export_layer.clicked.connect(
self._on_export_clusters
)
Expand Down Expand Up @@ -252,30 +258,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.
Expand Down Expand Up @@ -310,7 +292,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
Expand Down Expand Up @@ -338,6 +319,10 @@ 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()

# 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()
Expand Down Expand Up @@ -367,16 +352,22 @@ 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(
self._get_features()["frame"] == current_step, dtype=float
)
size = np.ones(len(alpha)) * 50
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] = 0.25
size[index_out_of_frame] = 35
alpha[index_out_of_frame] = self._out_of_frame_alpha
size[index_out_of_frame] = (
default_size * self._out_of_frame_size_factor
)
self.plotting_widget.active_artist.alpha = alpha
self.plotting_widget.active_artist.size = size

Expand All @@ -390,11 +381,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):
Expand Down Expand Up @@ -422,8 +418,35 @@ 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_type == "HISTOGRAM2D":
return

if self.frame_highlighting_activated:
self._on_frame_changed(None)
else:
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
active_artist.size = active_artist.default_size

# 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_activated(self, val: bool):
self.control_widget.checkBox_frame_highlighting.setChecked(val)

@property
def log_scale(self):
return self.control_widget.log_scale_checkbutton.isChecked()
Expand Down
40 changes: 38 additions & 2 deletions src/napari_clusters_plotter/_tests/test_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,8 +676,15 @@ 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.plotting_widget.active_artist.default_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(
Expand Down Expand Up @@ -719,6 +726,35 @@ 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.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)
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(
"create_sample_layers",
[
Expand Down
Loading
Loading