动态更改y限制

时间:2015-07-09 15:48:38

标签: python matplotlib

以下是代码:

#!/usr/bin/python
import numpy as np
import matplotlib.pyplot  as plt
from   matplotlib.widgets import Slider
########################################
t = np.arange(0.0, 1.0, 0.001)
a0 = 5
f0 = 3
s = a0*np.sin(2*np.pi*f0*t)
########################################
plt.close('all')
fig, ax = plt.subplots(nrows=2, ncols=1)
plt.subplots_adjust(bottom=0.30)
########################################
line0, = ax[0].plot(t,s, lw=2, color='red',   label="red")
# IS THIS LINE NECESSARY
line1, = ax[1].plot(t,s, lw=2, color='green', label="green")
########################################
ax[0].set_xlim([0, 1])
ax[0].set_ylim([-10, 10])
########################################
axcolor = 'lightgoldenrodyellow'
left   = 0.25
bottom = 0.20
width  = 0.65
# DIFFERENT SCALE
# height = fig.get_size_inches()[1] * 0.1
height = 0.03
vgap   = 0.02
print "fig height %s" % fig.get_size_inches()[1]

f1  = plt.axes([left, bottom-0*(height+vgap), width, height], axisbg=axcolor)
a1  = plt.axes([left, bottom-1*(height+vgap), width, height], axisbg=axcolor)

sf1 = Slider(f1, 'Freq1', 0.1, 30.0, valinit=f0)
sa1 = Slider(a1, 'Amp1',  0.1, 10.0, valinit=a0)
########################################
def update1(val):
    amp  = sa1.val
    freq = sf1.val

    line0.set_ydata(amp*np.sin(2*np.pi*freq*t))
    line1.set_ydata(2*amp*np.sin(2*np.pi*freq*t))

sf1.on_changed(update1)
sa1.on_changed(update1)

plt.show()

当使用滑块改变第一个图上波的幅度/频率时,它也会改变第二个图上波的幅度/频率(它使第二个图上的波幅加倍)。问题是当第一个图的幅度超过3时。在这种情况下,它根本不适合第二个图。因为它的y范围是-6到6。 y limit is not enough

三个问题:

  1. -6和6号码来自哪里?我没有设置它们。
  2. 如何在第二个图上动态更改y限制?我可以使用例如ax[1].set_ylim([-20, 20])但我想要更通用的东西。让我们假设第二个图可以有y值超过20(这可能是一些复杂计算的结果,在绘图过程中是未知的)。基本上,当第一个图的幅度很小时,第二个图的y应该缩小,当幅度很大时y应该展开。
  3. 我可以将第二个图留空,直到我改变第一个图的幅度/频率。换句话说,这也可以(请显示两个案例,一个是第二个图已经存在而另一个是不存在的情况下),而不使用以下行创建第二个图:line1, = ax[1].plot(t,s, lw=2, color='green', label="green")

1 个答案:

答案 0 :(得分:3)

编辑: 用户hitzg对原始答案提供了一些有用的改进in comments - 我已经采取了这些措施,并且通常会使答案更深入而且更通用。

我将逐一提出问题

  
      
  1. 6和-6来自哪里?
  2.   

这是matplotlib的最佳猜测,基于您最初在轴上绘制的数据。如果您没有指定任何值,它将尽可能地适应轴限制。

对于那些感兴趣的人 - these lines of code是matplotlib默认自动缩放轴的地方,如果没有指定比例,this line实际应用自动缩放。

  
      
  1. 如何在第二个图上动态更改y限制?我
  2.   

你快到了。在update1()中添加ax[1].autoscale_view(),在您添加新数据时,必须以 ax[1].relim()开头。这将使matplotlib自动调整轴以适应您在其上绘制的任何数据的值,并且是通用解决方案。如果您需要“手动”但自己动态控制轴,请参阅下面我的原始建议。

NB 在原始版本中,我建议只编写ax[1].set_ylim(-2.2*amp,2.2*amp)或类似的地方2.2是一个任意因素:正弦波幅度的限制由滑块加一点(0.2

  
      
  1. 我可以将第二个图留空,直到我改变第一个图的幅度/频率?
  2.   

是。一种方法是替换

line1, = ax[1].plot(t,s, lw=2, color='green', label="green")

line1, = ax[1].plot([],[], lw=2, color='green', label="green")

这会在您可以更新的轴上创建一个线对象,但最初没有数据。注:我最初建议使用0,0而不是[],[],但这会在0,0处绘制一点,这可能不适合您的目的。

然后在update1() put

line1.set_xdata(t)

update1()函数的最终代码

def update1(val):
    amp  = sa1.val
    freq = sf1.val

    line0.set_ydata(amp*np.sin(2*np.pi*freq*t))
    line1.set_xdata(t)
    line1.set_ydata(2*amp*np.sin(2*np.pi*freq*t))
    ax[1].relim()
    ax[1].autoscale_view()