Skip to content

Commit 8486517

Browse files
authored
Worktree issue 1030 (#1059)
* Add MCDA module for spatial multi-criteria decision analysis (#1030) 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 * Add test suite for MCDA module (#1030) 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. * Add MCDA docs reference page and README feature matrix (#1030) * Add MCDA user guide notebook (#1030) 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. * Fix accuracy and performance issues in MCDA module (#1030) 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). * Add edge case tests and AHP incomplete-comparison warning (#1030) 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 * Validate inputs and add edge case tests for MCDA module (#1030) 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 * Fix degenerate inputs and add remaining edge case tests (#1030) 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)
1 parent ebd6ae1 commit 8486517

File tree

0 file changed

+0
-0
lines changed

    0 file changed

    +0
    -0
    lines changed

    0 commit comments

    Comments
     (0)