13

それぞれが複数の行を持つ2つのサブプロットをアニメーション化しようとしています。私はMatplotlibを使用しており、アニメーションの例FuncAnimationの多くで使用されているを使用しています。

アニメーションの使用:

アニメーション化しようとすると、最初のフレームの結果しか得られません。 アニメーション付き

アニメーションを使用しない場合:

関数を手動で呼び出すと、update_lines正常に機能します。 アニメーションなし

コード:

以下は完全なコードです(作品で示された3行のコメントを外しますmain()が、リアルタイムで更新されることを望んでいるため、アニメーションを使用しようとしています)。

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()
4

1 に答える 1

14

(文書化されていませんか?)フック

それで、私はのソースコードを調べていましたmatplotlib.animation.Animation、そして私は関数のこれらの行に気づきました__init__()

# 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)

おなじみのようですね...

これは今のところ正しく見えます。呼び出しはすぐに私のself._init_draw()最初のフレームを描画します。次に、animation-objectはfigure-objectにフックし、figureが表示されるのを待ってから、アニメーション用にさらにフレームを描画しようとします。

ユーレカ!

キーワードは、animation- objectです。後でアニメーションインスタンスを使用する予定がなかったため(たとえば、映画を描くため)、変数に割り当てませんでした。実は、私はパイフレークに怒鳴らていました。Local variable '...' is assigned to but never used

しかし、すべての機能がフックに依存しているため、キャンバスが最終的に表示されたときに、PythonのガベージコレクションがAnimationインスタンスを削除したと推測します---変数に割り当てられなかったため---したがって、アニメーションを開始することはできません。

修正

FuncAnimationインスタンスインスタンスを変数に割り当てるだけで、すべてが期待どおりに機能します。

anim = FuncAnimation(fig=fig,
                     func=update_lines,
                     frames=make_data,
                     fargs=(lines,),
                     interval=10,
                     blit=False)
于 2013-03-10T21:42:01.210 に答える