|
3 | 3 | Plotting multiple lines with a LineCollection |
4 | 4 | ============================================= |
5 | 5 |
|
6 | | -Matplotlib can efficiently draw multiple lines at once using a |
7 | | -`~.LineCollection`, as showcased below. |
| 6 | +Matplotlib can efficiently draw multiple lines at once using a `~.LineCollection`. |
8 | 7 | """ |
9 | 8 |
|
10 | 9 | import matplotlib.pyplot as plt |
11 | 10 | import numpy as np |
12 | 11 |
|
13 | 12 | from matplotlib.collections import LineCollection |
14 | 13 |
|
15 | | -x = np.arange(100) |
16 | | -# Here are many sets of y to plot vs. x |
17 | | -ys = x[:50, np.newaxis] + x[np.newaxis, :] |
| 14 | +colors = ["indigo", "blue", "green", "yellow", "orange", "red"] |
18 | 15 |
|
19 | | -segs = np.zeros((50, 100, 2)) |
20 | | -segs[:, :, 1] = ys |
21 | | -segs[:, :, 0] = x |
| 16 | +# create a list of half-circles with varying radii |
| 17 | +theta = np.linspace(0, np.pi, 36) |
| 18 | +radii = np.linspace(4, 5, num=len(colors)) |
| 19 | +arcs = [np.column_stack([r * np.cos(theta), r * np.sin(theta)]) for r in radii] |
22 | 20 |
|
23 | | -# Mask some values to test masked array support: |
24 | | -segs = np.ma.masked_where((segs > 50) & (segs < 60), segs) |
| 21 | +fig, ax = plt.subplots(figsize=(6.4, 3.2)) |
| 22 | +# set axes limits manually because Collections do not take part in autoscaling |
| 23 | +ax.set_xlim(-6, 6) |
| 24 | +ax.set_ylim(0, 6) |
| 25 | +ax.set_aspect("equal") # to make the arcs look circular |
25 | 26 |
|
26 | | -# We need to set the plot limits, they will not autoscale |
27 | | -fig, ax = plt.subplots() |
28 | | -ax.set_xlim(x.min(), x.max()) |
29 | | -ax.set_ylim(ys.min(), ys.max()) |
| 27 | +# create a LineCollection with the half-circles |
| 28 | +# its properties can be set per line by passing a sequence (here used for *colors*) |
| 29 | +# or they can be set for all lines by passing a scalar (here used for *linewidths*) |
| 30 | +line_collection = LineCollection(arcs, colors=colors, linewidths=4) |
| 31 | +ax.add_collection(line_collection) |
30 | 32 |
|
31 | | -# *colors* is sequence of rgba tuples. |
32 | | -# *linestyle* is a string or dash tuple. Legal string values are |
33 | | -# solid|dashed|dashdot|dotted. The dash tuple is (offset, onoffseq) where |
34 | | -# onoffseq is an even length tuple of on and off ink in points. If linestyle |
35 | | -# is omitted, 'solid' is used. |
36 | | -# See `matplotlib.collections.LineCollection` for more information. |
37 | | -colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] |
38 | | - |
39 | | -line_segments = LineCollection(segs, linewidths=(0.5, 1, 1.5, 2), |
40 | | - colors=colors, linestyle='solid') |
41 | | -ax.add_collection(line_segments) |
42 | | -ax.set_title('Line collection with masked arrays') |
43 | 33 | plt.show() |
44 | 34 |
|
45 | 35 | # %% |
46 | | -# In the following example, instead of passing a list of colors |
47 | | -# (``colors=colors``), we pass an array of values (``array=x``) that get |
48 | | -# colormapped. |
| 36 | +# Instead of passing a list of colors (``colors=colors``), we can alternatively use |
| 37 | +# colormapping. The lines are then color-coded based on an additional array of values |
| 38 | +# passed to the *array* parameter. In the below example, we color the lines based on |
| 39 | +# their radius by passing ``array=radii``. |
49 | 40 |
|
50 | | -N = 50 |
51 | | -x = np.arange(N) |
52 | | -ys = [x + i for i in x] # Many sets of y to plot vs. x |
53 | | -segs = [np.column_stack([x, y]) for y in ys] |
| 41 | +num_arcs = 15 |
| 42 | +theta = np.linspace(0, np.pi, 36) |
| 43 | +radii = np.linspace(4, 5.5, num=num_arcs) |
| 44 | +arcs = [np.column_stack([r * np.cos(theta), r * np.sin(theta)]) for r in radii] |
54 | 45 |
|
55 | | -fig, ax = plt.subplots() |
56 | | -ax.set_xlim(np.min(x), np.max(x)) |
57 | | -ax.set_ylim(np.min(ys), np.max(ys)) |
| 46 | +fig, ax = plt.subplots(figsize=(6.4, 3)) |
| 47 | +# set axes limits manually because Collections do not take part in autoscaling |
| 48 | +ax.set_xlim(-6, 6) |
| 49 | +ax.set_ylim(0, 6) |
| 50 | +ax.set_aspect("equal") # to make the arcs look circular |
58 | 51 |
|
59 | | -line_segments = LineCollection(segs, array=x, |
60 | | - linewidths=(0.5, 1, 1.5, 2), |
61 | | - linestyles='solid') |
62 | | -ax.add_collection(line_segments) |
63 | | -axcb = fig.colorbar(line_segments) |
64 | | -axcb.set_label('Line Number') |
65 | | -ax.set_title('Line Collection with mapped colors') |
66 | | -plt.sci(line_segments) # This allows interactive changing of the colormap. |
67 | | -plt.show() |
| 52 | +# create a LineCollection with the half-circles and color mapping |
| 53 | +line_collection = LineCollection(arcs, array=radii, cmap="rainbow") |
| 54 | +ax.add_collection(line_collection) |
68 | 55 |
|
| 56 | +fig.colorbar(line_collection, label="Radius") |
| 57 | +ax.set_title("Line Collection with mapped colors") |
| 58 | + |
| 59 | +plt.show() |
69 | 60 | # %% |
70 | 61 | # |
71 | 62 | # .. admonition:: References |
72 | 63 | # |
73 | 64 | # The use of the following functions, methods, classes and modules is shown |
74 | 65 | # in this example: |
75 | 66 | # |
76 | | -# - `matplotlib.collections` |
77 | 67 | # - `matplotlib.collections.LineCollection` |
78 | | -# - `matplotlib.cm.ScalarMappable.set_array` |
| 68 | +# - `matplotlib.collections.Collection.set_array` |
79 | 69 | # - `matplotlib.axes.Axes.add_collection` |
80 | 70 | # - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar` |
81 | | -# - `matplotlib.pyplot.sci` |
0 commit comments