Skip to content

zonal: rename crop(zones_ids=) -> crop(zone_ids=) with deprecation shim (#2521)#2527

Merged
brendancol merged 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-api-consistency-zonal-2026-05-27
May 27, 2026
Merged

zonal: rename crop(zones_ids=) -> crop(zone_ids=) with deprecation shim (#2521)#2527
brendancol merged 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-api-consistency-zonal-2026-05-27

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

  • xrspatial.zonal.crop() accepts the canonical zone_ids kwarg, matching stats() and crosstab().
  • The legacy zones_ids kwarg (extra s) is kept as a deprecated alias; passing it now emits DeprecationWarning.
  • Passing both kwargs raises TypeError; passing neither also raises TypeError.
  • Internal call sites and tests migrated to zone_ids; regression tests cover both paths plus the error cases.

Closes #2521.

Why

The api-consistency sweep against zonal (2026-05-27) flagged this as a HIGH Cat 1 finding: same concept named differently across sibling public functions inside one module. A user who learned zone_ids from stats() or crosstab() would hit TypeError: crop() got an unexpected keyword argument 'zone_ids' and vice versa.

Test Plan

  • pytest xrspatial/tests/test_zonal.py — all 130 tests pass
  • pytest xrspatial/tests/test_dask_cupy_gaps.py -k crop — 4 pass
  • pytest xrspatial/tests/test_validation.py -k crop — 1 pass
  • New tests cover: canonical path, legacy path emits warning, canonical path emits no warning, both raises, neither raises

…im (xarray-contrib#2521)

stats() and crosstab() use zone_ids, but crop() historically used
zones_ids (extra 's'). Switching between sibling zonal functions raised
TypeError on the typo. Fix accepts both kwargs, emits DeprecationWarning
on the legacy zones_ids, raises if both are passed, and raises if
neither is supplied. Internal call sites migrated to the canonical
zone_ids; new regression tests cover both paths plus error cases.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 27, 2026
@brendancol brendancol merged commit a9620ba into xarray-contrib:main May 27, 2026
9 checks passed
brendancol added a commit that referenced this pull request May 28, 2026
…m/crop/apply (#2530)

* test_zonal: close HIGH backend-coverage gaps for crosstab / regions / trim / crop / apply

Adds test_zonal_backend_coverage_2026_05_27.py (32 tests, all passing on a
CUDA host) covering test-coverage gaps surfaced by the deep-sweep
test-coverage pass on the zonal module.

Cat 1 HIGH backend coverage:
- crosstab cupy + dask+cupy parity vs numpy (_crosstab_cupy /
  _crosstab_dask_cupy were registered in ArrayTypeFunctionMapping but
  never invoked by any test).
- regions cupy + dask+cupy parity vs numpy (cupyx.scipy.ndimage label
  branch + dask+cupy compute-then-label branch).
- trim dask+numpy + cupy + dask+cupy parity (the cupy data.get() path
  and the dask _trim_bounds_dask isnan branch were untested).
- crop dask+numpy + cupy + dask+cupy parity (matching _crop_bounds_dask
  branch).
- apply 3D cupy + dask+cupy parity (per-layer kernel launch over the
  third axis; existing 3D apply tests covered numpy + dask+numpy only).

Cat 3 MEDIUM geometric edges:
- 1x1 single-pixel raster on trim / crop.
- 1xN and Nx1 strips on regions.

Cat 4 LOW parameter coverage:
- regions(neighborhood=6) -> ValueError pin.
- suggest_zonal_canvas(crs='Geographic') aspect-ratio pin and
  invalid-crs KeyError.
- crosstab cupy with zone_ids / cat_ids subset.
- crosstab cupy with agg='percentage'.

Cat 5 MEDIUM metadata propagation:
- regions preserves coords + attrs (numpy + dask+numpy).
- trim / crop set name and preserve attrs.

Also pins the documented numpy-vs-dask trim asymmetry on the NaN sentinel:
numpy _trim uses equality (never matches NaN), dask _trim_bounds_dask has
a dedicated isnan branch.  Mutation against cupy.asnumpy() in
_crosstab_cupy flipped test_crosstab_cupy_matches_numpy red, confirming
the test detects regressions.  Source untouched.

* test_zonal_backend_coverage: apply review-pr suggestions

- Lift duplicated _canonical_labels helper to module scope so a fix
  lands once instead of twice (was duplicated in
  test_regions_cupy_matches_numpy and test_regions_dask_cupy_matches_numpy).
- Import cuda_and_cupy_available and dask_array_available from
  general_checks instead of redeclaring locally.  dask_required is now
  a single-line alias of the shared decorator.
- Drop unused imports (zonal.stats, has_cuda_and_cupy) flagged by flake8.
- Tighten test_suggest_zonal_canvas_geographic_crs docstring (removed
  an unedited mid-sentence "wait..." correction).

zones_ids=... parameter rename to zone_ids=... is intentionally
deferred to rebase: this branch is behind origin/main, the rename +
deprecation shim only exist on main, so renaming here would break the
tests on this branch.

32 tests still pass on the CUDA host.

* test_zonal_backend_coverage: use canonical crop(zone_ids=) after #2527
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.crop uses zones_ids; siblings stats/crosstab use zone_ids

1 participant