Matplotlib 3D散点图动画 - 如何正确更新

3

我试图使用matplotlib在3D散点动画中绘制粒子。我尝试修改官方的3D线条动画示例来实现这一点。然而,我的代码没有使点运动,而是一次性呈现了它们。我无法弄清楚问题所在。非常感谢任何帮助或提示。

最小可重现示例:

import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
import numpy as np




def Gen_RandPrtcls():
    n = 10
    x = np.random.normal(size=(n,3))*5
    # m = np.repeat(1. / n, n)

    # Computing trajectory
    data = [x]
    nbr_iterations = 300
    for iteration in range(nbr_iterations):
        # data.append(data[-1] + GravAccel(data[-1], m))
        data.append(data[-1]*1.01)

    return data


def update_prtcls(num, dataPrtcls, parts):
    for prtcl, data in zip(parts, dataPrtcls):
        # NOTE: there is no .set_data() for 3 dim data...
        prtcl.set_data(data[:num][:,0:1])
        prtcl.set_3d_properties(data[:num][:,2])
    return parts

# Attaching 3D axis to the figure
fig = plt.figure()
ax = p3.Axes3D(fig)

# Fifty parts of random 3-D parts
data = Gen_RandPrtcls()

# NOTE: Can't pass empty arrays into 3d version of plot()
parts = [ax.plot(dat[:,0], dat[:,1], dat[:,2], marker='.', linestyle="None")[0] for dat in data]

# Setting the axes properties
ax.set_xlim3d([-10.0, 10.0])
ax.set_xlabel('X')

ax.set_ylim3d([-10.0, 10.0])
ax.set_ylabel('Y')

ax.set_zlim3d([-10.0, 10.0])
ax.set_zlabel('Z')

ax.set_title('3D Test')

# Creating the Animation object
prtcl_ani = animation.FuncAnimation(fig, update_prtcls, 25, fargs=(data, parts),
                                   interval=50, blit=False)

plt.show()


你想让一个点的行出现在另一个点的后面吗? 还是你想让所有的行一起随着时间变长? 所以,这个链接不是你想要的? - scleronomic
所有的线条随着时间的推移都会变得越来越长。我想将其用于重力模拟。 - FPisker
1个回答

3
您已经将您的数据结构与您预期的不同顺序进行了构建。
import numpy as np

def Gen_RandPrtcls(n_particles, n_iterations):
    x = np.random.normal(size=(n_particles, 3))*5

    # Computing trajectory
    data = [x]
    for iteration in range(n_iterations):
        # data.append(data[-1] + GravAccel(data[-1], m))
        data.append(data[-1]*1.01)
    return data

data = Gen_RandPrtcls(n_particles=10, n_iterations=300)
data = np.array(data)  # (n_iterations, n_particles, 3)

data 的第一维是 iterations,第二维是不同的 particles,第三维是 spacial coordinates

在您当前的更新中,您为粒子绘制了所有迭代次数,直到 num,即 data[:, 0:num, :],而不是所有粒子的迭代次数,即 data[0:num, :, :]

我对您的代码做了一些小改动。我同时绘制了所有粒子的轨迹,从第一个迭代开始。因此,我不必循环遍历粒子。(如果所有粒子应该显示为相同的颜色 [marker, ...],这将非常有效。否则,您将拥有每个粒子的 LineObject。但逻辑应该是相同的)。

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation

fig = plt.figure()
ax = p3.Axes3D(fig)

# Plot the first position for all particles
h = ax.plot(*data[0].T, marker='.', linestyle='None')[0]
# Equivalent to
# h = ax.plot(data[0, :, 0], data[0, :, 1], data[0, :, 2], 
#             marker='.', linestyle='None')[0]

# Setting the axes properties
ax.set_xlim3d([-100.0, 100.0])
ax.set_xlabel('X')

ax.set_ylim3d([-100.0, 100.0])
ax.set_ylabel('Y')

ax.set_zlim3d([-100.0, 100.0])
ax.set_zlabel('Z')
ax.set_title('3D Test')

def update_particles(num):
    # Plot the iterations up to num for all particles
    h.set_xdata(data[:num, :, 0].ravel())
    h.set_ydata(data[:num, :, 1].ravel())
    h.set_3d_properties(data[:num, :, 2].ravel())
    return h

prtcl_ani = animation.FuncAnimation(fig, update_particles, frames=301, 
                                    interval=10)

这里是结果。 希望有所帮助。

编辑:

如果您想要粒子使用不同的颜色,您需要将它们分别绘制:

colormap = plt.cm.tab20c
colors = [colormap(i) for i in np.linspace(0, 1, n_particles)]
h_particles = [ax.plot(*data[:1, i].T, marker='.', c=colors[i], ls='None')[0]
               for i in range(n_particles)]


def update_particles(num):
    for i, h in enumerate(h_particles):
        h.set_xdata(data[:num, i, 0])
        h.set_ydata(data[:num, i, 1])
        h.set_3d_properties(data[:num, i, 2])
    return h_particles

这个解决方案非常好。你能告诉我如何为不同的线条指定颜色吗?colors=[...]似乎不起作用,而像这样的sth也不行:colormap = plt.cm.tab20c colors = [colormap(i) for i in np.linspace(0, 1, n_prtcls)] for i, j in enumerate(ax.lines): print(colors[i]) j.set_color(colors[i]) - FPisker
当我尝试跟随这个时,我得到了“Path3DCollection”对象没有属性“set_xdata”的错误。 - kjohnsen
你使用的matplotlib版本是什么? - scleronomic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接