matplotlib animation won't animate sine function - python

I'm trying to animate the function with matplotlib:
But for some reason, when I write it like that in the animate function:
l = 0.5
k = (2 * np.pi)/l
f = 4
w = 2 * np.pi * f
y = np.sin(k * x + w * i)
It doesn't animate, only when I write it with numbers it animates:
y = np.sin(15*x - 62 * i)
What is the reason? Why can't I use the other form?
Relevant code:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)
# initialization function
def init():
line.set_data([], [])
return line,
# animation function
def animate(i):
x = np.linspace(0, 2, 1000)
l = 0.5
k = (2 * np.pi)/l
f = 4
w = 2 * np.pi * f
y = np.sin(k * x + w * i)
#y = np.sin(15*x - 62 * i)
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=300, interval=20, blit=True)
anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()
Thanks !!

The only problem is that your f is an integer and hence w is a multiple of 2 * np.pi. The function is essentially unchanged for integer i's. Change f to be non integer.

Related

How to generate an animation composed of several plots in python?

I'm having trouble plotting an animation with python. What I want to do is basically an animation that contains the superposition of many complete plots. In such a way that each frame will be a plot given by
plt.plot(r, Sevol[n])
The code and error displayed on the screen are below. Thanks for any help.
UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. anim, that exists until you have outputted the Animation using plt.show() or anim.save().
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
nr = 300
ri = 0
rf = 300
dr = (rf - ri) / (nr - 1)
nt = 1000
dt = 0.1
r = np.linspace(ri, rf, num=nr)
def rk3_step(t, h, y, f, *args):
k1 = h * f(t , y , *args)
k2 = h * f(t + h/2, y + 1/2 * k1 , *args)
k3 = h * f(t + h , y - k1 + 2 * k2, *args)
return y + 1/6*(k1 + 4*k2 + k3)
def rhs_perturb(t, u):
S = u.T[0]
S_dot = u.T[1]
F = u.T[2]
F_dot = u.T[3]
rhs = np.empty((nr, 4))
rhs[0] = np.array([S_dot[0],
(S[2] - 2 * S[1] + S[0]) / (dr ** 2), # + F[0],
F_dot[0],
- S[0] + (F[2] - 2 * F[1] + F[0]) / (dr ** 2)])
rhs[-1] = np.array([S_dot[-1],
(S[-1] - 2 * S[-2] + S[-3]) / (dr ** 2), # + F[-1],
F_dot[-1],
- S[-1] + (F[-1] - 2 * F[-2] + F[-3]) / (dr ** 2)])
for i in range(1, nr - 1):
rhs[i] = np.array([S_dot[i],
(S[i + 1] - 2 * S[i] + S[i - 1]) / (dr ** 2), # + F[i],
F_dot[i],
- S[i] + (F[i + 1] - 2 * F[i] + F[i - 1]) / (dr ** 2)])
return rhs
sigma = 3
r0 = 100
F = np.empty(nr)
F_dot = np.empty(nr)
S = np.empty(nr)
S_dot = np.empty(nr)
for i in range(nr):
F[i] = 0
F_dot[i] = 0
S_dot[i] = 0
S[i] = math.exp(-(r[i] - r0)**2 / sigma**2)
uin = np.block([[S], [S_dot], [F], [F_dot]]).T
u = np.copy(uin)
uaux = np.copy(uin)
nsave = 10
Sevol = np.empty((math.floor(nt/nsave),nr))
Sevol[0] = S
Fevol = np.empty((math.floor(nt/nsave),nr))
Fevol[0] = F
for n in range(nt):
uaux = rk3_step(n * dt, dt, u, rhs_perturb)
if np.any(np.isnan(uaux)):
break
u = uaux
if (n + 1) % nsave == 0:
Sevol[math.floor(n / nsave)] = u.T[0]
Fevol[math.floor(n / nsave)] = u.T[2]
fig = plt.figure()
plt.xlabel('r')
plt.xlabel('S')
plt.grid()
plt.xlim(ri, rf)
def animate(i):
numPlots = i //10 # how many plots (-1) will be shown based on the frame.
for n in range(numPlots):
plt.plot(r[n], Sevol[n], color='gold', markersize=3)
ani = FuncAnimation(fig, animate, frames=100, interval=10, blit = False, repeat = False)
plt.close()
plt.show()
I would suggest initializing your animations with a list of empty placeholders plots. In your case, it looks like you need 100 plots. And then update the data for plot i at each frame with the actual values.
Below is what the animation code looks like:
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter
N_plots=100
fig,ax = plt.subplots()
color = plt.cm.viridis(np.linspace(0, 1, N_plots))
lns=[ax.plot([],[],color=color[i]) for i in range(N_plots)]
lns=[lns[i][0] for i in range(N_plots)]
plt.xlabel('r')
plt.ylabel('S')
plt.grid()
plt.xlim(ri, rf)
plt.ylim(-0.25, 1)
def animate(i):
lns[i].set_data(r,Sevol[i])
return lns
ani = FuncAnimation(fig, animate, frames=N_plots, interval=100)
And the output gives:
EDIT:
Note that if instead of superimposing the curves you just want to replace them by the next, you can simply use set_data to update your one plot.
See code below:
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter
N_plots=100
fig,ax = plt.subplots()
color = plt.cm.viridis(np.linspace(0, 1, N_plots))
ln,=ax.plot([],[])
plt.xlabel('r')
plt.ylabel('S')
plt.grid()
plt.xlim(ri, rf)
plt.ylim(-0.25, 1)
def animate(i):
ln.set_data(r,Sevol[i])
ln.set_color(color[i])
return ln
ani = FuncAnimation(fig, animate, frames=N_plots, interval=100)
And the output gives:

