unable to point pick 2nd axis after upgrade to mpl 1.0

Hello, list.

I have created a runnable sample app that demonstrates the problem (mentioned also in another thread) in the subject line. The sample is:

  • mpl 1.0 embedded in wxPython using wxAgg backend.

  • using plot() for simplicity, but see same issue if it is plot_date(). (I do date plotting).

  • using twinx to have a 2nd axis (in the problematic case).

  • trying to have point picking on both axes.

You can demonstrate the problem by first running the app and clicking on one red marker and then one blue marker. The message dialog will, each time, indicate the line/pos you picked, and it will work for both the red and blue markers.

But then if you comment out line 52 and comment in line 56, thereby adding a second axis, you will find you can only pick the red markers (which are on the first axis).

This problem did not occur in my previous (0.98.5.2) version of matplotlib.

In addition, in my app, I also have a legend, and–only if I have a 2nd axis–I cannot pick that, either. (I kept it out of this sample to keep things simpler).

Thank you for any help or suggestions to get this to work.

-Che

2nd_axis_picking_problem.py (4.06 KB)

I have created a runnable sample app that demonstrates the problem

Here is a much simpler 10 line sample that doesn’t require wxPython and demonstrates the problem: you can’t pick the red line. This seems like a bug in mpl 1.0.

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()

line, = ax.plot([1,2,3], ‘r-o’, markersize=15, picker=5)
line2, = ax2.plot([4,2,12], ‘b-o’, markersize=15, picker=5)

def onpick(event):
print 'picked line: ', event.artist

fig.canvas.mpl_connect(‘pick_event’, onpick)

plt.show()

2010/12/9 C M <cmpython@...287...>:

I have created a runnable sample app that demonstrates the problem

Here is a much simpler 10 line sample that doesn't require wxPython and
demonstrates the problem: you can't pick the red line. This seems like a
bug in mpl 1.0.

Confirmed using tkagg, mpl 1.0.0 and Ubuntu 10.10. I do not know much
about the semantics of the pick event but it I don't think it should
discriminate between lines in the same canvas si I guess it's a bug.

Goyo

As far as I understand, all the events in matplotlib are associated
with a single Axes instance (or None). For overlapping multiple axes,
the axes with highest zorder is picked up. And a "pick
event only works for artists in the associated axes.
While this simple approach is okay at least to me, I want to hear from
other developers.

For the example above, a workaround is to move the line to the axes of
higher zorder.

line.remove()
ax2.add_line(line)

Regards,

-JJ

···

On Fri, Dec 10, 2010 at 5:01 AM, Goyo <goyodiaz@...287...> wrote:

2010/12/9 C M <cmpython@...287...>:

I have created a runnable sample app that demonstrates the problem

Here is a much simpler 10 line sample that doesn't require wxPython and
demonstrates the problem: you can't pick the red line. This seems like a
bug in mpl 1.0.

Confirmed using tkagg, mpl 1.0.0 and Ubuntu 10.10. I do not know much
about the semantics of the pick event but it I don't think it should
discriminate between lines in the same canvas si I guess it's a bug.

Goyo

------------------------------------------------------------------------------
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

As far as I understand, all the events in matplotlib are associated

with a single Axes instance (or None). For overlapping multiple axes,

the axes with highest zorder is picked up. And a "pick

event only works for artists in the associated axes.

When I was using matplotlib 0.98.5.2, I had the same code as I have now, with two different axes, and pick events were picked up on lines belonging to either of the axes. Unless I’m misunderstanding, something has changed and this used to be possible. Is that correct?

For the example above, a workaround is to move the line to the axes of

higher zorder.

line.remove()

ax2.add_line(line)

Thanks. That works for that example, but in my actual program I want to highlight the picked points with a star. if I reparent the one line to the other axis, the stars will be plotted on the wrong axis, way off the intended marker. This can be seen in the modification of the above code, posted below (click on the middle red marker, then the middle blue one). Is there a further workaround? (Code at bottom).

I also use the identity of the picked line in my code, since I provide additional information about that data series to the user based on which line (and point) they picked. So if reparenting the line loses that information, that’s going to be a problem.

thanks,
-Che

···

On Thu, Dec 9, 2010 at 8:45 PM, Jae-Joon Lee <lee.j.joon@…287…> wrote:


import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()

line, = ax.plot([1,2,5], ‘r-o’, markersize=15, picker=5)
line2, = ax2.plot([4,5,12], ‘b-o’, markersize=15, picker=5)

