选择事件演示#
你可以通过设置艺术家的 “picker” 属性来启用选择功能(例如 Matplotlib 中的 Line2D、Text、Patch、Polygon、AxesImage 等)。
picker 属性有多种含义:
None
- 对于此艺术家禁用选择(默认)bool
- 如果为True
,则启用选择功能,当鼠标事件在艺术家上时,艺术家将触发 pick 事件。 设置pickradius
将在点中添加epsilon
容差,如果其数据在鼠标事件的epsilon
范围内,则艺术家将触发事件。对于某些艺术家如线条和补丁集合,艺术家可能会为生成的 pick 事件提供额外的数据,例如在 pick 事件的epsilon
范围内的数据的索引。function
- 如果 picker 是可调用的,它是用户提供的函数,用于确定鼠标事件是否命中艺术家。hit, props = picker(artist, mouseevent)
来确定命中测试。如果鼠标事件在艺术家上,返回
hit=True
并且props
是要添加到PickEvent
属性的字典。
在通过设置 "picker"
属性启用艺术家的选择后,你需要连接到 figure canvas 的 pick_event,以在鼠标按下事件上获得 pick 回调。例如,::
python def pick_handler(event): mouseevent = event.mouseevent artist = event.artist # 现在用这个做一些事情...
传递给你的回调的 pick 事件(matplotlib.backend_bases.PickEvent
)总是带有两个属性:
mouseevent
生成 pick 事件的鼠标事件。鼠标事件又具有诸如
x
和y
(显示空间中的坐标,例如从左下角的像素)以及xdata
,ydata
(数据空间中的坐标)等属性。此外,你可以获取有关哪个按钮被按下、哪些键被按下、鼠标在哪个轴上等信息。请参阅matplotlib.backend_bases.MouseEvent
获取详细信息。artist
生成 pick 事件的matplotlib.artist
。
另外,像 Line2D 和 PatchCollection 这样的特定艺术家可能会附加额外的元数据,如满足选择标准的数据的索引(例如,在指定的 epsilon 容差范围内的所有点)。
以下示例说明了这些方法。
# %matplotlib tk
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand
from matplotlib.image import AxesImage
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
from matplotlib.text import Text
# Fixing random state for reproducibility
np.random.seed(19680801)
简单的选择:线条、矩形和文本#
fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.set_title('click on points, rectangles or text', picker=True)
ax1.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red'))
line, = ax1.plot(rand(100), 'o', picker=True, pickradius=5)
# Pick the rectangle.
ax2.bar(range(10), rand(10), picker=True)
for label in ax2.get_xticklabels(): # Make the xtick labels pickable.
label.set_picker(True)
def onpick1(event):
if isinstance(event.artist, Line2D):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print('onpick1 line:', np.column_stack([xdata[ind], ydata[ind]]))
elif isinstance(event.artist, Rectangle):
patch = event.artist
print('onpick1 patch:', patch.get_path())
elif isinstance(event.artist, Text):
text = event.artist
print('onpick1 text:', text.get_text())
fig.canvas.mpl_connect('pick_event', onpick1)
14
onpick1 line: [[37. 0.48320961]]
onpick1 line: [[35. 0.78306588]]
onpick1 patch: Path(array([[0., 0.],
[1., 0.],
[1., 1.],
[0., 1.],
[0., 0.]]), array([ 1, 2, 2, 2, 79], dtype=uint8))
onpick1 patch: Path(array([[0., 0.],
[1., 0.],
[1., 1.],
[0., 1.],
[0., 0.]]), array([ 1, 2, 2, 2, 79], dtype=uint8))
onpick1 patch: Path(array([[0., 0.],
[1., 0.],
[1., 1.],
[0., 1.],
[0., 0.]]), array([ 1, 2, 2, 2, 79], dtype=uint8))
onpick1 line: [[82. 0.2268104]]
onpick1 line: [[82. 0.2268104]]
onpick1 line: [[82. 0.2268104]]
onpick1 line: [[82. 0.2268104]]
onpick1 patch: Path(array([[0., 0.],
[1., 0.],
[1., 1.],
[0., 1.],
[0., 0.]]), array([ 1, 2, 2, 2, 79], dtype=uint8))
使用自定义命中测试函数的选择#
你可以通过将 picker
设置为可调用的函数来定义自定义选择器。该函数具有以下签名:
hit, props = func(artist, mouseevent)
来确定命中测试。如果鼠标事件在艺术家上,返回 hit=True
并且 props
是你想添加到 .PickEvent
属性的属性字典。
def line_picker(line, mouseevent):
"""
Find the points within a certain distance from the mouseclick in
data coords and attach some extra attributes, pickx and picky
which are the data points that were picked.
"""
if mouseevent.xdata is None:
return False, dict()
xdata = line.get_xdata()
ydata = line.get_ydata()
maxd = 0.05
d = np.sqrt(
(xdata - mouseevent.xdata)**2 + (ydata - mouseevent.ydata)**2)
ind, = np.nonzero(d <= maxd)
if len(ind):
pickx = xdata[ind]
picky = ydata[ind]
props = dict(ind=ind, pickx=pickx, picky=picky)
return True, props
else:
return False, dict()
def onpick2(event):
print('onpick2 line:', event.pickx, event.picky)
fig, ax = plt.subplots()
ax.set_title('custom picker for line data')
line, = ax.plot(rand(100), rand(100), 'o', picker=line_picker)
fig.canvas.mpl_connect('pick_event', onpick2)
14
onpick2 line: [0.11632148] [0.68948604]
onpick2 line: [0.06097709 0.05552486] [0.79304089 0.84058217]
onpick2 line: [0.53413535] [0.45664264]
onpick2 line: [0.51195743 0.53413535] [0.50131575 0.45664264]
onpick2 line: [0.51195743 0.53413535] [0.50131575 0.45664264]
onpick2 line: [0.5838648] [0.53457107]
onpick2 line: [0.70743918] [0.55113251]
onpick2 line: [0.15024598 0.19481606 0.22140904 0.20272247] [0.28792293 0.26229789 0.24974709 0.2895639 ]
在散点图上的选择#
散点图由 PathCollection
支持。
x, y, c, s = rand(4, 100)
def onpick3(event):
ind = event.ind
print('onpick3 scatter:', ind, x[ind], y[ind])
fig, ax = plt.subplots()
ax.scatter(x, y, 100*s, c, picker=True)
fig.canvas.mpl_connect('pick_event', onpick3)
14
onpick3 scatter: [70 97] [0.24263777 0.23168902] [0.70451921 0.68434196]
选择图像#
使用 .Axes.imshow
绘制的图像是 AxesImage
对象。
fig, ax = plt.subplots()
ax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True)
ax.imshow(rand(5, 10), extent=(3, 4, 1, 2), picker=True)
ax.imshow(rand(20, 25), extent=(1, 2, 3, 4), picker=True)
ax.imshow(rand(30, 12), extent=(3, 4, 3, 4), picker=True)
ax.set(xlim=(0, 5), ylim=(0, 5))
def onpick4(event):
artist = event.artist
if isinstance(artist, AxesImage):
im = artist
A = im.get_array()
print('onpick4 image', A.shape)
fig.canvas.mpl_connect('pick_event', onpick4)
plt.show()
onpick4 image (10, 5)
onpick4 image (20, 25)
onpick4 image (30, 12)
onpick4 image (5, 10)
选择事件演示 2#
计算 100 个数据集的均值(mu)和标准差(sigma),绘制 mu 与 sigma。当你点击其中一个 (mu, sigma) 点时,绘制生成该点的数据集的原始数据。
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)
fig, ax = plt.subplots()
ax.set_title('click on point to plot time series')
line, = ax.plot(xs, ys, 'o', picker=True, pickradius=5)
def onpick(event):
if event.artist != line:
return
N = len(event.ind)
if not N:
return
figi, axs = plt.subplots(N, squeeze=False)
for ax, dataind in zip(axs.flat, event.ind):
ax.plot(X[dataind])
ax.text(.05, .9, f'mu={xs[dataind]:1.3f}\nsigma={ys[dataind]:1.3f}',
transform=ax.transAxes, va='top')
ax.set_ylim(-0.5, 1.5)
figi.show()
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()