diff --git a/examples/lines_bars_and_markers/curve_error_band.py b/examples/lines_bars_and_markers/curve_error_band.py index 56d95977a54c..e55b467849a8 100644 --- a/examples/lines_bars_and_markers/curve_error_band.py +++ b/examples/lines_bars_and_markers/curve_error_band.py @@ -10,7 +10,6 @@ # sphinx_gallery_thumbnail_number = 2 import numpy as np -from scipy.interpolate import splprep, splev import matplotlib.pyplot as plt from matplotlib.path import Path @@ -22,8 +21,8 @@ x, y = r * np.cos(t), r * np.sin(t) fig, ax = plt.subplots() -ax.plot(x, y) -plt.show() +ax.plot(x, y, "k") +ax.set(aspect=1) ############################################################################# # An error band can be used to indicate the uncertainty of the curve. @@ -39,34 +38,43 @@ # `~.Axes.fill_between` method (see also # :doc:`/gallery/lines_bars_and_markers/fill_between_demo`). -# Error amplitudes depending on the curve parameter *t* -# (actual values are arbitrary and only for illustrative purposes): -err = 0.05 * np.sin(2 * t) ** 2 + 0.04 + 0.02 * np.cos(9 * t + 2) -# calculate normals via derivatives of splines -tck, u = splprep([x, y], s=0) -dx, dy = splev(u, tck, der=1) -l = np.hypot(dx, dy) -nx = dy / l -ny = -dx / l +def draw_error_band(ax, x, y, err, **kwargs): + # Calculate normals via centered finite differences (except the first point + # which uses a forward difference and the last point which uses a backward + # difference). + dx = np.concatenate([[x[1] - x[0]], x[2:] - x[:-2], [x[-1] - x[-2]]]) + dy = np.concatenate([[y[1] - y[0]], y[2:] - y[:-2], [y[-1] - y[-2]]]) + l = np.hypot(dx, dy) + nx = dy / l + ny = -dx / l -# end points of errors -xp = x + nx * err -yp = y + ny * err -xn = x - nx * err -yn = y - ny * err + # end points of errors + xp = x + nx * err + yp = y + ny * err + xn = x - nx * err + yn = y - ny * err -vertices = np.block([[xp, xn[::-1]], - [yp, yn[::-1]]]).T -codes = Path.LINETO * np.ones(len(vertices), dtype=Path.code_type) -codes[0] = codes[len(xp)] = Path.MOVETO -path = Path(vertices, codes) + vertices = np.block([[xp, xn[::-1]], + [yp, yn[::-1]]]).T + codes = np.full(len(vertices), Path.LINETO) + codes[0] = codes[len(xp)] = Path.MOVETO + path = Path(vertices, codes) + ax.add_patch(PathPatch(path, **kwargs)) -patch = PathPatch(path, facecolor='C0', edgecolor='none', alpha=0.3) -fig, ax = plt.subplots() -ax.plot(x, y) -ax.add_patch(patch) +axs = (plt.figure(constrained_layout=True) + .subplots(1, 2, sharex=True, sharey=True)) +errs = [ + (axs[0], "constant error", 0.05), + (axs[1], "variable error", 0.05 * np.sin(2 * t) ** 2 + 0.04), +] +for i, (ax, title, err) in enumerate(errs): + ax.set(title=title, aspect=1, xticks=[], yticks=[]) + ax.plot(x, y, "k") + draw_error_band(ax, x, y, err=err, + facecolor=f"C{i}", edgecolor="none", alpha=.3) + plt.show() #############################################################################
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: