Matplotlib: John Hunter, Darren Dale, Eric Firing, Michael Droettboom and The Matplotlib Development Team
Matplotlib: John Hunter, Darren Dale, Eric Firing, Michael Droettboom and The Matplotlib Development Team
Release 2.0.2
John Hunter, Darren Dale, Eric Firing, Michael Droettboom and the ma
I User’s Guide 1
1 Introduction 3
2 Installing 5
3 Tutorials 11
5 Colors 145
11 License 417
12 Credits 421
                                                i
18 artist Module               535
21 backends 913
22 cbook 953
23 cm (colormap) 971
24 collections 975
25 colorbar 1145
26 colors 1151
27 container 1165
28 dates 1167
29 dviread 1181
30 figure 1185
31 finance 1207
32 font_manager 1219
33 gridspec 1227
34 image 1231
36 lines 1245
37 markers 1255
38 mathtext 1259
39 mlab 1279
40 offsetbox 1313
41 patches 1325
42 path 1367
43 patheffects 1375
44 projections 1379
ii
45 pyplot                                            1387
46 rcsetup 1593
47 sankey 1597
48 scale 1605
49 spines 1615
50 style 1619
51 text 1621
52 ticker 1635
53 tight_layout 1647
56 type1font 1683
57 units 1685
58 widgets 1687
59 Installation 1705
60 Usage 1713
61 How-To 1725
62 Troubleshooting 1741
                                                       iii
68 The Matplotlib AxesGrid Toolkit API                         1795
V mplot3d 1823
VI Toolkits 1879
75 Videos 1897
76 Tutorials 1899
77 Contributing 1903
86 Licenses 2017
iv
IX   Matplotlib Examples                  2023
                                             v
X    Glossary         3015
Bibliography 3019
Index 3023
vi
   Part I
User’s Guide
               1
                                                                                                  CHAPTER
ONE
INTRODUCTION
Matplotlib is a library for making 2D plots of arrays in Python. Although it has its origins in emulating
the MATLAB®1 graphics commands, it is independent of MATLAB, and can be used in a Pythonic, object
oriented way. Although Matplotlib is written primarily in pure Python, it makes heavy use of NumPy and
other extension code to provide good performance even for large arrays.
Matplotlib is designed with the philosophy that you should be able to create simple plots with just a few
commands, or just one! If you want to see a histogram of your data, you shouldn’t need to instantiate objects,
call methods, set properties, and so on; it should just work.
For years, I used to use MATLAB exclusively for data analysis and visualization. MATLAB excels at mak-
ing nice looking plots easy. When I began working with EEG data, I found that I needed to write applications
to interact with my data, and developed an EEG analysis application in MATLAB. As the application grew
in complexity, interacting with databases, http servers, manipulating complex data structures, I began to
strain against the limitations of MATLAB as a programming language, and decided to start over in Python.
Python more than makes up for all of MATLAB’s deficiencies as a programming language, but I was having
difficulty finding a 2D plotting package (for 3D VTK more than exceeds all of my needs).
When I went searching for a Python plotting package, I had several requirements:
      • Plots should look great - publication quality. One important requirement for me is that the text looks
        good (antialiased, etc.)
      • Postscript output for inclusion with TeX documents
      • Embeddable in a graphical user interface for application development
      • Code should be easy enough that I can understand it and extend it
      • Making plots should be easy
Finding no package that suited me just right, I did what any self-respecting Python programmer would do:
rolled up my sleeves and dived in. Not having any real experience with computer graphics, I decided to
emulate MATLAB’s plotting capabilities because that is something MATLAB does very well. This had the
added advantage that many people have a lot of MATLAB experience, and thus they can quickly get up to
steam plotting in python. From a developer’s perspective, having a fixed user interface (the pylab interface)
has been very useful, because the guts of the code base can be redesigned without affecting user code.
The Matplotlib code is conceptually divided into three parts: the pylab interface is the set of functions
provided by matplotlib.pylab which allow the user to create plots with code quite similar to MATLAB
  1
      MATLAB is a registered trademark of The MathWorks, Inc.
                                                                                                            3
Matplotlib, Release 2.0.2
figure generating code (Pyplot tutorial). The Matplotlib frontend or Matplotlib API is the set of classes that
do the heavy lifting, creating and managing figures, text, lines, plots and so on (Artist tutorial). This is an
abstract interface that knows nothing about output. The backends are device-dependent drawing devices, aka
renderers, that transform the frontend representation to hardcopy or a display device (What is a backend?).
Example backends: PS creates PostScript® hardcopy, SVG creates Scalable Vector Graphics hardcopy,
Agg creates PNG output using the high quality Anti-Grain Geometry library that ships with Matplotlib,
GTK embeds Matplotlib in a Gtk+ application, GTKAgg uses the Anti-Grain renderer to create a figure and
embed it in a Gtk+ application, and so on for PDF, WxWidgets, Tkinter, etc.
Matplotlib is used by many people in many different contexts. Some people want to automatically generate
PostScript files to send to a printer or publishers. Others deploy Matplotlib on a web application server to
generate PNG output for inclusion in dynamically-generated web pages. Some use Matplotlib interactively
from the Python shell in Tkinter on Windows™. My primary use is to embed Matplotlib in a Gtk+ EEG
application that runs on Windows, Linux and Macintosh OS X.
4                                                                                  Chapter 1. Introduction
                                                                                                    CHAPTER
TWO
INSTALLING
There are many different ways to install matplotlib, and the best way depends on what operating system you
are using, what you already have installed, and how you want to use it. To avoid wading through all the
details (and potential complications) on this page, there are several convenient options.
The first option is to use one of the pre-packaged python distributions that already provide matplotlib built-in.
The Continuum.io Python distribution (Anaconda or miniconda) and the Enthought distribution (Canopy)
are both excellent choices that “just work” out of the box for Windows, OSX and common Linux platforms.
Both of these distributions include matplotlib and lots of other useful tools.
If you are on Linux, you might prefer to use your package manager. matplotlib is packaged for almost every
major Linux distribution.
   • Debian / Ubuntu : sudo apt-get install python-matplotlib
   • Fedora / Redhat : sudo yum install python-matplotlib
If you are on Mac OSX you can probably install matplotlib binaries using the standard Python installation
program pip. See Installing OSX binary wheels.
2.1.4 Windows
If you don’t already have Python installed, we recommend using one of the scipy-stack compatible Python
distributions such as WinPython, Python(x,y), Enthought Canopy, or Continuum Anaconda, which have
matplotlib and many of its dependencies, plus other useful packages, preinstalled.
For standard Python installations, install matplotlib using pip:
                                                                                                               5
Matplotlib, Release 2.0.2
In case Python 2.7 or 3.4 are not installed for all users, the Microsoft Visual C++ 2008 (64 bit or 32 bit for
Python 2.7) or Microsoft Visual C++ 2010 (64 bit or 32 bit for Python 3.4) redistributable packages need to
be installed.
Matplotlib depends on Pillow for reading and saving JPEG, BMP, and TIFF image files. Matplotlib requires
MiKTeX and GhostScript for rendering text with LaTeX. FFmpeg, avconv, mencoder, or ImageMagick are
required for the animation module.
The following backends should work out of the box: agg, tkagg, ps, pdf and svg. For other backends you
may need to install pycairo, PyQt4, PyQt5, PySide, wxPython, PyGTK, Tornado, or GhostScript.
TkAgg is probably the best backend for interactive use from the standard Python shell or IPython. It is
enabled as the default backend for the official binaries. GTK3 is not supported on Windows.
The Windows wheels (*.whl) on the PyPI download page do not contain test data or example
code. If you want to try the many demos that come in the matplotlib source distribution, down-
load the *.tar.gz file and look in the examples subdirectory. To run the test suite, copy the
lib\matplotlib\tests and lib\mpl_toolkits\tests directories from the source distribution to sys.
prefix\Lib\site-packages\matplotlib and sys.prefix\Lib\site-packages\mpl_toolkits
respectively, and install nose, mock, Pillow, MiKTeX, GhostScript, ffmpeg, avconv, mencoder, ImageMag-
ick, and Inkscape.
If you are interested in contributing to matplotlib development, running the latest source code, or just like to
build everything yourself, it is not difficult to build matplotlib from source. Grab the latest tar.gz release file
from the PyPI files page, or if you want to develop matplotlib or just need the latest bugfixed version, grab
the latest git version Source install from git.
The standard environment variables CC, CXX, PKG_CONFIG are respected. This means you can set them if
your toolchain is prefixed. This may be used for cross compiling.
export CC=x86_64-pc-linux-gnu-gcc
export CXX=x86_64-pc-linux-gnu-g++
export PKG_CONFIG=x86_64-pc-linux-gnu-pkg-config
Once you have satisfied the requirements detailed below (mainly python, numpy, libpng and freetype), you
can build matplotlib.
cd matplotlib
python setup.py build
python setup.py install
We provide a setup.cfg file that goes with setup.py which you can use to customize the build process. For
example, which default backend to use, whether some of the optional libraries that matplotlib ships with are
installed, and so on. This file will be particularly useful to those packaging matplotlib.
6                                                                                        Chapter 2. Installing
                                                                                  Matplotlib, Release 2.0.2
If you have installed prerequisites to nonstandard places and need to inform matplotlib where they are,
edit setupext.py and add the base dirs to the basedir dictionary entry for your sys.platform. e.g., if
the header to some required library is in /some/path/include/someheader.h, put /some/path in the
basedir list for your platform.
These are external packages which you will need to install before installing matplotlib. If you are building on
OSX, see Building on OSX. If you are building on Windows, see Building on Windows. If you are installing
dependencies with a package manager on Linux, you may need to install the development packages (look
for a “-dev” postfix) in addition to the libraries themselves.
Required Dependencies
These are optional packages which you may want to install to use matplotlib with a user interface toolkit.
See What is a backend? for more details on the optional matplotlib backends and the capabilities they
provide.
tk 8.3 or later, not 8.6.0 or 8.6.1 The TCL/Tk widgets library used by the TkAgg backend.
      Versions 8.6.0 and 8.6.1 are known to have issues that may result in segfaults when closing multiple
      windows in the wrong order.
pyqt 4.4 or later The Qt4 widgets library python wrappers for the Qt4Agg backend
pygtk 2.4 or later The python wrappers for the GTK widgets library for use with the GTK or GTKAgg
      backend
wxpython 2.8 or later The python wrappers for the wx widgets library for use with the WX or WXAgg
     backend
