|
3 | 3 | Markevery Demo |
4 | 4 | ============== |
5 | 5 |
|
6 | | -This example demonstrates the various options for showing a marker at a |
7 | | -subset of data points using the ``markevery`` property of a Line2D object. |
8 | | -
|
9 | | -Integer arguments are fairly intuitive. e.g. ``markevery=5`` will plot every |
10 | | -5th marker starting from the first data point. |
11 | | -
|
12 | | -Float arguments allow markers to be spaced at approximately equal distances |
13 | | -along the line. The theoretical distance along the line between markers is |
14 | | -determined by multiplying the display-coordinate distance of the axes |
15 | | -bounding-box diagonal by the value of ``markevery``. The data points closest |
16 | | -to the theoretical distances will be shown. |
17 | | -
|
18 | | -A slice or list/array can also be used with ``markevery`` to specify the |
19 | | -markers to show. |
| 6 | +The ``markevery`` property of `.Line2D` allows drawing markers at a subset of |
| 7 | +data points. |
| 8 | +
|
| 9 | +The list of possible parameters is specified at `.Line2D.set_markevery`. |
| 10 | +In short: |
| 11 | +
|
| 12 | +- A single integer N draws every N-th marker. |
| 13 | +- A tuple of integers (start, N) draws every N-th marker, starting at data |
| 14 | + index *start*. |
| 15 | +- A list of integers draws the markers at the specified indices. |
| 16 | +- A slice draws the markers at the sliced indices. |
| 17 | +- A float specifies the distance between markers as a fraction of the Axes |
| 18 | + diagonal in screen space. This will lead to a visually uniform distribution |
| 19 | + of the points along the line, irrespective of scales and zooming. |
20 | 20 | """ |
21 | 21 |
|
22 | 22 | import numpy as np |
23 | 23 | import matplotlib.pyplot as plt |
24 | 24 |
|
25 | 25 | # define a list of markevery cases to plot |
26 | | -cases = [None, |
27 | | - 8, |
28 | | - (30, 8), |
29 | | - [16, 24, 30], [0, -1], |
30 | | - slice(100, 200, 3), |
31 | | - 0.1, 0.3, 1.5, |
32 | | - (0.0, 0.1), (0.45, 0.1)] |
33 | | - |
34 | | -# define the figure size and grid layout properties |
35 | | -figsize = (10, 8) |
36 | | -cols = 3 |
37 | | -rows = len(cases) // cols + 1 |
38 | | -# define the data for cartesian plots |
| 26 | +cases = [ |
| 27 | + None, |
| 28 | + 8, |
| 29 | + (30, 8), |
| 30 | + [16, 24, 32], |
| 31 | + [0, -1], |
| 32 | + slice(100, 200, 3), |
| 33 | + 0.1, |
| 34 | + 0.4, |
| 35 | + (0.2, 0.4) |
| 36 | +] |
| 37 | + |
| 38 | +# data points |
39 | 39 | delta = 0.11 |
40 | 40 | x = np.linspace(0, 10 - 2 * delta, 200) + delta |
41 | 41 | y = np.sin(x) + 1.0 + delta |
42 | 42 |
|
43 | | - |
44 | | -def trim_axs(axs, N): |
45 | | - """ |
46 | | - Reduce *axs* to *N* Axes. All further Axes are removed from the figure. |
47 | | - """ |
48 | | - axs = axs.flat |
49 | | - for ax in axs[N:]: |
50 | | - ax.remove() |
51 | | - return axs[:N] |
52 | | - |
53 | 43 | ############################################################################### |
54 | | -# Plot each markevery case for linear x and y scales |
| 44 | +# markevery with linear scales |
| 45 | +# ---------------------------- |
55 | 46 |
|
56 | | -axs = plt.figure(figsize=figsize, constrained_layout=True).subplots(rows, cols) |
57 | | -axs = trim_axs(axs, len(cases)) |
58 | | -for ax, case in zip(axs, cases): |
59 | | - ax.set_title('markevery=%s' % str(case)) |
60 | | - ax.plot(x, y, 'o', ls='-', ms=4, markevery=case) |
| 47 | +fig, axs = plt.subplots(3, 3, figsize=(10, 6), constrained_layout=True) |
| 48 | +for ax, markevery in zip(axs.flat, cases): |
| 49 | + ax.set_title(f'markevery={markevery}') |
| 50 | + ax.plot(x, y, 'o', ls='-', ms=4, markevery=markevery) |
61 | 51 |
|
62 | 52 | ############################################################################### |
63 | | -# Plot each markevery case for log x and y scales |
64 | | - |
65 | | -axs = plt.figure(figsize=figsize, constrained_layout=True).subplots(rows, cols) |
66 | | -axs = trim_axs(axs, len(cases)) |
67 | | -for ax, case in zip(axs, cases): |
68 | | - ax.set_title('markevery=%s' % str(case)) |
| 53 | +# markevery with log scales |
| 54 | +# ------------------------- |
| 55 | +# |
| 56 | +# Note that the log scale causes a visual asymmetry in the marker distance for |
| 57 | +# when subsampling the data using an integer. In contrast, subsampling on |
| 58 | +# fraction of figure size creates even distributions, because it's based on |
| 59 | +# fractions of the Axes diagonal, not on data coordinates or data indices. |
| 60 | + |
| 61 | +fig, axs = plt.subplots(3, 3, figsize=(10, 6), constrained_layout=True) |
| 62 | +for ax, markevery in zip(axs.flat, cases): |
| 63 | + ax.set_title(f'markevery={markevery}') |
69 | 64 | ax.set_xscale('log') |
70 | 65 | ax.set_yscale('log') |
71 | | - ax.plot(x, y, 'o', ls='-', ms=4, markevery=case) |
| 66 | + ax.plot(x, y, 'o', ls='-', ms=4, markevery=markevery) |
72 | 67 |
|
73 | 68 | ############################################################################### |
74 | | -# Plot each markevery case for linear x and y scales but zoomed in |
75 | | -# note the behaviour when zoomed in. When a start marker offset is specified |
76 | | -# it is always interpreted with respect to the first data point which might be |
77 | | -# different to the first visible data point. |
78 | | - |
79 | | -axs = plt.figure(figsize=figsize, constrained_layout=True).subplots(rows, cols) |
80 | | -axs = trim_axs(axs, len(cases)) |
81 | | -for ax, case in zip(axs, cases): |
82 | | - ax.set_title('markevery=%s' % str(case)) |
83 | | - ax.plot(x, y, 'o', ls='-', ms=4, markevery=case) |
| 69 | +# markevery on zoomed plots |
| 70 | +# ------------------------- |
| 71 | +# |
| 72 | +# Integer-based *markevery* specifications select points from the underlying |
| 73 | +# data and are independent on the view. In contrast, float-based specifications |
| 74 | +# are related to the Axes diagonal. While zooming does not change the Axes |
| 75 | +# diagonal, it changes the displayed data range, and more points will be |
| 76 | +# displayed when zooming. |
| 77 | + |
| 78 | +fig, axs = plt.subplots(3, 3, figsize=(10, 6), constrained_layout=True) |
| 79 | +for ax, markevery in zip(axs.flat, cases): |
| 80 | + ax.set_title(f'markevery={markevery}') |
| 81 | + ax.plot(x, y, 'o', ls='-', ms=4, markevery=markevery) |
84 | 82 | ax.set_xlim((6, 6.7)) |
85 | 83 | ax.set_ylim((1.1, 1.7)) |
86 | 84 |
|
87 | | -# define data for polar plots |
| 85 | +############################################################################### |
| 86 | +# markevery on polar plots |
| 87 | +# ------------------------ |
| 88 | + |
88 | 89 | r = np.linspace(0, 3.0, 200) |
89 | 90 | theta = 2 * np.pi * r |
90 | 91 |
|
91 | | -############################################################################### |
92 | | -# Plot each markevery case for polar plots |
93 | | - |
94 | | -axs = plt.figure(figsize=figsize, constrained_layout=True).subplots( |
95 | | - rows, cols, subplot_kw={'projection': 'polar'}) |
96 | | -axs = trim_axs(axs, len(cases)) |
97 | | -for ax, case in zip(axs, cases): |
98 | | - ax.set_title('markevery=%s' % str(case)) |
99 | | - ax.plot(theta, r, 'o', ls='-', ms=4, markevery=case) |
| 92 | +fig, axs = plt.subplots(3, 3, figsize=(10, 6), constrained_layout=True, |
| 93 | + subplot_kw={'projection': 'polar'}) |
| 94 | +for ax, markevery in zip(axs.flat, cases): |
| 95 | + ax.set_title(f'markevery={markevery}') |
| 96 | + ax.plot(theta, r, 'o', ls='-', ms=4, markevery=markevery) |
100 | 97 |
|
101 | 98 | plt.show() |
0 commit comments