我正在尝试使用 xarray 和 cartopy 在地图上绘制流图。但是,图形是空的。我正在使用 NCEP 再分析 2 中的风组件,该文件可在 here 中找到。此数据的经度坐标范围为 0 到 360 度,经度坐标范围为 90 到 -90 度。
在没有地图的情况下绘制流线图按预期工作(我必须通过增加纬度对数据进行排序,正如 streamplot 函数所预期的那样):
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
dados = xr.open_dataset('u_v_sample_data.nc')
dados = dados.sortby('lat')
lc = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(270,330)).plot.streamplot(x='lon',
y='lat',
u='u',
v='v')
vetores = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(270,330)).plot.quiver(x='lon',
y='lat',
u='u',
v='v')
plt.show()
此代码创建以下情节:
当尝试使用 cartopy 在地图上绘制相同的数据时,我得到一个空图形(矢量图工作正常,而不是):
mapa = plt.axes( projection=ccrs.PlateCarree() )
lc = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(270,330)).plot.streamplot(x='lon',
y='lat',
u='u',
v='v',
transform = ccrs.PlateCarree(),
density=5,
ax=mapa)
vetores = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(270,330)).plot.quiver(x='lon',
y='lat',
u='u',
v='v',
transform = ccrs.PlateCarree(),
ax=mapa)
mapa.gridlines(draw_labels=True)
mapa.coastlines()
plt.show()
结果如下图:
最后,cartopy map画流线只有经度坐标变换到[-180,180]范围才有效,如下图(注意slice函数中的经度坐标):
dados.coords['lon'] = ( ( dados.coords['lon'] + 180 ) % 360 ) - 180
dados = dados.sortby( dados.lon )
mapa = plt.axes( projection=ccrs.PlateCarree() )
lc = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(-90,-30)).plot.streamplot(x='lon',
y='lat',
u='u',
v='v',
transform = ccrs.PlateCarree(),
density=5,
ax=mapa)
vetores = dados.sel(time='2023-03-17-00',
level=250,
lat=slice(-60,10),
lon=slice(-90,-30)).plot.quiver(x='lon',
y='lat',
u='u',
v='v',
transform = ccrs.PlateCarree(),
ax=mapa)
mapa.gridlines(draw_labels=True)
mapa.coastlines()
plt.show()
结果...
在 streamplot 文档中,x 和 y 数据的数组只有一个要求:均匀分布的严格递增数组以制作网格,因为它们是一维数组。
当经度数据在 [0,360] 范围内时,streamplot 函数似乎无法在 cartopy 地图上正确放置/绘制流线。
这是预期的行为还是 streamplot 和 cartopy 有问题?
谢谢!
从你的报价:
It seems that streamplot function cannot place/draw correctly streamlines over a cartopy map when longitude data is in [0,360] range...
,你已经知道了。
我可以通过下面的一些编码和输出图来确认。
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
noproj = projection=ccrs.PlateCarree()
shift90E = projection=ccrs.PlateCarree(central_longitude=90)
shift180 = projection=ccrs.PlateCarree(central_longitude=180)
shift90W = projection=ccrs.PlateCarree(central_longitude=-90)
# Creating dataset
w = 180
h = 90
# Domains of X,Y: (-180, 180), (-90, 90)
# Domains of X,Y are chosen to comply with ability to plot
# successfully with Cartopy.
Y, X = np.mgrid[-h:h:100j, -w:w:100j]
U = -1 - X**2 + Y
V = 1 + X - Y**2
#speed = np.sqrt(U**2 + V**2)
fig = plt.figure(figsize=[10, 6])
def ax_plot(index, use_project, title):
ax = fig.add_subplot(2,2,index, projection = use_project)
ax.streamplot(X,Y,U,V, density=[0.8, 0.8],transform=noproj,linewidth=0.6,minlength=0.2,arrowstyle='->')
ax.set_extent([-180,180, -90,90], crs=noproj)
ax.coastlines(resolution='110m', alpha=0.3)
ax.gridlines(draw_labels=["bottom", "left"])
ax.set_title(title)
ax_plot(1, noproj, "Zero-meridian-centered")
ax_plot(2, shift90E, "Centered at 90E longitude")
ax_plot(3, shift180, "Dateline-centered")
ax_plot(4, shift90W, "Centered at 90W longitude")
plt.show()
在经度域 (-180, 180) 中使用适当的数据,任何经度偏移的投影上的所有图都是好的。
与具有经度域(0, 360)的类似数据集进行比较, 就在代码行之后
V = 1 + X - Y**2
添加以下代码
X += 180
运行代码后,我得到了这些图。显然,其中一个情节是不可接受的。