ffmpeg/avconv or mencoder Required for the animation module to be save out put to movie formats.
ImageMagick Required for the animation module to be able to save to animated gif.
Optional dependencies
Pillow If Pillow is installed, matplotlib can read and write a larger selection of image file formats.
pkg-config A tool used to find required non-python libraries. This is not strictly required, but can make
     installation go more smoothly if the libraries and headers are not in the expected locations.
agg 2.4 The antigrain C++ rendering engine. matplotlib links against the agg template source statically, so
      it will not affect anything on your system outside of matplotlib.
qhull 2012.1 A library for computing Delaunay triangulations.
ttconv truetype font utility
If you are on Fedora/RedHat, you can get all the dependencies required to build matplotlib by first installing
yum-builddep and then running:
su -c "yum-builddep python-matplotlib"
This does not build matplotlib, but it does get the install the build dependencies, which will make building
from source easier.
8                                                                                     Chapter 2. Installing
                                                                              Matplotlib, Release 2.0.2
The build situation on OSX is complicated by the various places one can get the libpng and freetype re-
quirements (darwinports, fink, /usr/X11R6) and the different architectures (e.g., x86, ppc, universal) and
the different OSX version (e.g., 10.4 and 10.5). We recommend that you build the way we do for the OSX
release: get the source from the tarball or the git repository and follow the instruction in README.osx.
The Python shipped from https://www.python.org is compiled with Visual Studio 2008 for versions before
3.3, Visual Studio 2010 for 3.3 and 3.4, and Visual Studio 2015 for 3.5 and 3.6. Python extensions are
recommended to be compiled with the same compiler.
Since there is no canonical Windows package manager, the methods for building freetype, zlib, and libpng
from source code are documented as a build script at matplotlib-winbuild.
10                          Chapter 2. Installing
                                                                                                    CHAPTER
THREE
TUTORIALS
3.1 Introductory
matplotlib.pyplot is a collection of command style functions that make matplotlib work like MATLAB.
Each pyplot function makes some change to a figure: e.g., creates a figure, creates a plotting area in a figure,
plots some lines in a plotting area, decorates the plot with labels, etc. In matplotlib.pyplot various states
are preserved across function calls, so that it keeps track of things like the current figure and plotting area,
and the plotting functions are directed to the current axes (please note that “axes” here and in most places in
the documentation refers to the axes part of a figure and not the strict mathematical term for more than one
axis).
                                                                                                             11
Matplotlib, Release 2.0.2
4.0
3.5
                3.0
 some numbers
2.5
2.0
1.5
                1.0
                      0.0   0.5     1.0        1.5         2.0        2.5         3.0
You may be wondering why the x-axis ranges from 0-3 and the y-axis from 1-4. If you provide a single
list or array to the plot() command, matplotlib assumes it is a sequence of y values, and automatically
generates the x values for you. Since python ranges start with 0, the default x vector has the same length as
y but starts with 0. Hence the x data are [0,1,2,3].
plot() is a versatile command, and will take an arbitrary number of arguments. For example, to plot x
versus y, you can issue the command:
For every x, y pair of arguments, there is an optional third argument which is the format string that indicates
the color and line type of the plot. The letters and symbols of the format string are from MATLAB, and you
concatenate a color string with a line style string. The default format string is ‘b-‘, which is a solid blue line.
For example, to plot the above with red circles, you would issue
12                                                                                        Chapter 3. Tutorials
                                                                                  Matplotlib, Release 2.0.2
    20.0
    17.5
    15.0
    12.5
    10.0
      7.5
      5.0
      2.5
      0.0
            0          1           2           3           4           5           6
See the plot() documentation for a complete list of line styles and format strings. The axis() command
in the example above takes a list of [xmin, xmax, ymin, ymax] and specifies the viewport of the axes.
If matplotlib were limited to working with lists, it would be fairly useless for numeric processing. Generally,
you will use numpy arrays. In fact, all sequences are converted to numpy arrays internally. The example
below illustrates a plotting several lines with different format styles in one command using arrays.
import numpy as np
import matplotlib.pyplot as plt
3.1. Introductory                                                                                           13
Matplotlib, Release 2.0.2
100
80
60
40
20
         0
               0             1             2             3             4            5
Lines have many attributes that you can set: linewidth, dash style, antialiased, etc; see matplotlib.lines.
Line2D. There are several ways to set line properties
     • Use keyword args:
       plt.plot(x, y, linewidth=2.0)
     • Use the setter methods of a Line2D instance. plot returns a list of Line2D objects; e.g., line1,
       line2 = plot(x1, y1, x2, y2). In the code below we will suppose that we have only one line
       so that the list returned is of length 1. We use tuple unpacking with line, to get the first element of
       that list:
       line, = plt.plot(x, y, '-')
       line.set_antialiased(False) # turn off antialising
     • Use the setp() command. The example below uses a MATLAB-style command to set multiple
       properties on a list of lines. setp works transparently with a list of objects or a single object. You can
       either use python keyword arguments or MATLAB-style string/value pairs:
       lines = plt.plot(x1, y1, x2, y2)
       # use keyword args
       plt.setp(lines, color='r', linewidth=2.0)
14                                                                                       Chapter 3. Tutorials
                                                                                   Matplotlib, Release 2.0.2
To get a list of settable line properties, call the setp() function with a line or lines as argument
In [69]: lines = plt.plot([1, 2, 3])
In [70]: plt.setp(lines)
  alpha: float
  animated: [True | False]
  antialiased or aa: [True | False]
3.1. Introductory                                                                                        15
Matplotlib, Release 2.0.2
...snip
MATLAB, and pyplot, have the concept of the current figure and the current axes. All plotting com-
mands apply to the current axes. The function gca() returns the current axes (a matplotlib.axes.Axes
instance), and gcf() returns the current figure (matplotlib.figure.Figure instance). Normally, you
don’t have to worry about this, because it is all taken care of behind the scenes. Below is a script to create
two subplots.
import numpy as np
import matplotlib.pyplot as plt
def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)
plt.figure(1)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()
16                                                                                    Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
     1.0
     0.5
     0.0
     0.5
             0           1           2           3           4            5
     1.0
     0.5
     0.0
     0.5
     1.0
             0           1           2           3           4            5
The figure() command here is optional because figure(1) will be created by default, just as a
subplot(111) will be created by default if you don’t manually specify any axes. The subplot() com-
mand specifies numrows, numcols, fignum where fignum ranges from 1 to numrows*numcols. The
commas in the subplot command are optional if numrows*numcols<10. So subplot(211) is identical
to subplot(2, 1, 1). You can create an arbitrary number of subplots and axes. If you want to place
an axes manually, i.e., not on a rectangular grid, use the axes() command, which allows you to specify
the location as axes([left, bottom, width, height]) where all values are in fractional (0 to 1) co-
ordinates. See pylab_examples example code: axes_demo.py for an example of placing axes manually and
pylab_examples example code: subplots_demo.py for an example with lots of subplots.
You can create multiple figures by using multiple figure() calls with an increasing figure number. Of
course, each figure can contain as many axes and subplots as your heart desires:
3.1. Introductory                                                                                   17
Matplotlib, Release 2.0.2
You can clear the current figure with clf() and the current axes with cla(). If you find it annoying that
states (specifically the current image, figure and axes) are being maintained for you behind the scenes, don’t
despair: this is just a thin stateful wrapper around an object oriented API, which you can use instead (see
Artist tutorial)
If you are making lots of figures, you need to be aware of one more thing: the memory required for a figure
is not completely released until the figure is explicitly closed with close(). Deleting all references to the
figure, and/or using the window manager to kill the window in which the figure appears on the screen, is not
enough, because pyplot maintains internal references until close() is called.
The text() command can be used to add text in an arbitrary location, and the xlabel(), ylabel() and
title() are used to add text in the indicated locations (see Text introduction for a more detailed example)
import numpy as np
import matplotlib.pyplot as plt
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
18                                                                                    Chapter 3. Tutorials
                                                                                     Matplotlib, Release 2.0.2
                                        Histogram of IQ
              0.030
0.025 = 100, = 15
              0.020
Probability
0.015
0.010
0.005
              0.000
                      40   60        80         100         120         140         160
                                               Smarts
    All of the text() commands return an matplotlib.text.Text instance. Just as with with lines above,
    you can customize the properties by passing keyword arguments into the text functions or using setp():
These properties are covered in more detail in Text properties and layout.
    matplotlib accepts TeX equation expressions in any text expression. For example to write the expression
    σi = 15 in the title, you can write a TeX expression surrounded by dollar signs:
plt.title(r'$\sigma_i=15$')
    The r preceding the title string is important – it signifies that the string is a raw string and not to treat
    backslashes as python escapes. matplotlib has a built-in TeX expression parser and layout engine, and ships
    its own math fonts – for details see Writing mathematical expressions. Thus you can use mathematical text
    across platforms without requiring a TeX installation. For those who have LaTeX and dvipng installed, you
    can also use LaTeX to format your text and incorporate the output directly into your display figures or saved
    postscript – see Text rendering With LaTeX.
    3.1. Introductory                                                                                         19
Matplotlib, Release 2.0.2
Annotating text
The uses of the basic text() command above place text at an arbitrary position on the Axes. A common use
for text is to annotate some feature of the plot, and the annotate() method provides helper functionality
to make annotations easy. In an annotation, there are two points to consider: the location being annotated
represented by the argument xy and the location of the text xytext. Both of these arguments are (x,y)
tuples.
import numpy as np
import matplotlib.pyplot as plt
ax = plt.subplot(111)
plt.ylim(-2,2)
plt.show()
      2.0
      1.5                                            local max
      1.0
      0.5
      0.0
      0.5
      1.0
      1.5
      2.0
             0            1            2            3            4            5
In this basic example, both the xy (arrow tip) and xytext locations (text location) are in data coordinates.
20                                                                                  Chapter 3. Tutorials
                                                                                Matplotlib, Release 2.0.2
There are a variety of other coordinate systems one can choose – see Basic annotation and Advanced Anno-
tation for details. More examples can be found in pylab_examples example code: annotation_demo.py.
matplotlib.pyplot supports not only linear axis scales, but also logarithmic and logit scales. This is
commonly used if data spans many orders of magnitude. Changing the scale of an axis is easy:
      plt.xscale(‘log’)
An example of four plots with the same data and different scales for the y axis is shown below.
import numpy as np
import matplotlib.pyplot as plt
# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)
# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)
# symmetric log
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.01)
plt.title('symlog')
plt.grid(True)
# logit
3.1. Introductory                                                                                     21
Matplotlib, Release 2.0.2
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
# Format the minor tick labels of the y-axis into empty strings with
# `NullFormatter`, to avoid cumbering the axis with too many labels.
plt.gca().yaxis.set_minor_formatter(NullFormatter())
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "1 - 10^{-3}"
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
                     wspace=0.35)
