动画绘图“列表”对象没有“set_data”属性,即使我在遵循针对其他类似问题给出的建议?

2024-10-02 20:44:20 发布

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

让我先让大家知道,我对编程还是有点陌生,所以我确信我的代码在某些部分可能相当低效,有一些潜在的令人生厌的行。我事先道歉

不管怎么说,我正试图编写一个2D物理模拟器,模拟给定一组初始条件的两个天体之间的相互作用,然后为它们的轨迹设置动画。问题是,当我运行代码时,会出现以下错误:AttributeError: 'list' object has no attribute 'set_data',特别是引用了init()中的line.set_data([],[])命令。这个错误指向我在下面标记的第61行(我删掉了一些不必要的注释&肯定弄乱了下面代码段的行号)。这是我的密码:

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

# ->> Initialize Figure <<-
fig = plt.figure()                                  # creates figure window
ax = plt.axes(xlim=(x[0],x[-1]),ylim=(y[0],y[-1]))  # creates axis object
plotColors = ("blue","red","green","black") # colors to use in plots (qty. must match or exceed numBodies)
line, = ax.plot([],[],lw=2)                 # creates blank line object
lines = []                                  # list that contains line objects for simulated bodies
numBodies = 2                               # number of bodies to intitialize (not necessarily simulate)
numArgs = 2                                 # DO NOT CHANGE: number of bodies to simulate
xBody1,xBody2 = [],[]                       # tracks x-coordinates for both simulated bodies
yBody1,yBody2 = [],[]                       # tracks y-coordinates for both simulated bodies

print("-- One --")

# ->> Initialize list of line objects for all bodies <<-
for i in range(numArgs):
    line_obj = ax.plot([],[],lw=2,color=plotColors[i])
    lines.append(line_obj)

print("-- Two --")

# ->> Initialize Animation Frame Initialization Function <<-
def init():
    for line in lines:
        line.set_data([],[])  #............................................<<<<<<< LINE 61 <<<<<<<
    return lines

print("-- Three --")

# ->> Initialize Animation Function (called sequentially) <<-
def animate(i):
        
    xList = [xBody1,xBody2]     # contains x-coordinate data for each body
    yList = [yBody1,yBody2]     # contains y-coordinate data for each body
    
    for num,line in enumerate(lines):           # for index in range(0,1):
        line.set_data(xList[num],yList[num])    # set data for each line separately
    
    plt.pause(0.1)
    return lines

# ->> Initialize Numerical Calculation Sequence <<-
def calculate(lastP,lastV,lastA):               # calculates each iteration of movements
    x1 = lastP[0] + lastV[0]*dt + 0.5*lastA[0]*np.square(dt)
    y1 = lastP[1] + lastV[1]*dt + 0.5*lastA[1]*np.square(dt)
    x2 = lastP[2] + lastV[2]*dt + 0.5*lastA[2]*np.square(dt)
    y2 = lastP[3] + lastV[3]*dt + 0.5*lastA[3]*np.square(dt)
    vx1 = lastV[0] + lastA[0]*dt
    vy1 = lastV[1] + lastA[1]*dt
    vx2 = lastV[2] + lastA[2]*dt
    vy2 = lastV[3] + lastA[3]*dt
    fx1 = G*m1*m2/np.square(x2-x1)
    fy1 = G*m1*m2/np.square(y2-y1)
    fx2 = G*m1*m2/np.square(x1-x2)
    fy2 = G*m1*m2/np.square(y1-y2)
    ax1 = fx1/m1
    ay1 = fy1/m1
    ax2 = fx2/m2
    ay2 = fy2/m2
    pos = [x1,y1,x2,y2]
    vel = [vx1,vy1,vx2,vy2]
    force = [fx1,fy1,fx2,fy2]
    acc = [ax1,ay1,ax2,ay2]
    return pos,vel,force,acc

