Skip to article frontmatterSkip to article content

https://pyresample.readthedocs.io/en/latest/

This package seems a bit more speciallized, and does not have as tight of integration with xarray like xESMF and Verde do. If working with satellite or swath data, this is not one to miss! This package integrates with Satpy https://satpy.readthedocs.io/en/stable/ .

(more) Integration with xarray

Prerequisites

Knowing your way around xarray, numpy is beneficial. This is not deisgned to be an introduction to any of those packages. Would do this notebook after doing the xESMF one!

Imports

import pandas as pd
import numpy as np
import xarray as xr

import matplotlib.pyplot as plt

from appdirs import *

import dask.array as da

import pyresample
from pyresample import image, geometry
from pyresample.bilinear import NumpyBilinearResampler

from xarray import DataArray
from pyresample.bilinear import XArrayBilinearResampler

import os
%load_ext watermark
%watermark --iversions
pandas    : 2.3.3
sys       : 3.13.7 | packaged by conda-forge | (main, Sep  3 2025, 14:30:35) [GCC 14.3.0]
dask      : 2025.9.1
matplotlib: 3.10.6
appdirs   : 1.4.4
xarray    : 2025.9.1
numpy     : 2.3.3
pyresample: 1.34.2

Loading in one netCDF

file = '../data/onestorm.nc'

Let’s open this file with xarray:

ds = xr.open_dataset(file)
ds
Loading...

Trying to do the same thing with pyresample:

from pyresample.utils import load_cf_area
area_def, cf_info = load_cf_area('data/onestorm.nc', variable='visible', x='x', y='y')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/file_manager.py:219, in CachingFileManager._acquire_with_cache_info(self, needs_lock)
    218 try:
--> 219     file = self._cache[self._key]
    220 except KeyError:

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/lru_cache.py:56, in LRUCache.__getitem__(self, key)
     55 with self._lock:
---> 56     value = self._cache[key]
     57     self._cache.move_to_end(key)

KeyError: [<function _open_scipy_netcdf at 0x7f76de363420>, ('/home/runner/work/gridding-cookbook/gridding-cookbook/notebooks/data/onestorm.nc',), 'r', (('mmap', None), ('version', 2)), '752b4cc0-4fa4-410d-bdd5-34b799b7f787']

During handling of the above exception, another exception occurred:

FileNotFoundError                         Traceback (most recent call last)
Cell In[6], line 1
----> 1 area_def, cf_info = load_cf_area('data/onestorm.nc', variable='visible', x='x', y='y')

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/pyresample/utils/cf.py:444, in load_cf_area(nc_file, variable, y, x)
    441 if (x is not None and y is None) or (x is None and y is not None):
    442     raise ValueError("You must specify both or neither of x= and y=")
--> 444 nc_handle = _open_nc_file(nc_file)
    445 if variable is None:
    446     # if the variable=None, we search through all variables
    447     area_def, cf_info = _load_cf_area_several_variables(nc_handle)

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/pyresample/utils/cf.py:478, in _open_nc_file(nc_file)
    475 if isinstance(nc_file, xr.Dataset):
    476     return nc_file
--> 478 return xr.open_dataset(nc_file)

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/api.py:596, in open_dataset(filename_or_obj, engine, chunks, cache, decode_cf, mask_and_scale, decode_times, decode_timedelta, use_cftime, concat_characters, decode_coords, drop_variables, create_default_indexes, inline_array, chunked_array_type, from_array_kwargs, backend_kwargs, **kwargs)
    584 decoders = _resolve_decoders_kwargs(
    585     decode_cf,
    586     open_backend_dataset_parameters=backend.open_dataset_parameters,
   (...)    592     decode_coords=decode_coords,
    593 )
    595 overwrite_encoded_chunks = kwargs.pop("overwrite_encoded_chunks", None)
--> 596 backend_ds = backend.open_dataset(
    597     filename_or_obj,
    598     drop_variables=drop_variables,
    599     **decoders,
    600     **kwargs,
    601 )
    602 ds = _dataset_from_backend_dataset(
    603     backend_ds,
    604     filename_or_obj,
   (...)    615     **kwargs,
    616 )
    617 return ds

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/scipy_.py:395, in ScipyBackendEntrypoint.open_dataset(self, filename_or_obj, mask_and_scale, decode_times, concat_characters, decode_coords, drop_variables, use_cftime, decode_timedelta, mode, format, group, mmap, lock)
    393 store_entrypoint = StoreBackendEntrypoint()
    394 with close_on_error(store):
--> 395     ds = store_entrypoint.open_dataset(
    396         store,
    397         mask_and_scale=mask_and_scale,
    398         decode_times=decode_times,
    399         concat_characters=concat_characters,
    400         decode_coords=decode_coords,
    401         drop_variables=drop_variables,
    402         use_cftime=use_cftime,
    403         decode_timedelta=decode_timedelta,
    404     )
    405 return ds

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/store.py:42, in StoreBackendEntrypoint.open_dataset(self, filename_or_obj, mask_and_scale, decode_times, concat_characters, decode_coords, drop_variables, set_indexes, use_cftime, decode_timedelta)
     27 def open_dataset(
     28     self,
     29     filename_or_obj: T_PathFileOrDataStore,
   (...)     38     decode_timedelta=None,
     39 ) -> Dataset:
     40     assert isinstance(filename_or_obj, AbstractDataStore)
