sciris.sc_plotting

Extensions to Matplotlib, including 3D plotting and plot customization.

Highlights:
  • plot3d(): easy way to render 3D plots

  • boxoff(): turn off top and right parts of the axes box

  • commaticks(): convert labels from “10000” and “1e6” to “10,000” and “1,000,0000”

  • SIticks(): convert labels from “10000” and “1e6” to “10k” and “1m”

  • maximize(): make the figure fill the whole screen

  • savemovie(): save a sequence of figures as an MP4 or other movie

  • fonts(): list available fonts or add new ones

Functions

SIticks

Apply SI tick formatting to one axis of a figure (e.g., 34k instead of 34000)

ax3d

Create a 3D axis to plot in.

bar3d

Plot 2D data as 3D bars

boxoff

Removes the top and right borders ("spines") of a plot.

commaticks

Use commas in formatting the y axis of a figure (e.g., 34,000 instead of 34000).

dateformatter

Format the x-axis to use a given date formatter.

datenumformatter

Format a numeric x-axis to use dates.

emptyfig

The emptiest figure possible

fig3d

Shortcut for creating a figure with 3D axes.

figlayout

Alias to both fig.set_tight_layout() and fig.subplots_adjust().

fonts

List available fonts, or add new ones.

get_rows_cols

Get the number of rows and columns needed to plot N figures.

getrowscols

Get the number of rows and columns needed to plot N figures.

loadfig

Load a plot from a file and reanimate it.

loadmetadata

Read metadata from a saved image; currently only PNG and SVG are supported.

maximize

Maximize the current (or supplied) figure.

orderlegend

Create a legend with a specified order, or change the order of an existing legend.

plot3d

Plot 3D data as a line

reanimateplots

Reconnect plots (actually figures) to the Matplotlib backend.

savefig

Save a figure, including metadata

savefigs

Save the requested plots to disk.

savemovie

Save a set of Matplotlib artists as a movie.

scatter3d

Plot 3D data as a scatter

separatelegend

Allows the legend of a figure to be rendered in a separate window instead

setaxislim

A small script to determine how the y limits should be set. Looks at all data (a list of arrays) and computes the lower limit to use, e.g.::.

setxlim

Alias for sc.setaxislim(which='x')

setylim

Alias for sc.setaxislim(which='y').

stackedbar

Create a stacked bar chart.

surf3d

Plot 2D data as a 3D surface

Classes

ScirisDateFormatter

An adaptation of Matplotlib's ConciseDateFormatter with a slightly different approach to formatting dates.

animation

A class for storing and saving a Matplotlib animation.

fig3d(num=None, returnax=False, figkwargs=None, axkwargs=None, **kwargs)[source]

Shortcut for creating a figure with 3D axes.

Usually not invoked directly; kwargs are passed to pl.figure()

ax3d(fig=None, ax=None, returnfig=False, silent=False, elev=None, azim=None, figkwargs=None, axkwargs=None, **kwargs)[source]

Create a 3D axis to plot in.

Usually not invoked directly; kwags are passed to add_subplot()

plot3d(x, y, z, c=None, fig=None, ax=None, returnfig=False, figkwargs=None, axkwargs=None, plotkwargs=None, **kwargs)[source]

Plot 3D data as a line

Parameters
  • x (arr) – x coordinate data

  • y (arr) – y coordinate data

  • z (arr) – z coordinate data

  • c (str/tuple) – color, can be any of the types accepted by matplotlib’s plot()

  • fig (fig) – an existing figure to draw the plot in

  • ax (axes) – an existing axes to draw the plot in

  • returnfig (bool) – whether to return the figure, or just the axes

  • figkwargs (dict) – passed to figure()

  • axkwargs (dict) – passed to axes()

  • plotkwargs (dict) – passed to plot()

  • kwargs (dict) – also passed to plot()

Example:

x,y,z = pl.rand(3,10)
sc.plot3d(x, y, z)
scatter3d(x, y, z, c=None, fig=None, returnfig=False, figkwargs=None, axkwargs=None, plotkwargs=None, **kwargs)[source]

Plot 3D data as a scatter

