Один из вариантов - подключиться к сигналу xlim_changed
и рассчитать, основываясь на текущих пределах x, новые пределы для оси y так, чтобы все данные были включены.
Следующее делает это, и это немного сложнее, чем первоначально предполагалось, потому что просто установка пределов y не сработает, потому что они будут перезаписаны (одновременным) событием ylim_changed
, которое вызывает масштабирование. Таким образом, вместо этого есть таймер, установленный на 10 миллисекунд, который искусственно устанавливает пределы после обработки этого события.
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
class AutoScaleY():
def __init__(self, line, margin=0.05):
self.margin = margin
self.line = line
self.ax = line.axes
self.ax.callbacks.connect('xlim_changed', self.rescale_y)
def rescale_y(self,evt=None):
xmin, xmax = ax.get_xlim()
x, y = line.get_data()
cond = (x >= xmin) & (x <= xmax)
yrest = y[cond]
margin = (yrest.max()-yrest.min())*self.margin
self.ybounds = [yrest.min()-margin, yrest.max()+margin]
self.timer = self.ax.figure.canvas.new_timer(interval=10)
self.timer.single_shot = True
self.timer.add_callback(self.change_y)
self.timer.start()
def change_y(self):
self.ax.set_ylim(self.ybounds)
self.ax.figure.canvas.draw()
x=np.linspace(0,100,1001)
y = np.sin(x/16) + np.cumsum(np.random.randn(1001))/30.
fig, ax = plt.subplots()
line, = ax.plot(x,y)
r = AutoScaleY(line)
plt.show()