在Python

时间:2018-03-05 21:38:44

标签: python animation matplotlib

我正在尝试为2d路径制作动画,我希望它有一种“消失的尾巴”,在任何给定的时间,它只显示最后5个(例如)粒子。

我目前所拥有的远非如此:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML

sample_path = np.random.uniform(size=(100,2))

fig, ax = plt.subplots()

x = np.arange(-1, 1, 0.01)        # x-array
line, = ax.plot(sample_path[0,0], sample_path[0,1])

def connect(i):
    (x0,y0) = sample_path[i-1,:]
    (x1,y1) = sample_path[i,:]
    plt.plot([x0,x1],[y0,y1],'ro-')
    return line,

def init():
    line.set_ydata(np.ma.array(x, mask=True))
    return line,

ani = animation.FuncAnimation(fig, connect, np.arange(1, 100), init_func=init,
interval=200, blit=True)
HTML(ani.to_html5_video())

这保留了“完整的尾巴”,即在k步之后,它显示了所有前k个位置。

有没有办法调整我所拥有的内容,以便动画只显示粒子的最新历史记录?

2 个答案:

答案 0 :(得分:2)

您可能希望更新该行,而不是向绘图中添加许多新点。选择5个最近的点可以通过索引来完成,例如,

sample_path[i-5:i, 0]

完整示例,我们注意不要使用否定索引,也不要使用blit(如果保存动画则没有意义)。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc

r = np.sin(np.linspace(0,3.14,100))
t = np.linspace(0, 10, 100)
sample_path = np.c_[r*(np.sin(t)+np.cos(t)), r*(np.cos(t)-np.sin(t))]/1.5

fig, ax = plt.subplots()

line, = ax.plot(sample_path[0,0], sample_path[0,1], "ro-")

def connect(i):
    start=max((i-5,0))
    line.set_data(sample_path[start:i,0],sample_path[start:i,1])
    return line,

ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
ani = animation.FuncAnimation(fig, connect, np.arange(1, 100), interval=200)
plt.show()

enter image description here

答案 1 :(得分:1)

在技术上不如ImportanceOfBeingErnest的答案好,但它仍然可以完成工作并且看起来非常酷,只需绘制最新点并清除旧点。我添加了一些并加速了,因为我觉得它用更长的路径看起来更好。

def connect(i):
    #clear current points
    plt.clf()

    #prevent axis auto-resizing
    plt.plot(0,0)
    plt.plot(1,1)

    #generate points to plot
    (x0,y0) = sample_path[i-8,:]
    (x1,y1) = sample_path[i-7,:]
    (x2,y2) = sample_path[i-6,:]
    (x3,y3) = sample_path[i-5,:]
    (x4,y4) = sample_path[i-4,:]
    (x5,y5) = sample_path[i-3,:]
    (x6,y6) = sample_path[i-2,:]
    (x7,y7) = sample_path[i-1,:]
    (x8,y8) = sample_path[i,:]

    #plot old points
    plt.plot([x0,x1,x2,x3,x4,x5,x6,x7],[y0,y1,y2,y3,y4,y5,y6,y7],'ro-')

    #plot new point in blue
    plt.plot([x7,x8],[y7,y8],'bo-')
    return line,

def init():
    line.set_ydata(np.ma.array(x, mask=True))
    return line,

ani = animation.FuncAnimation(fig, connect, frames=np.arange(1, 100), 
init_func=init,
interval=50, blit=True)
HTML(ani.to_html5_video())