问题
I am using ginput
for a graphic selection of a few points along a time signal. Sometimes, when the signal is too dense it might be useful to zoom over an area before making the selection of points. My problem is that it seems that the zoom to rectangle
option seems to be accounted for in ginput
.
For instance, with this sample code:
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()
If I zoom over a portion of the signal, the clicks made for the zoom area selection are accounted for in ginput
... Is there a way to avoid this and make the zoom area selection independent from ginput
?
回答1:
I was having the same issue and my fix was to write a function to zoom with the mouse wheel so I could zoom without clicking. I got the function from this page:
Matplotlib plot zooming with scroll wheel
and modified the function so that it was not zoomed past the original x and y limits:
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
So for a given figure:
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)
回答2:
As I did not get any answer and I could not find much on the topic, here is how I solved this problem: I added a pre-procedure allowing the user to zoom in over a chosen area. When the area is suitable for point picking, the user simply has to press "Enter" and go on with 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()
来源:https://stackoverflow.com/questions/29145821/can-python-matplotlib-ginput-be-independent-from-zoom-to-rectangle