The index returned in the pick_event (event.ind) does not correspond to the index of the source data.
It also changes depending on the view onto the data.
The example contains two points.
When you click on a point, the event.ind is printed out.
The one at (0,0,0) should have index 0, the other index 1.
Rotate the plot so that the second point is further behind (semi transparent). Now it has index 0.
Rotate the plot so that the second point is further in front (full opacity). Now it has index 1.
The example contains two points.
When you click on a point, the event.ind is printed out.
The one at (0,0,0) should have index 0, the other index 1.
Rotate the plot so that the second point is further behind (semi transparent). Now it has index 0.
Rotate the plot so that the second point is further in front (full opacity). Now it has index 1.
Expected outcome
The returned event.ind should not depend on view.
For the point in the centre it should always return 0, for the point to the right, it should always return 1.
Matplotlib version
Operating system: macOS Catalina; 10.15.4
Matplotlib version (import matplotlib; print(matplotlib.__version__)): '3.3.4'
Anyone got a clue where the code is that populates the event.ind? I took linear algebra and I write python code all the time, but finding my way around this project, where should I start?
Activity
snaxxus commented on Mar 31, 2021
The axes reverse directions on the selection depending on which points are in front when you rotate the graph. Using matplotlib 3.4.1
#!/usr/bin/env python3 from mpl_toolkits.mplot3d import proj3d import matplotlib.pyplot as plt import matplotlib print('matplotlib: {}'.format(matplotlib.__version__)) fig = plt.figure() ax = fig.add_subplot(111, projection = '3d') x = [0, 2, 0,0] y = [0, 2, 0,2] z = [0, 2, 2,0] scatter = ax.scatter(x,y,z,picker=True) def chaos_onclick(event): point_index = int(event.ind) print(point_index) print("X=",x[point_index], " Y=",y[point_index], " Z=",z[point_index], " PointIdx=", point_index) fig.canvas.mpl_connect('pick_event', chaos_onclick) plt.show()snaxxus commented on Apr 1, 2021
Anyone got a clue where the code is that populates the event.ind? I took linear algebra and I write python code all the time, but finding my way around this project, where should I start?
QuLogic commented on Apr 2, 2021
That's determined in Collection.contains; it's likely that there needs to be an override in Path3DCollection to undo the effect of depth sorting.
snaxxus commented on Apr 2, 2021
I'll take a look. meanwhile this is a work around.
#!/usr/bin/env python3 # much from https://stackoverflow.com/questions/58218482/annotate-3d-scatter-plot-on-pick-event/66926265#66926265 from mpl_toolkits.mplot3d import proj3d import matplotlib.pyplot as plt import numpy as np import matplotlib print('matplotlib: {}'.format(matplotlib.__version__)) fig = plt.figure() ax = fig.add_subplot(111, projection = '3d') x = [0, 2, 0,0] y = [0, 2, 0,2] z = [0, 2, 2,0] scatter = ax.scatter(x,y,z,picker=True) ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') def onMouseMotion(event): print(event) def chaos_onclick(event): print(dir(event.mouseevent)) xx=event.mouseevent.x yy=event.mouseevent.y #magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot x2, y2, z2=proj3d.proj_transform(x[0], y[0], z[0], plt.gca().get_proj()) x3, y3 = ax.transData.transform((x2, y2)) #the distance d=np.sqrt ((x3 - xx)**2 + (y3 - yy)**2) print ("distance=",d) #find the closest by searching for min distance. #All glory to https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot imin=0 dmin=10000000 for i in range(len(x)): #magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot x2, y2, z2=proj3d.proj_transform(x[i], y[i], z[i], plt.gca().get_proj()) x3, y3 = ax.transData.transform((x2, y2)) #the distance magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot d=np.sqrt ((x3 - xx)**2 + (y3 - yy)**2) #We find the distance and also the index for the closest datapoint if d< dmin: dmin=d imin=i #print ("i=",i," d=",d, " imin=",imin, " dmin=",dmin) # gives the incorrect data point index point_index = int(event.ind) print("Xfixed=",x[imin], " Yfixed=",y[imin], " Zfixed=",z[imin], " PointIdxFixed=", imin) print("Xbroke=",x[point_index], " Ybroke=",y[point_index], " Zbroke=",z[point_index], " PointIdx=", point_index) fig.canvas.mpl_connect('pick_event', chaos_onclick) #fig.canvas.mpl_connect('motion_notify_event', onMouseMotion) # on mouse motion plt.show()tacaswell commented on Apr 2, 2021
On the bright side, via #19812 we now carry the z-sorting on the artist so we know enough to do the inversion.