| """Tests for pixel-level change detection.""" |
| import numpy as np |
| import pytest |
|
|
|
|
| def test_compute_zscore_raster(): |
| from app.analysis.change import compute_zscore_raster |
| current = np.array([[0.5, 0.3], [0.7, 0.4]], dtype=np.float32) |
| baseline_mean = np.array([[0.6, 0.6], [0.6, 0.6]], dtype=np.float32) |
| baseline_std = np.array([[0.05, 0.05], [0.05, 0.05]], dtype=np.float32) |
| z = compute_zscore_raster(current, baseline_mean, baseline_std, min_std=0.02) |
| expected = np.array([[-2.0, -6.0], [2.0, -4.0]], dtype=np.float32) |
| np.testing.assert_array_almost_equal(z, expected, decimal=1) |
|
|
|
|
| def test_compute_zscore_raster_clamps_std(): |
| from app.analysis.change import compute_zscore_raster |
| current = np.array([[0.5]], dtype=np.float32) |
| baseline_mean = np.array([[0.5]], dtype=np.float32) |
| baseline_std = np.array([[0.001]], dtype=np.float32) |
| z = compute_zscore_raster(current, baseline_mean, baseline_std, min_std=0.02) |
| assert z[0, 0] == pytest.approx(0.0, abs=0.01) |
|
|
|
|
| def test_detect_hotspots(): |
| from app.analysis.change import detect_hotspots |
| z = np.array([[-3.0, 0.5, 2.5], [1.0, -0.3, -2.1]], dtype=np.float32) |
| mask, pct = detect_hotspots(z, threshold=2.0) |
| assert mask[0, 0] == True |
| assert mask[0, 1] == False |
| assert mask[0, 2] == True |
| assert mask[1, 2] == True |
| assert pct == pytest.approx(50.0, abs=0.1) |
|
|
|
|
| def test_cluster_hotspots(): |
| from app.analysis.change import cluster_hotspots |
| mask = np.array([ |
| [True, True, False, False, False], |
| [True, True, False, False, False], |
| [False, False, False, True, True], |
| [False, False, False, True, True], |
| ], dtype=bool) |
| z = np.array([ |
| [-2.5, -2.3, 0.0, 0.0, 0.0], |
| [-2.1, -2.0, 0.0, 0.0, 0.0], |
| [0.0, 0.0, 0.0, 2.5, 2.3], |
| [0.0, 0.0, 0.0, 2.1, 2.8], |
| ], dtype=np.float32) |
| clusters = cluster_hotspots(mask, z, pixel_area_ha=1.0, min_pixels=2) |
| assert len(clusters) == 2 |
| assert clusters[0]["area_ha"] == 4.0 |
| assert clusters[1]["area_ha"] == 4.0 |
|
|
|
|
| def test_cluster_hotspots_filters_small(): |
| from app.analysis.change import cluster_hotspots |
| mask = np.array([[True, False, False], [False, False, True]], dtype=bool) |
| z = np.full((2, 3), -2.5, dtype=np.float32) |
| clusters = cluster_hotspots(mask, z, pixel_area_ha=1.0, min_pixels=2) |
| assert len(clusters) == 0 |
|
|