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 0x11d73b210>]

There are multiple ways to pass variables to plot():
plot(y)
: x is assumed as the indices of yplot(x, y)
: specify both x and y valuesplot(x1, y1, x2, y2,...)
: multiple linesplot(x, Y)
: lines for columns of matrix Y
# specify both x and y values
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x11d84d3d0>]

# take another function of x
y2 = x*np.cos(x)
# plot two lines
plt.plot(x, y, x, y2)
[<matplotlib.lines.Line2D at 0x11dcac390>,
<matplotlib.lines.Line2D at 0x11dc94dd0>]

# phase plot
plt.plot(y, y2);
# you can supress <matplotlib...> output by ;

# 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

# plot multiple lines by a matrix
Y = np.array([np.sin(k*x) for k in range(4)])
plt.plot(x, Y.T);

Options for plotting#
Line styles can be specified by
color=
(orc=
) for color by code, name, RGB or RGBAcode: ‘r’, ‘g’, ‘b’, ‘y’, ‘c’, ‘m’, ‘k’, ‘w’
marker=
for marker stylecode: ‘.’, ‘o’, ‘+’, ‘*’, ‘^’, …
linestyle=
(orls=
) for line stylecode: ‘-’, ‘–’, ‘:’, ‘-.’, …
linewidth=
(orlw=
) for line widtha 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

# using keyword=value
plt.plot(x, y, c=[0.2,0.5,0.8,0.5], marker='o', markersize=10, ls='-.', lw=2);

It’s a good practice to add axis lables and plot title.
You can use Latex format by \( \).
plt.plot(x, y)
plt.title('oscillation')
plt.xlabel('time ($\\mu s$)') # $ $ for latex code with \\ for symbols
plt.ylabel('amplitude')
Text(0, 0.5, 'amplitude')

It is also nice to add a legend box.
ax = plt.plot(x, y, x, y2)
plt.legend(('x sin x','x cos x')) # second line in LaTex
<matplotlib.legend.Legend at 0x11dfc7f50>

The texts in a figure tend to be too small when included in a slide or a paper.
You can control the default font size by rcParams.update()
and specifying fontsize
for particular labels.
# set default font size to 20 point
plt.rcParams.update({'font.size': 20})
ax = plt.plot(x, y, x, y2)
plt.title('oscillation', fontsize=28) # title in 28 point
plt.xlabel('time ($\\mu s$)')
plt.ylabel('amplitude')
plt.legend(('t sin t','t cos t'))
<matplotlib.legend.Legend at 0x11dea6950>

You can control axis ranges and scaling.
plt.plot(x, y)
plt.xlim(-1, 5)
plt.ylim(-4, 4)
(-4.0, 4.0)

plt.plot(y, y2)
plt.axis('equal') # equal scaling for x and y
(-6.10798067784125, 8.582949839004911, -10.247801600732576, 7.121229063313089)

plt.plot(y, y2)
plt.axis('square') # in square plot area
(-6.10798067784125, 11.261049986204412, -10.247801600732576, 7.121229063313088)

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 0x11e95d450>]

Bar plot and histogram#
i = np.arange(10)
j = i**2
plt.bar(i, j)
<BarContainer object of 10 artists>

np.random.randn()
gives random numbers from the normal distribution
z = np.random.randn(500)
plt.hist(z)
(array([ 2., 2., 26., 61., 117., 117., 118., 44., 11., 2.]),
array([-3.72532545, -3.00287778, -2.28043011, -1.55798244, -0.83553476,
-0.11308709, 0.60936058, 1.33180825, 2.05425592, 2.7767036 ,
3.49915127]),
<BarContainer object of 10 artists>)

plt.hist(z, bins=20)
(array([ 1., 1., 0., 2., 11., 15., 18., 43., 56., 61., 57., 60., 63.,
55., 28., 16., 8., 3., 1., 1.]),
array([-3.72532545, -3.36410162, -3.00287778, -2.64165394, -2.28043011,
-1.91920627, -1.55798244, -1.1967586 , -0.83553476, -0.47431093,
-0.11308709, 0.24813674, 0.60936058, 0.97058442, 1.33180825,
1.69303209, 2.05425592, 2.41547976, 2.7767036 , 3.13792743,
3.49915127]),
<BarContainer object of 20 artists>)

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()

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 0x11eae13...
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=2.9027777777777715, y...
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

plt.plot(x, y)
fig = plt.gcf()
plt.setp(fig, size_inches=(8,4), facecolor=[0.5,0.5,0.5])
[None, None]

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 0x11ec8e250>, ...
clip_box = None
clip_on = True
clip_path = None
data_ratio = 1.3355391378951056
default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x11ec800d0>, ...
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 0x11ec29bd...
shared_y_axes = <matplotlib.cbook.GrouperView object at 0x11ecb06d...
sketch_params = None
snap = None
subplotspec = GridSpec(1, 1)[0:1, 0:1]
tightbbox = Bbox(x0=2.9027777777777715, y0=15.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 7 Line2D gridline objects>
xlabel =
xlim = (-0.5, 10.5)
xmajorticklabels = [Text(-2.5, 0, '−2.5'), Text(0.0, 0, '0.0'), Text(...
xminorticklabels = []
xscale = linear
xticklabels = [Text(-2.5, 0, '−2.5'), Text(0.0, 0, '0.0'), Text(...
xticklines = <a list of 14 Line2D ticklines objects>
xticks = [-2.5 0. 2.5 5. 7.5 10. ]...
yaxis = YAxis(80.0,52.8)
yaxis_transform = BlendedGenericTransform( BboxTransformTo( ...
ybound = (-6.10798067784125, 8.582949839004911)
ygridlines = <a list of 8 Line2D gridline objects>
ylabel =
ylim = (-6.10798067784125, 8.582949839004911)
ymajorticklabels = [Text(0, -7.5, '−7.5'), Text(0, -5.0, '−5.0'), Tex...
yminorticklabels = []
yscale = linear
yticklabels = [Text(0, -7.5, '−7.5'), Text(0, -5.0, '−5.0'), Tex...
yticklines = <a list of 16 Line2D ticklines objects>
yticks = [-7.5 -5. -2.5 0. 2.5 5. ]...
zorder = 0
[None]

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 0x11ece7710>]

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 0x11ed023d0>

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 0x11ee2c4d0>

# some more options
plt.imshow(Z, origin='lower', extent=(-4.5, 4.5, -3.5, 3.5))
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x11eea1d90>

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 0x11ef2f090>

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)

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 0x11edd1390>

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')

!open VdP.pdf