I'm plotting multiple lines using matplolib's Line2D and want to pick or select all lines at once.
The MWE provided plots a triangle (could be any polygon or shape) and includes a function which enables to pick every line separately. I would like to pick the whole triangle by clicking on it. Additionally I noticed that if I add another line the onPick function doesn't work at all. Does anyone have an idea what I did wrong?
Edit As suggested in the comments below I added a Polygon and a modified function pick_simple() (from: https://matplotlib.org/3.1.0/gallery/event_handling/pick_event_demo.html). But unfortunately this brings new problems. By plotting the Polygon I get a filled blue patch even though I set fill=False as well as linewidth and color. Also the pick_simple() function doesn't do anything which confuses me a lot.
from matplotlib import pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
fig = plt.figure()
ax = fig.add_subplot(111)
triangle = [[0.1, 0.3],
[0.2, 0.8],
[0.3, 0.5],
[0.1, 0.3]]
for i in range(len(triangle)-1):
tri = Line2D([triangle[i][0],triangle[i+1][0]],[triangle[i][1],
triangle[i+1][1]], linewidth=0.75, color='#F97306')
tri.set_picker(True)
ax.add_line(tri)
geometry = [[0.0,0.0],[0.1,0.05],[0.2,0.15],[0.3,0.20],[0.4,0.25],[0.5,0.30],
[0.6,0.25],[0.7,0.15],[0.8,0.05],[0.9,0.025],[1.0,0.0]]
patches = []
polygon = Polygon(geometry, closed=False, fill=False, linewidth=0.75, color='#F97306')
polygon.set_picker(True)
patches.append(polygon)
p = PatchCollection(patches)
ax.add_collection(p)
plt.show()
def pick_simple():
def onpick(event):
if isinstance(event.artist, Polygon):
patch = event.artist
print('onpick patch:', patch.get_path())
fig.canvas.mpl_connect('pick_event', onpick)
def pick_factory(ax):
def onPick(event):
if event.inaxes == ax:
for line in ax.lines:
if line.get_picker():
cont, ind = line.contains(event)
if cont:
line.set_color('#029386')
line.set_linewidth(5)
ax.figure.canvas.draw_idle()
fig = ax.get_figure() # get the figure of interest
fig.canvas.mpl_connect('button_press_event', onPick)
pick_factory(ax)
pick_simple()
There are a couple of smaller mistakes.
event.ind
.PatchCollection
's aim is usually to set the properties, like linewidth, color, etc., of its children itself. If you don't want that, you need to use the match_original=True
Complete code:
from matplotlib import pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
fig = plt.figure()
ax = fig.add_subplot(111)
geometry = [[0.0,0.0],[0.1,0.05],[0.2,0.15],[0.3,0.20],[0.4,0.25],[0.5,0.30],
[0.6,0.25],[0.7,0.15],[0.8,0.05],[0.9,0.025],[1.0,0.0]]
patches = []
polygon = Polygon(geometry, closed=False, fill=False, linewidth=3, color='#F97306')
patches.append(polygon)
p = PatchCollection(patches, match_original=True)
p.set_picker(True)
ax.add_collection(p)
def pick_simple():
def onpick(event):
if isinstance(event.artist, PatchCollection):
collection = event.artist
print('onpick collection:', collection)
print('picked index', event.ind)
print('path at index', collection.get_paths()[event.ind[0]])
return fig.canvas.mpl_connect('pick_event', onpick)
cid = pick_simple()
plt.show()