2. Visualization#

Visualizatin is vital in data analysis and scientific computing, to

  • get intuitive understanding

  • come up with a new hypothesis

  • detect a bug or data anormaly

That is why we’ll cover this topic at the beginning of this course.

Matplotlib#

Matplotlib is the standard graphics package for Python. It mimics many graphics functions of MATLAB.
The Matplotlib gallery (http://matplotlib.org/stable/gallery) illustrates variety of plots.

import numpy as np
import matplotlib.pyplot as plt

Usually matplotlib opens a window for a new plot.

A nice feature of Jupyter notebook is that you can embed the figures produced by your program within the notebook by the following magic command
%matplotlib inline
(It may be a default setting in recent jupyter notebook).

%matplotlib inline

Plotting functions#

The standard way is to prepare an array for x values, compute y values, and call plot( ) function.

# make an array from 0 to 10, the default is 50 points
x = np.linspace(0, 10)
# comupute a function for each point
y = x*np.sin(x)
# plot the points
plt.plot(y)  # x is the index of y
[<matplotlib.lines.Line2D at 0x111774ec0>]
_images/b6dcee7526659b55f92dbaf8d1e980df2a3d4ed56f466db322ec1e12715f459b.png

There are multiple ways to pass variables to plot():

  • plot(y): x is assumed as the indices of y

  • plot(x, y): specify both x and y values

  • plot(x1, y1, x2, y2,...): multiple lines

  • plot(x, Y): lines for columns of matrix Y

# specify both x and y values
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x111813320>]
_images/f2c3cd2893d273e04fa79cb47382f8885484f6dc2ec8bcb7727f04ba4b5a655a.png
# take another function of x
y2 = x*np.cos(x)
# plot two lines
plt.plot(x, y, x, y2)
[<matplotlib.lines.Line2D at 0x1118e4e30>,
 <matplotlib.lines.Line2D at 0x1118e4e60>]
_images/cc3e25a3ec148f3f582f9eb453455d02cd63426d8f626bad9d5a699ca866885c.png
# phase plot
plt.plot(y, y2);
# you can supress <matplotlib...> output by ;
_images/1b0a0698eef09f6203abab10b0ffd5cb5fb901379bf2665c27a6c48852340936.png
# plot multiple lines by a matrix
Y = np.array([y, y2])  # stack data in two rows
plt.plot(x, Y.T); # transpose to give data in two columns
_images/cc3e25a3ec148f3f582f9eb453455d02cd63426d8f626bad9d5a699ca866885c.png
# plot multiple lines by a matrix
Y = np.array([np.sin(k*x) for k in range(4)])
plt.plot(x, Y.T);
_images/ba345399db57b587c2afe3c503312a2e87c2ca81ef72a8bf30e9c1c18dfbc81a.png

Options for plotting#

Line styles can be specified by

  • color= (or c= ) for color by code, name, RGB or RGBA

    • code: ‘r’, ‘g’, ‘b’, ‘y’, ‘c’, ‘m’, ‘k’, ‘w’

  • marker= for marker style

    • code: ‘.’, ‘o’, ‘+’, ‘*’, ‘^’, …

  • linestyle= (or ls= ) for line style

    • code: ‘-’, ‘–’, ‘:’, ‘-.’, …

  • linewidth= (or lw= ) for line width

  • a string of color, marker and line sytel codes, e.g. ‘ro:’

# using code string
plt.plot(x, y, 'm:', x, y2, 'c*');  # magenta dash-dot, cyan circle
_images/826d35732972722c6e80ae9c3a5f3e58a2ae855c9e5463a8b08bd4c5d5361363.png
# using keyword=value
plt.plot(x, y, c=[0.2,0.5,0.8,0.5], marker='o', markersize=10, ls='-.', lw=2);
_images/7d92f0594ef4c8e032d380ddd8cda3523917c1e3b6c2fe35b5cd093b65b0989b.png

It’s a good practice to add axis lables and plot title.

plt.plot(x, y)
plt.title('oscillation')
plt.xlabel('time ($\\mu s$)')
plt.ylabel('amplitude')
Text(0, 0.5, 'amplitude')
_images/44b65f695b3bdc6ef6225d29ed13b7c625fc9dc1b70da769c877ecbc64b3b7c8.png

It is also nice to add a legend box.

ax = plt.plot(x, y, x, y2)
plt.legend(('x sin x','x cos x'))
<matplotlib.legend.Legend at 0x111a25ca0>
_images/e68de60a58d71c46dc10cde37a234c208046b4ca9a957e8174e036bbfba3c471.png

You can control axis ranges and scaling.

