1.5. matplotlib - Plotting in Python#
Matplotlib has advantages:
Easy to get started (MATLAB-like interface)
Support for LaTeX formatted labels and texts
Output in many formats, including PNG, PDF, SVG, EPS, and PGF.
Extensive gallery of examples with source code (https://matplotlib.org/gallery.html)
Programmatic control over all aspects of figures
Programmatic control is a blessing and a curse…
Other plotting tools are available (Plotly, Bokeh, D3, …) but matplotlib
is the workhorse.
Matplotlib can be used in two ways:
pylab
modules (works like MATLAB)object-oreinted interface (harder but more powerful)
%matplotlib inline
1.5.1. MATLAB-like API#
The easiest way to get started with plotting using matplotlib is often to use the MATLAB-like API provided by matplotlib.
It is designed to be compatible with MATLAB’s plotting functions, so it is easy to get started with if you are familiar with MATLAB.
To use this API from matplotlib, we need to include the symbols in the pylab
module:
from pylab import *
x = np.linspace(0, 5, 10)
y = x ** 2
figure()
plot(x, y, 'r')
xlabel('x')
ylabel('y')
title('title')
show()
Most of the plotting related functions in MATLAB are covered by the pylab
module. For example, subplot and color/symbol selection:
subplot(1,2,1)
plot(x, y, 'r--')
subplot(1,2,2)
plot(y, x, 'g*-');
1.5.2. The matplotlib object-oriented interface#
The pylab
interface is easy, but limited.
Use simple global functions that match with MATLAB
Objects are implicitly defined and hidden from users.
The pyplot
object-oriented interface is harder to learn, but much more powerful.
Use objects instead of global functions.
Explicitly define objects - much better for multiple figures.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title');
fig = plt.figure()
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # inset axes
# main figure
axes1.plot(x, y, 'r')
axes1.set_xlabel('x')
axes1.set_ylabel('y')
axes1.set_title('title')
# insert
axes2.plot(y, x, 'g')
axes2.set_xlabel('y')
axes2.set_ylabel('x')
axes2.set_title('insert title');
This gives us lots of control, but can also be inconvenient. There are tools to make life a little easier, like subplots
:
fig, axes = plt.subplots()
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title');
fig, axes = plt.subplots(nrows=1, ncols=2)
for ax in axes:
ax.plot(x, y, 'r')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
#fig.tight_layout()
1.5.2.1. Figure size, aspect ratio and DPI#
Matplotlib allows control of:
figure size (aspect ration)
dpi (resolution)
when the figure is created. This also works with subplots
. If you are planning to put the figure into a report/manuscript it is worthwhile to set this!
fig = plt.figure(figsize=(8,4), dpi=100)
#OR
fig, axes = plt.subplots(figsize=(8,4))
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')
1.5.2.2. Saving figures#
To save a figure to a file we can use the savefig
method in the Figure
class. You can output in many formats, but the most common are:
PNG (raster)
JPG (raster)
SVG (vector)
PDF (vector)
The SVG and PDF formats are great because they can be edited afterward with vector graphics programs like Inkscape or Adobe Illustrator.
# if saving rasterized images you can set the dpi (300 is standard)
fig.savefig("filename.png", dpi=300)
fig.savefig("filename.pdf")
1.5.2.3. Titles, labels, and legends#
You should always label axes (including units!), and legends are useful if you have many things plotted at once. You can also set the title of each axis. Note that these are controlled by the axes
object, not the Figure
object.
axes.set_title("title")
axes.set_xlabel("x [units]")
axes.set_ylabel("y [units]")
fig
Legends
Legends for curves in a figure can be added in two ways.
legend
method of the axis objectlabel
argument of plot
axes.legend(["curve1"]);
fig
axes.plot(x, x**2, label="curve1")
axes.plot(x, x**3, label="curve2")
axes.legend()
fig
axes.legend(loc=0) # let matplotlib decide the optimal location
axes.legend(loc=1) # upper right corner
axes.legend(loc=2) # upper left corner
axes.legend(loc=3) # lower left corner
axes.legend(loc=4) # lower right corner
# .. many more options are available
fig
Putting it all together…
fig, ax = plt.subplots()
ax.plot(x, x**2, label="y = x**2")
ax.plot(x, x**3, label="y = x**3")
ax.legend(loc=2); # upper left corner
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title');
1.5.2.4. Setting colors, linewidths, linetypes#
When plotting a line the following keyword arguments control its properties:
color (r, g, b, k, y, m, #000000,…)
alpha (0 to 1 for transparancy)
marker (‘o’,’+’,’^’,…)
linestyle or ls (‘-’, ‘:’, ‘–’, …)
linewidth or lw (1, 2, 3, 4 …)
fig, ax = plt.subplots()
ax.plot(x, x+1, color="red", alpha=0.5) # half-transparant red
ax.plot(x, x+2, color="#1155dd") # RGB hex code for a bluish color
ax.plot(x, x+3, color="#15cc55") # RGB hex code for a greenish color
ax.plot(x, x+4, color='b', marker='^', ls='--') #dashed blue line with triangle markers
There is also a Matlab-like syntax for simple plots:
ax.plot(x, x+5, '-ok') # black line with circle markers
fig
Lots more examples…
fig, ax = plt.subplots(figsize=(12,6))
ax.plot(x, x+1, color="blue", linewidth=0.25)
ax.plot(x, x+2, color="blue", linewidth=0.50)
ax.plot(x, x+3, color="blue", linewidth=1.00)
ax.plot(x, x+4, color="blue", linewidth=2.00)
# possible linestype options ‘-‘, ‘--’, ‘-.’, ‘:’, ‘steps’
ax.plot(x, x+5, color="red", lw=2, linestyle='-')
ax.plot(x, x+6, color="red", lw=2, ls='-.')
ax.plot(x, x+7, color="red", lw=2, ls=':')
# possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 8, color="green", lw=2, ls='--', marker='+')
ax.plot(x, x+9, color="green", lw=2, ls='--', marker='o')
ax.plot(x, x+10, color="green", lw=2, ls='--', marker='s')
ax.plot(x, x+11, color="green", lw=2, ls='--', marker='1')
# marker size and color
ax.plot(x, x+12, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=2, markeredgecolor="blue");
1.5.2.5. Control over axis appearance#
There are many options for modifying axis appearance. The most basic one is controlling the range of the plot. You can use:
set_xlim
- control x rangeset_ylim
- control y rangeaxis('tight')
- automaticlly “tighten” the axis range.
You can also control tick positions, tick labels, log scale, etc. See the many examples online.
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("default axes ranges")
axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tight axes")
axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 0.4])
axes[2].set_xlim([0.25, 0.6])
axes[2].set_title("custom axes range");
1.5.2.6. Twin axes#
Sometimes it is useful to have dual x or y axes in a figure; for example, when plotting curves with different units together. Matplotlib supports this with the twinx
and twiny
functions:
fig, ax1 = plt.subplots()
ax1.plot(x, x**2, lw=2, color="blue")
ax1.set_ylabel(r"area $(m^2)$", fontsize=18, color="blue") #note support for LaTeX-style formatting
for label in ax1.get_yticklabels(): #an example of controlling tick label color
label.set_color("blue")
ax2 = ax1.twinx()
ax2.plot(x, x**3, lw=2, color="red")
ax2.set_ylabel(r"volume $(m^3)$", fontsize=18, color="red")
for label in ax2.get_yticklabels():
label.set_color("red")
1.5.2.7. Text annotation#
Often it is useful to place annotations on a plot. There are two options:
text
- place text at an absolute positionannotate
- place text at a position relative to another point
annotate
is useful if you want to draw arrows.
fig, ax = plt.subplots()
t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
ax.plot(t, s, lw=2)
ax.text(s='this is a sin curve', x=0, y=1.3)
ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
arrowprops=dict(facecolor='black', shrink=0.05),
)
#ax.set_ylim(-2,2)
1.5.2.8. Colormap and contour figures#
Colormaps and contour figures are useful for plotting functions of two variables. In most of these functions we will use a colormap to encode one dimension of the data. There are a number of predefined colormaps. It is relatively straightforward to define custom colormaps. For a list of pre-defined colormaps, see: http://www.scipy.org/Cookbook/Matplotlib/Show_colormaps
Plotting 3D data can be done with:
pcolor (show directly with x, y)
contour (contour lines with x, y)
imshow (interpolate and transpose)
See this discussion of choosing color maps. The “perceptually uniform” color maps are preferred since they work with greyscale and are easier for colorblind people.
#cook up some 3D data to plot
alpha = 0.7
phi_ext = 2 * np.pi * 0.5
def flux_qubit_potential(phi_m, phi_p):
return 2 + alpha - 2 * np.cos(phi_p) * np.cos(phi_m) - alpha * np.cos(phi_ext - 2*phi_p)
phi_m = np.linspace(0, 2*np.pi, 100)
phi_p = np.linspace(0, 2*np.pi, 100)
X,Y = np.meshgrid(phi_p, phi_m)
Z = flux_qubit_potential(X, Y).T
from matplotlib.cm import jet, RdBu, gray, viridis, plasma
fig, ax = plt.subplots()
p = ax.pcolor(X, Y, Z, cmap=viridis)#, vmin=abs(Z).min(), vmax=abs(Z).max())
cb = fig.colorbar(p, ax=ax)
fig, ax = plt.subplots()
cnt = ax.contour(X, Y, Z, cmap=viridis)#, vmin=abs(Z).min(), vmax=abs(Z).max())
cb = fig.colorbar(cnt, ax=ax)
fig, ax = plt.subplots()
im = ax.imshow(Z, cmap=viridis, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 2, 0, 1])
im.set_interpolation('bilinear')
cb = fig.colorbar(im, ax=ax)
1.5.2.9. Images#
Matplotlib treats images as numpy arrays, which makes them easy to analyze. There is a toolkit designed specifically for images (matplotlib.image
)
import matplotlib.image as mpimg
img = mpimg.imread('bug.jpg') #we can read png or jpg
#print(img)
fig,ax = plt.subplots()
ax.imshow(img)
Images are 3D arrays with x,y,RGB
print(img.shape)
ax.imshow(img[:,:,1],cmap=gray)
fig
It is easy to look at histograms:
fig, axes = plt.subplots(1,2)
axes[0].imshow(img)
axes[0].set_title('image')
axes[1].hist(img[:,:,0].ravel(), bins=256)
axes[1].set_title('color histogram')
#How can we look at the greyscale histogram?
#fig.tight_layout()
1.5.3. 3D figures#
Matplotlib can make 3D plots, but its not easy. I recommend searching the gallery for examples if you really think you need a 3D plot.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=viridis)
cset = ax.contourf(X, Y, Z, zdir='x', offset=-40, cmap=viridis)
cset = ax.contourf(X, Y, Z, zdir='y', offset=40, cmap=viridis)
ax.set_xlabel('X')
ax.set_xlim(-40, 40)
ax.set_ylabel('Y')
ax.set_ylim(-40, 40)
ax.set_zlabel('Z')
ax.set_zlim(-100, 100)
plt.show()
1.5.4. Further reading#
jrjohansson/scientific-python-lectures - Lecture 3 is the more detailed version of this lecture.
http://scipy.org/NumPy_for_Matlab_Users - A Numpy guide for MATLAB users.
Lectures 3+4 of Johanssen: jrjohansson/scientific-python-lectures
Scipy:
http://www.scipy.org - The official web page for the SciPy project.
http://docs.scipy.org/doc/scipy/reference/tutorial/index.html - A tutorial on how to get started using SciPy.
scipy/scipy - The SciPy source code.
Matplotlib:
http://www.matplotlib.org - The project web page for matplotlib.
matplotlib/matplotlib - The source code for matplotlib.
http://matplotlib.org/gallery.html - A large gallery showcaseing various types of plots matplotlib can create. Highly recommended!
http://www.loria.fr/~rougier/teaching/matplotlib - A good matplotlib tutorial.
http://scipy-lectures.github.io/matplotlib/matplotlib.html - Another good matplotlib reference.
1.5.5. Versions#
%reload_ext version_information
%version_information numpy, scipy, matplotlib