Late Edit / Shameless Plug: 现在可以(功能更强)作为mpldatacursor。
就我所知,没有一个国家已经执行,但写类似的东西并不难:
import matplotlib.pyplot as plt
class DataCursor(object):
text_template = x: %0.2f
y: %0.2f
x, y = 0.0, 0.0
xoffset, yoffset = -20, 20
text_template = x: %0.2f
y: %0.2f
def __init__(self, ax):
self.ax = ax
self.annotation = ax.annotate(self.text_template,
xy=(self.x, self.y), xytext=(self.xoffset, self.yoffset),
textcoords= offset points , ha= right , va= bottom ,
bbox=dict(boxstyle= round,pad=0.5 , fc= yellow , alpha=0.5),
arrowprops=dict(arrowstyle= -> , connectionstyle= arc3,rad=0 )
)
self.annotation.set_visible(False)
def __call__(self, event):
self.event = event
# xdata, ydata = event.artist.get_data()
# self.x, self.y = xdata[event.ind], ydata[event.ind]
self.x, self.y = event.mouseevent.xdata, event.mouseevent.ydata
if self.x is not None:
self.annotation.xy = self.x, self.y
self.annotation.set_text(self.text_template % (self.x, self.y))
self.annotation.set_visible(True)
event.canvas.draw()
fig = plt.figure()
line, = plt.plot(range(10), ro- )
fig.canvas.mpl_connect( pick_event , DataCursor(plt.gca()))
line.set_picker(5) # Tolerance in points
似乎至少有几个人正在使用这一工具,因此,我在此补充了以下最新版本。
新版本的用法比较简单,文件数量也很多(即至少是细微的比值)。
基本上,你使用这种方法:
plt.figure()
plt.subplot(2,1,1)
line1, = plt.plot(range(10), ro- )
plt.subplot(2,1,2)
line2, = plt.plot(range(10), bo- )
DataCursor([line1, line2])
plt.show()
主要差异是:(a) 无需人工打电话line.set_picker(...)
,b) 不需要人工打电话<代码>fig.canvas.mpl_link,c) 该版本处理多个轴和多个数字。
from matplotlib import cbook
class DataCursor(object):
"""A simple data cursor widget that displays the x,y location of a
matplotlib artist when it is selected."""
def __init__(self, artists, tolerance=5, offsets=(-20, 20),
template= x: %0.2f
y: %0.2f , display_all=False):
"""Create the data cursor and connect it to the relevant figure.
"artists" is the matplotlib artist or sequence of artists that will be
selected.
"tolerance" is the radius (in points) that the mouse click must be
within to select the artist.
"offsets" is a tuple of (x,y) offsets in points from the selected
point to the displayed annotation box
"template" is the format string to be used. Note: For compatibility
with older versions of python, this uses the old-style (%)
formatting specification.
"display_all" controls whether more than one annotation box will
be shown if there are multiple axes. Only one will be shown
per-axis, regardless.
"""
self.template = template
self.offsets = offsets
self.display_all = display_all
if not cbook.iterable(artists):
artists = [artists]
self.artists = artists
self.axes = tuple(set(art.axes for art in self.artists))
self.figures = tuple(set(ax.figure for ax in self.axes))
self.annotations = {}
for ax in self.axes:
self.annotations[ax] = self.annotate(ax)
for artist in self.artists:
artist.set_picker(tolerance)
for fig in self.figures:
fig.canvas.mpl_connect( pick_event , self)
def annotate(self, ax):
"""Draws and hides the annotation box for the given axis "ax"."""
annotation = ax.annotate(self.template, xy=(0, 0), ha= right ,
xytext=self.offsets, textcoords= offset points , va= bottom ,
bbox=dict(boxstyle= round,pad=0.5 , fc= yellow , alpha=0.5),
arrowprops=dict(arrowstyle= -> , connectionstyle= arc3,rad=0 )
)
annotation.set_visible(False)
return annotation
def __call__(self, event):
"""Intended to be called through "mpl_connect"."""
# Rather than trying to interpolate, just display the clicked coords
# This will only be called if it s within "tolerance", anyway.
x, y = event.mouseevent.xdata, event.mouseevent.ydata
annotation = self.annotations[event.artist.axes]
if x is not None:
if not self.display_all:
# Hide any other annotation boxes...
for ann in self.annotations.values():
ann.set_visible(False)
# Update the annotation in the current axis..
annotation.xy = x, y
annotation.set_text(self.template % (x, y))
annotation.set_visible(True)
event.canvas.draw()
if __name__ == __main__ :
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(2,1,1)
line1, = plt.plot(range(10), ro- )
plt.subplot(2,1,2)
line2, = plt.plot(range(10), bo- )
DataCursor([line1, line2])
plt.show()