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.

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
import numpy as np
import matplotlib.pyplot as plt

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 0x115a54680>]
_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 0x115aa1010>]
_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 0x115b7c8f0>,
 <matplotlib.lines.Line2D at 0x115b7c920>]
_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')
<>:3: SyntaxWarning: invalid escape sequence '\m'
<>:3: SyntaxWarning: invalid escape sequence '\m'
/var/folders/0z/3cttnw852b959kp4wjh_z_wc0000gn/T/ipykernel_51581/2066067687.py:3: SyntaxWarning: invalid escape sequence '\m'
  plt.xlabel('time ($\mu s$)')
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 0x115c77e00>
_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 0x115f8dd30>]
_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(100)
plt.hist(z)
(array([ 1.,  2., 14., 13., 20., 26., 11.,  8.,  4.,  1.]),
 array([-2.53293677, -1.99641202, -1.45988728, -0.92336253, -0.38683778,
         0.14968697,  0.68621172,  1.22273647,  1.75926122,  2.29578597,
         2.83231072]),
 <BarContainer object of 10 artists>)
_images/1be40db579a9358c9d7498a51a65820b121b7527130ed77c63d47c706963776f.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.subplot(2, 2, 1)
plt.plot(x, y)
plt.subplot(2, 2, 2)
plt.plot(y, x)
plt.subplot(2, 2, 3)
plt.plot(x, y2)
plt.subplot(2, 2, 4)
plt.plot(y, y2)
[<matplotlib.lines.Line2D at 0x115d1d070>]
_images/4f82110acb5b08c2fc622cbf67b83b5ed378be3dbbc0f26c6f5d3891df25d882.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 0x115f265...
    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 0x115c0b500>, ...
    clip_box = None
    clip_on = True
    clip_path = None
    data_ratio = 1.3355391378951056
    default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x11611c0b0>, ...
    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 0x115f6958...
    shared_y_axes = <matplotlib.cbook.GrouperView object at 0x115f683e...
    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 0x1160496d0>]
_images/3cc96e22393480fc38eade30ee5b53a0d810a0a58bea37725f4bbbcf5cbddc58.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 0x116189130>
_images/034e7acff8245ecaa6a0c65977ae5c53fe9fdedb3fd65c99be7a17203bdc0462.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 0x11629d070>
_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 0x116344a10>
_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 0x116419fa0>
_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 0x116419d30>
_images/d253409e54b0df34d7629302dc4c7bfd503ca0afb4aeed7b53d58ff0112534ab.png