xrspatial.dasymetric.pycnophylactic#
- xrspatial.dasymetric.pycnophylactic(zones: DataArray, values: dict | Series, max_iterations: int = 100, convergence: float = 1e-05, nodata_zone: int | None = None, name: str = 'pycnophylactic') DataArray[source]#
Tobler’s pycnophylactic interpolation preserving zone totals.
Produces a smooth surface by iteratively applying Laplacian smoothing and then rescaling each zone so its pixel sum matches the original value. Unlike
disaggregate(), no ancillary weight raster is needed – smoothness alone drives the redistribution.- Parameters:
zones (xr.DataArray) – 2-D integer raster identifying zone membership for each pixel.
values (dict or pd.Series) – Mapping of
zone_id -> valueto redistribute.max_iterations (int, default 100) – Maximum number of smoothing-correction iterations.
convergence (float, default 1e-5) – Stop when the largest per-pixel change is below this threshold.
nodata_zone (int or None, default None) – Zone ID to treat as no-data (output NaN).
name (str, default
'pycnophylactic') – Name for the output DataArray.
- Returns:
Float raster with the same shape, coordinates, and attributes as zones. Zone totals are preserved (pycnophylactic property).
- Return type:
xr.DataArray
Notes
Currently supports numpy and cupy (via CPU fallback) backends. Dask arrays raise
NotImplementedErrorbecause the algorithm is inherently iterative and requires global zone sums each iteration.References
Tobler, W. R. (1979). “Smooth Pycnophylactic Interpolation for Geographical Regions”. Journal of the American Statistical Association, 74(367), 519-530.
Examples
>>> import numpy as np, xarray as xr >>> from xrspatial.dasymetric import pycnophylactic >>> zones = xr.DataArray(np.array([[1, 1], [2, 2]]), dims=['y', 'x']) >>> result = pycnophylactic(zones, {1: 100, 2: 50}) >>> float(np.nansum(result.values[:1, :])) # zone 1 sum 100.0