使用边界框子集切片 NetCDF 变量

Slicing NetCDF variable using bounding box subset

背景

我正在尝试使用 lat/lons 的边界框对 NetCDF 文件进行切片。该文件的相关信息如下(变量、形状、尺寸):

根据此处的大多数答案和标准教程,这应该非常简单,我的解释是您只需找到 lat/lons 的索引并根据这些索引对变量数组进行切片。

Attempt/Code

 def netcdf_worker(nc_file, bbox):
    dataset = Dataset(nc_file)
    for variable in dataset.variables.keys():
        if (variable != 'lat') and (variable != 'lon'):
            var_name = variable
            break

    # Full extent of data
    lats = dataset.variables['lat'][:]
    lons = dataset.variables['lon'][:]

    if bbox:
        lat_bnds = [bbox[0], bbox[2]]  # min lat, max lat
        lon_bnds = [bbox[1], bbox[3]]  # min lon, max lon
        lat_inds = np.where((lats > lat_bnds[0]) & (lats < lat_bnds[1]))
        lon_inds = np.where((lons > lon_bnds[0]) & (lons < lon_bnds[1]))

        var_subset = dataset.variables[var_name][:, lat_inds[0], lon_inds[0]]

        # would also be great to slice the lats and lons too for visualization

问题

当尝试通过上述代码实施在 SO 上列出的其他答案中找到的解决方案时,我遇到了错误:

File "/Users/XXXXXX/Desktop/Viewer/viewer.py", line 41, in netcdf_worker
    var_subset = dataset.variables[var_name][:, lat_inds[0], lon_inds[0]]
  File "netCDF4/_netCDF4.pyx", line 4095, in netCDF4._netCDF4.Variable.__getitem__
  File "/Users/XXXXXX/Viewer/lib/python3.6/site-packages/netCDF4/utils.py", line 242, in _StartCountStride
    ea = np.where(ea < 0, ea + shape[i], ea)
IndexError: tuple index out of range

我相信我 missing/not 了解关于切片多维数组的一些小问题,希望得到任何帮助。我对任何带来任何其他包或在 python 外部运行的解决方案不感兴趣(请不要回答 CDO 或 NCKS!)。谢谢你的帮助。

在Python中,我认为最简单的解决方案是使用xarray。最小示例(使用一些 ERA5 数据):

import xarray as xr

f = xr.open_dataset('model_fc.nc')

print(f['latitude'].values)  # [52.771 52.471 52.171 51.871 51.571 51.271 50.971]
print(f['longitude'].values) # [3.927 4.227 4.527 4.827 5.127 5.427 5.727]

f2 = f.sel(longitude=slice(4.5, 5.4), latitude=slice(52.45, 51.5))  

print(f2['latitude'].values)  # [52.171 51.871 51.571]
print(f2['longitude'].values) # [4.527 4.827 5.127]

作为示例,我只显示了 latitudelongitude 变量,但是 NetCDF 文件中具有 latitudelongitude 维度的所有变量都被切片了自动。


或者,如果您想 select 手动框(使用 NetCDF4):

import netCDF4 as nc4
import numpy as np

f = nc4.Dataset('model_fc.nc')

lat = f.variables['latitude'][:]
lon = f.variables['longitude'][:]

# All indices in bounding box:
where_j = np.where((lon >= 4.5) & (lon <= 5.4))[0]
where_i = np.where((lat >= 51.5) & (lat <= 52.45))[0]

# Start and end+1 indices in each dimension:
i0 = where_i[0]
i1 = where_i[-1]+1

j0 = where_j[0]
j1 = where_j[-1]+1

print(lat[i0:i1])  # [52.171 51.871 51.571]
print(lon[j0:j1])  # [4.527 4.827 5.127]

当然,现在您必须手动对每个数据数组进行切片,例如使用var_slice = var[j0:j1, i0:i1]