Working with matplotlib (JYP version)

Summary: there are lots of python libraries that you can use for plotting, but Matplotlib has become a de facto standard

Where: Matplotlib web site

Help on stack overflow: matplotlib help

The matplotlib documentation is good, but not always easy to use. A good way to start with matplotlib is to quickly read the following, practice, and read this section again

Have a quick look at the matplotlib gallery to get an idea of all you can do with matplotlib. Later, when you need to plot something, go back to the gallery to find some examples that are close to what you need and click on them to view their source code

some examples are more pythonic (ie object oriented) than others, and some examples mix different styles of coding, which can be quite confusing. Try to use an object oriented way of doing things!

Use the free hints provided by JY!

You will usually initialize matplotlib with: import matplotlib.pyplot as plt

in some cases you may also need: import matplotlib as mpl

later, you may need other matplotlib related modules, for advanced usage

You need to know some matplotlib specific vocabulary:

a Matplotlib Figure (or canvas) is a graphical window in which you create your plots…

example: my_page = plt.figure()

if you need several display windows at the same time, create several figures!

win_1 = plt.figure()
win_2 = plt.figure()

the parts of a figure are often positioned in normalized coordinates: (0, 0) is the bottom left of the figure, and (1, 1) the top right

You don't really specify the page orientation (portrait or landscape) of a plot. If you want a portrait plot, it's up to you to create a plot that will look higher than it is large. The idea is not to worry about this and just check the final resulting plot: create a plot, save it, display the resulting png/pdf and then adjust the creation script

If you do have an idea of the layout of what you want to plot, it may be easier to explicitly specify the figure size/ratio at creation time, and then try to fill the normalized coordinates space of the figure

my_page = plt.figure(): the ratio of the default figure is landscape, because it is 33% larger than it is high. Creating a default figure will be OK most of the time!

my_page = plt.figure(figsize=(width, height)): create a figure with a custom ratio (sizes are considered to be in inches)

my_page = plt.figure(figsize=(8.3, 11.7)): create a figure that will theoretically fill an A4 size page in portrait mode (check Dimensions Of A Series Paper Sizes if you need more size details)

a Matplotlib Axis is a plot inside a Figure… More details

reserve space for one plot that will use most of the available area of the figure/page:

my_plot = my_page.add_subplot(1, 1, 1): syntax is add_subplot(nrows, ncols, index)

my_plot = my_page.subplots()

create 3 plots on 1 column (each plot uses the full width of the figure):

top_plot = my_page.add_subplot(3, 1, 1)
middle_plot = my_page.add_subplot(3, 1, 2)
bottom_plot = my_page.add_subplot(3, 1, 3)

the following method is more efficient than add_subplot when there are lots of plots on a page

plot_array = my_page.subplots(3, 1)
top_plot = plot_array[0]
middle_plot = plot_array[1]
bottom_plot = plot_array[2]

creating a figure and axes with a single line: my_page, plot_array = plt.subplots(3, 1)

use my_page.add_axes(...) to add an axis in an arbirary location of the page
my_page.add_axes([left, bottom, width, height])

a Matplotlib Artist or Patch is something (e.g a line, a group of markers, text, the legend…) plotted on the Figure/Axis

clearing the page (or part of it): you probably won't need that…

my_page.clear() or my_page.clf() or plt.clf(): clear the (current) figure

my_plot.clear() or my_plot.cla(): clear the (current) axis

some resources for having multiple plots on the same figure

Easily creating subplots

fig.add_subplot(...)

fig.add_axes(...)

plt.subplot(...)

plt.subplots(...) with an s at the end (demo)

subplots_adjust can be used to change the overall boundaries of the subplots on the figure, and the spacing between the subplots
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
or my_page.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

hspace/wspace is the amount of height/width between the subplots

hspace=0.1 is enough for just displaying the ticks and the labels, without the axis name

use hspace=0 to stick the plots together vertically

do not forget to disable the ticks where there is no space to plot them: my_plot.set_xticks([])

my_page.subplots_adjust(right=0.75) will leave 25% on the right of the page for adding a legend outside of a plot

You can also resize an existing (sub)plot the following way:

Get the current size information: pl_x_bottomleft, pl_y_bottomleft, pl_width, pl_height = my_plot.get_position().bounds