Parameters
  • x (arr) – x coordinate data

  • y (arr) – y coordinate data

  • z (arr) – z coordinate data

  • c (arr) – color data

  • fig (fig) – an existing figure to draw the plot in

  • ax (axes) – an existing axes to draw the plot in

  • returnfig (bool) – whether to return the figure, or just the axes

  • figkwargs (dict) – passed to figure()

  • axkwargs (dict) – passed to axes()

  • plotkwargs (dict) – passed to plot()

  • kwargs (dict) – also passed to plot()

Example:

x,y,z = pl.rand(3,10)
sc.scatter3d(x, y, z, c=z)
surf3d(data, x=None, y=None, fig=None, returnfig=False, colorbar=True, figkwargs=None, axkwargs=None, plotkwargs=None, **kwargs)[source]

Plot 2D data as a 3D surface

Parameters
  • data (arr) – 2D data

  • x (arr) – 1D vector or 2D grid of x coordinates (optional)

  • y (arr) – 1D vector or 2D grid of y coordinates (optional)

  • fig (fig) – an existing figure to draw the plot in

  • ax (axes) – an existing axes to draw the plot in

  • returnfig (bool) – whether to return the figure, or just the axes

  • colorbar (bool) – whether to plot a colorbar

  • figkwargs (dict) – passed to figure()

  • axkwargs (dict) – passed to axes()

  • plotkwargs (dict) – passed to plot()

  • kwargs (dict) – also passed to plot()

Example:

data = sc.smooth(pl.rand(30,50))
sc.surf3d(data)
bar3d(data, fig=None, returnfig=False, cmap='viridis', figkwargs=None, axkwargs=None, plotkwargs=None, **kwargs)[source]

Plot 2D data as 3D bars

Parameters
  • data (arr) – 2D data

  • fig (fig) – an existing figure to draw the plot in

  • cmap (str) – colormap name

  • ax (axes) – an existing axes to draw the plot in

  • returnfig (bool) – whether to return the figure, or just the axes

  • colorbar (bool) – whether to plot a colorbar

  • figkwargs (dict) – passed to figure()

  • axkwargs (dict) – passed to axes()

  • plotkwargs (dict) – passed to plot()

  • kwargs (dict) – also passed to plot()

Example:

data = pl.rand(5,4)
sc.bar3d(data)
stackedbar(x=None, values=None, colors=None, labels=None, transpose=False, flipud=False, cum=False, barh=False, **kwargs)[source]

Create a stacked bar chart.

Parameters
  • x (array) – the x coordinates of the values

  • values (array) – the 2D array of values to plot as stacked bars

  • colors (list/arr) – the color of each set of bars

  • labels (list) – the label for each set of bars

  • transpose (bool) – whether to transpose the array prior to plotting

  • flipud (bool) – whether to flip the array upside down prior to plotting

  • cum (bool) – whether the array is already a cumulative sum

  • barh (bool) – whether to plot as a horizontal instead of vertical bar

  • kwargs (dict) – passed to pl.bar()

Example:

values = pl.rand(3,5)
sc.stackedbar(values, labels=['bottom','middle','top'])
pl.legend()

New in version 2.0.4.

boxoff(ax=None, which=None, removeticks=True)[source]

Removes the top and right borders (“spines”) of a plot.

Also optionally removes the tick marks, and flips the remaining ones outside. Can be used as an alias to pl.axis('off') if which='all'.

Parameters
  • ax (Axes) – the axes to remove the spines from (if None, use current)

  • which (str/list) – a list or comma-separated string of spines: ‘top’, ‘bottom’, ‘left’, ‘right’, or ‘all’ (default top & right)

  • removeticks (bool) – whether to also remove the ticks from these spines

  • flipticks (bool) – whether to flip remaining ticks out

Examples:

pl.figure()
pl.plot([2,5,3])
sc.boxoff()

fig, ax = pl.subplots()
pl.plot([1,4,1,4])
sc.boxoff(ax=ax, which='all')

fig = pl.figure()
pl.scatter(np.arange(100), pl.rand(100))
sc.boxoff('top, bottom')

New in version 1.3.3: ability to turn off multiple spines; removed “flipticks” arguments