plt.plot(x, y)
plt.xlim(-1, 5)
plt.ylim(-4, 4)
(-4.0, 4.0)
_images/c47db4946a2fa8d0b8f8a0f82e98b382b48d3951b32590068b5044acd5dd3064.png
plt.plot(y, y2)
plt.axis('equal')  # equal scaling for x and y
(-6.107980677841252, 8.582949839004911, -10.247801600732576, 7.121229063313089)
_images/296efd853f3fd988a90dda9f446ec412c7c3f9975075c46fe7cec0a4cf5857af.png
plt.plot(y, y2)
plt.axis('square')  # in square plot area
(-6.107980677841252,
 11.261049986204412,
 -10.247801600732576,
 7.121229063313088)
_images/27122b8bb9af22ca729874ea15d17b048d3a63ac4f097c7a1a7613661db206af.png

You can create a fiure of your preferred size by plt.figure() function

fig = plt.figure(figsize=(6, 6))
plt.plot(y, y2)
[<matplotlib.lines.Line2D at 0x111cdfd10>]
_images/b20555051806927c15317daaea3420580c1f9cc58eb43db8145e807a40c24667.png

Bar plot and histogram#

i = np.arange(10)
j = i**2
plt.bar(i, j)
<BarContainer object of 10 artists>
_images/d13a3a44d89cac25123ffccb0154de7acec55c0321ace4c3cf1f4158c9b8d4da.png

np.random.randn() gives random numbers from the normal distribution

z = np.random.randn(500)
plt.hist(z)
(array([  2.,  15.,  53.,  76., 108., 109.,  81.,  28.,  20.,   8.]),
 array([-2.91394416, -2.32460043, -1.73525671, -1.14591299, -0.55656926,
         0.03277446,  0.62211818,  1.21146191,  1.80080563,  2.39014935,
         2.97949308]),
 <BarContainer object of 10 artists>)
_images/fdcb05893b64e8754e3483ef7fff303fde804044b81e334c5adad96db24be305.png
plt.hist(z, bins=20)
(array([ 1.,  1.,  6.,  9., 21., 32., 29., 47., 53., 55., 53., 56., 48.,
        33., 18., 10., 11.,  9.,  5.,  3.]),
 array([-2.91394416, -2.6192723 , -2.32460043, -2.02992857, -1.73525671,
        -1.44058485, -1.14591299, -0.85124113, -0.55656926, -0.2618974 ,
         0.03277446,  0.32744632,  0.62211818,  0.91679005,  1.21146191,
         1.50613377,  1.80080563,  2.09547749,  2.39014935,  2.68482122,
         2.97949308]),
 <BarContainer object of 20 artists>)
_images/0b91ef5885e90f0dd4f427b699bcab5d068241c7a8d88c55861dfa774d44f383.png

Subplot and axes#

You can create multiple axes in a figure by subplot(rows, columns, index).
It uses a MATLAB legacy for index starting from 1.

plt.tight_layout() adjusts the space between axes.

plt.subplot(2, 2, 1)
plt.plot(x, y)
plt.xlabel('x'); plt.ylabel('y')
plt.subplot(2, 2, 2)
plt.plot(y, x)
plt.xlabel('y'); plt.ylabel('x')
plt.subplot(2, 2, 3)
plt.plot(x, y2)
plt.xlabel('x'); plt.ylabel('y2')
plt.subplot(2, 2, 4)
plt.plot(y, y2)
plt.xlabel('y'); plt.ylabel('y2')
plt.tight_layout()
_images/c75d65b260d2caded173daa7c3b1604f7820783c85afbc58a787bea887daa89a.png

Figure and axes#

When you make a plot, matplotlib creates a figure object with an axes object.
You can use gcf() and gca() to identify them and getp() and setp() to access their parameters.

