用于子图的set_ydata或者为什么包含两个子图的图比没有子图的图慢得多

时间:2015-07-08 00:21:44

标签: python matplotlib

我已经扩展following示例以使用多个子图。这是我的代码:

#!/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)
########################################
ax[0].plot(t,s, lw=2, color='red', label="red")
ax[1].plot(t,s, lw=2, color='green', label="green")
########################################
# plt.axis([0, 1, -10, 10])
ax[0].set_xlim([0, 1])
ax[0].set_ylim([-10, 10])

ax[1].set_xlim([0, 1])
ax[1].set_ylim([-10, 10])
########################################
axcolor = 'lightgoldenrodyellow'
f1  = plt.axes([0.25, 0.20,  0.65, 0.03], axisbg=axcolor)
a1  = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)

f2  = plt.axes([0.25, 0.1,  0.65, 0.03], axisbg=axcolor)
a2  = plt.axes([0.25, 0.05,  0.65, 0.03], axisbg=axcolor)

sf1 = Slider(f1, 'Freq1', 0.1, 30.0, valinit=f0)
sa1 = Slider(a1, 'Amp1',  0.1, 10.0, valinit=a0)

sf2 = Slider(f2, 'Freq2', 0.1, 30.0, valinit=f0)
sa2 = Slider(a2, 'Amp2',  0.1, 10.0, valinit=a0)
########################################
def update1(val):
    amp  = sa1.val
    freq = sf1.val

    # DOES NOT WORKS - set_ydata DOES NOT EXISTS
    # ax[1].set_ydata(amp*np.sin(2*np.pi*freq*t))
    # ax[2].set_ydata(amp*np.sin(2*np.pi*freq*t))

    # WORKS BUT IT SEEMS SLOW
    s = amp*np.sin(2*np.pi*freq*t)
    ax[0].clear()
    ax[0].plot(t,s, lw=2, color='red', label="red")
    ax[0].set_xlim([0, 1])
    ax[0].set_ylim([-10, 10])

    # THIS HAS NO EFFECT ON SPEED
    fig.canvas.draw_idle()

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


def update2(val):
    amp  = sa2.val
    freq = sf2.val

    # DOES NOT WORKS - set_ydata DOES NOT EXISTS
    # ax[1].set_ydata(amp*np.sin(2*np.pi*freq*t))
    # ax[2].set_ydata(amp*np.sin(2*np.pi*freq*t))

    # WORKS BUT IT SEEMS SLOW
    s = amp*np.sin(2*np.pi*freq*t)
    ax[1].clear()
    ax[1].plot(t,s, lw=2, color='green', label="green")
    ax[1].set_xlim([0, 1])
    ax[1].set_ylim([-10, 10])

    # THIS HAS NO EFFECT ON SPEED
    fig.canvas.draw_idle()

sf2.on_changed(update2)
sa2.on_changed(update2)

plt.show()

唯一的问题是它比原始速度慢(当点击滑块时)。我怀疑这是由update1update2函数中使用的一堆代码引起的。我不知道如何更有效地重写它。原始示例使用set_ydata函数,但似乎子图不具有此功能。我一直在考虑所有四个滑块的update函数,但我不知道是否可以区分触发更新的对象并在函数内处理它。感谢

1 个答案:

答案 0 :(得分:1)

您尝试分别在set_ydata(或ax[0])上致电ax[1]。这显然不起作用,因为这些是轴实例。 set_ydataLine2D艺术家的一种方法。在您已链接的示例中,在开头创建了一行l,它在更新函数中接收新的y数据。你在代码中忘记了这一点。

所以你需要创建一行:

line0, = ax[0].plot(t,s, lw=2, color='red')
line1, = ax[1].plot(t,s, lw=2, color='green')

在开头,然后在您的更新功能中,您可以致电:

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

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

注意:这里的想法是只更改线条的y坐标。通过解决方法,您删除了整个图并重新创建了它。这是更多的工作,因此它会使事情变得更慢。