From 669cdc26bb6091f1209242b367820a2a6280233a Mon Sep 17 00:00:00 2001 From: Sam Cunliffe Date: Thu, 8 Jun 2023 09:53:09 +0100 Subject: [PATCH 1/3] Test first. A TDD test to check we can set the theme from a user-defined stylesheet. For this, just use Solarized_Light2. --- src/napari_matplotlib/tests/test_theme.py | 38 ++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/napari_matplotlib/tests/test_theme.py b/src/napari_matplotlib/tests/test_theme.py index 7af61f17..fb1416fe 100644 --- a/src/napari_matplotlib/tests/test_theme.py +++ b/src/napari_matplotlib/tests/test_theme.py @@ -1,10 +1,15 @@ from copy import deepcopy +import shutil +from pathlib import Path + +import matplotlib import napari import numpy as np import pytest +from matplotlib.colors import to_rgba -from napari_matplotlib import ScatterWidget +from napari_matplotlib import HistogramWidget, ScatterWidget from napari_matplotlib.base import NapariMPLWidget @@ -140,3 +145,34 @@ def test_custom_theme(make_napari_viewer, theme_path, brain_data): viewer.layers.selection.add(viewer.layers[1]) return deepcopy(widget.figure) + + +def find_mpl_stylesheet(name: str) -> Path: + """Find the built-in matplotlib stylesheet.""" + return Path(matplotlib.__path__[0]) / f"mpl-data/stylelib/{name}.mplstyle" + + +def test_stylesheet_in_cwd(tmpdir, make_napari_viewer, image_data): + """ + Test that a stylesheet in the current directory is given precidence. + + Do this by copying over a stylesheet from matplotlib's built in styles, + naming it correctly, and checking the colours are as expected. + """ + with tmpdir.as_cwd(): + # Copy Solarize_Light2 to current dir as if it was a user-overriden stylesheet. + shutil.copy(find_mpl_stylesheet("Solarize_Light2"), "./user.mplstyle") + viewer = make_napari_viewer() + viewer.add_image(image_data[0], **image_data[1]) + widget = HistogramWidget(viewer) + ax = widget.figure.gca() + + # The axes should have a light brownish grey background: + assert ax.get_facecolor() == to_rgba("#eee8d5") + assert ax.patch.get_facecolor() == to_rgba("#eee8d5") + + # The figure background and axis gridlines are light yellow: + assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3") + for gridline in ax.get_xgridlines() + ax.get_ygridlines(): + assert gridline.get_visible() is True + assert gridline.get_color() == "#fdf6e3" From 13d22686764bb2badc973dca6331eafd7a15c135 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 26 Jun 2023 20:42:24 +0100 Subject: [PATCH 2/3] Add support for custom style sheets --- docs/user_guide.rst | 11 ++++++ src/napari_matplotlib/base.py | 8 +++- src/napari_matplotlib/tests/test_theme.py | 48 +++++++++++++---------- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 15b44f44..0872e540 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -36,3 +36,14 @@ To use these: 1. Open the desired widget using the ``Plugins > napari-matplotlib`` menu in napari. 2. Select a single layer that has a features table using the napari layers list in the bottom left-hand side of the window. 3. Use the drop down menu(s) under the Matplotlib figure to select the feature(s) to plot. + +Customising plots +----------------- +`Matplotlib style sheets `__ can be used to customise +the plots generated by ``napari-matplotlib``. +To use a custom style sheet: + +1. Save it as ``napari-matplotlib.mplstyle`` +2. Put it in the Matplotlib configuration directory. + The location of this directory varies on different computers, + and can be found by calling :func:`matplotlib.get_configdir()`. diff --git a/src/napari_matplotlib/base.py b/src/napari_matplotlib/base.py index 89c6d3de..792b5aff 100644 --- a/src/napari_matplotlib/base.py +++ b/src/napari_matplotlib/base.py @@ -2,6 +2,7 @@ from pathlib import Path from typing import List, Optional, Tuple +import matplotlib import matplotlib.style as mplstyle import napari from matplotlib.backends.backend_qtagg import ( @@ -16,6 +17,10 @@ __all__ = ["BaseNapariMPLWidget", "NapariMPLWidget", "SingleAxesWidget"] +_CUSTOM_STYLE_PATH = ( + Path(matplotlib.get_configdir()) / "napari-matplotlib.mplstyle" +) + class BaseNapariMPLWidget(QWidget): """ @@ -46,7 +51,6 @@ def __init__( 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") self.toolbar = NapariNavigationToolbar( self.canvas, parent=self @@ -73,6 +77,8 @@ def mpl_style_sheet_path(self) -> Path: """ if self._mpl_style_sheet_path is not None: return self._mpl_style_sheet_path + elif (_CUSTOM_STYLE_PATH).exists(): + return _CUSTOM_STYLE_PATH elif self._napari_theme_has_light_bg(): return Path(__file__).parent / "styles" / "light.mplstyle" else: diff --git a/src/napari_matplotlib/tests/test_theme.py b/src/napari_matplotlib/tests/test_theme.py index fb1416fe..49738abd 100644 --- a/src/napari_matplotlib/tests/test_theme.py +++ b/src/napari_matplotlib/tests/test_theme.py @@ -1,6 +1,5 @@ -from copy import deepcopy - import shutil +from copy import deepcopy from pathlib import Path import matplotlib @@ -152,27 +151,36 @@ def find_mpl_stylesheet(name: str) -> Path: return Path(matplotlib.__path__[0]) / f"mpl-data/stylelib/{name}.mplstyle" -def test_stylesheet_in_cwd(tmpdir, make_napari_viewer, image_data): +def test_custom_stylesheet(make_napari_viewer, image_data): """ Test that a stylesheet in the current directory is given precidence. Do this by copying over a stylesheet from matplotlib's built in styles, naming it correctly, and checking the colours are as expected. """ - with tmpdir.as_cwd(): - # Copy Solarize_Light2 to current dir as if it was a user-overriden stylesheet. - shutil.copy(find_mpl_stylesheet("Solarize_Light2"), "./user.mplstyle") - viewer = make_napari_viewer() - viewer.add_image(image_data[0], **image_data[1]) - widget = HistogramWidget(viewer) - ax = widget.figure.gca() - - # The axes should have a light brownish grey background: - assert ax.get_facecolor() == to_rgba("#eee8d5") - assert ax.patch.get_facecolor() == to_rgba("#eee8d5") - - # The figure background and axis gridlines are light yellow: - assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3") - for gridline in ax.get_xgridlines() + ax.get_ygridlines(): - assert gridline.get_visible() is True - assert gridline.get_color() == "#fdf6e3" + # Copy Solarize_Light2 as if it was a user-overriden stylesheet. + style_sheet_path = ( + Path(matplotlib.get_configdir()) / "napari-matplotlib.mplstyle" + ) + if style_sheet_path.exists(): + pytest.skip("Won't ovewrite existing custom style sheet.") + shutil.copy( + find_mpl_stylesheet("Solarize_Light2"), + style_sheet_path, + ) + + viewer = make_napari_viewer() + viewer.add_image(image_data[0], **image_data[1]) + widget = HistogramWidget(viewer) + assert widget.mpl_style_sheet_path == style_sheet_path + ax = widget.figure.gca() + + # The axes should have a light brownish grey background: + assert ax.get_facecolor() == to_rgba("#eee8d5") + assert ax.patch.get_facecolor() == to_rgba("#eee8d5") + + # The figure background and axis gridlines are light yellow: + assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3") + for gridline in ax.get_xgridlines() + ax.get_ygridlines(): + assert gridline.get_visible() is True + assert gridline.get_color() == "#fdf6e3" From 3e6bf2c2ff899145c11cf056cc28c64849c26090 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 26 Jun 2023 20:58:25 +0100 Subject: [PATCH 3/3] Delte style sheet after test --- src/napari_matplotlib/tests/test_theme.py | 34 +++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/napari_matplotlib/tests/test_theme.py b/src/napari_matplotlib/tests/test_theme.py index 49738abd..a3642f8f 100644 --- a/src/napari_matplotlib/tests/test_theme.py +++ b/src/napari_matplotlib/tests/test_theme.py @@ -1,3 +1,4 @@ +import os import shutil from copy import deepcopy from pathlib import Path @@ -169,18 +170,21 @@ def test_custom_stylesheet(make_napari_viewer, image_data): style_sheet_path, ) - viewer = make_napari_viewer() - viewer.add_image(image_data[0], **image_data[1]) - widget = HistogramWidget(viewer) - assert widget.mpl_style_sheet_path == style_sheet_path - ax = widget.figure.gca() - - # The axes should have a light brownish grey background: - assert ax.get_facecolor() == to_rgba("#eee8d5") - assert ax.patch.get_facecolor() == to_rgba("#eee8d5") - - # The figure background and axis gridlines are light yellow: - assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3") - for gridline in ax.get_xgridlines() + ax.get_ygridlines(): - assert gridline.get_visible() is True - assert gridline.get_color() == "#fdf6e3" + try: + viewer = make_napari_viewer() + viewer.add_image(image_data[0], **image_data[1]) + widget = HistogramWidget(viewer) + assert widget.mpl_style_sheet_path == style_sheet_path + ax = widget.figure.gca() + + # The axes should have a light brownish grey background: + assert ax.get_facecolor() == to_rgba("#eee8d5") + assert ax.patch.get_facecolor() == to_rgba("#eee8d5") + + # The figure background and axis gridlines are light yellow: + assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3") + for gridline in ax.get_xgridlines() + ax.get_ygridlines(): + assert gridline.get_visible() is True + assert gridline.get_color() == "#fdf6e3" + finally: + os.remove(style_sheet_path) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy