前序博文cnmaps填色图介绍了cnmaps在线地图库如何绘制省级边界和白化,cartopy白化介绍了如何用cartopy白化中国地区(包含南海小地图和九段线),这篇博文可以说是两者的结合,即用cnmaps+cartopy白化中国地区并添加南海小地图,是更为方便简洁的中国地区白化方法。
这块主要绘制的是填色的中国大地区,并白化,和前序博文cnmaps填色图的思路基本一致,即:
值得注意的是,如果要添加南海九段线,绘制地图的时候要用map的返回值,如果用map_oneline,则没有九段线,只有南海诸岛。而对于白化来说,一定要使用map的地图返回,不然会报错,所以,代码里地图的返回值用了两种方式。本人还没发现更好的解决这个问题的办法,如果其他同学发现了,欢迎在评论区交流。
def map_plot(fig,ax,lat,lon,data, is_mask, is_province_boundary,title):
# 获取地图
big_map = get_adm_maps(country='中华人民共和国', level='国') #包含南海九段线,用于地图绘制
big_map_oneline = get_adm_maps(country='中华人民共和国', level='国', record='first', only_polygon=True) #用于白化
#绘制填色图
cf = ax.contourf(lon, lat,data, cmap=plt.cm.jet,levels=np.linspace(-12, 30, 43),transform=ccrs.PlateCarree())
#设置是否白化,白化必须基于一条边界(jingjinji2)
if is_mask:
clip_contours_by_map(cf, big_map_oneline)
#绘制地图
draw_maps(big_map,linewidth=1.2, color='k') #仅绘制所有省份的一条边界
#添加海岸线
ax.coastlines()
#设置显示区域
ax.set_extent([70,140,15,55], crs=ccrs.PlateCarree())
#设置标题
ax.set_title(title)
#添加经纬度格网
gl=ax.gridlines(draw_labels=True,linestyle=":",linewidth=0.1 ,x_inline=False, y_inline=False,color='k')
gl.top_labels=False #关闭上部经纬标签
gl.right_labels=False#关闭右边经纬标签
gl.rotate_labels=None#关闭兰伯特经纬标签旋转
gl.xformatter = LONGITUDE_FORMATTER #使横坐标转化为经纬度格式
gl.yformatter = LATITUDE_FORMATTER
#添加coloarbar
fig.colorbar(cf,ax=ax, shrink=0.9, extendfrac='auto',extendrect=True,location='bottom',fraction=0.05, pad=0.08)
添加南海小地图就是图中图的概念,最关键的有以下几点:
这里需要注意的是,绘制南海填色图时,lat, lon, data一定要用南海小地图范围内的数据,不要用全部大地图的数据,不然会出现两个大地图在同一图中。
#----------添加南海小地图------------------
def add_nanhai (ax, pos, lat, lon, data):
#--------------右下角添加南海地图------------------------------------------
lon1, lon2, lat1, lat2 = 103, 125, 2, 25
box_nanhai=[lon1, lon2, lat1, lat2] #南海小地图的经纬度位置
ax_nanhai = fig.add_axes(pos,projection = ccrs.PlateCarree()) #定义ax_nanhai
# #重新选择data数据,削减掉box_nanhai以外的数据,不然会把整个大地图填色再添加到图中
# lon_new = lon[]
# 重复大地图的画图步骤
nanhai = get_adm_maps(country='中华人民共和国', level='国') #包含南海九段线,用于地图绘制
nanhai_oneline = get_adm_maps(country='中华人民共和国', level='国', record='first', only_polygon=True) #用于白化
ax_nanhai.set_extent(box_nanhai, crs=ccrs.PlateCarree())
cf = ax_nanhai.contourf(lon.loc[lon1:lon2], lat.loc[lat1:lat2],data.loc[lat1:lat2, lon1:lon2], cmap=plt.cm.jet,levels=np.linspace(-12, 30, 43),transform=ccrs.PlateCarree())
clip_contours_by_map(cf, nanhai_oneline)
draw_maps(nanhai,linewidth=0.8, color='k')
ax_nanhai.coastlines()
# read data
data_path = "D:/ERA5/era5_for_o3/download_daily_mean_2m_temperature_2022_04.nc"
ds = xr.open_dataset(data_path)
temp = ds['t2m'].mean('time')-273.17 #求月均值,并换算为百帕
lat, lon = ds['lat'], ds['lon']
# 定义画布
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(6, 6))
#调入参数,画图
ax1 = fig.add_subplot(1,1,1, projection=proj)
map_plot(fig, ax1, lat, lon, temp, True, True, 'T2 in April 2022') #绘制大地图
pos1 = [0.78, 0.213, 0.12, 0.12] #南海小地图位置和长宽,根据画布自己调试
add_nanhai(ax1,pos1,lat,lon,temp) #添加南海小地图
plt.savefig('t2.jpg')
# %%
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
from cnmaps import get_adm_maps, draw_maps,clip_contours_by_map, draw_map
mpl.rcParams["font.size"] = 13
# %%
#----------------绘制大地图------------------------------
def map_plot(fig,ax,lat,lon,data, is_mask, is_province_boundary,title):
# 获取地图
big_map = get_adm_maps(country='中华人民共和国', level='国') #包含南海九段线,用于地图绘制
map_oneline = get_adm_maps(country='中华人民共和国', level='国', record='first', only_polygon=True) #用于白化
#绘制填色图
cf = ax.contourf(lon, lat,data, cmap=plt.cm.jet,levels=np.linspace(-12, 30, 43),transform=ccrs.PlateCarree())
#设置是否白化,白化必须基于一条边界(jingjinji2)
if is_mask:
clip_contours_by_map(cf, big_map_oneline)
#绘制地图
draw_maps(big_map,linewidth=1.2, color='k') #仅绘制所有省份的一条边界
#添加海岸线
ax.coastlines()
#设置显示区域
ax.set_extent([70,140,15,55], crs=ccrs.PlateCarree())
#设置标题
ax.set_title(title)
#添加经纬度格网
gl=ax.gridlines(draw_labels=True,linestyle=":",linewidth=0.1 ,x_inline=False, y_inline=False,color='k')
gl.top_labels=False #关闭上部经纬标签
gl.right_labels=False#关闭右边经纬标签
gl.rotate_labels=None#关闭兰伯特经纬标签旋转
gl.xformatter = LONGITUDE_FORMATTER #使横坐标转化为经纬度格式
gl.yformatter = LATITUDE_FORMATTER
#添加coloarbar
fig.colorbar(cf,ax=ax, shrink=0.9, extendfrac='auto',extendrect=True,location='bottom',fraction=0.05, pad=0.08)
# %%
#----------添加南海小地图------------------
def add_nanhai (ax, pos, lat, lon, data):
#--------------右下角添加南海地图------------------------------------------
lon1, lon2, lat1, lat2 = 103, 125, 2, 25
box_nanhai=[lon1, lon2, lat1, lat2] #南海小地图的经纬度位置
ax_nanhai = fig.add_axes(pos,projection = ccrs.PlateCarree()) #定义ax_nanhai
# #重新选择data数据,削减掉box_nanhai以外的数据,不然会把整个大地图填色再添加到图中
# lon_new = lon[]
# 重复大地图的画图步骤
nanhai = get_adm_maps(country='中华人民共和国', level='国') #包含南海九段线,用于地图绘制
nanhai_oneline = get_adm_maps(country='中华人民共和国', level='国', record='first', only_polygon=True) #用于白化
ax_nanhai.set_extent(box_nanhai, crs=ccrs.PlateCarree())
cf = ax_nanhai.contourf(lon.loc[lon1:lon2], lat.loc[lat1:lat2],data.loc[lat1:lat2, lon1:lon2], cmap=plt.cm.jet,levels=np.linspace(-12, 30, 43),transform=ccrs.PlateCarree())
clip_contours_by_map(cf, nanhai_oneline)
draw_maps(nanhai,linewidth=0.8, color='k')
ax_nanhai.coastlines()
# %%
# read data
data_path = "D:/ERA5/era5_for_o3/download_daily_mean_2m_temperature_2022_04.nc"
ds = xr.open_dataset(data_path)
temp = ds['t2m'].mean('time')-273.17 #求月均值,并换算为百帕
lat, lon = ds['lat'], ds['lon']
# %%
# 定义画布
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(6, 6))
#调入参数,画图
ax1 = fig.add_subplot(1,1,1, projection=proj)
map_plot(fig, ax1, lat, lon, temp, True, True, 'T2 in April 2022') #绘制大地图
pos1 = [0.78, 0.213, 0.12, 0.12] #南海小地图位置和长宽,根据画布自己调试
add_nanhai(ax1,pos1,lat,lon,temp) #添加南海小地图
plt.savefig('t2.jpg')
# %%