Python 在matplotlib中设置面片集合的动画

Python 在matplotlib中设置面片集合的动画,python,matplotlib,Python,Matplotlib,我正在尝试设置一组粒子的动画,这些粒子沿着x、y和z的轨迹运动。每个对象都有一个特定的半径,该半径以轴单位表示,这就是为什么我希望每个对象由一个圆形面片表示,我可以指定面片的大小(与散点图相反,在散点图中,我必须将大小转换为轴单位) 另一个约束是,我希望面片根据颜色贴图着色,面片的颜色由z值决定 我发现用彩色贴图绘制一组面片的唯一方法是将它们放在集合中。因此,这成功地生成了一个帧 import numpy as np import matplotlib.pyplot as plt import

我正在尝试设置一组粒子的动画,这些粒子沿着x、y和z的轨迹运动。每个对象都有一个特定的半径,该半径以轴单位表示,这就是为什么我希望每个对象由一个圆形面片表示,我可以指定面片的大小(与散点图相反,在散点图中,我必须将大小转换为轴单位)

另一个约束是,我希望面片根据颜色贴图着色,面片的颜色由z值决定

我发现用彩色贴图绘制一组面片的唯一方法是将它们放在集合中。因此,这成功地生成了一个帧

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)
但是我该如何设置动画呢

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

然后:

anim = anm.FuncAnimation(fig, animate,
                               frames=10, interval=100, blit=True)
HTML(anim.to_html5_video())
但它不会删除前一帧

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


有什么想法吗?

当然,想法是只向轴添加一次集合。然后通过
收藏更改收藏中的艺术家。设置路径

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()
另一种选择是使用此答案中提供的解决方案:
并创建一个
updateablepatchcollection
。这将允许只更新循环中原始面片的属性

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