scopeinpython.rtmo

Optical top-of-canopy BRDF: volume-scattering geometry, hot-spot gap probability, multi-layer 4-stream reflectance propagation, vertical flux profile, and the top-level run_rtmo orchestrator. Direct port of SCOPEinR/R/RTMo_functions.R and RTMo.R (getRTMo) — stops at the optical BRDF; does not compute leaf/soil temperatures, sensible/ latent heat fluxes, or photosynthesis (see Known limitations).

RTMo: optical top-of-canopy bidirectional reflectance pipeline.

Direct, function-by-function port of the optical BRDF portion of SCOPEinR/R/RTMo.R and its helpers in SCOPEinR/R/RTMo_functions.R (get.volscatt.scope, get.Pso, get.reflectances, get.fluxprofile). Ported outputs: the four-stream TOC reflectance factors (rdd, rsd, rdo, rso), the apparent TOC reflectance (refl), the TOC radiance in viewing direction (Lo_), the outgoing top-of-canopy flux (Eout_/Eouto/Eoutt/Lot), and the gap probabilities (Ps, Po, Pso, k, K).

Also includes net_radiation_lite(), a partial port of RTMo.R’s section 4 (PAR / net-radiation absorption breakdown) – specifically just Rnuc/Rnhc/Rnus/Rnhs/Pnu_Cab/Pnh_Cab, the six quantities scopeinpython.ebal actually consumes; the “lite” (scalar-per-layer, not full (13,36,nl) per-leaf-angle) branch only, matching every reference case in this port.

The direct-beam term (Rndir/Pndir_Cab/etc) decays with canopy depth using the full per-layer vectors (Asun etc.), the same as the diffuse term.

NOT ported (out of scope for this port, see python/README.md):
  • Everything else in RTMo.R’s section 4 (Rnuc_Car/Pnuc_Car/ Rnuc_PAR/Rnhc_PAR, top-of-canopy incident PAR P/EPAR, the full (13,36,nl) per-leaf-angle branch) – not consumed by scopeinpython.ebal, so out of scope for now;

  • the MODTRAN-atmospheric-file branch of get.calcTOCirr (only the “precomputed Esun_/Esky_” branch, i.e. the default SCOPE example irradiance, is ported);

  • mSCOPE per-layer leaf property variation (a single leaf-optics spectrum is broadcast to all nl canopy layers, as in the R example script here, i.e. mly$nly == 1).

scopeinpython.rtmo.get_volscatt_scope(tts, tto, psi, ttli)[source]

Volume scattering phase functions and interception coefficients, vectorised over the leaf inclination classes ttli.

Direct port of SCOPEinR::get.volscatt.scope (distinct from toolsrtm.canopy.volscatt, the scalar-ttl variant used by fourSAIL; SCOPE’s RTMo uses this vectorised formulation instead).

Return type:

dict with keys chi_s, chi_o, frho, ftau (arrays, same length as ttli).

Parameters:
  • tts (float)

  • tto (float)

  • psi (float)

  • ttli (ndarray)

scopeinpython.rtmo.get_pso(K, k, LAI, q, dso, xl)[source]

Bi-directional gap probability at normalized canopy depth xl.

Direct port of SCOPEinR::get.Pso.

Parameters:
  • K (float)

  • k (float)

  • LAI (float)

  • q (float)

  • dso (float)

  • xl (float)

Return type:

float

scopeinpython.rtmo.get_reflectances(tau_ss, tau_sd, tau_dd, rho_dd, rho_sd, rsoil, nl, nwl)[source]

Propagate thin-layer reflectance/transmittance down through nl canopy layers to the soil and back, producing the directional- hemispherical (R_sd) and hemispherical-hemispherical (R_dd) reflectance at the top of each layer (and the soil, layer index nl).

Direct port of SCOPEinR::get.reflectances. All spectral inputs are (nl, nwl) arrays except rsoil (nwl,); tau_ss may be (nl, nwl) or a scalar/((nl,) broadcastable) as in the R caller (constant per layer for a homogeneous canopy).

Return type:

