Matplotlib#

  • Python 2D plotting library which produces figures in many formats and interactive environments.

  • Tries to make easy things easy and hard things possible.

  • You can generate plots, histograms, power spectra, bar charts, errorcharts, scatterplots, etc., with just a few lines of code.

  • Check the Matplotlib gallery.

  • For simple plotting the pyplot module provides a MATLAB-like interface, particularly when combined with IPython.

  • Matplotlib provides a set of functions familiar to MATLAB users.

In this notebook we use some numpy command that will be explain more precisely later.

Line Plots#

  • np.linspace(0,1,10) return 10 evenly spaced values over \([0,1]\).

%matplotlib inline
# inline can be replaced by notebook to get interactive plots
import numpy as np
import matplotlib.pyplot as plt

%config InlineBackend.figure_format = "retina"
plt.rcParams['figure.figsize'] = (10.0, 6.0) # set figures display bigger
x = np.linspace(- 5*np.pi,5*np.pi,100) 
plt.plot(x,np.sin(x)/x);
_images/12-Matplotlib_3_0.png
plt.plot(x,np.sin(x)/x,x,np.sin(2*x)/x);
_images/12-Matplotlib_4_0.png

If you have a recent Macbook with a Retina screen, you can display high-resolution plot outputs. Running the next cell will give you double resolution plot output for Retina screens.

Note: the example below won’t render on non-retina screens

%config InlineBackend.figure_format = 'retina'
# red, dot-dash, triangles and blue, dot-dash, bullet
plt.plot(x,np.sin(x)/x, 'r-^',x,np.sin(2*x)/x, 'b-o');
_images/12-Matplotlib_7_0.png

Simple Scatter Plot#

x = np.linspace(-1,1,50)
y = np.sqrt(1-x**2)
plt.scatter(x,y);
_images/12-Matplotlib_9_0.png

Colormapped Scatter Plot#

theta = np.linspace(0,6*np.pi,50) # 50 steps from 0 to 6 PI
size = 30*np.ones(50) # array with 50 values set to 30
z = np.random.rand(50) # array with 50 random values in [0,1]
x = theta*np.cos(theta)
y = theta*np.sin(theta)
plt.scatter(x,y,size,z)
plt.colorbar();
_images/12-Matplotlib_11_0.png

Change Colormap#

fig = plt.figure() # create a figure
ax = fig.add_subplot(1, 1, 1) # add a single plot
ax.scatter(x,y,size,z,cmap='jet');
ax.set_aspect('equal', 'datalim')
_images/12-Matplotlib_13_0.png

colormaps in matplotlib documentation.

Multiple Figures#

plt.figure()
plt.plot(x)
plt.figure()
plt.plot(z,'ro');
_images/12-Matplotlib_16_0.png _images/12-Matplotlib_16_1.png

Multiple Plots Using subplot#

plt.subplot(1,2,1) # 1 row 1, 2 columns, active plot number 1
plt.plot(x,'b-*')
plt.subplot(1,2,2) # 1 row 1, 2 columns, active plot number 2
plt.plot(z,'ro');
_images/12-Matplotlib_18_0.png

Legends#

  • Legends labels with plot

theta =np.linspace(0,4*np.pi,200)
plt.plot(np.sin(theta), label='sin')
plt.plot(np.cos(theta), label='cos')
plt.legend();
_images/12-Matplotlib_20_0.png
  • Labelling with legend

plt.plot(np.sin(theta))
plt.plot(np.cos(theta)**2)
plt.legend(['sin','$\cos^2$']);
_images/12-Matplotlib_22_0.png

Titles and Axis Labels#

plt.plot(theta,np.sin(theta))
plt.xlabel('radians from 0 to $4\pi$')
plt.ylabel('amplitude');
_images/12-Matplotlib_24_0.png
t = np.arange(0.01, 20.0, 0.01)

plt.subplot(121) 
plt.semilogy(t, np.exp(-t/5.0))
plt.title('semilogy')
plt.grid(True)

plt.subplot(122,fc='y') 
plt.semilogx(t, np.sin(2*np.pi*t))
plt.title('semilogx')
plt.grid(True)
_images/12-Matplotlib_25_0.png

Plot Grid and Save to File#

theta = np.linspace(0,2*np.pi,100)
plt.plot(np.cos(theta),np.sin(theta))
plt.grid();
_images/12-Matplotlib_27_0.png
plt.savefig('circle.png');
%ls *.png
circle.png  logo.png
<Figure size 1000x600 with 0 Axes>

Histogram#

from numpy.random import randn
plt.hist(randn(1000));
_images/12-Matplotlib_30_0.png

Change the number of bins and supress display of returned array with ;

plt.hist(randn(1000), 30);
_images/12-Matplotlib_32_0.png

Contour Plot#

x = y = np.arange(-2.0*np.pi, 2.0*np.pi+0.01, 0.01)
X, Y = np.meshgrid(x, y)
Z = np.sin(X)*np.cos(Y)

plt.contourf(X, Y, Z,cmap=plt.cm.hot);
_images/12-Matplotlib_34_0.png

Image Display#

img = plt.imread("https://hackage.haskell.org/package/JuicyPixels-extra-0.1.0/src/data-examples/lenna.png")
plt.imshow(img)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[20], line 1
----> 1 img = plt.imread("https://hackage.haskell.org/package/JuicyPixels-extra-0.1.0/src/data-examples/lenna.png")
      2 plt.imshow(img)

File /usr/share/miniconda3/envs/runenv/lib/python3.10/site-packages/matplotlib/pyplot.py:2123, in imread(fname, format)
   2121 @_copy_docstring_and_deprecators(matplotlib.image.imread)
   2122 def imread(fname, format=None):
