focal: align signatures across mean/apply/focal_stats/hotspots (#2689)#2699
Merged
Conversation
- apply/hotspots: rename first arg raster -> agg with a deprecation shim that still accepts raster= and warns - focal_stats/hotspots: add name= param; set output DataArray name consistently across numpy/cupy/dask backends (numpy focal_stats no longer leaks the internal 'focal_apply' name) - mean: document the excludes parameter - mean/focal_stats: replace mutable list defaults with None sentinels - tests: cover deprecation warnings, name= parity across backends, and default-value behaviour
brendancol
commented
May 29, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
PR Review: focal: align signatures across mean/apply/focal_stats/hotspots (#2689)
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
- focal.py:
focal_statsandhotspotsgained aname=parameter. The
docs/source/reference/focal.rstautosummary pulls params from the
docstrings, so no rst change is needed here. Flagging it so the docs side
doesn't get missed.
Nits (optional improvements)
- focal.py
_resolve_raster_alias:stacklevel=3is right for the current
depth (user -> public func -> helper), but it's a magic number. If the call
chain changes later, the warning points at the wrong frame. A one-line
comment noting the assumed depth would save a future debugging session.
What looks good
- The
raster=shim is keyword-only (*, raster=None), so positional callers
are untouched and only the deprecated keyword warns. It warns once even on
the 3D per-band recursion, since the recursive calls passaggpositionally. - Passing both
aggandrasterraisesTypeErrorinstead of silently
picking one. name=is set the same way on numpy, cupy, dask+numpy, and dask+cupy. The
old behaviour wherefocal_statsleaked the internalfocal_applyname on
numpy and returnedNoneon cupy is gone.- Mutable list defaults are now
Nonesentinels, and a test checks that an
explicitexcludesdoesn't bleed into the next default call. - Tests cover the deprecation warnings, the both-args
TypeError, name parity
across backends including the GPU variants, and the default-value behaviour.
Checklist
- Algorithm matches reference/paper (no algorithm change; signature/docs only)
- All implemented backends produce consistent results (name= verified on all four)
- NaN handling is correct (unchanged)
- Edge cases are covered by tests (3D path, both-args conflict, default isolation)
- Dask chunk boundaries handled correctly (unchanged; name= is a lazy metadata op)
- No premature materialization or unnecessary copies (result.name= is metadata-only)
- Benchmark exists or is not needed (not needed; no perf-relevant change)
- README feature matrix updated (not applicable; no new function)
- Docstrings present and accurate (excludes documented; name documented; raster deprecation noted)
brendancol
commented
May 29, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
Follow-up review (after 062160a)
Addressed the one nit from the previous pass: _resolve_raster_alias now has
a comment explaining the stacklevel=3 assumption (caller -> public func ->
helper).
The earlier Suggestion about docs was informational; the autosummary in
focal.rst picks up the new name= params from the docstrings, so no rst
change is needed.
No remaining blockers, suggestions, or open nits. Re-ran the focal API tests
(10 passed) and flake8 is clean on the changed lines.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2689.
Makes the four public functions in
xrspatial/focal.pyline up on aconsistent signature.
applyandhotspots: first argument renamedraster->agg(matchingmean,focal_stats, and the rest of the library). A deprecation shimkeeps
raster=working as a keyword and emits aDeprecationWarning;passing both
aggandrasterraisesTypeError.focal_statsandhotspots: added aname=parameter and set thereturned DataArray name the same way across backends. Before this,
focal_statsreturned a DataArray namedfocal_applyon numpy andNoneon cupy.
mean: documented the existingexcludesparameter, which the docstringhad omitted.
meanandfocal_stats: replaced mutable list defaults withNonesentinels.
Backend coverage: the
name=and deprecation changes were verified onnumpy, cupy, dask+numpy, and dask+cupy entry points.
Test plan:
pytest xrspatial/tests/test_focal.py(124 passed, including newdeprecation/name/default tests and their GPU variants)
pytest test_validation.py test_dataset_support.py test_dask_laziness.py(111 passed)