Matplotlib 3.5.1流场图中实现箭头大小与线宽成正比
Matplotlib 3.5.1流场图中实现箭头大小与线宽成正比
我最近在处理一组随距离衰减的涡旋流场数据,举个简单的例子,用下面的代码就能生成这类流场:
import numpy as np # model flow field x = np.linspace(0, 2 * np.pi, 100) y = np.linspace(0, 2 * np.pi, 100) X, Y = np.meshgrid(x, y) U = (np.cos(X) * np.sin(Y)) * np.exp(-X) V = -np.sin(X) * np.cos(Y) * np.exp(-X)
我想用带箭头的流线图来可视化这个流场,并且让流线的线宽和流速大小成正比,这部分我已经实现了,代码如下:
import matplotlib.pyplot as plt # Create a figure with axes fig, ax1 = plt.subplots(1, 1, figsize=(3, 3)) mag = np.sqrt(U**2+V**2) # Create a streamplot on the axis lw = (mag/np.max(mag[10:,:])) stream = ax1.streamplot(X, Y, U, V, linewidth=lw, arrowsize=1.5) # Display the plots plt.tight_layout() plt.show()
但我还希望箭头大小也能和流场的速度大小成正比,不然图里会出现这种情况——在没有流动的区域也有箭头乱指,看起来很不直观。
(图中显示无流动区域有多余箭头,影响可视化效果)
我尝试了各种方法来解决这个问题,毕竟streamplot函数本身并不原生支持这个功能,但都没成功。比如我试着获取streamplot返回的对象,想重新调整箭头大小后再绘制,但下面这段代码根本画不出任何东西:
# Create a figure with axes fig, ax = plt.subplots(1, 1, figsize=(3, 3)) # Access the arrow collection arrow_coll = stream.arrows line_coll = stream.lines arrow_paths = arrow_coll.get_paths() ax.add_collection(arrow_coll) # Display the plots plt.tight_layout() plt.show()
之后我又想暴力获取原箭头的平均位置,然后换一种绘制方式(比如用FancyArrowPatch),但这里也遇到了瓶颈——我没法正确获取箭头在原坐标轴ax1中的坐标位置。我用下面的代码测试了一下,散点图显示的位置和原流线图里的箭头位置完全对不上:
# Create a figure with two axes fig, ax = plt.subplots(1, 1, figsize=(3, 3)) # Access the arrow collection arrow_coll = stream.arrows line_coll = stream.lines arrow_paths = arrow_coll.get_paths() transform = ax1.transData.inverted() full_transform = arrow_coll.get_transform() + transform for idx, path in enumerate(arrow_paths): vertices = full_transform.transform(arrow_paths[idx].vertices) pos = np.mean(vertices, axis=0) ax.scatter(pos[0], pos[1], marker='.') # Display the plots plt.tight_layout() plt.show()
(散点图显示获取的箭头位置和实际不符)
我现在有点迷茫,不太理解ax.streamplot()返回的到底是什么对象。理想情况下,我希望箭头大小能和线宽一样随流速缩放,或者至少让无流区的箭头消失也行,求各位帮忙!
备注:内容来源于stack exchange,提问作者vercors
相关产品推荐
相关产品推荐