setaxislim(which=None, ax=None, data=None)[source]

A small script to determine how the y limits should be set. Looks at all data (a list of arrays) and computes the lower limit to use, e.g.:

sc.setaxislim([np.array([-3,4]), np.array([6,4,6])], ax)

will keep Matplotlib’s lower limit, since at least one data value is below 0.

Note, if you just want to set the lower limit, you can do that with this function via:

sc.setaxislim()
setxlim(data=None, ax=None)[source]

Alias for sc.setaxislim(which='x')

setylim(data=None, ax=None)[source]

Alias for sc.setaxislim(which='y').

Example:

pl.plot([124,146,127])
sc.setylim() # Equivalent to pl.ylim(bottom=0)
commaticks(ax=None, axis='y', precision=2, cursor_precision=0)[source]

Use commas in formatting the y axis of a figure (e.g., 34,000 instead of 34000).

To use something other than a comma, set the default separator via e.g. sc.options(sep='.').

Parameters
  • ax (any) – axes to modify; if None, use current; else can be a single axes object, a figure, or a list of axes

  • axis (str/list) – which axis to change (default ‘y’; can accept a list)

  • precision (int) – shift how many decimal places to show for small numbers (+ve = more, -ve = fewer)

  • cursor_precision (int) – ditto, for cursor

Example:

data = pl.rand(10)*1e4
pl.plot(data)
sc.commaticks()

See http://stackoverflow.com/questions/25973581/how-to-format-axis-number-format-to-thousands-with-a-comma-in-matplotlib

New in version 1.3.0: ability to use non-comma thousands separator
New in version 1.3.1: added “precision” argument
New in version 2.0.0: ability to set x and y axes simultaneously
SIticks(ax=None, axis='y', fixed=False)[source]

Apply SI tick formatting to one axis of a figure (e.g., 34k instead of 34000)

Parameters
  • ax (any) – axes to modify; if None, use current; else can be a single axes object, a figure, or a list of axes

  • axis (str) – which axes to change (default ‘y’)

  • fixed (bool) – use fixed-location tick labels (by default, update them dynamically)

Example:

data = pl.rand(10)*1e4
pl.plot(data)
sc.SIticks()
getrowscols(n, nrows=None, ncols=None, ratio=1, make=False, tight=True, remove_extra=True, **kwargs)[source]

Get the number of rows and columns needed to plot N figures.

If you have 37 plots, then how many rows and columns of axes do you know? This function convert a number (i.e. of plots) to a number of required rows and columns. If nrows or ncols is provided, the other will be calculated. Ties are broken in favor of more rows (i.e. 7x6 is preferred to 6x7). It can also generate the plots, if make=True.

Note: sc.getrowscols() and sc.get_rows_cols() are aliases.

Parameters
  • n (int) – the number (of plots) to accommodate

  • nrows (int) – if supplied, keep this fixed and calculate the columns

  • ncols (int) – if supplied, keep this fixed and calculate the rows

  • ratio (float) – sets the number of rows relative to the number of columns (i.e. for 100 plots, 1 will give 10x10, 4 will give 20x5, etc.).

  • make (bool) – if True, generate subplots

  • tight (bool) – if True and make is True, then apply tight layout

  • remove_extra (bool) – if True and make is True, then remove extra subplots

  • kwargs (dict) – passed to pl.subplots()

Returns

A tuple of ints for the number of rows and the number of columns (which, of course, you can reverse)

Examples:

nrows,ncols = sc.get_rows_cols(36) # Returns 6,6
nrows,ncols = sc.get_rows_cols(37) # Returns 7,6
nrows,ncols = sc.get_rows_cols(100, ratio=2) # Returns 15,7
nrows,ncols = sc.get_rows_cols(100, ratio=0.5) # Returns 8,13 since rows are prioritized
fig,axs     = sc.getrowscols(37, make=True) # Create 7x6 subplots, using the alias
New in version 1.0.0.
New in version 1.2.0: “make”, “tight”, and “remove_extra” arguments
New in version 1.3.0: alias without underscores
get_rows_cols(n, nrows=None, ncols=None, ratio=1, make=False, tight=True, remove_extra=True, **kwargs)

Get the number of rows and columns needed to plot N figures.

If you have 37 plots, then how many rows and columns of axes do you know? This function convert a number (i.e. of plots) to a number of required rows and columns. If nrows or ncols is provided, the other will be calculated. Ties are broken in favor of more rows (i.e. 7x6 is preferred to 6x7). It can also generate the plots, if make=True.

Note: sc.getrowscols() and sc.get_rows_cols() are aliases.

Parameters
  • n (int) – the number (of plots) to accommodate

  • nrows (int) – if supplied, keep this fixed and calculate the columns

  • ncols (int) – if supplied, keep this fixed and calculate the rows

  • ratio (float) – sets the number of rows relative to the number of columns (i.e. for 100 plots, 1 will give 10x10, 4 will give 20x5, etc.).

  • make (bool) – if True, generate subplots

  • tight (bool) – if True and make is True, then apply tight layout

  • remove_extra (bool) – if True and make is True, then remove extra subplots

  • kwargs (dict) – passed to pl.subplots()

Returns

A tuple of ints for the number of rows and the number of columns (which, of course, you can reverse)

Examples:

nrows,ncols = sc.get_rows_cols(36) # Returns 6,6
nrows,ncols = sc.get_rows_cols(37) # Returns 7,6
nrows,ncols = sc.get_rows_cols(100, ratio=2) # Returns 15,7
nrows,ncols = sc.get_rows_cols(100, ratio=0.5) # Returns 8,13 since rows are prioritized
fig,axs     = sc.getrowscols(37, make=True) # Create 7x6 subplots, using the alias
New in version 1.0.0.
New in version 1.2.0: “make”, “tight”, and “remove_extra” arguments
New in version 1.3.0: alias without underscores
figlayout(fig=None, tight=True, keep=False, **kwargs)[source]

Alias to both fig.set_tight_layout() and fig.subplots_adjust().

Parameters
  • fig (Figure) – the figure (by default, use current)

  • tight (bool, or dict) – passed to fig.set_tight_layout(); default True

  • keep (bool) – if True, then leave tight layout on; else, turn it back off

  • kwargs (dict) – passed to fig.subplots_adjust()

Example:

fig,axs = sc.get_rows_cols(37, make=True, tight=False) # Create 7x6 subplots, squished together
sc.figlayout(bottom=0.3)

New in version 1.2.0.

maximize(fig=None, die=False)[source]

Maximize the current (or supplied) figure. Note: not guaranteed to work for all Matplotlib backends (e.g., agg).

Parameters
  • fig (Figure) – the figure object; if not supplied, use the current active figure

  • die (bool) – whether to propagate an exception if encountered (default no)

Example:

pl.plot([2,3,5])
sc.maximize()

New in version 1.0.0.

fonts(add=None, use=False, output='name', dryrun=False, rebuild=False, verbose=False, die=False, **kwargs)[source]

List available fonts, or add new ones. Alias to Matplotlib’s font manager.

Note: if the font is not available after adding it, set rebuild=True. However, note that this can be very slow.

Parameters
  • add (str/list) – path of the fonts or folders to add; if none, list available fonts

  • use (bool) – set the last-added font as the default font

  • output (str) – what to display the listed fonts as: options are ‘name’ (list of names, default), ‘path’ (dict of name:path), or ‘font’ (dict of name:font object)

  • dryrun (bool) – list fonts to be added rather than adding them

  • rebuild (bool) – whether to rebuild Matplotlib’s font cache (slow)

  • verbose (bool) – print out information on errors

  • die (bool) – whether to raise an exception if fonts can’t be added

  • kwargs (dict) – passed to matplotlib.font_manager.findSystemFonts()

Examples:

sc.fonts() # List available font names
sc.fonts(fullfont=True) # List available font objects
sc.fonts('myfont.ttf', use=True) # Add this font and immediately set to default
sc.fonts(['/folder1', '/folder2']) # Add all fonts in both folders
sc.fonts(rebuild=True) # Run this if added fonts aren't appearing
class ScirisDateFormatter(locator, formats=None, zero_formats=None, show_offset=False, show_year=True, **kwargs)[source]

