During this week, we are going to learn to use one of the most used plotting libraries available on python
, Matplotlib.
As we are going to use some array
-like structures, we are also going to keep working on NumPy.
Firts of all, matplotlib
is a huge library, so we are going to use (Not forever), just a small module, pylab
. This package can be imported, but we are going to use a standard method, such that,
import numpy as np
import matplotlib.pylab as plt
Where all the plt
functions belong to the plot library.
Second of all, we have to understand that matplotlib
does not plot functions, it plots array
-like structures or numbers, such as numpy.array
s, list
s, int
s, float
s and so on.
Let see some examples, consider the following list
x=[1,3,7,4]
we want to plot these points, easily we can use the matplotlib.pylab.plot
function.
plt.plot(x)
[<matplotlib.lines.Line2D at 0x10ec77d30>]
There are two relevant comments to do here,
array
(matplotlib
uses a range(len(.))
for the $x$ axis) on the latest matplotlib
versions. python
script, we should also use plt.show()
. Just for you not to get confused about it, we are going to use the line plt.show()
in all the cells with plots.One can give the plot additional options, for example, let us use points instead of lines on our plot
plt.plot(x,'o')
plt.show()
what if, additionally I want the points to be red,
plt.plot(x,'ro')
plt.show()
if we want to have more than one plot, we use matplotlib.pylab.plot
more than once before the matplotlib.pylab.show()
.
On the Jupyter notebook, we must use them on the same cell.
plt.plot(x,'ro')
plt.plot(x,'b')
plt.show()
Order is important!
plt.plot(x,'b')
plt.plot(x,'ro')
plt.show()
One can use severad already defined colors
Character | Color |
---|---|
'b' |
Blue |
'g' |
Green |
'r' |
Red |
'c' |
Cyan |
'm' |
Magenta |
'y' |
Yellow |
'k' |
Black |
'w' |
White |
The point style can be choosen from,
Character | Description | Character | Description |
---|---|---|---|
'.' |
Point | 's' |
Square |
',' |
Pixel | 'p' |
Pentagon |
'o' |
Circle | '*' |
Star |
'v' |
Triangle Down | 'h' |
Hexagon 1 |
'^' |
Triangle Up | 'H' |
Hexagon 2 |
'<' |
Triangle Left | '+' |
Plus |
'>' |
Triangle Right | 'x' |
x |
'1' |
Tri-Down | 'D' |
Diamond |
'2' |
Tri-Up | 'd' |
Thin Diamond |
'3' |
Tri-Left | '|' |
Vertical Line |
'4' |
Tri-Right | '_' |
Horizontal Line |
The lines allow us to choose among,
Character | Description |
---|---|
'-' |
Solid |
'--' |
Dashed |
'-.' |
Dash-dot |
':' |
Dotted |
'b' # blue markers with default shape
'ro' # red circles
'g-' # green solid line
'--' # dashed line with default color
'k^:' # black triangle_up markers connected by a dotted line
Let us use a bigger set of data, first we are going to generate some points as we did on the last homework, and then, we will load an external file.
def fun(x):
return np.sin(5*x)*np.exp(-x/5)
The function numpy.linspace
allows us to create an array with a certain amount of numbers on a given interval,
x=np.linspace(0,10,1000)
And, after that, create a new one applying a function to them,
y1=fun(x)
The plot, is done as simply as
plt.plot(x,y1)
plt.show()
We can add a legend,
plt.plot(x,y1,label='Function')
plt.legend()
plt.show()
Or even labels, on $x$
plt.plot(x,y1,label='Function')
plt.xlabel('Label on $x$')
plt.legend()
plt.show()
or in both $y$ and $x$ directions
plt.plot(x,y1,label='Function')
plt.xlabel('Label on $x$')
plt.ylabel('Label on $y$')
plt.legend()
plt.show()
And a title!
plt.plot(x,y1,label='Function')
plt.title('Title')
plt.xlabel('Label on $x$')
plt.ylabel('Label on $y$')
plt.legend()
plt.show()
There is a better way to do it, at the beginning it looks longer, but it will help us later when creating multiplots, it is using matplotlib.pylab.figure
s.
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x,y1)
plt.show()
Here, the labels are added a little bit different
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x,y1)
ax.set_xlabel('Label on $x$')
plt.show()
and so on,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x,y1,label='Title')
ax.set_xlabel('Label on $x$')
ax.set_ylabel('Label on $y$')
ax.set_title('Title')
plt.legend()
plt.show()
Let us use several experimental data on external files, you will be able to see the spectrum of a Deuterium and Tungsten (Wolfram) lamp, measued at the Optics Laboratory at the Universidad Nacional de Colombia.
On the following link you will find a folder with the data,
url='https://raw.githubusercontent.com/jmsevillam/Herramientas-Computacionales-UniAndes/master/Data/Spectra/'
We are going to open the files by using the numpy.genfromtxt
function
Deuterium=np.genfromtxt(url+'D.txt')
Tungsten=np.genfromtxt(url+'W.txt')
Both=np.genfromtxt(url+'W+D.txt')
This is one of the most important thins when working with data as we are,
print(Deuterium)
[[ 1.97750921e+02 4.96420000e-04] [ 1.97952761e+02 3.73730000e-04] [ 1.98154619e+02 1.24860000e-04] ... [ 1.02398952e+03 3.67800000e-05] [ 1.02423379e+03 -1.89400000e-05] [ 1.02447807e+03 2.32180000e-04]]
print(np.shape(Deuterium))
(3648, 2)
There are several ways to get the columns of the file, first
print(np.shape(Deuterium.T))
(2, 3648)
print(Deuterium.T)
[[ 1.97750921e+02 1.97952761e+02 1.98154619e+02 ... 1.02398952e+03 1.02423379e+03 1.02447807e+03] [ 4.96420000e-04 3.73730000e-04 1.24860000e-04 ... 3.67800000e-05 -1.89400000e-05 2.32180000e-04]]
Second, using a slicing strucure to extract the $n$th column,
print(Deuterium[:,0])
[ 197.75092074 197.952761 198.15461887 ... 1023.98952476 1024.23379367 1024.47806826]
Thus,
xD=Deuterium[:,0]
yD=Deuterium[:,1]
xW=Tungsten[:,0]
yW=Tungsten[:,1]
xB=Both[:,0]
yB=Both[:,1]
print(yD)
[ 4.9642e-04 3.7373e-04 1.2486e-04 ... 3.6780e-05 -1.8940e-05 2.3218e-04]
Again, the multiple plot goes as,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(xD,yD,label='Deuterium')
ax.plot(xW,yW,label='Tungsten')
ax.plot(xB,yB,label='Both')
ax.legend()
plt.show()
What if, we would like to have the three plots separated, here is where the figures and axes structure becomes useful, we may define more than one axes on each figure,
ax=fig.add_subplot(nml)
with n
,m
and l
numbers. n
is the number of columns, m
is the number of rows and l
is the position.
or equivalent
ax=fig.add_subplot(n,m,l)
This last one is needed when l>9
For example,
fig=plt.figure()
ax1=fig.add_subplot(311)
ax2=fig.add_subplot(312)
ax3=fig.add_subplot(313)
ax1.plot(xD,yD,label='Deuterium')
ax1.legend()
ax2.plot(xW,yW,label='Tungsten')
ax2.legend()
ax3.plot(xB,yB,label='Both')
ax3.legend()
plt.show()
But here we can see that, the space between the plots is not enough, one possible solution for this is changing the size of the figure,
fig=plt.figure(figsize=(15,6))
ax1=fig.add_subplot(311); ax2=fig.add_subplot(312); ax3=fig.add_subplot(313)
ax1.plot(xD,yD,label='Deuterium'); ax1.legend()
ax2.plot(xW,yW,label='Tungsten');ax2.legend()
ax3.plot(xB,yB,label='Both'); ax3.legend()
plt.savefig('plot1.pdf')
plt.show()
We can also change the color of the plots, for the default colors,
fig=plt.figure(figsize=(15,6))
ax1=fig.add_subplot(311); ax2=fig.add_subplot(312); ax3=fig.add_subplot(313)
ax1.plot(xD,yD,label='Deuterium'); ax1.legend()
ax2.plot(xW,yW,c='C1',label='Tungsten'); ax2.legend()
ax3.plot(xB,yB,label='Both'); ax3.legend()
plt.savefig('plot2.pdf')
plt.show()
The numeration starts on $0$
fig=plt.figure(figsize=(15,6))
ax1=fig.add_subplot(311); ax2=fig.add_subplot(312); ax3=fig.add_subplot(313)
ax1.plot(xD,yD,c='C0',label='Deuterium'); ax1.legend()
ax2.plot(xW,yW,c='C1',label='Tungsten'); ax2.legend()
ax3.plot(xB,yB,c='C2',label='Both'); ax3.legend()
plt.savefig('plot3.pdf')
plt.show()
A different example, is getting three columns and just one row
fig=plt.figure(figsize=(15,6))
ax1=fig.add_subplot(131); ax2=fig.add_subplot(132); ax3=fig.add_subplot(133)
ax1.plot(xD,yD,label='Deuterium'); ax1.legend()
ax2.plot(xW,yW,c='C1',label='Tungsten'); ax2.legend()
ax3.plot(xB,yB,c='C2',label='Both'); ax3.legend()
plt.savefig('plot4.pdf')
plt.show()
We can arange the plots differently,
fig=plt.figure(figsize=(10,5))
ax1=fig.add_subplot(221); ax2=fig.add_subplot(222); ax3=fig.add_subplot(212)
ax1.plot(xD,yD,label='Deuterium'); ax1.legend()
ax2.plot(xW,yW,c='C1',label='Tungsten'); ax2.legend()
ax3.plot(xB,yB,c='C2',label='Both'); ax3.legend()
plt.savefig('plot5.pdf')
plt.show()
Is a system of differential equations which becomes very famous, because it exhibits chaotic behavior with certain combination of paramters,
Named after Edward Lorenz, which during 1963 was developing a simplified mathematical model for atmospheric convection.
$$\frac{dx}{dt}=\sigma(y-x),$$$$\frac{dy}{dt}=x(\rho-z)-y,$$$$\frac{dz}{dt}=xy-\beta z.$$Where $\sigma$, $\rho$ and $\beta$ are the model parameteres.
The code that solves those equations can be found at the repository on the examples folder link.
On the following link there is a file with the data, on three columns
$x$ | $y$ | $z$ |
---|---|---|
We load just as before,
url='https://raw.githubusercontent.com/jmsevillam/Herramientas-Computacionales-UniAndes/master/examples/Lorentz%20Model/'
data=np.genfromtxt(url+'Lorentz.dat')
The data has the exact same structure as before,
print(data)
[[0.00000000e+00 1.00000000e+00 0.00000000e+00] [1.00000000e-01 9.90000000e-01 0.00000000e+00] [1.89000000e-01 1.00510000e+00 9.90000000e-04] ... [5.62775790e+00 6.07865401e+00 2.05607171e+01] [5.67284751e+00 6.26769956e+00 2.03545232e+01] [5.73233271e+00 6.46855338e+00 2.01672930e+01]]
So we must split it into the three columns
x=data[:,0]
y=data[:,1]
z=data[:,2]
As we have three coordinates, we can plot the projections,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.plot(x,y)
plt.show()
On a different axis,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel('$y$')
ax.set_ylabel('$z$')
ax.plot(y,z)
plt.show()
And on the last one!
fig=plt.figure()
ax=fig.add_subplot(111)
ax.set_xlabel('$x$')
ax.set_ylabel('$z$')
ax.plot(x,z)
plt.show()
If we want to visualize this on the three dimensions, by using another part of matplotlib
,
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111,projection='3d')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_zlabel('$z$')
ax.plot(x, y, z)
plt.show()
The plots do not have to be of the same kind when plotting the axes,
fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(221); ax1.set_xlabel('$x$'); ax1.set_ylabel('$y$')
ax1.plot(x, y)
ax2 = fig.add_subplot(222); ax2.set_xlabel('$y$'); ax2.set_ylabel('$z$')
ax2.plot(y, z)
ax3 = fig.add_subplot(223); ax3.set_xlabel('$x$'); ax3.set_ylabel('$z$')
ax3.plot(x, z)
ax4 = fig.add_subplot(224,projection='3d'); ax4.set_xlabel('$x$'); ax4.set_ylabel('$y$'); ax4.set_zlabel('$z$')
ax4.plot(x, y, z)
[<mpl_toolkits.mplot3d.art3d.Line3D at 0x10edfb4e0>]
On matplotlib
, there are several styles of plotting, a different than plot
, is the scater
, which looks like plotting with circles at first sight, but it will allows us to use many options,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x,z)
plt.show()
One option is the transparence,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x,z,alpha=0.1)
plt.show()
another one, is that we can use a pallete with the same or different array,
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x,z,c=y)
plt.show()
They can be combinated, and even we can generate a colorbar from there,
fig=plt.figure()
ax=fig.add_subplot(111)
pl=ax.scatter(x,z,c=y,alpha=0.5)
plt.colorbar(pl)
plt.show()
we are going to explore how to use two methods to plot surfaces, the first one, with the Axes3d
we have already used, and the other as if we are looking from above and the high is meant to be represented with color, just as a contourplot.
It is necessary that we understand the numpy.meshgrid
function, to do so, let us create a samall test
x=np.array([1,2])
y=np.array([3,4])
print(np.meshgrid(x,y))
[array([[1, 2], [1, 2]]), array([[3, 3], [4, 4]])]
It returns two arrays, so we have to separate them as,
X,Y=np.meshgrid(x,y)
print(X)
print(Y)
[[1 2] [1 2]] [[3 3] [4 4]]
So, if we think this as the pairs formed from (X[i,j],Y[i,j])
, they are all the possible combinations of the values of x
and y
.
For the surface plotting, first, we define a function we want to plot. (This example is thought to be on polar coordinates).
def f(r):
return np.exp(-r/5)*np.cos(3*r)
We have to define the points where we are going to generate the plot.
x=np.linspace(-5,5,1000)
y=np.linspace(-5,5,1000)
Create a grid, and from there, we create another grid with the radious information (Polar coordinates),
X,Y=np.meshgrid(x,y)
R=np.sqrt(X**2+Y**2)
We use the function we want to test,
Z=f(R)
Finally we can plot these matrices with the plot_surface
method,
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
surf = ax.plot_surface(X, Y, Z)
plt.show()
The other way, only needs one parameter, and uses range
s for the coordinates
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(Z)
plt.show()