![]() |
0.1.39
|
| Dependencies | None |
|---|---|
| Python Import | from pyhelios import LeafOptics |
| Main Class | LeafOptics |
| Dependencies | None |
|---|---|
| Platforms | Windows, Linux, macOS |
| GPU | Not required |
This plug-in computes leaf spectral reflectance and transmittance using the PROSPECT family of models. The implementation follows the PROSPECT–PRO formulation with eight absorbing constituents and a structural parameter \(N\) that represents the number of elementary layers in the leaf. Output spectra cover the range 400–2500 nm in 1 nm steps.
For each wavelength \(\lambda\) the absorption coefficient of a single layer is calculated as
\[ k(\lambda)=\frac{C_{ab}a_{ab}(\lambda)+C_{ar}a_{ar}(\lambda)+C_{an}a_{an}(\lambda)+C_{br}a_{br}(\lambda) +C_{w}a_{w}(\lambda)+C_{m}a_{m}(\lambda)+C_{p}a_{p}(\lambda)+C_{c}a_{c}(\lambda)}{N}, \]
where the \(C\) variables are the constituent masses per area and the \(a(\lambda)\) terms are the specific absorption coefficients loaded from the internal spectral library. Fresnel equations are used to compute surface reflectance and a radiative transfer solution gives the total leaf reflectance and transmittance.
| Constructors |
|---|
| LeafOptics |
The constructor simply stores a pointer to the Helios context and loads the spectral library data required by the model.
The LeafOpticsProperties structure stores the biochemical inputs to the model.
| Member | Units | Description | Default Value |
|---|---|---|---|
| numberlayers | unitless | Leaf structure parameter \(N\) | 1.5 |
| brownpigments | unitless | Mass of brown pigments | 0 |
| chlorophyllcontent | \(\mu\)g cm \(^{-2}\) | Total chlorophyll | 30 |
| carotenoidcontent | \(\mu\)g cm \(^{-2}\) | Total carotenoids | 7 |
| anthocyancontent | \(\mu\)g cm \(^{-2}\) | Anthocyanins | 1 |
| watermass | g cm \(^{-2}\) | Equivalent water thickness | 0.015 |
| drymass | g cm \(^{-2}\) | Dry matter mass | 0.09 |
| protein | g cm \(^{-2}\) | Protein mass | 0 |
| carbonconstituents | g cm \(^{-2}\) | Cellulose and other carbon compounds | 0 |
| V2Z | unitless, [0,1] | Violaxanthin↔zeaxanthin de-epoxidation state. Used by the radiation plugin's solar-induced fluorescence (SIF) pipeline; ignored by PROSPECT. | 0 |
| fqe | unitless | Intrinsic fluorescence quantum-efficiency scalar applied on top of the per-leaf Phi_F at SIF emission time. Ignored by PROSPECT. | 1 |
SIF parameters (helios-core v1.3.72+):
V2Zandfqeare inert for the pure reflectance/transmittance calculation. They are written tofluspect_biochem_<label>global data on everyrun()so the radiation plugin's SIF camera can look them up per primitive when building Fluspect-B emission kernels.
As of helios-core 1.3.80, the model validates its inputs before computing a spectrum and raises LeafOpticsError for values that are physically meaningless:
| Parameter | Requirement | Reason |
|---|---|---|
| numberlayers | \(N \ge 1\) | \(N\) counts the elementary layers making up the leaf. \(N < 1\) makes the Stokes exponent \(N-1\) negative, which inverts the layer stack, and \(N = 0\) divides by zero when computing the per-layer absorption coefficient. Use \(N = 1\) for a single compact layer. |
| All constituent contents | \(\ge 0\) | Constituent contents are masses (or concentrations) per unit leaf area. A negative value would contribute negative absorption. Set a constituent to zero to disable it. |
The constituent contents subject to the non-negativity check are chlorophyllcontent, carotenoidcontent, anthocyancontent, brownpigments, watermass, drymass, protein, and carbonconstituents.
Validation applies to every entry point that computes a spectrum, including getLeafSpectra() and run().
Note that the SIF fields V2Z and fqe are not validated, since they are inert for the PROSPECT reflectance/transmittance calculation.
If drymass, protein, and carbonconstituents are all zero, the leaf has no dry matter at all. This is not an error — the model still runs and returns a spectrum — but it is almost always a mistake, so a warning is printed unless messages have been disabled with disableMessages(). Set at least one dry-matter parameter to a non-zero value to suppress it.
Note that a leaf with no dry matter and no water and no pigments is perfectly non-absorbing at every wavelength. This is handled correctly (the elementary-layer transmittance is 1, so the leaf reflects and transmits all incident radiation with no absorption), but such a leaf is not physically meaningful.
The radiation plugin includes a Fluspect-B / van der Tol pipeline for simulating solar-induced chlorophyll fluorescence (SIF) — see SIF camera in the radiation docs. LeafOptics is the canonical way to author the per-leaf biochemistry that pipeline needs.
Every run(uuids, props, label) call emits one extra global-data entry and one extra primitive-data label, in addition to the reflectance and transmittance outputs:
| Output | Type | Description |
|---|---|---|
Global data fluspect_biochem_<label> | list of 11 floats | Fluspect-B biochemistry vector in fixed field order: [Cab, Cca, Cw, Cdm, Cs, Cant, Cp, Cbc, N, V2Z, fqe]. |
Primitive data fluspect_spectrum | string | Stamped on every UUID — value is "fluspect_biochem_<label>". The radiation plugin reads this per primitive to identify fluorescing leaves; primitives without it are silently treated as non-fluorescing (stems, soil, etc.). |
The biochemistry vector is keyed by label, so leaves sharing a spectrum label share a single Fluspect-B kernel in the radiation plugin's per-label kernel cache. This is automatic — no extra API to enable. A cached kernel is recomputed whenever the biochemistry stored under its label changes (for example when run() is called again with the same label and new properties), and SIF follows leaves that are moved to a different label.
LeafOpticsProperties Member | Fluspect-B Field | Notes |
|---|---|---|
chlorophyllcontent | Cab | Drives the dominant red-edge absorption that emits at 685 nm. |
carotenoidcontent | Cca | Combined with V2Z controls absorption in the 400–550 nm excitation range. |
watermass | Cw | Equivalent water thickness (cm). |
drymass | Cdm | PROSPECT-D dry matter (g/cm²). Set to 0 in PROSPECT-PRO mode. |
brownpigments | Cs | Senescence/brown-pigment content. |
anthocyancontent | Cant | |
protein | Cp | PROSPECT-PRO only. |
carbonconstituents | Cbc | PROSPECT-PRO only. |
numberlayers | N | Mesophyll layer parameter. |
V2Z | V2Z | SIF-only field; ignored by PROSPECT. |
fqe | fqe | SIF-only field; ignored by PROSPECT. |
Note: the reverse path
getPropertiesFromSpectrum()does not currently populateV2Zorfqeas primitive data — those fields are SIF-only and are read by the radiation plugin directly from thefluspect_biochem_*global-data vector.
The model can be run to produce global spectra and, optionally, assign those spectra and optical properties to a set of primitives.
This command creates global data labeled "leaf_reflectivity_example" and "leaf_transmissivity_example" containing the computed spectra. The spectra labels are also stored as primitive data for the specified UUIDs together with the biochemical property values.
The LeafOptics class includes a built-in species library that provides pre-configured optical properties for common plant species. This simplifies model usage by eliminating the need to manually specify biochemical parameters.
Use the getPropertiesFromLibrary() method to return a LeafOpticsProperties structure with species-specific values:
The method returns a LeafOpticsProperties structure with the nine PROSPECT biochemistry parameters populated (numberlayers, chlorophyllcontent, carotenoidcontent, anthocyancontent, brownpigments, watermass, drymass, protein, carbonconstituents). The optional Fluspect-B SIF fields (V2Z, fqe) keep their dataclass defaults (0.0 and 1.0); set them on the returned object if you intend to use the radiation plugin's SIF camera.
The library contains PROSPECT-D parameters fitted to measured leaf spectra by robust optimization. Most species are fitted to LOPEX93 spectral library samples; "common_bean" and "cowpea" are fitted to spectra from the GEMINI field experiments. All species use PROSPECT-D mode (drymass > 0, protein = 0, carbonconstituents = 0).
| Species Label | Scientific Name | N | Cab (µg/cm²) | Car (µg/cm²) | Ant (µg/cm²) | Cbrown | Cw (g/cm²) | Cm (g/cm²) | R² | Source |
|---|---|---|---|---|---|---|---|---|---|---|
| "default" | - | 1.50 | 30.0 | 7.00 | 1.00 | 0.000 | 0.0150 | 0.0900 | - | Original Helios defaults |
| "garden_lettuce" | Lactuca sativa L. | 2.01 | 30.3 | 6.99 | 1.36 | 0.107 | 0.0282 | 0.0053 | 0.993 | LOPEX93 sample 0021 |
| "alfalfa" | Medicago sativa L. | 2.01 | 43.6 | 10.3 | 1.34 | 0.000 | 0.0190 | 0.0047 | 0.994 | LOPEX93 sample 0036 |
| "corn" | Zea mays L. | 1.59 | 22.9 | 3.97 | 0.00 | 0.727 | 0.0150 | 0.0044 | 0.975 | LOPEX93 sample 0041 |
| "sunflower" | Helianthus annuus L. | 1.76 | 54.1 | 12.9 | 1.75 | 0.011 | 0.0186 | 0.0064 | 0.995 | LOPEX93 sample 0081 |
| "english_walnut" | Juglans regia L. | 1.56 | 55.9 | 12.5 | 1.74 | 0.000 | 0.0128 | 0.0058 | 0.994 | LOPEX93 sample 0091 |
| "rice" | Oryza sativa L. | 1.67 | 37.2 | 10.0 | 0.00 | 0.028 | 0.0101 | 0.0048 | 0.998 | LOPEX93 sample 0106 |
| "soybean" | Glycine max L. | 1.54 | 46.4 | 12.1 | 0.65 | 0.000 | 0.0101 | 0.0029 | 0.997 | LOPEX93 sample 0116 |
| "wine_grape" | Vitis vinifera L. | 1.43 | 50.9 | 12.5 | 1.44 | 0.080 | 0.0109 | 0.0060 | 0.997 | LOPEX93 sample 0276 |
| "tomato" | Lycopersicum esculentum | 1.40 | 48.3 | 11.6 | 1.45 | 0.000 | 0.0156 | 0.0026 | 0.997 | LOPEX93 sample 0316 |
| "common_bean" | Phaseolus vulgaris L. | 1.44 | 42.4 | 15.6 | 0.84 | 0.000 | 0.0150 | 0.0020 | - | GEMINI field experiments, day 35 |
| "cowpea" | Vigna unguiculata L. | 1.23 | 61.5 | 25.6 | 2.52 | 0.000 | 0.0221 | 0.0011 | - | GEMINI field experiments, day 48 |
Notes:
If an unknown species name is provided, the method:
This ensures that code continues to run even if a species name is misspelled or not yet in the library.
To add new species to the library, edit the species library data in the Helios C++ source code at plugins/leafoptics/src/LeafOptics.cpp. The library supports both PROSPECT-D mode (using drymass) and PROSPECT-PRO mode (using protein and carbonconstituents). Contact the PyHelios developers to request new species additions.
The LeafOptics class maintains an internal mapping between spectrum labels and the PROSPECT parameters used to generate them. This allows users to retrieve the original model parameters from primitives that have been assigned LeafOptics-generated spectra.
The getPropertiesFromSpectrum() method queries primitives for their "reflectivity_spectrum" primitive data and, if it matches a spectrum generated by the LeafOptics instance, assigns the corresponding PROSPECT parameters as primitive data:
For each UUID passed to getPropertiesFromSpectrum():
The method assigns primitive data using the same labels as setProperties():
| Primitive Data Label | Parameter | Condition |
|---|---|---|
| "chlorophyll" | chlorophyllcontent | Always |
| "carotenoid" | carotenoidcontent | Always |
| "anthocyanin" | anthocyancontent | Always |
| "brown" | brownpigments | If brownpigments > 0 |
| "water" | watermass | Always |
| "drymass" | drymass | If drymass > 0 (PROSPECT-D mode) |
| "protein" | protein | If drymass = 0 (PROSPECT-PRO mode) |
| "cellulose" | carbonconstituents | If drymass = 0 (PROSPECT-PRO mode) |
By default, the LeafOptics plug-in writes no leaf constituent concentrations to primitive data. Output is opt-in: call optionalOutputPrimitiveData() with the desired labels before calling run(), and only those labels will be written.
| Primitive Data Label | Units | Data Type | Description |
|---|---|---|---|
| chlorophyll | \(\mu\)g cm \(^{-2}\) | float | Total chlorophyll content |
| carotenoid | \(\mu\)g cm \(^{-2}\) | float | Total carotenoid content |
| anthocyanin | \(\mu\)g cm \(^{-2}\) | float | Anthocyanin content |
| brown | unitless | float | Brown pigment content (only written if value > 0) |
| water | g cm \(^{-2}\) | float | Equivalent water thickness |
| drymass | g cm \(^{-2}\) | float | Dry matter mass (PROSPECT-D mode only, when drymass > 0) |
| protein | g cm \(^{-2}\) | float | Protein mass (PROSPECT-PRO mode only, when drymass = 0) |
| cellulose | g cm \(^{-2}\) | float | Cellulose and carbon compounds (PROSPECT-PRO mode only, when drymass = 0) |
Instead of specifying pigments directly, LeafOptics can derive each leaf's chlorophyll and carotenoid content from its nitrogen content. Pass a LeafOpticsProperties_Nauto to run() without a label. The plug-in groups the primitives by parent object, reads the "leaf_nitrogen_gN_m2" object data (g N m \(^{-2}\), normally written by the PlantArchitecture nitrogen model) from each object, and computes:
f_photosynthetic \(\times\) N_to_Cab_coefficient, clamped to [5, 80]Car_to_Cab_ratioAll other PROSPECT parameters are fixed at the values in LeafOpticsProperties_Nauto. To limit the number of spectra, leaves are grouped into num_bins bins spaced evenly across the nitrogen range; each bin gets one spectrum stored as global data leaf_reflectivity_Nauto_<i>, leaf_transmissivity_Nauto_<i> and fluspect_biochem_Nauto_<i>, and every primitive of an object is assigned its bin's spectrum.
| Member | Default | Description |
|---|---|---|
f_photosynthetic | 0.50 | Fraction of leaf N in photosynthetic machinery [0-1] |
N_to_Cab_coefficient | 0.40 | Empirical N-to-chlorophyll coefficient |
Car_to_Cab_ratio | 0.25 | Carotenoid to chlorophyll ratio |
numberlayers, anthocyancontent, brownpigments, watermass, drymass, protein, carbonconstituents | 1.5, 1.0, 0.0, 0.015, 0.006, 0.0, 0.0 | Fixed PROSPECT parameters (note the lower drymass default than LeafOpticsProperties) |
V2Z, fqe | 0.0, 1.0 | SIF parameters, fixed across bins |
num_bins | 20 | Number of spectrum bins (one bin if all leaves share the same nitrogen) |
reassignment_threshold | 0.0 | Relative N change (fraction of bin centre) required before reassignment; 0 disables it |
min_reassignment_change | 0.05 | Absolute N change (g m \(^{-2}\)) required before reassignment; the new bin must also be closer by half this amount |
Behavior notes:
run() creates the bins and fixes the parameters; parameters passed on later calls are ignored. Later calls track added and removed primitives, reassign leaves whose nitrogen changed, and rebuild the bins if any leaf's nitrogen moves outside their range.updateNitrogenBasedSpectra() is a faster update for an unchanged primitive set; it never rebuilds bins, and raises LeafOpticsError if nitrogen mode has not been started."leaf_nitrogen_gN_m2" data raises LeafOpticsError. Primitives that are not part of a compound object are skipped with a warning.