Skip to content

Commit d6d15d2

Browse files
authored
Merge pull request #21153 from anntzer/ceb
DOC: Improve curve_error_band example.
2 parents c7c7946 + c9b0277 commit d6d15d2

File tree

1 file changed

+34
-26
lines changed

1 file changed

+34
-26
lines changed

examples/lines_bars_and_markers/curve_error_band.py

+34-26
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
# sphinx_gallery_thumbnail_number = 2
1111

1212
import numpy as np
13-
from scipy.interpolate import splprep, splev
1413

1514
import matplotlib.pyplot as plt
1615
from matplotlib.path import Path
@@ -22,8 +21,8 @@
2221
x, y = r * np.cos(t), r * np.sin(t)
2322

2423
fig, ax = plt.subplots()
25-
ax.plot(x, y)
26-
plt.show()
24+
ax.plot(x, y, "k")
25+
ax.set(aspect=1)
2726

2827
#############################################################################
2928
# An error band can be used to indicate the uncertainty of the curve.
@@ -39,34 +38,43 @@
3938
# `~.Axes.fill_between` method (see also
4039
# :doc:`/gallery/lines_bars_and_markers/fill_between_demo`).
4140

42-
# Error amplitudes depending on the curve parameter *t*
43-
# (actual values are arbitrary and only for illustrative purposes):
44-
err = 0.05 * np.sin(2 * t) ** 2 + 0.04 + 0.02 * np.cos(9 * t + 2)
4541

46-
# calculate normals via derivatives of splines
47-
tck, u = splprep([x, y], s=0)
48-
dx, dy = splev(u, tck, der=1)
49-
l = np.hypot(dx, dy)
50-
nx = dy / l
51-
ny = -dx / l
42+
def draw_error_band(ax, x, y, err, **kwargs):
43+
# Calculate normals via centered finite differences (except the first point
44+
# which uses a forward difference and the last point which uses a backward
45+
# difference).
46+
dx = np.concatenate([[x[1] - x[0]], x[2:] - x[:-2], [x[-1] - x[-2]]])
47+
dy = np.concatenate([[y[1] - y[0]], y[2:] - y[:-2], [y[-1] - y[-2]]])
48+
l = np.hypot(dx, dy)
49+
nx = dy / l
50+
ny = -dx / l
5251

53-
# end points of errors
54-
xp = x + nx * err
55-
yp = y + ny * err
56-
xn = x - nx * err
57-
yn = y - ny * err
52+
# end points of errors
53+
xp = x + nx * err
54+
yp = y + ny * err
55+
xn = x - nx * err
56+
yn = y - ny * err
5857

59-
vertices = np.block([[xp, xn[::-1]],
60-
[yp, yn[::-1]]]).T
61-
codes = Path.LINETO * np.ones(len(vertices), dtype=Path.code_type)
62-
codes[0] = codes[len(xp)] = Path.MOVETO
63-
path = Path(vertices, codes)
58+
vertices = np.block([[xp, xn[::-1]],
59+
[yp, yn[::-1]]]).T
60+
codes = np.full(len(vertices), Path.LINETO)
61+
codes[0] = codes[len(xp)] = Path.MOVETO
62+
path = Path(vertices, codes)
63+
ax.add_patch(PathPatch(path, **kwargs))
6464

65-
patch = PathPatch(path, facecolor='C0', edgecolor='none', alpha=0.3)
6665

67-
fig, ax = plt.subplots()
68-
ax.plot(x, y)
69-
ax.add_patch(patch)
66+
axs = (plt.figure(constrained_layout=True)
67+
.subplots(1, 2, sharex=True, sharey=True))
68+
errs = [
69+
(axs[0], "constant error", 0.05),
70+
(axs[1], "variable error", 0.05 * np.sin(2 * t) ** 2 + 0.04),
71+
]
72+
for i, (ax, title, err) in enumerate(errs):
73+
ax.set(title=title, aspect=1, xticks=[], yticks=[])
74+
ax.plot(x, y, "k")
75+
draw_error_band(ax, x, y, err=err,
76+
facecolor=f"C{i}", edgecolor="none", alpha=.3)
77+
7078
plt.show()
7179

7280
#############################################################################

0 commit comments

Comments
 (0)