matplotlib 使用Lambert投影绘制WRF数据的问题-未在数据顶部显示重叠线

3mpgtkmj  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(123)

我最近开始使用python通过jupyter在windows上绘制netCDF数据。然而,我在绘制使用Lambert Conformal投影的WRF运行的输出数据时遇到问题。我似乎无法将海岸线叠加并与数据图对齐,即海岸线叠加要么根本不显示,要么与数据略有偏移。这可能是由于数据的Lambert投影造成的吗引起问题?
下面是访问我使用的WRF输出nc文件的链接:https://drive.google.com/file/d/1s-0RLcaqIG0OoFEZtsE6_1xsE9B0DM1_/view?usp=sharing
我使用的代码的输出是附加的。

我似乎也无法在我使用的WRF输出文件上使用'Dataset',例如. ncfile = Dataset(“wrfout_d01_2016-10-07_00_00_00”)。这通常会导致以下错误:

61 lons = wrfnc.variables[lonvar][:]
    663 # Need to check all times
--> 664 for i in py3range(lats.shape[-3]):
    665     start_idxs = [0] * len(lats.shape)  # PyNIO does not support ndim
    666     start_idxs[-3] = i

IndexError:tuple index out of range
我对这一切都很陌生,所以如果这些是愚蠢的问题,我道歉。
下面是我尝试使用的代码。任何帮助解决这个错误将不胜感激。

from netCDF4 import Dataset
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

ds = xr.open_dataset("output_mean.nc")
temp2 = ds.T2[0,:,:]
temp2

fig = plt.figure(figsize=(5, 5))
ax1 = plt.axes(projection=ccrs.LambertConformal())
ax1.coastlines()

temp2.plot(ax=ax1, cmap='jet', transform=ccrs.LambertConformal())

ax1.set_extent([-140, -75, 17, 45], crs=ccrs.PlateCarree())

ax1.coastlines()

plt.show()
a64a0gku

a64a0gku1#

我认为还有一些不同的问题。避免使用Xarray数据集进行绘图可能会更清楚。为了方便起见,它通常是好的,但它也混淆了一些步骤,可能会增加这种情况下的混乱。看起来Xarray没有正确地选择坐标尺寸,如果你想直接使用Xarray数据集进行绘图,这可能需要一些修改。
我将从阅读Xarray对象到Numpy数组所需的数据开始:

import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

with xr.open_dataset("output_mean.nc") as ds:
    ds = ds.isel(Time=0) # strip the time dimension
    lons = ds["XLONG"].to_numpy()
    lats = ds["XLAT"].to_numpy()
    data = ds["T2"].to_numpy()

据我所知,坐标的投影并没有指定,但“WGS 84”或Cartopy中的ccrs.PlateCarree()通常是一个很好的猜测。
Cartopy中的默认LambertConformal与数据集中的数据具有不同的定义,您可以使用数据集中定义的值来指定相同的投影,它看起来应该是这样的:

map_proj = ccrs.LambertConformal(
    central_latitude=39, 
    central_longitude=-101, 
    standard_parallels=(32, 46),
)

如果你比较两者,你会注意到上面的定义并没有“扭曲”数据,与默认定义相比。如果数据在规则网格上,在同一个投影中绘制它可以避免在重新Map到不同投影时进行任何插值。这取决于需求是否需要。
有一件事你做错了,那就是指定LambertConformal作为数据的变换。但是使用Cartopy,你应该指定源数据的投影(你想要从源数据进行变换),它应该匹配你提供的坐标的投影,在这种情况下是纬度/经度坐标数组。目标投影,你想要变换到的地方,由轴的投影定义。

fig, ax = plt.subplots(
    figsize=(8, 5), facecolor="w",
    subplot_kw=dict(projection=map_proj ),
)

cm = ax.pcolormesh(lons, lats, data, cmap='turbo', transform=ccrs.PlateCarree())
cb = fig.colorbar(cm, ax=ax, shrink=.5)

# ax.set_extent([-140, -75, 17, 45], crs=ccrs.PlateCarree())
ax.coastlines()

如果省略设置范围,它将默认显示图中的所有数据:

使用LambertConformal()的默认定义会使其看起来像:

当然,在不同于输入数据的投影中绘图是完全有效的,但是在这样做时最好注意。
另一种方法是使用ax.imshow(假设它是一个规则的网格)绘图,这允许您按原样绘制数据(不需要重新投影),但这需要知道数据的范围。可能可以通过将角纬度/经度值重新投影到数据集中定义的投影来获得。

相关问题