Python draws Chinese map coloring map with South China Sea nine-dash line and compass

1. Library import

import cartopy
import numpy as np
import pandas as pd
import proplot as pplt
import geopandas as gpd
import matplotlib.pyplot as plt
from proplot import rc
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.path as mpath
import cmaps
seis = cmaps.GMT_seis

# 导出指北针的库
import gma
import gma.extend.mapplottools as mpt
import gma.extend.arrayenhancement as aec

# 导入自定义色带
from colormaps import parula

rc["font.family"] = "TeX Gyre Schola"
rc['tick.labelsize'] = 10
rc["axes.labelsize"] = 12
rc["axes.labelweight"] = "light"
rc["tick.labelweight"] = "light"

2. Import data

# 加载数据
import geopandas as gpd
file = r".\China map\中国省级地图GS(2019)1719号.geojson"
nine = r".\China map\九段线GS(2019)1719号.geojson"
china_main = gpd.read_file(file)
china_nine = gpd.read_file(nine)
china_main.head()

china_shp = "./nc data/Data_ipynb/country1"
from netCDF4 import Dataset 
import xarray as xr
nc_file = r".\nc data\EC-Interim_monthly_2018.nc" 
ds = xr.open_dataset(nc_file) 
lat = ds.latitude 
lon = ds.longitude 
data = (ds['t2m'][0,::-1,:] - 273.15) # 把温度转换为℃


3. Partial data preprocessing of the nine-dash line in the South China Sea

Data selection is required before starting drawing, that is, the data of the Chinese region, especially for drawing a small map of the South China Sea, which can avoid some problems (the complete map appears above the small map)

#中国整体范围
lon_range1=lon[(lon>=70)&(lon<=138)]
lat_range1=lat[(lat>=3)&(lat<=55)]
#南海九段线范围
lon_range2=lon[(lon>=104)&(lon<=125)]
lat_range2=lat[(lat>=0)&(lat<=27)]

china_full = data.sel(longitude=lon_range1,latitude=lat_range1)
china_sub = data.sel(longitude=lon_range2,latitude=lat_range2)
china_full_lon = china_full.longitude.values
china_full_lat = china_full.latitude.values
china_full_data = china_full.values

china_sub_lon = china_sub.longitude.values
china_sub_lat = china_sub.latitude.values
china_sub_data = china_sub.values

levels = np.arange(-25, 25 + 1, 1)  

4. Define the mask method, and cut out the data of the Chinese map part from the global nc data (cut the nc data according to the shp file)

def maskout_areas(originfig, ax, shp_path, proj=None):
    import shapefile
    import cartopy.crs as ccrs
    from matplotlib.path import Path
    #from cartopy.mpl.clip_path
    from matplotlib.patches import PathPatch
    #sf = shapefile.Reader(shp_path)
    sf = shapefile.Reader(shp_path,encoding='gbk')
    vertices = []
    codes = []
    for shape_rec in sf.shapeRecords():
        if shape_rec.record[2] == 'China':
            pts = shape_rec.shape.points
            prt = list(shape_rec.shape.parts) + [len(pts)]
            for i in range(len(prt) - 1):
                for j in range(prt[i], prt[i + 1]):
                    if proj:
                        vertices.append(proj.transform_point(pts[j][0], pts[j][1], ccrs.Geodetic()))
                    else:
                        vertices.append((pts[j][0], pts[j][1]))
                codes += [Path.MOVETO]
                codes += [Path.LINETO] * (prt[i + 1] - prt[i] - 2)
                codes += [Path.CLOSEPOLY]
            clip = Path(vertices, codes)
            clip = PathPatch(clip, transform=ax.transData)
    for contour in originfig.collections:
        contour.set_clip_path(clip)

5. Create a coloring map

levels = np.arange(-25, 25 + 1, 1)  

projn = ccrs.LambertConformal(central_longitude=107.5, 
                              central_latitude=36,
                              standard_parallels=(25.0, 47.0)
                            )
