【问题标题】:Matplotlib 3d scatter animation - How to update properlyMatplotlib 3d scatter 动画 - 如何正确更新
【发布时间】:2020-05-27 21:01:03
【问题描述】:

我正在尝试使用 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()

【问题讨论】:

  • 您希望一行点出现在另一行之后吗?还是您希望所有线条随着时间的推移而变长?所以this不是你想要的?
  • 随着时间的推移,所有行加在一起的时间越来越长。我想用它来模拟重力。

标签: python matplotlib animation 3d


【解决方案1】:

您的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。

在您当前的更新中,您绘制了粒子的所有迭代,直到 num data[:, 0:num, :],而不是所有粒子的迭代直到 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)

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

【讨论】:

  • 这个解决方案效果很好。你能告诉我如何为不同的线条指定颜色吗? colors=[...] 似乎不起作用,也不像这样:` 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])`
猜你喜欢
  • 1970-01-01
  • 2016-02-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多