Plotting and Visualization

This tutorial is prepared by ACM Student Chapter of King Abdullah University of Science and Technology (KAUST).
Parts of this tutorial re-use Scientific Python lectures by Robert Johansson linsensed under Creative Commons Attribution 3.0.


Matplotlib

Matplotlib is the basic package of Python for plotting.

In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

The first line above ensures that our plots appear in the browser, instead in a separate window. The other import pyplot package

Let's see a very simple example. Suppose we want to plot the function $\sin(\exp(x))$ on the interval $x\in(0,\pi)$. We'll want to use the NumPy functions of the sine and exponential functions. (Note: the math module operates only on scalars so we should use NumPy in such cases)

In [ ]:
x = np.linspace(0,np.pi,1000)
f = np.sin(np.exp(x))
g = np.cos(2*x)
plt.plot(x,f)
plt.plot(x,g)

There are several ways to format a plot in python. Here we just mention only the basic functionality. It's straightforward to use them and you will generally only get into its advanced functionality if you are customizing the look of a plot for a publication. Matplotlib documentation is very good, have a look here. You can also read this tutorial for an easy start. More references are listed at the end of this tutorial.

The following code does the basic formatting for the plot above:

In [ ]:
plt.figure(figsize=(10,6), dpi=300) # changing figure's shape
plt.xlim(x.min()-0.1, x.max()+0.1) # adjusting horizonatal axis limits
plt.ylim(f.min()-0.1, f.max()+0.1) # adjusting vertical axis limits
plt.xticks([0, np.pi/2, np.pi],[r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'],fontsize=14) # setting ticks
plt.yticks([-1, 0, +1],[r'$-1$', r'$0$', r'$+1$'],fontsize=14) # setting ticks

plt.plot(x, f, color="blue", linewidth=2.5, linestyle="-", label="$\sin(e^x)$") # changing color and thickness
plt.plot(x, g, color="red",  linewidth=2.5, linestyle="-",  label="$\cos(2x)$") # changing color and thickness
plt.legend(loc='lower left',prop={'size':16}) # placing legend on bottom left
plt.xlabel('$x$',fontsize=16) # horizontal axis name
plt.ylabel('test functions',fontsize=16) # vertical axis name
plt.title('Sample plot',fontsize=18) # title
plt.grid(True) # enabling grid

The image can be resized by dragging the handle in the lower right corner. Double clicking will return them to their original size.

One thing to be aware of is that by default, the figure object is cleared at the end of each cell.

You will need to issue all plotting commands for a single figure in a single cell.

In [ ]:
plt.savefig('trig_functions.pdf')
In [ ]:
plt.savefig?

Go on and open the pdf file. It is empty! Now uncomment the save line in the block where the figure is plotted.

3D-plotting

The following example is adapted from this tutorial. Let's define the following function:

In [ ]:
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)

Now create a mesh and evaluate the function over that mesh:

In [ ]:
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

Plot the surface:

In [ ]:
from mpl_toolkits.mplot3d.axes3d import Axes3D # imports 3D plotting
from matplotlib import cm # module for color pattern
fig = plt.figure(figsize=(14,6))

# `ax` is a 3D-aware axis instance because of the projection='3d' keyword argument to add_subplot
ax = fig.add_subplot(1, 2, 1, projection='3d')

p = ax.plot_surface(X, Y, Z, rstride=4, cstride=4, linewidth=0)

# surface_plot with color grading and color bar
ax = fig.add_subplot(1, 2, 2, projection='3d')
p = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
cb = fig.colorbar(p, shrink=0.5) # enables colorbar

Better control over plotting

So far, we matplotlib.pyplot module directly to produce plots. Sometimes we need more control over the the plots position, axes, insets, etc. We might also need to create different figures, or add different axes, put insets, etc. The following commands demonstrate this functionality.

In [ ]:
# Let's generate some synthetic data
data = np.random.uniform(size=(100,2))
x, y = data[:,0], data[:,1]
In [ ]:
# Let's create a fugure objec and an axes object
fig1 = plt.figure(figsize=(6,6))
ax1  = fig.add_axes([0.10,0.20,0.78,0.40])  # left, bottom, width, height
In [ ]:
print dir(fig1)
In [ ]:
print dir(plt)
In [ ]:
# Don't forget to create figures and axes in the cell you are plotting!
fig = plt.figure(figsize=(6,6))
ax1 = fig.add_axes([0.10,0.20,0.78,0.80])  # left, bottom, width, height

# Ex: Specify a title and the axes labels

ax1.scatter(x, y, marker='o')

Insets through multiple axes

In [ ]:
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')

# Ex: add a title to the inset with a font size of 12px

What if you want to enlarge some region of the figure and show it in the inset? Let's how we can do that.

In [ ]:
x = np.linspace(0,np.pi,1000)
f = np.sin(8*np.exp(x))
g = np.cos(2*x)

# How to enlarge a region on a plot?
fig = plt.figure(figsize=(8, 6))
ax  = fig.add_axes([0.15,0.11,0.83,0.83])
ax.set_xlim([0, 5])
ax.plot(x,f)
ax.plot(x,g)
In [ ]:
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes, mark_inset
zoomed_inset_axes?
In [ ]:
fig = plt.figure(figsize=(8, 6))
ax  = fig.add_axes([0.15,0.11,0.83,0.83])
ax.set_xlim([0, 5])
ax.plot(x,f,linewidth=0.5)
ax.plot(x,g)

# The inset axes
axins = zoomed_inset_axes(ax, 8, loc=1)
axins.plot(x, f, linewidth=1)
axins.plot(x, g, linewidth=2)
axins.set_xlim([2.85, 3.0])
axins.set_ylim([0.9, 1.0])

# Mark inset
mark_inset(ax, axins, loc1=3, loc2=2, fc="none", ec="0")

Matplotlib is a very rich library, and it has the functionality for literrally any kind of plotting. For more refence, you can check out a very detailed User Guide.

Beautiful and easy plot styling

A recently developed Seaborn package provides many different options of how to control the plot aesthetics. Let's look at some examples.

In [ ]:
# A very quick enhancement by just importing seaborn
import seaborn as sns
sns.set_style("whitegrid")

x = np.linspace(0,np.pi,1000)
f = np.sin(np.exp(x))
g = np.cos(2*x)
plt.plot(x,f)
plt.plot(x,g)
In [ ]:
sns.set_style?

A few more examples:

In [ ]:
# Bar plots
sns.set_style("whitegrid")
data = np.random.normal(size=(20, 6)) + np.arange(6) / 2
sns.boxplot(data);
In [ ]:
# Violing plots
f, ax = plt.subplots()
sns.violinplot(data)
sns.despine(offset=10, trim=True);
In [ ]:
# What are the styles and how to override them?
sns.axes_style()

Color paletes available in seaborn

In [ ]:
current_palette = sns.color_palette()
sns.palplot(current_palette)
In [ ]:
plt.plot([0, 1], [0, 1], sns.xkcd_rgb["pale red"], lw=3)
plt.plot([0, 1], [0, 2], sns.xkcd_rgb["medium green"], lw=3)
plt.plot([0, 1], [0, 3], sns.xkcd_rgb["denim blue"], lw=3);

Copyright 2015, Maruan Al-Shedivat, Yiannis Hadjimichael, ACM Student Chapter.