mpldatacursor 对于我想要的来说太复杂了,即以某种方式在回调函数中接收 x,y,z 坐标。我从 mpldatacursor pick_info.py 中提取了一个辅助函数 (get_xyz_mouse_click),该函数完成了获取坐标所需的最低限度(即,没有悬停窗口,没有复杂的事件处理)。这是辅助函数:
import numpy as np
import matplotlib.transforms as mtransforms
from mpl_toolkits import mplot3d
def get_xyz_mouse_click(event, ax):
"""
Get coordinates clicked by user
"""
if ax.M is None:
return {}
xd, yd = event.xdata, event.ydata
p = (xd, yd)
edges = ax.tunit_edges()
ldists = [(mplot3d.proj3d.line2d_seg_dist(p0, p1, p), i) for \
i, (p0, p1) in enumerate(edges)]
ldists.sort()
# nearest edge
edgei = ldists[0][1]
p0, p1 = edges[edgei]
# scale the z value to match
x0, y0, z0 = p0
x1, y1, z1 = p1
d0 = np.hypot(x0-xd, y0-yd)
d1 = np.hypot(x1-xd, y1-yd)
dt = d0+d1
z = d1/dt * z0 + d0/dt * z1
x, y, z = mplot3d.proj3d.inv_transform(xd, yd, z, ax.M)
return x, y, z
这是在 3D 散点图中使用它的示例:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import simple_pick_info.pick_info
# Fixing random state for reproducibility
np.random.seed(19680801)
def randrange(n, vmin, vmax):
'''
Helper function to make an array of random numbers having shape (n, )
with each number distributed Uniform(vmin, vmax).
'''
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
# For each set of style and range settings, plot n random points in the box
# defined by x in [23, 32], y in [0, 100], z in [zlow, zhigh].
for c, m, zlow, zhigh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
def on_press(event):
x,y,z = simple_pick_info.pick_info.get_xyz_mouse_click(event, ax)
print(f'Clicked at: x={x}, y={y}, z={z}')
cid = fig.canvas.mpl_connect('button_press_event', on_press)
您应该编辑 on_press() 以对 x,y,z 执行某些操作。它仍然存在使用轴网格生成点引用的另一个答案的问题(即,它不搜索原始数据以寻找最近的邻居)。我建议对原始数据模型(点、线等)进行距离变换,因为搜索表面中的补丁会变得非常复杂。
我真的希望它以 Matlab 的 datacursormode 的工作方式内置到 matplotlib 中!