07. Building RTM Workflows

What you will learn

  • How the models from Part I chain together, not just what each one does in isolation.

  • The four standard simulation pipelines used throughout the rest of this site.

  • Which chapter’s full runnable version to go to for each.

Concept

Part I covered six models one at a time. In practice they’re always used chained: a leaf model’s output becomes a canopy model’s input, a soil model’s output becomes a canopy model’s input, and so on. This chapter is those chains made explicit, as simple diagrams plus a minimal code snippet each.

Python tools used

Every function below is covered in depth in Part I: prospect_d(), foursail(), inform(), get_marmit_rsoil(), spart_toa(), get_scope(). This chapter is about how they connect, not new arguments.

1. PROSPECT -> fourSAIL -> canopy reflectance

The baseline pipeline: one leaf model feeds one canopy model, for a single homogeneous crop/grassland-type canopy over a flat soil.

Leaf traits (N, Cab, Car, Anth, EWT, LMA, alpha)
              |
              v
     prospect_d() / prospect_pro()
              |
              v
     Leaf reflectance (rho) / transmittance (tau)
              |
              |    Canopy structure (LAI, LIDFa, LIDFb, hspot)
              |    Sun-view geometry (tts, tto, psi)
              |    Soil background (rsoil)
              v
           foursail()
              |
              v
     Top-of-canopy (TOC) reflectance, 400-2500nm
from toolsrtm import prospect_d, foursail
leaf = prospect_d(N=1.5, Cab=40, Car=8, Anth=1, Cbrown=0, EWT=0.01, LMA=0.009, alpha=40)
sail = foursail(dict(N=1.5, Cab=40, Car=8, Anth=1, Cbrown=0, EWT=0.01, LMA=0.009, alpha=40,
                      LIDFa=-0.35, LIDFb=-0.15, TypeLidf=1, LAI=3, hspot=0.01, tts=30, tto=0, psi=0),
                 rsoil=[0.15] * 2101, leaf_model="PROSPECT-D", spectrum_all=True)
PROSPECT-D leaf optics and the resulting fourSAIL canopy TOC reflectance, real output of the code above

Real output: leaf-level optics (left, the input to the chain) and the resulting canopy-level TOC reflectance (right, the chain’s output) – the same two-step shape 01. Getting Started ran first.

Full version with a plot: Leaf + canopy (toolsrtm).

2. PROSPECT -> INFORM -> forest reflectance

Same leaf model, but the canopy step adds explicit tree-crown geometry – stem density, crown diameter, tree height, understorey LAI – instead of treating the whole canopy as one homogeneous layer.

Leaf traits  ->  prospect_d()  ->  Leaf reflectance/transmittance
                                           |
                       Understorey LAI, stem density,          |
                       crown diameter, tree height, diffuse-    |
                       light fraction (skyl)                    v
                                                             inform()
                                                                 |
                                                                 v
                                           TOC reflectance -- lower than
                                           fourSAIL at the same LAI (real
                                           crown/gap shadow geometry)
from toolsrtm import inform
r_forest = inform(dict(N=1.5, Cab=40, Car=8, Anth=1, Cbrown=0, EWT=0.01, LMA=0.009, alpha=40,
                        LIDFa=-0.35, LIDFb=-0.15, TypeLidf=1, LAI=3, hspot=0.01, tts=30, tto=0, psi=0,
                        LAIu=0.5, sd=650, cd=4.5, h=20, skyl=0.1),
                   rsoil=[0.15] * 2101, leaf_model="PROSPECT-D")
fourSAIL vs INFORM TOC reflectance at the same leaf and LAI, real output of the code above

Real output: same leaf optics and LAI through both chains – INFORM’s explicit crown/gap geometry produces lower reflectance than a homogeneous fourSAIL canopy, matching 04. Canopy Radiative Transfer Models’s own comparison.

Full version comparing fourSAIL vs. INFORM side by side: INFORM: explicit forest-canopy model (toolsrtm).

3. MARMIT -> fourSAIL -> SPART -> TOA

The full soil-plant-atmosphere chain: a real, moisture-dependent soil spectrum feeds the canopy model, and SPART’s own atmosphere step (SMAC) converts the result to what a real satellite would measure above the atmosphere – not just top-of-canopy.

Dry reference soil spectrum, water-film params (L, eps)
              |
              v
       get_marmit_rsoil()
              |
              v
       Wetted soil reflectance  ---+
                                    |
