Python matplotlib plotting series: Contour plots (2D)

 Contour plots are an excellent way to represent 3D data in a 2D space. Python matplotlib has three dedicated functions for the contour plot, namely:

  1. contour() -  for 2D discrete contours 
  2. countourf() - for 2D filled discrete contours
  3. imshow() -  for 2D data image
The three functions will be gradually explained here. But let us first state a problem, on which all these stated functions can be described and explained properly.

  • Problem statement:

Suppose z is a function of x and y, where z = x*y and x is a number between 1 to 13 and y is a number between -5 to 20. Plot some contours of the function z in the XY plane.

  • Solution by contour()

The function contour() takes at least one array z ( the function value/ the height). So, z should include the values of x and y in the given range. So, the first question is,'how to create this array z?'
The simplest way is via the meshgrid() function. To understand the working process of meshgrid() function, observe the following code and output:
import matplotlib.pyplot as plt
import numpy as np
xlist=np.linspace(1.0,13.0,7)
ylist=np.linspace(-5,20.0,6)
X, Y = np.meshgrid(xlist, ylist)
Z =X*Y
print('xlist\n',xlist,'\n','ylist\n',ylist,'\n','X\n',X,'\n','Y\n',Y,'\n','Z\n',Z)
The outputs are:
xlist
 [ 1.  3.  5.  7.  9. 11. 13.] 
 ylist
 [-5.  0.  5. 10. 15. 20.] 
 X
 [[ 1.  3.  5.  7.  9. 11. 13.]
 [ 1.  3.  5.  7.  9. 11. 13.]
 [ 1.  3.  5.  7.  9. 11. 13.]
 [ 1.  3.  5.  7.  9. 11. 13.]
 [ 1.  3.  5.  7.  9. 11. 13.]
 [ 1.  3.  5.  7.  9. 11. 13.]] 
 Y
 [[-5. -5. -5. -5. -5. -5. -5.]
 [ 0.  0.  0.  0.  0.  0.  0.]
 [ 5.  5.  5.  5.  5.  5.  5.]
 [10. 10. 10. 10. 10. 10. 10.]
 [15. 15. 15. 15. 15. 15. 15.]
 [20. 20. 20. 20. 20. 20. 20.]] 
 Z
 [[ -5. -15. -25. -35. -45. -55. -65.]
 [  0.   0.   0.   0.   0.   0.   0.]
 [  5.  15.  25.  35.  45.  55.  65.]
 [ 10.  30.  50.  70.  90. 110. 130.]
 [ 15.  45.  75. 105. 135. 165. 195.]
 [ 20.  60. 100. 140. 180. 220. 260.]]

So, meshgrid() takes two limits or ranges and returns two arrays as you can see above. X*Y performs elementwise multiplication and hence Z includes all the possible combination of multiplications of X and Y values returning an array with a shape equal to the X and Y array.
In the simplest form, we can plot the contour via the following code:
plt.contour(Z)
Notice that X and Y axis have the range of 6 and 5 respectively starting from 0. As we didn't mention the range of x and y axis in the contour() function, it fixed its range according to the element numbers of X and Y respectively. 
In the next plot, we will define the X and Y axis limit and add labels to every contour line. 
cp=plt.contour(X,Y,Z,colors='black')
plt.clabel(cp,fontsize=10)


Notice that, clabel() is used to show the labels of the line. Also, in the contour() function, we have added a colors command to make all contour lines of the same color. Notice that for single color, contour lines are dashed where the values of z is negative.
Further, the contour lines are at 50 values interval which is auto-adjusted. You can, however, specify how many lines you want or which value of z you want as contour lines.
Firstly, suppose we want 5 contour lines, we can do it by:
cp=plt.contour(X,Y,Z,5)
plt.clabel(cp,fontsize=10)
Lastly, we will define the contour values, along with title introduction and size adjustment:
levels=[5,23,27,150,200]
cp=plt.contour(X,Y,Z,levels)
plt.clabel(cp,fontsize=10)
plt.xlabel('x values')
plt.ylabel('y values')
fig=plt.gcf()
fig.set_size_inches(8,4)

  • Solution by contourf():

contourf() does exactly what contour() does, except that it filled the region between the contour lines. We can add a colormap to visualize the values more clearly.
cp=plt.contourf(X,Y,Z,cmap='hot')
plt.clabel(cp,fontsize=10)
plt.xlabel('x values')
plt.ylabel('y values')
plt.colorbar(cp)
fig=plt.gcf()
fig.set_size_inches(8,4)
Note that in cmap, the 'hot' colormap is used which is a sequential colormap (gradually increasing or decreasing the intensity of the color). Python has a variety of colormap and you can find them here
Also, colorbar() is used to show the colorbar.

  • Solution by imshow():

The previous two functions (contour and contourf) produce contour lines which are discrete. To get a continuous plot, imshow() is used, which produces an image  of 2D array data.
The following code produces the iage plot of the given problem:
plt.imshow(Z, extent=[0, 13, 0, 20], origin='lower',cmap='hot',aspect=0.5)
plt.colorbar()


Note that inside the imshow() function, unlike contour() or contourf() , we can't use arrays to define x and y axis. Rather, we have to specify the limits by an array in extent. Also,note that the origin has been set to lower to override the placement of origin at the upper left by default by imshow(). Again, the aspect of the graph is adjusted automatically by data given. Here, this is set manually.

  • Solution by both contour() and imshow():

Finally we can combine both contour and imshow via the following code:
contours = plt.contour(X, Y, Z,10,colors='black')
plt.clabel(contours, inline=True, fontsize=8)

plt.imshow(Z, extent=[0, 13, 0, 20], origin='lower',cmap='hot', aspect=0.5)
plt.colorbar()
The full code is available here.





Comments