Skip to content

Commit 8463b87

Browse files
committed
Add support for custom style sheets
1 parent 5ee9696 commit 8463b87

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

Diff for: docs/user_guide.rst

+11
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,14 @@ To use these:
3636
1. Open the desired widget using the ``Plugins > napari-matplotlib`` menu in napari.
3737
2. Select a single layer that has a features table using the napari layers list in the bottom left-hand side of the window.
3838
3. Use the drop down menu(s) under the Matplotlib figure to select the feature(s) to plot.
39+
40+
Customising plots
41+
-----------------
42+
`Matplotlib style sheets <https://matplotlib.org/stable/tutorials/introductory/customizing.html#defining-your-own-style>`__ can be used to customise
43+
the plots generated by ``napari-matplotlib``.
44+
To use a custom style sheet:
45+
46+
1. Save it as ``napari-matplotlib.mplstyle``
47+
2. Put it in the Matplotlib configuration directory.
48+
The location of this directory varies on different computers,
49+
and can be found by calling :func:`matplotlib.get_configdir()`.

Diff for: src/napari_matplotlib/base.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from pathlib import Path
33
from typing import List, Optional, Tuple
44

5+
import matplotlib
56
import matplotlib.style as mplstyle
67
import napari
78
from matplotlib.backends.backend_qtagg import (
@@ -16,6 +17,10 @@
1617

1718
__all__ = ["BaseNapariMPLWidget", "NapariMPLWidget", "SingleAxesWidget"]
1819

20+
_CUSTOM_STYLE_PATH = (
21+
Path(matplotlib.get_configdir()) / "napari-matplotlib.mplstyle"
22+
)
23+
1924

2025
class BaseNapariMPLWidget(QWidget):
2126
"""
@@ -46,7 +51,6 @@ def __init__(
4651
with mplstyle.context(self.mpl_style_sheet_path):
4752
self.canvas = FigureCanvas()
4853

49-
self.canvas.figure.patch.set_facecolor("none")
5054
self.canvas.figure.set_layout_engine("constrained")
5155
self.toolbar = NapariNavigationToolbar(
5256
self.canvas, parent=self
@@ -73,6 +77,8 @@ def mpl_style_sheet_path(self) -> Path:
7377
"""
7478
if self._mpl_style_sheet_path is not None:
7579
return self._mpl_style_sheet_path
80+
elif (_CUSTOM_STYLE_PATH).exists():
81+
return _CUSTOM_STYLE_PATH
7682
elif self._napari_theme_has_light_bg():
7783
return Path(__file__).parent / "styles" / "light.mplstyle"
7884
else:

Diff for: src/napari_matplotlib/tests/test_theme.py

+28-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from copy import deepcopy
2-
31
import shutil
2+
from copy import deepcopy
43
from pathlib import Path
54

65
import matplotlib
@@ -152,27 +151,36 @@ def find_mpl_stylesheet(name: str) -> Path:
152151
return Path(matplotlib.__path__[0]) / f"mpl-data/stylelib/{name}.mplstyle"
153152

154153

155-
def test_stylesheet_in_cwd(tmpdir, make_napari_viewer, image_data):
154+
def test_custom_stylesheet(make_napari_viewer, image_data):
156155
"""
157156
Test that a stylesheet in the current directory is given precidence.
158157
159158
Do this by copying over a stylesheet from matplotlib's built in styles,
160159
naming it correctly, and checking the colours are as expected.
161160
"""
162-
with tmpdir.as_cwd():
163-
# Copy Solarize_Light2 to current dir as if it was a user-overriden stylesheet.
164-
shutil.copy(find_mpl_stylesheet("Solarize_Light2"), "./user.mplstyle")
165-
viewer = make_napari_viewer()
166-
viewer.add_image(image_data[0], **image_data[1])
167-
widget = HistogramWidget(viewer)
168-
ax = widget.figure.gca()
169-
170-
# The axes should have a light brownish grey background:
171-
assert ax.get_facecolor() == to_rgba("#eee8d5")
172-
assert ax.patch.get_facecolor() == to_rgba("#eee8d5")
173-
174-
# The figure background and axis gridlines are light yellow:
175-
assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3")
176-
for gridline in ax.get_xgridlines() + ax.get_ygridlines():
177-
assert gridline.get_visible() is True
178-
assert gridline.get_color() == "#fdf6e3"
161+
# Copy Solarize_Light2 as if it was a user-overriden stylesheet.
162+
style_sheet_path = (
163+
Path(matplotlib.get_configdir()) / "napari-matplotlib.mplstyle"
164+
)
165+
if style_sheet_path.exists():
166+
pytest.skip("Won't ovewrite existing custom style sheet.")
167+
shutil.copy(
168+
find_mpl_stylesheet("Solarize_Light2"),
169+
style_sheet_path,
170+
)
171+
172+
viewer = make_napari_viewer()
173+
viewer.add_image(image_data[0], **image_data[1])
174+
widget = HistogramWidget(viewer)
175+
assert widget.mpl_style_sheet_path == style_sheet_path
176+
ax = widget.figure.gca()
177+
178+
# The axes should have a light brownish grey background:
179+
assert ax.get_facecolor() == to_rgba("#eee8d5")
180+
assert ax.patch.get_facecolor() == to_rgba("#eee8d5")
181+
182+
# The figure background and axis gridlines are light yellow:
183+
assert widget.figure.patch.get_facecolor() == to_rgba("#fdf6e3")
184+
for gridline in ax.get_xgridlines() + ax.get_ygridlines():
185+
assert gridline.get_visible() is True
186+
assert gridline.get_color() == "#fdf6e3"

0 commit comments

Comments
 (0)