当blit = True时,FuncAnimation不能将第一帧imshow内容搞砸掉?

时间:2017-10-06 10:17:38

标签: matplotlib

在FuncAnimation中使用imshow artist时。第一帧不能被遮挡。它将始终保持第一帧不受影响,但其他艺术家的行为正确。我们该如何解决这个问题? 这是代码:

from matplotlib import pyplot as plt, animation, cm
def show_imshow_blit_bug(start=0, blit=True):
    pic = np.zeros((10, 10), dtype=float)
    x = np.arange(0, 2 * np.pi, 0.01)
    amp = (x.max() - x.min()) / 2

    fig, ax = plt.subplots()
    extent = [x.min(), x.max(), -amp, amp]
    _cm = cm.jet
    picf = pic.flat
    picf[0] = 1
    picf[-1] = 0.5
    imart = ax.imshow(pic,
                      origin='lower',
                      extent=extent,
                      cmap=_cm
                      )
    # imart.set_animated(True) # set or not has no effect
    line, = ax.plot(x, np.sin(x)*amp)
    line2, = ax.plot(x[[0, -1]], np.array([-amp, amp]), 'r')
    line2.set_animated(True) # this make line2 disappear, since updater does not return this artist
    line3, = ax.plot(x[[0, -1]], np.array([amp, -amp]), 'C1')
    #line3 will be keeped since _animated = False
    ax.set_xlim(x.min(), x.max())
    ax.set_ylim(-amp * 1.1, amp * 1.1)
    fig.tight_layout()

    def updater(fn):
        print(fn)
        np.random.shuffle(picf)
        imart.set_data(np.ma.masked_where(pic == 0, pic))
        line.set_ydata(np.sin(x + fn / 10.0)*amp)
        return (imart, line,) # Both artist will be in blit list

    nframe = range(start, 200)
    anima = animation.FuncAnimation(fig,
                            updater,
                            nframe,
                            interval=20,
                            blit=blit,
                            repeat=False
                            )
    plt.show()

我知道在init_func中有一个hack solution设置艺术家隐身。但这是一个黑客,我不想使用与其余代码不兼容的init_func

1 个答案:

答案 0 :(得分:0)

FuncAnimation documentation

  

init_func:可调,可选

     

用于绘制清晰帧的函数。 如果没有给出,将使用帧序列中第一项绘制的结果。此功能将在第一帧之前调用一次。)

因此使用init_func不是黑客或不受欢迎的 - 它实际上是缩进的用法。

你会发起一个空图像

imart = ax.imshow([[]], ...)

有一个初始化函数

def init():
    return imart,line,

和更新功能

def updater(fn):
    np.random.shuffle(picf)
    imart.set_data(np.ma.masked_where(pic == 0, pic))
    line.set_ydata(np.sin(x + fn / 10.0)*amp)
    return (imart, line,)

并实例化FuncAnimation

anima = animation.FuncAnimation(fig,
                        updater,
                        nframe,
                        init_func=init,
                        interval=20,
                        blit=blit,
                        repeat=False
                        )