scopeinpython.biochemical

Leaf-level Farquhar/Collatz photosynthesis + van der Tol et al. (2014) fluorescence yield, given an assumed leaf micro-environment. Direct port of SCOPEinR/R/biochemical.R (get.biochemical) and its helpers in Biochemical_functions.R. This is the piece SCOPE’s (unported) energy- balance iteration calls repeatedly to get eta at each candidate leaf temperature – it does not itself solve for temperature.

Warning

Type='C4' with temp_correction=False reproduces a real crash in the R source: Vcmax/Rd are never assigned in that branch combination of biochemical.R (only the tempcor==1 C4 branch and a separate C3-only block set them). Not worked around here.

Where this fits

This is a pipeline-internal component, not something you typically call directly: scopeinpython.scope.get_scope() calls scopeinpython.ebal.ebal(), which calls this once per canopy layer, per iteration, at each candidate leaf temperature, to get the fluorescence yield eta and net photosynthesis at that temperature. Most users should just call get_scope() – see scopeinpython.scope for a full end-to-end example.

get_scope()  ->  ebal()  ->  get_biochemical()  [per layer, per iteration]
                                Ci-solver (Ball-Berry) + Farquhar/Collatz
                                -> An (net photosynthesis), eta (SIF yield)

Leaf biochemistry: Farquhar-von Caemmerer-Berry photosynthesis (Collatz C4 variant) coupled with a Ball-Berry/Leuning stomatal-conductance model and the van der Tol et al. (2014) fluorescence yield model.

Direct port of SCOPEinR/R/biochemical.R (get.biochemical) and its helpers in SCOPEinR/R/Biochemical_functions.R. This is the leaf-level photosynthesis+fluorescence solver called inside SCOPE’s energy-balance iteration (ebal.R, not ported) to get A/rcw/eta at a given leaf temperature – it does not itself iterate on temperature, so it can be called and verified standalone given an assumed leaf micro-environment (matching how the R function itself works: data.meteo$Temp is an input, not something this function solves for).

Only the tempcor=1 (temperature-corrected) C3 path and the BallBerry0 != 0 (iterative Ci) path are ported in full generality here; the BallBerry0 == 0 closed-form Ci path and the C4/no-temperature- correction paths are ported too but exercised less by the reference tests – see python/README.md.

class scopeinpython.biochemical.LeafBio(Type, stressfactor, Vcmax25, BallBerry0, BallBerrySlope, Rdparam, Kn0, Knalpha, Knbeta, g_m=None, TDP=<factory>)[source]

Bases: object

Leaf biochemical parameters (data.leafbio in R).

Parameters:
  • Type (str)

  • stressfactor (float)

  • Vcmax25 (float)

  • BallBerry0 (float)

  • BallBerrySlope (float)

  • Rdparam (float)

  • Kn0 (float)

  • Knalpha (float)

  • Knbeta (float)

  • g_m (float | None)

  • TDP (dict)

Type: str
stressfactor: float
Vcmax25: float
BallBerry0: float
BallBerrySlope: float
Rdparam: float
Kn0: float
Knalpha: float
Knbeta: float
g_m: float | None = None
TDP: dict
class scopeinpython.biochemical.MeteoLeaf(Q, Cs, Temp, eb, Oa, p)[source]

Bases: object

Leaf micro-environment (data.meteo in R).

Parameters:
  • Q (float)

  • Cs (float)

  • Temp (float)

  • eb (float)

  • Oa (float)

  • p (float)

Q: float
Cs: float
Temp: float
eb: float
Oa: float
p: float
class scopeinpython.biochemical.BiochemResult(A: 'np.ndarray', Ci: 'np.ndarray', Cc: 'np.ndarray | None', rcw: 'np.ndarray', gs: 'np.ndarray', RH: 'np.ndarray', Vcmax: 'np.ndarray', Rd: 'np.ndarray', Ja: 'np.ndarray', ps: 'np.ndarray', ps_rel: 'np.ndarray', Kd: 'np.ndarray', Kn: 'np.ndarray', NPQ: 'np.ndarray', Kf: 'float', Kp0: 'float', Kp: 'np.ndarray', eta: 'np.ndarray', qE: 'np.ndarray', fs: 'np.ndarray', SIF: 'np.ndarray', fo0: 'np.ndarray', fm0: 'np.ndarray', fo: 'np.ndarray', fm: 'np.ndarray', qQ: 'np.ndarray', Phi_N: 'np.ndarray')[source]

