From dba5a00b3dbf4138d9daaa91df28668ac9a7a3a5 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 12:54:55 +0100 Subject: [PATCH 01/12] Start a features mixin class --- src/napari_matplotlib/features.py | 21 +++++++++++++++++++++ src/napari_matplotlib/scatter.py | 13 ++----------- 2 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 src/napari_matplotlib/features.py diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py new file mode 100644 index 00000000..0f572ec0 --- /dev/null +++ b/src/napari_matplotlib/features.py @@ -0,0 +1,21 @@ +import napari.layers + +from napari_matplotlib.base import NapariMPLWidget +from napari_matplotlib.util import Interval + + +class FeaturesMixin(NapariMPLWidget): + """ + Mixin to help with widgets that plot data from a features table stored + on a single layer. + """ + + n_layers_input = Interval(1, 1) + # All layers that have a .features attributes + input_layer_types = ( + napari.layers.Labels, + napari.layers.Points, + napari.layers.Shapes, + napari.layers.Tracks, + napari.layers.Vectors, + ) diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 334f941c..4f69fa78 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -5,6 +5,7 @@ from qtpy.QtWidgets import QComboBox, QLabel, QVBoxLayout, QWidget from .base import SingleAxesWidget +from .features import FeaturesMixin from .util import Interval __all__ = ["ScatterBaseWidget", "ScatterWidget", "FeaturesScatterWidget"] @@ -85,21 +86,11 @@ def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: return x, y, x_axis_name, y_axis_name -class FeaturesScatterWidget(ScatterBaseWidget): +class FeaturesScatterWidget(ScatterBaseWidget, FeaturesMixin): """ Widget to scatter data stored in two layer feature attributes. """ - n_layers_input = Interval(1, 1) - # All layers that have a .features attributes - input_layer_types = ( - napari.layers.Labels, - napari.layers.Points, - napari.layers.Shapes, - napari.layers.Tracks, - napari.layers.Vectors, - ) - def __init__( self, napari_viewer: napari.viewer.Viewer, From 5702ed9da4d07bf0efdef13081cc41e4fc0773dc Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 12:58:07 +0100 Subject: [PATCH 02/12] Move get_valid_axis_keys --- src/napari_matplotlib/features.py | 17 +++++++++++++++++ src/napari_matplotlib/scatter.py | 17 +---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index 0f572ec0..f55592c2 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -1,3 +1,5 @@ +from typing import List + import napari.layers from napari_matplotlib.base import NapariMPLWidget @@ -19,3 +21,18 @@ class FeaturesMixin(NapariMPLWidget): napari.layers.Tracks, napari.layers.Vectors, ) + + def _get_valid_axis_keys(self) -> List[str]: + """ + Get the valid axis keys from the layer FeatureTable. + + Returns + ------- + axis_keys : List[str] + The valid axis keys in the FeatureTable. If the table is empty + or there isn't a table, returns an empty list. + """ + if len(self.layers) == 0 or not (hasattr(self.layers[0], "features")): + return [] + else: + return self.layers[0].features.keys() diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 4f69fa78..f29c2ef6 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Dict, Optional, Tuple, Union import napari import numpy.typing as npt @@ -141,21 +141,6 @@ def y_axis_key(self, key: str) -> None: self._selectors["y"].setCurrentText(key) self._draw() - def _get_valid_axis_keys(self) -> List[str]: - """ - Get the valid axis keys from the layer FeatureTable. - - Returns - ------- - axis_keys : List[str] - The valid axis keys in the FeatureTable. If the table is empty - or there isn't a table, returns an empty list. - """ - if len(self.layers) == 0 or not (hasattr(self.layers[0], "features")): - return [] - else: - return self.layers[0].features.keys() - def _ready_to_scatter(self) -> bool: """ Return True if selected layer has a feature table we can scatter with, From 7c51b5a344d25ed9c7a674747c3f62a1e5b9e861 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 13:23:09 +0100 Subject: [PATCH 03/12] Move layout setup --- src/napari_matplotlib/features.py | 23 ++++++++++++++++++++++- src/napari_matplotlib/scatter.py | 19 ++++--------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index f55592c2..e11e68ca 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -1,6 +1,8 @@ -from typing import List +from typing import Dict, List +import napari import napari.layers +from qtpy.QtWidgets import QComboBox, QLabel, QVBoxLayout from napari_matplotlib.base import NapariMPLWidget from napari_matplotlib.util import Interval @@ -10,6 +12,12 @@ class FeaturesMixin(NapariMPLWidget): """ Mixin to help with widgets that plot data from a features table stored on a single layer. + + Notes + ----- + This currently only works for widgets that plot two quatities against each other + e.g., scatter plots. It is intended to be generalised in the future for widgets + that plot one quantity e.g., histograms. """ n_layers_input = Interval(1, 1) @@ -22,6 +30,19 @@ class FeaturesMixin(NapariMPLWidget): napari.layers.Vectors, ) + def __init__(self) -> None: + # Set up selection boxes + self.layout().addLayout(QVBoxLayout()) + + self._selectors: Dict[str, QComboBox] = {} + for dim in ["x", "y"]: + self._selectors[dim] = QComboBox() + # Re-draw when combo boxes are updated + self._selectors[dim].currentTextChanged.connect(self._draw) + + self.layout().addWidget(QLabel(f"{dim}-axis:")) + self.layout().addWidget(self._selectors[dim]) + def _get_valid_axis_keys(self) -> List[str]: """ Get the valid axis keys from the layer FeatureTable. diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index f29c2ef6..892dd72a 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -1,8 +1,8 @@ -from typing import Any, Dict, Optional, Tuple, Union +from typing import Any, Optional, Tuple, Union import napari import numpy.typing as npt -from qtpy.QtWidgets import QComboBox, QLabel, QVBoxLayout, QWidget +from qtpy.QtWidgets import QWidget from .base import SingleAxesWidget from .features import FeaturesMixin @@ -96,19 +96,8 @@ def __init__( napari_viewer: napari.viewer.Viewer, parent: Optional[QWidget] = None, ): - super().__init__(napari_viewer, parent=parent) - - self.layout().addLayout(QVBoxLayout()) - - self._selectors: Dict[str, QComboBox] = {} - for dim in ["x", "y"]: - self._selectors[dim] = QComboBox() - # Re-draw when combo boxes are updated - self._selectors[dim].currentTextChanged.connect(self._draw) - - self.layout().addWidget(QLabel(f"{dim}-axis:")) - self.layout().addWidget(self._selectors[dim]) - + ScatterBaseWidget.__init__(self, napari_viewer, parent=parent) + FeaturesMixin.__init__(self) self._update_layers(None) @property From 75e79b6610be3f5d46eba54130e61f006bf9bf2f Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 13:36:33 +0100 Subject: [PATCH 04/12] Move key setting/getting --- src/napari_matplotlib/features.py | 30 ++++++++---- src/napari_matplotlib/scatter.py | 46 ++++--------------- .../tests/scatter/test_scatter_features.py | 8 ++-- 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index e11e68ca..bd40f1a3 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -1,4 +1,4 @@ -from typing import Dict, List +from typing import Dict, List, Optional import napari import napari.layers @@ -12,12 +12,6 @@ class FeaturesMixin(NapariMPLWidget): """ Mixin to help with widgets that plot data from a features table stored on a single layer. - - Notes - ----- - This currently only works for widgets that plot two quatities against each other - e.g., scatter plots. It is intended to be generalised in the future for widgets - that plot one quantity e.g., histograms. """ n_layers_input = Interval(1, 1) @@ -30,12 +24,14 @@ class FeaturesMixin(NapariMPLWidget): napari.layers.Vectors, ) - def __init__(self) -> None: + def __init__(self, *, ndim: int) -> None: + assert ndim in [1, 2] + self.dims = ["x", "y"][:ndim] # Set up selection boxes self.layout().addLayout(QVBoxLayout()) self._selectors: Dict[str, QComboBox] = {} - for dim in ["x", "y"]: + for dim in self.dims: self._selectors[dim] = QComboBox() # Re-draw when combo boxes are updated self._selectors[dim].currentTextChanged.connect(self._draw) @@ -43,6 +39,22 @@ def __init__(self) -> None: self.layout().addWidget(QLabel(f"{dim}-axis:")) self.layout().addWidget(self._selectors[dim]) + def get_key(self, dim: str) -> Optional[str]: + """ + Get key for a given dimension. + """ + if self._selectors[dim].count() == 0: + return None + else: + return self._selectors[dim].currentText() + + def set_key(self, dim: str, value: str) -> None: + """ + Set key for a given dimension. + """ + self._selectors[dim].setCurrentText(value) + self._draw() + def _get_valid_axis_keys(self) -> List[str]: """ Get the valid axis keys from the layer FeatureTable. diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 892dd72a..27904d94 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Tuple, Union +from typing import Any, Optional, Tuple import napari import numpy.typing as npt @@ -97,39 +97,9 @@ def __init__( parent: Optional[QWidget] = None, ): ScatterBaseWidget.__init__(self, napari_viewer, parent=parent) - FeaturesMixin.__init__(self) + FeaturesMixin.__init__(self, ndim=2) self._update_layers(None) - @property - def x_axis_key(self) -> Union[str, None]: - """ - Key for the x-axis data. - """ - if self._selectors["x"].count() == 0: - return None - else: - return self._selectors["x"].currentText() - - @x_axis_key.setter - def x_axis_key(self, key: str) -> None: - self._selectors["x"].setCurrentText(key) - self._draw() - - @property - def y_axis_key(self) -> Union[str, None]: - """ - Key for the y-axis data. - """ - if self._selectors["y"].count() == 0: - return None - else: - return self._selectors["y"].currentText() - - @y_axis_key.setter - def y_axis_key(self, key: str) -> None: - self._selectors["y"].setCurrentText(key) - self._draw() - def _ready_to_scatter(self) -> bool: """ Return True if selected layer has a feature table we can scatter with, @@ -143,8 +113,8 @@ def _ready_to_scatter(self) -> bool: return ( feature_table is not None and len(feature_table) > 0 - and self.x_axis_key in valid_keys - and self.y_axis_key in valid_keys + and self.get_key("x") in valid_keys + and self.get_key("y") in valid_keys ) def draw(self) -> None: @@ -173,11 +143,11 @@ def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: """ feature_table = self.layers[0].features - x = feature_table[self.x_axis_key] - y = feature_table[self.y_axis_key] + x = feature_table[self.get_key("x")] + y = feature_table[self.get_key("y")] - x_axis_name = str(self.x_axis_key) - y_axis_name = str(self.y_axis_key) + x_axis_name = str(self.get_key("x")) + y_axis_name = str(self.get_key("y")) return x, y, x_axis_name, y_axis_name diff --git a/src/napari_matplotlib/tests/scatter/test_scatter_features.py b/src/napari_matplotlib/tests/scatter/test_scatter_features.py index c211a064..0b3f7638 100644 --- a/src/napari_matplotlib/tests/scatter/test_scatter_features.py +++ b/src/napari_matplotlib/tests/scatter/test_scatter_features.py @@ -25,8 +25,8 @@ def test_features_scatter_widget_2D( # Select points data and chosen features viewer.layers.selection.add(viewer.layers[0]) # images need to be selected - widget.x_axis_key = "feature_0" - widget.y_axis_key = "feature_1" + widget.set_key("x", "feature_0") + widget.set_key("y", "feature_1") fig = widget.figure @@ -64,9 +64,9 @@ def test_features_scatter_get_data(make_napari_viewer): viewer.layers.selection = [labels_layer] x_column = "feature_0" - scatter_widget.x_axis_key = x_column y_column = "feature_2" - scatter_widget.y_axis_key = y_column + scatter_widget.set_key("x", x_column) + scatter_widget.set_key("y", y_column) x, y, x_axis_name, y_axis_name = scatter_widget._get_data() np.testing.assert_allclose(x, feature_table[x_column]) From b56c56c98adae0bf0136961615a1ea5496fa59b6 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 13:39:06 +0100 Subject: [PATCH 05/12] Move on_update_layers --- src/napari_matplotlib/features.py | 11 +++++++++++ src/napari_matplotlib/scatter.py | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index bd40f1a3..58252ef2 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -69,3 +69,14 @@ def _get_valid_axis_keys(self) -> List[str]: return [] else: return self.layers[0].features.keys() + + def on_update_layers(self) -> None: + """ + Called when the layer selection changes by ``self.update_layers()``. + """ + # Clear combobox + for dim in self.dims: + while self._selectors[dim].count() > 0: + self._selectors[dim].removeItem(0) + # Add keys for newly selected layer + self._selectors[dim].addItems(self._get_valid_axis_keys()) diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 27904d94..ed9e2efb 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -150,14 +150,3 @@ def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: y_axis_name = str(self.get_key("y")) return x, y, x_axis_name, y_axis_name - - def on_update_layers(self) -> None: - """ - Called when the layer selection changes by ``self.update_layers()``. - """ - # Clear combobox - for dim in ["x", "y"]: - while self._selectors[dim].count() > 0: - self._selectors[dim].removeItem(0) - # Add keys for newly selected layer - self._selectors[dim].addItems(self._get_valid_axis_keys()) From ddf81ff1b0787428787f87a551b8323e7d0b021b Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 13:43:31 +0100 Subject: [PATCH 06/12] Move ready_to_plot --- src/napari_matplotlib/features.py | 16 ++++++++++++++++ src/napari_matplotlib/scatter.py | 19 +------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index 58252ef2..4b1c67b4 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -70,6 +70,22 @@ def _get_valid_axis_keys(self) -> List[str]: else: return self.layers[0].features.keys() + def _ready_to_plot(self) -> bool: + """ + Return True if selected layer has a feature table we can plot with, + and the columns to plot have been selected. + """ + if not hasattr(self.layers[0], "features"): + return False + + feature_table = self.layers[0].features + valid_keys = self._get_valid_axis_keys() + return ( + feature_table is not None + and len(feature_table) > 0 + and all([self.get_key(dim) in valid_keys for dim in self.dims]) + ) + def on_update_layers(self) -> None: """ Called when the layer selection changes by ``self.update_layers()``. diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index ed9e2efb..95721161 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -100,28 +100,11 @@ def __init__( FeaturesMixin.__init__(self, ndim=2) self._update_layers(None) - def _ready_to_scatter(self) -> bool: - """ - Return True if selected layer has a feature table we can scatter with, - and the two columns to be scatterd have been selected. - """ - if not hasattr(self.layers[0], "features"): - return False - - feature_table = self.layers[0].features - valid_keys = self._get_valid_axis_keys() - return ( - feature_table is not None - and len(feature_table) > 0 - and self.get_key("x") in valid_keys - and self.get_key("y") in valid_keys - ) - def draw(self) -> None: """ Scatter two features from the currently selected layer. """ - if self._ready_to_scatter(): + if self._ready_to_plot(): super().draw() def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: From 91368c1802681d9e402b3b305fe8f7f3cdf8045d Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 13 Jun 2023 13:56:49 +0100 Subject: [PATCH 07/12] Move data getting --- src/napari_matplotlib/features.py | 26 +++++++++++++++++++++++++- src/napari_matplotlib/scatter.py | 27 ++------------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index 4b1c67b4..2845c21e 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -1,7 +1,10 @@ -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional, Tuple import napari import napari.layers +import numpy as np +import numpy.typing as npt +import pandas as pd from qtpy.QtWidgets import QComboBox, QLabel, QVBoxLayout from napari_matplotlib.base import NapariMPLWidget @@ -86,6 +89,27 @@ def _ready_to_plot(self) -> bool: and all([self.get_key(dim) in valid_keys for dim in self.dims]) ) + def _get_data_names( + self, + ) -> Tuple[List[npt.NDArray[Any]], List[str]]: + """ + Get the plot data from the ``features`` attribute of the first + selected layer. + + Returns + ------- + data : List[np.ndarray] + List contains X and Y columns from the FeatureTable. Returns + an empty array if nothing to plot. + names : List[str] + Names for each axis. + """ + feature_table: pd.DataFrame = self.layers[0].features + + names = [str(self.get_key(dim)) for dim in self.dims] + data = [np.array(feature_table[key]) for key in names] + return data, names + def on_update_layers(self) -> None: """ Called when the layer selection changes by ``self.update_layers()``. diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 95721161..4fa45798 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -108,28 +108,5 @@ def draw(self) -> None: super().draw() def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: - """ - Get the plot data from the ``features`` attribute of the first - selected layer. - - Returns - ------- - data : List[np.ndarray] - List contains X and Y columns from the FeatureTable. Returns - an empty array if nothing to plot. - x_axis_name : str - The title to display on the x axis. Returns - an empty string if nothing to plot. - y_axis_name: str - The title to display on the y axis. Returns - an empty string if nothing to plot. - """ - feature_table = self.layers[0].features - - x = feature_table[self.get_key("x")] - y = feature_table[self.get_key("y")] - - x_axis_name = str(self.get_key("x")) - y_axis_name = str(self.get_key("y")) - - return x, y, x_axis_name, y_axis_name + data, names = self._get_data_names() + return data[0], data[1], names[0], names[1] From e1870d6d59ee9560befd57bfff52cf7c39f9bf02 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 15 Jun 2023 13:58:29 +0100 Subject: [PATCH 08/12] Fix super() --- src/napari_matplotlib/base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/napari_matplotlib/base.py b/src/napari_matplotlib/base.py index 8c717d6a..5687895e 100644 --- a/src/napari_matplotlib/base.py +++ b/src/napari_matplotlib/base.py @@ -281,7 +281,9 @@ def __init__( napari_viewer: napari.viewer.Viewer, parent: Optional[QWidget] = None, ): - super().__init__(napari_viewer=napari_viewer, parent=parent) + NapariMPLWidget.__init__( + self, napari_viewer=napari_viewer, parent=parent + ) self.add_single_axes() def clear(self) -> None: From a04bd18b169f696d95ecaad2bbb6d3059995f5de Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 15 Jun 2023 14:03:01 +0100 Subject: [PATCH 09/12] Add features to API doc --- docs/api.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api.rst b/docs/api.rst index dba583af..ae0d78d2 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -8,3 +8,5 @@ plots though the napari user interface. .. automodapi:: napari_matplotlib .. automodapi:: napari_matplotlib.base + +.. automodapi:: napari_matplotlib.features From c0909d3b43e6b6808e92aa1de0aa6335286551d6 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 15 Jun 2023 14:09:20 +0100 Subject: [PATCH 10/12] Add __all__ --- src/napari_matplotlib/features.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index 2845c21e..c1991819 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -10,6 +10,7 @@ from napari_matplotlib.base import NapariMPLWidget from napari_matplotlib.util import Interval +__all__ = ["FeaturesMixin"] class FeaturesMixin(NapariMPLWidget): """ From 5e5afd18c324e563662c0079ded1bd77ee0c46bf Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 15 Jun 2023 14:45:35 +0100 Subject: [PATCH 11/12] Improve FeaturesMixin docs --- src/napari_matplotlib/features.py | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index c1991819..899687b4 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -12,10 +12,16 @@ __all__ = ["FeaturesMixin"] + class FeaturesMixin(NapariMPLWidget): """ Mixin to help with widgets that plot data from a features table stored - on a single layer. + in a single napari layer. + + This provides: + - Setup for one or two combo boxes to select features to be plotted. + - An ``on_update_layers()`` callback that updates the combo box options + when the napari layer selection changes. """ n_layers_input = Interval(1, 1) @@ -29,6 +35,13 @@ class FeaturesMixin(NapariMPLWidget): ) def __init__(self, *, ndim: int) -> None: + """ + Parameters + ---------- + ndim : int + Number of dimensions that are plotted by the widget. + Must be 1 or 2. + """ assert ndim in [1, 2] self.dims = ["x", "y"][:ndim] # Set up selection boxes @@ -46,6 +59,11 @@ def __init__(self, *, ndim: int) -> None: def get_key(self, dim: str) -> Optional[str]: """ Get key for a given dimension. + + Parameters + ---------- + dim : str + "x" or "y" """ if self._selectors[dim].count() == 0: return None @@ -55,13 +73,24 @@ def get_key(self, dim: str) -> Optional[str]: def set_key(self, dim: str, value: str) -> None: """ Set key for a given dimension. + + Parameters + ---------- + dim : str + "x" or "y" + value : str + Value to set. """ + assert value in self._get_valid_axis_keys(), ( + "value must be on of the columns " + "of the feature table on the currently seleted layer" + ) self._selectors[dim].setCurrentText(value) self._draw() def _get_valid_axis_keys(self) -> List[str]: """ - Get the valid axis keys from the layer FeatureTable. + Get the valid axis keys from the features table column names. Returns ------- From 8c2df620cf2038b7ae81f87bd3ac837a5902ee84 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Thu, 15 Jun 2023 14:56:49 +0100 Subject: [PATCH 12/12] Fix bullet points --- src/napari_matplotlib/features.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/napari_matplotlib/features.py b/src/napari_matplotlib/features.py index 899687b4..3e1eb9ba 100644 --- a/src/napari_matplotlib/features.py +++ b/src/napari_matplotlib/features.py @@ -19,6 +19,7 @@ class FeaturesMixin(NapariMPLWidget): in a single napari layer. This provides: + - Setup for one or two combo boxes to select features to be plotted. - An ``on_update_layers()`` callback that updates the combo box options when the napari layer selection changes.