J.R. Johansson (jrjohansson at gmail.com)

The latest version of this IPython notebook lecture is available at http://github.com/jrjohansson/scientific-python-lectures.

The other notebooks in this lecture series are indexed at http://jrjohansson.github.io.

Matplotlib is an excellent 2D and 3D graphics library for generating scientific figures. Some of the many advantages of this library include:

- Easy to get started
- Support for @@0@@ formatted labels and texts
- Great control of every element in a figure, including figure size and DPI.
- High-quality output in many formats, including PNG, PDF, SVG, EPS, and PGF.
- GUI for interactively exploring figures
*and*support for headless generation of figure files (useful for batch jobs).

One of the key features of matplotlib that I would like to emphasize, and that I think makes matplotlib highly suitable for generating figures for scientific publications is that all aspects of the figure can be controlled *programmatically*. This is important for reproducibility and convenient when one needs to regenerate the figure with updated data or change its appearance.

More information at the Matplotlib web page: http://matplotlib.org/

To get started using Matplotlib in a Python program, either include the symbols from the `pylab`

module (the easy way):

or import the `matplotlib.pyplot`

module under the name `plt`

(the tidy way):

The easiest way to get started with plotting using matplotlib is often to use the MATLAB-like API provided by matplotlib.

It is designed to be compatible with MATLAB's plotting functions, so it is easy to get started with if you are familiar with MATLAB.

To use this API from matplotlib, we need to include the symbols in the `pylab`

module:

A simple figure with MATLAB-like plotting API:

Loading output library...

Most of the plotting related functions in MATLAB are covered by the `pylab`

module. For example, subplot and color/symbol selection:

Loading output library...

The good thing about the pylab MATLAB-style API is that it is easy to get started with if you are familiar with MATLAB, and it has a minumum of coding overhead for simple plots.

However, I'd encourrage not using the MATLAB compatible API for anything but the simplest figures.

Instead, I recommend learning and using matplotlib's object-oriented plotting API. It is remarkably powerful. For advanced figures with subplots, insets and other components it is very nice to work with.

The main idea with object-oriented programming is to have objects that one can apply functions and actions on, and no object or program states should be global (such as the MATLAB-like API). The real advantage of this approach becomes apparent when more than one figure is created, or when a figure contains more than one subplot.

To use the object-oriented API we start out very much like in the previous example, but instead of creating a new global figure instance we store a reference to the newly created figure instance in the `fig`

variable, and from it we create a new axis instance `axes`

using the `add_axes`

method in the `Figure`

class instance `fig`

:

Loading output library...

Although a little bit more code is involved, the advantage is that we now have full control of where the plot axes are placed, and we can easily add more than one axis to the figure:

Loading output library...

If we don't care about being explicit about where our plot axes are placed in the figure canvas, then we can use one of the many axis layout managers in matplotlib. My favorite is `subplots`

, which can be used like this:

Loading output library...

Loading output library...

That was easy, but it isn't so pretty with overlapping figure axes and labels, right?

We can deal with that by using the `fig.tight_layout`

method, which automatically adjusts the positions of the axes on the figure canvas so that there is no overlapping content:

Loading output library...

Matplotlib allows the aspect ratio, DPI and figure size to be specified when the `Figure`

object is created, using the `figsize`

and `dpi`

keyword arguments. `figsize`

is a tuple of the width and height of the figure in inches, and `dpi`

is the dots-per-inch (pixel per inch). To create an 800x400 pixel, 100 dots-per-inch figure, we can do:

Loading output library...

The same arguments can also be passed to layout managers, such as the `subplots`

function:

Loading output library...

To save a figure to a file we can use the `savefig`

method in the `Figure`

class:

Here we can also optionally specify the DPI and choose between different output formats:

Matplotlib can generate high-quality output in a number formats, including PNG, JPG, EPS, SVG, PGF and PDF. For scientific papers, I recommend using PDF whenever possible. (LaTeX documents compiled with `pdflatex`

can include PDFs using the `includegraphics`

command). In some cases, PGF can also be good alternative.

Now that we have covered the basics of how to create a figure canvas and add axes instances to the canvas, let's look at how decorate a figure with titles, axis labels, and legends.

**Figure titles**

A title can be added to each axis instance in a figure. To set the title, use the `set_title`

method in the axes instance:

**Axis labels**

Similarly, with the methods `set_xlabel`

and `set_ylabel`

, we can set the labels of the X and Y axes:

**Legends**

Legends for curves in a figure can be added in two ways. One method is to use the `legend`

method of the axis object and pass a list/tuple of legend texts for the previously defined curves:

The method described above follows the MATLAB API. It is somewhat prone to errors and unflexible if curves are added to or removed from the figure (resulting in a wrongly labelled curve).

