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 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) # 把温度转换为℃
开始绘图之前需进行数据选择,即中国区域的数据,特别是绘制南海小地图的更需要,可避免一些问题(小地图上方出现完整地图)
#中国整体范围
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)
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)
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()