Animations#

%matplotlib inline

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

rc('animation', html='html5')

The animation class includes a function FuncAnimation that incorporations a user-specified function to update the figure for each frame of the animation. The result is an animation object which is subsequently called to actually produce the desired animation.

Step 1. Create the background frame.#

The following cell creates a background frame for the animation. These are standard matplotlib graphics commands, but where we have kept a reference to the resulting objects. The objects include fig for the figure object, ax1 and ax2 for each of the two plotting axes, and then txt_title, line1, line2, pt1, and line3 for graphical elements that will be updated in each frame of the animation.

# create a figure and axes
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(8,3))

# set up the subplots as needed
ax1.set_xlim(( 0, 2))            
ax1.set_ylim((-2, 2))
ax1.set_xlabel('Time')
ax1.set_ylabel('Magnitude')

ax2.set_xlim((-2,2))
ax2.set_ylim((-2,2))
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_title('Phase Plane')

# create objects that will change in the animation. These are
# initially empty, and will be given new values for each frame in the animation.
#Note the commas! that is because ax.plot returns a list of 2D line objects
txt_title = ax1.set_title('')
line1, = ax1.plot([], [], 'b', lw=2)     
line2, = ax1.plot([], [], 'r', lw=2)
pt1,   = ax2.plot([], [], 'g.', ms=20)
line3, = ax2.plot([], [], 'y', lw=2)

ax1.legend(['sin','cos']);
../_images/cb8201f93e076268c639909c3c12d507bdbebbf1d135be83d06661e5ef321304.png

Step 2. Define a function to draw each frame#

The animiation function is a function you define to draw individual frames in the animation. The variable n will be the frame number. The function draws the frame by resetting the data values for the global objects txt_title, line1, line2, pt1, and line3 that were defined above.

# animation function. This is called sequentially
def drawframe(n):
    
    x = np.linspace(0, 2, 1000)
    y1 = np.sin(2 * np.pi * (x - 0.01 * n))
    y2 = np.cos(2 * np.pi * (x - 0.01 * n))
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    line3.set_data(y1[0:50],y2[0:50])
    pt1.set_data(y1[0],y2[0])
    txt_title.set_text('Frame = {0:4d}'.format(n))
    
    return (line1,line2) #once line1 and line2 updated other global objects update too

Step 3. Create the Animation Object#

The animation class includes a function FuncAnimation that incorporations a user-specified function to update the figure for each frame of the animation. The result is an animation object which is subsequently called to actually produce the desired animation.

# blit=True re-draws only the parts that have changed.
anim = animation.FuncAnimation(fig, 
                               drawframe, 
                               frames=100, 
                               interval=20, 
                               blit=True)

anim
/var/folders/g4/3dkh7n1s0bjbl1tm3bgvvdsm0000gn/T/ipykernel_9309/841757530.py:10: MatplotlibDeprecationWarning: Setting data with a non sequence type is deprecated since 3.7 and will be remove two minor releases later
  pt1.set_data(y1[0],y2[0])
/var/folders/g4/3dkh7n1s0bjbl1tm3bgvvdsm0000gn/T/ipykernel_9309/841757530.py:10: MatplotlibDeprecationWarning: Setting data with a non sequence type is deprecated since 3.7 and will be remove two minor releases later
  pt1.set_data(y1[0],y2[0])
fig, ax = plt.subplots()
xdata, ydata = [], []

ln, = ax.plot([], [], 'ro')
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1);

def update(frame):
    
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    
    return ln,

ani = animation.FuncAnimation(fig, 
                              update, 
                              frames=np.linspace(0, 2*np.pi, 128),
                              blit=True)
ani
../_images/9a0ee02f29b32dafe47523dd0abe50c6e086e16577ab9baf3b61b5d38d8b8a0d.png