I am trying to make nan values outside the Indian region but it is still showing the values

48 views Asked by At
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from cartopy.io import shapereader

ax = plt.axes(projection=ccrs.PlateCarree())

clevs = [0, 0.05, 0.1, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60]

vp_fill = plt.contourf(tp.longitude, tp.latitude, tp.tprate[0,:,:]*1000, clevs,
transform=ccrs.PlateCarree(),cmap=plt.cm.viridis_r, extend='both')       

cbar = plt.colorbar(vp_fill, orientation='vertical')
cbar.ax.tick_params(labelsize=14)

# Set ticks and extent for the Indian region
ax.set_xticks([70, 75, 80, 85, 90, 95, 100], crs=ccrs.PlateCarree())
ax.set_yticks([5, 10, 15, 20, 25, 30, 35], crs=ccrs.PlateCarree())
ax.set_extent([68, 100, 5, 35])

plt.rcParams["figure.figsize"] = (12, 10)
ax.coastlines(alpha=0.8)

# Add states boundaries using the provided shapefile
shp = r'C:\Users\IMD\Swapi\india polygon\india-polygon.shp' # Replace with your actual path
ax.add_geometries(shapereader.Reader(shp).geometries(), ccrs.PlateCarree(), edgecolor='k',
facecolor='none')

plt.show()

I have tried mask function but it is showing TypeError: 'NoneType' object is not iterable

I also tried removing id column which contains none values but still showing same error

1

There are 1 answers

0
Ratislaus On

You could call ax.add_geometries() only for the shapes related to India. Here is an example of plotting states and provinces from the Natural Earth admin_1_states_provinces only if they are within India:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader

# map
fig = plt.figure(figsize=(12, 10))
ax = plt.axes(projection=ccrs.PlateCarree())

ax.set_title('India')

# ticks and extent for the Indian region
ax.set_xticks([70, 75, 80, 85, 90, 95, 100], crs=ccrs.PlateCarree())
ax.set_yticks([5, 10, 15, 20, 25, 30, 35], crs=ccrs.PlateCarree())
ax.set_extent([68, 100, 5, 35])

# get state and provinces boundaries of all countries from the Natural Earth
shapename = 'admin_1_states_provinces'
states_shp = shpreader.natural_earth(resolution='50m', category='cultural', name=shapename)
reader = shpreader.Reader(states_shp)
states = reader.records()

# show only states of India
for state in states:
    if state.attributes['admin'] == 'India':
        ax.add_geometries([state.geometry], ccrs.PlateCarree(), edgecolor='k', facecolor='none')

plt.show()

The result:

enter image description here

In case you want to show your filled contour data within India only, you can try to clip it with matplotlib.artist.Artist.set_clip_path() using a compound path generated from the patches corresponding to the plotted states of India:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
import numpy as np
import shapely.geometry as sg
import matplotlib.patches as patches
from matplotlib.patches import PathPatch
from matplotlib.path import Path

# map
fig = plt.figure(figsize=(12, 10))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_title('India')

# make some filled contour
clevs = [0, 0.05, 0.1, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60]
x, y = np.meshgrid(np.linspace(68, 100, 100), np.linspace(5, 37, 100))
z = y / x
cs = ax.contourf(x, y, z, clevs, transform=ccrs.PlateCarree(), cmap=plt.cm.viridis_r, extend='both')

# ticks and extent for the Indian region
ax.set_xticks([70, 75, 80, 85, 90, 95, 100], crs=ccrs.PlateCarree())
ax.set_yticks([5, 10, 15, 20, 25, 30, 35], crs=ccrs.PlateCarree())
ax.set_extent([68, 100, 5, 36])

# get state and provinces boundaries of all countries from the Natural Earth
shapename = 'admin_1_states_provinces'
states_shp = shpreader.natural_earth(resolution='50m', category='cultural', name=shapename)
reader = shpreader.Reader(states_shp)
states = reader.records()

# collect patches of all states of India
state_patches = []
for state in states:
    if state.attributes['admin'] == 'India':
        # show a state on the map only if it is in India
        ax.add_geometries([state.geometry], ccrs.PlateCarree(), edgecolor='k', facecolor='none')
        if isinstance(state.geometry, sg.MultiPolygon):
            # if this state includes a few polygons, process them separately
            polygons = list(state.geometry.geoms)
            for p in polygons:
                # make a patch out of this polygon and store it
                state_patches.append(patches.Polygon(np.array(p.exterior.xy).T))
        else:
            # make a patch out of this polygon and store it
            state_patches.append(patches.Polygon(np.array(state.geometry.exterior.xy).T))

# make a compound path out of vertices and codes of the state patches
vertices = np.concatenate([i.get_path().vertices for i in state_patches])
codes = np.concatenate([i.get_path().codes for i in state_patches])

# clip the filled contour using that compound path
cs.set_clip_path(PathPatch(Path(vertices, codes), transform=ax.transData))

plt.show()

The output: enter image description here