---> 42     vars, attrs = filename_or_obj.load()
     43     encoding = filename_or_obj.get_encoding()
     45     vars, attrs, coord_names = conventions.decode_cf_variables(
     46         vars,
     47         attrs,
   (...)     54         decode_timedelta=decode_timedelta,
     55     )

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/common.py:366, in AbstractDataStore.load(self)
    347 def load(self):
    348     """
    349     This loads the variables and attributes simultaneously.
    350     A centralized loading function makes it easier to create
   (...)    363     are requested, so care should be taken to make sure its fast.
    364     """
    365     variables = FrozenDict(
--> 366         (_decode_variable_name(k), v) for k, v in self.get_variables().items()
    367     )
    368     attributes = FrozenDict(self.get_attrs())
    369     return variables, attributes

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/scipy_.py:246, in ScipyDataStore.get_variables(self)
    244 def get_variables(self):
    245     return FrozenDict(
--> 246         (k, self.open_store_variable(k, v)) for k, v in self.ds.variables.items()
    247     )

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/scipy_.py:235, in ScipyDataStore.ds(self)
    233 @property
    234 def ds(self) -> scipy.io.netcdf_file:
--> 235     return self._manager.acquire()

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/file_manager.py:201, in CachingFileManager.acquire(self, needs_lock)
    186 def acquire(self, needs_lock: bool = True) -> T_File:
    187     """Acquire a file object from the manager.
    188 
    189     A new file is only opened if it has expired from the
   (...)    199         An open file object, as returned by ``opener(*args, **kwargs)``.
    200     """
--> 201     file, _ = self._acquire_with_cache_info(needs_lock)
    202     return file

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/file_manager.py:225, in CachingFileManager._acquire_with_cache_info(self, needs_lock)
    223     kwargs = kwargs.copy()
    224     kwargs["mode"] = self._mode
--> 225 file = self._opener(*self._args, **kwargs)
    226 if self._mode == "w":
    227     # ensure file doesn't get overridden when opened again
    228     self._mode = "a"

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/xarray/backends/scipy_.py:158, in _open_scipy_netcdf(filename, mode, mmap, version, flush_only)
    155             raise
    157 try:
--> 158     return netcdf_file(filename, mode=mode, mmap=mmap, version=version)
    159 except TypeError as e:  # netcdf3 message is obscure in this case
    160     errmsg = e.args[0]

File ~/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/scipy/io/_netcdf.py:251, in netcdf_file.__init__(self, filename, mode, mmap, version, maskandscale)
    249 self.filename = filename
    250 omode = 'r+' if mode == 'a' else mode
--> 251 self.fp = open(self.filename, f'{omode}b')
    252 if mmap is None:
    253     # Mmapped files on PyPy cannot be usually closed
    254     # before the GC runs, so it's better to use mmap=False
    255     # as the default.
    256     mmap = (not IS_PYPY)

FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/gridding-cookbook/gridding-cookbook/notebooks/data/onestorm.nc'

This is supposed to fail. Will chat about pro’s and con’s in the summary.

Resampling of gridded data using pyresample

Link to this turtorial is here: https://pyresample.readthedocs.io/en/latest/swath.html#pyresample-bilinear

We will be deconstructing it a bit to get into the details, but all of the code is from the above link.

target_def = geometry.AreaDefinition('areaD',
                                     'Europe (3km, HRV, VTC)',
                                     'areaD',
                                     {'a': '6378144.0', 'b': '6356759.0',
                                      'lat_0': '50.00', 'lat_ts': '50.00',
                                      'lon_0': '8.00', 'proj': 'stere'},
                                     800, 800,
                                     [-1370912.72, -909968.64,
                                      1029087.28, 1490031.36])

Unlike using xESMF, this does not depend or work with xarray:

print('target def type', type(target_def))
target def type <class 'pyresample.geometry.AreaDefinition'>
data = DataArray(da.from_array(np.fromfunction(lambda y, x: y*x, (500, 100))), dims=('y', 'x'))
type(data)
xarray.core.dataarray.DataArray
lons = da.from_array(np.fromfunction(lambda y, x: 3 + x * 0.1, (500, 100)))
lats = da.from_array(np.fromfunction(lambda y, x: 75 - y * 0.1, (500, 100)))
source_def = geometry.SwathDefinition(lons=lons, lats=lats)
resampler = XArrayBilinearResampler(source_def, target_def, 30e3)
result = resampler.resample(data)
type(result)
/home/runner/micromamba/envs/gridding-cookbook-dev/lib/python3.13/site-packages/pyproj/crs/crs.py:1295: UserWarning: You will likely lose important projection information when converting to a PROJ string from another format. See: https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems
  proj = self._crs.to_proj4(version=version)
xarray.core.dataarray.DataArray

Can export to xarray

result.to_dataset()
Loading...
data.to_dataset()
Loading...

Summary

Pyresample is a speciallist program, with strong functionality with satpy. Would reccomend if swath/sat image data is part of your normal workflow. For others, the requirement of the data being CF compliant and API is a hurdle.