寒潮是笔者主要的研究方向,寒潮路径作为寒潮重要的特征,是寒潮预报的重点之一,同样的道理也适用在台风研究以及降水的水汽来源研究中。关于路径的计算以及获取方法(比如轨迹倒推,模型追踪等等方法,台风有自己现成的数据集,比如ibtracs数据集等等)并不在本文的介绍范围之内,本文主要介绍在获取了相应的路径坐标后,如何在图中美观的展现。
上图展现了近40年东北亚区域的冬季冷空气活动路径,绘制这类图需要的数据只需为每条路径的N个三维坐标点,第一第二维分别为longitude和latitudee,第三维则比较随意,根据需要选择,比如说需要体现高度,那就用高度坐标,需要体现冷空气强度,那就用温度数据,水汽可以用相对湿度,台风也可以用速度等等。
通常此类数据是由.txt(.csv)等格式存储的,读取和处理方法可参考我的“Python气象数据处理与绘图(1):数据读取”,本文主要介绍绘图部分。
代码
#以下几行同先前文章所讲。使用时完全可以自定义函数进行封装,画图时直接调用,避免每次画地图均需设置诸多要素。
proj = ccrs.PlateCarree(central_longitude=95)
leftlon, rightlon, lowerlat, upperlat = (0,180,0,90)
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon_formatter = cticker.LongitudeFormatter()
lat_formatter = cticker.LatitudeFormatter()
fig3 = plt.figure(figsize=(12,7))
f3_ax6 = fig3.add_axes([0.1, 0.1, 0.6, 0.5],projection = proj)
f3_ax6.set_extent(img_extent, crs=ccrs.PlateCarree())
f3_ax6.add_feature(cfeature.COASTLINE.with_scale('50m'))
f3_ax6.add_feature(cfeature.LAKES, alpha=0.5)
f3_ax6.set_xticks(np.arange(leftlon,rightlon+30,30), crs=ccrs.PlateCarree())
f3_ax6.set_yticks(np.arange(lowerlat,upperlat+30,30), crs=ccrs.PlateCarree())
f3_ax6.xaxis.set_major_formatter(lon_formatter)
f3_ax6.yaxis.set_major_formatter(lat_formatter)
#以下为核心代码,n为路径条数,x,y,z分别为路径的三个维度,任意一维由[n,t]构成,比如说x[n,t],n为路径数,t指的是这一条路径是由t个时刻点构成。以此逐条路径循环绘制
for i in range(n):
lon = x[i,:]
lat = y[i,:]
#注意,X,Y第二维均为:,而h为1:,这是因为颜色只的是两点之间连线的颜色,m个点,产生m-1个线段,因此颜色的设置为从1开始,或者从0开始到倒数第一个,即为:-1,根据需要设置。
h = z[i,1:]
#将X,Y转置进同一数组,两两匹配
points = np.array([lon, lat]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
#设置色标的标准化范围(即将Z维度的数据对应为颜色数组)
norm = plt.Normalize(0, 5000)
#设置颜色线条,修改cmap调整colortable,transform为地图投影坐标转换
lc = LineCollection(segments, cmap='jet', norm=norm,transform=ccrs.PlateCarree())
lc.set_array(h)
#绘制线条
line = f3_ax6.add_collection(lc)
#以下为色标添加
position=fig3.add_axes([0.21, 0.03, 0.35, 0.025])
fig3.colorbar(line,cax=position,orientation='horizontal',format='%.1f')
当然根据需要,也可以直接绘制两维的轨迹,即取消掉颜色数组,用最简单的plot语句,循环绘制即可。
特别注意
有一个陷阱需要大家注意的是,当轨迹跨越了东西半球时,即穿越了0°或者360°经线时,它的连接方式是反向绕一圈,比如下图所示,你想要蓝色的轨迹,然而很有可能得到绿色的,这是因为你的网格数组的边界是断点,系统不会自动识别最短路径,只会在数组中直接想连,因为这不是循环数组。
我目前的解决办法是这样的:如果你的数据是0°-360°格式,那么变为-180°-180°的格式,反之相互转换。但是如果你的数据两种都出现了断点,也就是绕了地球一圈多,那无论怎样都么得办法了,我目前的思路是将数据转换成极坐标数据格式,理论上是可行的,CARTOPY的绘图也是支持极坐标数据的,具体实施还需要再试试。