Saving and displaying movies and dynamic figures
It is insanely useful to create movies to illustrate a talk, blog post or just to include in a notebook:
In [1]:
from IPython.display import HTML
HTML('<center><video controls autoplay loop src="../files/2016-11-15_noise.mp4" width=61.8%/></center>')
Out[1]:
For years I have used a custom made solution made around saving single frames and then calling ffmpeg
to save that files to a movie file. That function (called anim_save
had to be maintained accross different libraries to reflect new needs (going to WEBM and MP4 formats for instance). That made the code longer than necessary and had not its place in a scientific library.
Here, I show how to use the animation
library from matplotlib to replace that
There quite a few pages on the web describing a possible alternative:
In [2]:
import numpy as np
image = np.random.rand(64, 16, 128)
from IPython.display import display, clear_output, HTML, Image
In [3]:
import sys
import matplotlib.pyplot as plt
from matplotlib import animation, rc
animation.rcParams['animation.writer'] = 'ffmpeg'
# First set up the figure, the axis, and the plot element we want to animate
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 2))
plt.close()
ax.xlim = (0, image.shape[1])
ax.ylim = (0, image.shape[2])
ax.set_xticks([])
ax.set_yticks([])
img = ax.imshow(image[:, :, 0].T, cmap='gray')
img.set_interpolation('nearest')
def animate(i):
#img = ax.imshow(image[:, :, i].T, cmap='gray')
img.set_data(image[:, :, i].T)
#ax.xaxis.set_visible(False)
#ax.yaxis.set_visible(False)
clear_output(wait=True)
print ('It: %i'%i)
sys.stdout.flush()
return (img,)
# call the animator. blit=True means only re-draw the parts that have changed.
# *interval* draws a new frame every *interval* milliseconds.
anim = animation.FuncAnimation(fig, animate, frames=image.shape[-1], interval=50, blit=True)
HTML(anim.to_html5_video())
Out[3]:
The same anim
object can be used to save the movie as a file:
In [4]:
help(anim.save)