by Megat Harun Al Rashid bin Megat Ahmad
last updated: April 14, 2016
The $Matplotlib$ library can be considered as the default data visualization and plotting tools for Python, even though there are others libraries that can be used e.g. $Chaco$, $PyX$, $Bokeh$ and $Lightning$. In this tutorial, we will focus exclusively on $Matplotlib$ and explore the basics and few of its large number of advanced features.
Users can start plotting with the minimum lines of codes to create a simple line plot. In a 2-dimensional plot, data for x and y coordinates can be represented by lists or $NumPy$ arrays. Users can import the plotting function from the $Matplotlib$ library as well as specify on how to display it.
In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
Here the line (%matplotlib inline) means that the plot when created will be displayed on the working document. The second line import the plotting function of $Matplotlib$ library.
In [2]:
# Data in lists
x = [1,2,3,4,5]
y = [21,34,78,12,9]
# Plot x against y
plt.plot(x, y)
Out[2]:
Replacing the first line with %matplotlib qt, an interactive plotting graphical user interface (GUI) will be displayed instead in a separate window (similar to MATLAB).
In [3]:
%matplotlib qt
plt.plot(x, y)
Out[3]:
This GUI allows users to interactively inspect the plot .e.g. enlarging specific plot region for details, moving the plot on the canvas, changing the axis range and colors etc.
However, we will only use (%matplotlib inline) for the remainder of this tutorial. Let us see some other basic codes that are needed to prepare more than a simple plot.
In [4]:
%matplotlib inline
plt.plot(x, y)
plt.title('Plot Title')
plt.xlabel("label x") # naming the x-axis label
plt.ylabel("label y") # naming the y-axis label
plt.legend(['data'], loc='upper right') # displaying legend and its position
# saving the image plot with specific resolution
plt.savefig("Tutorial7/First_Image.png", dpi = 300)
In the above example, the same x and y data are used (both of which have been declared beforehand), instead of just plotting, users can add title of the graph, names for x and y axes, insert legend and save the file with specific resolution (in this case as .png file). It is not necessary to declare %matplotlib inline in the cell when it is already declared in previous cell (but if %matplotlib qt was declared at some cells previously, then %matplotlib inline needs to be re-declared again). Much more features can be added (like below) and we will see these one by one.
In [5]:
import numpy as np
x = [1.0,2.0,3.0,4.0,5.0]
y1 = [21,34,78,12,9]
y2 = [10,25,63,26,15]
plt.figure(figsize=(12, 6)) # set the figure canvas size before plotting
# Two plots here in the same graph, each on top the other going down the list
plt.plot(x,y2,'b--s', ms = 8, mfc = 'r', label='data 1')
plt.plot(x,y1,'g-o', linewidth = 4, ms = 12, mfc = 'magenta', alpha = 0.5, label='data 2')
plt.xlim(0.5,5.5) # setting x-axis range
plt.ylim(0,100) # setting y-axis range
plt.xticks(np.linspace(0.5,5.5,11)) # creating x ticks using numpy array
plt.yticks(np.linspace(0,100,11)) # creating y ticks using numpy array
plt.grid() # showing grid (according to ticks)
plt.xlabel("label x") # naming the x-axis label
plt.ylabel("label y") # naming the y-axis label
plt.legend(loc='upper right') # displaying legend and its position
# saving the image plot with specific resolution
plt.savefig("Tutorial7/Second_Image.eps", dpi = 100)
Multiple plots can be created in many ways. It can be done by specifying the position of these plots on the whole canvas.
In [6]:
x_data = np.linspace(0.5,2.5,20) # Creating data
x_data
Out[6]:
In [7]:
# y data are calculated inside plot() function
fig = plt.figure(figsize=(8, 6)) # set the figure canvas size before plotting
axes1 = fig.add_axes([0.1, 0.1, 0.9, 0.9]) # creating first plot and its positions on canvas
axes2 = fig.add_axes([0.2, 0.55, 0.35, 0.35]) # creating second plot and its position on canvas
# main figure
axes1.plot(x_data,np.exp(x_data),'go-') # green with square object and line
axes1.set_xlabel('x main')
axes1.set_ylabel('y main')
axes1.set_title('main title')
# embedded figure
axes2.plot(x_data,x_data**(-1),'r--') # just a red dashed line
axes2.set_xlabel('x embedded')
axes2.set_ylabel('y embedded')
axes2.set_title('embedded title')
Out[7]:
The input cell above shows the user how to embed a plot within a plot by specifying the initial coordinates and sizes of the plots. A slightly different syntax is used here with the sub plot properties assigned to variables axes1 and axes2. From here on it is easy to add features to each plot by operating on the each plot variable.
It is possibly much better to use sub plotting functions (depends on users taste) like $subplot(i,j,k)$ function where $i$ represents number of rows, $j$ represents number of columns and $k$ is the position of the plot (moving horizontally to the left from above to below) as shown for $i$ = 2 and $j$ = 2 below.
In [8]:
# y data are calculated inside plot() function
plt.subplot(1,2,1) # graph with one row, two columns at position 1
plt.plot(x_data,np.exp(x_data),'go-') # green with square object and line
plt.subplot(1,2,2) # graph with one row, two columns at position 2
plt.plot(x_data,x_data**(-1),'r--') # just a red dashed line
Out[8]:
In [9]:
plt.subplot(2,2,1)
plt.plot(x_data,np.exp(x_data),'go-')
plt.subplot(2,2,2)
plt.plot(x_data,x_data**(-1),'r--')
plt.subplot(2,2,4)
plt.plot(x_data,x_data,'bs-')
Out[9]:
Other subplot functions like $subplot2grid()$ and $gridspec()$ allow more control on the produced multi-plots. In the case of $subplot2grid()$, the location of a plot in a 2-dimensional graphical grid can be specified using coordinate (i,j) with both i and j starting at $0$.
In [10]:
# A canvas of 2 x 3 graph
plot1 = plt.subplot2grid((2,3), (0,0), rowspan=2) # a(i,j) = starting at (0,0) and extend to (1,0)
plot2 = plt.subplot2grid((2,3), (0,1), colspan=2) # a(i,j) = starting at (0,1) and extend to (0,2)
plot3 = plt.subplot2grid((2,3), (1,1)) # a(i,j) = starting at (1,1)
plot4 = plt.subplot2grid((2,3), (1,2)) # a(i,j) = starting at (1,2)
The axes numerics are quite messy becuase of overlapping. User can use the $tight{\_}layout()$ function to automatically tidy up the whole graph.
In [11]:
# A canvas of 2 x 3 graph
p1 = plt.subplot2grid((2,3), (0,0), rowspan=2) # a(i,j) = starting at (0,0) and extend to (1,0)
p2 = plt.subplot2grid((2,3), (0,1), colspan=2) # a(i,j) = starting at (0,1) and extend to (0,2)
p3 = plt.subplot2grid((2,3), (1,1)) # a# it return best fit values for parameters
# pass the function name, x array, y array, initial value of parameters (in list)(i,j) = starting at (1,1)
p4 = plt.subplot2grid((2,3), (1,2)) # a(i,j) = starting at (1,2)
plt.tight_layout()
We can now add some data inside these plots using data in _xdata (and also increase the canvas size).
In [12]:
# A canvas of 2 x 3 graph
plt.figure(figsize=(8,4))
p1 = plt.subplot2grid((2,3), (0,0), rowspan=2) # a(i,j) = starting at (0,0) and extend to (1,0)
p2 = plt.subplot2grid((2,3), (0,1), colspan=2) # a(i,j) = starting at (0,1) and extend to (0,2)
p3 = plt.subplot2grid((2,3), (1,1)) # a(i,j) = starting at (1,1)
p4 = plt.subplot2grid((2,3), (1,2)) # a(i,j) = starting at (1,2)
plt.tight_layout()
p1.plot(x_data,np.exp(x_data),'go-')
p2.plot(x_data,2.0*np.exp(-((x_data-1.5)**2/(2*0.05))),'ms-') # Gaussian function for y value
p3.plot(x_data,x_data,'bs-')
p4.plot(x_data,x_data**(-1),'r--')
Out[12]:
Relative size of row and column can be specified using $GridSpec()$:
In [13]:
# a 2 x 2 grid plot with specified relative width and height
plt.figure(figsize=(8,4))
gs = plt.GridSpec(2, 2, width_ratios=[1,2],height_ratios=[2.5,1.5]) # a 2 x 2 grid plot
gp1 = plt.subplot(gs[0])
gp2 = plt.subplot(gs[1])
gp3 = plt.subplot(gs[2])
gp4 = plt.subplot(gs[3])
plt.tight_layout()
gp1.plot(x_data,np.exp(x_data),'go-')
gp2.plot(x_data,2.0*np.exp(-((x_data-1.5)**2/(2*0.05))),'ms-')
gp3.plot(x_data,x_data,'bs-')
gp4.plot(x_data,x_data**(-1),'r--')
gp4.set_yticks(np.linspace(0.4,2.0,5)) # setting the y ticks for plot 4
Out[13]:
$GridSpec()$ also allows the users to mix relative lengths of rows and columns with plots that extend these rows and columns (much like $subplot2grid()$).
In [14]:
plt.figure(figsize=(12,4))
gs1 = plt.GridSpec(3, 3, width_ratios=[1.5,1,1.5],height_ratios=[1.5,1,1.5])
gs1.update(left=0.05, right=0.48, wspace=0.3, hspace=0.4) # size on canvas
fp1 = plt.subplot(gs1[:2, :2])
fp2 = plt.subplot(gs1[0, 2])
fp3 = plt.subplot(gs1[2, :2])
fp4 = plt.subplot(gs1[1:, 2])
gs2 = plt.GridSpec(3, 3, width_ratios=[1.6,1,1.4],height_ratios=[1.3,1,1.7])
gs2.update(left=0.55, right=0.98, wspace=0.3, hspace=0.4) # size on canvas
afp1 = plt.subplot(gs2[:2,0])
afp2 = plt.subplot(gs2[:2, 1:])
afp3 = plt.subplot(gs2[2, :-1])
afp4 = plt.subplot(gs2[2, -1])
Similarly, let add some data:
In [15]:
plt.figure(figsize=(12,4))
gs1 = plt.GridSpec(3, 3, width_ratios=[1.5,1,1.5],height_ratios=[1.5,1,1.5])
gs1.update(left=0.05, right=0.48, wspace=0.3, hspace=0.4) # size on canvas
fp1 = plt.subplot(gs1[:2, :2])
fp2 = plt.subplot(gs1[0, 2])
fp3 = plt.subplot(gs1[2, :2])
fp4 = plt.subplot(gs1[1:, 2])
gs2 = plt.GridSpec(3, 3, width_ratios=[1.6,1,1.4],height_ratios=[1.3,1,1.7])
gs2.update(left=0.55, right=0.98, wspace=0.3, hspace=0.4) # size on canvas
afp1 = plt.subplot(gs2[:2,0])
afp2 = plt.subplot(gs2[:2, 1:])
afp3 = plt.subplot(gs2[2, :-1])
afp4 = plt.subplot(gs2[2, -1])
fp1.plot(x_data,2.0*np.exp(-((x_data-1.5)**2/(2*0.05))),'ms-')
fp2.plot(x_data,np.exp(x_data),'go-')
fp2.set_yticks(np.linspace(0,14,5))
fp3.plot(x_data,x_data,'bs-')
fp4.plot(x_data,x_data**(-1),'r--')
afp1.plot(x_data,x_data**(-1),'r--')
afp2.plot(x_data,2.0*np.exp(-((x_data-1.5)**2/(2*0.05))),'ms-')
afp3.plot(x_data,np.exp(x_data),'go-')
afp4.plot(x_data,x_data,'bs-')
afp4.set_yticks(np.linspace(0,3,6))
Out[15]:
Features of a plot like label font size, legend position, ticks number etc. can be specified. There are many ways to do all of these and one of the way (possibly with the easiest syntax to understand) is shown in the codes below. It is good practice to assigned the plotting function to a variable before setting these features. This is very useful when doing multiple plotting.
In [16]:
xl = np.linspace(4,6,31)
Lf = 5*(0.02/((xl-5)**2 + 0.02)) # Cauchy or Lorentz distribution
# Setting the canvas size and also resolution
plt.figure(figsize=(14,5), dpi=100)
# Assigning plotting function to variable, here subplot() is used
# even though there is only one plot
# and no ticks created on the frame (ticks are specified later)
Lp = plt.subplot(xticks=[], yticks=[])
# Plot certain borders with width specified
Lp.spines['bottom'].set_linewidth(2)
Lp.spines['left'].set_linewidth(2)
plt.subplots_adjust(left=0.1, right=0.9, top=0.75, bottom=0.25) # size on canvas
# Plotting
Lp.plot(xl, Lf, color="r", linewidth=2.0, linestyle="-")
# Title and Axes and Legend
Lp.set_title('Cauchy \nDistribution', fontsize=18, color='blue',\
horizontalalignment='left', fontweight='bold', x=0.05, y=1.05)
Lp.set_xlabel(r'$x$', fontsize=20, fontweight='bold', color='g')
Lp.set_ylabel(r'$L(x) = A\left[\frac{\gamma}{(x - x_{o})^{2} + \gamma}\right]$', \
fontsize=20, fontweight='bold', color='#DF0101')
# Legend
## Anchoring legend on the canvas and made it translucent
Lp.legend([r'$Lorentz$'], fontsize=18, bbox_to_anchor=[0.2, 0.98]).get_frame().set_alpha(0.5)
# Axes ticks and ranges
ytick_list = np.linspace(0,6,7)
Lp.set_xticks(np.linspace(0,10,11))
Lp.set_yticks(ytick_list)
Lp.set_xticklabels(["$%.1f$" % xt for xt in (np.linspace(0,10,11))], fontsize = 14)
Lp.set_yticklabels(["$%d$" % yt for yt in ytick_list], fontsize = 14)
## Major ticks
Lp.tick_params(axis='x', which = 'major', direction='out', top = 'off', width=2, length=10, pad=15)
Lp.tick_params(axis='y', which = 'major', direction='in', right = 'off', width=2, length=10, pad=5)
## Minor ticks
Lp.set_xticks(np.linspace(-0.2,10.2,53), minor=True)
Lp.tick_params(axis='x', which = 'minor', direction='out', top = 'off', width=1, length=5)
# Grid
Lp.grid(which='major', color='#0B3B0B', alpha=0.75, linestyle='dashed', linewidth=1.2)
Lp.grid(which='minor', color='#0B3B0B', linewidth=1.2)
# Save the plot in many formats (compare the differences)
plt.savefig("Tutorial7/Third_Image.eps", dpi = 500)
plt.savefig("Tutorial7/Third_Image.jpeg", dpi = 75)
The $r\$\{text\}\$$ notation allows the writing of mathematical equations using $LaTeX$ syntax.
Let us now see some variety of plot lines that can be created.
In [17]:
xv = np.linspace(0,10,11)
yv = 5*xv
# Setting the canvas size and also resolution
plt.figure(figsize=(14,4), dpi=100)
plt.xlim(0,50)
plt.ylim(0,50)
Lp = plt.subplot()
# Plot without top and right borders
Lp.spines['top'].set_visible(False)
Lp.spines['right'].set_visible(False)
# Show ticks only on left and bottom spines
Lp.yaxis.set_ticks_position('left')
Lp.xaxis.set_ticks_position('bottom')
# Title and axes labels
Lp.set_title('Variety of Plot')
Lp.set_xlabel(r'$x$')
Lp.set_ylabel(r'$y$')
# Plotting
## Line widths and colors
Lp.plot(xv+2, yv, color="blue", linewidth=0.25)
Lp.plot(xv+4, yv, color="red", linewidth=0.50)
Lp.plot(xv+6, yv, color="m", linewidth=1.00)
Lp.plot(xv+8, yv, color="blue", linewidth=2.00)
## Linestype options: ‘-‘, ‘–’, ‘-.’, ‘:’, ‘steps’
Lp.plot(xv+12, yv, color="red", lw=2, linestyle='-')
Lp.plot(xv+14, yv, color="#08088A", lw=2, ls='-.')
Lp.plot(xv+16, yv, color="red", lw=2, ls=':')
## Dash line can be cusotomized
line, = Lp.plot(xv+20, yv, color="blue", lw=2)
line.set_dashes([5, 10, 15, 10]) # format: line length, space length, ...
## Possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
Lp.plot(xv+24, yv, color="#0B3B0B", lw=2, ls='', marker='+', markersize = 12)
Lp.errorbar(xv+26, yv, color="green", lw=2, ls='', marker='o', yerr=5)
Lp.plot(xv+28, yv, color="green", lw=2, ls='', marker='s')
Lp.plot(xv+30, yv, color="#0B3B0B", lw=2, ls='', marker='1', ms = 12)
# Marker sizes and colorsplt.errorbar(x, y, xerr=0.2, yerr=0.4)
Lp.plot(xv+34, yv, color="r", lw=1, ls='-', marker='o', markersize=3)
Lp.plot(xv+36, yv, color="g", lw=1, ls='-', marker='o', markersize=5)
Lp.plot(xv+38, yv, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
Lp.plot(xv+40, yv, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=2, markeredgecolor="blue");
I suppose most aspects of the line plot have been covered but please remember that there are many ways in which a line plot can be created.
Histograms and bar charts can be plotted with similar syntax but will be explored further when we learn $Pandas$ in the next tutorial. $Pandas$ has a rich approach to produce histogram/bar charts with $Matplotlib$. Some examples of histograms/bars charts:
Some examples of histograms/bars charts from $Matplotlib$:
In [18]:
people = ['Rechtschaffen', 'Tadashi', 'Vertueux', 'Justo', 'Salleh']
num_of_publ = [20,34,51,18,46]
y_pos = np.arange(len(people))
plt.title('Academic Output')
plt.barh(y_pos, num_of_publ, align='center', color = '#DF0101', alpha=0.5)
plt.yticks(y_pos, people)
plt.xlabel('Number of Publications')
plt.ylabel('Academicians')
Out[18]:
It is possible to extract the data from histogram/bar chart.
In [19]:
n = np.random.randn(100000) # a 1D normalized random array with 100,000 elements
fig, Hp = plt.subplots(1,2,figsize=(12,4))
# Each bin represents number of element (y-axis values) with
# certain values in the bin range (x-axis)
Hp[0].hist(n, bins = 50, color = 'red', alpha = 0.25)
Hp[0].set_title("Normal Distribution with bins = 50")
Hp[0].set_xlim((min(n), max(n)))
Hp[1].hist(n, bins = 25, color = 'g')
ni = plt.hist(n, cumulative=True, bins=25, visible=False) # Extract the data
Hp[1].set_title("Normal Distribution with bins = 25")
Hp[1].set_xlim((min(n), max(n)))
Hp[1].set_ylim(0, 15000)
Out[19]:
In [20]:
ni
Out[20]:
The histogram plots below is an example from one of the $Matplotlib$ gallery example with some slight modifications and added comments.
In [21]:
'''Plot histogram with multiple sample sets and demonstrate:
* Use of legend with multiple sample sets
* Stacked bars
* Step curve with a color fill
* Data sets of different sample sizes
'''
n_bins = 10 # Number of bins to be displayed
x = np.random.randn(1000, 3) # A 2D normalized random array with 3 x 1,000 elements
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,8))
ax0, ax1, ax2, ax3 = axes.flat # Assigning the axes list to different variables
colors = ['red', 'tan', 'lime']
# {normed = 1} means that y-axis values are normalized
ax0.hist(x, n_bins, normed=1, histtype='bar', color=colors, label=colors)
ax0.legend(prop={'size': 10})
ax0.set_title('bars with legend')
ax1.hist(x, n_bins, normed=1, histtype='bar', stacked=True)
ax1.set_title('stacked bar')
ax2.hist(x, n_bins, histtype='step', stacked=True, fill=True)
ax2.set_title('stepfilled')
# Make a multiple-histogram of data-sets with different length
# or inhomogeneous 2D normalized random array
x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
ax3.hist(x_multi, n_bins, histtype='bar')
ax3.set_title('different sample sizes')
plt.tight_layout()
A 3D plot can be created by importing the Axes3D class and passing a projection='3d' argument.
In [22]:
from mpl_toolkits.mplot3d.axes3d import Axes3D
In [23]:
# 2D Gaussian Plot (3D image)
import matplotlib.cm as cm
import matplotlib.ticker as ticker
a = 12.0
b = 5.0
c = 0.3
fig = plt.figure(figsize=(6,4))
ax = fig.gca(projection='3d') # Passing a projection='3d' argument
X = np.linspace(4, 6, 100)
Y = np.linspace(4, 6, 100)
X, Y = np.meshgrid(X, Y)
R = (X-b)**2/(2*c**2) + (Y-b)**2/(2*c**2) # Use the declared a,b,c values in 1D-Gaussian
Z = a*np.exp(-R)
# Applying the plot features to variable surf
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.hsv,
linewidth=0, antialiased=True, alpha=0.3)
ax.set_zlim(-1.01, 14)
ax.zaxis.set_major_locator(ticker.LinearLocator(8))
ax.zaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
fig.colorbar(surf, shrink=0.4, aspect=10)
ax.view_init(30, 40) # Angles of viewing
plt.tight_layout()
Using the data X, Y and Z in the computer memory from the above cell, we create a wireframe plot and a surface plot with contour projection.
In [24]:
fig_wire = plt.figure(figsize=(12,6))
# Wireframe plot
ax1 = fig_wire.add_subplot(1,2,1, projection='3d')
ax1.plot_wireframe(X, Y, Z, rstride=4, cstride=4, alpha=0.75)
ax1.view_init(55, 30)
ax1.set_zlim(-2, 14)
ax1.set_title('Wireframe')
# Surface plot
ax2 = fig_wire.add_subplot(1,2,2, projection='3d')
ax2.plot_surface(X, Y, Z, rstride=6, cstride=6, alpha=0.45)
ax2.view_init(30, 30)
ax2.set_title('Surface and Contour')
# Different color maps used for each contours
# the offset argument refers to the position of contour
ax2.contour(X, Y, Z, zdir='x', offset=3, cmap=cm.hsv)
ax2.contour(X, Y, Z, zdir='y', offset=3, cmap=cm.prism)
ax2.contour(X, Y, Z, zdir='z', offset=-8, cmap=cm.coolwarm)
# Axes range for contours
ax2.set_xlim3d(3, 7)
ax2.set_ylim3d(3, 7)
ax2.set_zlim3d(-8, 20)
fig_wire.tight_layout()
$Matplotlib$ has the ability to generate a movie file from sequences of figures. Let see an example of the syntax needed to capture a Brownian motion in a video (it is necessary to explicitly import the animation module from $Matplotlib$).
In [25]:
# Brownian motion of particle suspended in liquid
nu = 0.7978E-3 # Pa s
kB = 1.3806488E-23 # m^2 kg s^-2 K^-1
d = 0.001 # 1 micron
T = 30+273.15 # Kelvin
D = kB*T/(3*np.pi*nu*d)
dt = 0.00001
dl = np.sqrt(2*D*dt)
In [26]:
xp = np.random.uniform(0,0.0001,20)
yp = np.random.uniform(-0.00000005,0.000000005,20)
for value in range(0,xp.size,1):
angle1 = np.random.normal(0,np.pi,500)
xb = xp[value]+np.cumsum(dl*np.cos(angle1))
yb = yp[value]+np.cumsum(dl*np.sin(angle1))
plt.figure(figsize=(6,4))
plt.plot(xb,yb)
Out[26]:
In [27]:
from matplotlib import animation # Importing the animation module
fig, ax = plt.subplots(figsize=(6,4))
xr = np.sqrt((xb.max()-xb.min())**2)/20.0
yr = np.sqrt((yb.max()-yb.min())**2)/20.0
ax.set_xlim([(xb.min()-xr), (xb.max()+xr)])
ax.set_ylim([(yb.min()-yr), (yb.max()+yr)])
line1, = ax.plot([], [], 'ro-')
line2, = ax.plot([], [], color="blue", lw=1)
x2 = np.array([])
y2 = np.array([])
def init():
line1.set_data([], [])
line2.set_data([], [])
def update(n):
# n = frame counter
global x2, y2
x2 = np.hstack((x2,xb[n]))
y2 = np.hstack((y2,yb[n]))
line1.set_data([xb[n],xb[n+1]],[yb[n],yb[n+1]])
line2.set_data(x2, y2)
# Creating the animation
# anim = animation.FuncAnimation(fig, update, init_func=init, frames=len(xb)-1, blit=True)
anim = animation.FuncAnimation(fig, update, init_func=init, frames=len(xb)-1)
# Saving the animation film in .mp4 format
anim.save('Tutorial7/Brownian.mp4', fps=10, writer="avconv", codec="libx264")
plt.close(fig)
Creating the video in a correct video format that can be run by your browser may require the installation of these tools (in my case with Ubuntu 14.04LTS):
sudo apt-get install ffmpeg libav-tools
sudo apt-get install libavcodec-extra-*
Different linux variants and other operating systems may require further tuning.
The video can then be displayed:
In [28]:
from IPython.display import HTML
video = open("Tutorial7/Brownian.mp4", "rb").read()
video_encoded = video.encode("base64")
video_tag = '<video controls alt="test" src="data:video/x-m4v;base64,{0}">'.format(video_encoded)
HTML(video_tag)
Out[28]:
Further $Matplotlib$ features can be found in http://matplotlib.org/index.html. Other interesting examples include tutorial by J.R. Johansson and the sane3d library.