Reputation: 135
I have several data series scattered in a figure and want to be able to toggle annotations for them. The problem is, sometimes there are two pick events triggered (when the user clicks on a spot that is within both an annotation and a dot). The "annotation" pick event clears the annotation, but the "dot" pick event puts it right back, so the effect is the toggle doesn't work.
df = pd.DataFrame({'a': np.random.rand(25)*1000,
'b': np.random.rand(25)*1000,
'c': np.random.rand(25)})
def handlepick(event):
artist = event.artist
if isinstance(artist, matplotlib.text.Annotation):
artist.set_visible(not artist.get_visible())
else:
x = event.mouseevent.xdata
y = event.mouseevent.ydata
if artist.get_label() == 'a':
ann = matplotlib.text.Annotation('blue', xy=(x,y), picker=5)
else: # label == 'b'
ann = matplotlib.text.Annotation('red', xy=(x,y), picker=5)
plt.gca().add_artist(ann)
plt.figure()
plt.scatter(data=df, x='a', y='c', c='blue', s='a', alpha=0.5, picker=5, label='a')
plt.scatter(data=df, x='b', y='c', c='red', s='b', alpha=0.5, picker=5, label='b')
plt.gcf().canvas.mpl_connect('pick_event', handlepick)
plt.show()
How can I separate the annotate and dot pick events and tell it not to annotate if the dot already has an annotation? I'm already using the labels to decide which scatter series is picked.
Thanks very much.
Upvotes: 3
Views: 519
Reputation: 339052
You could create an annotation for every scatter point beforehands and set all of those invisible. A click on the scatterpoint would toggle visibility of the respective annotation. A click on the annotation would simply do nothing.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.DataFrame({'a': np.random.rand(25)*1000,
'b': np.random.rand(25)*1000,
'c': np.random.rand(25)})
def handlepick(event):
artist = event.artist
lab = artist.get_label()
if lab in d:
for ind in event.ind:
ann = d[lab][ind]
ann.set_visible(not ann.get_visible() )
plt.gcf().canvas.draw()
plt.figure()
plt.scatter(data=df, x='a', y='c', c='blue', s='a', alpha=0.5, picker=5, label='a')
plt.scatter(data=df, x='b', y='c', c='red', s='b', alpha=0.5, picker=5, label='b')
d = {"a" : [], "b": []}
for i in range(len(df)):
ann = plt.annotate("blue", xy=(df["a"].iloc[i], df["c"].iloc[i]), visible=False)
d["a"].append(ann)
ann = plt.annotate("red", xy=(df["b"].iloc[i], df["c"].iloc[i]), visible=False)
d["b"].append(ann)
plt.gcf().canvas.mpl_connect('pick_event', handlepick)
plt.show()
Upvotes: 2