dict with R_sd, R_dd (nl+1, nwl), Xss (nl,), Xsd, Xdd (nl, nwl).

Parameters:
  • nl (int)

  • nwl (int)

scopeinpython.rtmo.get_fluxprofile(Esun_, Esky_, rsoil, Xss, Xsd, Xdd, R_sd, R_dd, nl, nwl, rs_thermal=0.06)[source]

Propagate top-of-canopy direct/diffuse irradiance down through the canopy (and back up) to the vertical flux profile.

Direct port of SCOPEinR::get.fluxprofile (the nwl==2162/no spectral-padding path; the R function’s dim==2001 branch is dead code in the standard pipeline used here, since leaf/soil optics are already built at full nwl width before this is called – see run_rtmo()).

Return type:

dict with Es_, Emin_, Eplu_ ((nl+1, nwl) arrays).

Parameters:
  • nl (int)

  • nwl (int)

  • rs_thermal (float)

class scopeinpython.rtmo.CanopyStructure(LAI, lidf, hot, nlayers=None, litab=None, lazitab=None, xl=None)[source]

Bases: object

Canopy structural inputs for RTMo (subset of data.canopy in R needed by the optical BRDF pipeline).

Parameters:
LAI: float
lidf: ndarray
hot: float
nlayers: int | None = None
litab: ndarray = None
lazitab: ndarray = None
xl: ndarray = None
class scopeinpython.rtmo.RTMoResult(rdd: 'np.ndarray', rsd: 'np.ndarray', rdo: 'np.ndarray', rso: 'np.ndarray', refl: 'np.ndarray', Lo_: 'np.ndarray', Eout_: 'np.ndarray', Eouto: 'float', Eoutt: 'float', Lot: 'float', Esun_: 'np.ndarray', Esky_: 'np.ndarray', k: 'float', K: 'float', Ps: 'np.ndarray', Po: 'np.ndarray', Pso: 'np.ndarray', Emin_: 'np.ndarray', Eplu_: 'np.ndarray', Emins_: 'np.ndarray', Emind_: 'np.ndarray', Eplus_: 'np.ndarray', Eplud_: 'np.ndarray', rho_dd: 'np.ndarray', R_dd: 'np.ndarray', Xdd: 'np.ndarray', tau_dd: 'np.ndarray', vb: 'np.ndarray', vf: 'np.ndarray', Xsd: 'np.ndarray', Xss: 'np.ndarray', R_sd: 'np.ndarray')[source]

Bases: object

Parameters:
rdd: ndarray
rsd: ndarray
rdo: ndarray
rso: ndarray
refl: ndarray
Lo_: ndarray
Eout_: ndarray
Eouto: float
Eoutt: float
Lot: float
Esun_: ndarray
Esky_: ndarray
k: float
K: float
Ps: ndarray
Po: ndarray
Pso: ndarray
Emin_: ndarray
Eplu_: ndarray
Emins_: ndarray
Emind_: ndarray
Eplus_: ndarray
Eplud_: ndarray
rho_dd: ndarray
R_dd: ndarray
Xdd: ndarray
tau_dd: ndarray
vb: ndarray
vf: ndarray
Xsd: ndarray
Xss: ndarray
R_sd: ndarray
scopeinpython.rtmo.run_rtmo(spectral, leaf_refl, leaf_tran, rho_thermal, tau_thermal, rsoil, canopy, tts, tto, psi, Esun_, Esky_)[source]

Top-of-canopy optical BRDF: leaf optics + soil + canopy structure + geometry -> rdd/rsd/rdo/rso/refl (plus Lo_, Eout_ and gap probabilities).

Direct port of the optical-BRDF portion of SCOPEinR:::getRTMo (sections 0-3.3 and the outgoing-radiance block of section 5; the thermal energy balance and PAR/net-radiation breakdown, sections 4 and the vertical-profile block of section 5, are NOT ported – see module docstring).

