0

I plotted a graph with matplotlib, and I want to interact with it when I clicked some of the points. I have many points overlapping on each other.

def foo():
    plist = list()
    data = data_generator()
    for ind in range(0, len(data)):
        x_plot, y_plot = generator()
        paths = ax.plot(x_plot, y_plot, alpha=alpha)
        plist.append(paths[0])

class AbstractPlotPage(tk.Frame):
    def __init__():
        self.paths = foo()
        self.canvas = FigureCanvasTkAgg(f, self)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.canvas.show()
    def on_pick():
        print('test')

The thing is, I noticed matplotlib does not run the on_pick once for all the overlapped points. But it runs once for a single points then run it again.

So is there a way to check when the event queue is done? Or how can I watch this event queue?

J.R.
  • 769
  • 2
  • 10
  • 25
  • It should run the callback exactly once per click. If you experience something different, please show a [mcve]. – ImportanceOfBeingErnest May 03 '19 at 12:55
  • @ImportanceOfBeingErnest Hi, I will update the question, it's will be a pain if I upload all the codes cause it's over thoussands line so I can only copy part of them. – J.R. May 03 '19 at 13:01
  • 1
    Yes, creating a [mcve] isn't easy. But without reproducible code one can rarely find a solution. So you might find it worthwhile taking the time to reduce your problem to some 30 lines maximum. – ImportanceOfBeingErnest May 03 '19 at 13:07
  • @ImportanceOfBeingErnest thank you. I updated the question, hope there's enought information. – J.R. May 03 '19 at 13:10
  • Not for me. Maybe someone else has the energy to construct some runnable code from the snippet. – ImportanceOfBeingErnest May 03 '19 at 13:13
  • @ImportanceOfBeingErnest Thank you anyway. At least I know there's something weird running cause the callback should only run once. – J.R. May 03 '19 at 13:37
  • 1
    Almost the same question got asked [here](https://stackoverflow.com/questions/56015753/picking-a-single-artist-from-a-set-of-overlapping-artists-in-matplotlib), but in a more understandable way such that it got two answers. – ImportanceOfBeingErnest May 07 '19 at 15:23
  • @ImportanceOfBeingErnest Thnx, that's very informative! – J.R. May 08 '19 at 07:55

1 Answers1

0

Just if anyone is interested, I found some explaination but not a real solution. The following is the code from artist, everytime when the self.figure.canvas.pick_event is called, the event will run the callback. Basically this recursion iterates over all the elements on a figure, so it's actually true that if you selected multiple points, the callback will be run multiple times.

How to handle it? I guess you should re-write some code from the matplotlib. I think my version is bit too old, it's 1. something. Maybe the newer version already did some change.

def pick(self, mouseevent):
    """
    call signature::

      pick(mouseevent)

    each child artist will fire a pick event if *mouseevent* is over
    the artist and the artist has picker set
    """
    # Pick self
    if self.pickable():
        picker = self.get_picker()
        if six.callable(picker):
            inside, prop = picker(self, mouseevent)
        else:
            inside, prop = self.contains(mouseevent)
        if inside:
            self.figure.canvas.pick_event(mouseevent, self, **prop)

    # Pick children
    for a in self.get_children():
        # make sure the event happened in the same axes
        ax = getattr(a, 'axes', None)
        if mouseevent.inaxes is None or ax is None or \
                mouseevent.inaxes == ax:
            # we need to check if mouseevent.inaxes is None
            # because some objects associated with an axes (e.g., a
            # tick label) can be outside the bounding box of the
            # axes and inaxes will be None
            # also check that ax is None so that it traverse objects
            # which do no have an axes property but children might
            a.pick(mouseevent)
J.R.
  • 769
  • 2
  • 10
  • 25