OverlapConservativeResampler — first-order overlap-area conservative remapping#
OverlapConservativeResampler implements the classical first-order
conservative remapping used in Earth-system modelling: each source cell’s
value is redistributed over every HEALPix cell it overlaps, with weights
proportional to the source/target intersection areas.
This is the same mathematical formulation as ESMF/xESMF conservative
(and conservative_normed), applied to a HEALPix destination grid.
Which conservative method do I want?#
healpix-resample offers three different notions of conservation. They
are not interchangeable — they answer different questions.
Class / mode |
Geometry |
Local redistribution |
Conserves |
PSF-aware |
|---|---|---|---|---|
|
sample → containing cell |
no (hard binning) |
exact discrete total |
no |
|
source/target cell intersections |
yes, by overlap area |
exact integral |
no |
|
observation operator (inverse problem) |
implicit, through reconstruction |
global constraint |
yes |
Use ConservativeResampler for fast aggregation of scattered samples when
each sample is small compared to a HEALPix cell. Use
OverlapConservativeResampler when source cells are comparable to or
larger than the target cells and their content must be split
geometrically — the classical flux-remapping situation. Use the
constrained PSFResampler when you want to reconstruct a latent field
through an instrument response while imposing a global total.
The difference is easiest to see on a constant field: a constant remapped by overlap areas stays constant everywhere, whereas hard binning gives each target cell the sum of whatever samples happened to fall inside it.
Usage#
The source grid is described by its cell boundaries (not centres):
import numpy as np
from healpix_resample import OverlapConservativeResampler
lon_bounds = np.arange(0.0, 360.0 + 1e-9, 1.0) # 360 columns
lat_bounds = np.arange(-90.0, 90.0 + 1e-9, 1.0) # 180 rows
remap = OverlapConservativeResampler(lon_bounds, lat_bounds, level=6)
result = remap.resample(field) # field.shape == (180, 360)
result.cell_data # values on HEALPix cells
result.cell_ids # nested cell ids
The geometric weights are the expensive part and are computed once. Reuse
the same object for every variable and time step sharing that grid — the
sparse matrix is exposed as remap.weights if you need it directly.
Descending lat_bounds (the common convention for gridded climate data)
is detected and handled: pass the field in the same orientation as the
bounds you supplied.
Normalization: "destination" vs "covered"#
For target cells that are only partly covered by the source grid (a regional grid, or a masked domain), two conventions exist:
OverlapConservativeResampler(..., normalization="destination") # default
OverlapConservativeResampler(..., normalization="covered")
"destination"divides by the full HEALPix cell area, so uncovered area contributes zero. A constant fieldCreads asC × (covered fraction)on boundary cells. This is the convention that conserves the integral over the whole target grid — the equivalent of xESMFconservative."covered"divides by the actually covered area, so a constant field reads asCeverywhere it is defined. This is the equivalent of xESMFconservative_normed, and is usually what you want for an intensive physical field on a regional domain.
Both are identical wherever coverage is complete.
Intensive vs extensive fields#
remap.resample(flux, quantity="intensive") # default: W/m², K, ...
remap.resample(energy, quantity="extensive") # counts, per-cell totals
For an intensive field (a density) the result is the overlap-weighted
average over the target cell. For an extensive field (a quantity already
integrated over its source cell) the source total is split across target
cells in proportion to the overlap fraction of the source cell, so that
result.cell_data.sum() == field.sum() exactly. Getting this distinction
wrong silently changes the physics, so the parameter is explicit and has
no “guess” mode.
Accuracy and scope#
Overlap areas are computed exactly on the sphere, with no polygon densification: the computation exploits the fact that in the HEALPix equal-area projection, cells are exact squares and the images of source lat/lon rectangles are straight-edged convex quadrilaterals — once each rectangle is split at the two transition latitudes (|sin φ| = 2/3) and at the polar-quadrant meridians. The intersections are then exact convex polygon clippings, and the only error is floating-point rounding (observed: global conservation to ~10⁻¹⁴, constant-field preservation to ~10⁻¹¹). Antimeridian crossings and polar cells need no special handling.
Current scope:
rectilinear lat/lon source grids (regular or irregular), given by 1D boundary arrays;
spherical Earth model (areas in steradians; multiply by
R²);nested or ring HEALPix indexing, any level.
Curvilinear source grids and an authalic-ellipsoid variant are not
implemented yet. Note that this resampler is deliberately independent of
the KNeighborsResampler base class (it is a grid-to-grid geometric
operator, not a sample-based one), so it does not take sigma_m,
threshold, device or the other kernel parameters.