Spaces:
Sleeping
Sleeping
Chandra-Align
feat: scientific photogrammetric workstation - preprocessing, ground metrics, visualization, export, enhanced UI
38d2728 Download tests/test_iirs_preprocessing.py from RevanShriyan/Chandra-Align: direct link, hf CLI and curl.
- Browser
- Download file 6.19 kB
-
https://huggingface.co/spaces/RevanShriyan/Chandra-Align/resolve/main/tests/test_iirs_preprocessing.py
- Command line
-
hf download hf://spaces/RevanShriyan/Chandra-Align/tests/test_iirs_preprocessing.py
-
curl -L -o test_iirs_preprocessing.py https://huggingface.co/spaces/RevanShriyan/Chandra-Align/resolve/main/tests/test_iirs_preprocessing.py
6.19 kB
| import numpy as np | |
| import pytest | |
| from chandra_align.preprocessing.iirs import ( | |
| IIRSPreprocessingResult, | |
| find_optimal_reflectance_band, | |
| histogram_match_to_reference, | |
| preprocess_iirs_raster, | |
| ) | |
| class TestIIRSPreprocessing: | |
| """Unit tests for IIRS SWIR cross-modal preprocessor.""" | |
| def test_find_optimal_band_target_1_55(self): | |
| """Test band selection prefers 1.55 µm target.""" | |
| wavelengths = [0.8, 1.2, 1.55, 1.8, 2.1, 2.5, 3.0, 3.5, 4.0] | |
| idx, wl = find_optimal_reflectance_band(wavelengths) | |
| assert idx == 2 | |
| assert wl == 1.55 | |
| def test_find_optimal_band_target_2_10(self): | |
| """Test band selection prefers 2.10 µm when 1.55 not available.""" | |
| wavelengths = [0.8, 1.2, 1.8, 2.1, 2.5] | |
| idx, wl = find_optimal_reflectance_band(wavelengths) | |
| assert idx == 3 | |
| assert wl == 2.1 | |
| def test_find_optimal_band_avoids_thermal(self): | |
| """Test band selection strictly avoids wavelengths > 3.0 µm.""" | |
| wavelengths = [0.8, 1.2, 1.55, 3.5, 4.0, 4.5, 5.0] | |
| idx, wl = find_optimal_reflectance_band(wavelengths) | |
| assert idx == 2 | |
| assert wl == 1.55 | |
| def test_find_optimal_band_all_thermal_fallback(self): | |
| """Test fallback to first band when all bands are thermal.""" | |
| wavelengths = [3.5, 4.0, 4.5, 5.0] | |
| idx, wl = find_optimal_reflectance_band(wavelengths) | |
| assert idx == 0 | |
| assert wl == 3.5 | |
| def test_find_optimal_band_empty_raises(self): | |
| """Test empty wavelength list raises ValueError.""" | |
| with pytest.raises(ValueError): | |
| find_optimal_reflectance_band([]) | |
| def test_histogram_match_2d_arrays(self): | |
| """Test histogram matching with synthetic 2D arrays.""" | |
| np.random.seed(42) | |
| source = np.random.randint(0, 256, (64, 64), dtype=np.uint8) | |
| ref = np.random.randint(0, 256, (64, 64), dtype=np.uint8) | |
| matched = histogram_match_to_reference(source, ref) | |
| assert matched.shape == source.shape | |
| assert matched.dtype == np.uint8 | |
| def test_histogram_match_invalid_dim_raises(self): | |
| """Test histogram matching rejects non-2D arrays.""" | |
| source = np.random.randint(0, 256, (3, 64, 64), dtype=np.uint8) | |
| ref = np.random.randint(0, 256, (64, 64), dtype=np.uint8) | |
| with pytest.raises(ValueError): | |
| histogram_match_to_reference(source, ref) | |
| def test_preprocess_iirs_2d_input(self): | |
| """Test preprocessing with 2D input (already single band).""" | |
| band = np.random.rand(64, 64).astype(np.float32) | |
| result = preprocess_iirs_raster(band) | |
| assert isinstance(result, IIRSPreprocessingResult) | |
| assert result.selected_band_index == 0 | |
| assert result.selected_wavelength_um == 1.55 | |
| assert result.processed_2d_raster.shape == (64, 64) | |
| assert result.processed_2d_raster.dtype == np.uint8 | |
| assert not result.histogram_matched | |
| def test_preprocess_iirs_3d_band_selection(self): | |
| """Test preprocessing selects optimal band from 3D hyperspectral data.""" | |
| wavelengths = [0.8, 1.0, 1.55, 2.1, 3.5, 4.5] # 6 bands | |
| multiband = np.random.rand(6, 64, 64).astype(np.float32) | |
| result = preprocess_iirs_raster(multiband, wavelengths_um=wavelengths) | |
| assert isinstance(result, IIRSPreprocessingResult) | |
| assert result.selected_band_index == 2 # 1.55 µm band | |
| assert result.selected_wavelength_um == 1.55 | |
| assert result.processed_2d_raster.shape == (64, 64) | |
| def test_preprocess_iirs_3d_avoids_thermal_bands(self): | |
| """Test preprocessing avoids thermal bands (>3.0 µm) even if closest to 1.55.""" | |
| wavelengths = [0.8, 3.5, 4.0, 5.0] # Only first band is valid | |
| multiband = np.random.rand(4, 64, 64).astype(np.float32) | |
| result = preprocess_iirs_raster(multiband, wavelengths_um=wavelengths) | |
| assert result.selected_band_index == 0 | |
| assert result.selected_wavelength_um == 0.8 | |
| def test_preprocess_iirs_histogram_matching(self): | |
| """Test histogram matching against reference raster.""" | |
| np.random.seed(42) | |
| wavelengths = [0.8, 1.55, 2.1, 3.5] | |
| multiband = np.random.rand(4, 64, 64).astype(np.float32) | |
| ref = np.random.randint(0, 256, (64, 64), dtype=np.uint8) | |
| result = preprocess_iirs_raster(multiband, wavelengths_um=wavelengths, ref_raster=ref) | |
| assert result.histogram_matched | |
| assert result.processed_2d_raster.dtype == np.uint8 | |
| def test_preprocess_iirs_invalid_shape_raises(self): | |
| """Test preprocessing rejects invalid shapes.""" | |
| with pytest.raises(ValueError): | |
| preprocess_iirs_raster(np.random.rand(3, 4, 64, 64)) | |
| def test_preprocess_iirs_clahe_enhancement(self): | |
| """Test that CLAHE is applied (local contrast enhancement).""" | |
| # Create image with uniform regions - CLAHE should enhance local contrast | |
| band = np.ones((64, 64), dtype=np.float32) * 100 | |
| band[10:20, 10:20] = 150 # small bright patch | |
| result = preprocess_iirs_raster(band) | |
| # CLAHE should enhance the patch | |
| processed = result.processed_2d_raster | |
| assert processed.shape == (64, 64) | |
| assert processed.dtype == np.uint8 | |
| def test_preprocess_iirs_dummy_wavelengths_generated(self): | |
| """Test dummy wavelengths generated when not provided.""" | |
| multiband = np.random.rand(10, 32, 32).astype(np.float32) | |
| result = preprocess_iirs_raster(multiband) | |
| assert result.selected_wavelength_um < 3.0 # Should pick valid band | |
| assert 0 <= result.selected_band_index < 10 | |
| def test_preprocess_iirs_percentile_normalization(self): | |
| """Test percentile-based normalization (2-98% clip).""" | |
| # Create band with outliers | |
| band = np.ones((64, 64), dtype=np.float32) * 100 | |
| band[0, 0] = 10000 # extreme outlier | |
| band[63, 63] = -500 # extreme negative | |
| result = preprocess_iirs_raster(band) | |
| # Should normalize without extreme values dominating | |
| assert result.processed_2d_raster.max() <= 255 | |
| assert result.processed_2d_raster.min() >= 0 |