Skip to content

interpolate: stop leaking template nodata sentinel onto float64 outputs#2

Open
jam-lock wants to merge 1 commit into
mainfrom
deep-sweep-metadata-interpolate-2026-05-21-01
Open

interpolate: stop leaking template nodata sentinel onto float64 outputs#2
jam-lock wants to merge 1 commit into
mainfrom
deep-sweep-metadata-interpolate-2026-05-21-01

Conversation

@jam-lock
Copy link
Copy Markdown
Owner

Summary

  • idw(), kriging(), and spline() previously copied template.attrs wholesale onto the float64 interpolation output, leaking the template's nodata sentinel (e.g. -9999 for an integer DEM template) onto a result whose actual no-data value is NaN (kriging/spline/idw-default) or the user's explicit fill_value (idw).
  • New _validation._build_output_attrs helper strips inherited nodata keys, preserves spatial-reference attrs (crs, res, transform, extra coords), and re-emits the (nodata, _FillValue, nodatavals) triplet only when the actual fill value is non-NaN. Same pattern as the rasterize() fix in rasterize: drop attrs, recompute coords, and don't emit _FillValue when like= is given xarray-contrib/xarray-spatial#2018.
  • Kriging's singular-matrix fallback now returns a properly-named {name}_variance DataArray with attrs that match the prediction's.

Test plan

  • New TestMetadataPropagation covers spatial-ref preservation, nodata-key stripping for default NaN fill, triplet emission for explicit non-NaN fill, dims/coords preservation, no-mutation of caller's template.attrs, dask-vs-numpy attrs parity, and kriging variance vs prediction attrs parity (12 tests).
  • pytest xrspatial/tests/test_interpolation.py -- 48 passed, 5 skipped (CuPy).
  • pytest xrspatial/tests/test_interpolation.py xrspatial/tests/test_rasterize.py -- 209 passed, 52 skipped, no regressions.
  • CuPy / dask+cupy paths: not executed on this host (CUDA unavailable). They share the centralised public-API attrs construction in each xr.DataArray(...) call, so the fix applies uniformly. Re-validate on a GPU host before merge if desired.

Found by /deep-sweep metadata sweep.

idw(), kriging(), and spline() copied `template.attrs` wholesale onto
the float64 interpolation surface, leaking the template's nodata
sentinel (e.g. `-9999` for an integer DEM template) onto a result whose
actual no-data value is NaN (kriging, spline, and idw default) or the
user's explicit `fill_value` (idw). Downstream code that read
`result.attrs['nodatavals']` or `_FillValue` for masking saw a stale
sentinel that no longer matched the data.

Add `_validation._build_output_attrs` which strips inherited nodata
keys, preserves spatial-reference attrs (`crs`, `res`, `transform`,
extra coords), and re-emits the (`nodata`, `_FillValue`, `nodatavals`)
triplet only when the actual fill value is non-NaN -- same pattern as
the rasterize() fix in xarray-contrib#2018. Also tighten kriging's singular-matrix
fallback to return a properly-named `{name}_variance` DataArray with
attrs equal to the prediction's.

12 new tests in `TestMetadataPropagation` cover spatial-ref
preservation, nodata-key stripping for the default NaN fill, triplet
emission for explicit non-NaN fill, dims/coords preservation, the
no-mutation contract on the caller's template.attrs, dask-vs-numpy
attrs parity, and kriging variance/prediction attrs parity. CuPy and
dask+cupy paths share the centralised public-API attrs construction so
the fix applies uniformly; they were not executed here because CUDA is
unavailable on this host.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant