对matplotlib中的补丁集进行动画处理 [英] Animate a collection of patches in matplotlib

查看:44
本文介绍了对matplotlib中的补丁集进行动画处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为一组遵循 x、y 和 z 轨迹的粒子设置动画.每个对象都有一个特定的半径,以轴为单位,这就是为什么我希望每个对象都由一个Circle色块表示,因此我可以在其中指定色块的大小(与散点图相反,我必须在该位置进行转换)轴单位的大小).

I'm trying to animate a set of particles that follow trajectories in x, y and z. Each object has a specific radius which is relevant in axis units, which is why I want each object to be represented by a Circle patch, where I can specify the size of the patch (as opposed to a scatter plot, where I have to convert the size to axis units).

另一个限制是我希望补丁按照颜色图着色,补丁的颜色由z的值确定.

The other constraint is that I want the patches to be colored according to a colormap, with the color of the patch determined by the value of z.

我发现绘制带有色图的一组补丁的唯一方法是将它们放置在一个集合中.所以,这成功地产生了一帧

The only way I have found of plotting a set of patches with a colormap is by putting them inside a collection. So, this successfully produces one frame

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm
import matplotlib.collections as clt

fig, ax = plt.subplots(1,1,figsize=(7,7))

ax.set_xlim(-1,1)
ax.set_ylim(-1,1)

n_of_particles = 3
frames = 10

radius = 0.05
x = 0.5*np.random.randn(frames,n_of_particles)
y = 0.5*np.random.randn(frames,n_of_particles)
z = 0.5*np.random.randn(frames,n_of_particles)

patches = []
for p in range(n_of_particles):
    circle = plt.Circle((x[0,p], y[0,p]), radius)
    patches.append(circle)

collection = clt.PatchCollection(patches, cmap=plt.cm.jet, alpha=0.4)
collection.set_array(z[0,:])
collection.set_clim([-1, 1])
plt.colorbar(collection)

ax.add_collection(collection)

但我如何为其设置动画?

But how do I animate it?

我尝试在末尾添加(而不是 ax.add_collection(collection))

I have tried to add at the end (instead of ax.add_collection(collection))

def animate(frame):
    patches = []
    for p in range(n_of_particles):
        circle = plt.Circle((x[frame,p], y[frame,p]), radius)
        patches.append(circle)

    collection = clt.PatchCollection(patches, cmap=plt.cm.jet, alpha=0.4)
    collection.set_array(z[0,:])

    ax.add_collection(collection)
    return collection,

然后:

anim = anm.FuncAnimation(fig, animate,
                               frames=10, interval=100, blit=True)
HTML(anim.to_html5_video())

但是不会删除前一帧.

理想情况下,我更愿意改变补丁的位置,而不是重新定义它们.但是我不知道如何修改集合.

Ideally, I would prefer to change the position of the patches, instead of redefining them. But I don't know how to modify a collection.

有什么想法吗?

推荐答案

这个想法当然是只将集合添加到坐标区一次.然后通过 collection.set_paths 更改集合中的艺术家.

The idea would of course be to add the collection only once to the axes. Then change the artists inside the collection via collection.set_paths.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm
import matplotlib.collections as clt

fig, ax = plt.subplots(1,1,figsize=(7,7))

ax.set_xlim(-1,1)
ax.set_ylim(-1,1)

n_of_particles = 3
frames = 10

radius = 0.05
x = 0.5*np.random.randn(frames,n_of_particles)
y = 0.5*np.random.randn(frames,n_of_particles)
z = 0.5*np.random.randn(frames,n_of_particles)

patches = []
for p in range(n_of_particles):
    circle = plt.Circle((x[0,p], y[0,p]), radius)
    patches.append(circle)

collection = clt.PatchCollection(patches, cmap=plt.cm.jet, alpha=0.4)
collection.set_array(z[0,:])
collection.set_clim([-1, 1])
fig.colorbar(collection)

ax.add_collection(collection)

def animate(frame):
    patches = []
    for p in range(n_of_particles):
        circle = plt.Circle((x[frame,p], y[frame,p]), radius)
        patches.append(circle)

    collection.set_paths(patches)
    collection.set_array(z[frame,:])

anim = anm.FuncAnimation(fig, animate,
                               frames=10, interval=1000, blit=False)
plt.show()

另一种选择可能是使用此答案中提供的解决方案:matplotlib 更改PatchCollection 中的补丁
并创建一个 UpdatablePatchCollection .这将允许只更新循环内原始补丁的属性.

The other option could be to use the solution provided in this answer: matplotlib change a Patch in PatchCollection
and create an UpdatablePatchCollection. This would allow to just update the properties of the original patches inside the loop.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm
import matplotlib.collections as clt

fig, ax = plt.subplots(1,1,figsize=(7,7))

ax.set_xlim(-1,1)
ax.set_ylim(-1,1)

n_of_particles = 3
frames = 10

radius = 0.05
x = 0.5*np.random.randn(frames,n_of_particles)
y = 0.5*np.random.randn(frames,n_of_particles)
z = 0.5*np.random.randn(frames,n_of_particles)

patches = []
for p in range(n_of_particles):
    circle = plt.Circle((x[0,p], y[0,p]), radius)
    patches.append(circle)

class UpdatablePatchCollection(clt.PatchCollection):
    def __init__(self, patches, *args, **kwargs):
        self.patches = patches
        clt.PatchCollection.__init__(self, patches, *args, **kwargs)

    def get_paths(self):
        self.set_paths(self.patches)
        return self._paths

collection = UpdatablePatchCollection(patches, cmap=plt.cm.jet, alpha=0.4)
collection.set_array(z[0,:])
collection.set_clim([-1, 1])
fig.colorbar(collection)

ax.add_collection(collection)

def animate(frame):
    for p in range(n_of_particles):
        patches[p].center = x[frame,p], y[frame,p]   
    collection.set_array(z[frame,:])

anim = anm.FuncAnimation(fig, animate,
                               frames=10, interval=1000, blit=False)

plt.show()

这篇关于对matplotlib中的补丁集进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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