Skip to content

10 - Leaf optics

A leaf's reflectance and transmittance spectra determine how vegetation looks in optical images and how much light a leaf absorbs for photosynthesis. LESS offers three leaf optical properties:

Property Input Use
Prospect Leaf biochemistry General optical simulation
Fluspect Biochemistry and fluorescence quantum yield When chlorophyll fluorescence is needed
MeasuredSpectrum Measured reflectance and transmittance When you have measured leaf spectra

They can be assigned directly to mesh leaves or used as the representative leaf inside statistical vegetation (chapter 12).

PROSPECT

PROSPECT treats a leaf as a stack of plates and computes reflectance and transmittance from 400 to 2500 nm from the pigment, water and dry-matter contents:

import less

leaf = less.Prospect(cab=45, car=10, canth=0, cbrown=0, cw=0.012, cm=0.008, N=1.5)
Parameter Meaning Typical range Unit
cab Chlorophyll a+b 10–80 µg cm⁻²
car Carotenoids 5–20 µg cm⁻²
canth Anthocyanins 0–40 µg cm⁻²
cbrown Brown pigments 0–1 —
cw Equivalent water thickness 0.005–0.03 cm
cm Dry matter 0.003–0.015 g cm⁻²
N Leaf structure parameter 1.0–3.0 —

Where each parameter matters most:

Wavelengths Main parameters
400–500 nm Strong absorption by cab and car
500–600 nm Weaker cab absorption, the green peak
600–700 nm cab; canth absorbs green and red
700–750 nm (red edge) cab and N set the position and slope of the red edge
750–1300 nm N controls scattering in the mesophyll; cab has almost no effect
1300–2500 nm Water absorption bands (cw) and cm

Some typical leaf states:

green = less.Prospect(cab=45, car=10, cw=0.012, cm=0.008, N=1.5)
yellow = less.Prospect(cab=5, car=15, cbrown=0.3, cw=0.008, cm=0.010, N=2.0)
red = less.Prospect(cab=3, car=5, canth=30, cbrown=0.15, cw=0.010, cm=0.009, N=1.8)

Compute and compare their spectra with evaluate():

import numpy as np
import matplotlib.pyplot as plt

wavelengths = np.arange(400, 2501, 5)
fig, ax = plt.subplots(figsize=(7, 4))
for name, model in [("green", green), ("yellow", yellow), ("red", red)]:
    ax.plot(wavelengths, model.evaluate(wavelengths)["reflectance"], label=name)
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("Reflectance")
ax.legend()
fig.savefig("leaf_spectra.png", dpi=150, bbox_inches="tight")

FLUSPECT

FLUSPECT extends PROSPECT with chlorophyll fluorescence. The parameters are nearly the same (anthocyanins are called can), plus the fluorescence quantum yield fqe:

fluorescent_leaf = less.Fluspect(cab=45, car=10, cw=0.012, cm=0.006, N=1.5, fqe=0.012)
print(fluorescent_leaf.evaluate([550, 850]))
  • a single fqe value gives a fixed fluorescence yield;
  • fqe=(0.002, 0.01) gives separate yields for photosystems I and II, so their fluorescence can be computed separately;
  • fqe="dynamic" lets the photosynthesis model set the yield.

When fluorescence is not needed, both models serve equally well for optical simulation. Fluorescence calculations and imaging are covered in chapter 27 and chapter 33.

Measured spectra

For measured leaf spectra use MeasuredSpectrum:

measured = less.MeasuredSpectrum(
    wavelengths=[400, 500, 550, 650, 700, 750, 850, 1650, 2200],
    reflectance=[0.05, 0.07, 0.13, 0.07, 0.25, 0.45, 0.48, 0.32, 0.15],
    back_reflectance=[0.07, 0.09, 0.15, 0.09, 0.28, 0.46, 0.49, 0.33, 0.17],
    transmittance=[0.01, 0.04, 0.10, 0.03, 0.20, 0.42, 0.45, 0.35, 0.12],
)
  • reflectance is the reflectance of the leaf's front face and back_reflectance that of the back face; without it both faces are the same;
  • without transmittance the leaf is opaque;
  • spectra are linearly interpolated to the simulation wavelengths.

The front and back faces follow the orientation of the triangles (see chapter 5).

A measured spectrum does not say how much light each pigment absorbs. For photosynthesis, give a pigment partition model so that LESS can estimate the part absorbed by chlorophyll:

leaf_for_photosynthesis = less.MeasuredSpectrum(
    wavelengths=[400.0, 550.0, 700.0],
    reflectance=[0.08, 0.12, 0.18],
    transmittance=[0.04, 0.08, 0.12],
    absorption_partition=less.ProspectPartition(cab=45.0),
)

Leaves in the spectral library

Leaf spectra from the built-in library can be used directly:

birch = less.SpectrumDB("birch_leaf_green")
larch = less.SpectrumDB("larch_leaf_green")

Using leaf models in a scene

tree = less.Object("ash", mesh=less.asset_path("FREX.obj"))
tree.set_property("leaves", green)
tree.set_property("stem_branch", less.Lambertian(reflectance=0.08))

scene = less.Scene()
scene.size = 20.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.12))
scene.illumination = less.Illumination(
    source=less.Sun(zenith=35, azimuth=150), atmosphere=less.NoAtmosphere())
scene.add(tree, positions=[[10, 10, 0]])

sensor = less.OpticalImager(less.Orthographic(image_size=128),
                            bands=[650, 550, 450], quality=32)
summer = scene.simulate(sensor)

tree.set_property("leaves", red)
autumn = scene.simulate(sensor)

Next