Aperture / tests /test_change.py
KSvend
feat: add seasonal baseline computation module
03db879
"""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