# ->> Initialize Simulation Function
def simulate(sPos,sVel,sAcc):     # handles calculations & data management for animation
    xx1,xx2 = [],[]
    yy1,yy2 = [],[]
    xx1.append(sPos[0])
    yy1.append(sPos[1])
    xx2.append(sPos[2])
    yy2.append(sPos[3])
    Pos,Vel,Force,Acc = calculate(sPos,sVel,sAcc)
    for t in range(N):
        lastPos = Pos
        lastVel = Vel
        lastAcc = Acc
        Pos,Vel,Force,Acc = calculate(lastPos,lastVel,lastAcc)
        xx1.append(Pos[0])
        yy1.append(Pos[1])
        xx2.append(Pos[2])
        yy2.append(Pos[3])
    return xx1,yy1,xx2,yy2

print("-- Four --")

# ->> Specify Simulation Quantities <<-
G = 1           # gravitational constant (actually equals 6.67430e-11)
tmin = 0
tmax = 10000
N = 20000
dt = (tmax-tmin)/N

# ->> Specify Initial Conditions <<-
m1 = 1000       # mass of body 1 (kg)
m2 = 1000       # mass of body 2 (kg)

x1s = 10        # starting x-coordinate of body 1
y1s = 90        # starting y-coordinate of body 1
x2s = 90        # starting x-coordinate of body 2
y2s = 10        # starting y-coordinate of body 2

fx1s = 0    # initial x-directed force on body 1 (N) at t=0-
fy1s = 0    # initial y-directed force on body 1 (N) at t=0-
fx2s = 0    # initial x-directed force on body 2 (N) at t=0-
fy2s = 0    # initial y-directed force on body 2 (N) at t=0-

ax1s = fx1s/m1  # initial x-acceleration of body 1 (m/s^2)
ay1s = fy1s/m1  # initial y-acceleration of body 1 (m/s^2)
ax2s = fx2s/m2  # initial x-acceleration of body 2 (m/s^2)
ay2s = fy2s/m2  # initial y-acceleration of body 2 (m/s^2)

vx1s = 0        # initial x-velocity of body 1 (m/s)
vy1s = 0        # initial y-velocity of body 1 (m/s)
vx2s = 0        # initial x-velocity of body 2 (m/s)
vy2s = 0        # initial y-velocity of body 2 (m/s)

# ->> Initialize Physics Vectors <<-
mass = [m1,m2]
Pos = [x1s,y1s,x2s,y2s]
xPos = [x1s,x2s]
yPos = [y1s,y2s]
Force = [fx1s,fy1s,fx2s,fy2s]
xForce = [fx1s,fx2s]
yForce = [fy1s,fy2s]
Acc = [ax1s,ay1s,ax2s,ay2s]
xAcc = [ax1s,ax2s]
yAcc = [ay1s,ay2s]
Vel = [vx1s,vy1s,vx2s,vy2s]
xVel = [vx1s,vx2s]
yVel = [vy1s,vy2s]

simulate(Pos,Vel,Acc)

print(type(line))
print("-- Five --")

# ->> ANIMATE SIMULATION <<-
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)
#anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()

下面是让我困惑的地方:我知道这个错误通常是在您“未能解包Line2D对象的列表”时出现的,如this question的答案中所述。要解决这个问题,您应该在试图“解包”的变量旁边加一个逗号。在本例中,当我朝代码段顶部初始化line时,我肯定包含了那个逗号。所以我很困惑为什么我会收到这个错误信息?作为参考,我一直遵循this example来创建动画情节,我相信我在很大程度上与他们的代码是一致的

此外,我创建了一些print()语句来帮助我查看代码执行的各个阶段。这是错误消息之前的输出外观:

-- One --
-- Two --
-- Three --
-- Four --
<class 'matplotlib.lines.Line2D'>
-- Five --

正如您所看到的,line变量在模拟开始之前是lines.Line2D类型的,这正是我们想要的(对吧?)。我怀疑一旦simulation()被调用,引擎盖下会发生一些奇怪的事情,但我没有足够的能力来引导这个过程

有人能帮我找出代码中的错误吗?谢谢


Tags: ofposfordatanplinedtbody