fig = plt.figure(figsize=(4,3.5),dpi=120,facecolor="w")
ax = fig.add_subplot(projection=projn)
# cs = data.plot.contourf(ax=ax,levels=levels,cbar_kwargs=cbar_kwargs,
#                         cmap=parula,transform=ccrs.PlateCarree(),
#                        )
#自定义colorbar 参数
cs = china_full.plot.contourf(ax=ax,levels=levels,add_colorbar=False,
                        cmap=parula,transform=ccrs.PlateCarree(),
                       )
# #basemask(ax=ax, cs=cs,shp=china_shp)
maskout_areas(originfig=cs,ax=ax,shp_path=china_shp,proj=projn)

ax.set_facecolor('#BEE8FF')
ax.spines['geo'].set_linewidth(0.5)
#ax.stock_img()
ax.set_extent([80, 130, 16, 52.5], crs=ccrs.PlateCarree())
ax.coastlines(linewidth=0.3,zorder=20)
ax.add_feature(cfeature.LAND, facecolor='white')
ax.add_feature(cfeature.LAKES.with_scale('110m'), facecolor='#BEE8FF')
#添加geopandas 读取的地理文件
ax.add_geometries(china_main["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="k",linewidth=.2)
ax.add_geometries(china_nine["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="black",linewidth=.3)
#设置标题
ax.set_title("Example Of China Lambert Projection")
gls = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree(), 
                   color='gray', linestyle='dashed', linewidth=0.2, 
                   y_inline=False, x_inline=False,
                   rotate_labels=0,xpadding=5,
                   xlocs=range(-180,180,10), ylocs=range(-90,90,5),
                   xlabel_style={
    
    "size":8,"weight":"bold"},
                   ylabel_style={
    
    "size":8,"weight":"bold"}
                  )
gls.top_labels= False                      
gls.right_labels=False

#添加南海小地图
# 定位南海子图的位置,四个数字需要调整
# 四个数字分别是(left, bottom, width, height):
# 子图左下角水平方向相对位置,左下角垂直方向相对位置,子图宽,子图高
ax2 = fig.add_axes([0.74, 0.24, 0.1, 0.25], projection = projn)
ax2.set_extent([104.5, 124, 0, 26],crs=ccrs.PlateCarree())
#ax2.set(xlim=(104.5, 125),ylim=(0, 26))
ax2.set_facecolor('#BEE8FF')
ax2.spines['geo'].set_linewidth(0.4)

cs2 = china_sub.plot.contourf(ax=ax2,levels=levels,add_colorbar=False,
                        cmap=parula,transform=ccrs.PlateCarree(),
                       )
#basemask(ax=ax2, cs=cs2,shp=china_shp)
maskout_areas(originfig=cs2,ax=ax2,shp_path=china_shp,proj=projn)
ax2.set_title("")

# 设置网格点
lb=ax2.gridlines(draw_labels=False,x_inline=False, y_inline=False,
                 linewidth=0.1, color='gray', alpha=0.8, 
                 linestyle='--' )
ax2.add_geometries(china_main["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="k",linewidth=.3)
ax2.add_geometries(china_nine["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="black",linewidth=.5)
ax2.add_feature(cfeature.LAND, facecolor='w')

## n.1 添加指北针
mpt.AddCompass(ax, LOC = (0.07, 0.86), SCA = 0.04, FontSize = 8)
## n.2 添加比例尺
mpt.AddScaleBar(ax, LOC = (0.2, 0.05), SCA = 0.12, FontSize = 6, 
                UnitPad = 0.2, BarWidth = 0.6)

cbar = fig.colorbar(cs,ax=ax,orientation='horizontal',
                    shrink=0.65,aspect=25,pad=.08)
cbar.ax.tick_params(labelsize=7.5,direction="in")
cbar.ax.tick_params(which="minor",direction="in")
#cbar.ax.xaxis.set_ticks_position('top')
cbar.set_label("Temperature (℃)",fontsize=9)
#cbar.ax.set_title("Sea Surface Temperature(m)",fontsize=9)
cbar.outline.set_linewidth(.4)
#plt.tight_layout()

insert image description here

Guess you like

Origin blog.csdn.net/qq_35240689/article/details/130132703