Set the new size: e.g reduce the height with my_plot.set_position( (pl_x_bottomleft, pl_y_bottomleft, pl_width, pl_height * 0.5) )

Subplots, axes and figures gallery

Customizing Figure Layouts Using GridSpec and Other Functions, constrained layout and tight layout

use my_page.savefig(...) to save a figure

savefig(…) must be called before plt.show()!

my_page.savefig('my_plot.pdf'): save the figure to a pdf file

my_page.savefig('my_plot.png', dpi=200, transparent=True, bbox_inches='tight'): save the figure to a png file at a higher resolution than the default (default is 100 dots per inch), with a transparent background and no extra space around the figure

display the figure and its plots, and start interacting (zooming, panning…) with them:
plt.show()

it may be hard to (remember how to) work with colors and colorbars. Some examples from the matplotlib Gallery can help you!
Note: A reversed version of each colormap is available by appending _r to the name, e.g., viridis_r

leftventricle_bulleye.py: associating different types of colormaps to a plot and colorbar

colorbar_only.py: the different types of colorbars (or plotting only a colorbar)

colormaps_reference.py: pre-defined colormaps

named_colors.py: named colors

More details about colors and colorbars below, in the Useful matplotlib reference pages section and the Graphics related resources section

if you don't see a part of what you have plotted, maybe it's hidden behind other elements! Use the zorder parameter to explicitly specify the plotting order/layers/depth

things should automatically work as expected if zorder is not explicitly specified

Use the zorder=NN parameter when creating objects. NN is an integer where 0 is the lowest value (the farthest from the eye), and objects are plotted above objects with a lower zorder value

Use matplotlib_object.set_order(NN) to change the order after an object has been created

you can use transparency to partially show what is behind some markers or other objects. Many artists accept the alpha parameter where 0.0 means that the object is completely transparent, and 1.0 means completely opaque
e.g. my_plot.scatter(…, alpha=0.7)

sometimes the results of the python/matplolib commands are displayed immediately, sometimes not. It depends if you are in interactive or non-interactive mode

if your matplotlib is executed in a batch script, it will generate an error when trying to create (show()) a plot, because matplotlib expects to be able to display the figure on a screen by default.

Check how you can generate images offline

the documentation may mention backends. What?? Basically, you use python commands to create a plot, and the backend is the thing that will render your plot on the screen or in a file (png, pdf, etc…)

Read the Matplotlib tutorial by Nicolas Rougier

Download the pdf version of the manual. Do not print the 2300+ pages of the manual! Read the beginner's guide (Chapter FIVE of Part II) and have a super quick look at the table of contents of the whole document.

Useful matplotlib reference pages

Some plot types:

plot(...): Plot y versus x as lines and/or markers

scatter(...): A scatter plot of y vs x with varying marker size and/or color

The plot function will be faster for scatterplots where markers don't vary in size or color

contour(...) and contourf(...): draw contour lines and filled contours

X and Y axes parameters

Axis range: my_plot.set_xlim(x_leftmost_value, x_rightmost_value)

Use the leftmost and rightmost values to specify the orientation of the axis (i.e the rightmost value can be smaller than the leftmost)

Axis label: my_plot.set_xlabel(x_label_string, fontsize=axis_label_fontsize)

