""" Test script for cloud_removal module Kiểm tra các phương pháp xử lý mây """ import numpy as np import xarray as xr from cloud_removal import ( process_cloud_removal, get_available_methods, compare_methods ) def create_mock_s2_data(): """Tạo mock Sentinel-2 data để test""" # Create synthetic data: 5 time steps, 100x100 pixels np.random.seed(42) time_steps = 5 y_size = 100 x_size = 100 # Create bands bands = {} for band in ["B02", "B03", "B04", "B08", "B11"]: # Random reflectance values data = np.random.rand(time_steps, y_size, x_size) * 0.3 + 0.1 bands[band] = (["time", "y", "x"], data) # Create SCL (Scene Classification Layer) # Mostly vegetation (4), with some clouds scl_data = np.full((time_steps, y_size, x_size), 4, dtype=np.uint8) # Add clouds (class 9) in random locations for t in range(time_steps): # Random cloud patches n_clouds = np.random.randint(5, 15) for _ in range(n_clouds): y_start = np.random.randint(0, y_size - 20) x_start = np.random.randint(0, x_size - 20) cloud_height = np.random.randint(10, 20) cloud_width = np.random.randint(10, 20) scl_data[t, y_start:y_start+cloud_height, x_start:x_start+cloud_width] = 9 bands["SCL"] = (["time", "y", "x"], scl_data) # Create xarray Dataset ds = xr.Dataset( bands, coords={ "time": np.arange(time_steps), "y": np.arange(y_size), "x": np.arange(x_size) } ) return ds def test_available_methods(): """Test lấy danh sách methods""" print("=" * 60) print("TEST: Get Available Methods") print("=" * 60) methods = get_available_methods() print(f"\nFound {len(methods)} methods:") for method, description in methods.items(): print(f" - {method:20s}: {description}") print("\n✅ Test passed!") def test_single_method(method_name="classic"): """Test một method cụ thể""" print("\n" + "=" * 60) print(f"TEST: Cloud Removal Method '{method_name}'") print("=" * 60) # Create mock data s2_data = create_mock_s2_data() print(f"\nMock data created: {dict(s2_data.dims)}") # Process clouds cleaned_data, metadata = process_cloud_removal( s2_data=s2_data, method=method_name, verbose=True ) # Check results print(f"\nMetadata:") print(f" - Method: {metadata['method']}") print(f" - Cloud coverage: {metadata['cloud_coverage_percent']:.1f}%") print(f" - Masked pixels: {metadata['masked_pixels']:,}/{metadata['total_pixels']:,}") print(f" - Steps applied: {', '.join(metadata['steps_applied'])}") # Verify no NaN remaining nan_count = 0 for band in cleaned_data.data_vars: if band != "SCL": nan_count += np.isnan(cleaned_data[band].values).sum() print(f"\nRemaining NaN pixels: {nan_count}") if nan_count == 0: print("✅ Test passed - no NaN remaining!") else: print(f"⚠️ Warning - {nan_count} NaN pixels remaining") def test_comparison(): """Test so sánh nhiều methods""" print("\n" + "=" * 60) print("TEST: Compare Multiple Methods") print("=" * 60) # Create mock data s2_data = create_mock_s2_data() # Compare methods methods_to_test = ["classic", "temporal_only", "median_composite", "ml_knn"] print(f"\nComparing {len(methods_to_test)} methods...") results = compare_methods(s2_data, methods=methods_to_test) # Print summary print("\n" + "-" * 60) print(f"{'Method':<20} {'Success':<10} {'NaN %':<10} {'Steps'}") print("-" * 60) for method, result in results.items(): if result['success']: nan_pct = result['remaining_nan_percent'] steps = ', '.join(result['metadata']['steps_applied'][:2]) # First 2 steps print(f"{method:<20} {'✅':<10} {nan_pct:>6.2f}% {steps}") else: print(f"{method:<20} {'❌':<10} {'ERROR':<10} {result['error']}") print("-" * 60) print("\n✅ Comparison test completed!") def test_edge_cases(): """Test các trường hợp đặc biệt""" print("\n" + "=" * 60) print("TEST: Edge Cases") print("=" * 60) # Case 1: No SCL band print("\n1. Testing without SCL band...") s2_data = create_mock_s2_data() s2_data_no_scl = s2_data.drop_vars("SCL") cleaned, meta = process_cloud_removal(s2_data_no_scl, method="classic", verbose=False) print(f" Result: {meta.get('warning', 'OK')}") # Case 2: 100% cloud coverage print("\n2. Testing with 100% cloud coverage...") s2_data_full_cloud = create_mock_s2_data() s2_data_full_cloud["SCL"][:] = 9 # All clouds cleaned, meta = process_cloud_removal(s2_data_full_cloud, method="classic", verbose=False) print(f" Cloud coverage: {meta['cloud_coverage_percent']:.1f}%") # Case 3: No clouds print("\n3. Testing with no clouds...") s2_data_clear = create_mock_s2_data() s2_data_clear["SCL"][:] = 4 # All vegetation cleaned, meta = process_cloud_removal(s2_data_clear, method="classic", verbose=False) print(f" Cloud coverage: {meta['cloud_coverage_percent']:.1f}%") print("\n✅ Edge case tests passed!") if __name__ == "__main__": print("\n" + "🌥️ CLOUD REMOVAL MODULE TESTS 🌥️ ".center(60, "=")) print() # Run tests test_available_methods() test_single_method("classic") test_single_method("hybrid") test_comparison() test_edge_cases() print("\n" + "=" * 60) print("ALL TESTS COMPLETED!") print("=" * 60) print("\nModule is ready to use. Available methods:") for method, desc in get_available_methods().items(): print(f" • {method}")