使用 matplotlib 动画点

Animate points with matplotlib

我想要10个移动点。我使用了下面的代码。我正在试验我不太了解的 matplotlib

from matplotlib import pyplot as plt
import numpy as np
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

# second option - move the point position at every frame
def update_point(n, x, y, z, point):
    point.set_data(np.array([x[n], y[n]]))
    point.set_3d_properties(z[n], 'z')
    return point

def x(i):
    return np.cos(t*i)

for i in range(10):
    t=np.arange(0, 2*np.pi, 2*np.pi/100)
    y=np.sin(t)
    z=t/(2.*np.pi)
    point, = ax.plot([x(i)[0]], [y[0]], [z[0]], 'o')
    ani=animation.FuncAnimation(fig, update_point, 99, fargs=(x(i), y, z, point))

ax.legend()
ax.set_xlim([-1.5, 1.5])
ax.set_ylim([-1.5, 1.5])
ax.set_zlim([-1.5, 1.5])

plt.show()

我希望如果我把x变成i的一个函数,那么我在for循环中就会有10个点,但是什么也没有发生。只有一点在移动。我做错了什么?

首先,将动画对象 anim 放入循环中,因此不仅 point 数据而且动画对象也会被重复覆盖。为了便于使用,让我们将数据点放入 numpy 数组中,其中行代表时间,列代表您想要设置动画的不同点。然后,我们根据 t 数组计算 xyz 数组(为了美观,沿着长度为 2*pi 的列进行无缝循环,每列移动以使点均匀分布)并在每个动画步骤中简单地更新 xyz 数据 row-wise。与您的脚本密切相关,这看起来像:

from matplotlib import pyplot as plt
import numpy as np
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

num_of_points = 7
num_of_frames = 50

t=np.linspace(0, 2*np.pi, num_of_frames, endpoint=False)[:, None] + np.linspace(0, 2*np.pi, num_of_points, endpoint=False)[None, :]
x=np.cos(t)
y=np.sin(t)
z=np.sin(t)*np.cos(t)

points, = ax.plot([], [], [], 'o')


def update_points(n):
    points.set_data(np.array([x[n, :], y[n, :]]))
    points.set_3d_properties(z[n, :], 'z')
    return points,

ax.set_xlim([-1.5, 1.5])
ax.set_ylim([-1.5, 1.5])
ax.set_zlim([-1.5, 1.5])


ani=animation.FuncAnimation(fig, update_points, num_of_frames, interval=10, blit=True, repeat=True)
plt.show()

示例输出:

当你选择动画线图(这些是没有可见线的动画标记,散点图在结构上不同),你不能使用不同的颜色,除非你单独绘制每个点。从好的方面来说,您可以使用 blitting 使动画更快。 关于您的代码的另一点 - 我建议不要使用 np.arange(),因为这会导致端点出现浮动问题。请改用 np.linspace()。默认情况下,包含端点,但在此脚本中,我们将其更改为 False,因此时间点 [0] 是时间点 [-1].[=33 之后 2*pi 循环中的下一步=]

对于不同的点特征,你只需要不同地填充你的数组即可。正如我所说,每个由每个点的列和不同时间点的行组成:

from matplotlib import pyplot as plt
import numpy as np
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

num_of_points = 4
num_of_frames = 100

#different rotation frequencies
t = np.linspace(0, 2*np.pi, num_of_frames, endpoint=False)[:, None] * np.arange(1, num_of_points+1)
#different x-y centers
x = np.cos(t) + np.asarray([0, 4, 0, 3])
y = np.sin(t) + np.asarray([0, 0, 5, 2])
#different heights
z = np.zeros(num_of_frames)[:, None] +  np.arange(num_of_points)
#point 4 gets random altitude fluctuations
z[:, 3] += np.random.random(num_of_frames)/5

points, = ax.plot([], [], [], 'o')


def update_points(n):
    points.set_data(np.array([x[n, :], y[n, :]]))
    points.set_3d_properties(z[n, :], 'z')
    return points,

ax.set_xlim([x.min()-0.5, x.max()+0.5])
ax.set_ylim([y.min()-0.5, y.max()+0.5])
ax.set_zlim([z.min()-0.5, z.max()+0.5])


ani=animation.FuncAnimation(fig, update_points, num_of_frames, interval=20, blit=True, repeat=True)
plt.show()

由于时间信息是从行号派生的,您也可以忘记 t 辅助数组,直接用所需的或随机数据如下例所示。然而,对于动画,您必须确保状态之间的平滑过渡,因此沿轴 0 的增量变化是必不可少的。

...
num_of_points = 4
num_of_frames = 100

#random walk
x = np.random.random((num_of_frames, num_of_points))-0.4
y = np.random.random((num_of_frames, num_of_points))-0.3
z = np.random.random((num_of_frames, num_of_points))-0.5
x[:] = x.cumsum(axis=0)
y[:] = y.cumsum(axis=0)
z[:] = z.cumsum(axis=0)

points, = ax.plot([], [], [], 'o')
...