satpy.modifiers._crefl_utils module

Shared utilities for correcting reflectance data using the ‘crefl’ algorithm.

The CREFL algorithm in this module is based on the NASA CREFL SPA software, the NASA CVIIRS SPA, and customizations of these algorithms for ABI/AHI by Ralph Kuehn and Min Oo at the Space Science and Engineering Center (SSEC).

The CREFL SPA documentation page describes the algorithm by saying:

The CREFL_SPA processes MODIS Aqua and Terra Level 1B DB data to create the MODIS Level 2 Corrected Reflectance product. The algorithm performs a simple atmospheric correction with MODIS visible, near-infrared, and short-wave infrared bands (bands 1 through 16).

It corrects for molecular (Rayleigh) scattering and gaseous absorption (water vapor and ozone) using climatological values for gas contents. It requires no real-time input of ancillary data. The algorithm performs no aerosol correction. The Corrected Reflectance products created by CREFL_SPA are very similar to the MODIS Land Surface Reflectance product (MOD09) in clear atmospheric conditions, since the algorithms used to derive both are based on the 6S Radiative Transfer Model. The products show differences in the presence of aerosols, however, because the MODIS Land Surface Reflectance product uses a more complex atmospheric correction algorithm that includes a correction for aerosols.

The additional logic to support ABI (AHI support not included) was originally written by Ralph Kuehn and Min Oo at SSEC. Additional modifications were performed by Martin Raspaud, David Hoese, and Will Roberts to make the code work together and be more dask compatible.

The AHI/ABI implementation is based on the MODIS collection 6 algorithm, where a spherical-shell atmosphere was assumed rather than a plane-parallel. See Appendix A in: “The Collection 6 MODIS aerosol products over land and ocean” Atmos. Meas. Tech., 6, 2989–3034, 2013 www.atmos-meas-tech.net/6/2989/2013/ DOI:10.5194/amt-6-2989-2013.

The original CREFL code is similar to what is described in appendix A1 (page 74) of the ATBD for the MODIS MOD04/MYD04 data product.

class satpy.modifiers._crefl_utils._ABIAtmosphereVariables(G_O3, G_H2O, G_O2, *args)[source]

Bases: _AtmosphereVariables

_get_th2o()[source]
_get_to2()[source]
_get_to3()[source]
class satpy.modifiers._crefl_utils._ABICREFLRunner(refl_data_arr)[source]

Bases: _CREFLRunner

_run_crefl(mus, muv, phi, solar_zenith, sensor_zenith, height, coeffs)[source]
property coeffs_cls: Type[_Coefficients]
class satpy.modifiers._crefl_utils._ABICoefficients(wavelength_range, resolution=0)[source]

Bases: _Coefficients

COEFF_INDEX_MAP: dict[int, dict[tuple | str, int]] = {2000: {'C01': 0, 'C02': 1, 'C03': 2, 'C05': 3, 'C06': 4, (0.45, 0.47, 0.49, 'µm'): 0, (0.59, 0.64, 0.69, 'µm'): 1, (0.8455, 0.865, 0.8845, 'µm'): 2, (1.58, 1.61, 1.64, 'µm'): 3, (2.225, 2.25, 2.275, 'µm'): 4}}
LUTS: list[ndarray] = [array([0.0024111 , 0.00431497, 0.0079258 , 0.0093392 , 0.0253    ]), array([0.001236  , 0.0037296 , 0.00017772, 0.0104899 , 0.0163    ]), array([4.2869000e-03, 1.4107995e-02, 8.0243190e-04, 0.0000000e+00,        2.0000000e-05]), array([0.18472   , 0.052349  , 0.015845  , 0.0013074 , 0.00031129])]
RG_FUDGE = 0.55
class satpy.modifiers._crefl_utils._AtmosphereVariables(mus, muv, phi, height, ah2o, bh2o, ao3, tau)[source]

Bases: object

_get_th2o()[source]
_get_to2()[source]
_get_to3()[source]
class satpy.modifiers._crefl_utils._CREFLRunner(refl_data_arr)[source]

Bases: object

_height_from_avg_elevation(avg_elevation: ndarray | None) Array | float[source]

Get digital elevation map data for our granule with ocean fill value set to 0.

