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()
会导致所有数据加载到内存中 - 这是您希望避免的。
最简单的方法是使用像 cdo
和 nco
这样的运算符。
例如:
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 是您常用的选项列表
- 一个 nc 文件以使用来自
的网格
- 常规网格说明符,例如r360x180
- 带有网格描述符的 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.
我正在尝试将 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()
会导致所有数据加载到内存中 - 这是您希望避免的。
最简单的方法是使用像 cdo
和 nco
这样的运算符。
例如:
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 是您常用的选项列表
- 一个 nc 文件以使用来自 的网格
- 常规网格说明符,例如r360x180
- 带有网格描述符的 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.