Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 931cf4a

Browse files
story645anntzer
andcommitted
Adds xkcd style sheet, replicates tests using plt.xkcd with xkcd style,
Co-authored-by: Antony Lee <[email protected]>
1 parent e20e646 commit 931cf4a

File tree

6 files changed

+136
-43
lines changed

6 files changed

+136
-43
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
path.effects rcParam can be set in stylesheet and new xkcd stylesheet
2+
---------------------------------------------------------------------
3+
4+
Can now set the ``path.effects`` :ref:`rcParam in a style sheet <customizing>`
5+
using a list of ``(patheffects function name, {**kwargs})``::
6+
7+
path.effects: ('Normal', ), ('Stroke', {'offset': (1, 2)}), ('withStroke', {'linewidth': 4, 'foreground': 'w'})
8+
9+
10+
This feature means that the xkcd style can be used like any other stylesheet:
11+
12+
.. plot::
13+
:include-source: true
14+
:alt: plot where graph and text appear in a hand drawn comic like style
15+
16+
import numpy as np
17+
import matplotlib.pyplot as plt
18+
19+
x = np.linspace(0, 2* np.pi, 100)
20+
y = np.sin(x)
21+
22+
with plt.style.context('xkcd'):
23+
24+
fig, ax = plt.subplots()
25+
ax.set_title("sine curve")
26+
ax.plot(x, y)

galleries/examples/style_sheets/style_sheets_reference.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import matplotlib.pyplot as plt
2424
import numpy as np
2525

26+
import matplotlib as mpl
2627
import matplotlib.colors as mcolors
2728
from matplotlib.patches import Rectangle
2829

@@ -47,7 +48,7 @@ def plot_colored_lines(ax):
4748
def sigmoid(t, t0):
4849
return 1 / (1 + np.exp(-(t - t0)))
4950

