前面的推文对于常用的Python绘图工具都有了一些介绍,在这里就不赘述了。本文主要就以下几个方面:“中国区域绘图”、“包含南海”、“兰伯特投影带经纬度标签”、“基于salm的mask方法”、“进阶中国区域mask方法”、“进阶省份mask方法”。对日常的实用需求能够在一定程度上满足。后续就Python在气象常用的统计方法(显著性检验)、合成分析、多变量叠加绘图再进行推送,敬请期待!
简单粗暴,Just show you my code!,细节暂不做过多分析,有问题可以探讨。数据、中文字体、地图shapefile文件、代码后文全部提供。使用建议,根据提示把缺失的库使用pip install xxx /conda install xxx /python setup.py install;安装完备,Python环境管理只推荐conda来统一管理。IDE推荐:PyCharm(有教育版)本地/服务器远程、Jupyter notebook。
Python资源共享群:484031800
•绘制兰勃脱投影的中国区域(包含南海子图)
•Mask掉海洋部分的兰勃脱投影(包含南海子图)
•基于salm的白化
•中国区域白化(包含南海子图)
•单独省份区域白化
1.绘制兰勃脱投影的中国区域(包含南海子图):
import numpy as np import xarray as xr import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature from copy import copy from cartopy.mpl.gridliner import LATITUDE_FORMATTER, LONGITUDE_FORMATTER import shapely.geometry as sgeom def find_side(ls, side): """ Given a shapely LineString which is assumed to be rectangular, return the line corresponding to a given side of the rectangle. """ minx, miny, maxx, maxy = ls.bounds points = {'left': [(minx, miny), (minx, maxy)], 'right': [(maxx, miny), (maxx, maxy)], 'bottom': [(minx, miny), (maxx, miny)], 'top': [(minx, maxy), (maxx, maxy)],} return sgeom.LineString(points[side]) def lambert_xticks(ax, ticks): """Draw ticks on the bottom x-axis of a Lambert Conformal projection.""" te = lambda xy: xy[0] lc = lambda t, n, b: np.vstack((np.zeros(n) + t, np.linspace(b[2], b[3], n))).T xticks, xticklabels = _lambert_ticks(ax, ticks, 'bottom', lc, te) ax.xaxis.tick_bottom() ax.set_xticks(xticks) ax.set_xticklabels([ax.xaxis.get_major_formatter()(xtick) for xtick in xticklabels]) def lambert_yticks(ax, ticks): """Draw ricks on the left y-axis of a Lamber Conformal projection.""" te = lambda xy: xy[1] lc = lambda t, n, b: np.vstack((np.linspace(b[0], b[1], n), np.zeros(n) + t)).T yticks, yticklabels = _lambert_ticks(ax, ticks, 'left', lc, te) ax.yaxis.tick_left() ax.set_yticks(yticks) ax.set_yticklabels([ax.yaxis.get_major_formatter()(ytick) for ytick in yticklabels]) def _lambert_ticks(ax, ticks, tick_location, line_constructor, tick_extractor): """Get the tick locations and labels for an axis of a Lambert Conformal projection.""" outline_patch = sgeom.LineString(ax.outline_patch.get_path().vertices.tolist()) axis = find_side(outline_patch, tick_location) n_steps = 30 extent = ax.get_extent(ccrs.PlateCarree()) _ticks = [] for t in ticks: xy = line_constructor(t, n_steps, extent) proj_xyz = ax.projection.transform_points(ccrs.Geodetic(), xy[:, 0], xy[:, 1]) xyt = proj_xyz[..., :2] ls = sgeom.LineString(xyt.tolist()) locs = axis.intersection(ls) if not locs: tick = [None] else: tick = tick_extractor(locs.xy) _ticks.append(tick[0]) # Remove ticks that aren't visible: ticklabels = copy(ticks) while True: try: index = _ticks.index(None) except ValueError: break _ticks.pop(index) ticklabels.pop(index) return _ticks, ticklabels # Load the border data, CN-border-La.dat is downloaded from # https://gmt-china.org/data/CN-border-La.dat with open('CN-border-La.dat') as src: context = src.read() blocks = [cnt for cnt in context.split('>') if len(cnt) > 0] borders = [np.fromstring(block, dtype=float, sep=' ') for block in blocks] # Set figure size proj = ccrs.LambertConformal(central_longitude=105, central_latitude=90, false_easting=400000, false_northing=400000)#,standard_parallels=(46, 49)) fig = plt.figure(figsize=[10, 8],frameon=True) # Set projection and plot the main figure ax = fig.add_axes([0.08, 0.05, 0.8, 0.94], projection=proj) # Set figure extent ax.set_extent([80, 130, 15, 55],crs=ccrs.PlateCarree()) # Plot border lines for line in borders: ax.plot(line[0::2], line[1::2], '-', lw=1.5, color='k', transform=ccrs.Geodetic()) # Add ocean, land, rivers and lakes ax.add_feature(cfeature.OCEAN.with_scale('50m')) ax.add_feature(cfeature.LAND.with_scale('50m')) ax.add_feature(cfeature.RIVERS.with_scale('50m')) ax.add_feature(cfeature.LAKES.with_scale('50m')) # *must* call draw in order to get the axis boundary used to add ticks: fig.canvas.draw() # Define gridline locations and draw the lines using cartopy's built-in gridliner: # xticks = np.arange(80,130,10) # yticks = np.arange(15,55,5) xticks = [55, 65, 75, 85, 95, 105,