Multiple selection events interfering

I have several rows of data scattered across a shape and want them to be able to toggle annotations for them. The problem is that sometimes two selection events are fired (when the user clicks on a point that is in both the annotation and the point). The "annotation" select event clears the annotation, but the point select event brings it back, so the toggle effect does not 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 decouple the annotation and point selection events and tell it not to comment if the point already has an annotation? I already use labels to decide which scatter series are selected.

Many thanks.

+3


source to share


1 answer


You can create annotation for each scatter point before starting and set all invisible. Clicking on a scatter point will toggle the visibility of the corresponding annotation. Clicking on annotations just didn't do anything.



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()

      

+2


source







All Articles