diff --git a/src/earthrs/processing/atmospheric.py b/src/earthrs/processing/atmospheric.py index 533630b..beb7d36 100644 --- a/src/earthrs/processing/atmospheric.py +++ b/src/earthrs/processing/atmospheric.py @@ -1,21 +1,33 @@ -"""Atmospheric-correction processing placeholder.""" +"""Atmospheric-correction processing routines.""" from __future__ import annotations from typing import Any +from earthrs.processing.core import _ATMOSPHERIC_REGISTRY, register_atmospheric_method from earthrs.scene import Scene def atmospheric_correction(scene: Scene, *, method: str = "default", **kwargs: Any) -> Scene: """Apply atmospheric correction to reflectance inputs. - The function is registry-ready but atmospheric correction is not yet implemented. + Method names are resolved from the atmospheric-correction registry. Atmospheric + correction is not yet implemented, so the registered ``"default"`` method raises + ``NotImplementedError``. """ + processor = _ATMOSPHERIC_REGISTRY.get(method.lower()) + if processor is None: + raise ValueError(f"Unknown atmospheric-correction method '{method}'.") + return processor(scene, **kwargs) + + +def _default_atmospheric_correction(scene: Scene, **kwargs: Any) -> Scene: _ = scene - _ = method _ = kwargs raise NotImplementedError( "Atmospheric correction is not yet implemented. Check for a new version of earthrs." ) + + +register_atmospheric_method("default", _default_atmospheric_correction) diff --git a/src/earthrs/processing/core.py b/src/earthrs/processing/core.py index 7629a1d..118d0fc 100644 --- a/src/earthrs/processing/core.py +++ b/src/earthrs/processing/core.py @@ -11,10 +11,12 @@ GlintProcessor = Any DepthProcessor = Any CloudProcessor = Any +AtmosphericProcessor = Any _GLINT_REGISTRY: dict[str, GlintProcessor] = {} _DEPTH_REGISTRY: dict[str, DepthProcessor] = {} _CLOUD_REGISTRY: dict[str, CloudProcessor] = {} +_ATMOSPHERIC_REGISTRY: dict[str, AtmosphericProcessor] = {} def register_glint_method(name: str, func: GlintProcessor) -> None: @@ -29,6 +31,10 @@ def register_cloud_method(name: str, func: CloudProcessor) -> None: _CLOUD_REGISTRY[name.lower()] = func +def register_atmospheric_method(name: str, func: AtmosphericProcessor) -> None: + _ATMOSPHERIC_REGISTRY[name.lower()] = func + + _RESAMPLING_METHODS = frozenset({"nearest", "bilinear"}) Transform = tuple[float, float, float, float, float, float] diff --git a/tests/test_processing.py b/tests/test_processing.py index 11fb4c3..a0da0b7 100644 --- a/tests/test_processing.py +++ b/tests/test_processing.py @@ -41,6 +41,36 @@ def test_atmospheric_correction_is_deferred() -> None: atmospheric_correction(scene) +def test_atmospheric_correction_default_method_is_deferred() -> None: + scene = Scene(data={"blue": [0.1]}, band_names=["blue"]) + + with pytest.raises(NotImplementedError): + atmospheric_correction(scene, method="default") + + +def test_atmospheric_correction_rejects_unknown_method() -> None: + scene = Scene(data={"blue": [0.1]}, band_names=["blue"]) + + with pytest.raises(ValueError): + atmospheric_correction(scene, method="not_a_method") + + +def test_register_atmospheric_method_round_trips_through_registry() -> None: + from earthrs.processing.core import _ATMOSPHERIC_REGISTRY, register_atmospheric_method + + def _dummy_processor(scene: Scene, **kwargs: object) -> Scene: + return scene + + register_atmospheric_method("Dummy", _dummy_processor) + try: + assert _ATMOSPHERIC_REGISTRY["dummy"] is _dummy_processor + + scene = Scene(data={"blue": [0.1]}, band_names=["blue"]) + assert atmospheric_correction(scene, method="DUMMY") is scene + finally: + del _ATMOSPHERIC_REGISTRY["dummy"] + + def test_hedley_glint_removal_subtracts_scaled_nir_and_clamps_at_zero() -> None: scene = Scene(data={"nir": [10, 20], "red": [5, 8]}, band_names=["nir", "red"])