2014-01-13 1 views
8

アニメーションプロットを出力する関数を実装しようとしています。python matplotlib:関数内からFuncAnimationを呼び出すことができません

私はベースとして(matplotlibの例から)simple_anim.pyを取る場合:

""" 
A simple example of an animated plot 
""" 
import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 

fig, ax = plt.subplots() 

x = np.arange(0, 2*np.pi, 0.01)  # x-array 
line, = ax.plot(x, np.sin(x)) 

def animate(i): 
    line.set_ydata(np.sin(x+i/10.0)) # update the data 
    return line, 

#Init only required for blitting to give a clean slate. 
def init(): 
    line.set_ydata(np.ma.array(x, mask=True)) 
    return line, 

ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init, 
    interval=25, blit=True) 
plt.show() 

効果的にそれが動作します。私は(変更パラメータを提供し、それぞれの可能なパラメータの値を明示的にファイルを行うことを避けるために)関数の中で、このコードを閉じた場合

しかし、:

""" 
A simple example of an animated plot 
""" 
import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 

def a(): 
    fig, ax = plt.subplots() 

    x = np.arange(0, 2*np.pi, 0.01)  # x-array 
    line, = ax.plot(x, np.sin(x)) 

    def animate(i): 
     line.set_ydata(np.sin(x+i/10.0)) # update the data 
     return line, 

    #Init only required for blitting to give a clean slate. 
    def init(): 
     line.set_ydata(np.ma.array(x, mask=True)) 
     return line, 

    ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init, 
     interval=25, blit=True) 
    plt.show() 

して、関数を呼び出し、フィギュアプロットは白色のままです。実際、アニメート機能に入ることは決してありません。

私はいくつかの情報が不足していることを知っています。それがうまくいかない理由です。 誰かに私にいくつかのヒントを与えることができますか?

は、どうもありがとうございました

アンドレス

+1

両方のコードは私のために正常に動作します。 'a'を呼び出すコードも投稿してください。 – Nabla

答えて

15

この問題が発生したことを理由タイマーとは、ウィンドウオブジェクトaniの属性である更新背中を呼び出すことです。それを参照しないと、aniのガベージが収集され、タイマー/コールバックがなくなります。

ソリューションは、あなたの関数の戻り値にaniを持っており、あなたのコードでそれへの参照を維持することです:

def a(...): 
    # stuff 
    ani = animation.FuncAnimation(...) 
    # more stuff 
    return ani 

outer_ani = a(...) 

この問題を(github #1656を参照)で議論されてきたが、解決されません。

+0

しかし、 'plt.show()'はウィンドウが閉じられるまでブロックしませんか? 'a()'関数は 'plt.show()'が返った後に残されます。その前に、「アニメ」のガベージコレクションは起こり得ません。 – Nabla

+0

'plt.show()'はnon-blockingにすることができます。例えば、シェルで対話的にコードを実行している場合 – tacaswell

+0

matplotlib 1.3.0とpython 3.2.5で 'plt.show()'はどんな場合でもブロックされます私が引数として 'block = False'を指定した場合を除いて、私はプロットをインタラクティブモードでしか表示せず、シェルがユーザ入力を待っている間だけアニメーションを維持します。この場合でも、問題の両方のコードブロックはまだ問題なく動作します。この問題のバージョン依存性があるのでしょうか、それとも明らかに何かが間違っていますか? – Nabla

1

tcaswellの善良な答えは、削除されてガベージコレクションに使用できるオブジェクトに依存するため、問題コードの動作は定義されていません。

実際には、この未定義の動作はGUIのバックエンドによって異なります。いくつかのユーザ(例えばthis "duplicate" question)では、IDLEでWxバックエンドを使用するか、Windows上のデフォルトのPylabショートカットを使用すると、未定義のコードが動作するように見えます(実際には動作していないので、 )。デフォルトのQtバックエンドでCanopy GUIを実行している場合、コードは機能しません。 QtとWxは非常に異なるアーキテクチャとガベージコレクションを持っています。 (Canopでは、GUIのバックエンドはPreferencesメニューのPythonタブで変更できます;もしWxに変更されていれば、未定義のコードもうまくいくようですが、正しいとは言えません)

関連する問題