An adaptation of Matplotlib’s ConciseDateFormatter with a slightly different approach to formatting dates. Specifically:

  • Years are shown below dates, rather than on the RHS

  • The day and month are always shown.

  • The cursor shows only the date, not the time

This formatter is not intended to be called directly – use sc.dateformatter() instead. It is also optimized for plotting dates, rather than times – for those, ConciseDateFormatter is better.

See sc.dateformatter() for explanation of arguments.

New in version 1.3.0.

format_data_short(value)[source]

Show year-month-day, not with hours and seconds

format_ticks(values)[source]

Append the year to the tick label for the first label, or if the year changes. This avoids the need to use offset_text, which is difficult to control.

dateformatter(ax=None, style='sciris', dateformat=None, start=None, end=None, rotation=None, locator=None, axis='x', **kwargs)[source]

Format the x-axis to use a given date formatter.

By default, this will apply the Sciris date formatter to the current x-axis. This formatter is a combination of Matplotlib’s Concise date formatter, and Plotly’s date formatter.

See also sc.datenumformatter() to convert a numeric axis to date labels.

Parameters
  • ax (axes) – if supplied, use these axes instead of the current one

  • style (str) – the style to use if the axis already uses dates; options are “sciris”, “auto”, “concise”, or a Formatter object

  • dateformat (str) – the date format (default '%Y-%b-%d'; not needed if x-axis already uses dates)

  • start (str/int) – if supplied, the lower limit of the axis

  • end (str/int) – if supplied, the upper limit of the axis

  • rotation (float) – rotation of the labels, in degrees

  • locator (Locator) – if supplied, use this instead of the default AutoDateLocator locator

  • axis (str) – which axis to apply to the formatter to (default ‘x’)

  • kwargs (dict) – passed to the date formatter (e.g., ScirisDateFormatter)

Examples:

# Reformat date data
pl.figure()
x = sc.daterange('2021-04-04', '2022-05-05', asdate=True)
y = sc.smooth(pl.rand(len(x)))
pl.plot(x, y)
sc.dateformatter()

# Configure with Matplotlib's Concise formatter
fig,ax = pl.subplots()
pl.plot(sc.date(np.arange(365), start_date='2022-01-01'), pl.randn(365))
sc.dateformatter(ax=ax, style='concise')
New in version 1.2.0.
New in version 1.2.2: “rotation” argument; renamed “start_day” to “start_date”
New in version 1.3.0: refactored to use built-in Matplotlib date formatting
New in version 1.3.2: “axis” argument
New in version 1.3.3: split sc.dateformatter() from sc.datenumformatter()
datenumformatter(ax=None, start_date=None, dateformat=None, interval=None, start=None, end=None, rotation=None)[source]

Format a numeric x-axis to use dates.

See also sc.dateformatter(), which is intended for use when the axis already has date data.

Parameters
  • ax (axes) – if supplied, use these axes instead of the current one

  • start_date (str/date) – the start day, either as a string or date object (not needed if x-axis already uses dates)

  • dateformat (str) – the date format (default '%Y-%b-%d'; not needed if x-axis already uses dates)

  • interval (int) – if supplied, the interval between ticks (not needed if x-axis already uses dates)

  • start (str/int) – if supplied, the lower limit of the axis

  • end (str/int) – if supplied, the upper limit of the axis

  • rotation (float) – rotation of the labels, in degrees

Examples:

# Automatically configure a non-date axis with default options
pl.plot(np.arange(365), pl.rand(365))
sc.datenumformatter(start_date='2021-01-01')

# Manually configure
fig,ax = pl.subplots()
ax.plot(np.arange(60), np.random.random(60))
formatter = sc.datenumformatter(start_date='2020-04-04', interval=7, start='2020-05-01', end=50, dateformat='%m-%d', ax=ax)
New in version 1.2.0.
New in version 1.2.2: “rotation” argument; renamed “start_day” to “start_date”
New in version 1.3.3: renamed from sc.dateformatter() to sc.datenumformatter()
savefig(filename, fig=None, dpi=None, comments=None, freeze=False, frame=2, folder=None, makedirs=True, die=True, verbose=True, **kwargs)[source]

