以下是代码:
#!/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。
三个问题:
ax[1].set_ylim([-20, 20])
但我想要更通用的东西。让我们假设第二个图可以有y
值超过20(这可能是一些复杂计算的结果,在绘图过程中是未知的)。基本上,当第一个图的幅度很小时,第二个图的y
应该缩小,当幅度很大时y
应该展开。line1, = ax[1].plot(t,s, lw=2, color='green', label="green")
答案 0 :(得分:3)
编辑: 用户hitzg对原始答案提供了一些有用的改进in comments - 我已经采取了这些措施,并且通常会使答案更深入而且更通用。
我将逐一提出问题
- 6和-6来自哪里?
醇>
这是matplotlib的最佳猜测,基于您最初在轴上绘制的数据。如果您没有指定任何值,它将尽可能地适应轴限制。
对于那些感兴趣的人 - these lines of code是matplotlib默认自动缩放轴的地方,如果没有指定比例,this line实际应用自动缩放。
- 如何在第二个图上动态更改y限制?我
醇>
你快到了。在update1()
中添加ax[1].autoscale_view()
,在您添加新数据时,必须以 ax[1].relim()
开头。这将使matplotlib自动调整轴以适应您在其上绘制的任何数据的值,并且是通用解决方案。如果您需要“手动”但自己动态控制轴,请参阅下面我的原始建议。
NB 在原始版本中,我建议只编写ax[1].set_ylim(-2.2*amp,2.2*amp)
或类似的地方2.2
是一个任意因素:正弦波幅度的限制由滑块加一点(0.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()