matplotlib动画绘制所有点,而不仅仅是最新的迭代

时间:2017-11-26 17:40:35

标签: python numpy animation matplotlib

我正在尝试使用matplotlib为在2D空间中移动的一组点设置动画。它目前有点工作,因为它代码确实产生了点的动画,但它不是我认为它会工作的方式。而不是在每个时刻绘制点,而是在所有时间点绘制它们。

例如,如果代码以二十个点运行,我希望它在一帧显示二十个点,然后在下一帧显示相同的点,依此类推。相反,它保留了先前的帧点,而不是仅显示新的点。

有人可以告诉我哪里出错了吗?

另外,我从我的研究中发现,最好为动画启用blitting以优化问题但是当我添加blit = True作为FuncAnimation的参数时,控制台会发出一个巨大的回溯结束于:

文件“C:\ Users \ Anaconda3 \ lib \ site-packages \ matplotlib \ animation.py”,第1568行,在_draw_frame中     a.set_animated(self._blit)

AttributeError:'numpy.ndarray'对象没有属性'set_animated'

我也不知道为什么会这种情况发生,在线搜索也没有用。

代码如下:

import matplotlib.pyplot as plt #Import plotting library
from matplotlib import animation
import numpy as np #Import numpy library

dim = 2             #Defines the dimensionality of the system
n = 25               #Number of BOIDS
tmax = 80             #Length of sim
dmax = 5            #Distance boids can "see", determines what other boids interact with them
o = np.zeros(dim) #Origin as vector
r = np.random.rand(n,dim) #Places BOIDs randomly with co-ordinates (x,y,z) from 0 to 1. Has dimensions n and dim
v = 2*np.random.rand(n,dim)-1#Sets initial velocity of each BOID from -1 to 1 in each cardinal direction
rt = np.zeros((tmax,n,dim)) #This array contains the whole system's positions at each point in time
x = np.empty(n)
y = np.empty(n)
d = np.zeros(n)
vk = np.zeros((n,2))
vksum = np.zeros((n,2))
pltx = np.zeros((tmax,n))
plty = np.zeros((tmax,n))
"""rt[a][b][0] is the x co-ordinate of boid n=b at t=a
   rt[a][b][1] is the y co-ordiante of boid n=b at t=a
   np.linalg.norm gives the modulus of an array, check documentation for arguments"""

fig, ax = plt.subplots(figsize=(14,9))
ax.grid(True,linestyle='-',color='0.75') #Sets up a grid on subplot
ax.set_xlim(-50,50)
ax.set_ylim(-50,50) #Set limits for x and y axes 

for t in range (0,tmax):
    for i in range (0,n):
        for k in range (0,n):
            if abs(k-n)>0:
                d[k] = ((r[i][0]-r[k][0])**2+(r[i][1]-r[k][1])**2)**(1/2) #Checks distance from ith boid to each other boid
            if (d[k]-dmax)<0:   #If they are within range of the ith boid
                vk[k] = (v[i] +v[k])/((np.linalg.norm(v[i]))*np.linalg.norm(v[k]))#Aligns the velocity of ith boid toward the velocity of the kth boid
        for l in range (0,n):
            vksum[i] = vksum[i] + vk[l] #Sums the boid's velocity contributions together
        v[i] = (3/4)*v[i] + (vksum[i]/np.linalg.norm(vksum[i])) #Sets the boid's new velocity 
        r[i] = r[i] + v[i]  #Sets the boid's new position
        rt[t][i] = r[i] #Logs the position of the boid in the time array
        pltx[t][i] = r[i][0]
        plty[t][i] = r[i][1]


def init():
    for i in range (0,n):
        x[i] = rt[0][i][0]
        y[i] = rt[0][i][1]
    return x,y,  

def update(j):
    for i in range (0,n):
        x[i] = rt[j][i][0]
        y[i] = rt[j][i][1]
    points = ax.scatter(x[:],y[:],c='r')
    return x,y

anim = animation.FuncAnimation(fig, update, frames=tmax, interval=50,blit=True)

2 个答案:

答案 0 :(得分:1)

我意识到furas' answers为您的问题提供了解决方法,但这里有更多关于您的问题的解释。

首先,blitting。如果您想使用blitting,请使用update()函数needs to return a list of updated artists。您将返回两个numpy数组,但您应该return points,

关于绘制前一时间点保持点的第二个问题是由于您在每次迭代时重复调用ax.scatter()。与普通的matplotlib行为类似,如果在同一轴上进行两次scatter()次调用,最终会得到两组点。

动画的一般建议是在初始化阶段创建一个艺术家(无论是使用Line2D的{​​{1}}对象还是plot()的{​​{1}}) ,然后在更新功能中更新此艺术家的属性(颜色,位置等),而无需创建新的艺术家。

考虑到所有这些因素,您的代码最终会出现:

PathCollection

enter image description here

答案 1 :(得分:0)

使用abc??????????...?删除前一点(当您使用?时)

malloc()