_run_crefl(mus, muv, phi, solar_zenith, sensor_zenith, height, coeffs)[source]
property coeffs_cls: Type[_Coefficients]
class satpy.modifiers._crefl_utils._Coefficients(wavelength_range, resolution=0)[source]

Bases: object

COEFF_INDEX_MAP: dict[int, dict[tuple | str, int]] = {}
LUTS: list[ndarray] = []
_find_coefficient_index(wavelength_range, resolution=0)[source]

Return index in to coefficient arrays for this band’s wavelength.

This function search through the COEFF_INDEX_MAP dictionary and finds the first key where the nominal wavelength of wavelength_range falls between the minimum wavelength and maximum wavelength of the key. wavelength_range can also be the standard name of the band. For example, “M05” for VIIRS or “1” for MODIS.

Parameters:
  • wavelength_range – 3-element tuple of (min wavelength, nominal wavelength, max wavelength) or the string name of the band.

  • resolution – resolution of the band to be corrected

Returns:

index in to coefficient arrays like aH2O, aO3, etc. None is returned if no matching wavelength is found

satpy.modifiers._crefl_utils._G_calc(zenith, a_coeff)[source]
class satpy.modifiers._crefl_utils._MODISAtmosphereVariables(*args)[source]

Bases: _VIIRSAtmosphereVariables

_get_th2o()[source]
_get_to3()[source]
class satpy.modifiers._crefl_utils._MODISCREFLRunner(refl_data_arr)[source]

Bases: _VIIRSMODISCREFLRunner

_run_crefl(mus, muv, phi, solar_zenith, sensor_zenith, height, coeffs)[source]
property coeffs_cls: Type[_Coefficients]
class satpy.modifiers._crefl_utils._MODISCoefficients(wavelength_range, resolution=0)[source]

Bases: _Coefficients

COEFF_INDEX_MAP: dict[int, dict[tuple | str, int]] = {250: {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, (0.459, 0.469, 0.479, 'µm'): 2, (0.545, 0.555, 0.565, 'µm'): 3, (0.62, 0.645, 0.67, 'µm'): 0, (0.841, 0.8585, 0.876, 'µm'): 1, (1.23, 1.24, 1.25, 'µm'): 4, (1.628, 1.64, 1.652, 'µm'): 5, (2.105, 2.13, 2.155, 'µm'): 6}, 500: {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, (0.459, 0.469, 0.479, 'µm'): 2, (0.545, 0.555, 0.565, 'µm'): 3, (0.62, 0.645, 0.67, 'µm'): 0, (0.841, 0.8585, 0.876, 'µm'): 1, (1.23, 1.24, 1.25, 'µm'): 4, (1.628, 1.64, 1.652, 'µm'): 5, (2.105, 2.13, 2.155, 'µm'): 6}, 1000: {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, (0.459, 0.469, 0.479, 'µm'): 2, (0.545, 0.555, 0.565, 'µm'): 3, (0.62, 0.645, 0.67, 'µm'): 0, (0.841, 0.8585, 0.876, 'µm'): 1, (1.23, 1.24, 1.25, 'µm'): 4, (1.628, 1.64, 1.652, 'µm'): 5, (2.105, 2.13, 2.155, 'µm'): 6}}
LUTS: list[ndarray] = [array([-5.60723, -5.25251,  0.     ,  0.     , -6.29824, -7.70944,        -3.91877,  0.     ,  0.     ,  0.     ,  0.     ,  0.     ,         0.     ,  0.     ,  0.     ,  0.     ]), array([0.820175, 0.725159, 0.      , 0.      , 0.865732, 0.966947,        0.745342, 0.      , 0.      , 0.      , 0.      , 0.      ,        0.      , 0.      , 0.      , 0.      ]), array([0.0715289 , 0.        , 0.00743232, 0.089691  , 0.        ,        0.        , 0.        , 0.001     , 0.00383   , 0.0225    ,        0.0663    , 0.0836    , 0.0485    , 0.0395    , 0.0119    ,        0.00263   ]), array([0.051  , 0.01631, 0.19325, 0.09536, 0.00366, 0.00123, 0.00043,        0.3139 , 0.2375 , 0.1596 , 0.1131 , 0.0994 , 0.0446 , 0.0416 ,        0.0286 , 0.0155 ])]
class satpy.modifiers._crefl_utils._VIIRSAtmosphereVariables(*args)[source]

