2017-08-30 42 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() 

动画从不更新。它被冻结在一个空的地块上。

我会对其他优化方式开放。目前的解决方案似乎相当冗长,只是每个框架添加一个矩形。

回答

2

我不知道我完全理解你的代码。将矩形的facecolor从白色切换到黑色的想法是将该矩形添加到该图上?

我花了一点时间来弄清楚为什么你的代码不工作,但事实证明这是一个愚蠢的错误。问题是与行ax.add_patch(patch)。实际上,您在图上添加了两组矩形,一个作为单个Rectangle实例,第二个作为PatchCollection的一部分。它看起来像Rectangles留在收藏的顶部,所以你只是没有看到动画。只是评论违规行(ax.add_patch(patch))似乎解决了这个问题。

另外,FuncAnimation(..., interval=)ms表示,因此您可能想要将值增大到更大的值(100ms或1000ms,即1秒)以查看动画。

在这里,我怎么会写代码(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

我没有处理大量元素的动画处理经验。但据我所知,只要您可以接受使用“集合”对象的限制,它总是比绘制单个补丁更快 –