50-
nb_colors = len(plt.rcParams['axes.prop_cycle'])
51+
nb_colors = len(mpl.rcParams['axes.prop_cycle'])
5152
shifts = np.linspace(-5, 5, nb_colors)
5253
amplitudes = np.linspace(1, 1.5, nb_colors)
5354
for t0, a in zip(shifts, amplitudes):
@@ -75,14 +76,15 @@ def plot_colored_circles(ax, prng, nb_samples=15):
7576
the color cycle, because different styles may have different numbers
7677
of colors.
7778
"""
78-
for sty_dict, j in zip(plt.rcParams['axes.prop_cycle'](),
79+
for sty_dict, j in zip(mpl.rcParams['axes.prop_cycle'](),
7980
range(nb_samples)):
8081
ax.add_patch(plt.Circle(prng.normal(scale=3, size=2),
8182
radius=1.0, color=sty_dict['color']))
8283
ax.grid(visible=True)
8384

8485
# Add title for enabling grid
85-
plt.title('ax.grid(True)', family='monospace', fontsize='small')
86+
font_family = mpl.rcParams.get('font.family', 'monospace')
87+
ax.set_title('ax.grid(True)', family=font_family, fontsize='medium')
8688

8789
ax.set_xlim([-4, 8])
8890
ax.set_ylim([-5, 6])
@@ -133,11 +135,12 @@ def plot_figure(style_label=""):
133135
# make a suptitle, in the same style for all subfigures,
134136
# except those with dark backgrounds, which get a lighter color:
135137
background_color = mcolors.rgb_to_hsv(
136-
mcolors.to_rgb(plt.rcParams['figure.facecolor']))[2]
138+
mcolors.to_rgb(mpl.rcParams['figure.facecolor']))[2]
137139
if background_color < 0.5:
138140
title_color = [0.8, 0.8, 1]
139141
else:
140142
title_color = np.array([19, 6, 84]) / 256
143+
141144
fig.suptitle(style_label, x=0.01, ha='left', color=title_color,
142145
fontsize=14, fontfamily='DejaVu Sans', fontweight='normal')
143146

@@ -147,28 +150,25 @@ def plot_figure(style_label=""):
147150
plot_colored_lines(axs[3])
148151
plot_histograms(axs[4], prng)
149152
plot_colored_circles(axs[5], prng)
150-
151153
# add divider
152154
rec = Rectangle((1 + 0.025, -2), 0.05, 16,
153155
clip_on=False, color='gray')
154156

155157
axs[4].add_artist(rec)
156158

157-
if __name__ == "__main__":
158-
159-
# Set up a list of all available styles, in alphabetical order but
160-
# the `default` and `classic` ones, which will be forced resp. in
161-
# first and second position.
162-
# styles with leading underscores are for internal use such as testing
163-
# and plot types gallery. These are excluded here.
164-
style_list = ['default', 'classic'] + sorted(
165-
style for style in plt.style.available
166-
if style != 'classic' and not style.startswith('_'))
167-
168-
# Plot a demonstration figure for every available style sheet.
169-
for style_label in style_list:
170-
with plt.rc_context({"figure.max_open_warning": len(style_list)}):
171-
with plt.style.context(style_label):
172-
plot_figure(style_label=style_label)
173159

174-
plt.show()
160+
# Set up a list of all available styles, in alphabetical order but
161+
# the `default` and `classic` ones, which will be forced resp. in
162+
# first and second position.
163+
# styles with leading underscores are for internal use such as testing
164+
# and plot types gallery. These are excluded here.
165+
style_list = ['default', 'classic'] + sorted(
166+
style for style in mpl.style.available
167+
if style != 'classic' and not style.startswith('_'))
168+
169+
# Plot a demonstration figure for every available style sheet:
170+
for style_label in style_list:
171+
with mpl.rc_context({"figure.max_open_warning": len(style_list)}):
172+
with mpl.style.context(style_label, after_reset=True):
173+
plot_figure(style_label=style_label)
174+
plt.show()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## default xkcd style
2+
3+
# line
4+
lines.linewidth : 2.0
5+
6+
# font
7+
font.family : xkcd, xkcd Script, Comic Neue, Comic Sans MS
8+
font.size : 14.0
9+
10+
# axes
11+
axes.linewidth : 1.5
12+
axes.grid : False
13+
axes.unicode_minus: False
14+
axes.edgecolor: black
15+
16+
# ticks
17+
xtick.major.size : 8
18+
xtick.major.width: 3
19+
ytick.major.size : 8
20+
ytick.major.width: 3
21+
22+
# grids
23+
grid.linewidth: 0.0
24+
25+
# figure
26+
figure.facecolor: white
27+
28+
# path
29+
path.sketch : 1, 100, 2
30+
path.effects: ('withStroke', {'linewidth': 4, 'foreground': 'w' })

lib/matplotlib/pyplot.py

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -747,27 +747,8 @@ def xkcd(
747747
stack = ExitStack()
748748
stack.callback(dict.update, rcParams, rcParams.copy()) # type: ignore
749749

750-
from matplotlib import patheffects
751-
rcParams.update({
752-
'font.family': ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue',
753-
'Comic Sans MS'],
754-
'font.size': 14.0,
755-
'path.sketch': (scale, length, randomness),
756-
'path.effects': [
757-
patheffects.withStroke(linewidth=4, foreground="w")],
758-
'axes.linewidth': 1.5,
759-
'lines.linewidth': 2.0,
760-
'figure.facecolor': 'white',
761-
'grid.linewidth': 0.0,
762-
'axes.grid': False,
763-
'axes.unicode_minus': False,
764-
'axes.edgecolor': 'black',
765-
'xtick.major.size': 8,
766-
'xtick.major.width': 3,
767-
'ytick.major.size': 8,
768-
'ytick.major.width': 3,
769-
})
770-
750+
rcParams.update({**style.library["xkcd"],
751+
'path.sketch': (scale, length, randomness)})
771752
return stack
772753

773754

lib/matplotlib/tests/test_path.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ def test_xkcd():
253253
ax.plot(x, y)
254254

255255

256+
@image_comparison(['xkcd.png'], remove_text=True)
257+
def test_xkcd_style():
258+
np.random.seed(0)
259+
260+
x = np.linspace(0, 2 * np.pi, 100)
261+
y = np.sin(x)
262+
263+
with plt.style.context('xkcd'):
264+
fig, ax = plt.subplots()
265+
ax.plot(x, y)
266+
267+
256268
@image_comparison(['xkcd_marker.png'], remove_text=True)
257269
def test_xkcd_marker():
258270
np.random.seed(0)
@@ -269,6 +281,22 @@ def test_xkcd_marker():
269281
ax.plot(x, y3, '^', ms=10)
270282

271283

284+
@image_comparison(['xkcd_marker.png'], remove_text=True)
285+
def test_xkcd_marker_style():
286+
np.random.seed(0)
287+
288+
x = np.linspace(0, 5, 8)
289+
y1 = x
290+
y2 = 5 - x
291+
y3 = 2.5 * np.ones(8)
292+
293+
with plt.style.context('xkcd'):
294+
fig, ax = plt.subplots()
295+
ax.plot(x, y1, '+', ms=10)
296+
ax.plot(x, y2, 'o', ms=10)
297+
ax.plot(x, y3, '^', ms=10)
298+
299+
272300
@image_comparison(['marker_paths.pdf'], remove_text=True)
273301
def test_marker_paths_pdf():
274302
N = 7

lib/matplotlib/tests/test_style.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import matplotlib as mpl
1010
from matplotlib import pyplot as plt, style
11+
from matplotlib.testing.decorators import check_figures_equal
1112
from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
1213

1314

@@ -170,13 +171,40 @@ def test_xkcd_no_cm():
170171
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
171172

172173

174+
def test_xkcd_no_cm_style():
175+
assert mpl.rcParams["path.sketch"] is None
176+
plt.style.use('xkcd')
177+
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
178+
np.testing.break_cycles()
179+
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
180+
181+
173182
def test_xkcd_cm():
174183
assert mpl.rcParams["path.sketch"] is None
175184
with plt.xkcd():
176185
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
177186
assert mpl.rcParams["path.sketch"] is None
178187

179188

189+
def test_xkcd_cm_style():
190+
assert mpl.rcParams["path.sketch"] is None
191+
with style.context('xkcd'):
192+
assert mpl.rcParams["path.sketch"] == (1, 100, 2)
193+
assert mpl.rcParams["path.sketch"] is None
194+
195+
196+
@check_figures_equal()
197+
def test_xkcd_style(fig_test, fig_ref):
198+
199+
with style.context('xkcd'):
200+
fig_test.subplots().plot([1, 2, 3])
201+
fig_test.text(.5, .5, "Hello World!")
202+
203+
with plt.xkcd():
204+
fig_ref.subplots().plot([1, 2, 3])
205+
fig_ref.text(.5, .5, "Hello World!")
206+
207+
180208
def test_up_to_date_blacklist():
181209
assert mpl.style.core.STYLE_BLACKLIST <= {*mpl.rcsetup._validators}
182210

0 commit comments

Comments
 (0)