2

I have 3 lists. x, y, and z. I would like to create a contour plot showing the intensity of z with a colour scale at point (x,y).

A question very similar to this has been asked and answered before (Python : 2d contour plot from 3 lists : x, y and rho?), but I am encountering problem where the x and y axis do not show up.

My script:

import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate

x =  [428, 598, 482, 351, 508, 413, 417, 471, 287, 578]
y =  [17449761, 19201380, 19766087, 18535270, 21441241, 20863875, 18686389, 17776179, 16372016, 20170943]
n =  [1.4406303782314329, 1.3248722314086339, 1.4064635429655712, 2.8806478042859767, 1.4067238073230157, 1.6444745940954972, 1.5180461138137205, 1.3819609357508074, 25.370740891787577, 1.3420941843768535]

# convert to arrays to make use of previous answer to similar question
x = np.asarray(x)
y = np.asarray(y)
z = np.asarray(n)
print "x = ", x
print "y = ", y
print "z = ", z

# Set up a regular grid of interpolation points
nInterp = 200
xi, yi = np.linspace(x.min(), x.max(), nInterp), np.linspace(y.min(), y.max(), nInterp)
xi, yi = np.meshgrid(xi, yi)

# Interpolate; there's also method='cubic' for 2-D data such as here
#rbf = scipy.interpolate.Rbf(x, y, z, function='linear')
#zi = rbf(xi, yi)
zi = scipy.interpolate.griddata((x, y), z, (xi, yi), method='linear')


plt.imshow(zi, vmin=z.min(), vmax=z.max(), origin='lower',
           extent=[x.min(), x.max(), y.min(), y.max()])

plt.xlabel("X")
plt.ylabel("Y")        
plt.colorbar()
plt.show()

This generates the following plot:

faulty_plot

I have played around with the Python scripts shown in Python : 2d contour plot from 3 lists : x, y and rho? and the number of interpolation points as well as the size of original lists/arrays appears to cause the problem of disappearing axis / failure to plot points.

I do not know what is causing this error. Any help is much appreciated.

Community
  • 1
  • 1
Aaron
  • 85
  • 2
  • 7

2 Answers2

1

As has been explained here, imshow by default uses an aspect ratio of 1. Which, in your case, leads to the badly scaled plot. Include a statement to adjust the aspect ratio in imshow - for example aspect='auto' - and you will get the plot you are expecting.

plt.imshow(zi, vmin=z.min(), vmax=z.max(), origin='lower',
       extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto') 

The result is:

enter image description here

Community
  • 1
  • 1
Schorsch
  • 7,761
  • 6
  • 39
  • 65
1

As an alternative, you might find it interesting to use tricontouring plot like this:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as mtri

x =  [428, 598, 482, 351, 508, 413, 417, 471, 287, 578]
y =  [17449761, 19201380, 19766087, 18535270, 21441241, 20863875, 18686389, 17776179, 16372016, 20170943]
z =  [1.4406303782314329, 1.3248722314086339, 1.4064635429655712, 2.8806478042859767, 1.4067238073230157, 1.6444745940954972, 1.5180461138137205, 1.3819609357508074, 25.370740891787577, 1.3420941843768535]

x = np.asarray(x)
y = np.asarray(y)
z = np.asarray(z)

triang = mtri.Triangulation(x, y)
plt.triplot(triang)
plt.tricontourf(triang, z, vmin=z.min(), vmax=z.max(), origin='lower',
       extent=[x.min(), x.max(), y.min(), y.max()])

plt.xlabel("X")
plt.ylabel("Y")        
plt.colorbar()
plt.show()

Tricontouring

Also refer to the exemples in tri module: http://matplotlib.org/api/tri_api.html

GBy
  • 1,719
  • 13
  • 19