Skip to content

Fix disaggregate(limiting_variable) silently losing a zone's value (#3403)#3414

Open
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-accuracy-dasymetric-2026-06-20
Open

Fix disaggregate(limiting_variable) silently losing a zone's value (#3403)#3414
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-accuracy-dasymetric-2026-06-20

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

Fixes #3403.

disaggregate(method='limiting_variable') dropped a zone's whole value when the zone had no pixel that could hold it. If every pixel in a zone fell in a cap-0 class (all zero-weight under the default caps), the leftover loop found no overflow pixels and threw the remaining mass away, leaving those pixels at their initialised 0. The value disappeared with no error, even though the docstring promises zone totals are preserved.

The weighted method already handles this by returning NaN. This change makes limiting_variable do the same: when no pixel can absorb the leftover, the zone's result is NaN instead of silent zeros.

zones = xr.DataArray(np.array([[1, 1], [1, 1]], dtype=np.float64), dims=['y', 'x'])
weight = xr.DataArray(np.zeros((2, 2)), dims=['y', 'x'])

# before: [0. 0. 0. 0.], nansum 0.0  (500 lost)
# after:  [nan nan nan nan]          (matches weighted)
disaggregate(zones, {1: 500.0}, weight, method='limiting_variable')

Added test_uninhabitable_zone_is_nan_not_zero, which fails on the old code and passes now. The full dasymetric suite stays green (62 tests, including the cupy and dask+cupy cross-backend checks on this GPU host). The cupy and dask backends route through the numpy core, so the fix reaches all four backends.

Found by the accuracy sweep on the dasymetric module.

…array-contrib#3403)

When a zone has no pixel that can absorb its value (every pixel falls in a
cap-0 class, e.g. all zero-weight under the default caps), the leftover loop
found no overflow pixels and discarded the remaining mass, leaving the zone's
pixels at their initialised 0. The zone's whole value vanished with no error,
breaking the documented conservation property.

Match the weighted method: when no pixel can absorb the leftover, set the
zone result to NaN instead of silently zeroing it.

Also record the accuracy-sweep state for the dasymetric module.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Jun 20, 2026
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.

disaggregate(limiting_variable) silently loses a zone's value when no habitable pixels exist

1 participant