最近在计算波作用通量,正好就画到了矢量箭头图,画的过程中发现还是有很多细节需要注意的,那就直接进入正题吧。
首先,矢量箭头图是分为两种的,一种类似我们常见的风场(左图),另一种则是特殊的流场,也就是流线图(右图),这两张都是画的Plumb通量,显然对于波通量来说还是箭头好一些。
对于左图和右图来说分别使用的画图函数为:
quiver([X, Y], U, V, [C], **kw)
和
streamplot([X, Y], U, V, [C], **kw)
我整理了相应的参数:
1. quiver
X: 数组,
为X坐标,通常为我们的经度lon
Y:
为Y坐标,通常为我们的纬度lat
U:
纬向风分量,二维数组
V:
经向风分量,二维数组
C:
箭头颜色数组,可为一种颜色,也可为颜色数组
units(单位): [ 'width' | 'height' | 'dots' | 'inches' | 'x' | 'y' | 'xy' ]
箭头尺寸(除长度外)以此单位的倍数计算——即是说选定单位后,箭头尺寸即是此单位的倍数
‘width’或’height’:轴(axis)的宽度或高度
‘dots’或’inches’:像素或英寸,基于图的dpi
‘x’, ‘y’或‘xy’:分别是X、Y或X2+Y2的数据单位(data units)
箭头依单位不同而不同。对于’x’或’y’,箭头会随着其一的增大(zoom in)而增大;对于其他单位,箭头的大小与缩放状态(zoom state)无关。对于’width’或’height’,当窗口重置时,箭头的大小会随着轴(axes)的宽度和高度的增大而增大
angles: [‘uv’ | ‘xy’]
用于决定箭头角度的方法,默认是’uv’
‘uv’:箭头的纵横比(axis aspect ratio)为1,所以若U==V,则绘图上箭头的方向与水平轴逆时针呈45度(正向右)。
‘xy’: 箭头从(x,y)指向(x + u,y + v)。例如,使用它来绘制渐变场(gradient field)。
或者,可以将任意角度指定为以水平轴逆时针方向的度数值的数组。
注意:反转数据轴将相应地仅使用angles='xy'反转箭头。
scale :
每个箭头长度单位的数据单位数量,例如,每个绘图宽度m / s;参数scale越小箭头越长。默认是None
若是None,一个简单的自动缩放算法将被采用,基于平均矢量长度和适量的数量。箭头长度单位由scale_units参数给出。
scale_units : [ 'width' | 'height' | 'dots' | 'inches' | 'x' | 'y' | 'xy' ]
如果关键字参数scale是None,那么箭头长度单位默认是None
例如:scale_units是’inches’,scale是2.0,(u,v)=(1,0),那么矢量将会是0.5英寸长。
如果scale_units是’width/height’,那么矢量长度是轴’width/height’的半长
如果scale_units是’x’那么矢量是x轴单位的0.5倍。要在x-y平面上画矢量,使得u和v与x和y有相同的单位,则应另angles=’xy’, scale_units’xy’, scale=1.
width : scalar(标量), optional
箭头杆(shaft)的宽度,以箭头单位衡量。常用的初始值是0.005倍的画的宽度
headwidth :
头部宽度相对于箭杆宽度的倍数,默认是3倍
headlength :
轴交叉处的头部长度,默认是4.5
minshaft :
箭头比例的长度,以头部长度为单位。
minlength :
最小长度为轴宽的倍数;如果箭头长度小于此值,则绘制该直径的点(六边形)。
pivot : [ 'tail' | 'mid' | 'middle' | 'tip' ], optional
箭头的基点,比如说选择mid,那个箭头中间位置就是所在坐标点位置。
老实说,关于units,scale,和scale_units的设置十分复杂,画图时可先均不设置,看看默认效果,然后逐渐调整。通常只调整scale即可,另外两项除非必要,均可不设置。
2. streamplot
略过相同部分
density : float
控制流线的闭合度。当密度为1时,将域划分为30x30网格。密度线性缩放此网格。网格中的每个单元格最多只能有一条横贯流线。对于每个方向上的不同密度,使用一个元组(密度x,密度y)。
linewidth : float or 2D array
流线的宽度。使用二维数组,可以在网格上改变线宽。数组的形状必须与u和v相同。
color:matplotlib颜色代码或二维数组
流线型的颜色。如果给定一个数组,则使用cmap和norm将其值转换为颜色。数组的形状必须与u和v相同。
cmap:颜色映射
用于绘制流线和箭头的彩色地图。这只在颜色是数组时使用。
norm:
规格化用于将亮度数据缩放到0,1的对象。如果没有,则拉伸(最小,最大)到(0,1)。这只在颜色是数组时使用。
arrowsize:float
箭头大小的比例因子。
arrowstyle:str
箭头样式。见https://matplotlib.org/api/_as_gen/matplotlib.patches.FancyArrowPatch.html#matplotlib.patches.FancyArrowPatch
minlength:浮动
轴线坐标中流线的最小长度。
start_points :
数据坐标中流线起点的坐标(与x和y数组的坐标相同)。
maxlength:浮点
轴线坐标中流线的最大长度。
integration_direction:{'forward','backward','both'}
将流线向前、向后或双向整合。默认值为“both”。
以上便是常用参数,仍有一些参数是可以使用的,比如说zorder(图层顺序),transform(坐标转换)等等。需要注意的是,当我们在地图投影上叠加风场时,需要设置transform=ccrs.PlateCarree() 来将坐标转换为圆柱地图投影坐标,该参数调用了cartopy库的函数,具体使用可参考我先前发布的文章,有关于地图投影的详细描写。
那么,再回到我们最开始展示的那张图,我给出该图的部分代码以供参考。
#以下四行为地图投影以及坐标轴的设置,具体参考先前发布的文章
proj = ccrs.PlateCarree(central_longitude=50)
leftlon, rightlon, lowerlat, upperlat = (0,180,0,90)
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon_formatter = cticker.LongitudeFormatter()
lat_formatter = cticker.LatitudeFormatter()
#创建画布
fig7 = plt.figure(figsize=(12,8))
#创建地图投影子图
f7_ax1 = fig7.add_axes([0.1, 0.1, 0.6, 0.6],projection = proj)
#地图相关设置,包括边界,河流,海岸线,坐标的经纬度显示
f7_ax1.set_extent([leftlon, rightlon, lowerlat, upperlat], crs=ccrs.PlateCarree())
f7_ax1.add_feature(cfeature.COASTLINE.with_scale('50m'))
f7_ax1.add_feature(cfeature.LAKES, alpha=0.5)
f7_ax1.set_xticks(np.arange(leftlon,rightlon+10,10), crs=ccrs.PlateCarree())
f7_ax1.set_yticks(np.arange(lowerlat,upperlat+10,10), crs=ccrs.PlateCarree())
f7_ax1.xaxis.set_major_formatter(lon_formatter)
f7_ax1.yaxis.set_major_formatter(lat_formatter)
f7_ax1.set_title('(a) quiver',loc='left')
#因为是波作用通量,首先画扰动流函数
cf=f7_ax1.contourf(lon,lat,streamf_mean/1e5,cmap='RdBu_r',extend='both',levels=np.arange(-16,18,2),transform=ccrs.PlateCarree())
c=f7_ax1.contour(lon,lat,streamf_mean/1e5,colors='black',linewidths=0.5,levels=np.arange(-16,18,2),transform=ccrs.PlateCarree())
#画矢量箭头核心代码在这里,::2表示每隔2个点画箭头,不然会太密集,记得在投影坐标上画时一定要设置transform
Q = f7_ax1.quiver(lon[::2], lat[::2], px_mean[::2,::2], py_mean[::2,::2],pivot='mid',width=0.0018,scale=10,headwidth=4,transform=ccrs.PlateCarree())
#添加色标
position=fig7.add_axes([0.57, 0.08, 0.35, 0.025])
fig7.colorbar(cf,cax=position,orientation='horizontal',format='%d',)
右半图的代码就不展示了,唯一区别就是quiver变成了streamplot,我没有过多修改。