Regrid NetCDF/climate data using CDO (default), NCO (ncremap), or ncatted.
Help the user regrid climate/satellite NetCDF data. Default to CDO unless the user specifies NCO/ncremap.
conda install -c conda-forge cdo
conda install -c conda-forge nco
# apt (Debian/Ubuntu)
sudo apt install cdo nco
# brew (macOS)
brew install cdo nco
cdo remapnn,TARGET_GRID input.nc output.nc
cdo remapbil,TARGET_GRID input.nc output.nc
cdo remapcon,TARGET_GRID input.nc output.nc
# Generate weights once
cdo gencon,TARGET_GRID input.nc weights.nc
# Apply weights
cdo remap,TARGET_GRID,weights.nc input.nc output.nc
Pass a grid description file or an existing NetCDF file as TARGET_GRID.
gridtype = lonlat
xsize = 1440
ysize = 721
xfirst = -179.875
xinc = 0.25
yfirst = -90.0
yinc = 0.25
cdo griddes reference.nc > target_grid.txt
cdo remapbil,target_grid.txt input.nc output.nc
-O — overwrite output-R — reset time counter-P N — parallel processing (N threads)-setmisstoc,VALUE — replace missing values with VALUE-selname,VAR — select variable before regridding-mergetime — merge multiple time-step filescdo -O remapnn,target_grid.txt input.nc output.nc
for f in input_*.nc; do
cdo -O -P 8 remapbil,target_grid.txt "${f}" "${f%.nc}.regrid.nc"
done
cdo -O mergetime input_*.nc merged.nc
cdo -O remapcon,target_grid.txt merged.nc output.nc
ncatted -a units,lon,c,c,"degrees_east" \
-a units,lat,c,c,"degrees_north" \
input.nc input_fixed.nc
cdo remapnn,target_grid.txt input_fixed.nc output.nc
# Basic usage
ncremap -i input.nc -m weights.nc -o output.nc
# With MPAS projection and missing value
ncremap -i input.nc -m weights.nc -o output.nc -P mpas --mss_val=-9999
Requires the E3SM Unified environment or nco with ESMF support.
For large batches, wrap CDO with Dask:
import subprocess
from dask.distributed import LocalCluster, Client
cluster = LocalCluster(n_workers=8)
client = Client(cluster)
def regrid_file(fn):
out = fn.replace('.nc', '_regrid.nc')
cmd = f"cdo -O remap,{GRID},{WEIGHTS} -setmisstoc,-99999 {fn} {out}"
subprocess.run(cmd, shell=True, check=True)
futures = client.map(regrid_file, file_list)
client.gather(futures)
Alternatively use xesmf for pure-Python regridding:
import xesmf as xe
import xarray as xr
ds_in = xr.open_dataset("input.nc")
ds_out = xr.Dataset({"lat": (["lat"], lats), "lon": (["lon"], lons)})
regridder = xe.Regridder(ds_in, ds_out, "bilinear")
ds_regridded = regridder(ds_in)