From abd00bd4c40b8101fb1be66b3599f507a7285e13 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 19 Jun 2023 15:36:04 +0100 Subject: [PATCH 1/4] MVP for using style sheets --- MANIFEST.in | 1 + src/napari_matplotlib/base.py | 85 ++++++++++++--------- src/napari_matplotlib/scatter.py | 2 + src/napari_matplotlib/styles/README.md | 3 + src/napari_matplotlib/styles/dark.mplstyle | 12 +++ src/napari_matplotlib/styles/light.mplstyle | 12 +++ src/napari_matplotlib/tests/test_theme.py | 6 +- 7 files changed, 80 insertions(+), 41 deletions(-) create mode 100644 src/napari_matplotlib/styles/README.md create mode 100644 src/napari_matplotlib/styles/dark.mplstyle create mode 100644 src/napari_matplotlib/styles/light.mplstyle diff --git a/MANIFEST.in b/MANIFEST.in index 7ce16f9b..d625d95e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include LICENSE include README.md +recursive-include * *.mplstyle recursive-exclude * __pycache__ recursive-exclude * *.py[co] diff --git a/src/napari_matplotlib/base.py b/src/napari_matplotlib/base.py index 8c717d6a..89c6d3de 100644 --- a/src/napari_matplotlib/base.py +++ b/src/napari_matplotlib/base.py @@ -2,8 +2,8 @@ from pathlib import Path from typing import List, Optional, Tuple +import matplotlib.style as mplstyle import napari -from matplotlib.axes import Axes from matplotlib.backends.backend_qtagg import ( FigureCanvas, NavigationToolbar2QT, @@ -40,8 +40,11 @@ def __init__( ): super().__init__(parent=parent) self.viewer = napari_viewer + self._mpl_style_sheet_path: Optional[Path] = None - self.canvas = FigureCanvas() + # Sets figure.* style + with mplstyle.context(self.mpl_style_sheet_path): + self.canvas = FigureCanvas() self.canvas.figure.patch.set_facecolor("none") self.canvas.figure.set_layout_engine("constrained") @@ -52,7 +55,7 @@ def __init__( # callback to update when napari theme changed # TODO: this isn't working completely (see issue #140) # most of our styling respects the theme change but not all - self.viewer.events.theme.connect(self._on_theme_change) + self.viewer.events.theme.connect(self._on_napari_theme_changed) self.setLayout(QVBoxLayout()) self.layout().addWidget(self.toolbar) @@ -63,47 +66,40 @@ def figure(self) -> Figure: """Matplotlib figure.""" return self.canvas.figure + @property + def mpl_style_sheet_path(self) -> Path: + """ + Path to the set Matplotlib style sheet. + """ + if self._mpl_style_sheet_path is not None: + return self._mpl_style_sheet_path + elif self._napari_theme_has_light_bg(): + return Path(__file__).parent / "styles" / "light.mplstyle" + else: + return Path(__file__).parent / "styles" / "dark.mplstyle" + + @mpl_style_sheet_path.setter + def mpl_style_sheet_path(self, path: Path) -> None: + self._mpl_style_sheet_path = Path(path) + def add_single_axes(self) -> None: """ Add a single Axes to the figure. The Axes is saved on the ``.axes`` attribute for later access. """ - self.axes = self.figure.subplots() - self.apply_napari_colorscheme(self.axes) + # Sets axes.* style. + # Does not set any text styling set by axes.* keys + with mplstyle.context(self.mpl_style_sheet_path): + self.axes = self.figure.subplots() - def apply_napari_colorscheme(self, ax: Axes) -> None: - """Apply napari-compatible colorscheme to an Axes.""" - # get the foreground colours from current theme - theme = napari.utils.theme.get_theme(self.viewer.theme, as_dict=False) - fg_colour = theme.foreground.as_hex() # fg is a muted contrast to bg - text_colour = theme.text.as_hex() # text is high contrast to bg - - # changing color of axes background to transparent - ax.set_facecolor("none") - - # changing colors of all axes - for spine in ax.spines: - ax.spines[spine].set_color(fg_colour) - - ax.xaxis.label.set_color(text_colour) - ax.yaxis.label.set_color(text_colour) - - # changing colors of axes labels - ax.tick_params(axis="x", colors=text_colour) - ax.tick_params(axis="y", colors=text_colour) - - def _on_theme_change(self) -> None: - """Update MPL toolbar and axis styling when `napari.Viewer.theme` is changed. - - Note: - At the moment we only handle the default 'light' and 'dark' napari themes. + def _on_napari_theme_changed(self) -> None: + """ + Called when the napari theme is changed. """ self._replace_toolbar_icons() - if self.figure.gca(): - self.apply_napari_colorscheme(self.figure.gca()) - def _theme_has_light_bg(self) -> bool: + def _napari_theme_has_light_bg(self) -> bool: """ Does this theme have a light background? @@ -124,7 +120,7 @@ def _get_path_to_icon(self) -> Path: https://github.com/matplotlib/matplotlib/tree/main/lib/matplotlib/mpl-data/images """ icon_root = Path(__file__).parent / "icons" - if self._theme_has_light_bg(): + if self._napari_theme_has_light_bg(): return icon_root / "black" else: return icon_root / "white" @@ -211,6 +207,16 @@ def current_z(self) -> int: """ return self.viewer.dims.current_step[0] + def _on_napari_theme_changed(self) -> None: + """Update MPL toolbar and axis styling when `napari.Viewer.theme` is changed. + + Note: + At the moment we only handle the default 'light' and 'dark' napari themes. + """ + super()._on_napari_theme_changed() + self.clear() + self.draw() + def _setup_callbacks(self) -> None: """ Sets up callbacks. @@ -240,12 +246,14 @@ def _draw(self) -> None: Clear current figure, check selected layers are correct, and draw new figure if so. """ - self.clear() + # Clearing axes sets new defaults, so need to make sure style is applied when + # this happens + with mplstyle.context(self.mpl_style_sheet_path): + self.clear() if self.n_selected_layers in self.n_layers_input and all( isinstance(layer, self.input_layer_types) for layer in self.layers ): self.draw() - self.apply_napari_colorscheme(self.figure.gca()) self.canvas.draw() def clear(self) -> None: @@ -288,7 +296,8 @@ def clear(self) -> None: """ Clear the axes. """ - self.axes.clear() + with mplstyle.context(self.mpl_style_sheet_path): + self.axes.clear() class NapariNavigationToolbar(NavigationToolbar2QT): diff --git a/src/napari_matplotlib/scatter.py b/src/napari_matplotlib/scatter.py index 334f941c..db86c7f3 100644 --- a/src/napari_matplotlib/scatter.py +++ b/src/napari_matplotlib/scatter.py @@ -23,6 +23,8 @@ def draw(self) -> None: """ Scatter the currently selected layers. """ + if len(self.layers) == 0: + return x, y, x_axis_name, y_axis_name = self._get_data() if x.size > self._threshold_to_switch_to_histogram: diff --git a/src/napari_matplotlib/styles/README.md b/src/napari_matplotlib/styles/README.md new file mode 100644 index 00000000..79d3c417 --- /dev/null +++ b/src/napari_matplotlib/styles/README.md @@ -0,0 +1,3 @@ +This folder contains default built-in Matplotlib style sheets. +See https://matplotlib.org/stable/tutorials/introductory/customizing.html#defining-your-own-style +for more info on Matplotlib style sheets. diff --git a/src/napari_matplotlib/styles/dark.mplstyle b/src/napari_matplotlib/styles/dark.mplstyle new file mode 100644 index 00000000..1658f9b4 --- /dev/null +++ b/src/napari_matplotlib/styles/dark.mplstyle @@ -0,0 +1,12 @@ +# Dark-theme napari colour scheme for matplotlib plots + +# text (very light grey - almost white): #f0f1f2 +# foreground (mid grey): #414851 +# background (dark blue-gray): #262930 + +figure.facecolor : none +axes.labelcolor : f0f1f2 +axes.facecolor : none +axes.edgecolor : 414851 +xtick.color : f0f1f2 +ytick.color : f0f1f2 diff --git a/src/napari_matplotlib/styles/light.mplstyle b/src/napari_matplotlib/styles/light.mplstyle new file mode 100644 index 00000000..be78f2ce --- /dev/null +++ b/src/napari_matplotlib/styles/light.mplstyle @@ -0,0 +1,12 @@ +# Light-theme napari colour scheme for matplotlib plots + +# text (): #3b3a39 +# foreground (): #d6d0ce +# background (): #efebe9 + +figure.facecolor : none +axes.labelcolor : 3b3a39 +axes.facecolor : none +axes.edgecolor : d6d0ce +xtick.color : 3b3a39 +ytick.color : 3b3a39 diff --git a/src/napari_matplotlib/tests/test_theme.py b/src/napari_matplotlib/tests/test_theme.py index cf841d2b..734c64ef 100644 --- a/src/napari_matplotlib/tests/test_theme.py +++ b/src/napari_matplotlib/tests/test_theme.py @@ -43,14 +43,14 @@ def test_theme_background_check(make_napari_viewer): widget = NapariMPLWidget(viewer) viewer.theme = "dark" - assert widget._theme_has_light_bg() is False + assert widget._napari_theme_has_light_bg() is False viewer.theme = "light" - assert widget._theme_has_light_bg() is True + assert widget._napari_theme_has_light_bg() is True _mock_up_theme() viewer.theme = "blue" - assert widget._theme_has_light_bg() is True + assert widget._napari_theme_has_light_bg() is True @pytest.mark.parametrize( From 3528dac6b04d3c5942465cd6844f5852c360dede Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 19 Jun 2023 18:16:28 +0100 Subject: [PATCH 2/4] Add theme test --- .../tests/baseline/test_custom_theme.png | Bin 0 -> 15662 bytes src/napari_matplotlib/tests/conftest.py | 6 +++++ .../tests/data/test_theme.mplstyle | 15 ++++++++++++ src/napari_matplotlib/tests/test_theme.py | 22 ++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 src/napari_matplotlib/tests/baseline/test_custom_theme.png create mode 100644 src/napari_matplotlib/tests/data/test_theme.mplstyle diff --git a/src/napari_matplotlib/tests/baseline/test_custom_theme.png b/src/napari_matplotlib/tests/baseline/test_custom_theme.png new file mode 100644 index 0000000000000000000000000000000000000000..65c43a49c60da77f7c6a5401f10aca4a95771f01 GIT binary patch literal 15662 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 Date: Tue, 20 Jun 2023 09:11:27 +0100 Subject: [PATCH 3/4] Update third party docs --- docs/guide/third_party.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/guide/third_party.rst b/docs/guide/third_party.rst index 4a793e6c..d892ba8d 100644 --- a/docs/guide/third_party.rst +++ b/docs/guide/third_party.rst @@ -32,7 +32,6 @@ The following properties and methods are useful for working with the figure and - `~.BaseNapariMPLWidget.figure` provides access to the figure - :meth:`~.BaseNapariMPLWidget.add_single_axes` adds a single axes to the figure, which can be accessed using the ``.axes`` attribute. -- :meth:`~.BaseNapariMPLWidget.apply_napari_colorscheme` can be used to apply the napari colorscheme to any Axes you setup manually on the figure. Working with napari layers -------------------------- From 373f945b86935277394d0629f34d82e591702f2c Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 20 Jun 2023 16:40:19 +0100 Subject: [PATCH 4/4] Add descriptions to light theme Co-authored-by: Sam Cunliffe --- src/napari_matplotlib/styles/light.mplstyle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/napari_matplotlib/styles/light.mplstyle b/src/napari_matplotlib/styles/light.mplstyle index be78f2ce..3b8d7d1d 100644 --- a/src/napari_matplotlib/styles/light.mplstyle +++ b/src/napari_matplotlib/styles/light.mplstyle @@ -1,8 +1,8 @@ # Light-theme napari colour scheme for matplotlib plots -# text (): #3b3a39 -# foreground (): #d6d0ce -# background (): #efebe9 +# text (very dark grey - almost black): #3b3a39 +# foreground (mid grey): #d6d0ce +# background (brownish beige): #efebe9 figure.facecolor : none axes.labelcolor : 3b3a39