Skip to content

Worktree issue 1030#1059

Merged
brendancol merged 8 commits intomasterfrom
worktree-issue-1030
Mar 23, 2026
Merged

Worktree issue 1030#1059
brendancol merged 8 commits intomasterfrom
worktree-issue-1030

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Fixes #

Proposed Changes

New xrspatial.mcda subpackage with five modules:
- standardize: value functions (linear, sigmoidal, gaussian, triangular, piecewise, categorical)
- weights: AHP eigenvector method with consistency ratio, rank-order weighting (ROC, RS, RR)
- combine: WLC, WPM, OWA, fuzzy overlay, boolean overlay
- constrain: exclusion mask application
- sensitivity: one-at-a-time perturbation and Monte Carlo CV analysis
69 tests covering standardize (all 6 methods + dask), AHP and rank
weights, WLC/WPM/OWA/fuzzy/boolean combination, constraints,
sensitivity analysis, and an end-to-end suitability workflow.
Also fix nanmin/nanmax in linear standardize when bounds are not given.
Covers the full workflow: synthetic terrain criteria, all six
standardization methods, AHP and rank-order weights, WLC/WPM/OWA/fuzzy
combination, constraint masking, and sensitivity analysis with
side-by-side method comparison plots.
Correctness:
- Fix triangular degenerate cases (peak==low, peak==high, all equal)
  returning 0 instead of the correct one-sided triangle shape
- Fix _get_xp returning cupy for dask+cupy arrays, which would pass
  dask arrays to cupy ops and fail or materialize full arrays
- Fix dask+cupy map_blocks closures in categorical/piecewise using
  np.asarray to handle cupy chunks
- Clamp sigmoidal exponent to [-500, 500] to prevent overflow warnings
- Suppress RuntimeWarning from nanmin/nanmax on all-NaN input
- Remove unused baseline variable in _oat sensitivity
- Remove unused stacked.copy() in OWA

Performance:
- Monte Carlo sensitivity: compute dask criteria eagerly before the
  loop to prevent graph explosion (1000 iterations was creating
  35,000+ chained graph tasks with no parallelism)
- Fuse two separate dask.compute calls for nanmin/nanmax into one
- Replace xr.where(a < b, a, b) with np.minimum in fuzzy and/or

Tests: add 10 edge case tests (degenerate triangles, sigmoid overflow,
all-NaN input, NaN propagation in WLC, OWA exact equality, dask MC).
Warn when AHP receives fewer than n(n-1)/2 pairwise comparisons,
since missing pairs silently default to equal importance.

28 new tests covering:
- Single-pixel rasters through all standardize methods and combine
- NaN propagation through WLC, WPM, OWA, and all 5 fuzzy operators
- Piecewise extrapolation outside breakpoint range
- Categorical float precision (exact match only) and integer data
- AHP incomplete comparison warning and no-warn for complete input
- Mismatched coords producing NaN outside overlap region
- Dask chunk alignment for standardize, WLC, fuzzy, and OAT sensitivity
- WPM with all-ones and all-zeros
- Constrain with empty exclude list and full exclusion
Input validation:
- Raise on inverted bounds in linear standardize (lo > hi)
- Raise on duplicate piecewise breakpoints
- Raise on AHP self-comparisons, zero, and negative values
- Raise when weights dict has keys not in criteria Dataset
- Boolean overlay casts float input to bool instead of TypeError

25 new test classes / cases covering:
- Inverted bounds, duplicate breakpoints, AHP validation
- Extra weight keys, boolean overlay with float data
- Inf values treated as NaN across all standardize methods
- Sensitivity weight clamping to [0, 1] boundary
- Monte Carlo reproducibility (same seed = same output)
- Gaussian with very small std (delta function behavior)
- OWA risk attitude ordering (conservative <= optimistic)
- Rank weights with 20 criteria (sum, monotonicity)
- Constant surface with no bounds returns 0.5
- Overlapping constraint masks
Fixes:
- Single-criterion sensitivity: _perturb_weights returned weights
  summing to <1 when no other criteria exist to absorb the remainder.
  Now returns unmodified weights (perturbation is a no-op).
- Duplicate criteria names in AHP and rank_weights: silently corrupted
  results by overwriting index mapping. Now raises ValueError.

16 new tests covering:
- Single-criterion Dataset through WLC, WPM, OWA, all fuzzy operators
- Boolean overlay NaN gotcha (bool(NaN)=True documented)
- Sensitivity with single criterion (OAT and MC both zero)
- Sensitivity with WPM combine method (OAT and MC)
- AHP with 16 criteria (>15, _RI table fallback)
- Duplicate criteria names in AHP and rank_weights
- Constrain with integer mask
- Monte Carlo with n_samples=1 (zero CV)
- 3D DataArray input (band, y, x)
@github-actions github-actions bot added the performance PR touches performance-sensitive code label Mar 23, 2026
@brendancol brendancol merged commit 8486517 into master Mar 23, 2026
10 of 11 checks passed
@brendancol brendancol deleted the worktree-issue-1030 branch March 25, 2026 14:18
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.

1 participant