Reputation: 23
I have a similar problem to this one: Animate a python pyplot by moving a point plotted via scatter. The given values are positions (q) with corresponding velocities (v). Now I want to animate the shift in position over time for each point. My attempt
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
q = [[-4.32, -2.17, -2.25, 4.72, 2.97, 1.74],
[ 2.45, 9.73, 7.45,4.01,3.42, 1.80],[-1.40, -1.76, -3.08,-9.94,-3.13,-1.13]]
v = [[ 0.0068,0.024, -0.014,-0.013, -0.0068,-0.04],[ 0.012,
0.056, -0.022,0.016, 0.0045, 0.039],
[-0.0045, 0.031, 0.077,0.0016, -0.015,-0.00012]]
t=np.arange(0, 1000, 2)
x=q[0]
y=q[1]
z=q[2]
s=v[0]
u=v[1]
w=v[2]
points, = ax.plot(x, y, z, '*')
def update_points(t, x, y, z, points):
point = []
for i in range(0,len(x)-1,1):
points.set_data(np.array([x[i]+s[i]*t*5, y[i]+u[i]*t*5]))
points.set_3d_properties(z[i]+w[i]*t*5, 'z')
return point
ani=animation.FuncAnimation(fig, update_points, 10, fargs=(x, y, z, points))
plt.show()
does not work properly. The first image of the animation shows all points, but afterward, only the movement of the last point is simulated. The error happens in the defined update_points function because it seems like only the values for the last I are stored. Does anybody know how I have to change the code that all points are moving simultaneously?
Upvotes: 1
Views: 6383
Reputation: 23
Thank you very much! It works now
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
q = [[-4.32, -2.17, -2.25, 4.72, 2.97, 1.74],
[ 2.45, 9.73, 7.45,4.01,3.42, 1.80],[-1.40, -1.76, -3.08,-9.94,-3.13,-1.13]]
v = [[ 0.0068,0.024, -0.014,-0.013, -0.0068,-0.04],[ 0.012,
0.056, -0.022,0.016, 0.0045, 0.039],
[-0.0045, 0.031, 0.077,0.0016, -0.015,-0.00012]]
x=np.array(q[0])
y=np.array(q[1])
z=np.array(q[2])
s=np.array(v[0])
u=np.array(v[1])
w=np.array(v[2])
points, = ax.plot(x, y, z, '*')
txt = fig.suptitle('')
def update_points(t, x, y, z, points):
txt.set_text('num={:d}'.format(t))
new_x = x + s * t
new_y = y + u * t
new_z = z + w * t
print('t:', t)
# update properties
points.set_data(new_x,new_y)
points.set_3d_properties(new_z, 'z')
# return modified artists
return points,txt
ani=animation.FuncAnimation(fig, update_points, frames=15, fargs=(x, y, z, points))
ax.set_xlabel("x [pc]")
ax.set_ylabel("y [pc]")
ax.set_zlabel('z [pc]')
plt.show()
Upvotes: 1
Reputation: 40667
Your problem is that you are only passing one set of coordinates to set_data()
/set_3d_properties
, and therefore only one point remains. You need to update all the coordinates of all your points, and then update points
with those arrays.
I could not figure out exactly how you were doing your math in the update function, so here's an example using random fluctuations:
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
q = [[-4.32, -2.17, -2.25, 4.72, 2.97, 1.74],
[ 2.45, 9.73, 7.45,4.01,3.42, 1.80],[-1.40, -1.76, -3.08,-9.94,-3.13,-1.13]]
v = [[ 0.0068,0.024, -0.014,-0.013, -0.0068,-0.04],[ 0.012,
0.056, -0.022,0.016, 0.0045, 0.039],
[-0.0045, 0.031, 0.077,0.0016, -0.015,-0.00012]]
x=np.array(q[0])
y=np.array(q[1])
z=np.array(q[2])
s=np.array(v[0])
u=np.array(v[1])
w=np.array(v[2])
points, = ax.plot(x, y, z, '*')
txt = fig.suptitle('')
def update_points(num, x, y, z, points):
txt.set_text('num={:d}'.format(num)) # for debug purposes
# calculate the new sets of coordinates here. The resulting arrays should have the same shape
# as the original x,y,z
new_x = x+np.random.normal(1,0.1, size=(len(x),))
new_y = y+np.random.normal(1,0.1, size=(len(y),))
new_z = z+np.random.normal(1,0.1, size=(len(z),))
# update properties
points.set_data(new_x,new_y)
points.set_3d_properties(new_z, 'z')
# return modified artists
return points,txt
ani=animation.FuncAnimation(fig, update_points, frames=10, fargs=(x, y, z, points))
plt.show()
Upvotes: 4