首页 > 解决方案 > Matplotlib scatter 3D button_press_event 根据子图上的散点轴位置给出错误的索引

问题描述

我在 3D 散点图上显示了一些点,我想突出显示单击的点。但是 ind["ind"][0] 根据图表上 x 轴(顶部或底部)或 y 轴(左侧或右侧)的位置给出了所选点的错误索引。因此,突出显示的不是我点击的那个。

问候,

马特

import matplotlib.pyplot as plt
import numpy as np

Lx = 0.8
Ly = 0.5
n = 10
Nx = 8
Ny = 5
x = np.linspace(0, Lx, Nx)
y = np.linspace(0, Ly, Ny)

X, Y = np.meshgrid(x, y)

#visualisaiton 3D
fig = plt.figure('Visualisation 3D')
ax2 = plt.subplot(1, 1, 1, projection='3d')

ac_x, ac_y = 1, 1

sc = ax2.scatter(X.ravel(), Y.ravel(), np.zeros(Nx * Ny), picker=True)
ac = ax2.scatter(x[ac_x], y[ac_y], 0, 'r', s=50)

def click(event, ind):
    i = ind["ind"][0]
    xx, yy, zz = sc._offsets3d

    def find_nearest(array, value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return idx

    ac_x = np.where(x == xx[i])[0]
    ac_y = np.where(y == yy[i])[0]

    print('xx[i], yy[i]: (%.2f, %.2f)' % (xx[i], yy[i]))

    print('Click at: (%.2f, %.2f)' % (xx[i], yy[i]))
    print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
          ('double' if event.dblclick else 'single', event.button,
           event.x, event.y, event.xdata, event.ydata))

    ac_act = ax2.scatter(x[ac_x], y[ac_y], 0, 'r', s=50)

    print('index (%d, %d) position: (%.2f, %.2f)' % (ac_x, ac_y, x[ac_x], y[ac_y]))

def on_click(event):
    if event.inaxes == ax2:
        cont2, ind2 = sc.contains(event)
        if cont2:
            click(event, ind2)
            fig.canvas.draw_idle()

fig.canvas.mpl_connect('button_press_event', on_click)


plt.show()

工作示例:

在此处输入图像描述

不工作:

在此处输入图像描述

标签: pythonmatplotlibscatter

解决方案


从 Path3DCollection 获取正确索引时,我也遇到了一些麻烦。在进行了一些挖掘之后,我发现数据数组是基于 z 坐标的。要获取原始索引,您需要访问成员 _z_markers_idx,不幸的是,该成员受保护。

在文件中:

mpl_toolkits\mplot3d\art3d.py

我在 Path3DCollection 类中添加了以下 getter:

def get_z_markers_idx(self):
    return self._z_markers_idx

然后,您将能够通过以下方式获取正确的索引:

def click(event, ind):
    i = sc.get_z_markers_idx()[ind["ind"][0]]

推荐阅读