msi_processor.computing.atmospheric package#
Atmospheric-correction processing unit (C-PU-ATM; DPM-M-ATM).
TOA -> BOA (surface) reflectance inversion (6S/Vermote, ATBD <5.8>) plus scene
classification and cloud / cloud-shadow masking; emits the L2A product.
Submodules#
msi_processor.computing.atmospheric.core module#
Pure atmospheric-correction core (C-PU-ATM; ALG-ATM-PAR/RT/SCM).
CPM-free, I/O-free functions implementing the atmospheric-correction algorithms
of ATBD <5.8>. This stage has no prior-work heritage; it is new development
specified interface-first (SDD <5.4.9>) with a candidate algorithm whose RT
engine and parameter-retrieval/classifier bodies are down-selected in the DPM and
left as private [impl] stubs.
Algorithm split (operational baseline vs [impl])#
Two boundaries follow the same pattern as the geo-referencing core (an operational baseline now, the rigorous body deferred to the DPM/CDR):
ALG-ATM-RT(TOA -> BOA inversion). The 6S surface-reflectance inversion itself is exact algebra once the per-band radiative-transfer terms \(\{\rho_{\mathrm{atm}}, T, S\}\) are known; it is realised here (invert_boa(),toa_to_boa()) and fully unit-tested. The RT engine that *builds/interpolates* the LUT for the per-pixel geometry / AOT / water vapour / surface altitude (Py6S / 6SV / Sen2Cor-LUT / ACOLITE – down-selected in the DPM) is the deferred bodyresolve_rt_lut()([impl]). The unit consumes an already-resolvedRTLutfor the scene operating point.ALG-ATM-PAR(parameter ingest/retrieval). Ingesting AOT / water vapour / ozone from auxiliary meteorology is realised here (get_atmospheric_parameters()withmode="ingest"). Retrieving them from the imagery (dark-dense-vegetation AOT inversion, differential band-ratio water vapour) is the deferred body (mode="retrieve"->retrieve_atmospheric_parameters(),[impl]).ALG-ATM-SCM(scene classification & masks). A spectral-threshold scene classifier (Sen2Cor-style candidate, ATBD <5.8>) is realised here (classify_scene()) producing a scene-class layer plus cloud / cloud-shadow masks. A sophisticated (e.g. ML) classifier is the deferred refinement (classify_scene_ml(),[impl]).
Theory (ATBD <5.8>). Over a Lambertian surface the TOA reflectance is \(\rho_{\mathrm{TOA}} = \rho_{\mathrm{atm}} + T(\theta_s)T(\theta_v)\rho_s / (1 - S\rho_s)\); inverting for the surface (BOA) reflectance gives \(\rho_{\mathrm{BOA}} = (\rho_{\mathrm{TOA}} - \rho_{\mathrm{atm}}) / (T + S(\rho_{\mathrm{TOA}} - \rho_{\mathrm{atm}}))\) with \(T = T(\theta_s)T(\theta_v)\).
Trace: REQ-F-ATM-01..04; DPM-M-ATM; ALG-ATM-PAR/RT/SCM.
- class msi_processor.computing.atmospheric.core.AtmAux(aot, water_vapour, ozone=None)#
Bases:
objectAuxiliary atmospheric inputs ingested from meteorology ADFs (ingest mode).
Mirrors the
atmosphericADF content forALG-ATM-PARmode="ingest".- Attributes:
- ozone
-
aot:
Union[float,ndarray[tuple[Any,...],dtype[float64]]]#
-
ozone:
Optional[float] = None#
-
water_vapour:
Union[float,ndarray[tuple[Any,...],dtype[float64]]]#
- class msi_processor.computing.atmospheric.core.AtmParams(aot, water_vapour, ozone=None)#
Bases:
objectAtmospheric state used by the RT inversion (ALG-ATM-PAR output).
- Attributes:
- aot:
Aerosol optical thickness (550 nm), scalar or per-pixel field.
- water_vapour:
Columnar water vapour (g/cm^2), scalar or per-pixel field.
- ozone:
Columnar ozone (Dobson units), optional scalar.
-
aot:
Union[float,ndarray[tuple[Any,...],dtype[float64]]]#
-
ozone:
Optional[float] = None#
-
water_vapour:
Union[float,ndarray[tuple[Any,...],dtype[float64]]]#
- class msi_processor.computing.atmospheric.core.RTLut(path_reflectance, transmittance, spherical_albedo=<factory>)#
Bases:
objectPer-band radiative-transfer terms for the scene operating point (ALG-ATM-RT).
Each mapping is keyed by band id. The terms are the Vermote/6S decomposition:
path_reflectance– intrinsic (path) reflectance \(\rho_{\mathrm{atm}}\);transmittance– total two-way transmittance \(T = T(\theta_s)T(\theta_v)\);spherical_albedo– atmospheric spherical albedo \(S\).
Producing this table from an RT engine / pre-computed LUT for a given
AtmParams+SceneGeometry+ DEM altitude is the[impl]resolve_rt_lut().-
path_reflectance:
Mapping[str,float]#
-
spherical_albedo:
Mapping[str,float]#
-
transmittance:
Mapping[str,float]#
- msi_processor.computing.atmospheric.core.ScalarOrArray#
A radiative quantity that may be a per-scene scalar or a per-pixel field.
alias of
Union[float,ndarray[tuple[Any, …],dtype[float64]]]
- class msi_processor.computing.atmospheric.core.SceneClass#
Bases:
objectScene-classification label codes (Sen2Cor-style subset, ALG-ATM-SCM).
Stored as a
uint8layer inquality/scene_classificationof the L2A product.NO_DATAis reserved for fill; the cloud / cloud-shadow classes are mirrored into the per-band QA flag layer (QAFlag).- BARE_SOIL = 4#
- CLOUD = 1#
- CLOUD_SHADOW = 2#
- NO_DATA = 0#
- UNCLASSIFIED = 6#
- VEGETATION = 3#
- WATER = 5#
- class msi_processor.computing.atmospheric.core.SceneGeometry(sun_zenith, view_zenith=0.0, relative_azimuth=0.0)#
Bases:
objectPer-scene illumination/view geometry operating point (degrees).
The LUT is resolved at this operating point; rigorous per-pixel variation is handled inside the
[impl]resolve_rt_lut().-
relative_azimuth:
float= 0.0#
-
sun_zenith:
float#
-
view_zenith:
float= 0.0#
-
relative_azimuth:
- msi_processor.computing.atmospheric.core.classify_scene(boa, params)#
ALG-ATM-SCM – spectral-threshold scene classification + masks.
A Sen2Cor-style spectral-threshold classifier (ATBD <5.8> candidate). It derives, from the BOA stack, a scene-class layer (
SceneClasscodes) plus boolean cloud and cloud-shadow masks. Spectral roles (blue,green,red,nir) are resolved viaparams["band_roles"]or common band names; vegetation/water use NDVI/NDWI, clouds use a brightness threshold and shadows a low-NIR/low-brightness threshold. A more sophisticated (ML) classifier is the deferredclassify_scene_ml()([impl]).Thresholds (overridable via
params):cloud_brightness(0.5),shadow_nir(0.08),shadow_brightness(0.12),ndvi_veg(0.4),ndwi_water(0.2).- Return type:
tuple[ndarray[tuple[Any,...],dtype[uint8]],ndarray[tuple[Any,...],dtype[bool]],ndarray[tuple[Any,...],dtype[bool]]]- Returns:
- tuple
(scene_class[uint8], cloud_mask[bool], cloud_shadow_mask[bool]).
- Raises:
- InputValidationError
If the BOA stack is empty.
- msi_processor.computing.atmospheric.core.classify_scene_ml(boa, params)#
ALG-ATM-SCM refinement – learned scene classifier, [impl].
A trained (e.g. CNN / random-forest) scene classifier is the CDR refinement of the spectral-threshold baseline (
classify_scene()). The model and its training data are down-selected in the DPM; this fail-stops until then.- Return type:
tuple[ndarray[tuple[Any,...],dtype[uint8]],ndarray[tuple[Any,...],dtype[bool]],ndarray[tuple[Any,...],dtype[bool]]]
- msi_processor.computing.atmospheric.core.get_atmospheric_parameters(toa_refl, mode, aux, params)#
ALG-ATM-PAR – obtain the atmospheric state (ingest or retrieve).
- Return type:
- Parameters:
- toa_refl:
TOA reflectance band stack (only used by the retrieval path).
- mode:
"ingest"reads AOT / water vapour / ozone fromaux(auxiliary meteorology);"retrieve"inverts them from the imagery and is the deferred[impl]body (DDV AOT, band-ratio water vapour, ATBD <5.8>).- aux:
Ingested auxiliary atmospheric inputs (mandatory for
mode="ingest").- params:
Profile parameters (e.g. default fallbacks); reserved for the retrieval path.
- Returns:
- AtmParams
The atmospheric state for the RT inversion.
- Raises:
- InputValidationError
On an unknown
modeor a missingauxin ingest mode.- AtmosphericError
From the
[impl]retrieval path (until down-selected in the DPM).
- msi_processor.computing.atmospheric.core.invert_boa(toa, path_reflectance, transmittance, spherical_albedo)#
ALG-ATM-RT kernel – invert one band’s TOA reflectance to BOA.
Applies the 6S surface-reflectance inversion (ATBD <5.8>): :rtype:
ndarray[tuple[Any,...],dtype[float32]]\[\rho_{\mathrm{BOA}} = \frac{\rho_{\mathrm{TOA}} - \rho_{\mathrm{atm}}} {T + S\,(\rho_{\mathrm{TOA}} - \rho_{\mathrm{atm}})}\]with
Tthe total two-way transmittance andSthe spherical albedo. The result is clipped to the physical[0, 1]reflectance range.- Raises:
- AtmosphericError
If the total transmittance is non-positive (degenerate / invalid LUT term).
- msi_processor.computing.atmospheric.core.resolve_rt_lut(atm, geometry, dem, raw_lut)#
Interpolate the per-band RT terms for the scene operating point – [impl].
Multi-dimensional interpolation of a pre-computed radiative-transfer LUT (or a direct RT-engine call) over geometry, AOT, water vapour and surface altitude, yielding
RTLut. The engine (Py6S / 6SV / Sen2Cor-LUT / ACOLITE) is down-selected in the DPM and licence-screened in the SRF; the inversion that consumes the result (toa_to_boa()) is operational. Fail-stops until the engine is selected (ATBD <5.8> open point 1).- Return type:
- msi_processor.computing.atmospheric.core.retrieve_atmospheric_parameters(toa_refl, params)#
ALG-ATM-PAR retrieval body – [impl] (DPM down-selection / CDR target).
Image-based retrieval of AOT (dark-dense-vegetation inversion) and water vapour (differential band-ratio absorption) per ATBD <5.8>. The concrete method is down-selected and validated in the DPM before CDR; until then this fail-stops so the chain never emits an L2A product from un-retrieved parameters.
- Return type:
- msi_processor.computing.atmospheric.core.toa_to_boa(toa_refl, atm, geometry, dem, rt_lut)#
ALG-ATM-RT – invert the TOA reflectance stack to BOA per band.
For each band the per-band RT terms are looked up from
rt_lut(resolved at the scene operating point) and the 6S inversion (invert_boa()) is applied. Theatm/geometry/demarguments document the operating point the LUT was resolved at; per-pixel LUT interpolation lives in the[impl]resolve_rt_lut().- Return type:
dict[str,ndarray[tuple[Any,...],dtype[float32]]]- Returns:
- dict[str, ndarray]
BOA reflectance per band,
float32in[0, 1].
- Raises:
- AtmosphericError
If a band has no RT terms in the LUT (missing coverage).
msi_processor.computing.atmospheric.unit module#
Thin EOProcessingUnit wrapper for atmospheric correction (C-PU-ATM).
Adapts the pure core to the EOPF CPM
runtime following the wrapper template of SDD <5.4.1>/<5.4.9>: read parameters,
extract the TOA-reflectance bands, load/validate ADFs, orchestrate the pure-core
functions (ALG-ATM-PAR -> ALG-ATM-RT -> ALG-ATM-SCM), propagate QA, and build the
L2A EOProduct (BOA reflectance + scene classification + cloud/shadow
masks). No algorithm lives here.
Input convention. The upstream stage is the georeference unit; its l1c
product carries the orthorectified TOA reflectance under
measurements/reflectance/<band> and QA under quality/mask/<band>
(IF-PROD-03). Atmospheric correction inverts the TOA reflectance to BOA (surface)
reflectance on the same grid; L2A is the surface-reflectance product (DPM <8.7>).
ADF data convention (this increment). ADF content is read from the
AuxiliaryDataFile.data_ptr mapping:
atmospheric->{"aot": float|ndarray, "water_vapour": float|ndarray, "ozone": float | None, "rt_lut": {"path_reflectance": {band: float}, "transmittance": {band: float}, "spherical_albedo": {band: float}}}(optional; required whenmode="ingest": ingested AOT/water-vapour + the resolved per-band RT terms for the scene operating point, ICD <5.3.2>A). Building thert_lutfrom a radiative-transfer engine is the[impl]resolve_rt_lut().dem->{"elevation": ndarray2d, ...}(mandatory; surface altitude for the RT operating point; presence/coverage enforced here, REQ-F-ATM-02).
Implementation status (ATBD <5.8> open point 1). Image-based parameter
retrieval (mode="retrieve") and the RT engine that builds the LUT are
[impl] (DPM down-selection / CDR target). The PDR-operational path realised
here is parameter ingest (mode="ingest") with a pre-resolved RT-LUT from the
atmospheric ADF, the exact 6S BOA inversion, and the spectral-threshold scene
classifier.
Fail-stop (REQ-F-ATM-04). Missing DEM coverage, a missing atmospheric ADF
in ingest mode, or the [impl] retrieval/RT-engine paths raise
AtmosphericError; it propagates to the
chain runner so no L2A product is emitted from incomplete atmospheric inputs.
Cloud / cloud-shadow pixels are flagged CLOUD / CLOUD_SHADOW in the QA
layer (REQ-F-ATM-03) but never abort the chain.
Mandatory inputs/ADFs are declared by the CPM computing-model JSON
(models/msi_atmospheric_1.0.0.json), not by overriding the list methods.
Trace: REQ-F-ATM-01..04; DPM-M-ATM; ALG-ATM-PAR/RT/SCM; ICD IF-PROD-03, REQ-IF-OUT-02.
- class msi_processor.computing.atmospheric.unit.AtmosphericUnit(identifier='')#
Bases:
EOProcessingUnitAtmospheric-correction processing unit (C-PU-ATM; SDD <5.4.9>).
- Attributes:
identifierIdentifier of the processing step
Methods
run:
Invert the TOA-reflectance stack to BOA (surface) reflectance, classify the scene and emit the
L2Aproduct with cloud / cloud-shadow QA. Image-based parameter retrieval and the RT-LUT-building engine are[impl](ATBD <5.8> open point 1); the operational path is ingest mode with a pre-resolved RT-LUT.- PROCESSOR_LEVEL = 'L2A'#
- PROCESSOR_MODEL = True#
- PROCESSOR_NAME = 'msi_atmospheric'#
- PROCESSOR_VERSION = '1.0.0'#
- run(inputs, adfs=None, mode=None, **kwargs)#
Run the atmospheric correction.
- Return type:
Mapping[str,Union[EOProduct,EOContainer,DataTree,Iterable[Union[EOProduct,EOContainer,DataTree]]]]- Parameters:
- inputs:
{"l1c": EOProduct}with TOA reflectance undermeasurements/reflectance/<band>and optional QA underquality/mask/<band>.- adfs:
atmospheric(required forparam_mode="ingest": ingested AOT/water-vapour + a resolved RT-LUT) anddem(mandatory; surface altitude).- mode:
"nominal"(the only supported processing mode).- **kwargs:
param_mode("ingest"|"retrieve", default"ingest"),sun_zenith/view_zenith/relative_azimuth(scene geometry operating point), scene-classification thresholds andband_roles(seeclassify_scene()), and an optionalnamefor the output product.
- Returns:
- Mapping[str, DataType]
{"l2a": EOProduct}with BOAmeasurements/reflectance/<band>,quality/scene_classificationandquality/mask/<band>.
- Raises:
- AtmosphericError
On missing DEM coverage, a missing
atmosphericADF in ingest mode, or the[impl]retrieval / RT-engine paths – fail-stop (REQ-F-ATM-04).