我使用ginput
对时间信号上的几个点进行图形选择。有时,当信号过于密集时,在选择点之前放大一个区域可能会很有用。我的问题是,zoom to rectangle
选项似乎在ginput
中得到了考虑。
例如,使用以下示例代码:
from __future__ import print_function
from pylab import arange, plot, sin, ginput, show
import numpy as np
t = np.linspace(0,25,500)
plot(t, sin(t))
x = ginput(3)
print("clicked",x)
show()
如果我放大信号的一部分,则在ginput
中会考虑到为缩放区域选择而进行的点击。。。有没有办法避免这种情况,并使缩放区域的选择独立于ginput
?
我也遇到了同样的问题,我的解决方案是编写一个用鼠标滚轮缩放的函数,这样我就可以在不点击的情况下进行缩放。我从这个页面得到了功能:
Matplotlib使用滚轮进行绘图缩放
并修改了函数,使其不会缩放超过原始的x和y限制:
def zoom_factory(ax, max_xlim, max_ylim, base_scale = 2.):
def zoom_fun(event):
# get the current x and y limits
cur_xlim = ax.get_xlim()
cur_ylim = ax.get_ylim()
xdata = event.xdata # get event x location
ydata = event.ydata # get event y location
if event.button == 'up':
# deal with zoom in
scale_factor = 1/base_scale
x_scale = scale_factor / 2
elif event.button == 'down':
# deal with zoom out
scale_factor = base_scale
x_scale = scale_factor * 2
else:
# deal with something that should never happen
scale_factor = 1
print(event.button)
# set new limits
new_width = (cur_xlim[1] - cur_xlim[0]) * x_scale
new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor
relx = (cur_xlim[1] - xdata) / (cur_xlim[1] - cur_xlim[0])
rely = (cur_ylim[1] - ydata) / (cur_ylim[1] - cur_ylim[0])
if xdata - new_width * (1 - relx) > max_xlim[0]:
x_min = xdata - new_width * (1 - relx)
else:
x_min = max_xlim[0]
if xdata + new_width * (relx) < max_xlim[1]:
x_max = xdata + new_width * (relx)
else:
x_max = max_xlim[1]
if ydata - new_height * (1 - rely) > max_ylim[0]:
y_min = ydata - new_height * (1 - rely)
else:
y_min = max_ylim[0]
if ydata + new_height * (rely) < max_ylim[1]:
y_max = ydata + new_height * (rely)
else:
y_max = max_ylim[1]
ax.set_xlim([x_min, x_max])
ax.set_ylim([y_min, y_max])
ax.figure.canvas.draw()
fig = ax.get_figure() # get the figure of interest
# attach the call back
fig.canvas.mpl_connect('scroll_event',zoom_fun)
#return the function
return zoom_fun
因此,对于给定的数字:
t = np.linspace(0,250,5000)
y = sin(t)
fig = figure()
ax = fig.add_subplot(111)
plt.plot(t,y)
max_xlim = ax.get_xlim() # get current x_limits to set max zoom out
max_ylim = ax.get_ylim() # get current y_limits to set max zoom out
f = zoom_factory(ax, max_xlim, max_ylim, base_scale=1.1)
show()
x = ginput(3)
由于我没有得到任何答案,也找不到太多关于这个主题的内容,以下是我解决这个问题的方法:我添加了一个预过程,允许用户放大选定的区域。当该区域适合点拾取时,用户只需按"Enter"并继续ginput
。
from __future__ import print_function
from pylab import arange, plot, sin, ginput, show
import matplotlib as plt
from pylab import *
import numpy as np
def closest_point(vec,val):
ind = np.where(vec==min(vec,key=lambda x:abs(x-val)))
return ind[0][0]
t = np.linspace(0,250,5000)
y = sin(t)
fig = plt.figure()
plt.suptitle('chosing points over a possibly dense signal...',fontsize=14)
zoom_ok = False
while not zoom_ok:
plt.plot(t,y)
plt.title('1 - click on the two corners of the area to enlarge',fontsize=12)
zoom = ginput(2,timeout=-1)
xzoom = np.zeros([0])
for i in range(2):
xzoom = np.concatenate((xzoom,[int(closest_point(t,zoom[i][0]))]))
temps_zoom = t[xzoom[0]:xzoom[1]]
dep_zoom = y[xzoom[0]:xzoom[1]]
plt.clf()
plt.plot(temps_zoom,dep_zoom,'b')
plt.title('2 - if zoom ok -> press Enter, otherwise -> mouse click',fontsize=12)
zoom_ok = plt.waitforbuttonpress()
plt.title('3 - you may now select the points ',fontsize=16)
x = ginput(2,timeout=-1)
plt.show()
我使用的一个变通方法是将鼠标按钮参数设置为None
:
plt.ginput(n=0, timeout=0, mouse_add=None, mouse_pop=None, mouse_stop=None)
然后我使用键盘添加/pop/stop。(要添加点,请将鼠标移动到正确的位置,然后按下Spacebar
或j
等。使用Delete
删除最后一个点,使用Enter
停止。)这样,当我使用鼠标进行矩形缩放时,我不会得到不需要的点。
当然,你可能会尝试的一些键盘键可能会有其他与窗口/缩放相关的副作用。(例如Backspace
将弹出并重置缩放),因此您必须小心。