-> 2123     return matplotlib.image.imread(fname, format)

File /usr/share/miniconda3/envs/runenv/lib/python3.10/site-packages/matplotlib/image.py:1536, in imread(fname, format)
   1532 img_open = (
   1533     PIL.PngImagePlugin.PngImageFile if ext == 'png' else PIL.Image.open)
   1534 if isinstance(fname, str) and len(parse.urlparse(fname).scheme) > 1:
   1535     # Pillow doesn't handle URLs directly.
-> 1536     raise ValueError(
   1537         "Please open the URL for reading and pass the "
   1538         "result to Pillow, e.g. with "
   1539         "``np.array(PIL.Image.open(urllib.request.urlopen(url)))``."
   1540         )
   1541 with img_open(fname) as image:
   1542     return (_pil_png_to_float_array(image)
   1543             if isinstance(image, PIL.PngImagePlugin.PngImageFile) else
   1544             pil_to_array(image))

ValueError: Please open the URL for reading and pass the result to Pillow, e.g. with ``np.array(PIL.Image.open(urllib.request.urlopen(url)))``.

figure and axis#

Best method to create a plot with many components

fig = plt.figure()
axis = fig.add_subplot(111, aspect='equal',
                     xlim=(-2, 2), ylim=(-2, 2))

state = -0.5 + np.random.random((50, 4))
state[:, :2] *= 3.9
bounds = [-1, 1, -1, 1]

particles = axis.plot(state[:,0], state[:,1], 'bo', ms=6)
rect = plt.Rectangle(bounds[::2],
                     bounds[1] - bounds[0],
                     bounds[3] - bounds[2],
                     ec='r', lw=2, fc='none')
axis.grid()
axis.add_patch(rect)
axis.text(-0.5,1.1,"BOX")
Text(-0.5, 1.1, 'BOX')
_images/12-Matplotlib_38_1.png

Exercises#

Recreate the image my_plots.png using the delicate_arch.png file in images directory.

Alternatives#

  • bqplot : Jupyter Notebooks, Interactive.

  • seaborn : Statistics build on top of matplotlib.

  • toyplot : Nice graphes.

  • bokeh : Interactive and Server mode.

  • pygal : Charting

  • Altair : Data science (js backend)

  • plot.ly : Data science and interactive

  • Mayavi: 3D

  • YT: Astrophysics (volume rendering, contours, particles).

  • VisIt: Powerful, easy to use but heavy.

  • Paraview: The most-used visualization application. Need high learning effort.

  • PyVista: 3D plotting and mesh analysis through a streamlined interface for the Visualization Toolkit (VTK)

  • Yellowbrick : Yellowbrick: Machine Learning Visualization

  • scikit-plot : Plot sklearn metrics

#example from Filipe Fernandes
#http://nbviewer.jupyter.org/gist/ocefpaf/9730c697819e91b99f1d694983e39a8f
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation

g = 9.81
denw = 1025.0  # Seawater density [kg/m**3].
sig = 7.3e-2  # Surface tension [N/m].
a = 1.0  # Wave amplitude [m].

L, h = 100.0, 50.0  # Wave height and water column depth.
k = 2 * np.pi / L
omega = np.sqrt((g * k + (sig / denw) * (k**3)) * np.tanh(k * h))
T = 2 * np.pi / omega
c = np.sqrt((g / k + (sig / denw) * k) * np.tanh(k * h))

# We'll solve the wave velocities in the `x` and `z` directions.
x, z = np.meshgrid(np.arange(0, 160, 10), np.arange(0, -80, -10),)
u, w = np.zeros_like(x), np.zeros_like(z)


def compute_vel(phase):
    u = a * omega * (np.cosh(k * (z+h)) / np.sinh(k*h)) * np.cos(k * x - phase)
    w = a * omega * (np.sinh(k * (z+h)) / np.sinh(k*h)) * np.sin(k * x - phase)
    mask = -z > h
    u[mask] = 0.0
    w[mask] = 0.0
    return u, w


def basic_animation(frames=91, interval=30, dt=0.3):
    fig = plt.figure(figsize=(8, 6))
    ax = plt.axes(xlim=(0, 150), ylim=(-70, 10))

    # Animated.
    quiver = ax.quiver(x, z, u, w, units='inches', scale=2)
    ax.quiverkey(quiver, 120, -60, 1,
                 label=r'1 m s$^{-1}$',
                 coordinates='data')
    line, = ax.plot([], [], 'b')

    # Non-animated.
    ax.plot([0, 150], [0, 0], 'k:')
    ax.set_ylabel('Depth [m]')
    ax.set_xlabel('Distance [m]')
    text = (r'$\lambda$ = %s m;  h = %s m;  kh = %2.3f;  h/L = %s' %
            (L, h, k * h, h/L))
    ax.text(10, -65, text)
    time_step = ax.text(10, -58, '')
    line.set_data([], [])

    def init():
        return line, quiver, time_step

    def animate(i):
        time = i * dt
        phase = omega * time
        eta = a * np.cos(x[0] * k - phase)
        u, w = compute_vel(phase)
        quiver.set_UVC(u, w)
        line.set_data(x[0], 5 * eta)
        time_step.set_text('Time = {:.2f} s'.format(time))
        return line, quiver, time_step

    return animation.FuncAnimation(fig, animate, init_func=init,
                                   frames=frames, interval=interval)
from IPython.display import HTML

HTML(basic_animation(dt=0.3).to_jshtml())
_images/12-Matplotlib_42_1.png

References#