savemovie(frames, filename=None, fps=None, quality=None, dpi=None, writer=None, bitrate=None, interval=None, repeat=False, repeat_delay=None, blit=False, verbose=True, **kwargs)[source]#

Save a set of Matplotlib artists as a movie.

Note: in most cases, it is preferable to use sc.animation().

  • frames (list) – The list of frames to animate

  • filename (str) – The name (or full path) of the file; expected to end with mp4 or gif (default movie.mp4)

  • fps (int) – The number of frames per second (default 10)

  • quality (string) – The quality of the movie, in terms of dpi (default “high” = 300 dpi)

  • dpi (int) – Instead of using quality, set an exact dpi

  • writer (str or object) – Specify the writer to be passed to (default “ffmpeg”)

  • bitrate (int) – The bitrate. Note, may be ignored; best to specify in a writer and to pass in the writer as an argument

  • interval (int) – The interval between frames; alternative to using fps

  • repeat (bool) – Whether or not to loop the animation (default False)

  • repeat_delay (bool) – Delay between repeats, if repeat=True (default None)

  • blit (bool) – Whether or not to “blit” the frames (default False, since otherwise does not detect changes )

  • verbose (bool) – Whether to print statistics on finishing.

  • kwargs (dict) – Passed to


A Matplotlib animation object


import pylab as pl
import sciris as sc

# Simple example (takes ~5 s)
frames = [pl.plot(pl.cumsum(pl.randn(100))) for i in range(20)] # Create frames
sc.savemovie(frames, 'dancing_lines.gif') # Save movie as medium-quality gif

# Complicated example (takes ~15 s)
nframes = 100 # Set the number of frames
ndots = 100 # Set the number of dots
axislim = 5*pl.sqrt(nframes) # Pick axis limits
dots = pl.zeros((ndots, 2)) # Initialize the dots
frames = [] # Initialize the frames
old_dots = sc.dcp(dots) # Copy the dots we just made
fig = pl.figure(figsize=(10,8)) # Create a new figure
for i in range(nframes): # Loop over the frames
    dots += pl.randn(ndots, 2) # Move the dots randomly
    color = pl.norm(dots, axis=1) # Set the dot color
    old = pl.array(old_dots) # Turn into an array
    plot1 = pl.scatter(old[:,0], old[:,1], c='k') # Plot old dots in black
    plot2 = pl.scatter(dots[:,0], dots[:,1], c=color) # Note: Frames will be separate in the animation
    pl.xlim((-axislim, axislim)) # Set x-axis limits
    pl.ylim((-axislim, axislim)) # Set y-axis limits
    kwargs = {'transform':pl.gca().transAxes, 'horizontalalignment':'center'} # Set the "title" properties
    title = pl.text(0.5, 1.05, f'Iteration {i+1}/{nframes}', **kwargs) # Unfortunately pl.title() can't be dynamically updated
    pl.xlabel('Latitude') # But static labels are fine
    pl.ylabel('Longitude') # Ditto
    frames.append((plot1, plot2, title)) # Store updated artists
    old_dots = pl.vstack([old_dots, dots]) # Store the new dots as old dots
sc.savemovie(frames, 'fleeing_dots.mp4', fps=20, quality='high') # Save movie as a high-quality mp4

Version: 2019aug21