Matplotlib 3d散点动画如何正确更新

2024-10-03 11:21:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用matplotlib在3d散射动画中绘制粒子。我已经尝试修改官方的3d线图动画示例来实现这一点。但是,我的代码不会设置点的动画,而是一次渲染所有点。我搞不清楚问题是什么。任何帮助或提示都将不胜感激

MRE:

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


Tags: inimportfordatamatplotlibasnp动画
1条回答
网友
1楼 · 发布于 2024-10-03 11:21:50

您以不同于预期的顺序构建了data

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

在当前更新中,为所有粒子绘制到numdata[:, 0:num, :]的所有迭代,而不是绘制到numdata[0:num, :, :]的所有迭代

我对你的代码做了一些小改动。我同时绘制所有粒子的轨迹,从第一次迭代开始。 所以我不必在粒子上循环。(如果所有粒子都应使用相同的颜色[标记,…]显示,则此操作正常。否则,您将 每个粒子的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)

Here is the result. 希望有帮助

编辑:

如果希望粒子具有不同的颜色,则需要分别对其进行打印:

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

相关问题 更多 >