plt.show()
                     linear                                         log
     1.0                                       100
     0.8
     0.6                                      10   1
     0.4
     0.2                                      10   2
     0.0
           0     250    500         750                0      250
                    symlog                                          logit500     750
 10   1                                   1 10 3
 10   2                                     0.99
      0                                     0.90
                                            0.50
  10 2                                      0.10
  10 1                                      0.01
   100
           0     250       500      750                0      250       500      750
It is also possible to add your own scale, see Developer’s guide for creating scales and transformations for
details.
22                                                                                  Chapter 3. Tutorials
                                                                                    Matplotlib, Release 2.0.2
Startup commands
First, let’s start IPython. It is a most excellent enhancement to the standard Python prompt, and it ties in
especially well with Matplotlib. Start IPython either at a shell, or the IPython Notebook now.
With IPython started, we now need to connect to a GUI event loop. This tells IPython where (and how) to
display plots. To connect to a GUI loop, execute the %matplotlib magic at your IPython prompt. There’s
more detail on exactly what this does at IPython’s documentation on GUI event loops.
If you’re using IPython Notebook, the same commands are available, but people commonly use a specific
argument to the %matplotlib magic:
This turns on inline plotting, where plot graphics will appear in your notebook. This has important implica-
tions for interactivity. For inline plotting, commands in cells below the cell that outputs a plot will not affect
the plot. For example, changing the color map is not possible from cells below the cell that creates a plot.
However, for other backends, such as qt4, that open a separate window, cells below those that create the plot
will change the plot - it is a live object in memory.
This tutorial will use matplotlib’s imperative-style plotting interface, pyplot. This interface maintains global
state, and is very useful for quickly and easily experimenting with various plot settings. The alternative is
the object-oriented interface, which is also very powerful, and generally more suitable for large application
development. If you’d like to learn about the object-oriented interface, a great place to start is our FAQ on
usage. For now, let’s get on with the imperative-style approach:
Loading image data is supported by the Pillow library. Natively, matplotlib only supports PNG images. The
commands shown below fall back on Pillow if the native read fails.
The image used in this example is a PNG file, but keep that Pillow requirement in mind for your own data.
Here’s the image we’re going to play with:
3.1. Introductory                                                                                              23
Matplotlib, Release 2.0.2
It’s a 24-bit RGB PNG image (8 bits for each of R, G, B). Depending on where you get your data, the other
kinds of image that you’ll most likely encounter are RGBA images, which allow for transparency, or single-
channel grayscale (luminosity) images. You can right click on it and choose “Save image as” to download
it to your computer for the rest of this tutorial.
And here we go...
In [5]: img=mpimg.imread('stinkbug.png')
Out[5]:
array([[[ 0.40784314, 0.40784314, 0.40784314],
        [ 0.40784314, 0.40784314, 0.40784314],
        [ 0.40784314, 0.40784314, 0.40784314],
        ...,
        [ 0.42745098, 0.42745098, 0.42745098],
        [ 0.42745098, 0.42745098, 0.42745098],
        [ 0.42745098, 0.42745098, 0.42745098]],
        ...,
        [[ 0.44313726,      0.44313726,   0.44313726],
         [ 0.4509804 ,      0.4509804 ,   0.4509804 ],
         [ 0.4509804 ,      0.4509804 ,   0.4509804 ],
         ...,
         [ 0.44705883,      0.44705883,   0.44705883],
24                                                                                 Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
Note the dtype there - float32. Matplotlib has rescaled the 8 bit data from each channel to floating point
data between 0.0 and 1.0. As a side note, the only datatype that Pillow can work with is uint8. Matplotlib
plotting can handle float32 and uint8, but image reading/writing for any format other than PNG is limited
to uint8 data. Why 8 bits? Most displays can only render 8 bits per channel worth of color gradation. Why
can they only render 8 bits/channel? Because that’s about all the human eye can see. More here (from a
photography standpoint): Luminous Landscape bit depth tutorial.
Each inner list represents a pixel. Here, with an RGB image, there are 3 values. Since it’s a black and white
image, R, G, and B are all similar. An RGBA (where A is alpha, or transparency), has 4 values per inner list,
and a simple luminance image just has one value (and is thus only a 2-D array, not a 3-D array). For RGB
and RGBA images, matplotlib supports float32 and uint8 data types. For grayscale, matplotlib supports only
float32. If your array data does not meet one of these descriptions, you need to rescale it.
So, you have your data in a numpy array (either by importing it, or by generating it). Let’s render it. In
Matplotlib, this is performed using the imshow() function. Here we’ll grab the plot object. This object
gives you an easy way to manipulate the plot from the prompt.
In [6]: imgplot = plt.imshow(img)
        0
      50
     100
     150
     200
     250
     300
     350
            0          100           200            300           400           500
3.1. Introductory                                                                                         25
Matplotlib, Release 2.0.2
Pseudocolor can be a useful tool for enhancing contrast and visualizing your data more easily. This is
especially useful when making presentations of your data using projectors - their contrast is typically quite
poor.
Pseudocolor is only relevant to single-channel, grayscale, luminosity images. We currently have an RGB
image. Since R, G, and B are all similar (see for yourself above or in your data), we can just pick one
channel of our data:
This is array slicing. You can read more in the Numpy tutorial.
In [8]: plt.imshow(lum_img)
        0
      50
     100
     150
     200
     250
     300
     350
            0          100           200            300           400           500
Now, with a luminosity (2D, no color) image, the default colormap (aka lookup table, LUT), is applied. The
default is called viridis. There are plenty of others to choose from.
26                                                                                    Chapter 3. Tutorials
                                                                            Matplotlib, Release 2.0.2
       0
      50
     100
     150
     200
     250
     300
     350
           0          100          200           300          400           500
Note that you can also change colormaps on existing plot objects using the set_cmap() method:
3.1. Introductory                                                                                 27
Matplotlib, Release 2.0.2
        0
      50
     100
     150
     200
     250
     300
     350
            0          100            200           300           400            500
Note: However, remember that in the IPython notebook with the inline backend, you can’t make changes
to plots that have already been rendered. If you create imgplot here in one cell, you cannot call set_cmap()
on it in a later cell and expect the earlier plot to change. Make sure that you enter these commands together
in one cell. plt commands will not change plots from earlier cells.
There are many other colormap schemes available. See the list and images of the colormaps.
It’s helpful to have an idea of what value a color represents. We can do that by adding color bars.
28                                                                                     Chapter 3. Tutorials
                                                                                  Matplotlib, Release 2.0.2
                                                                            0.8
        0
                                                                            0.7
      50
                                                                            0.6
     100
     150                                                                    0.5
     200                                                                    0.4
     250                                                                    0.3
     300
                                                                            0.2
     350
            0       100         200        300         400        500       0.1
                                                                            0.0
This adds a colorbar to your existing figure. This won’t automatically change if you change you switch to a
different colormap - you have to re-create your plot, and add in the colorbar again.
Sometimes you want to enhance the contrast in your image, or expand the contrast in a particular region
while sacrificing the detail in colors that don’t vary much, or don’t matter. A good tool to find interesting
regions is the histogram. To create a histogram of our image data, we use the hist() function.
3.1. Introductory                                                                                         29
Matplotlib, Release 2.0.2
8000
6000
4000
2000
        0
             0.0          0.2          0.4          0.6          0.8          1.0
Most often, the “interesting” part of the image is around the peak, and you can get extra contrast by clipping
the regions above and/or below the peak. In our histogram, it looks like there’s not much useful information
in the high end (not many white things in the image). Let’s adjust the upper limit, so that we effectively
“zoom in on” part of the histogram. We do this by passing the clim argument to imshow. You could also do
this by calling the set_clim() method of the image plot object, but make sure that you do so in the same
cell as your plot command when working with the IPython Notebook - it will not change plots from earlier
cells.
30                                                                                    Chapter 3. Tutorials
                                                                                  Matplotlib, Release 2.0.2
                        Before                                  After
        0                                       0
      100                                    100
      200                                    200
      300                                    300
             0         200         400              0         200          400
Interpolation calculates what the color or value of a pixel “should” be, according to different mathematical
schemes. One common place that this happens is when you resize an image. The number of pixels change,
but you want the same information. Since pixels are discrete, there’s missing space. Interpolation is how
you fill that space. This is why your images sometimes come out looking pixelated when you blow them
up. The effect is more pronounced when the difference between the original image and the expanded image
is greater. Let’s take our image and shrink it. We’re effectively discarding pixels, only keeping a select few.
Now when we plot it, that data gets blown up to the size on your screen. The old pixels aren’t there anymore,
and the computer has to draw in pixels to fill that space.
We’ll use the Pillow library that we used to load the image also to resize the image.
3.1. Introductory                                                                                           31
Matplotlib, Release 2.0.2
10
20
30
40
0 10 20 30 40 50 60
Here we have the default interpolation, bilinear, since we did not give imshow() any interpolation argument.
Let’s try some others:
32                                                                                  Chapter 3. Tutorials
                                                                   Matplotlib, Release 2.0.2
10
20
30
40
0 10 20 30 40 50 60
3.1. Introductory                                                                        33
Matplotlib, Release 2.0.2
10
20
30
40
0 10 20 30 40 50 60
Bicubic interpolation is often used when blowing up photos - people tend to prefer blurry over pixelated.
      GridSpec specifies the geometry of the grid that a subplot will be placed. The number of
          rows and number of columns of the grid need to be set. Optionally, the subplot layout
          parameters (e.g., left, right, etc.) can be tuned.
      SubplotSpec specifies the location of the subplot in the given GridSpec.
      subplot2grid() a helper function that is similar to subplot() but uses 0-based indexing
          and let subplot to occupy multiple cells.
To use subplot2grid(), you provide geometry of the grid and the location of the subplot in the grid. For
a simple single-cell subplot:
is identical to
34                                                                                  Chapter 3. Tutorials
                                                                               Matplotlib, Release 2.0.2
ax = plt.subplot(2, 2, 1)
Note that, unlike Matplotlib’s subplot, the index starts from 0 in GridSpec.
To create a subplot that spans multiple cells,
creates
subplot2grid
ax1
ax2
ax3
ax4 ax5
You can create GridSpec explicitly and use them to create a subplot.
For example,
3.1. Introductory                                                                                    35
Matplotlib, Release 2.0.2
is equal to
A GridSpec instance provides array-like (2d or 1d) indexing that returns the SubplotSpec instance. For a
SubplotSpec that spans multiple cells, use slice.
gs = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(gs[0, :])
ax2 = plt.subplot(gs[1, :-1])
ax3 = plt.subplot(gs[1:, -1])
ax4 = plt.subplot(gs[-1, 0])
ax5 = plt.subplot(gs[-1, -2])
GridSpec
ax1
ax2
ax3
ax4 ax5
36                                                                               Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
When a GridSpec is explicitly used, you can adjust the layout parameters of subplots that are created from
the GridSpec.
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
This is similar to subplots_adjust(), but it only affects the subplots that are created from the given
GridSpec.
The code below
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = plt.subplot(gs1[:-1, :])
ax2 = plt.subplot(gs1[-1, :-1])
ax3 = plt.subplot(gs1[-1, -1])
gs2 = gridspec.GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = plt.subplot(gs2[:, :-1])
ax5 = plt.subplot(gs2[:-1, -1])
ax6 = plt.subplot(gs2[-1, -1])
creates
ax1 ax5
ax4
3.1. Introductory                                                                                      37
Matplotlib, Release 2.0.2
You can create GridSpec from the SubplotSpec, in which case its layout parameters are set to that of the
location of the given SubplotSpec.
gs0 = gridspec.GridSpec(1, 2)
ax1 ax5
ax4
Here’s a more sophisticated example of nested GridSpec where we put a box around each cell of the outer
4x4 grid, by hiding appropriate spines in each of the inner 3x3 grids.
38                                                                               Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
By default, GridSpec creates cells of equal sizes. You can adjust relative heights and widths of rows and
columns. Note that absolute values are meaningless, only their relative ratios matter.
gs = gridspec.GridSpec(2, 2,
                       width_ratios=[1, 2],
                       height_ratios=[4, 1]
                       )
ax1 = plt.subplot(gs[0])
ax2 = plt.subplot(gs[1])
3.1. Introductory                                                                                     39
Matplotlib, Release 2.0.2
ax3 = plt.subplot(gs[2])
ax4 = plt.subplot(gs[3])
ax1 ax2
ax3 ax4
tight_layout automatically adjusts subplot params so that the subplot(s) fits in to the figure area. This is an
experimental feature and may not work for some cases. It only checks the extents of ticklabels, axis labels,
and titles.
Simple Example
In matplotlib, the location of axes (including subplots) are specified in normalized figure coordinates. It can
happen that your axis labels or titles (or sometimes even ticklabels) go outside the figure area, and are thus
clipped.
plt.rcParams['savefig.facecolor'] = "0.8"
40                                                                                     Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
ax.set_title('Title', fontsize=fontsize)
  plt.close('all')
  fig, ax = plt.subplots()
  example_plot(ax, fontsize=24)
                                          Title
        2.0
y-label
1.5
        1.0
              0.0                             0.5                             1.0
                                       x-label
  To prevent this, the location of axes needs to be adjusted. For subplots, this can be done by adjusting the
  subplot params (Move the edge of an axes to make room for tick labels). Matplotlib v1.1 introduces a new
  command tight_layout() that does this automatically for you.
plt.tight_layout()
  3.1. Introductory                                                                                       41
  Matplotlib, Release 2.0.2
                                             Title
        2.0
y-label
1.5
        1.0
               0.0                               0.5                                1.0
                                          x-label
  When you have multiple subplots, often you see labels of different axes overlapping each other.
  plt.close('all')
  fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
  example_plot(ax1)
  example_plot(ax2)
  example_plot(ax3)
  example_plot(ax4)
  42                                                                                  Chapter 3. Tutorials
                                                                           Matplotlib, Release 2.0.2
                       Title                               Title
          2.0                                 2.0
y-label
                                    y-label
          1.5                                 1.5
          1.0                                 1.0
                0.0    Title
                        0.5           1.0           0.0    Title
                                                            0.5           1.0
          2.0         x-label                 2.0         x-label
y-label
y-label
1.5 1.5
          1.0                                 1.0
                0.0     0.5           1.0           0.0     0.5           1.0
                      x-label                             x-label
tight_layout() will also adjust spacing between subplots to minimize the overlaps.
plt.tight_layout()
3.1. Introductory                                                                                43
 Matplotlib, Release 2.0.2
                       Title                                   Title
          2.0                                     2.0
y-label
                                        y-label
          1.5                                     1.5
          1.0                                     1.0
                0.0     0.5          1.0                0.0     0.5           1.0
                      x-label                                 x-label
                       Title                                   Title
          2.0                                     2.0
y-label
                                        y-label
          1.5                                     1.5
          1.0                                     1.0
                0.0     0.5          1.0                0.0     0.5           1.0
                      x-label                                 x-label
 tight_layout() can take keyword arguments of pad, w_pad and h_pad. These control the extra padding
 around the figure border and between subplots. The pads are specified in fraction of fontsize.
 44                                                                           Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
                         Title                                        Title
          2.0                                         2.0
y-label
                                            y-label
          1.5                                         1.5
          1.0                                         1.0
                0.0       0.5              1.0              0.0        0.5             1.0
                        x-label                                     x-label
                         Title                                       Title
          2.0                                         2.0
y-label
y-label
1.5 1.5
          1.0                                         1.0
                0.0       0.5              1.0              0.0        0.5             1.0
                        x-label                                     x-label
   tight_layout() will work even if the sizes of subplots are different as far as their grid specification is
   compatible. In the example below, ax1 and ax2 are subplots of a 2x2 grid, while ax3 is of a 1x2 grid.
   plt.close('all')
   fig = plt.figure()
   ax1 = plt.subplot(221)
   ax2 = plt.subplot(223)
   ax3 = plt.subplot(122)
   example_plot(ax1)
   example_plot(ax2)
   example_plot(ax3)
plt.tight_layout()
   3.1. Introductory                                                                                      45
Matplotlib, Release 2.0.2
                        Title                                         Title
          2.0                                            2.0
y-label
1.5
          1.0
                0.0      0.5             1.0
                                               y-label
                       x-label                           1.5
                        Title
          2.0
y-label
1.5
          1.0                                            1.0
                0.0      0.5             1.0                   0.0     0.5       1.0
                       x-label                                       x-label
It works with subplots created with subplot2grid(). In general, subplots created from the gridspec (Cus-
tomizing Location of Subplot Using GridSpec) will work.
plt.close('all')
fig = plt.figure()
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout()
46                                                                               Chapter 3. Tutorials
                                                                                            Matplotlib, Release 2.0.2
                       Title                                        Title
          2.0                                   2.0
y-label
                                      y-label
          1.5                                   1.5
          1.0                                   1.0
                0.0     0.5     1.0                   0.0            0.5                         1.0
                      x-label                                     x-label
                                        Title                                            Title
          2.0                                                               2.0
y-label
                                                                  y-label
          1.5                                                               1.5
          1.0                                                               1.0
                 0.0                     0.5                1.0                   0.0     0.5     1.0
                                      x-label                                           x-label
Although not thoroughly tested, it seems to work for subplots with aspect != “auto” (e.g., axes with images).
arr = np.arange(100).reshape((10,10))
plt.close('all')
fig = plt.figure(figsize=(5,4))
ax = plt.subplot(111)
im = ax.imshow(arr, interpolation="none")
plt.tight_layout()
3.1. Introductory                                                                                                 47
Matplotlib, Release 2.0.2
0 2 4 6 8
Caveats
     • tight_layout() only considers ticklabels, axis labels, and titles. Thus, other artists may be clipped
       and also may overlap.
     • It assumes that the extra space needed for ticklabels, axis labels, and titles is independent of original
       location of axes. This is often true, but there are rare cases where it is not.
     • pad=0 clips some of the texts by a few pixels. This may be a bug or a limitation of the current
       algorithm and it is not clear why it happens. Meanwhile, use of pad at least larger than 0.3 is recom-
       mended.
GridSpec has its own tight_layout() method (the pyplot api tight_layout() also works).
plt.close('all')
fig = plt.figure()
gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
48                                                                                      Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
example_plot(ax1)
example_plot(ax2)
gs1.tight_layout(fig)
                                              Title
          2.0
y-label
1.5
          1.0
                0.0                            0.5                               1.0
                                            x-label
                                             Title
          2.0
y-label
1.5
          1.0
                0.0                            0.5                               1.0
                                            x-label
You may provide an optional rect parameter, which specifies the bounding box that the subplots will be fit
inside. The coordinates must be in normalized figure coordinates and the default is (0, 0, 1, 1).
3.1. Introductory                                                                                      49
 Matplotlib, Release 2.0.2
                        Title
          2.0
y-label
1.5
          1.0
                0.0      0.5            1.0
                      x-label
                       Title
          2.0
y-label
1.5
          1.0
                0.0      0.5            1.0
                      x-label
 For example, this can be used for a figure with multiple gridspecs.
gs2 = gridspec.GridSpec(3, 1)
 for ss in gs2:
     ax = fig.add_subplot(ss)
     example_plot(ax)
     ax.set_title("")
     ax.set_xlabel("")
ax.set_xlabel("x-label", fontsize=12)
 50                                                                    Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
                        Title                           2.0
          2.0
                                              y-label
                                                        1.5
y-label
          1.5
                                                        1.0
                                                              0.0     0.5            1.0
                                                        2.0
          1.0
                0.0      0.5            1.0
                                              y-label
                      x-label                           1.5
                       Title
          2.0                                           1.0
                                                              0.0     0.5            1.0
                                                        2.0
y-label
          1.5
                                              y-label
1.5
          1.0                                           1.0
                0.0      0.5            1.0                   0.0     0.5            1.0
                      x-label                                       x-label
 We may try to match the top and bottom of two grids
 gs1.update(top=top, bottom=bottom)
 gs2.update(top=top, bottom=bottom)
 While this should be mostly good enough, adjusting top and bottom may require adjustment of hspace also.
 To update hspace & vspace, we call tight_layout() again with updated rect argument. Note that the rect
 argument specifies the area including the ticklabels, etc. Thus, we will increase the bottom (which is 0 for
 the normal case) by the difference between the bottom from above and the bottom of each gridspec. Same
 thing for the top.
 3.1. Introductory                                                                                        51
 Matplotlib, Release 2.0.2
                        Title
          2.0                                           2.0
                                              y-label
                                                        1.5
y-label
          1.5
                                                        1.0
                                                              0.0     0.5     1.0
          1.0                                           2.0
                0.0      0.5            1.0
                                              y-label
                      x-label                           1.5
                       Title
          2.0                                           1.0
                                                              0.0     0.5     1.0
                                                        2.0
y-label
          1.5
                                              y-label
                                                        1.5
          1.0                                           1.0
                0.0      0.5            1.0                   0.0     0.5     1.0
                      x-label                                       x-label
 plt.close('all')
 fig = plt.figure()
 for ax in grid:
     example_plot(ax)
     ax.title.set_visible(False)
plt.tight_layout()
 52                                                                           Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
y-label 2.0
1.5
          1.0
          2.0
y-label
1.5
          1.0
                0.0        0.5             1.0    0.0              0.5             1.0
                        x-label                                 x-label
Colorbar
If you create a colorbar with the colorbar() command, the created colorbar is an instance of Axes, not
Subplot, so tight_layout does not work. With Matplotlib v1.1, you may create a colorbar as a subplot using
the gridspec.
plt.close('all')
arr = np.arange(100).reshape((10,10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")
plt.colorbar(im, use_gridspec=True)
plt.tight_layout()
3.1. Introductory                                                                                      53
Matplotlib, Release 2.0.2
  0
                                                            80
  2
                                                            60
  4
6 40
8 20
       0        2         4        6         8
                                                            0
Another option is to use AxesGrid1 toolkit to explicitly create an axes for colorbar.
plt.close('all')
arr = np.arange(100).reshape((10,10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")
plt.tight_layout()
54                                                                                      Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
  0
                                                             80
  2
                                                             60
  4
                                                             40
  6
                                                             20
  8
                                                             0
       0         2         4         6         8
3.2 Intermediate
There are three layers to the matplotlib API. The matplotlib.backend_bases.FigureCanvas is the area
onto which the figure is drawn, the matplotlib.backend_bases.Renderer is the object which knows
how to draw on the FigureCanvas, and the matplotlib.artist.Artist is the object that knows how to
use a renderer to paint onto the canvas. The FigureCanvas and Renderer handle all the details of talking
to user interface toolkits like wxPython or drawing languages like PostScript®, and the Artist handles all
the high level constructs like representing and laying out the figure, text, and lines. The typical user will
spend 95% of their time working with the Artists.
There are two types of Artists: primitives and containers. The primitives represent the standard graphical
objects we want to paint onto our canvas: Line2D, Rectangle, Text, AxesImage, etc., and the containers
are places to put them (Axis, Axes and Figure). The standard use is to create a Figure instance, use
the Figure to create one or more Axes or Subplot instances, and use the Axes instance helper methods
to create the primitives. In the example below, we create a Figure instance using matplotlib.pyplot.
figure(), which is a convenience method for instantiating Figure instances and connecting them with
your user interface or drawing toolkit FigureCanvas. As we will discuss below, this is not necessary –
you can work directly with PostScript, PDF Gtk+, or wxPython FigureCanvas instances, instantiate your
Figures directly and connect them yourselves – but since we are focusing here on the Artist API we’ll
let pyplot handle some of those details for us:
3.2. Intermediate                                                                                         55
Matplotlib, Release 2.0.2
The Axes is probably the most important class in the matplotlib API, and the one you will be working with
most of the time. This is because the Axes is the plotting area into which most of the objects go, and the
Axes has many special helper methods (plot(), text(), hist(), imshow()) to create the most common
graphics primitives (Line2D, Text, Rectangle, Image, respectively). These helper methods will take your
data (e.g., numpy arrays and strings) and create primitive Artist instances as needed (e.g., Line2D), add
them to the relevant containers, and draw them when requested. Most of you are probably familiar with the
Subplot, which is just a special case of an Axes that lives on a regular rows by columns grid of Subplot
instances. If you want to create an Axes at an arbitrary location, simply use the add_axes() method which
takes a list of [left, bottom, width, height] values in 0-1 relative figure coordinates:
fig2 = plt.figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
In this example, ax is the Axes instance created by the fig.add_subplot call above (remember Subplot
is just a subclass of Axes) and when you call ax.plot, it creates a Line2D instance and adds it to the
Axes.lines list. In the interactive ipython session below, you can see that the Axes.lines list is length
one and contains the same line that was returned by the line, = ax.plot... call:
In [101]: ax.lines[0]
Out[101]: <matplotlib.lines.Line2D instance at 0x19a95710>
In [102]: line
Out[102]: <matplotlib.lines.Line2D instance at 0x19a95710>
If you make subsequent calls to ax.plot (and the hold state is “on” which is the default) then additional
lines will be added to the list. You can remove lines later simply by calling the list methods; either of these
will work:
del ax.lines[0]
ax.lines.remove(line)       # one or the other, not both!
The Axes also has helper methods to configure and decorate the x-axis and y-axis tick, tick labels and axis
labels:
xtext = ax.set_xlabel('my xdata') # returns a Text instance
ytext = ax.set_ylabel('my ydata')
When you call ax.set_xlabel, it passes the information on the Text instance of the XAxis. Each Axes
instance contains an XAxis and a YAxis instance, which handle the layout and drawing of the ticks, tick
labels and axis labels.
56                                                                                     Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
                                         a sine wave
        1.0
        0.5
volts
        0.0
        0.5
        1.0
                  0.0       0.2          0.4        0.6           0.8          1.0
          60
          40
          20
              0
                  4     3     2      1      0      1       2       3       4
                                          time (s)
Every element in the figure is represented by a matplotlib Artist, and each has an extensive list of proper-
ties to configure its appearance. The figure itself contains a Rectangle exactly the size of the figure, which
you can use to set the background color and transparency of the figures. Likewise, each Axes bounding
box (the standard white box with black edges in the typical matplotlib plot, has a Rectangle instance that
determines the color, transparency, and other properties of the Axes. These instances are stored as mem-
ber variables Figure.patch and Axes.patch (“Patch” is a name inherited from MATLAB, and is a 2D
“patch” of color on the figure, e.g., rectangles, circles and polygons). Every matplotlib Artist has the
following properties
3.2. Intermediate                                                                                          57
Matplotlib, Release 2.0.2
 Property     Description
 alpha        The transparency - a scalar from 0-1
 animated     A boolean that is used to facilitate animated drawing
 axes         The axes that the Artist lives in, possibly None
 clip_box     The bounding box that clips the Artist
 clip_on      Whether clipping is enabled
 clip_path    The path the artist is clipped to
 contains     A picking function to test whether the artist contains the pick point
 figure       The figure instance the artist lives in, possibly None
 label        A text label (e.g., for auto-labeling)
 picker       A python object that controls object picking
 transform    The transformation
 visible      A boolean whether the artist should be drawn
 zorder       A number which determines the drawing order
 rasterized   Boolean; Turns vectors into rastergraphics: (for compression & eps transparency)
Each of the properties is accessed with an old-fashioned setter or getter (yes we know this irritates Python-
istas and we plan to support direct access via properties or traits but it hasn’t been done yet). For example,
to multiply the current alpha by a half:
a = o.get_alpha()
o.set_alpha(0.5*a)
If you want to set a number of properties at once, you can also use the set method with keyword arguments.
For example:
o.set(alpha=0.5, zorder=2)
If you are working interactively at the python shell, a handy way to inspect the Artist properties is to use
the matplotlib.artist.getp() function (simply getp() in pylab), which lists the properties and their
values. This works for classes derived from Artist as well, e.g., Figure and Rectangle. Here are the
Figure rectangle properties mentioned above:
In [149]: matplotlib.artist.getp(fig.patch)
    alpha = 1.0
    animated = False
    antialiased or aa = True
    axes = None
    clip_box = None
    clip_on = False
    clip_path = None
    contains = None
    edgecolor or ec = w
    facecolor or fc = 0.75
    figure = Figure(8.125x6.125)
    fill = 1
    hatch = None
    height = 1
    label =
    linewidth or lw = 1.0
    picker = None
58                                                                                    Chapter 3. Tutorials
                                                                                   Matplotlib, Release 2.0.2
The docstrings for all of the classes also contain the Artist properties, so you can consult the interactive
“help” or the artist Module for a listing of properties for a given object.
Object containers
Now that we know how to inspect and set the properties of a given object we want to configure, we need to
know how to get at that object. As mentioned in the introduction, there are two kinds of objects: primitives
and containers. The primitives are usually the things you want to configure (the font of a Text instance,
the width of a Line2D) although the containers also have some properties as well – for example the Axes
Artist is a container that contains many of the primitives in your plot, but it also has properties like the
xscale to control whether the xaxis is ‘linear’ or ‘log’. In this section we’ll review where the various
container objects store the Artists that you want to get at.
Figure container
The top level container Artist is the matplotlib.figure.Figure, and it contains everything in the
figure. The background of the figure is a Rectangle which is stored in Figure.patch. As you add
subplots (add_subplot()) and axes (add_axes()) to the figure these will be appended to the Figure.
axes. These are also returned by the methods that create them:
In [159]: ax1
Out[159]: <matplotlib.axes.Subplot instance at 0xd54b26c>
Because the figure maintains the concept of the “current axes” (see Figure.gca and Figure.sca) to
support the pylab/pyplot state machine, you should not insert or remove axes directly from the axes list, but
rather use the add_subplot() and add_axes() methods to insert, and the delaxes() method to delete.
You are free however, to iterate over the list of axes or index into it to get access to Axes instances you want
to customize. Here is an example which turns all the axes grids on:
3.2. Intermediate                                                                                            59
Matplotlib, Release 2.0.2
for ax in fig.axes:
    ax.grid(True)
The figure also has its own text, lines, patches and images, which you can use to add primitives directly. The
default coordinate system for the Figure will simply be in pixels (which is not usually what you want) but
you can control this by setting the transform property of the Artist you are adding to the figure.
More useful is “figure coordinates” where (0, 0) is the bottom-left of the figure and (1, 1) is the top-right of
the figure which you can obtain by setting the Artist transform to fig.transFigure:
In [195]: fig.canvas.draw()
60                                                                                      Chapter 3. Tutorials
                                                                                   Matplotlib, Release 2.0.2
Axes container
The matplotlib.axes.Axes is the center of the matplotlib universe – it contains the vast majority of all
the Artists used in a figure with many helper methods to create and add these Artists to itself, as well
as helper methods to access and customize the Artists it contains. Like the Figure, it contains a Patch
patch which is a Rectangle for Cartesian coordinates and a Circle for polar coordinates; this patch
determines the shape, background and border of the plotting region:
ax = fig.add_subplot(111)
rect = ax.patch # a Rectangle instance
rect.set_facecolor('green')
When you call a plotting method, e.g., the canonical plot() and pass in arrays or lists of values, the method
will create a matplotlib.lines.Line2D() instance, update the line with all the Line2D properties passed
as keyword arguments, add the line to the Axes.lines container, and returns it to you:
plot returns a list of lines because you can pass in multiple x, y pairs to plot, and we are unpacking the first
element of the length one list into the line variable. The line has been added to the Axes.lines list:
Similarly, methods that create patches, like bar() creates a list of rectangles, will add the patches to the
Axes.patches list:
In [234]: rectangles
Out[234]: <a list of 50 Patch objects>
You should not add objects directly to the Axes.lines or Axes.patches lists unless you know exactly
what you are doing, because the Axes needs to do a few things when it creates and adds an object. It sets the
figure and axes property of the Artist, as well as the default Axes transformation (unless a transformation is
set). It also inspects the data contained in the Artist to update the data structures controlling auto-scaling,
3.2. Intermediate                                                                                            61
Matplotlib, Release 2.0.2
so that the view limits can be adjusted to contain the plotted data. You can, nonetheless, create objects
yourself and add them directly to the Axes using helper methods like add_line() and add_patch().
Here is an annotated interactive session illustrating what is going on:
In [262]: ax = fig.add_subplot(111)
# and notice that the ax.add_patch method has set the axes
# instance
In [267]: print rect.get_axes()
Axes(0.125,0.1;0.775x0.8)
# notice that the xlimits of the Axes have not been changed
In [270]: print ax.get_xlim()
(0.0, 1.0)
# but the data limits have been updated to encompass the rectangle
In [271]: print ax.dataLim.bounds
(1.0, 1.0, 5.0, 12.0)
62                                                                                Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
There are many, many Axes helper methods for creating primitive Artists and adding them to their respec-
tive containers. The table below summarizes a small sampling of them, the kinds of Artist they create,
and where they store them
 Helper method                    Artist                    Container
 ax.annotate - text annotations   Annotate                  ax.texts
 ax.bar - bar charts              Rectangle                 ax.patches
 ax.errorbar - error bar plots    Line2D and Rectangle      ax.lines and ax.patches
 ax.fill - shared area            Polygon                   ax.patches
 ax.hist - histograms             Rectangle                 ax.patches
 ax.imshow - image data           AxesImage                 ax.images
 ax.legend - axes legends         Legend                    ax.legends
 ax.plot - xy plots               Line2D                    ax.lines
 ax.scatter - scatter charts      PolygonCollection         ax.collections
 ax.text - text                   Text                      ax.texts
In addition to all of these Artists, the Axes contains two important Artist containers: the XAxis and
YAxis, which handle the drawing of the ticks and labels. These are stored as instance variables xaxis and
yaxis. The XAxis and YAxis containers will be detailed below, but note that the Axes contains many
helper methods which forward calls on to the Axis instances so you often do not need to work with them
directly unless you want to. For example, you can set the font color of the XAxis ticklabels using the Axes
helper method:
Axis containers
The matplotlib.axis.Axis instances handle the drawing of the tick lines, the grid lines, the tick labels
and the axis label. You can configure the left and right ticks separately for the y-axis, and the upper and
lower ticks separately for the x-axis. The Axis also stores the data and view intervals used in auto-scaling,
panning and zooming, as well as the Locator and Formatter instances which control where the ticks are
placed and how they are represented as strings.
Each Axis object contains a label attribute (this is what pylab modifies in calls to xlabel() and
3.2. Intermediate                                                                                         63
Matplotlib, Release 2.0.2
ylabel()) as well as a list of major and minor ticks. The ticks are XTick and YTick instances, which
contain the actual line and text primitives that render the ticks and ticklabels. Because the ticks are dynam-
ically created as needed (e.g., when panning and zooming), you should access the lists of major and minor
ticks through their accessor methods get_major_ticks() and get_minor_ticks(). Although the ticks
contain all the primitives and will be covered below, Axis instances have accessor methods that return the
tick lines, tick labels, tick locations etc.:
In [286]: axis.get_ticklocs()
Out[286]: array([ 0., 1., 2.,           3.,   4.,   5.,    6.,   7.,   8.,   9.])
In [287]: axis.get_ticklabels()
Out[287]: <a list of 10 Text major ticklabel objects>
Here is a summary of some of the useful accessor methods of the Axis (these have corresponding setters
where useful, such as set_major_formatter)
 Accessor method         Description
 get_scale               The scale of the axis, e.g., ‘log’ or ‘linear’
 get_view_interval       The interval instance of the axis view limits
 get_data_interval       The interval instance of the axis data limits
 get_gridlines           A list of grid lines for the Axis
 get_label               The axis label - a Text instance
 get_ticklabels          A list of Text instances - keyword minor=True|False
 get_ticklines           A list of Line2D instances - keyword minor=True|False
 get_ticklocs            A list of Tick locations - keyword minor=True|False
 get_major_locator       The matplotlib.ticker.Locator instance for major ticks
 get_major_formatter     The matplotlib.ticker.Formatter instance for major ticks
 get_minor_locator       The matplotlib.ticker.Locator instance for minor ticks
 get_minor_formatter     The matplotlib.ticker.Formatter instance for minor ticks
 get_major_ticks         A list of Tick instances for major ticks
 get_minor_ticks         A list of Tick instances for minor ticks
 grid                    Turn the grid on or off for the major or minor ticks
Here is an example, not recommended for its beauty, which customizes the axes and tick properties
64                                                                                    Chapter 3. Tutorials
                                                           Matplotlib, Release 2.0.2
import numpy as np
import matplotlib.pyplot as plt
plt.show()
3.2. Intermediate                                                                65
Matplotlib, Release 2.0.2
     1.0
     0.8
     0.6
     0.4
     0.2
     0.0
  0.0
  0.2
  0.4
  0.6
  0.8
  1.0
Tick containers
The matplotlib.axis.Tick is the final container object in our descent from the Figure to the Axes to
the Axis to the Tick. The Tick contains the tick and grid line instances, as well as the label instances for
the upper and lower ticks. Each of these is accessible directly as an attribute of the Tick. In addition, there
are boolean variables that determine whether the upper labels and ticks are on for the x-axis and whether the
right labels and ticks are on for the y-axis.
 Tick attribute   Description
 tick1line        Line2D instance
 tick2line        Line2D instance
 gridline         Line2D instance
 label1           Text instance
 label2           Text instance
 gridOn           boolean which determines whether to draw the gridline
 tick1On          boolean which determines whether to draw the 1st tickline
 tick2On          boolean which determines whether to draw the 2nd tickline
 label1On         boolean which determines whether to draw the 1st tick label
 label2On         boolean which determines whether to draw the 2nd tick label
Here is an example which sets the formatter for the right side ticks with dollar signs and colors them green
on the right side of the yaxis
66                                                                                     Chapter 3. Tutorials
                                                              Matplotlib, Release 2.0.2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(100*np.random.rand(20))
plt.show()
$100.00
$80.00
$60.00
$40.00
$20.00
3.2. Intermediate                                                                   67
Matplotlib, Release 2.0.2
This legend guide is an extension of the documentation available at legend() - please ensure you are
familiar with contents of that documentation before proceeding with this guide.
This guide makes use of some common terms, which are documented here for clarity:
legend entry A legend is made up of one or more legend entries. An entry is made up of exactly one key
      and one label.
legend key The colored/patterned marker to the left of each legend label.
legend label   The text which describes the handle represented by the key.
legend handle The original object which is used to generate an appropriate entry in the legend.
Calling legend() with no arguments automatically fetches the legend handles and their associated labels.
This functionality is equivalent to:
The get_legend_handles_labels() function returns a list of handles/artists which exist on the Axes
which can be used to generate entries for the resulting legend - it is worth noting however that not all artists
can be added to a legend, at which point a “proxy” will have to be created (see Creating artists specifically
for adding to the legend (aka. Proxy artists) for further details).
For full control of what is being added to the legend, it is common to pass the appropriate handles directly
to legend():
In some cases, it is not possible to set the label of the handle, so it is possible to pass through the list of
labels to legend():
Creating artists specifically for adding to the legend (aka. Proxy artists)
Not all handles can be turned into legend entries automatically, so it is often necessary to create an artist
which can. Legend handles don’t have to exists on the Figure or Axes in order to be used.
Suppose we wanted to create a legend which has an entry for some data which is represented by a red color:
68                                                                                      Chapter 3. Tutorials
                                                                               Matplotlib, Release 2.0.2
plt.show()
      1.0
                                                                The red data
0.8
0.6
0.4
0.2
      0.0
         0.0           0.2           0.4           0.6           0.8           1.0
There are many supported legend handles, instead of creating a patch of color we could have created a line
with a marker:
plt.show()
3.2. Intermediate                                                                                      69
Matplotlib, Release 2.0.2
      1.0
                                                                     Blue stars
0.8
0.6
0.4
0.2
      0.0
         0.0            0.2           0.4            0.6           0.8            1.0
Legend location
The location of the legend can be specified by the keyword argument loc. Please see the documentation at
legend() for more details.
The bbox_to_anchor keyword gives a great degree of control for manual legend placement. For example,
if you want your axes legend located at the figure’s top right-hand corner instead of the axes’ corner, simply
specify the corner’s location, and the coordinate system of that location:
plt.legend(bbox_to_anchor=(1, 1),
           bbox_transform=plt.gcf().transFigure)
plt.subplot(211)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# Place a legend above this subplot, expanding itself to
# fully use the given bounding box.
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
           ncol=2, mode="expand", borderaxespad=0.)
70                                                                                      Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
plt.subplot(223)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# Place a legend to the right of this smaller subplot.
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
                   test1                                                    test2
      3.0
      2.5
      2.0
      1.5
      1.0
          0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00
      3.0                          test1
                                   test2
      2.5
      2.0
      1.5
      1.0
             0             1              2
Sometimes it is more clear to split legend entries across multiple legends. Whilst the instinctive approach
to doing this might be to call the legend() function multiple times, you will find that only one legend ever
exists on the Axes. This has been done so that it is possible to call legend() repeatedly to update the legend
to the latest handles on the Axes, so to persist old legend instances, we must add them manually to the Axes:
3.2. Intermediate                                                                                          71
Matplotlib, Release 2.0.2
plt.show()
      3.00                                                              Line 1
      2.75
      2.50
      2.25
      2.00
      1.75
      1.50
      1.25
      1.00                                                              Line 2
             0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00
Legend Handlers
In order to create legend entries, handles are given as an argument to an appropriate HandlerBase subclass.
The choice of handler subclass is determined by the following rules:
     1. Update get_legend_handler_map() with the value in the handler_map keyword.
     2. Check if the handle is in the newly created handler_map.
     3. Check if the type of handle is in the newly created handler_map.
     4. Check if any of the types in the handle‘s mro is in the newly created handler_map.
For completeness, this logic is mostly implemented in get_legend_handler().
72                                                                                  Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
All of this flexibility means that we have the necessary hooks to implement custom handlers for our own
type of legend key.
The simplest example of using custom handlers is to instantiate one of the existing HandlerBase subclasses.
For the sake of simplicity, let’s choose matplotlib.legend_handler.HandlerLine2D which accepts a
numpoints argument (note numpoints is a keyword on the legend() function for convenience). We can
then pass the mapping of instance to Handler as a keyword to legend.
plt.legend(handler_map={line1: HandlerLine2D(numpoints=4)})
    3.00
    2.75
    2.50
    2.25
                                                                        Line 1
    2.00                                                                Line 2
    1.75
    1.50
    1.25
    1.00
           0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00
As you can see, “Line 1” now has 4 marker points, where “Line 2” has 2 (the default). Try the above code,
only change the map’s key from line1 to type(line1). Notice how now both Line2D instances get 4
markers.
Along with handlers for complex plot types such as errorbars, stem plots and histograms, the default
handler_map has a special tuple handler (HandlerTuple) which simply plots the handles on top of
one another for each item in the given tuple. The following example demonstrates combining two legend
keys on top of one another:
3.2. Intermediate                                                                                       73
Matplotlib, Release 2.0.2
z = randn(10)
      2.0
                   Attr A
      1.5          Attr A+B
      1.0
      0.5
      0.0
      0.5
      1.0
      1.5
0 2 4 6 8
A custom handler can be implemented to turn any handle into a legend key (handles don’t necessarily need
to be matplotlib artists). The handler must implement a “legend_artist” method which returns a single artist
for the legend to use. Signature details about the “legend_artist” are documented at legend_artist().
class AnyObject(object):
    pass
74                                                                                  Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
class AnyObjectHandler(object):
    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        width, height = handlebox.width, handlebox.height
        patch = mpatches.Rectangle([x0, y0], width, height, facecolor='red',
                                    edgecolor='black', hatch='xx', lw=3,
                                    transform=handlebox.get_transform())
        handlebox.add_artist(patch)
        return patch
     1.0
                                                           My first handler
0.8
0.6
0.4
0.2
     0.0
        0.0           0.2           0.4           0.6          0.8            1.0
Alternatively, had we wanted to globally accept AnyObject instances without needing to manually set the
handler_map keyword all the time, we could have registered the new handler with:
from matplotlib.legend import Legend
Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})
Whilst the power here is clear, remember that there are already many handlers implemented and what you
want to achieve may already be easily possible with existing classes. For example, to produce elliptical
legend keys, rather than rectangular ones:
from matplotlib.legend_handler import HandlerPatch
import matplotlib.pyplot as plt
3.2. Intermediate                                                                                    75
Matplotlib, Release 2.0.2
class HandlerEllipse(HandlerPatch):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
        p = mpatches.Ellipse(xy=center, width=width + xdescent,
                             height=height + ydescent)
        self.update_prop(p, orig_handle, legend)
        p.set_transform(trans)
        return [p]
      1.0
                                                 An ellipse, not a rectangle
0.8
0.6
0.4
0.2
      0.0
         0.0           0.2           0.4           0.6           0.8           1.0
Here is a non-exhaustive list of the examples available involving legend being used in various ways:
76                                                                                   Chapter 3. Tutorials
                                                                               Matplotlib, Release 2.0.2
3.3 Advanced
Like any graphics packages, matplotlib is built on top of a transformation framework to easily move be-
tween coordinate systems, the userland data coordinate system, the axes coordinate system, the figure
coordinate system, and the display coordinate system. In 95% of your plotting, you won’t need to think
about this, as it happens under the hood, but as you push the limits of custom figure generation, it helps
to have an understanding of these objects so you can reuse the existing transformations matplotlib makes
available to you, or create your own (see matplotlib.transforms). The table below summarizes the ex-
isting coordinate systems, the transformation object you should use to work in that coordinate system, and
the description of that system. In the Transformation Object column, ax is a Axes instance, and fig is
a Figure instance.
 Co-      Transfor-     Description
 ordi-    mation
 nate     Object
 data   ax.        The userland data coordinate system, controlled by the xlim and ylim
        transData
 axes ax.          The coordinate system of the Axes; (0,0) is bottom left of the axes, and (1,1) is
        transAxes top right of the axes.
 figure fig.       The coordinate system of the Figure; (0,0) is bottom left of the figure, and (1,1)
        transFigureis top right of the figure.
 displayNone       This is the pixel coordinate system of the display; (0,0) is the bottom left of the
                   display, and (width, height) is the top right of the display in pixels. Alternatively,
                   the identity transform (matplotlib.transforms.IdentityTransform())
                   may be used instead of None.
All of the transformation objects in the table above take inputs in their coordinate system, and transform
the input to the display coordinate system. That is why the display coordinate system has None for the
Transformation Object column – it already is in display coordinates. The transformations also know
how to invert themselves, to go from display back to the native coordinate system. This is particularly
useful when processing events from the user interface, which typically occur in display space, and you want
to know where the mouse click or key-press occurred in your data coordinate system.
3.3. Advanced                                                                                           77
Matplotlib, Release 2.0.2
Data coordinates
Let’s start with the most commonly used coordinate, the data coordinate system. Whenever you add data to
the axes, matplotlib updates the datalimits, most commonly updated with the set_xlim() and set_ylim()
methods. For example, in the figure below, the data limits stretch from 0 to 10 on the x-axis, and -1 to 1 on
the y-axis.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
plt.show()
     1.00
     0.75
     0.50
     0.25
     0.00
     0.25
     0.50
     0.75
     1.00
            0            2             4             6             8             10
You can use the ax.transData instance to transform from your data to your display coordinate system,
either a single point or a sequence of points as shown below:
78                                                                                    Chapter 3. Tutorials
                                                                                  Matplotlib, Release 2.0.2
In [14]: type(ax.transData)
Out[14]: <class 'matplotlib.transforms.CompositeGenericTransform'>
You can use the inverted() method to create a transform which will take you from display to data coordi-
nates:
In [42]: type(inv)
Out[42]: <class 'matplotlib.transforms.CompositeGenericTransform'>
If your are typing along with this tutorial, the exact values of the display coordinates may differ if you have
a different window size or dpi setting. Likewise, in the figure below, the display labeled points are probably
not the same as in the ipython session because the documentation figure size defaults are different.
    1.00
    0.75
               data = (5.0, 0.0)
    0.50
    0.25
    0.00                                                                   display = (281.9, 222.8)
    0.25
    0.50
    0.75
    1.00
           0             2              4             6              8             10
3.3. Advanced                                                                                               79
Matplotlib, Release 2.0.2
Note: If you run the source code in the example above in a GUI backend, you may also find that the two
arrows for the data and display annotations do not point to exactly the same point. This is because the
display point was computed before the figure was displayed, and the GUI backend may slightly resize the
figure when it is created. The effect is more pronounced if you resize the figure yourself. This is one good
reason why you rarely want to work in display space, but you can connect to the 'on_draw' Event to
update figure coordinates on figure draws; see Event handling and picking.
When you change the x or y limits of your axes, the data limits are updated so the transformation yields a
new display point. Note that when we just change the ylim, only the y-display coordinate is altered, and
when we change the xlim too, both are altered. More on this later when we talk about the Bbox.
In [55]: ax.set_ylim(-1,2)
Out[55]: (-1, 2)
In [57]: ax.set_xlim(10,20)
Out[57]: (10, 20)
Axes coordinates
After the data coordinate system, axes is probably the second most useful coordinate system. Here the
point (0,0) is the bottom left of your axes or subplot, (0.5, 0.5) is the center, and (1.0, 1.0) is the top right.
You can also refer to points outside the range, so (-0.1, 1.1) is to the left and above your axes. This coordinate
system is extremely useful when placing text in your axes, because you often want a text bubble in a fixed,
location, e.g., the upper left of the axes pane, and have that location remain fixed when you pan or zoom.
Here is a simple example that creates four panels and labels them ‘A’, ‘B’, ‘C’, ‘D’ as you often see in
journals.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
for i, label in enumerate(('A', 'B', 'C', 'D')):
    ax = fig.add_subplot(2,2,i+1)
    ax.text(0.05, 0.95, label, transform=ax.transAxes,
      fontsize=16, fontweight='bold', va='top')
plt.show()
80                                                                                       Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
      1.0                      1.0
      0.8
             A                 0.8
                                                    B
      0.6                      0.6
      0.4                      0.4
      0.2                      0.2
      0.0                      0.0
        0.00 0.25 0.50 0.75 1.00 0.00 0.25 0.50 0.75 1.00
      1.0                      1.0
      0.8
             C                 0.8
                                                    D
      0.6                      0.6
      0.4                      0.4
      0.2                      0.2
      0.0                      0.0
        0.00 0.25 0.50 0.75 1.00 0.00 0.25 0.50 0.75 1.00
You can also make lines or patches in the axes coordinate system, but this is less useful in my experience
than using ax.transAxes for placing text. Nonetheless, here is a silly example which plots some random
dots in data space, and overlays a semi-transparent Circle centered in the middle of the axes with a radius
one quarter of the axes – if your axes does not preserve aspect ratio (see set_aspect()), this will look like
an ellipse. Use the pan/zoom tool to move around, or manually change the data xlim and ylim, and you
will see the data move, but the circle will remain fixed because it is not in data coordinates and will always
remain at the center of the axes.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
x, y = 10*np.random.rand(2, 1000)
ax.plot(x, y, 'go') # plot some data in data coordinates
plt.show()
3.3. Advanced                                                                                              81
Matplotlib, Release 2.0.2
10
         0
              0            2            4            6            8            10
Blended transformations
Drawing in blended coordinate spaces which mix axes with data coordinates is extremely useful, for
example to create a horizontal span which highlights some region of the y-data but spans across the x-axis
regardless of the data limits, pan or zoom level, etc. In fact these blended lines and spans are so useful, we
have built in functions to make them easy to plot (see axhline(), axvline(), axhspan(), axvspan())
but for didactic purposes we will implement the horizontal span here using a blended transformation. This
trick only works for separable transformations, like you see in normal Cartesian coordinate systems, but not
on inseparable transformations like the PolarTransform.
import   numpy as np
import   matplotlib.pyplot as plt
import   matplotlib.patches as patches
import   matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.random.randn(1000)
ax.hist(x, 30)
ax.set_title(r'$\sigma=1 \/ \dots \/ \sigma=2$', fontsize=16)
82                                                                                    Chapter 3. Tutorials
                                                                              Matplotlib, Release 2.0.2
ax.add_patch(rect)
plt.show()
                                     =1            =2
     100
80
60
40
20
        0
                  3        2        1       0        1        2       3        4
Note: The blended transformations where x is in data coords and y in axes coordinates is so useful
that we have helper methods to return the versions mpl uses internally for drawing ticks, ticklabels, etc.
The methods are matplotlib.axes.Axes.get_xaxis_transform() and matplotlib.axes.Axes.
get_yaxis_transform(). So in the example above, the call to blended_transform_factory() can
be replaced by get_xaxis_transform:
trans = ax.get_xaxis_transform()
3.3. Advanced                                                                                          83
Matplotlib, Release 2.0.2
One use of transformations is to create a new transformation that is offset from another transformation, e.g.,
to place one object shifted a bit relative to another object. Typically you want the shift to be in some physical
dimension, like points or inches rather than in data coordinates, so that the shift effect is constant at different
zoom levels and dpi settings.
One use for an offset is to create a shadow effect, where you draw one object identical to the first just to the
right of it, and just below it, adjusting the zorder to make sure the shadow is drawn first and then the object
it is shadowing above it. The transforms module has a helper transformation ScaledTranslation. It is
instantiated with:
trans = ScaledTranslation(xt, yt, scale_trans)
where xt and yt are the translation offsets, and scale_trans is a transformation which scales xt and
yt at transformation time before applying the offsets. A typical use case is to use the figure fig.
dpi_scale_trans transformation for the scale_trans argument, to first scale xt and yt specified in
points to display space before doing the final offset. The dpi and inches offset is a common-enough use
case that we have a special helper function to create it in matplotlib.transforms.offset_copy(),
which returns a new transform with an added offset. But in the example below, we’ll create the offset
transform ourselves. Note the use of the plus operator in:
offset = transforms.ScaledTranslation(dx, dy,
  fig.dpi_scale_trans)
shadow_transform = ax.transData + offset
showing that can chain transformations using the addition operator. This code says: first apply the data
transformation ax.transData and then translate the data by dx and dy points. In typography, a‘point
<https://en.wikipedia.org/wiki/Point_%28typography%29>‘_ is 1/72 inches, and by specifying your offsets
in points, your figure will look the same regardless of the dpi resolution it is saved in.
import   numpy as np
import   matplotlib.pyplot as plt
import   matplotlib.patches as patches
import   matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
84                                                                                        Chapter 3. Tutorials
                                                                                 Matplotlib, Release 2.0.2
The ax.transData transform we have been working with in this tutorial is a composite of three different
transformations that comprise the transformation pipeline from data -> display coordinates. Michael
Droettboom implemented the transformations framework, taking care to provide a clean API that segre-
gated the nonlinear projections and scales that happen in polar and logarithmic plots, from the linear affine
transformations that happen when you pan and zoom. There is an efficiency here, because you can pan and
zoom in your axes which affects the affine transformation, but you may not need to compute the potentially
expensive nonlinear scales or projections on simple navigation events. It is also possible to multiply affine
transformation matrices together, and then apply them to coordinates in one step. This is not true of all
possible transformations.
Here is how the ax.transData instance is defined in the basic separable axis Axes class:
3.3. Advanced                                                                                             85
Matplotlib, Release 2.0.2
We’ve been introduced to the transAxes instance above in Axes coordinates, which maps the (0,0), (1,1)
corners of the axes or subplot bounding box to display space, so let’s look at these other two pieces.
self.transLimits is the transformation that takes you from data to axes coordinates; i.e., it maps your
view xlim and ylim to the unit space of the axes (and transAxes then takes that unit space to display space).
We can see this in action here
In [80]: ax = subplot(111)
In [82]: ax.set_ylim(-1,1)
Out[82]: (-1, 1)
In [84]: ax.transLimits.transform((0,-1))
Out[84]: array([ 0., 0.])
In [85]: ax.transLimits.transform((10,-1))
Out[85]: array([ 1., 0.])
In [86]: ax.transLimits.transform((10,1))
Out[86]: array([ 1., 1.])
In [87]: ax.transLimits.transform((5,0))
Out[87]: array([ 0.5, 0.5])
and we can use this same inverted transformation to go from the unit axes coordinates back to data coor-
dinates.
The final piece is the self.transScale attribute, which is responsible for the optional non-linear scaling
of the data, e.g., for logarithmic axes. When an Axes is initially setup, this is just set to the identity trans-
form, since the basic matplotlib axes has linear scale, but when you call a logarithmic scaling function like
semilogx() or explicitly set the scale to logarithmic with set_xscale(), then the ax.transScale at-
tribute is set to handle the nonlinear projection. The scales transforms are properties of the respective xaxis
and yaxis Axis instances. For example, when you call ax.set_xscale('log'), the xaxis updates its
scale to a matplotlib.scale.LogScale instance.
For non-separable axes the PolarAxes, there is one more piece to consider, the projection transformation.
The transData matplotlib.projections.polar.PolarAxes is similar to that for the typical separable
matplotlib Axes, with one additional piece transProjection:
transProjection handles the projection from the space, e.g., latitude and longitude for map data, or radius
and theta for polar data, to a separable Cartesian coordinate system. There are several projection examples
in the matplotlib.projections package, and the best way to learn more is to open the source for those
packages and see how to make your own, since matplotlib supports extensible axes and projections. Michael
86                                                                                      Chapter 3. Tutorials
                                                                                  Matplotlib, Release 2.0.2
Droettboom has provided a nice tutorial example of creating a hammer projection axes; see api example
code: custom_projection_example.py.
The object underlying all of the matplotlib.patch objects is the Path , which supports the standard set of
moveto, lineto, curveto commands to draw simple and compound outlines consisting of line segments and
splines. The Path is instantiated with a (N,2) array of (x,y) vertices, and a N-length array of path codes. For
example to draw the unit rectangle from (0,0) to (1,1), we could use this code
verts = [
    (0., 0.),    #   left, bottom
    (0., 1.),    #   left, top
    (1., 1.),    #   right, top
    (1., 0.),    #   right, bottom
    (0., 0.),    #   ignored
    ]
codes = [Path.MOVETO,
         Path.LINETO,
         Path.LINETO,
         Path.LINETO,
         Path.CLOSEPOLY,
         ]
fig = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
plt.show()
3.3. Advanced                                                                                               87
Matplotlib, Release 2.0.2
     2.0
     1.5
     1.0
     0.5
     0.0
     0.5
     1.0
     1.5
     2.0
           2.0     1.5      1.0    0.5     0.0      0.5     1.0      1.5      2.0
Bézier example
Some of the path components require multiple vertices to specify them: for example CURVE 3 is a bézier
curve with one control point and one end point, and CURVE4 has three vertices for the two control points
and the end point. The example below shows a CURVE4 Bézier spline – the bézier curve will be contained
in the convex hull of the start point, the two control points, and the end point
88                                                                                  Chapter 3. Tutorials
                                                          Matplotlib, Release 2.0.2
verts = [
    (0., 0.),    #   P0
    (0.2, 1.),   #   P1
    (1., 0.8),   #   P2
    (0.8, 0.),   #   P3
    ]
codes = [Path.MOVETO,
         Path.CURVE4,
         Path.CURVE4,
         Path.CURVE4,
         ]
fig = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(path, facecolor='none', lw=2)
ax.add_patch(patch)
xs, ys = zip(*verts)
ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10)
ax.set_xlim(-0.1, 1.1)
ax.set_ylim(-0.1, 1.1)
plt.show()
3.3. Advanced                                                                   89
Matplotlib, Release 2.0.2
                          P1
      1.0
                                                                                 P2
      0.8
0.6
0.4
0.2
      0.0     P0                                                     P3
               0.0         0.2         0.4         0.6         0.8         1.0
Compound paths
All of the simple patch primitives in matplotlib, Rectangle, Circle, Polygon, etc, are implemented with
simple path. Plotting functions like hist() and bar(), which create a number of primitives, e.g., a bunch
of Rectangles, can usually be implemented more efficiently using a compound path. The reason bar creates
a list of rectangles and not a compound path is largely historical: the Path code is comparatively new and
bar predates it. While we could change it now, it would break old code, so here we will cover how to create
compound paths, replacing the functionality in bar, in case you need to do so in your own code for efficiency
reasons, e.g., you are creating an animated bar plot.
We will make the histogram chart by creating a series of rectangles for each histogram bar: the rectangle
width is the bin width and the rectangle height is the number of datapoints in that bin. First we’ll create
some random normally distributed data and compute the histogram. Because numpy returns the bin edges
and not centers, the length of bins is 1 greater than the length of n in the example below:
We’ll now extract the corners of the rectangles. Each of the left, bottom, etc, arrays below is len(n),
where n is the array of counts for each histogram bar:
90                                                                                    Chapter 3. Tutorials
                                                                                   Matplotlib, Release 2.0.2
Now we have to construct our compound path, which will consist of a series of MOVETO, LINETO and
CLOSEPOLY for each rectangle. For each rectangle, we need 5 vertices: 1 for the MOVETO, 3 for the LINETO,
and 1 for the CLOSEPOLY. As indicated in the table above, the vertex for the closepoly is ignored but we still
need it to keep the codes aligned with the vertices:
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5,0] = left
verts[0::5,1] = bottom
verts[1::5,0] = left
verts[1::5,1] = top
verts[2::5,0] = right
verts[2::5,1] = top
verts[3::5,0] = right
verts[3::5,1] = bottom
All that remains is to create the path, attach it to a PathPatch, and add it to our axes:
3.3. Advanced                                                                                              91
Matplotlib, Release 2.0.2
35
30
25
20
15
10
        0
                 3        2         1       0        1         2        3        4
Matplotlib’s patheffects module provides functionality to apply a multiple draw stage to any Artist which
can be rendered via a Path .
Artists which can have a path effect applied to them include Patch , Line2D, Collection and even Text.
Each artist’s path effects can be controlled via the set_path_effects method (set_path_effects),
which takes an iterable of AbstractPathEffect instances.
The simplest path effect is the Normal effect, which simply draws the artist without any effect:
92 Chapter 3. Tutorials