File size: 2,141 Bytes
ae4c60c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | """Tests for cross-indicator compound signal detection."""
import numpy as np
import pytest
def test_compute_overlap_pct():
from app.analysis.compound import compute_overlap_pct
a = np.array([[True, True, False], [False, False, True]], dtype=bool)
b = np.array([[True, False, False], [False, False, True]], dtype=bool)
pct = compute_overlap_pct(a, b)
assert pct > 0
def test_detect_land_conversion():
from app.analysis.compound import detect_compound_signals
ndvi_z = np.full((10, 10), -2.5, dtype=np.float32)
buildup_z = np.full((10, 10), 2.5, dtype=np.float32)
water_z = np.zeros((10, 10), dtype=np.float32)
sar_z = np.zeros((10, 10), dtype=np.float32)
signals = detect_compound_signals(
zscore_rasters={"ndvi": ndvi_z, "water": water_z, "sar": sar_z, "buildup": buildup_z},
pixel_area_ha=0.04, threshold=2.0,
)
land_conv = [s for s in signals if s.name == "land_conversion"]
assert len(land_conv) == 1
assert land_conv[0].triggered is True
assert "ndvi" in land_conv[0].indicators
assert "buildup" in land_conv[0].indicators
def test_no_signals_when_all_normal():
from app.analysis.compound import detect_compound_signals
normal = np.zeros((10, 10), dtype=np.float32)
signals = detect_compound_signals(
zscore_rasters={"ndvi": normal, "water": normal, "sar": normal, "buildup": normal},
pixel_area_ha=0.04, threshold=2.0,
)
triggered = [s for s in signals if s.triggered]
assert len(triggered) == 0
def test_flood_signal():
from app.analysis.compound import detect_compound_signals
sar_z = np.full((10, 10), -2.5, dtype=np.float32)
water_z = np.full((10, 10), 2.5, dtype=np.float32)
ndvi_z = np.zeros((10, 10), dtype=np.float32)
buildup_z = np.zeros((10, 10), dtype=np.float32)
signals = detect_compound_signals(
zscore_rasters={"ndvi": ndvi_z, "water": water_z, "sar": sar_z, "buildup": buildup_z},
pixel_area_ha=0.04, threshold=2.0,
)
flood = [s for s in signals if s.name == "flood_event"]
assert len(flood) == 1
assert flood[0].triggered is True
|