Matplotlib第一帧后停止动画 [英] Matplotlib stops animating after first frame

查看:766
本文介绍了Matplotlib第一帧后停止动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图动画2次要情节,每多行。我使用的 Matplotlib ,而我使用<$c$c>FuncAnimation,它是由许多的动画范例的。

使用动画:

如果我尝试动画吧,我只得到第一帧的结果:

如果不使用动画:

如果我手动调用我的 update_lines 函数,它工作正常。

code:

以下是完整code(取消注释3所示的行的main()的作品,但我想看到它在实时更新,因此,尝试使用动画)。

 进口matplotlib.pyplot如PLT
从matplotlib.animation进口FuncAnimation
高清make_subplots():
    高清setup_axes(轴):
        在轴AX:
            ax.set_xbound(0,100)根据需要#结合将改变。
            ax.set_ylim(0,1)#限制不会自动改变。    高清make_lines(轴):
        标签=('A','B','C')
        行= []
        在轴AX:
            ax_lines = []
            在标签标签:
                的x,y = [0],[0]
                行= ax.plot(X,Y​​,标签=标签)#逗号拆箱。
                ax_lines.append((线,X,Y))
            lines.append(ax_lines)
        返回线    无花果,轴= plt.subplots(2,1,sharex = TRUE,sharey = TRUE)
    线= make_lines(轴)
    setup_axes(轴)
    返回无花果,轴,线
高清make_data():
    在的xrange(100)I:
        打印make_data()',我
        数据字典=()
        在('一个','B','C')标签:
            从随机随机进口
            数据[标签] =随机()
        产量第(i + 1,数据)
高清update_lines(数据线):
    打印update_lines()',数据线
    updated_lines = []
    在线路ax_lines:
        为线,X,Y在ax_lines:
            标签= line.get_label()
            x.append(数据[0])
            y.append(数据[1] [标签])
            line.set_data(X,Y)
            updated_lines.append(线)
高清的main():
    无花果,斧头,线条= make_subplots()    #取消这3条线,和它的作品!
    #NEW_DATA = make_data()
    #在NEW_DATA数据:
    #update_lines(数据行)    FuncAnimation(图=图,
                  FUNC = update_lines,
                  帧= make_data,
                  fargs =(线,),
                  间隔= 10,
                  的blit = FALSE)    plt.show()
如果__name__ =='__main__':
    主要()


解决方案

(无证?)挂钩​​

所以,我周围挖 matplotlib.animation.Animation 的源 - code,我注意到在 __ init__这些线路()功能:

 #清除初始帧
self._init_draw()#相反,从现在开始的事件源,我们连接到人物的
#draw_event,让我们曾经的身影已经绘就只启动。
self._first_draw_id = fig.canvas.mpl_connect('draw_event',self._start)

听起来很耳熟...

这看起来正确为止。在 self._init_draw()呼叫立即吸引我的第一帧。然后动画对象挂钩插入数字对象,并等待该图以试图绘制任何更多的帧的动画之前被显示。

尤里卡!

关键词是:animation-的目标即可。因为我不是在以后的使用动画实例规划(例如,画一个电影),我没有把它分配给一个变​​量。的实际上的,我被大叫 pyflakes 因为局部变量'...'被分配到,但从未使用过

但是,因为所有的功能依赖上了钩,当画布终于显示我presume Python的垃圾收集去掉了动画实例---因为它从来没有分配给一个变​​量---因此,动画永远不能启动。

的修复

简单实例 FuncAnimation 实例分配给一个变​​量,一切工作正常!

 动画= FuncAnimation(图=图,
                     FUNC = update_lines,
                     帧= make_data,
                     fargs =(线,),
                     间隔= 10,
                     的blit = FALSE)

I'm trying to animate two subplots, each with multiple lines. I am using Matplotlib, and I am using the FuncAnimation, which is used by many of the animation examples.

Using animation:

If I try to animate it, I only get the result of the first frame:

Without using animation:

If I manually call my update_lines function, it works fine.

Code:

Below is the full code (uncommenting the 3 indicated lines in main() works, but I would like to see it update in real-time, hence trying to use the animation).

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation


def make_subplots():
    def setup_axes(axes):
        for ax in axes:
            ax.set_xbound(0, 100)  # bound will change as needed.
            ax.set_ylim(0, 1)  # limit won't change automatically.

    def make_lines(axes):
        labels = ('a', 'b', 'c')
        lines = []
        for ax in axes:
            ax_lines = []
            for label in labels:
                x, y = [0], [0]
                line, = ax.plot(x, y, label=label)  # comma for unpacking.
                ax_lines.append((line, x, y))
            lines.append(ax_lines)
        return lines

    fig, axes = plt.subplots(2, 1, sharex=True, sharey=True)
    lines = make_lines(axes)
    setup_axes(axes)
    return fig, axes, lines


def make_data():
    for i in xrange(100):
        print 'make_data():', i
        data = dict()
        for label in ('a', 'b', 'c'):
            from random import random
            data[label] = random()
        yield (i + 1, data)


def update_lines(data, lines):
    print 'update_lines():', data, lines
    updated_lines = []
    for ax_lines in lines:
        for line, x, y in ax_lines:
            label = line.get_label()
            x.append(data[0])
            y.append(data[1][label])
            line.set_data(x, y)
            updated_lines.append(line)


def main():
    fig, axes, lines = make_subplots()

    # Uncomment these 3 lines, and it works!
    # new_data = make_data()
    # for data in new_data:
    #     update_lines(data, lines)

    FuncAnimation(fig=fig,
                  func=update_lines,
                  frames=make_data,
                  fargs=(lines,),
                  interval=10,
                  blit=False)

    plt.show()


if __name__ == '__main__':
    main()

解决方案

(Undocumented?) Hooks

So, I was digging around the source-code of matplotlib.animation.Animation, and I noticed these lines in the __init__() function:

# Clear the initial frame
self._init_draw()

# Instead of starting the event source now, we connect to the figure's
# draw_event, so that we only start once the figure has been drawn.
self._first_draw_id = fig.canvas.mpl_connect('draw_event', self._start)

Sounds familiar...

This looks right so far. The self._init_draw() call draws my first frame immediately. Then the animation-object hooks into the figure-object and waits for the figure to be shown before attempting to draw any more frames for the animation.

Eureka!

The keyword is: animation-object. Since I wasn't planning on using the animation instance later (for example, to draw a movie), I didn't assign it to a variable. In fact, I was being yelled at by pyflakes because Local variable '...' is assigned to but never used.

But because all of the functionality relies on the hook, when the canvas is finally shown I presume Python's garbage collection has removed the Animation instance---since it was never assigned to a variable---and therefore the animation can never be started.

The fix

Simply assign the instance FuncAnimation instance to a variable, and everything works as expected!

anim = FuncAnimation(fig=fig,
                     func=update_lines,
                     frames=make_data,
                     fargs=(lines,),
                     interval=10,
                     blit=False)

这篇关于Matplotlib第一帧后停止动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