python 中的 Regrid Netcdf 文件

Regrid Netcdf file in python

我正在尝试将 NetCDF 文件从 0.125 度重新网格化为 0.083 度空间比例。 netcdf 包含 224 个纬度和 464 个经度,它有一年的每日数据。

我为它尝试了 xarray,但它产生了这个内存错误: MemoryError: Unable to allocate 103. GiB for an array with shape (13858233841,) and data type float64

如何使用 python 重新网格化文件?

Xarray 使用称为 'lazy loading' 的东西来尝试避免使用过多内存。在您的代码中的某处,您正在使用一个将全部数据加载到内存中的命令,这是它无法做到的。相反,您应该指定计算,然后将结果直接保存到文件中。 Xarray 将一次执行一个块的计算,而不会将所有内容加载到内存中。

重新网格化的示例可能如下所示:

da_input = open_dataarray(
    'input.nc') # the file the data will be loaded from
regrid_axis = np.arange(-90, 90, 0.125) # new coordinates
da_output = da_input.interp(lat=regrid_axis) # specify calculation
da_ouput.to_netcdf('output.nc') # save direct to file

例如,da_input.load()da_output.compute() 会导致所有数据加载到内存中 - 这是您希望避免的。

最简单的方法是使用像 cdonco 这样的运算符。

例如:

cdo remapbil,target_grid infile.nc ofile.nc

target_grid 可以是描述符文件,或者您可以使用具有所需网格分辨率的 NetCDF 文件。记下可能适合您需要的其他重网格化方法。上面的例子是使用双线性插值。

另一个选项是 try cf-python,它可以(通常)在球面极坐标和笛卡尔坐标中重新网格化大于内存的数据集。它使用 ESMF 重新网格化引擎来执行此操作,因此可以使用线性、一阶和二阶保守、最近邻等重新网格化方法。

这是您需要的重新网格化示例:

import cf
import numpy

f = cf.example_field(2) # Use cf.read to read your own data

print('Source field:')
print(f)

# Define the output grid
lat = cf.DimensionCoordinate(
           data=cf.Data(numpy.arange(-90, 90.01, 0.083), 'degreesN'))
lon = cf.DimensionCoordinate(
          data=cf.Data(numpy.arange(0, 360, 0.083), 'degreesE'))

# Regrid the field
g = f.regrids({'latitude': lat, 'longitude': lon}, method='linear')

print('\nRegridded field:')
print(g)

产生:

Source field:
Field: air_potential_temperature (ncvar%air_potential_temperature)
------------------------------------------------------------------
Data            : air_potential_temperature(time(36), latitude(5), longitude(8)) K
Cell methods    : area: mean
Dimension coords: time(36) = [1959-12-16 12:00:00, ..., 1962-11-16 00:00:00]
                : latitude(5) = [-75.0, ..., 75.0] degrees_north
                : longitude(8) = [22.5, ..., 337.5] degrees_east
                : air_pressure(1) = [850.0] hPa

Regridded field:
Field: air_potential_temperature (ncvar%air_potential_temperature)
------------------------------------------------------------------
Data            : air_potential_temperature(time(36), latitude(2169), longitude(4338)) K
Cell methods    : area: mean
Dimension coords: time(36) = [1959-12-16 12:00:00, ..., 1962-11-16 00:00:00]
                : latitude(2169) = [-90.0, ..., 89.94399999999655] degreesN
                : longitude(4338) = [0.0, ..., 359.971] degreesE
                : air_pressure(1) = [850.0] hPa

有很多选项可以从其他字段获取目标网格,也可以明确定义它。可以找到更多详细信息 in the documentation

cf-python 将从附加到数据集的 CF 元数据推断出哪些轴是 X 轴和 Y 轴等,但如果缺少它,则总有办法手动设置它或解决它。

一个Python选项,使用CDO作为后端,是我的包nctoolkit:https://nctoolkit.readthedocs.io/en/latest/, instalable via pip (https://pypi.org/project/nctoolkit/)

它有一个名为 to_latlon 的内置方法,它将重新网格化到指定的 latlon 网格

在你的情况下,你需要做:

import nctoolkit as nc
data = nc.open_data(infile)
data.to_latlon(lon = [lon_min,lon_max],lat=[lat_min,lat_max], res =[0.083, 0.083])

从 python 中访问 cdo 功能的另一种方法是使用 Pypi cdo project:

pip install cdo 

那你可以做

from cdo import Cdo
cdo=Cdo()
cdo.remapbil("target_grid",input="in.nc",output="out.nc")

其中 target_grid 是您常用的选项列表

  1. 一个 nc 文件以使用来自
  2. 的网格
  3. 常规网格说明符,例如r360x180
  4. 带有网格描述符的 txt 文件(见下文)

有几种内置的重新网格化方法:

  • remapbic:双三次插值
  • remapbil:双线性插值
  • remapnn:最近邻插值
  • remapcon:一阶保守重映射
  • remapcon2:二阶保守重映射

您可以使用网格描述符文件来定义需要插值的区域...

在文件中 grid.txt

gridtype=lonlat
xfirst=X   (here X is the longitude of the left hand point)
xinc=0.083
xsize=NX   (here put the number of points in domain)
yfirst=Y
yinc=0.083
ysize=NY

更多详情可以参考我的video guide on interpolation.