Summary
Six small fixes from the resample audit:
-
A-1: The comment in xrspatial/resample.py (lines 39-44) on the cubic overlap depth says depth 10 brings the IIR prefilter transient to "machine epsilon". The actual value is 0.268^10, about 4e-7, closer to single-precision epsilon (~1e-7) than float64 epsilon (~2e-16). The constant 10 is fine for float32 output, but the comment misrepresents it. Reword to "depth 10 brings the boundary transient to ~1e-7 (sufficient for float32 output and well under typical interpolation error)".
-
A-6: The NaN-gating threshold in _nan_aware_interp_np, _nan_aware_interp_cupy, and the dask block variants (_interp_block_np, _interp_block_cupy) uses z_wt > 0.01. With 0.01, an output pixel can be marked valid even when only a tiny fraction of kernel weight came from valid input pixels (one cubic sidelobe can leak about 5% from a single neighbor). The standard choice for kernel-weighted nan-aware resampling is > 0.5, meaning more than half of the sampling kernel weight came from valid pixels. Switch all four sites and add a comment.
-
T-3: Test that a raster with descending y coordinates (e.g. y=[10, 9, ..., 3]) resamples to descending y output with correct cell-centered values and no vertical flip.
-
T-6: Test that np.inf and -np.inf either propagate or get treated as NaN. Lock in whichever the current code does.
-
T-7: Test that the 3D-rejection error message mentions "must be 2D".
-
T-9: Test that the same call produces bit-identical output across two invocations for bilinear, cubic, and average.
Why
The doc fix and the tighter NaN gate are cheap to land. The tests cover behavior that current coverage misses: orientation, infs, and run-to-run determinism.
Notes
No public API changes. The threshold bump is the only behavior change: pixels in the [0.01, 0.5] weight-fraction band that previously came back as a fractional value will now be NaN. That is the intended, more conservative behavior.
Summary
Six small fixes from the resample audit:
A-1: The comment in
xrspatial/resample.py(lines 39-44) on the cubic overlap depth says depth 10 brings the IIR prefilter transient to "machine epsilon". The actual value is0.268^10, about4e-7, closer to single-precision epsilon (~1e-7) than float64 epsilon (~2e-16). The constant 10 is fine for float32 output, but the comment misrepresents it. Reword to "depth 10 brings the boundary transient to ~1e-7 (sufficient for float32 output and well under typical interpolation error)".A-6: The NaN-gating threshold in
_nan_aware_interp_np,_nan_aware_interp_cupy, and the dask block variants (_interp_block_np,_interp_block_cupy) usesz_wt > 0.01. With 0.01, an output pixel can be marked valid even when only a tiny fraction of kernel weight came from valid input pixels (one cubic sidelobe can leak about 5% from a single neighbor). The standard choice for kernel-weighted nan-aware resampling is> 0.5, meaning more than half of the sampling kernel weight came from valid pixels. Switch all four sites and add a comment.T-3: Test that a raster with descending y coordinates (e.g.
y=[10, 9, ..., 3]) resamples to descending y output with correct cell-centered values and no vertical flip.T-6: Test that
np.infand-np.infeither propagate or get treated as NaN. Lock in whichever the current code does.T-7: Test that the 3D-rejection error message mentions "must be 2D".
T-9: Test that the same call produces bit-identical output across two invocations for bilinear, cubic, and average.
Why
The doc fix and the tighter NaN gate are cheap to land. The tests cover behavior that current coverage misses: orientation, infs, and run-to-run determinism.
Notes
No public API changes. The threshold bump is the only behavior change: pixels in the [0.01, 0.5] weight-fraction band that previously came back as a fractional value will now be NaN. That is the intended, more conservative behavior.