Leaf + canopy traits                v
              |               (used as rsoil)
              v                     |
         foursail()  <--------------+
              |
              v
       TOC reflectance
              |
              |    Atmosphere (Pa, aot550, uo3, uh2o), sensor (Sentinel-2A)
              v
          spart_toa()  (re-derives TOC via BSM + adds SMAC atmosphere)
              |
              v
       TOA reflectance, per sensor band
from toolsrtm import get_marmit_rsoil, spart_toa, sentinel2a_msi
soil = get_marmit_rsoil(soil_id=3, L=0.05, eps=0.4, version="marmit1")
result = spart_toa(dict(N=1.5, Cab=40, Car=8, Anth=1, Cbrown=0, EWT=0.01, LMA=0.009, alpha=40,
                         LIDFa=-0.35, LIDFb=-0.15, TypeLidf=1, LAI=3, hspot=0.01, tts=30, tto=0, psi=0,
                         Pa=1000, aot550=0.3246, uo3=0.348, uh2o=1.4116),
                    sensor=sentinel2a_msi(), leaf_model="PROSPECT-PRO",
                    BSMBrightness=0.5, BSMlat=25, BSMlon=45, SMp=15)

Note

spart_toa builds its own soil internally via BSM parameters (BSMBrightness/BSMlat/BSMlon/SMp), a separate soil model from MARMIT – 05. Soil & Atmosphere covers how the two differ. MARMIT’s output is shown here as a standalone soil-spectrum step you could feed into plain foursail() instead, if TOC (not TOA) is all you need.

SPART TOC and TOA reflectance across Sentinel-2A bands, real output of the code above

Real output: TOC and TOA reflectance diverge sharply in the water-vapour bands (~940/1370nm), the same atmospheric effect 05. Soil & Atmosphere quantifies.

Full versions: MARMIT soil moisture model (toolsrtm), SPART: full soil-plant-atmosphere chain (toolsrtm).

4. SCOPE -> reflectance + SIF + energy balance

A structurally different pipeline: instead of one forward pass through leaf -> canopy, SCOPE iterates leaf/soil temperature until the energy balance closes, then derives everything else (fluorescence, carbon flux) from that solved state.

One LUT row: leaf biochemistry + canopy structure + soil + meteorology
                           |
                           v
           get_fluspect_cx_scope()  (leaf optics + fluorescence matrices)
                           |
                           v
                      run_rtmo()  (optical TOC BRDF)
                           |
                           v
                 ebal()  <-----------------------+
                 (iterates leaf/soil temperature   |
                  until flux budget closes,         |
                  calling get_biochemical() at       get_biochemical()
                  each candidate temperature)  ------+  (photosynthesis,
                           |                             fluorescence yield)
                           v
                 rtmf() / rtmz()  (optional: canopy fluorescence, zeaxanthin)
                           |
                           v
       Reflectance + SIF + leaf/soil temperature + carbon/water flux
import csv
from scopeinpython import ScopeOptions, get_scope
with open("SCOPEinR/inst/input/LUT_input.csv", newline="") as f:
    row = next(csv.DictReader(f))
res = get_scope(row, options=ScopeOptions(k_maxit=100, maxEBer=1.0))
Full SCOPE TOC reflectance and emitted SIF spectrum, real output of the code above

Real output of the single get_scope() call above: TOC reflectance (left) and the emitted SIF spectrum (right) – the same call 06. SCOPE reads photosynthesis/temperature from too.

Full version: Full SCOPE run: energy balance + fluorescence (scopeinpython).

Try it yourself

  • Feed pipeline 3’s soil.rsoil_wet (MARMIT) directly as rsoil into pipeline 1’s foursail() call, instead of the flat baseline – a hybrid chain not shown explicitly above.

  • Swap leaf_model="PROSPECT-D" for "PROSPECT-PRO" in pipeline 1 or 2 and confirm the result barely changes (03. Leaf Radiative Transfer Models already showed why).

  • In pipeline 4, check res.rtmf – is fluorescence actually returned for this LUT row, or None?

Common mistakes

  • Pipelines 1-3 all need a 2101-element rsoil/soil spectrum matching the 400-2500nm/1nm grid – mixing up a MARMIT output’s length with a hand-built flat array is a common source of shape errors.

  • Pipeline 3’s SPART soil (BSM) and pipeline 3’s own MARMIT step are independent – MARMIT’s wetted spectrum isn’t automatically used unless you explicitly pass it in.

  • Pipeline 4 (SCOPE) is far more expensive per call than 1-3 – don’t substitute it into a workflow that only needs plain reflectance.

Next

08. Sensor Simulation – resampling any of the reflectance spectra above onto a real sensor’s bands.


Using R? -> ToolsRTM Tutorial 04: Comparing Models