Use matplotlib pick event to trigger when center of pcolormesh squares are clicked?

你说的曾经没有我的故事 提交于 2020-01-03 04:32:11

问题


I am working on a broader project, but am running into an issue using matplotlibs picker=True and pick_event with a pcolormesh. It works, but is not intuitive as the pick event is only triggered when i click along the edges of the heatmap 'boxes', and it returns the surrounding indices (so if you click a corner 4 indices are returned by the intersection of the 4 boxes at that point).

For example, in the following picture when I click near the yellow circle my picker returns indices [5 8] (5 is the box below and 8 above). Instead, I'd like to return only index 5 when that 'box' is clicked.

Here is the code I used to exemplify my issue:

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.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.drawcustomplot()

    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()

this is further to the question found here: Can matplotlib pick_event return array indeces rather than values or pixels?. I'd like to avoid trying to draw an underlying scatterplot that is masked by the pcolormesh, but handles the picker events if possible as I feel there must be a simpler way to achieve the desired result.


回答1:


I would suggest to use a button_press_event here. From that you can easily obtain the coordinates of the clicked pixel. In the case of an imshow plot it's even easier,

x = int(np.round(event.xdata))
y = int(np.round(event.ydata))

Complete example (using imshow):

import numpy as np
import matplotlib.pyplot as plt

X=np.array(np.random.normal(size=[3,3]))

myxlabels=["LabX"+str(l) for l in range(len(X[0,:]))]
myylabels=["LabY"+str(l) for l in range(len(X))]
plt.imshow(X)
plt.xticks(range(len(X[0,:])),myxlabels )
plt.yticks(range(len(X)),myylabels )

def onclick(event):
    print('Returned indices')
    print(event.xdata, event.ydata)
    print('mapping back:')
    x = int(np.round(event.xdata))
    y = int(np.round(event.ydata))
    tx = "Y: {}, X: {}, Value: {:.2f}".format(myylabels[y], myxlabels[x], X[y,x])
    print(tx)

plt.gcf().canvas.mpl_connect('button_press_event', onclick)

plt.show()


来源:https://stackoverflow.com/questions/43979953/use-matplotlib-pick-event-to-trigger-when-center-of-pcolormesh-squares-are-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!