diff --git a/docs/Makefile b/docs/Makefile index b50c24dc..5117fbf5 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line, and also # from the environment for the first two. -SPHINXOPTS ?= -W +SPHINXOPTS ?= -W --keep-going SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index 2c04f853..efff247a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -56,10 +56,18 @@ automodapi_inheritance_diagram = False intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), "napari": ("https://napari.org/", None), + "numpy": ("https://numpy.org/doc/stable/", None), "matplotlib": ("https://matplotlib.org/", None), + "PyQT6": ("https://www.riverbankcomputing.com/static/Docs/PyQt6/", None), } +nitpicky = True +# Can't work out how to link this properley using intersphinx and the PyQT6 docs. +# TODO: fix at some point +nitpick_ignore = [("py:class", "PyQt6.QtWidgets.QWidget")] + # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/docs/make.bat b/docs/make.bat index 32bb2452..4b78115a 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -7,6 +7,9 @@ REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) +if "%SPHINXOPTS%" == "" ( + set SPHINXOPTS="--keep-going" +) set SOURCEDIR=. set BUILDDIR=_build diff --git a/src/napari_matplotlib/base.py b/src/napari_matplotlib/base.py index b69d0310..fc8fa17f 100644 --- a/src/napari_matplotlib/base.py +++ b/src/napari_matplotlib/base.py @@ -22,11 +22,12 @@ class NapariMPLWidget(QWidget): """ - Base Matplotlib canvas. Widget that can be embedded as a napari widget. + Widget containing a Matplotlib canvas and toolbar. - This creates a single FigureCanvas, which contains a single Figure. - It is not responsible for creating any Axes, because different widgets - may want to implement different subplot layouts. + This creates a single FigureCanvas, which contains a single + `~matplotlib.figure.Figure`, and an associated toolbar. + It is not responsible for creating any Axes, because different + widgets may want to implement different subplot layouts. This class also handles callbacks to automatically update figures when the layer selection or z-step is changed in the napari viewer. To take @@ -60,12 +61,12 @@ def __init__(self, napari_viewer: napari.viewer.Viewer): self.layout().addWidget(self.toolbar) self.layout().addWidget(self.canvas) - self.setup_callbacks() + self._setup_callbacks() self.layers: List[napari.layers.Layer] = [] - # Accept any number of input layers by default + #: Number of layers taken as input n_layers_input = Interval(None, None) - # Accept any type of input layer by default + #: Type of layer taken as input input_layer_types: Tuple[napari.layers.Layer, ...] = (napari.layers.Layer,) @property @@ -83,17 +84,17 @@ def n_selected_layers(self) -> int: @property def current_z(self) -> int: """ - Current z-step of the viewer. + Current z-step of the napari viewer. """ return self.viewer.dims.current_step[0] - def setup_callbacks(self) -> None: + def _setup_callbacks(self) -> None: """ Sets up callbacks. - Sets up callbacks for: - - Layer selection changing - - z-step changing + Sets up callbacks for when: + - Layer selection is changed + - z-step is changed """ # z-step changed in viewer self.viewer.dims.events.current_step.connect(self._draw) @@ -102,7 +103,7 @@ def setup_callbacks(self) -> None: def update_layers(self, event: napari.utils.events.Event) -> None: """ - Update the layers attribute with currently selected layers and re-draw. + Update the ``layers`` attribute with currently selected layers and re-draw. """ self.layers = list(self.viewer.layers.selection) self._on_update_layers() @@ -145,7 +146,7 @@ def add_single_axes(self) -> None: @staticmethod def apply_napari_colorscheme(ax: Axes) -> None: - """Apply napari-compatible colorscheme to an axes object.""" + """Apply napari-compatible colorscheme to an Axes.""" # changing color of axes background to transparent ax.set_facecolor("none") diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 405b7b09..858a42a8 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -8,7 +8,7 @@ from .base import NapariMPLWidget from .util import Interval -__all__ = ["ScatterWidget", "FeaturesScatterWidget"] +__all__ = ["ScatterBaseWidget", "ScatterWidget", "FeaturesScatterWidget"] class ScatterBaseWidget(NapariMPLWidget): @@ -68,7 +68,7 @@ def _get_data(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any], str, str]: class ScatterWidget(ScatterBaseWidget): """ - Widget to display scatter plot of two similarly shaped image layers. + Scatter data in two similarly shaped layers. If there are more than 500 data points, a 2D histogram is displayed instead of a scatter plot, to avoid too many scatter points. @@ -127,7 +127,7 @@ def __init__(self, napari_viewer: napari.viewer.Viewer): @property def x_axis_key(self) -> Optional[str]: """ - Key to access x axis data from the FeaturesTable. + Key for the x-axis data. """ return self._x_axis_key @@ -139,7 +139,7 @@ def x_axis_key(self, key: Optional[str]) -> None: @property def y_axis_key(self) -> Optional[str]: """ - Key to access y axis data from the FeaturesTable. + Key for the y-axis data. """ return self._y_axis_key diff --git a/src/napari_matplotlib/slice.py b/src/napari_matplotlib/slice.py index 4e22bad8..c29fff5c 100644 --- a/src/napari_matplotlib/slice.py +++ b/src/napari_matplotlib/slice.py @@ -50,7 +50,7 @@ def __init__(self, napari_viewer: napari.viewer.Viewer): self.update_layers(None) @property - def layer(self) -> napari.layers.Layer: + def _layer(self) -> napari.layers.Layer: """ Layer being plotted. """ @@ -73,28 +73,19 @@ def current_dim_index(self) -> int: return _dims[::-1].index(self.current_dim) @property - def selector_values(self) -> Dict[str, int]: + def _selector_values(self) -> Dict[str, int]: """ Values of the slice selectors. """ return {d: self.slice_selectors[d].value() for d in _dims_sel} - def update_slice_selectors(self) -> None: - """ - Update range and enabled status of the slice selectors, and the value - of the z slice selector. - """ - # Update min/max - for i, dim in enumerate(_dims_sel): - self.slice_selectors[dim].setRange(0, self.layer.data.shape[i]) - - def get_xy(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any]]: + def _get_xy(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any]]: """ Get data for plotting. """ - x = np.arange(self.layer.data.shape[self.current_dim_index]) + x = np.arange(self._layer.data.shape[self.current_dim_index]) - vals = self.selector_values + vals = self._selector_values vals.update({"z": self.current_z}) slices = [] @@ -109,7 +100,7 @@ def get_xy(self) -> Tuple[npt.NDArray[Any], npt.NDArray[Any]]: # Reverse since z is the first axis in napari slices = slices[::-1] - y = self.layer.data[tuple(slices)].ravel() + y = self._layer.data[tuple(slices)].ravel() return x, y @@ -123,8 +114,8 @@ def draw(self) -> None: """ Clear axes and draw a 1D plot. """ - x, y = self.get_xy() + x, y = self._get_xy() self.axes.plot(x, y) self.axes.set_xlabel(self.current_dim) - self.axes.set_title(self.layer.name) + self.axes.set_title(self._layer.name) diff --git a/src/napari_matplotlib/util.py b/src/napari_matplotlib/util.py index 4ae8ca19..17965caf 100644 --- a/src/napari_matplotlib/util.py +++ b/src/napari_matplotlib/util.py @@ -28,6 +28,12 @@ def __init__(self, lower_bound: Optional[int], upper_bound: Optional[int]): self.lower = lower_bound self.upper = upper_bound + def __repr__(self) -> str: + """ + Get string representation. + """ + return f"Interval({self.lower}, {self.upper})" + def __contains__(self, val: int) -> bool: """ Return True if val is in the current interval.