A better method is to use the `label="label text"`

keyword argument when plots or other objects are added to the figure, and then using the `legend`

method without arguments to add the legend to the figure:

The advantage with this method is that if curves are added or removed from the figure, the legend is automatically updated accordingly.

The `legend`

function takes an optional keyword argument `loc`

that can be used to specify where in the figure the legend is to be drawn. The allowed values of `loc`

are numerical codes for the various places the legend can be drawn. See http://matplotlib.org/users/legend_guide.html#legend-location for details. Some of the most common `loc`

values are:

Loading output library...

The following figure shows how to use the figure title, axis labels and legends described above:

Loading output library...

The figure above is functional, but it does not (yet) satisfy the criteria for a figure used in a publication. First and foremost, we need to have LaTeX formatted text, and second, we need to be able to adjust the font size to appear right in a publication.

Matplotlib has great support for LaTeX. All we need to do is to use dollar signs encapsulate LaTeX in any text (legend, title, label, etc.). For example, `"$y=x^3$"`

.

But here we can run into a slightly subtle problem with LaTeX code and Python text strings. In LaTeX, we frequently use the backslash in commands, for example `\alpha`

to produce the symbol @@0@@. But the backslash already has a meaning in Python strings (the escape code character). To avoid Python messing up our latex code, we need to use "raw" text strings. Raw text strings are prepended with an '`r`

', like `r"\alpha"`

or `r'\alpha'`

instead of `"\alpha"`

or `'\alpha'`

:

Loading output library...

We can also change the global font size and font family, which applies to all text elements in a figure (tick labels, axis labels and titles, legends, etc.):

Loading output library...

A good choice of global fonts are the STIX fonts:

Loading output library...

Or, alternatively, we can request that matplotlib uses LaTeX to render the text elements in the figure:

Loading output library...

With matplotlib, we can define the colors of lines and other graphical elements in a number of ways. First of all, we can use the MATLAB-like syntax where `'b'`

means blue, `'g'`

means green, etc. The MATLAB API for selecting line styles are also supported: where, for example, 'b.-' means a blue line with dots:

Loading output library...

We can also define colors by their names or RGB hex codes and optionally provide an alpha value using the `color`

and `alpha`

keyword arguments:

Loading output library...

Loading output library...

To change the line width, we can use the `linewidth`

or `lw`

keyword argument. The line style can be selected using the `linestyle`

or `ls`

keyword arguments:

Loading output library...

The appearance of the axes is an important aspect of a figure that we often need to modify to make a publication quality graphics. We need to be able to control where the ticks and labels are placed, modify the font size and possibly the labels used on the axes. In this section we will look at controling those properties in a matplotlib figure.

The first thing we might want to configure is the ranges of the axes. We can do this using the `set_ylim`

and `set_xlim`

methods in the axis object, or `axis('tight')`

for automatrically getting "tightly fitted" axes ranges:

Loading output library...

It is also possible to set a logarithmic scale for one or both axes. This functionality is in fact only one application of a more general transformation system in Matplotlib. Each of the axes' scales are set seperately using `set_xscale`

and `set_yscale`

methods which accept one parameter (with the value "log" in this case):

Loading output library...

We can explicitly determine where we want the axis ticks with `set_xticks`

and `set_yticks`

, which both take a list of values for where on the axis the ticks are to be placed. We can also use the `set_xticklabels`

and `set_yticklabels`

methods to provide a list of custom text labels for each tick location:

Loading output library...

There are a number of more advanced methods for controlling major and minor tick placement in matplotlib figures, such as automatic placement according to different policies. See http://matplotlib.org/api/ticker_api.html for details.

With large numbers on axes, it is often better use scientific notation:

Loading output library...

Loading output library...

Unfortunately, when saving figures the labels are sometimes clipped, and it can be necessary to adjust the positions of axes a little bit. This can be done using `subplots_adjust`

:

Loading output library...

With the `grid`

method in the axis object, we can turn on and off grid lines. We can also customize the appearance of the grid lines using the same keyword arguments as the `plot`

function:

Loading output library...

We can also change the properties of axis spines:

Loading output library...

Sometimes it is useful to have dual x or y axes in a figure; for example, when plotting curves with different units together. Matplotlib supports this with the `twinx`

and `twiny`

functions:

Loading output library...

Loading output library...

In addition to the regular `plot`

method, there are a number of other functions for generating different kind of plots. See the matplotlib plot gallery for a complete list of available plot types: http://matplotlib.org/gallery.html. Some of the more useful ones are show below:

Loading output library...

Loading output library...

Loading output library...

Annotating text in matplotlib figures can be done using the `text`

function. It supports LaTeX formatting just like axis label texts and titles:

Loading output library...