line.remove()
ax2.add_line(line)

def onpick(event):
thisline = event.artist
print 'picked line: ', event.artist
ind = event.ind
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()

star, = ax.plot([xdata[ind]], [ydata[ind]], '*', ms=40, mfc='y', mec='b')            
fig.canvas.draw()

fig.canvas.mpl_connect(‘pick_event’, onpick)

plt.show()

When I was using matplotlib 0.98.5.2, I had the same code as I have now,
with two different axes, and pick events were picked up on lines belonging
to either of the axes. Unless I'm misunderstanding, something has changed
and this used to be possible. Is that correct?

Yes, I believe this used to be possible. While I'm not sure why it
changed, I'm also not sure if we need to revert this change as I
personally prefer the current simple behavior (although there could be
a room for improvement). And I want to hear what others think. You may
file a new feature request (or a bug if you want) issue regarding
this.

For the example above, a workaround is to move the line to the axes of
higher zorder.

line.remove()
ax2.add_line(line)

Thanks. That works for that example, but in my actual program I want to
highlight the picked points with a star. if I reparent the one line to the
other axis, the stars will be plotted on the wrong axis, way off the
intended marker. This can be seen in the modification of the above code,
posted below (click on the middle red marker, then the middle blue one). Is
there a further workaround? (Code at bottom).

It will work if you explicitly set its transform.

    star, = ax.plot([xdata[ind]], [ydata[ind]], '*',
                    ms=40, mfc='y', mec='b',
transform=thisline.get_transform())

I also use the identity of the picked line in my code, since I provide
additional information about that data series to the user based on which
line (and point) they picked. So if reparenting the line loses that
information, that's going to be a problem.

I believe that reparenting only changes the "axes" attribute of the
line, so it might not be a problem.

Given the current implementation of the pick event handler, I think it
might be better for you to implement a custom handler although this
may takes you more time.

However, I must admit that I rarely use events with matplotlib. I'm
only addressing this since there were no response from other
developers. And they may have different opinions than me.

Regards,

-JJ

···

thanks,
-Che

---
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()

line, = ax.plot([1,2,5], 'r-o', markersize=15, picker=5)
line2, = ax2.plot([4,5,12], 'b-o', markersize=15, picker=5)

line.remove()
ax2.add_line(line)

def onpick(event):
thisline = event.artist
print 'picked line: ', event.artist
ind = event.ind
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()

star, = ax\.plot\(\[xdata\[ind\]\], \[ydata\[ind\]\], &#39;\*&#39;, ms=40, mfc=&#39;y&#39;,

mec='b')
fig.canvas.draw()

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

It will work if you explicitly set its transform.

star, = ax.plot([xdata[ind]], [ydata[ind]], '*',

ms=40, mfc=‘y’, mec=‘b’,

transform=thisline.get_transform())

JJ, thank you, this worked in my app as well.

I also use the identity of the picked line in my code, since I provide

additional information about that data series to the user based on which

line (and point) they picked. So if reparenting the line loses that

information, that’s going to be a problem.

I believe that reparenting only changes the “axes” attribute of the

line, so it might not be a problem.

Yes, it turns out it doesn’t seem to cause any problem, which is great.

When I was using matplotlib 0.98.5.2, I had the same code as I have now,

with two different axes, and pick events were picked up on lines belonging

to either of the axes. Unless I’m misunderstanding, something has changed

and this used to be possible. Is that correct?

Yes, I believe this used to be possible. While I’m not sure why it

changed, I’m also not sure if we need to revert this change as I

personally prefer the current simple behavior (although there could be

a room for improvement). And I want to hear what others think. You may

file a new feature request (or a bug if you want) issue regarding

this.

I don’t know if the other developers have weighed in on this in some other forum or in personal communication, but as a user my vote is to keep the old behavior. I don’t know how much of a simplicity benefit the developer team gets, but as a user I doubt I would have been able to figure out your suggestions based on Matplotlib documentation alone, unless maybe I am missing something. The previous way it worked strikes me as the user-intuitive way; this new way requires you to move a line to an axis that it doesn’t match but then use its transform to “decode” what it really should be (if I understand it about right). And then one has to do that for every line. That seems complex from the user’s perspective. Now that it is all in place it is no problem, but getting here was tough and un-doable without help. I guess I will file a feature request or bug report about it.

So thank you very much, JJ, for all your help on at least three key details that massively improve the user experience of the app I am trying to put together.

And thanks to John and the rest of the developers for Matplotlib!

Che