Save a figure, including metadata

Wrapper for Matplotlib’s savefig() function which automatically stores metadata in the figure. By default, it saves (git) information from the calling function. Additional comments can be added to the saved file as well. These can be retrieved via sc.loadmetadata().

Metadata can be stored and retrieved for PNG or SVG. Metadata can be stored for PDF, but cannot be automatically retrieved.

Parameters
  • filename (str/Path) – name of the file to save to

  • fig (Figure) – the figure to save (if None, use current)

  • dpi (int) – resolution of the figure to save (default 200 or current default, whichever is higher)

  • comments (str) – additional metadata to save to the figure

  • freeze (bool) – whether to store the contents of pip freeze in the metadata (warning, slow)

  • frame (int) – which calling file to try to store information from (default, the file calling sc.savefig())

  • folder (str/Path) – optional folder to save to (can also be provided as part of the filename)

  • makedirs (bool) – whether to create folders if they don’t already exist

  • die (bool) – whether to raise an exception if metadata can’t be saved

  • verbose (bool) – if die is False, print a warning if metadata can’t be saved

  • kwargs (dict) – passed to fig.save()

Examples:

pl.plot([1,3,7])

sc.savefig('example1.png')
print(sc.loadmetadata('example1.png'))

sc.savefig('example2.png', comments='My figure', freeze=True)
sc.pp(sc.loadmetadata('example2.png'))

New in version 1.3.3.

loadmetadata(filename, load_all=False, die=True)[source]

Read metadata from a saved image; currently only PNG and SVG are supported.

Only for use with images saved with sc.savefig(). Metadata retrieval for PDF is not currently supported.

Parameters
  • filename (str) – the name of the file to load the data from

  • load_all (bool) – whether to load all metadata available in an image (else, just load what was saved by Sciris)

  • die (bool) – whether to raise an exception if the metadata can’t be found

Example:

pl.plot([1,2,3], [4,2,6])
sc.savefig('example.png')
sc.loadmetadata('example.png')
savefigs(figs=None, filetype=None, filename=None, folder=None, savefigargs=None, aslist=False, verbose=False, **kwargs)[source]

Save the requested plots to disk.

Parameters
  • figs (list) – the figure objects to save

  • filetype (str) – the file type; can be ‘fig’, ‘singlepdf’ (default), or anything supported by savefig()

  • filename (str) – the file to save to (only uses path if multiple files)

  • folder (str) – the folder to save the file(s) in

  • savefigargs (dict) – arguments passed to savefig()

  • aslist (bool) – whether or not return a list even for a single file

  • varbose (bool) – whether to print progress

Examples:

import pylab as pl
import sciris as sc
fig1 = pl.figure(); pl.plot(pl.rand(10))
fig2 = pl.figure(); pl.plot(pl.rand(10))
sc.savefigs([fig1, fig2]) # Save everything to one PDF file
sc.savefigs(fig2, 'png', filename='myfig.png', savefigargs={'dpi':200})
sc.savefigs([fig1, fig2], filepath='/home/me', filetype='svg')
sc.savefigs(fig1, position=[0.3,0.3,0.5,0.5])

If saved as ‘fig’, then can load and display the plot using sc.loadfig().

Version: 2018aug26

loadfig(filename=None)[source]

Load a plot from a file and reanimate it.

Example usage:

import pylab as pl
import sciris as sc
fig = pl.figure(); pl.plot(pl.rand(10))
sc.savefigs(fig, filetype='fig', filename='example.fig')

Later:

example = sc.loadfig('example.fig')
emptyfig(*args, **kwargs)[source]

The emptiest figure possible

separatelegend(ax=None, handles=None, labels=None, reverse=False, figsettings=None, legendsettings=None)[source]

Allows the legend of a figure to be rendered in a separate window instead

orderlegend(order=None, ax=None, handles=None, labels=None, reverse=None, **kwargs)[source]

Create a legend with a specified order, or change the order of an existing legend. Can either specify an order, or use the reverse argument to simply reverse the order. Note: you do not need to create the legend before calling this function; if you do, you will need to pass any additional keyword arguments to this function since it will override existing settings.