Use the extra labelpad parameter to move the label closer (negative value) to the axis or farther (positive value): e.g. my_plot.set_xlabel('A closer label', labelpad=-20

Major (and minor) tick marks location: my_plot.set_xticks(x_ticks_values, minor=False)

Use an empty list if you don't want tick marks: my_plot.set_xticks([])

Tick labels (if you don't want the default values): my_plot.set_xticklabels(x_ticks_labels, minor=False, fontsize=ticklabels_fontsize)

x_ticks_labels is a list of strings that has the same length as x_ticks_values. Use an empty string in the positions where you don't want a label

Many more options for ticks, labels, orientation, …

line parameters

linestyle: solid, None, other (default styles example, custom styles example)

marker types

Default marker size and edge width:

mpl.rcParams['lines.markersize'] ** 2 ⇒ 36

mpl.rcParams['lines.linewidth'] ⇒ 1.5

Other marker attributes. For plot, all the markers have the same attributes, and for scatter the attributes can be the same, or specified for each marker

plot(...): fmt (see documentation) or marker and markerfacecolor/mfc (and markerfacecoloralt/mfcalt for dual color markers), markersize, markeredgewidth/mew, markeredgecolor (use markeredgecolor='none' if you don't want to plot the edge of the markers), fillstyle (full, None, other)

scatter(...): marker (marker type), c (color), s (size), linewidths (linewidth of the marker edges), edgecolors

colors and colormaps

color demo

named colors

Reverting the colors: add _r at the end of the colormap name

Number of colors in the my_cmap colormap (usually 256): my_cmap.N

Accessing the RGB color definition by index, from 0 to my_cmap.N - 1. Note that the index will saturate below 0 and above my_cmap.N - 1

>>> my_cmap.N
256
>>> my_cmap(-1) # Same as ano_cmap(0)
(0.3686274509803922, 0.30980392156862746, 0.6352941176470588, 1.0)
>>> my_cmap(0)
(0.3686274509803922, 0.30980392156862746, 0.6352941176470588, 1.0)
>>> my_cmap(1)
(0.36186082276047676, 0.3185697808535179, 0.6394463667820068, 1.0)
>>> my_cmap(255)
(0.6196078431372549, 0.00392156862745098, 0.25882352941176473, 1.0)
>>> my_cmap(256) # Same as ano_cmap(255)
(0.6196078431372549, 0.00392156862745098, 0.25882352941176473, 1.0)
>>> my_cmap(257) # Same as ano_cmap(255)
(0.6196078431372549, 0.00392156862745098, 0.25882352941176473, 1.0)

Special colormap colors

my_cmap.set_bad(color='k'): color to be used for masked values

my_cmap.set_over(color='k'): color to be used for high out-of-range values if extend is specified and is 'both' or 'max'. Default color is my_cmap(my_cmap.N - 1)

my_cmap.set_under(color='k'): color to be used for low out-of-range values if extend is specified and is 'both' or 'min'. Default color is my_cmap(0)

colorbar

Placing colorbars demo

contourf + colorbar demo

text(...) and annotations

Some titles:

Figure title: my_figure.suptitle('Figure title', x=xloc_in_normalized_coordinates, y=yloc_in_normalized_coordinates, …)

Axis Labels, title, and legend: my_plot.set_title('Plot title', …)

fontsize: size in points, or (better!) string specifying a relative size (xx-small, x-small, small, medium, large, x-large, xx-large)

all the text properties

legend(...) (legend demo, advanced legend guide)

The legend will show the lines (or other objects) that were associated with a label with the label= keyword when creating/updating a plot

If there are some elements of a plot that you do not want to associate with a legend (e.g. there are several lines with the same color and markers, but you want to plot the legend only once), do not specify a label= keyword for these elements, or add a _ at the front of the label strings

The legend is positioned somewhere (that can be specified) inside the plot. In order to place a legend outside the plot, use the bbox_to_anchor parameter

the parameters of bbox_to_anchor are in normalized coordinates of the current (sub)plot:

(0, 0) is the lower left corner of the plot, and (1, 1) the upper right corner

legend(… bbox_to_anchor=(1.05, 1.), loc='upper left', …) will put the upper left corner of the legend slightly right ((1.05, 1.)) of the upper right corner ((1, 1)) of the plot

if the legend is outside of the plot, you have to explicitly provide enough space for the legend on the page

e.g. with subplots_adjust, plt.subplots_adjust(right=0.75) will make all the plots use 75% on the left of the page, and leave 25% on the right for the legend

The figure(...) and the associated methods

The axes and the associated methods

matplotlib default config/settings can be queried and updated

example: the default figure size (inches) is mpl.rcParams['figure.figsize'] ([6.4, 4.8])

current settings' file: mpl.matplotlib_fname()

Animations (demo)

Misc Matplotlib tricks

Specifying the background color of a plot (e.g. when plotting a masked variable and you don't want the masked areas to be white)

# make the background dark gray (call this before the contourf)
plt.gca().patch.set_color('.25')
plt.contourf(d)
plt.show()

trick source

[ PMIP3 Wiki Home ] - [ Help! ] - [ Wiki syntax ]