Python matplotlib pick_事件能否返回数组索引而不是值或像素?

Python matplotlib pick_事件能否返回数组索引而不是值或像素?,python,matplotlib,Python,Matplotlib,我正在尝试为matplotlib中的绘图编写点选择器。我想让它告诉我我点击的绘制数组的I,j索引。似乎唯一的选项是event.mouseevent.xdata,它是以打印的坐标值表示的,或者event.mouseevent.x,它是以像素表示的(从我看到的情况来看,“像素”与网格框(即我正在寻找的)不同) 我是否误解了扩展数据/x是什么。有没有办法做我想做的事 谢谢 尼尔 编辑:单击的图像是二维阵列打印,例如,使用pcolormesh,您可以: 首先,使您的艺术家(以下示例中的阵列)可拾取 单

我正在尝试为matplotlib中的绘图编写点选择器。我想让它告诉我我点击的绘制数组的I,j索引。似乎唯一的选项是event.mouseevent.xdata,它是以打印的坐标值表示的,或者event.mouseevent.x,它是以像素表示的(从我看到的情况来看,“像素”与网格框(即我正在寻找的)不同)

我是否误解了扩展数据/x是什么。有没有办法做我想做的事

谢谢 尼尔

编辑:单击的图像是二维阵列打印,例如,使用pcolormesh,您可以:

  • 首先,使您的艺术家(以下示例中的阵列)可拾取
  • 单击操作时,检查单击是否在艺术家身上
  • 使用
    event.ind[0]
    属性获取索引
进一步的文件。示例如下:

from numpy import linspace
from numpy import cos
from numpy import pi
import matplotlib.pyplot as plt

x = linspace(0,1,100)
y = cos(x*8*pi)   # your array

fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot(x, y, 'b',picker=10)

def onpick(event):

    if event.artist!=line:  #check that you clicked on the object you wanted
        return True     
    if not len(event.ind):  #check the index is valid
        return True
    ind = event.ind[0]

    ax.plot(x[ind],y[ind],'ro')

    fig.canvas.draw() 
    return True

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

编辑:好的。然后,可以首先在栅格点处精确地绘制一条线,然后在上面绘制pcolormesh对象,并隐藏该线。这是密码

x = linspace(0,9,10)+.5
y = linspace(0,9,10)+.5   # your array
x,y=meshgrid(x,y)
x=x.flatten()
y=y.flatten()

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

line, = ax.plot(x, y, 'b',picker=10)
line.set_visible(False)
ax.pcolormesh(np.random.randn(10,10))

def onpick(event):

    if event.artist!=line:  #check that you clicked on the object you wanted
        return True     
    if not len(event.ind):  #check the index is valid
        return True
    ind = event.ind[0]

    ax.plot(x[ind],y[ind],'ro')

    fig.canvas.draw() 
    return True

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

我遇到了一个类似的问题,并成功地解决了。不过,首先,如果您发布一些示例代码,这会很有帮助。这里是我从一个用于更新嵌入式图表的不同示例中重新编译的东西,但无论如何我必须添加一个选择器。我现在遇到的问题是,对于pcolormesh,选择器仅在您单击边界时返回(gg349从技术上解决了这一问题……但很难实现)。如果您运行以下代码并单击绘图按钮并单击单元格边框,您可以看到我如何返回“数据”点(在本例中,仅返回标签索引,但您得到jist:

In [1]
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
#import matplotlib.animation as animation
#from matplotlib import style
import numpy as np

import Tkinter as tk
import ttk

def customplot(f,X):
    try:
        f.clf()
    except:
        None
    try:
        ax=ax
    except:
        ax=f.add_subplot(111)
    ax.pcolormesh(X,picker=True)
    ax.set_yticks(arange(0.5,len(X)+0.5))
    ax.set_xticks(arange(0.5,len(X)+0.5))
    ax.set_yticklabels(["LabY"+str(l) for l in range(len(X))])
    ax.set_xticklabels(["LabX"+str(l) for l in range(len(X))])

class My_GUI:

    def __init__(self,master):
        self.master=master
        self.f = Figure(figsize=(5,5), dpi=100)
        self.canvas1=FigureCanvasTkAgg(self.f,self.master)
        self.updatechartbutton=tk.Button(master=master,text='update plot',command=self.drawcustomplot)
        self.canvas1.get_tk_widget().pack(side="top",fill='x',expand=True)
        self.canvas1.mpl_connect('pick_event',self.onpick)
        self.toolbar=NavigationToolbar2TkAgg(self.canvas1,master)
        self.toolbar.update()
        self.toolbar.pack(side='top',fill='x')           
        self.updatechartbutton.pack(side='top')

    def drawcustomplot(self):
        self.X=array(np.random.normal(size=[3,3]))
        customplot(self.f,self.X)
        #plt.xticks([1,2,3],['one','two','three'])
        self.canvas1.show()

    def onpick(self,event):
        print('Returned indices')
        print(event.ind)
        print('mapping back:')
        self.myxlabels=["LabX"+str(l) for l in range(len(self.X))]
        self.myylabels=["LabY"+str(l) for l in range(len(self.X))]
        self.ypos=event.ind[0] / 3
        self.xpos=event.ind[0] % 3
        print("Y: "+str(self.myylabels[self.ypos])+'  X:'+str(self.myxlabels[self.xpos]))


root=tk.Tk()
gui=My_GUI(root)
root.mainloop()
单击时,您可以看到它返回索引,然后返回我的重新映射点:

Out [1]
Returned indices
[2]
mapping back:
Y: LabY0  X:LabX2
Returned indices
[1]
mapping back:
Y: LabY0  X:LabX1
Returned indices
[7]
mapping back:
Y: LabY2  X:LabX1
Returned indices
[8]
mapping back:
Y: LabY2  X:LabX2
Returned indices
[5 8]
mapping back:
Y: LabY1  X:LabX2
例如,在上一次单击中,我单击了右中和右上之间的边界,返回索引[5 8](第5个框和第8个框首先从左下到右上沿行计数。这里我总是说获取第一个索引(因此,如果单击所需框的顶部,它将返回正确的索引).因此,这里我们正确地返回了第Y1行和第X2列

我知道这可能并不理想,我仍在研究如何使其成为触发事件的框的中心,但至少向您展示了如何从pcolormesh选择器返回的索引中获取一些数据


如果我的示例不清楚,这里是我的“最后一次”单击的可视化显示。数字是从每个框的event.ind返回的索引,5周围的红色圆圈表示我的代码在单击黄色圆圈的位置时查找标签并返回的索引。

抱歉-我的问题框架不够清晰,这是我的错。我想选择一个2D数组。event.ind很有用,但我不确定结果是什么:它返回1到4个数字。我想将它们转换为I和j。上面编辑的问题。谢谢你的全面回答。我给你打了绿色标记,因为它符合我的需要,然而,这对我来说似乎有点不满意。基本上,这涉及到制作一个不可见的新情节作为代理-这对meAlso来说似乎有点尴尬。因此,看到这个问题:@nrob-see了解有关修复需要单击边缘与框中任意位置的问题的更多信息。