|
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