joferkington / mpldatacursor

Interactive "data cursors" (a.k.a. annotation pop-ups) for matplotlib
MIT License
194 stars 47 forks source link

Feature request: enforce one annotation per click #52

Closed Joe-Chapman closed 8 years ago

Joe-Chapman commented 8 years ago

Hi Joe,

When plotting/viewing really dense data and making a cursor in the 'multiple' display mode, I'll sometimes end up in a situation where a single click generates many annotations. Could you add the feature that sets a one annotation per click policy? Annotating the closest object to the click would be a bonus, but not necessary for my needs.

joferkington commented 8 years ago

Out of curiosity, which backend are you using?

There's already code in-place to prevent this, but it relies on single-shot timers, which don't work properly on all backends. I've been meaning to round up a list of every backend + OS where single-shot timers aren't working and send PR's upstream.

At any rate, I'm beginning to think I should re-architect things and avoid pick events entirely. The big advantage is that it would avoid a reliance on timers altogether.

Joe-Chapman commented 8 years ago

I’m using Qt4Agg, (packaged with an “Anaconda2” distribution for Python 2.7/Windows 8.1 64-bit).

Thanks, Joe

From: Joe Kington [mailto:notifications@github.com] Sent: Saturday, February 20, 2016 10:24 PM To: joferkington/mpldatacursor mpldatacursor@noreply.github.com Cc: Chapman, Joe jchapman@mitre.org Subject: Re: [mpldatacursor] Feature request: enforce one annotation per click (#52)

Out of curiosity, which backend are you using?

There's already code in-place to prevent this, but it relies on single-shot timers, which don't work properly on all backends. I've been meaning to round up a list of every backend + OS where single-shot timers aren't working and send PR's upstream.

At any rate, I'm beginning to think I should re-architect things and avoid pick events entirely. The big advantage is that it would avoid a reliance on timers altogether.

— Reply to this email directly or view it on GitHubhttps://github.com/joferkington/mpldatacursor/issues/52#issuecomment-186730008.

anntzer commented 8 years ago

I think this happens in DataCursor._select, namely:

        for artist in self.artists:
            fixed_event = event_axes_data(event, artist.axes)
            inside, info = contains(artist, fixed_event)
            if inside:
                fig = artist.figure
                new_event = PickEvent('pick_event', fig.canvas, fixed_event,
                                     artist, **info)
                self(new_event)

Enforcing a single annotation per click can be trivially enforced by adding break at the end of the if clause. Getting the closest line is a bit harder, you basically need to propagate the info back to that point for sorting purposes.

joferkington commented 8 years ago

Fixed as @anntzer suggested. I'm going to leave the "closest artist" part out for the moment, as it adds a fair amount of complexity for relatively little gain.