2017-08-30 8 views
0

matplotlibアニメーションを最適化しようとしていますが、繰り返しごとにプロットに矩形を追加します。アニメーション機能は反復ごとにパッチのセット全体を更新するので、大きなセットのパッチでは非常に遅いです。Python Matplotlib:PatchCollectionアニメーションが更新されない

いくつかの情報源によれば、パッチをループする代わりにPatchCollectionを使用することで、このプロセスを高速化できます。これは私の試みです:

from matplotlib import pyplot 
from matplotlib import patches 
from matplotlib import animation 
from matplotlib.collections import PatchCollection 

fig = pyplot.figure() 

coords = [[1,0],[0,1],[0,0]] #arbitrary set of coordinates 

ax = pyplot.axes(xlim=(0, len(coords)), ylim=(0, len(coords))) 
ax.set_aspect('equal') 


patchList = list() 

for coord in coords: 
    patch = patches.Rectangle(coord, 1, 1, color="white") 
    ax.add_patch(patch) 
    patch.set_visible = True 
    patchList.append(patch) 

rectangles = PatchCollection(patchList, animated=True) 
ax.add_collection(rectangles) 


black = [] 
white = ["white"]*len(patchList) 

def animate(i): 
    black.append("black") 
    white.pop() 

    colors = black + white 
    print(colors) 

    rectangles.set_facecolors(colors) 
    print("%.2f%%..."%(100*float(i+1)/len(coords))) 

    return rectangles, 

anim = animation.FuncAnimation(fig, animate, 
           # init_func=init, 
           frames=len(coords)-1, 
           interval=1, 
           blit=True, 
           repeat = False) 

pyplot.show() 

アニメーションは決して更新されません。それは空のプロット上で凍結されます。

私はこれを他の方法で最適化することができます。現在のソリューションは、各フレームを1つの長方形に追加するだけで非常に冗長に見えます。

答えて

2

私はあなたのコードを完全に理解していません。矩形のfacecolorを白から黒に切り替えることは、その矩形をプロットに「追加する」という考えですか?

あなたのコードがうまくいかなかった理由を理解するのに少し時間がかかりましたが、それは愚かな間違いであることが判明しました。問題はラインax.add_patch(patch)です。実際には、1つのRectangleインスタンスとして1回、PatchCollectionの一部として2つ目の四角形をプロットに追加しています。 Rectanglesがコレクションの上にとどまっているように見えるので、アニメーションが表示されないだけです。違反行(ax.add_patch(patch))にコメントするだけで、問題が解決されたようです。

また、FuncAnimation(..., interval=)はアニメーションを見ることがmsで表現されるので、あなたは、より大きな何かに値を増やすことができます(1S 100ミリ秒、または1000ミリ秒すなわち)。

ここで私はコード(loosely inspired by this question on SOを)書くでしょうか:

Nx = 30 
Ny = 20 
size = 0.5 

colors = ['w']*Nx*Ny 

fig, ax = plt.subplots() 

rects = [] 
for i in range(Nx): 
    for j in range(Ny): 
     rect = plt.Rectangle([i - size/2, j - size/2], size, size) 
     rects.append(rect) 

collection = PatchCollection(rects, animated=True) 

ax.add_collection(collection) 
ax.autoscale_view(True) 

def init(): 
    # sets all the patches in the collection to white 
    collection.set_facecolor(colors) 
    return collection, 

def animate(i): 
    colors[i] = 'k' 
    collection.set_facecolors(colors) 
    return collection, 

ani = FuncAnimation(fig, init_func=init, func=animate, frames=Nx*Ny, 
     interval=1e2, blit=True) 

enter image description here

+0

おかげで、これは私の問題を解決します。その余分なadd_patch行は私が以前使っていたPatchCollectionsクラスを使わなかったメソッドの痕跡だったので、削除するのを忘れてしまった。 – Ryan

+0

以前は、プロットを更新する実際の時間が制限要因でした。私は500-1000の正方形をアニメーション化していますので、できるだけ早く実行するようにしました。 20msは50fpsのアニメーションになりますが、これは私の目的にとっては良いことです。 また、カラーリストのi番目の値を代入すると意味があることに同意します。このスタイルの独自のアニメーションを作成する場合は、PatchCollectionsを使用してカラー配列を編集するか、別の方法で行いますか? – Ryan

+0

アニメーション化する要素がたくさんある経験はありません。しかし、私が知る限り、 'Collection'オブジェクトを使って作業することの限界を受け入れられる限り、個々のパッチを描画するよりも常に速くなります –

関連する問題