Skip to content

zonal: make apply() output .name deterministic across backends#2622

Merged
brendancol merged 2 commits into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-zonal-2026-05-29
May 29, 2026
Merged

zonal: make apply() output .name deterministic across backends#2622
brendancol merged 2 commits into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-zonal-2026-05-29

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Closes #2611

What changed

  • zonal.apply() now sets a deterministic .name on its output and accepts a name parameter (default None), matching regions, hypsometric_integral, trim, and crop.
  • The name is assigned after the DataArray is built. xr.DataArray(dask_array, name=None) otherwise inherits the dask graph's internal task name, which differs from the numpy/cupy backends and changes between runs.

Backend coverage

numpy, cupy, dask+numpy, dask+cupy. The new test runs on all four; before this change the two dask backends returned a task-hash name while numpy/cupy returned None.

Test plan

  • test_apply_name_consistent_across_backends (new): default name is None and an explicit name= is honored on every backend
  • Full zonal suite: 213 passed
  • flake8 clean on xrspatial/zonal.py and the added test lines

@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 29, 2026
Copy link
Copy Markdown
Contributor Author

@brendancol brendancol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: zonal: make apply() output .name deterministic across backends

Blockers (must fix before merge)

None.

Suggestions (should fix, not blocking)

None.

Nits (optional improvements)

  • The new name parameter goes at the end of the signature, after rasterize_kw. That keeps existing positional calls working and matches how regions/trim/crop expose name, so it is fine as-is. Noting the placement was a deliberate compatibility choice.

What looks good

  • Root cause is correct: xr.DataArray(dask_array, name=None) inherits the dask graph's task name, so assigning .name after construction is the right fix. Setting it at construction time does not override the dask name.
  • The test runs on all four backends and checks both the default (None) and an explicit name, which is exactly the inconsistency being fixed.
  • Attrs, dims, and coords handling is untouched; only .name changed.
  • The code comment explains why the assignment happens after construction, which is the non-obvious part.

Checklist

  • Algorithm matches reference/paper: n/a (metadata fix)
  • All implemented backends produce consistent results: yes, verified by the new parametrized test
  • NaN handling is correct: unchanged by this PR
  • Edge cases covered by tests: name default and explicit name both tested
  • Dask chunk boundaries handled correctly: unchanged
  • No premature materialization or unnecessary copies: confirmed, no compute added
  • Benchmark exists or is not needed: not needed
  • README feature matrix updated: not applicable, no new function
  • Docstrings present and accurate: the new name parameter is documented

…y-contrib#2611)

apply() never set the result name, so numpy/cupy returned None while the
dask backends inherited an internal dask task name (also non-deterministic
between runs). Add a name parameter (default None) and assign it after
constructing the DataArray so the name is identical on all four backends.
@brendancol brendancol force-pushed the deep-sweep-metadata-zonal-2026-05-29 branch from 263caf1 to f2dee0e Compare May 29, 2026 16:01
@brendancol brendancol merged commit 3e36334 into xarray-contrib:main May 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zonal.apply() output .name is inconsistent across backends

1 participant