plt.plot(x, y)
fig = plt.gcf()  # get current figure
plt.getp(fig)  # show all parameters
    agg_filter = None
    alpha = None
    animated = False
    axes = [<Axes: >]
    children = [<matplotlib.patches.Rectangle object at 0x111940d...
    clip_box = None
    clip_on = True
    clip_path = None
    constrained_layout = False
    constrained_layout_pads = (None, None, None, None)
    default_bbox_extra_artists = [<Axes: >, <matplotlib.spines.Spine object at 0x11...
    dpi = 100.0
    edgecolor = (1.0, 1.0, 1.0, 1.0)
    facecolor = (1.0, 1.0, 1.0, 1.0)
    figheight = 4.8
    figure = Figure(640x480)
    figwidth = 6.4
    frameon = True
    gid = None
    in_layout = True
    label = 
    layout_engine = None
    linewidth = 0.0
    mouseover = False
    path_effects = []
    picker = None
    rasterized = False
    size_inches = [6.4 4.8]
    sketch_params = None
    snap = None
    suptitle = 
    supxlabel = 
    supylabel = 
    tight_layout = False
    tightbbox = TransformedBbox(     Bbox(x0=49.77777777777777, y0...
    transform = IdentityTransform()
    transformed_clip_path_and_affine = (None, None)
    url = None
    visible = True
    window_extent = TransformedBbox(     Bbox(x0=0.0, y0=0.0, x1=6.4, ...
    zorder = 0
_images/f2c3cd2893d273e04fa79cb47382f8885484f6dc2ec8bcb7727f04ba4b5a655a.png
plt.plot(x, y)
fig = plt.gcf()
plt.setp(fig, size_inches=(8,4), facecolor=[0.5,0.5,0.5])
[None, None]
_images/6acf0471d2d0f5ca0e0614b825e1d2788b863799681806457a757643c70fb7de.png
plt.plot(x, y)
ax = plt.gca()  # get current axes
plt.getp(ax)
plt.setp(ax, facecolor='y')  # change parameters
    adjustable = box
    agg_filter = None
    alpha = None
    anchor = C
    animated = False
    aspect = auto
    autoscale_on = True
    autoscalex_on = True
    autoscaley_on = True
    axes_locator = None
    axisbelow = line
    box_aspect = None
    children = [<matplotlib.lines.Line2D object at 0x111f48d70>, ...
    clip_box = None
    clip_on = True
    clip_path = None
    data_ratio = 1.3355391378951056
    default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x111f18ad0>, ...
    facecolor or fc = (1.0, 1.0, 1.0, 1.0)
    figure = Figure(640x480)
    frame_on = True
    gid = None
    gridspec = GridSpec(1, 1)
    images = <a list of 0 AxesImage objects>
    in_layout = True
    label = 
    legend = None
    legend_handles_labels = ([], [])
    lines = <a list of 1 Line2D objects>
    mouseover = False
    navigate = True
    navigate_mode = None
    path_effects = []
    picker = None
    position = Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=...
    rasterization_zorder = None
    rasterized = False
    shared_x_axes = <matplotlib.cbook.GrouperView object at 0x111ee05c...
    shared_y_axes = <matplotlib.cbook.GrouperView object at 0x111ee2bd...
    sketch_params = None
    snap = None
    subplotspec = GridSpec(1, 1)[0:1, 0:1]
    tightbbox = Bbox(x0=49.77777777777777, y0=29.077777777777776, ...
    title = 
    transform = IdentityTransform()
    transformed_clip_path_and_affine = (None, None)
    url = None
    visible = True
    window_extent = TransformedBbox(     Bbox(x0=0.125, y0=0.109999999...
    xaxis = XAxis(80.0,52.8)
    xaxis_transform = BlendedGenericTransform(     CompositeGenericTrans...
    xbound = (-0.5, 10.5)
    xgridlines = <a list of 8 Line2D gridline objects>
    xlabel = 
    xlim = (-0.5, 10.5)
    xmajorticklabels = [Text(-2.0, 0, '−2'), Text(0.0, 0, '0'), Text(2.0,...
    xminorticklabels = []
    xscale = linear
    xticklabels = [Text(-2.0, 0, '−2'), Text(0.0, 0, '0'), Text(2.0,...
    xticklines = <a list of 16 Line2D ticklines objects>
    xticks = [-2.  0.  2.  4.  6.  8.]...
    yaxis = YAxis(80.0,52.8)
    yaxis_transform = BlendedGenericTransform(     BboxTransformTo(     ...
    ybound = (-6.107980677841252, 8.582949839004911)
    ygridlines = <a list of 10 Line2D gridline objects>
    ylabel = 
    ylim = (-6.107980677841252, 8.582949839004911)
    ymajorticklabels = [Text(0, -8.0, '−8'), Text(0, -6.0, '−6'), Text(0,...
    yminorticklabels = []
    yscale = linear
    yticklabels = [Text(0, -8.0, '−8'), Text(0, -6.0, '−6'), Text(0,...
    yticklines = <a list of 20 Line2D ticklines objects>
    yticks = [-8. -6. -4. -2.  0.  2.]...
    zorder = 0
[None]
_images/9849dba0a1021e01c32838bfa3db2e2cf00bafffc3a15beecf0d949ec1ed5d46.png

Visualizing data in 2D#

A standard way for visualizing pariwise data is a scatter plot.

n = 100
x = np.random.uniform(-1, 1, n)  # n points in [-1,1]
y = 2*x + np.random.randn(n)  # scale and add noise
plt.plot(x, y, 'o')
[<matplotlib.lines.Line2D at 0x111fb8b00>]
_images/680d80cb6d1c19ca8cd1d067221f41e9582e6bde6e0164b0f042eba36f33c19b.png

By scatterplot( ) you can specify the size and the color of each point to visualize higher dimension information.

z = x**2 + y**2
c = y - 2*x
# z for size, c for color
plt.scatter(x, y, z, c)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x111d54ce0>
_images/bdb16cc4dfc5676c5f70a9d04266c5ad8ae1891acb77bae0e1199d485d52c39c.png

Visualizing a matrix or a function in 2D space#

meshgrid() is for preparing x and y values in a grid.

x = np.linspace(-4, 4, 9)
y = np.linspace(-3, 3, 7)
print(x, y)
X, Y = np.meshgrid(x, y)
print(X, Y)
[-4. -3. -2. -1.  0.  1.  2.  3.  4.] [-3. -2. -1.  0.  1.  2.  3.]
[[-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]
 [-4. -3. -2. -1.  0.  1.  2.  3.  4.]] [[-3. -3. -3. -3. -3. -3. -3. -3. -3.]
 [-2. -2. -2. -2. -2. -2. -2. -2. -2.]
 [-1. -1. -1. -1. -1. -1. -1. -1. -1.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  1.  1.  1.  1.  1.  1.]
 [ 2.  2.  2.  2.  2.  2.  2.  2.  2.]
 [ 3.  3.  3.  3.  3.  3.  3.  3.  3.]]

We can use imshow() to visualize a matrix as an image.

Z = X**2 * Y
print(Z)
plt.imshow(Z)
[[-48. -27. -12.  -3.  -0.  -3. -12. -27. -48.]
 [-32. -18.  -8.  -2.  -0.  -2.  -8. -18. -32.]
 [-16.  -9.  -4.  -1.  -0.  -1.  -4.  -9. -16.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [ 16.   9.   4.   1.   0.   1.   4.   9.  16.]
 [ 32.  18.   8.   2.   0.   2.   8.  18.  32.]
 [ 48.  27.  12.   3.   0.   3.  12.  27.  48.]]
<matplotlib.image.AxesImage at 0x1120c40e0>
_images/2837c9b552291f5902c8c8b5f0c9393c0f27e94f23398a7e3741e1d3ff28fd65.png
# some more options
plt.imshow(Z, origin='lower', extent=(-4.5, 4.5, -3.5, 3.5))
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x111992540>
_images/01eb253f07e309acc8ae4fe5e7caa60f944bcb710520b0e820d089050bf841b2.png

color maps#

imshow( ) maps a scalar Z value to color by a colormap. The standard color map viridis is friedly to color blindness and monochrome printing. You can also choose other color maps.

plt.imshow(Z, cmap='jet')
<matplotlib.image.AxesImage at 0x1121c6270>
_images/a68600ce6a613c75a3ab562e51d096a09292999c5ffb25b4502f2e6591f8df34.png

contour plot#

x = np.linspace(-4, 4, 25)
y = np.linspace(-4, 4, 25)
X, Y = np.meshgrid(x, y)
Z = X**2 + 2*Y**2
plt.contour(X, Y, Z)
plt.axis('square')
(-4.0, 4.0, -4.0, 4.0)
_images/5cad26d3529b18947d75bbabd48661e44c4359aae6218ae3ac4e412c45405f08.png

vector field by quiver( )#

x = np.linspace(-3, 3, 15)
y = np.linspace(-3, 3, 15)
X, Y = np.meshgrid(x, y)
# Van del Pol model
k = 1  # paramter
U = Y  # dx/dt
V = k*(1 - X**2)*Y - X  # dy/dt
plt.quiver(X, Y, U, V)
<matplotlib.quiver.Quiver at 0x111bf4e60>
_images/d253409e54b0df34d7629302dc4c7bfd503ca0afb4aeed7b53d58ff0112534ab.png

Saving the image#

You can save a plot as a .png file by right-clicking it and choosing a pop-up menu like “save image as …” by the browser.

You can use plt.savefig() function to save it in other formats.

plt.quiver(X, Y, U, V)
plt.title('Van der Pol model')
plt.xlabel('u')
plt.ylabel('v')
plt.axis('square')
plt.savefig('VdP.pdf')
_images/b99a33de8fc55b4ef95ca2678d5e1b9c7d90570e4491372837d01b14335849f2.png
!open VdP.pdf