Python实现NetCDF文件球面重网格化遇到问题求解决方案
大家好,这是我在这里提出的第一个问题^^
我需要对部分NetCDF文件做重网格化处理,先后尝试使用cdo和cf模块操作均失败,希望有人能推荐适配的其他模块,或帮忙排查报错原因。首先我尝试使用cf模块:
df = cf.read('my_file.nc')[0] # 定义新网格 lat1 = cf.DimensionCoordinate(data=cf.Data(np.arange(-90, 90.01, 0.1), 'degreesN')) lon1 = cf.DimensionCoordinate(data=cf.Data(np.arange(-180, 180.01, 0.1), 'degreesE')) # 重网格化 g = df.regrids({'lat': lat1, 'lon': lon1}, method='linear')
运行后报错:RuntimeError: Regridding methods will not work unless the ESMF library is installed,我不知道该如何在我使用的远程服务器上安装该依赖库。
之后我尝试使用cdo模块:
# 定义输入输出文件 infile='my_file.nc' outfile='newgrid.nc' # 存储目标网格参数的文件 gridfile='gridfile.txt' # 双线性重网格化 cdo.remapbil('gridfile.txt', input=infile, output=outfile)
运行后报错:
...
STDERR:Error (cdf_load_bounds) : Allocation of 134369280000 bytes failed. [ line 2048 file stream_cdf_i.c ]
System error message : Cannot allocate memory
我的源文件仅2GB左右,不清楚为什么该操作需要134GB内存。
我也尝试过使用xarray模块:
# 读取输入文件 da_input = xarray.open_dataarray('my_file.nc') # 定义新坐标 regrid_axis = np.arange(-90, 90, 0.1) # 执行插值 da_output = da_input.interp(latitude=regrid_axis) # 直接保存到文件 da_output.to_netcdf('output.nc')
该代码可以正常运行,但我认为它仅在笛卡尔平面做插值,而我需要的是球面插值效果。
提前感谢各位的帮助
问题更新
感谢大家的解答,最终定位问题出在源文件本身,其分辨率过高(300x300m)。我先将文件切分为多个小文件(切分操作中cdo.sellonlatbox也需要134GB内存,因此我选用xarray.sel完成切分),之后用cdo做重网格化再合并结果,完成了处理。
解决方案
1. cf模块ESMF依赖安装
远程服务器无需管理员权限也可安装,在个人目录下安装miniconda后,执行以下命令即可完成全部依赖配置:
conda install -c conda-forge esmf esmpy cf-python
2. CDO内存溢出优化
除了拆分文件的方案外,也可以通过参数调整降低CDO内存占用,无需拆分:
cdo -O -remapbil,gridfile.txt -f nc4 -z zip my_file.nc newgrid.nc
添加-f nc4 -z zip参数使用压缩格式做中间存储,可大幅降低内存峰值,避免内存申请失败。
3. xarray生态球面插值实现
可以使用xarray搭配xesmf库实现球面插值,底层基于ESMF,支持分块处理,不需要一次性加载全量数据,也不会出现内存溢出问题:
import xarray as xr import xesmf as xe import numpy as np # 分块读取文件,可根据服务器内存调整块大小 da_input = xr.open_dataarray('my_file.nc', chunks={'lat': 1000, 'lon': 1000}) # 定义目标网格 ds_out = xr.Dataset({ 'lat': (['lat'], np.arange(-90, 90.01, 0.1)), 'lon': (['lon'], np.arange(-180, 180.01, 0.1)), }) # 构建重插值器,可选bilinear(球面双线性)、conservative(球面保守插值)等算法 regridder = xe.Regridder(da_input, ds_out, 'bilinear', extrap_method='nearest_s2d') da_output = regridder(da_input) da_output.to_netcdf('spatial_regrid_output.nc')
xesmf安装命令:conda install -c conda-forge xesmf esmpy
内容的提问来源于stack exchange,提问作者vakuoka

