I am trying to make an animated plot to show the behavior of a simple harmonic oscillator. I would like for this animation to be a combination of the following two plots. That is, I would like the red square to go up and down, and on the same plot I would like the blue line to progressively be displayed.
that is what I am having issues with. I cannot get my code to animate them both at the same time
This is the code I used to get the square to move up and down
%matplotlib notebook
import itertools
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
plt.rcParams["figure.figsize"] = 9,6
x_0, v_0, k, m = 1,2,1,2
omega = np.sqrt(k/m)
def HA(t):
xt = x_0*np.cos(omega*t) + (v_0/omega)*np.sin(omega*t)
return np.array([t, xt])
# create a figure with an axes
fig, ax = plt.subplots()
# set the axes limits
ax.axis([0.0,50,-4,4])
# create a point in the axes
point, = ax.plot(0,x_0, marker="s", color = 'red', markersize=20)
t_vector = np.linspace(0,50, 100)
xt_vector = x_0*np.cos(omega*t_vector) + (v_0/omega)*np.sin(omega*t_vector)
# Updating function, to be repeatedly called by the animation
def update(t):
#Point coordinates
t,xt = HA(t)
point.set_data([0],[xt])
return point
ani = animation.FuncAnimation(fig, update, interval=500, blit=True, repeat=True,frames=t_vector.size)
plt.axhline(y=0.0, color='black', linestyle='--', label = "Equilibrium")
plt.xlabel(r'$t$', fontsize=18)
plt.ylabel(r"$x(t)$", fontsize=16)
plt.legend()
#ani.save('Square.mp4', writer = 'ffmpeg', fps = 10)
plt.show()
And this is the code I used for the line
plt.rcParams["figure.figsize"] = 9,6
x_0, v_0, k, m = 1,2,1,2
omega = np.sqrt(k/m)
def HA(t):
xt = x_0*np.cos(omega*t) + (v_0/omega)*np.sin(omega*t)
return np.array([t, xt])
# create a figure with an axes
fig, ax = plt.subplots()
# set the axes limits
ax.axis([0.0,50,-4,4])
line, = ax.plot([], [], color="blue")
t_vector = np.linspace(0,50, 100)
xt_vector = x_0*np.cos(omega*t_vector) + (v_0/omega)*np.sin(omega*t_vector)
# Updating function, to be repeatedly called by the animation
def update(t):
line.set_data(t_vector[:t], xt_vector[:t])
return line
ani = animation.FuncAnimation(fig, update, interval=500, blit=True, repeat=True,frames=t_vector.size)
plt.axhline(y=0.0, color='black', linestyle='--', label = "Equilibrium")
plt.xlabel(r'$t$', fontsize=18)
plt.ylabel(r"$x(t)$", fontsize=16)
plt.legend()
#ani.save('Line.mp4', writer = 'ffmpeg', fps = 10)
plt.show()
I tried to just combine them both, but although this does not give any error, the resulting plot does not move. I am a rookie when it comes to animations with matplotlib, I checked the similar questions I could find, but none helped me. I could not extend their answers to get something useful for me.
plt.rcParams["figure.figsize"] = 9,6
x_0, v_0, k, m = 1,2,1,2
omega = np.sqrt(k/m)
def HA(t):
xt = x_0*np.cos(omega*t) + (v_0/omega)*np.sin(omega*t)
return np.array([t, xt])
# create a figure with an axes
fig, ax = plt.subplots()
ax.axis([0.0,50,-4,4])
# create a point in the axes
point, = ax.plot(0,x_0, marker="s", color = 'red', markersize=20)
line, = ax.plot([], [], color="blue")
t_vector = np.linspace(0,50, 100)
xt_vector = x_0*np.cos(omega*t_vector) + (v_0/omega)*np.sin(omega*t_vector)
# Updating function, to be repeatedly called by the animation
def update(t):
t,xt = HA(t)
line.set_data(t_vector[:t], xt_vector[:t])
point.set_data([0],[xt])
return line, point
ani = animation.FuncAnimation(fig, update, interval=500, blit=True, repeat=True,frames=t_vector.size)
plt.axhline(y=0.0, color='black', linestyle='--', label = "Equilibrium")
plt.xlabel(r'$t$', fontsize=18)
plt.ylabel(r"$x(t)$", fontsize=16)
plt.legend()
plt.show()
Could you help me, please?
I tried to just combine them both, but although this does not give any error, the resulting plot does not move.
In the update function, after t, xt = HA(t)
, t
is a float. You'll have to cast it back to an integer value for t_vector[:t]
and xt_vector[:t]
to work.
def update(t):
t,xt = HA(t)
t = int(t)
line.set_data(t_vector[:t], xt_vector[:t])
point.set_data([0],[xt])
return line, point
Note that it would probably make more sense for HA()
function to only return the xt
value rather than np.array([t, xt])
.
Doing this small edit, I obtain a working animation:
However, assuming that the red rectangle should follow the tip of the blue line along the Y-axis, this does not look good.
This is because the line is plotted from xt_vector
and the rectangle from the xt
value (returned by the HA()
function). Both formulas are the same but the t
differs: xt_vector
is computed for t
in np.linspace(0, 50, 100)
while xt
is computed for t
in np.range(0, nb_frame)
(nb_frame
= 100 here).
Bottom line: changing the update
function as follow should work
def update(t):
line.set_data(t_vector[:t], xt_vector[:t])
point.set_data([0], [xt_vector[t]])
return line, point