Bases: _AtmosphereVariables

_compute_airmass()[source]
_get_th2o()[source]
_get_to3()[source]
class satpy.modifiers._crefl_utils._VIIRSCREFLRunner(refl_data_arr)[source]

Bases: _VIIRSMODISCREFLRunner

_run_crefl(mus, muv, phi, solar_zenith, sensor_zenith, height, coeffs)[source]
property coeffs_cls: Type[_Coefficients]
class satpy.modifiers._crefl_utils._VIIRSCoefficients(wavelength_range, resolution=0)[source]

Bases: _Coefficients

COEFF_INDEX_MAP: dict[int, dict[tuple | str, int]] = {500: {'I01': 7, 'I02': 8, 'I03': 9, (0.6, 0.64, 0.68, 'µm'): 7, (0.845, 0.865, 0.884, 'µm'): 8, (1.58, 1.61, 1.64, 'µm'): 9}, 1000: {'M03': 2, 'M04': 3, 'M05': 0, 'M07': 1, 'M08': 4, 'M10': 5, 'M11': 6, (0.478, 0.488, 0.498, 'µm'): 2, (0.545, 0.555, 0.565, 'µm'): 3, (0.662, 0.672, 0.682, 'µm'): 0, (0.846, 0.865, 0.885, 'µm'): 1, (1.23, 1.24, 1.25, 'µm'): 4, (1.58, 1.61, 1.64, 'µm'): 5, (2.225, 2.25, 2.275, 'µm'): 6}}
LUTS: list[ndarray] = [array([4.06601e-04, 1.59330e-03, 0.00000e+00, 1.78644e-05, 2.96457e-03,        6.17252e-04, 9.96563e-04, 2.22253e-03, 9.40050e-04, 5.63288e-04,        0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,        0.00000e+00]), array([0.812659, 0.832931, 1.      , 0.867785, 0.806816, 0.944958,        0.78812 , 0.791204, 0.900564, 0.942907, 0.      , 0.      ,        0.      , 0.      , 0.      , 0.      ]), array([0.0433461, 0.       , 0.0178299, 0.0853012, 0.       , 0.       ,        0.       , 0.0813531, 0.       , 0.       , 0.0663   , 0.0836   ,        0.0485   , 0.0395   , 0.0119   , 0.00263  ]), array([0.0435 , 0.01582, 0.16176, 0.0974 , 0.00369, 0.00132, 0.00033,        0.05373, 0.01561, 0.00129, 0.1131 , 0.0994 , 0.0446 , 0.0416 ,        0.0286 , 0.0155 ])]
class satpy.modifiers._crefl_utils._VIIRSMODISCREFLRunner(refl_data_arr)[source]

Bases: _CREFLRunner

_run_crefl(mus, muv, phi, solar_zenith, sensor_zenith, height, coeffs)[source]
satpy.modifiers._crefl_utils._chand(phi, muv, mus, taur)[source]
satpy.modifiers._crefl_utils._correct_refl(refl, tOG, rhoray, TtotraytH2O, sphalb)[source]
satpy.modifiers._crefl_utils._csalbr(tau)[source]
satpy.modifiers._crefl_utils._run_crefl(refl, mus, muv, phi, height, sensor_name, *coeffs)[source]
satpy.modifiers._crefl_utils._run_crefl_abi(refl, mus, muv, phi, solar_zenith, sensor_zenith, height, *coeffs)[source]
satpy.modifiers._crefl_utils._runner_class_for_sensor(sensor_name: str) Type[_CREFLRunner][source]
satpy.modifiers._crefl_utils._space_mask_height(lon, lat, avg_elevation)[source]
satpy.modifiers._crefl_utils.run_crefl(refl, sensor_azimuth, sensor_zenith, solar_azimuth, solar_zenith, avg_elevation=None)[source]

Run main crefl algorithm.

All input parameters are per-pixel values meaning they are the same size and shape as the input reflectance data, unless otherwise stated.

Parameters:
  • refl – tuple of reflectance band arrays

  • sensor_azimuth – input swath sensor azimuth angle array

  • sensor_zenith – input swath sensor zenith angle array

  • solar_azimuth – input swath solar azimuth angle array

  • solar_zenith – input swath solar zenith angle array

  • avg_elevation – average elevation (usually pre-calculated and stored in CMGDEM.hdf)