Bases: object

Parameters:
A: ndarray
Ci: ndarray
Cc: ndarray | None
rcw: ndarray
gs: ndarray
RH: ndarray
Vcmax: ndarray
Rd: ndarray
Ja: ndarray
ps: ndarray
ps_rel: ndarray
Kd: ndarray
Kn: ndarray
NPQ: ndarray
Kf: float
Kp0: float
Kp: ndarray
eta: ndarray
qE: ndarray
fs: ndarray
SIF: ndarray
fo0: ndarray
fm0: ndarray
fo: ndarray
fm: ndarray
qQ: ndarray
Phi_N: ndarray
scopeinpython.biochemical.sel_root(a, b, c, dsign)[source]

Root of least magnitude of a*x^2 + b*x + c = 0. Direct port of SCOPEinR::sel_root. dsign: -1/0 picks the smaller root, +1 the larger (per quadratic-formula sign convention on the discriminant).

scopeinpython.biochemical.get_gs_fun(Cs, RH, A, BallBerrySlope, BallBerry0)[source]

Ball-Berry stomatal conductance. Direct port of SCOPEinR::get.gsFun.

scopeinpython.biochemical.get_ball_berry(Cs, RH, A, BallBerrySlope, BallBerry0, minCi, Ci_input=None)[source]

Ball-Berry/Leuning Ci and (optionally) gs. Direct port of SCOPEinR::get.BallBerry. Returns (gs, Ci) (gs is None when not computable, matching R’s NULL).

scopeinpython.biochemical.get_temperature_function_c3(Tref, R, Temp, deltaHa)[source]

Arrhenius temperature correction factor. Direct port of SCOPEinR::get.temperature.functionC3.

scopeinpython.biochemical.get_high_temp_inhibtion_c3(Tref, R, T, deltaS, deltaHd)[source]

High-temperature inhibition factor. Direct port of SCOPEinR::get.high.temp.inhibtionC3.

scopeinpython.biochemical.get_fluorescence_model(ps, x, Kp, Kf, Kd, Knparams)[source]

van der Tol et al. (2014) fluorescence-yield model. Direct port of SCOPEinR::get.Fluorescence.model. Returns a dict with eta, qE, qQ, fs, fo, fm, fo0, fm0, Kn.

scopeinpython.biochemical.get_ci_next(Ci_in, Cs, RH, minCi, BallBerrySlope, BallBerry0, A_fun, ppm2bar)[source]

Ci fixed-point residual (Ball-Berry Ci minus guessed Ci_in), used as the objective for the Brent root-finder in get_biochemical(). Direct port of SCOPEinR::get.Ci.next.

scopeinpython.biochemical.get_compute_a(Ci, Type, g_m, Vs_C3, MM_consts, Rd, Vcmax, Gamma_star, Je, effcon, atheta, kpepcase)[source]

Farquhar (C3) / Collatz (C4) net CO2 assimilation. Direct port of SCOPEinR::get.computeA. Returns a dict with A, Ag, Vc, Vs, Ve, CO2_per_electron (fcount – a debug iteration counter via R’s <<- – is not reproduced; it has no effect on the physics).

scopeinpython.biochemical.get_biochemical(leafbio, meteo, temp_correction, fV=1.0)[source]

Leaf-level photosynthesis (Farquhar/Collatz) + fluorescence yield (van der Tol et al. 2014). Direct port of SCOPEinR::get.biochemical.

Parameters:
  • leafbio (LeafBio)

  • meteo (MeteoLeaf)

  • temp_correction (bool) – Whether to apply temperature correction to Vcmax/Rd/Kc/Ko/Gamma_star (matches R’s data.opts row-7 tempcor flag). If True, leafbio.TDP must contain the relevant temperature-dependence parameters (C3: delHaV/delSV/delHdV/delHaR/delSR/ delHdR/delHaKc/delHaKo/delHaT; C4: Q10/s1-s6).

  • fV (float, default 1.0) – Scaling factor on Vcmax25 (e.g. a canopy N/Vcmax profile factor).

Return type:

BiochemResult