Simulate a rotating equal triangle by Python

can anyone help me, i stuck at the last step
[]
this is my code. then for the last step to rotate it, i didnt know what should i do to rotate the triangle
This is the perfect case for an animation:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib.animation import FuncAnimation
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
to=np.arange(0,2*np.pi,0.01)
x = r * np.cos(np.radians(theta))
y = r * np.sin(np.radians(theta))
xo = r * np.cos(to); yo = r * np.sin(to)
fig, ax = plt.subplots()
ax.plot(xo,yo)
# create artists: they will be used to update the position
# of the points being rendered
triangle, = ax.plot(x,y)
vertices = ax.scatter(x,y)
lim = r * 1.25
ax.set_xlim([-lim, lim]);ax.set_ylim([-lim, lim])
ax.set_aspect("equal")
w = 2
T = 2 * np.pi / w
# this defines the time steps of the animation
dt = np.linspace(0, 10 * T, num=500)
def animate(i):
x = r * np.cos(np.radians(theta) + w * dt[i])
y = r * np.sin(np.radians(theta) + w * dt[i])
# update the position of the points to be rendered
triangle.set_data(x, y)
vertices.set_offsets(np.stack([x, y]).T)
ax.set_title("Rotation #%s" % int(w * dt[i] / (2 * np.pi) + 1))
ani = FuncAnimation(fig, animate, frames=len(dt), repeat=False)
plt.show()
Check this out..
from IPython import display
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
w = 2
T = 2*np.pi/w
dt = np.linspace(0, 10*T, num=10) #increase num for more finely distributed rotations.
for d in dt:
to=np.arange(0,2*np.pi,0.01)
x = r*np.sin(np.radians(theta + d))
y=r*np.cos(np.radians(theta + d))
xo=r*np.sin(to);yo=r*np.cos(to)
plt.plot(xo,yo)
plt.plot(x,y)
plt.scatter(x,y)
plt.xlim([-1, 1]);plt.ylim([-1,1])

Python function animation for two graphes (displayed after each other)

I have two data sets y1 = vol1 and y2 = vol2 for the same x range (0 to 5000 in steps of 10). I would like to use function animation in order to first animate y1 and after that animate y2 while the graph of y1 remains.
This is what I got from combing several examples (incl. this):
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
x = range(0, 5000, 10)
y1 = vol1
y2 = vol2
fig, ax = plt.subplots()
ax.set_xlim(0, 5000)
ax.set_ylim(0, 1000)
l1, = plt.plot([],[],'b-')
l2, = plt.plot([],[],'r-')
def init1():
return l1,
def init2():
return l2,
def animate1(i):
l1.set_data(x[:i],y1[:i])
return l1,
def animate2(i):
l2.set_data(x[:i-500],y2[:i-500])
return l2,
def gen1():
i = 0
while(i<500):
yield i
i += 1
def gen2():
j = 500
while(j<1000):
yield j
j += 1
ani1 = FuncAnimation(fig, animate1, gen1, interval=1, save_count=len(x),
init_func=init1, blit=True,
repeat=False)
ani2 = FuncAnimation(fig, animate2, gen2, interval=1, save_count=len(x),
init_func=init2, blit=True,
repeat=False)
# ani.save('ani.mp4')
plt.show()
My idea was to make two 'counters' gen1 andgen2 but since I have the same x values for both data sets, I tried to compensate that in the animate2 function. But this doesn't work..
Obviously, I'm quite new to python and I appreciate any help.
I would do just one animation, keeping track of the frame with respect to the line length:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation, FFMpegWriter
x = np.linspace(0, 2 * np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
k = 0
fig, ax = plt.subplots()
ax.set_xlim(0, x.max())
ax.set_ylim(-1.5, 1.5)
l1, = plt.plot([],[],'b-')
l2, = plt.plot([],[],'r-')
def animate1(i):
global k
if k > 2 * len(x):
# reset if "repeat=True"
k = 0
if k <= len(x):
l1.set_data(x[:k],y1[:k])
else:
l2.set_data(x[:k - len(x)],y2[:k - len(x)])
k += 1
ani1 = FuncAnimation(fig, animate1, frames=2*len(x), interval=1, repeat=True)
writer = FFMpegWriter(fps=10)
ani1.save("test.mp4", writer=writer)
plt.show()

Animating a 3d vector - ValueError: too many values to unpack (expected 2)

I am trying to animate a rotating 3d vector. everything more or less works, expect my update-funtion for the "FuncAnimation"-part of the code. When I run the code, I get the following error message:
"Error in line "the line with the code "vector.set_data(u[i], v[i], w[i])" ValueError: too many values to unpack (expected 2)"
I have no idea what i am doing wrong, can anybody help?
from matplotlib import animation, rc
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10, 10))
ax = fig.gca(projection='3d')
t_end = 20
u0 = [1 / np.sqrt(2)]
v0 = [1 / np.sqrt(2)]
w0 = [0]
y0 = u0 + v0 + w0
print(y0)
def ode45(t, y):
u = np.array(y[0])
v = np.array(y[1])
w = np.array(y[2])
omega = np.pi / 2
delta = 0
dudt = delta * v
dvdt = -delta * u + omega * w
dwdt = - omega * v
return [dudt, dvdt, dwdt]
mysol = solve_ivp(ode45, [0, t_end], y0)
u = mysol.y[0]
v = mysol.y[1]
w = mysol.y[2]
r = np.mean(u ** 2 + v ** 2 + w ** 2)
print(r)
theta = np.linspace(0, 2 * np.pi, 101)
phi = np.linspace(0, np.pi, 101)
z = r * np.outer(np.ones(np.size(theta)), np.cos(phi))
x = r * np.outer(np.cos(theta), np.sin(phi))
y = r * np.outer(np.sin(theta), np.sin(phi))
ax.plot_surface(x, y, z, alpha=0.2, color='gray')
vector, = ax.plot([], [], [])
def update(i):
vector.set_data(u[i], v[i], w[i])
return vector
ax.plot([0], [0], [0], 'ro')
ax.plot(u, v, w, color='blue')
steps = 100 * t_end
anim = animation.FuncAnimation(fig, update, frames=t_end, interval=1, blit=True)
anim
plt.show()
This line is creating a tuple:
vector, = ax.plot([], [], [])
Pyplot .plot() returns a list (typically of lines or markers) to plot or adjust. I don't think it returns a tuple. So, in
def update(i):
vector.set_data(u[i], v[i], w[i])
return vector
The vector.set_data(u[i], v[i], w[i]) is calling set_data on a tuple of (ax.plot.lines, None). I think this might be the problem.
EDIT:
You should be able to fix it with this:
vector = ax.plot([], [], [])

How can I animate a 3d object in numpy

I have the following code :
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
p3.autoscale = True
ax = p3.Axes3D(fig)
ax.grid(True)
ax.set_xlim(-100, 100)
ax.set_ylim(-100, 100)
ax.set_zlim(-100, 100)
u = np.r_[0:2*np.pi:100j]
v = np.r_[0:np.pi:100j]
scale = 15
x = scale * np.outer(np.cos(u),np.sin(v))
y = scale * np.outer(np.sin(u),np.sin(v))
z = scale * np.outer(np.ones(np.size(u)),np.cos(v))
Line3DCollection_1 = ax.plot_wireframe(x,y,z, rstride=50, cstride=50)
Line3DCollection_2 = ax.plot_wireframe(x + 50,y,z, rstride=50, cstride=50)
# initialization function: plot the background of each frame
def init():
return Line3DCollection_1,
def animate(i):
print("frame :" + str(i))
x = 50 * np.sin(np.radians(i))
y = 50 * np.cos(np.radians(i))
path = plt.plot([x],[y],[0], 'bo')
return path
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=360, interval=0.1, blit=True)
plt.show()
This will produce 2 spheres and a path that I want one of the spheres to take, but I'm not sure how to include this in the animation, I can animate the path, but not the 'Line3DCollection_2' sphere.
Does anyone have any ideas?
Thanks.

Categories

Resources