3

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() 
3
  • does it work if you don't call plt.close() before plt.show()? Commented Sep 20, 2022 at 23:49
  • Yes, but the previous plot does not disappear. And then there are several plots together and the image is confused. I wanted the next one to "erase" the previous one Commented Sep 21, 2022 at 0:14
  • I see. yeah you need to plot using the same axis object, not using plt.plot. I think you need to essentially grab the objects in the figure/axis and either clear or manipulate them. matplotlib's animation tools are super confusing to me tbh but I know you can't just create a ton of figures. Commented Sep 21, 2022 at 0:14

1 Answer 1

2

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:

enter image description here

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:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.