Skip to content

Document num_sample=None in natural_breaks docstring#3505

Merged
brendancol merged 2 commits into
mainfrom
deep-sweep-api-consistency-classify-2026-06-25-01
Jun 26, 2026
Merged

Document num_sample=None in natural_breaks docstring#3505
brendancol merged 2 commits into
mainfrom
deep-sweep-api-consistency-classify-2026-06-25-01

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

Closes #3501.

natural_breaks already accepts num_sample=None (use all data) the same
way quantile, maximum_breaks, and percentiles do, but its docstring
only described num_sample as int and never mentioned None. This brings
the wording in line with the other three classifiers.

Docstring only. No signature or behavior change.

Verified natural_breaks(agg, k=5, num_sample=None) on both the numpy and
cupy backends. pytest xrspatial/tests/test_classify.py -k natural_breaks
passes (22 passed).

natural_breaks accepts num_sample=None (use all data) like the other
classifiers, but its docstring only described it as int. Bring the
parameter wording in line with quantile/maximum_breaks/percentiles.
@brendancol

Copy link
Copy Markdown
Contributor Author

Review: document num_sample=None in natural_breaks

Read the full natural_breaks / _compute_natural_break_bins / _run_dask_natural_break paths, not just the diff. Documenting that None is accepted is the right call and matches quantile, maximum_breaks, and percentiles. One wording issue.

Suggestion

xrspatial/classify.py:851-852 -- the new parenthetical "(safe for numpy/cupy, automatically capped for dask)" reads like it was copied from quantile/percentiles, where None just runs an exact percentile over the finite values. That clause doesn't describe natural_breaks:

  • On numpy/cupy, None makes _compute_natural_break_bins fit Jenks on the whole array. That's the O(n^2) path this same docstring warns about two lines up ("When n is large, we should fit the model on a small sub-sample").
  • _compute_natural_break_bins (line 684) raises MemoryError when the two Jenks matrices would exceed half of available RAM. So None on a large raster is the opposite of "safe" -- it's the case most likely to blow up.
  • For dask it isn't capped to a small sample either. _run_dask_natural_break sets num_sample = num_data and fits Jenks on all the data via indexed access.

Suggest rewording so it says None fits on all data, and that this is the expensive O(n^2) case guarded by a memory check, instead of calling it "safe".

What looks good

  • Documents the None option, in line with the other three samplers.
  • Docstring-only, non-breaking. num_sample=None verified on numpy and cupy.

Checklist

  • No code change; behavior unchanged
  • Docstring accurately describes None for the Jenks case (see suggestion)
  • API consistency improved
  • No tests needed (docstring only)

The first pass copied the percentile classifiers' '(safe for numpy/cupy,
automatically capped for dask)' wording. For natural_breaks None fits Jenks
on all data, which is the O(n^2) case the docstring warns about and which
raises MemoryError past the half-RAM guard, so 'safe' was wrong. Describe
the actual cost instead. Addresses review on #3505.
@brendancol brendancol merged commit aa65a77 into main Jun 26, 2026
10 checks passed
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.

natural_breaks num_sample docstring omits None, unlike the other classifiers

1 participant