Skip to content

Commit

Permalink
Simplify the LineCollection example
Browse files Browse the repository at this point in the history
Superseeds matplotlib#27871.

This example is much simpler, but conveys the same LineCollection
aspects - except for not using masked arrays. But I argue that this
the example should be simple and using masked arrays rather distracts
from the core aspects of LineCollection.

If there's concern of not showing masked array support, we should add
a third plot for that.
  • Loading branch information
timhoffm committed Mar 6, 2024
1 parent 70b1e80 commit c42c055
Showing 1 changed file with 35 additions and 47 deletions.
82 changes: 35 additions & 47 deletions galleries/examples/shapes_and_collections/line_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,67 @@
Plotting multiple lines with a LineCollection
=============================================
Matplotlib can efficiently draw multiple lines at once using a
`~.LineCollection`, as showcased below.
Matplotlib can efficiently draw multiple lines at once using a `~.LineCollection`.
"""

import matplotlib.pyplot as plt
import numpy as np

from matplotlib.collections import LineCollection

x = np.arange(100)
# Here are many sets of y to plot vs. x
ys = x[:50, np.newaxis] + x[np.newaxis, :]
colors = ['violet', 'blue', 'green', 'yellow', 'orange', 'red']

segs = np.zeros((50, 100, 2))
segs[:, :, 1] = ys
segs[:, :, 0] = x
# create a list of half-circles with varying radii
theta = np.linspace(0, np.pi, 36)
radii = np.linspace(4, 5, num=len(colors))
arcs = [np.column_stack([r * np.cos(theta), r * np.sin(theta)]) for r in radii]

# Mask some values to test masked array support:
segs = np.ma.masked_where((segs > 50) & (segs < 60), segs)
fig, ax = plt.subplots(figsize=(6.4, 3.2))
# set axes limits manually because Collections do not take part in autoscaling
ax.set_xlim(-6, 6)
ax.set_ylim(0, 6)
ax.set_aspect("equal") # to make the arcs look circular

# We need to set the plot limits, they will not autoscale
fig, ax = plt.subplots()
ax.set_xlim(x.min(), x.max())
ax.set_ylim(ys.min(), ys.max())
# create a LineCollection with the half-circles
# its properties can be set per line by passing a sequence (here used for *colors*)
# or they can be set for all lines by passing a scalar (here used for *linewidths*)
line_collection = LineCollection(arcs, colors=colors, linewidths=4)
ax.add_collection(line_collection)

# *colors* is sequence of rgba tuples.
# *linestyle* is a string or dash tuple. Legal string values are
# solid|dashed|dashdot|dotted. The dash tuple is (offset, onoffseq) where
# onoffseq is an even length tuple of on and off ink in points. If linestyle
# is omitted, 'solid' is used.
# See `matplotlib.collections.LineCollection` for more information.
colors = plt.rcParams['axes.prop_cycle'].by_key()['color']

line_segments = LineCollection(segs, linewidths=(0.5, 1, 1.5, 2),
colors=colors, linestyle='solid')
ax.add_collection(line_segments)
ax.set_title('Line collection with masked arrays')
plt.show()

# %%
# In the following example, instead of passing a list of colors
# (``colors=colors``), we pass an array of values (``array=x``) that get
# colormapped.
# Instead of passing a list of colors (``colors=colors``), we can use colormapping.
# The data to be mapped are passed via the ``array`` parameter.

num_arcs = 15
theta = np.linspace(0, np.pi, 36)
radii = np.linspace(4, 5.5, num=num_arcs)
arcs = [np.column_stack([r * np.cos(theta), r * np.sin(theta)]) for r in radii]
arc_numbers = np.arange(num_arcs)

N = 50
x = np.arange(N)
ys = [x + i for i in x] # Many sets of y to plot vs. x
segs = [np.column_stack([x, y]) for y in ys]
fig, ax = plt.subplots(figsize=(6.4, 3))
# set axes limits manually because Collections do not take part in autoscaling
ax.set_xlim(-6, 6)
ax.set_ylim(0, 6)
ax.set_aspect("equal") # to make the arcs look circular

fig, ax = plt.subplots()
ax.set_xlim(np.min(x), np.max(x))
ax.set_ylim(np.min(ys), np.max(ys))
# create a LineCollection with the half-circles and color mapping
line_collection = LineCollection(arcs, array=arc_numbers, cmap='rainbow')
ax.add_collection(line_collection)

line_segments = LineCollection(segs, array=x,
linewidths=(0.5, 1, 1.5, 2),
linestyles='solid')
ax.add_collection(line_segments)
axcb = fig.colorbar(line_segments)
axcb.set_label('Line Number')
fig.colorbar(line_collection, label='Line number')
ax.set_title('Line Collection with mapped colors')
plt.sci(line_segments) # This allows interactive changing of the colormap.
plt.show()

plt.show()
# %%
#
# .. admonition:: References
#
# The use of the following functions, methods, classes and modules is shown
# in this example:
#
# - `matplotlib.collections`
# - `matplotlib.collections.LineCollection`
# - `matplotlib.cm.ScalarMappable.set_array`
# - `matplotlib.collections.Collection.set_array`
# - `matplotlib.axes.Axes.add_collection`
# - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar`
# - `matplotlib.pyplot.sci`

0 comments on commit c42c055

Please sign in to comment.