Getting location of mouse click in Matplotlib using Tkinter

I am trying to write a simple GUI in python that displays a graph and then allows the user to click on certain key characteristics (turning points, etc.), which will then be used as a starting point for a suitable algorithm I'm developing.

I found the following thread to get me started; Save coordinates of mouse clicks with matplotlib

This seems to only give me the pixelated mouse locations from my computer perspective. I wish I could get the coordinates on the right side of the toolbar and use them; it seems a shame to try to write your own pixel-> data conversion when matplotlib is clearly already doing it for me somewhere.

Here is the code I have so far, if it looks like I am approaching the problem the wrong way please tell me, I am not too proud to start over.

import matplotlib
matplotlib.use('TkAgg')

import Tkinter as tk

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.backend_bases import MouseEvent
from matplotlib.figure import Figure

import numpy as np


def callback(event):
    print "clicked at", event.x, event.y

root = tk.Tk()

f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = np.arange(0.0,3.0,0.01)
s = np.sin(2*np.pi*t)

a.plot(t,s)

canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

canvas.mpl_connect('button_press_event',callback)
def callback(event):
    print "clicked at", event.xdata, event.ydata

toolbar = NavigationToolbar2TkAgg( canvas, root )
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

toolbar

root.mainloop()

      

+3


source to share


1 answer


Edit: I jumped in answering without reading your example in full. The problems you face are due to the fact that you have identified things. Basically you have:

import matplotlib.pyplot as plt

def callback(event):
    print event.x, event.y

fig, ax = plt.subplots()

fig.canvas.callbacks.connect('button_press_event', callback)
def callback(event):
    print event.xdata, event.ydata

      

When you connect the callback, the second function is not yet defined, so it connects to an earlier function of the same name. Either move the callback connection after the function is defined, or just move the function definition up and remove the (unused) first callback function.

Regardless, look at the matplotlib transforms to understand how you were converting between display / pixel coordinates and plot coordinates. I will leave my original answer in the hope that it will help someone else who comes across this question.


If I understand you correctly, do you need the coordinates of the data where the mouse click was made?

If so, use event.xdata

and event.ydata

.



As a quick example:

import matplotlib.pyplot as plt

def on_click(event):
    if event.inaxes is not None:
        print event.xdata, event.ydata
    else:
        print 'Clicked ouside axes bounds but inside plot window'

fig, ax = plt.subplots()
fig.canvas.callbacks.connect('button_press_event', on_click)
plt.show()

      

In general, take a look at matplotlib conversions to convert between display, figure, axes and data coordinates.

For example, the equivalent of event.xdata

, and event.ydata

will be:

x, y = event.inaxes.transData.inverted().transform((event.x, event.y))

      

It's a little verbose, but ax.transData

is a conversion between display (pixel) coordinates and data coordinates. We want to go the other way, so we invert the transformation with trans.inverted()

. Transform

do not only deal with points (usually you use them to plot something in a different coordinate system), so to transform a set of points we need to call the Transform

.

It sounds cumbersome at first, but it's actually quite sleek. All graphic artists take an argument transfom

that specifies the coordinate system they are drawn into. This is how things like annotate

, let you determine a location defined by offsets at points from elsewhere in the data coordinates.

+4


source







All Articles