Reputation: 44902
In R, there is a function locator
which is like Matlab's ginput
where you can click on the figure with a mouse and select any x,y coordinate. In addition, there is a function called identify(x,y)
where if you give it a set of points x,y that you have plotted and then click on the figure, it will return the index of the x,y point which lies nearest (within an adjustable tolerance) to the location you have selected (or multiple indices, if multiple points are selected). Is there such a functionality in Matplotlib?
Upvotes: 24
Views: 50327
Reputation: 1
The ginput()
is a handy tool to select x, y coordinates of any random point from a plotted window, however that point may not belong to the plotted data. To select x, y coordinates of a point from the plotted data, an efficient tool still is to use 'pick_event'
property with mpl_connect
as the example given in the documentation. For example:
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand
fig, ax = plt.subplots()
ax.plot(rand(100), rand(100), picker=3)
# 3, for example, is tolerance for picker i.e, how far a mouse click from
# the plotted point can be registered to select nearby data point/points.
def on_pick(event):
global points
line = event.artist
xdata, ydata = line.get_data()
print('selected point is:',np.array([xdata[ind], ydata[ind]]).T)
cid = fig.canvas.mpl_connect('pick_event', on_pick)
The last line above will connect the plot with the 'pick_event'
and the corrdinates of the nearest plot points will keep printing after each mouse click on plot, to end this process, we need to use mpl_disconnect
as:
fig.canvas.mpl_disconnect(cid)
Upvotes: 0
Reputation: 17607
Wow many years have passed! Now matplotlib
also support the ginput
function which has almost the same API as Matlab. So there is no need to hack by the mpl-connect and so on any more! (https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.ginput.html) For instance,
plt.ginput(4)
will let the user to select 4 points.
Upvotes: 8
Reputation: 1621
from __future__ import print_function
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
from matplotlib.text import Text
from matplotlib.image import AxesImage
import numpy as np
from numpy.random import rand
if 1:
fig, ax = plt.subplots()
ax.set_title('click on points', picker=True)
ax.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red'))
line, = ax.plot(rand(100), 'o', picker=5)
def onpick1(event):
if isinstance(event.artist, Line2D):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print 'X='+str(np.take(xdata, ind)[0]) # Print X point
print 'Y='+str(np.take(ydata, ind)[0]) # Print Y point
fig.canvas.mpl_connect('pick_event', onpick1)
Upvotes: 9
Reputation: 10139
You may want to use a pick event :
fig = figure()
ax1 = fig.add_subplot(111)
ax1.set_title('custom picker for line data')
line, = ax1.plot(rand(100), rand(100), 'o', picker=line_picker)
fig.canvas.mpl_connect('pick_event', onpick2)
Tolerance set by picker parameter there:
line, = ax1.plot(rand(100), 'o', picker=5) # 5 points tolerance
Upvotes: 18