Parameters
  • order (list or array) – the new order of the legend, as from e.g. np.argsort()

  • ax (axes) – the axes object; if omitted, defaults to current axes

  • handles (list) – the legend handles; can be used instead of ax

  • labels (list) – the legend labels; can be used instead of ax

  • reverse (bool) – if supplied, simply reverse the legend order

  • kwargs (dict) – passed to ax.legend()

Examples:

pl.plot([1,4,3], label='A')
pl.plot([5,7,8], label='B')
pl.plot([2,5,2], label='C')
sc.orderlegend(reverse=True) # Legend order C, B, A
sc.orderlegend([1,0,2], frameon=False) # Legend order B, A, C with no frame
pl.legend() # Restore original legend order A, B, C
class animation(fig=None, filename=None, dpi=200, fps=10, imageformat='png', basename='animation', nametemplate=None, imagefolder=None, anim_args=None, save_args=None, frames=None, tidy=True, verbose=True, **kwargs)[source]

A class for storing and saving a Matplotlib animation.

See also sc.savemovie(), which works directly with Matplotlib artists rather than an entire figure. Depending on your use case, one is likely easier to use than the other. Use sc.animation() if you want to animate a complex figure including non-artist objects (e.g., titles and legends); use sc.savemovie() if you just want to animate a set of artists (e.g., lines).

This class works by saving snapshots of the figure to disk as image files, then reloading them either via ffmpeg or as a Matplotlib animation. While (slightly) slower than working with artists directly, it means that anything that can be rendered to a figure can be animated.

Note: the terms “animation” and “movie” are used interchangeably here.

Parameters
  • fig (fig) – the Matplotlib figure to animate (if none, use current)

  • filename (str) – the name of the output animation (default: animation.mp4)

  • dpi (int) – the resolution to save the animation at

  • fps (int) – frames per second for the animation

  • imageformat (str) – file type for temporary image files, e.g. ‘jpg’

  • basename (str) – name for temporary image files, e.g. ‘myanimation’

  • nametemplate (str) – as an alternative to imageformat and basename, specify the full name template, e.g. ‘myanimation%004d.jpg’

  • imagefolder (str) – location to store temporary image files; default current folder, or use ‘tempfile’ to create a temporary folder

  • anim_args (dict) – passed to matplotlib.animation.ArtistAnimation() or ffmpeg.input()

  • save_args (dict) – passed to matplotlib.animation.save() or ffmpeg.run()

  • tidy (bool) – whether to delete temporary files

  • verbose (bool) – whether to print progress

  • kwargs (dict) – also passed to matplotlib.animation.save()

Example:

anim = sc.animation()

pl.figure()
pl.seed(1)
repeats = 21
colors = sc.vectocolor(repeats, cmap='turbo')
for i in range(repeats):
    scale = 1/np.sqrt(i+1)
    x = scale*pl.randn(10)
    y = scale*pl.randn(10)
    label = str(i) if not(i%5) else None
    pl.scatter(x, y, c=[colors[i]], label=label)
    pl.title(f'Scale = 1/√{i}')
    pl.legend()
    sc.boxoff('all')
    anim.addframe()

anim.save('dots.mp4')
New in version 1.3.3.
New in version 2.0.0: ffmpeg option.
initialize()[source]

Handle additional initialization of variables

addframe(fig=None, *args, **kwargs)[source]

Add a frame to the animation – typically a figure object, but can also be an artist or list of artists

loadframes()[source]

Load saved images as artists

rmfiles()[source]

Remove temporary image files

save(filename=None, fps=None, dpi=None, engine='ffmpeg', anim_args=None, save_args=None, frames=None, tidy=None, verbose=True, **kwargs)[source]

Save the animation – arguments the same as sc.animation() and sc.savemovie(), and are described there

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().

Parameters
  • 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 matplotlib.animation.save() (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 matplotlib.animation.save()

Returns

A Matplotlib animation object

Examples:

import pylab as pl
import sciris as sc

# Simple example (takes ~5 s)
pl.figure()
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)
pl.figure()
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