Axes can be added to a matplotlib Figure canvas manually using `fig.add_axes`

or using a sub-figure layout manager such as `subplots`

, `subplot2grid`

, or `gridspec`

:

Loading output library...

Loading output library...

Loading output library...

Manually adding axes with `add_axes`

is useful for adding insets to figures:

Loading output library...

Colormaps and contour figures are useful for plotting functions of two variables. In most of these functions we will use a colormap to encode one dimension of the data. There are a number of predefined colormaps. It is relatively straightforward to define custom colormaps. For a list of pre-defined colormaps, see: http://www.scipy.org/Cookbook/Matplotlib/Show_colormaps

Loading output library...

Loading output library...

Loading output library...

To use 3D graphics in matplotlib, we first need to create an instance of the `Axes3D`

class. 3D axes can be added to a matplotlib figure canvas in exactly the same way as 2D axes; or, more conveniently, by passing a `projection='3d'`

keyword argument to the `add_axes`

or `add_subplot`

methods.

Loading output library...

Loading output library...

Loading output library...

We can change the perspective of a 3D plot using the `view_init`

method, which takes two arguments: `elevation`

and `azimuth`

angle (in degrees):

Loading output library...

Matplotlib also includes a simple API for generating animations for sequences of figures. With the `FuncAnimation`

function we can generate a movie file from sequences of figures. The function takes the following arguments: `fig`

, a figure canvas, `func`

, a function that we provide which updates the figure, `init_func`

, a function we provide to setup the figure, `frame`

, the number of frames to generate, and `blit`

, which tells the animation function to only update parts of the frame which have changed (for smoother animations):

```
1
2
3
4
5
6
7
8
9
```

```
def init():
# setup figure
def update(frame_counter):
# update figure for new frame
anim = animation.FuncAnimation(fig, update, init_func=init, frames=200, blit=True)
anim.save('animation.mp4', fps=30) # fps = frames per second
```

To use the animation features in matplotlib we first need to import the module `matplotlib.animation`

:

Generate an animation that shows the positions of the pendulums as a function of time:

Loading output library...

Note: To generate the movie file we need to have either `ffmpeg`

or `avconv`

installed. Install it on Ubuntu using:

```
1
```

`$ sudo apt-get install ffmpeg`

or (newer versions)

```
1
```

`$ sudo apt-get install libav-tools`

On MacOSX, try:

```
1
```

`$ sudo port install ffmpeg`

Matplotlib has a number of "backends" which are responsible for rendering graphs. The different backends are able to generate graphics with different formats and display/event loops. There is a distinction between noninteractive backends (such as 'agg', 'svg', 'pdf', etc.) that are only used to generate image files (e.g. with the `savefig`

function), and interactive backends (such as Qt4Agg, GTK, MaxOSX) that can display a GUI window for interactively exploring figures.

A list of available backends are:

The default backend, called `agg`

, is based on a library for raster graphics which is great for generating raster formats like PNG.

Normally we don't need to bother with changing the default backend; but sometimes it can be useful to switch to, for example, PDF or GTKCairo (if you are using Linux) to produce high-quality vector graphics instead of raster based graphics.

When we use IPython notebook it is convenient to use a matplotlib backend that outputs the graphics embedded in the notebook file. To activate this backend, somewhere in the beginning on the notebook, we add:

`1`

`%matplotlib inline`

It is also possible to activate inline matplotlib plotting with:

`1`

`%pylab inline`

The difference is that `%pylab inline`

imports a number of packages into the global address space (scipy, numpy), while `%matplotlib inline`

only sets up inline plotting. In new notebooks created for IPython 1.0+, I would recommend using `%matplotlib inline`

, since it is tidier and you have more control over which packages are imported and how. Commonly, scipy and numpy are imported separately with:

`1 2 3`

`import numpy as np import scipy as sp import matplotlib.pyplot as plt`

The inline backend has a number of configuration options that can be set by using the IPython magic command `%config`

to update settings in `InlineBackend`

. For example, we can switch to SVG figures or higher resolution figures with either:

`1 2`

`%config InlineBackend.figure_format='svg'`

or:

`1`

`%config InlineBackend.figure_format='retina'`

For more information, type:

`1`

`%config InlineBackend`

Note that when we use an interactive backend, we must call `plt.show()`

to make the figure appear on the screen.

- http://www.matplotlib.org - The project web page for matplotlib.
- https://github.com/matplotlib/matplotlib - The source code for matplotlib.
- http://matplotlib.org/gallery.html - A large gallery showcaseing various types of plots matplotlib can create. Highly recommended!
- http://www.loria.fr/~rougier/teaching/matplotlib - A good matplotlib tutorial.
- http://scipy-lectures.github.io/matplotlib/matplotlib.html - Another good matplotlib reference.