Parameters:
  • spectral (SpectralConfig) – From scopeinpython.spectral.get_spectra_scope().

  • leaf_refl (array_like, shape (nl, 2001) or (2001,)) – Leaf hemispherical reflectance/transmittance, 400-2400 nm (e.g. from toolsrtm.prospect_d/prospect_pro, sliced to [:2001]). A 1-D array is broadcast to every canopy layer (equivalent to mSCOPE with a single layer, mly$nly == 1).

  • leaf_tran (array_like, shape (nl, 2001) or (2001,)) – Leaf hemispherical reflectance/transmittance, 400-2400 nm (e.g. from toolsrtm.prospect_d/prospect_pro, sliced to [:2001]). A 1-D array is broadcast to every canopy layer (equivalent to mSCOPE with a single layer, mly$nly == 1).

  • rho_thermal (float) – Leaf reflectance/transmittance in the thermal region (SCOPE default 0.01), extended across the 161 thermal bands.

  • tau_thermal (float) – Leaf reflectance/transmittance in the thermal region (SCOPE default 0.01), extended across the 161 thermal bands.

  • rsoil (array_like, shape (2001,)) – Soil reflectance, 400-2400 nm (e.g. from scopeinpython.soil.get_bsm()).

  • canopy (CanopyStructure)

  • tts (float) – Solar zenith, viewing zenith, relative azimuth (degrees).

  • tto (float) – Solar zenith, viewing zenith, relative azimuth (degrees).

  • psi (float) – Solar zenith, viewing zenith, relative azimuth (degrees).

  • Esun_ (array_like, shape (nwl,)) – Top-of-canopy direct solar / diffuse sky irradiance, on the spectral.wlS grid. This port only supports the “precomputed irradiance” mode of get.calcTOCirr (i.e. atmo already containing Esun_/Esky_, as in the default SCOPEinR example data SCOPEinR::Esun_/SCOPEinR::Esky_); the MODTRAN-atmospheric- file branch is not ported.

  • Esky_ (array_like, shape (nwl,)) – Top-of-canopy direct solar / diffuse sky irradiance, on the spectral.wlS grid. This port only supports the “precomputed irradiance” mode of get.calcTOCirr (i.e. atmo already containing Esun_/Esky_, as in the default SCOPEinR example data SCOPEinR::Esun_/SCOPEinR::Esky_); the MODTRAN-atmospheric- file branch is not ported.

Return type:

RTMoResult

class scopeinpython.rtmo.NetRadiationLite(Rnuc: 'np.ndarray', Rnhc: 'np.ndarray', Rnus: 'float', Rnhs: 'float', Pnu_Cab: 'np.ndarray', Pnh_Cab: 'np.ndarray')[source]

Bases: object

Parameters:
Rnuc: ndarray
Rnhc: ndarray
Rnus: float
Rnhs: float
Pnu_Cab: ndarray
Pnh_Cab: ndarray
scopeinpython.rtmo.net_radiation_lite(spectral, rtmo, canopy, tts, lazitab, leaf_refl, leaf_tran, rho_thermal, tau_thermal, rsoil, kChlrel)[source]

Direct, partial port of RTMo.R’s section 4 (“lite” branch only, see module docstring). Computes just the 6 quantities scopeinpython.ebal needs.

Parameters:
  • rtmo (RTMoResult) – From run_rtmo(), called with the same canopy/tts/ leaf_refl/leaf_tran/rho_thermal/tau_thermal/ rsoil as here (tto/psi/Esky_ aren’t needed here).

  • lazitab (array_like, shape (36,)) – Leaf azimuth classes, degrees (same grid as canopy.lidf’s 13 inclination classes pair with).

  • kChlrel (array_like, shape (nl, 2001) or (2001,)) – Relative contribution of chlorophyll to leaf absorption, 400-2400nm (from a Fluspect leaf model’s kChlrel output; a 1-D array broadcasts to every layer; pass zeros for a plain PROSPECT leaf model, matching R’s data.leafopt$kChlrel for that case).

  • spectral (SpectralConfig)

  • canopy (CanopyStructure)

  • tts (float)

  • leaf_refl (ndarray)

  • leaf_tran (ndarray)

  • rho_thermal (float)

  • tau_thermal (float)

  • rsoil (ndarray)

Return type:

NetRadiationLite