Matplotlib#

%config InlineBackend.figure_format = 'svg'
import numpy as np
import matplotlib.pyplot as plt

The first line above which begins with a % is called a magic command, which here sets the figure format to svg, which is a vector graphics format that looks prettier than default format.

There are two main approaches to use Matplotlib. The simplest one, which is somewhat similar to Matlab is described first. An object oriented approach is described in the end.

Single graph#

\[ f(x) = x \sin(x) \sin(50 x) \]
f = lambda x: x * np.sin(x) * np.sin(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

plt.plot(x, f(x))
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Plot of f(x)')
plt.grid(True)
_images/b8941be6a1d3cb60f9c64957dbb7a942746f53583a6ca724fdecc5db5134b0af.svg

Multiple graphs#

f = lambda x: x * np.sin(x) * np.sin(50*x)
g = lambda x: x * np.cos(x) * np.cos(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

plt.plot(x,f(x),x,g(x))
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Plot of f(x) and g(x)')
plt.legend(('f(x)','g(x)'))
plt.grid(True)
_images/63bb6a591a95faa4b1c985c08ede114a1805335f93b3d9ebc27a7d816716e4aa.svg

The line colors are set to different values automatically, which is useful to distinguish the graphs.

Control line style#

We can however control the line style ourselves.

f = lambda x: x * np.sin(x) * np.sin(50*x)
g = lambda x: x * np.cos(x) * np.cos(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

plt.plot(x,f(x),'r-',linewidth=2,label='f(x)')
plt.plot(x,g(x),'b--',label='g(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Plot of f(x) and g(x)')
plt.legend()
plt.grid(True)
_images/5a5ac118d3a13a7a20ede95d40ae6be528d4c14ee72985b0d6494fdc67894b98.svg

We can also specify parameters like this

plt.plot(x,f(x),c='red',ls='dashed',lw=2)
plt.xlabel('x'); plt.ylabel('y');
_images/853168cddc8667f6b432d14ef79c9dd2e46d4111cf2b5e6d20d8fdfa43308c8a.svg

Show symbols or markers#

f = lambda x: x * np.sin(x) * np.sin(50*x)
g = lambda x: np.cos(x) * np.cos(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

plt.plot(x,f(x),'k-o',markevery=10)
plt.plot(x,g(x),'r--s',markevery=10)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Plot of f(x) and g(x)')
plt.legend(('f(x)','g(x)'),loc='upper right')
plt.grid(True)
_images/4a1f8bbcf06d4097c3764f8bc02f66b6157864a87031b3a60b36547b8bd62aaf.svg

Matrix of plots#

n  = 200
x  = np.linspace(0.0,1.0,n)
y1 = np.sin(50*x)
y2 = np.log(x+1) + np.tanh(x)
y3 = x**2 + x * np.cos(10*x)
y4 = np.cos(10*x) + np.sin(5*x)

plt.figure(figsize=(10,8))
lw = 1.5

plt.subplot(221)
plt.plot(x,y1,'k-',linewidth=lw)
plt.xlabel('$x$'); plt.ylabel('$y_1$')
plt.title('y1')

plt.subplot(222)
plt.plot(x,y2,'r--',linewidth=lw)
plt.xlabel('$x$'); plt.ylabel('$y_2$')
plt.title('y2')

plt.subplot(223)
plt.plot(x,y3,'g-.',linewidth=lw)
plt.xlabel('$x$'); plt.ylabel('$y_3$')
plt.title('y3')

plt.subplot(224)
plt.plot(x,y4,'b:',linewidth=lw)
plt.xlabel('$x$'); plt.ylabel('$y_4$');
plt.title('y4');
_images/b50c18ab3dac1080322e3f1faf4a6581738973ed67f0c930a092657ff28bbc23.svg

Plot in log scale: semilogy#

\[ y = \exp(x), \qquad x \in [-100,0] \]
n = 100
x = np.linspace(-100,0,n)
y = np.exp(x)
plt.plot(x,y)
plt.xlabel('x'); plt.ylabel('y');
_images/6c3720df42495e32b2884a5b60db484f66243b6c1006a441ada54325ef9ce834.svg

The y axis has very small to very large values and the usual linear scale plot does not show this variation properly. We next plot the y axis in log scale.

plt.semilogy(x,y)
plt.xlabel('x'); plt.ylabel('y');
_images/706fe6c40f62b5f84dfb5ca3feeaebcecc0856598d13d183e328f4d38e414b62.svg

The linear curve clearly shows the exponential character of the function.

Plot in log scale: loglog#

\[ y = x^{-2}, \qquad x \in [10^{-3}, 10^{-2}] \]
n = 10
x = np.linspace(1e-3,1e-2,n)
y = 1.0/x**2
plt.plot(x,y,'o-')
plt.xlabel('x'); plt.ylabel('y');
_images/c79382285eaf453fa4c64eead2ea89b795a9402be8602d7b2b26c299fe07d1b3.svg

The variations in both axes are too large, so we plot both axes in log scale.

plt.loglog(x,y,'o-')
plt.xlabel('x'); plt.ylabel('y');
_images/a6044b34cfdf75b6a9645c9db06b3aa18d266e2cef91cd68011fa709254499d7.svg

Scientific notation for tick values#

n = 100
x = np.linspace(0.1,1,n)
y = 1e-4 * np.exp(x)
plt.plot(x,y)
plt.xlabel('x'); plt.ylabel('y');
_images/5d268d7ea5d3738a0b0c38a43c5458490de884994fc67196363265e93b9428d8.svg
plt.plot(x,y)
plt.ticklabel_format(axis="y", style="sci", scilimits=(0,0));
_images/623b6a8783e4d8fa90550c218ccb1e29a2a60acebad527ea27628b3d9bbade66.svg

Control tick values#

Which tick values are labelled is automatically chosen by matplotlib, but we can control this ourselves.

n = 100
x = np.linspace(0.0,1.0,n)
y = np.sin(2.0*np.pi*x)
plt.plot(x,y)
plt.xticks([0.0, 0.25, 0.5, 0.75, 1.0])
plt.yticks([-1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0])
plt.grid(True)
_images/5efb9fc94687d916eb068fb0332a979ac319a84df9b2cdef5f001a8195fbba94.svg

2-D contour plots#

\[ \psi = \sin(2\pi x) \cos(2\pi y), \qquad (x,y) \in [0,1] \times [0,1] \]
n = 100
x = np.linspace(0.0, 1.0, n)
y = np.linspace(0.0, 1.0, n)
X, Y = np.meshgrid(x,y)

psi = np.sin(2*np.pi*X) * np.cos(2*np.pi*Y)

plt.figure(figsize=(5,5))
plt.contour(X,Y,psi,levels=20,colors='black')
plt.xticks([0, 0.25, 0.5, 0.75, 1.0])
plt.yticks([0, 0.25, 0.5, 0.75, 1.0])
plt.xlabel('$x_1$')
plt.ylabel('$x_2$')
plt.grid(True)
_images/5fe50745933193baff44ad11122e8465d35f58fb0a2036177d9f3e1c8ed0a4b5.svg

2-D filled plots: contourf#

n = 100
x = np.linspace(0.0, 1.0, n)
y = np.linspace(0.0, 1.0, n)
X, Y = np.meshgrid(x,y)

psi = np.sin(2*np.pi*X) * np.cos(2*np.pi*Y)

cf = plt.contourf(X,Y,psi,levels=20,cmap='jet')
plt.colorbar(cf)
plt.xticks([0, 0.25, 0.5, 0.75, 1.0])
plt.yticks([0, 0.25, 0.5, 0.75, 1.0])
plt.xlabel('$x_1$')
plt.ylabel('$x_2$')
plt.axis('equal')
plt.grid(True)
_images/b401ade18993117c33ce8d8a36fc0f09516a72bc099b4584a5b743d5ae872428.svg

There are many colormaps available.

2-D surface plot#

We have to use object-oriented interface, which is explained below.

n = 100
x = np.linspace(0.0, 1.0, n)
y = np.linspace(0.0, 1.0, n)
X, Y = np.meshgrid(x,y)

psi = np.sin(2*np.pi*X) * np.cos(2*np.pi*Y)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X, Y, psi, cmap='viridis',
                       linewidth=0, antialiased=False,
                       vmin=-1, vmax=1)
fig.colorbar(surf, shrink=0.5, aspect=5)
ax.set_zlim(-1.01, 1.01)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label');
_images/2cdb56c86980f13576186627fb1565c67bf2dd3e298f2cef2f74dd7a1ff4f074.svg

Object oriented approach*#

A single plot.

f = lambda x: 0.5*x*np.sin(x)*np.sin(50*x)
g = lambda x: 0.5*x*np.cos(x)*np.cos(50*x)

n = 200
x = np.linspace(0.0,2.0,n)

fig, ax = plt.subplots()
ax.plot(x,f(x),'r-',linewidth=2,label='f(x)')
ax.plot(x,g(x),'b--',label='g(x)')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Plot of f(x) and g(x)')
ax.set_xlim(-0.1,2.1)
ax.set_ylim(-1,1)
ax.set_xticks([0,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0])
ax.legend()
ax.grid(True)
ax.set_aspect('equal')
ax.text(0, -0.4, '$\mu=115,\ \sigma=15$');
_images/64fab2ee52db8b38ded045a6ae3dedc46c6048f30d87797fe9ca0e96fff51df2.svg

A \(1 \times 2\) matrix of plots.

f = lambda x: x*np.sin(x)*np.sin(50*x)
g = lambda x: x*np.cos(x)*np.cos(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

fig, ax = plt.subplots(1,2,figsize=(8,5))

ax[0].plot(x,f(x),'r-',linewidth=2,label='f(x)')
ax[0].set_xlabel('x')
ax[0].set_ylabel('f(x)')
ax[0].set_title('Plot of f(x)')
ax[0].set_xlim(-0.1,1.1)
ax[0].set_ylim(-1,1)
ax[0].grid(True)
ax[0].legend()

ax[1].plot(x,g(x),'b--',label='g(x)')
ax[1].set_xlabel('x')
ax[1].set_ylabel('g(x)')
ax[1].set_title('Plot of g(x)')
ax[1].set_xlim(-0.1,1.1)
ax[1].set_ylim(-1,1)
ax[1].grid(True)
ax[1].legend()

fig.suptitle('Plot of f(x) and g(x)');
_images/8905f7de25ba4390f22219a5d868a60a0e3bce32281c4e4d336bb6d5e0081941.svg

We can make a \(2 \times 2\) matrix of plots like this.

f = lambda x: x*np.sin(x)*np.sin(50*x)
g = lambda x: x*np.cos(x)*np.cos(50*x)

n = 200
x = np.linspace(0.0,1.0,n)

fig, ax = plt.subplots(2,2,figsize=(8,5))

ax[0,0].plot(x,f(x),'r-',linewidth=2,label='f')
ax[0,0].set_xlabel('x')
ax[0,0].set_ylabel('f(x)')
ax[0,0].set_title('Plot of f(x)')
ax[0,0].set_xlim(-0.1,1.1)
ax[0,0].set_ylim(-1,1)
ax[0,0].grid(True)
ax[0,0].legend()

ax[0,1].plot(x,g(x),'b--',label='g')
ax[0,1].set_xlabel('x')
ax[0,1].set_ylabel('g(x)')
ax[0,1].set_title('Plot of g(x)')
ax[0,1].set_xlim(-0.1,1.1)
ax[0,1].set_ylim(-1,1)
ax[0,1].grid(True)
ax[0,1].legend()

ax[1,0].plot(x,f(x)-g(x),'r-',linewidth=2,label='f-g')
ax[1,0].set_xlabel('x')
ax[1,0].set_ylabel('f(x)-g(x)')
ax[1,0].set_title('Plot of f(x)-g(x)')
ax[1,0].set_xlim(-0.1,1.1)
ax[1,0].set_ylim(-1,1)
ax[1,0].grid(True)
ax[1,0].legend()

ax[1,1].plot(x,f(x)+g(x),'b--',label='f+g')
ax[1,1].set_xlabel('x')
ax[1,1].set_ylabel('f(x)+g(x)')
ax[1,1].set_title('Plot of f(x)+g(x)')
ax[1,1].set_xlim(-0.1,1.1)
ax[1,1].set_ylim(-1,1)
ax[1,1].grid(True)
ax[1,1].legend()

fig.suptitle('2x2 matrix of plots');
_images/a1a6d18f3bcb8a4264153316abffcc0407a855d3c60ab132cca5029fd698036d.svg