Description
_validate_weights in xrspatial.mcda.combine (and the owa() order-weights check) only validates that weights sum to about 1.0:
total = sum(weights.values())
if abs(total - 1.0) > 0.01:
raise ValueError(...)
If any weight is NaN, the sum is NaN, abs(NaN - 1.0) > 0.01 is False, and the check passes. wlc(), wpm(), and owa() then propagate the NaN to every pixel and return an all-NaN raster, no exception raised.
ahp_weights in xrspatial.mcda.weights has the same problem. Its guard is if val <= 0:, which NaN slips past. The matrix fills with NaN, the eigenvector solve produces NaN, and the function returns NaN weights.
Cat 3 (NaN as logic error) finding from the mcda security sweep. HIGH severity because the output looks structurally valid: same shape, no warning, no exception. Anything downstream (constrain, plotting, export) will treat it as real data.
Reproduction
import xarray as xr
import numpy as np
from xrspatial.mcda.combine import wlc
data = xr.Dataset({
'a': xr.DataArray(np.array([[0.5, 0.5], [0.5, 0.5]])),
'b': xr.DataArray(np.array([[0.5, 0.5], [0.5, 0.5]])),
})
result = wlc(data, {'a': 0.5, 'b': float('nan')})
print(result.values)
# Expected: ValueError naming the offending criterion
# Actual: [[nan nan] [nan nan]]
Expected behaviour
_validate_weights and the owa() order-weights check should raise ValueError and name the offending criteria (or positions) when a weight is NaN or infinite. ahp_weights should reject NaN/Inf comparison values the same way it rejects non-positive ones.
Affected files
xrspatial/mcda/combine.py -- _validate_weights (~lines 22-39), owa order-weights check (~lines 154-158)
xrspatial/mcda/weights.py -- ahp_weights value guard (~line 94)
Fix sketch
Sweep the weight dict once, raise ValueError on any NaN/Inf, then run the sum-to-1 check. Apply the same sweep to order_weights in owa. In ahp_weights, extend the val <= 0 check to also reject np.isnan(val) and np.isinf(val).
One fix per PR, per the existing security-sweep convention.
Description
_validate_weightsinxrspatial.mcda.combine(and theowa()order-weights check) only validates that weights sum to about 1.0:If any weight is NaN, the sum is NaN,
abs(NaN - 1.0) > 0.01is False, and the check passes.wlc(),wpm(), andowa()then propagate the NaN to every pixel and return an all-NaN raster, no exception raised.ahp_weightsinxrspatial.mcda.weightshas the same problem. Its guard isif val <= 0:, which NaN slips past. The matrix fills with NaN, the eigenvector solve produces NaN, and the function returns NaN weights.Cat 3 (NaN as logic error) finding from the mcda security sweep. HIGH severity because the output looks structurally valid: same shape, no warning, no exception. Anything downstream (
constrain, plotting, export) will treat it as real data.Reproduction
Expected behaviour
_validate_weightsand theowa()order-weights check should raiseValueErrorand name the offending criteria (or positions) when a weight is NaN or infinite.ahp_weightsshould reject NaN/Inf comparison values the same way it rejects non-positive ones.Affected files
xrspatial/mcda/combine.py--_validate_weights(~lines 22-39),owaorder-weights check (~lines 154-158)xrspatial/mcda/weights.py--ahp_weightsvalue guard (~line 94)Fix sketch
Sweep the weight dict once, raise
ValueErroron any NaN/Inf, then run the sum-to-1 check. Apply the same sweep toorder_weightsinowa. Inahp_weights, extend theval <= 0check to also rejectnp.isnan(val)andnp.isinf(val).One fix per PR, per the existing security-sweep convention.