I have a polygon shapefile (the state of Illinois) and a CSV file with (lat, lon, zvalue). I want to plot a smooth contour plot representing those zvalues. Following is my code:
import glob
import fiona
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.mlab import griddata
# Read in the tabulated data
tabfname = glob.glob("Outputs\\*.csv")[0]
df = pd.read_table(tabfname, sep=",")
print(df.head())
lat, lon, z = list(df.y), list(df.x), list(df["Theil Sen Slope"])
z0, z1, z2 = np.min(z)+0.03, np.mean(z), np.max(z)-0.01
# Read some metadata of the shapefile
shp = glob.glob("GIS\\*.shp")[0]
with fiona.drivers():
with fiona.open(shp) as src:
bnds = src.bounds
extent = [values for values in bnds]
lono = np.mean([extent[0], extent[2]])
lato = np.mean([extent[1], extent[3]])
llcrnrlon = extent[0]-0.5
llcrnrlat = extent[1]-0.5
urcrnrlon = extent[2]+0.5
urcrnrlat = extent[3]+0.5
# Create a Basemap
fig = plt.figure()
ax = fig.add_subplot(111)
m = Basemap(llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat,
urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat,
resolution='i', projection='tmerc' , lat_0 = lato, lon_0 = lono)
# Read in and display the shapefile
m.readshapefile(shp.split(".")[0], 'shf', zorder=2, drawbounds=True)
# Compute the number of bins to aggregate data
nx = 100
ny = 100
# Create a mesh and interpolate data
xi = np.linspace(llcrnrlon, urcrnrlon, nx)
yi = np.linspace(llcrnrlat, urcrnrlat, ny)
xgrid, ygrid = np.meshgrid(xi, yi)
xs, ys = m(xgrid, ygrid)
zs = griddata(lon, lat, z, xgrid, ygrid, interp='nn')
# Plot the contour map
conf = m.contourf(xs, ys, zs, 30, zorder=1, cmap='jet')
cbar = m.colorbar(conf, location='bottom', pad="5%", ticks=(z0, z1, z2))
# Scatter plot of the points that make up the contour
for x, y in zip(lon, lat):
X, Y = m(x,y)
m.scatter(X, Y, zorder=4, color='black', s=1)
plt.show()
fig.savefig("Myplot.png", format="png")
And this is the output I got(The scattered black dots are there to show the spatial distribution of the points from which the interpolation was generated. I used Nearest Neighbor interpolation method here.):
I basically referred to the examples given in the following two links to plot this:
- https://gist.github.com/urschrei/29cd446ae8a8ec60ddbc
- https://matplotlib.org/basemap/users/examples.html
Now this image has 3 problems:
- The interpolated contour does not expand within the whole of the shapefile
- The part of the contour plot protruding out of the shapefile boundary is not masked off
- The contour is not smooth.
What I want is to overcome these three deficiencies of my plot and generate a smooth and nice looking plot similar to the ones shown below (Source: https://doi.org/10.1175/JCLI3557.1 ):
How do I achieve that?