【问题标题】:Difficulty in using append function while animating in Matplotlib FuncAnimation在 Matplotlib FuncAnimation 中制作动画时难以使用附加函数
【发布时间】:2019-03-17 10:40:40
【问题描述】:

所以,我编写了一个简单的代码来使用 Matplotlib 的 FuncAnimation 创建一个动画图形。但是没有输出。 我认为错误出在“np.append”函数中,因为如果我给“animate”函数提供预制的 x、y、z 数组,代码就可以工作。但是,我不明白为什么这不起作用!

%matplotlib notebook

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

del_t = 0.01 ##Time-step value

x=np.array([0.0])
y=np.array([10.0])
z=np.array([0.0])

#These functions give how (x, y, z) co-ordinate
#changes with time
def dx_dt(x, y, z):
    return 10*(y-x)
def dy_dt(x, y, z):
    return -x*z + 28*x - y
def dz_dt(x, y, z):
    return x*y-(8/3)*z

#Runge-Kutta Method for numerical solution of differential equations
#These functions give next (x, y, z) co-ordinate
def next_xpt(x, y, z):
    k1 = dx_dt(x, y, z) * del_t
    k2 = dx_dt(x + k1/2, y, z) * del_t
    k3 = dx_dt(x + k2/2, y, z) * del_t
    k4 = dx_dt(x + k3, y, z) * del_t
    return x + (k1 + 2*k2 + 2*k3 + k4)/6
def next_ypt(x, y, z):
    k1 = dy_dt(x, y, z) * del_t
    k2 = dy_dt(x, y + k1/2, z) * del_t
    k3 = dy_dt(x, y + k2/2, z) * del_t
    k4 = dy_dt(x, y + k3, z) * del_t
    return y + (k1 + 2*k2 + 2*k3 + k4)/6
def next_zpt(x, y, z):
    k1 = dz_dt(x, y, z) * del_t
    k2 = dz_dt(x, y, z + k1/2) * del_t
    k3 = dz_dt(x, y, z + k2/2) * del_t
    k4 = dz_dt(x, y, z + k3) * del_t
    return z + (k1 + 2*k2 + 2*k3 + k4)/6

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

#Creating a line object
line, = ax.plot3D([0.0],[10.0],[0.0],'-b') 

ax.set_xlim3d(-30,30)
ax.set_xlabel("X")
ax.set_ylim3d(-30,30)
ax.set_ylabel("Y")
ax.set_zlim3d(-30,30)
ax.set_zlabel("Z")
ax.set_title("Lorenz Strange Attractor")

def animate(i, x, y, z, line):
    np.append(x, next_xpt(x[i], y[i], z[i]))
    np.append(y, next_ypt(x[i], y[i], z[i]))
    np.append(z, next_zpt(x[i], y[i], z[i]))
    line.set_data(x[:i+1],y[:i+1])
    line.set_3d_properties(z[:i+1])
    return line

ani = animation.FuncAnimation(fig, animate, fargs = (x, y, z, line), interval=50, blit=False)

【问题讨论】:

  • 重新阅读 np.append 的文档。它不像列表追加那样工作
  • 感谢您的回复。但是,我读过它们。我想我用于 np.append 的格式是正确的,因为我单独检查了它。这里,x 或 y 或 z 是 ndarray,“next_xpt”或“next_ypt”或“next_zpt”是返回浮点数的函数。
  • np.append 这个名字让用户误以为它像列表追加方法一样就地运行。这只是np.concatenate 的一个覆盖功能。在您的情况下,收集列表中的值可能会更快更简单。
  • 请注意,数值方法不是 RK4,而是一些复杂的方法来实现 1 阶方法,与显式欧拉方法相当。您需要将一个耦合系统求解为一个耦合系统。
  • @LutzL 感谢您的建议!拜托,你能帮我解决这个问题并告诉我更多细节吗?

标签: python python-3.x numpy matplotlib animation


【解决方案1】:

您需要将追加的结果保存在数组xyz 中。您看到它附加的原因是因为您最有可能以交互方式测试它。但是正如@hpaulj 提到的,为了您的目的,您必须将附加的数组存储在函数中。此外,您必须将x, y, z 声明为global 以反映更改以避免IndexError。要初始化线对象,您可以定义一个init 函数,然后只需在您的FuncAnimation 中传递可迭代索引i

docs 说(强调我的)

返回:追加:ndarray

带有附加到轴的值的 arr 副本。请注意,追加不会就地发生:分配并填充了一个新数组

您必须存储 新数组

# Initizlise x, y, z here

def init():
    line.set_data([], [])
    line.set_3d_properties([])
    return line,

# dx_dt, dy_dt, dz_dt etc. functions here 

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

#Creating a line object
line, = ax.plot3D([0.0],[10.0],[0.0],'-b') 

# Setting axes limits here    

def animate(i):
    global x, y, z
    x = np.append(x, next_xpt(x[i], y[i], z[i]))
    y = np.append(y, next_ypt(x[i], y[i], z[i]))
    z = np.append(z, next_zpt(x[i], y[i], z[i]))
    line.set_data(x[:i+1],y[:i+1])
    line.set_3d_properties(z[:i+1])
    return line,

ani = animation.FuncAnimation(fig, animate, init_func=init, interval=50, blit=False)

【讨论】:

  • 感谢您的回答。你正确地指出了这一点。我实现了这一点,但我仍然不明白为什么,但数组没有得到更新。错误仍然显示索引 1 超出了大小为 1 的数组的范围。
  • @AdityaDutta:我明白了,这可能是因为你的数组 x、y、z 是在函数外部定义的,所以每次退出函数时,你的 x、y、z 都会丢失前一个 x 的内存,y,z。您可以尝试将global x, y, z 添加为def animate 中的第一行,看看是否仍然出现此错误?
  • 显示错误:name 'x' is parameter and global
  • 是的,这行得通!你太棒了!我明白了。正如你在上一条评论中所说的那样。我不应该使用 x,y,z 作为最后一个错误的根源的参数。即使我使用 xs,ys,zs 作为参数,然后在 animate 中将 x,y,z 声明为全局变量,它也能正常工作!
  • 我也试过你的方法。但目前的答案非常简单,变量较少
猜你喜欢
  • 2021-10-27
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多