PhoTorch is a robust and generalized photosynthesis biochemical model fitting package based on PyTorch. Read more about PhoTorch in our paper: https://arxiv.org/abs/2501.15484.
Note: The latest version 1.3.0 includes changes to the file structure and function names within the package.
Currently, the package includes the Farquhar, von Caemmerer, and Berry (FvCB) model and stomatal conductance models including Buckley Mott Farquhar (BMF), Medlyn (MED), and Ball Woodrow Berry (BWB) versions. The Ball Berry Leuning (BBL) stomatal conductance model and the PROSPECT models are under development.
pip install torch
pip install numpy
pip install scipy
pip install pandas
Next, download all the files and directories, and try running the examples in the testphotorch.py file!
Create a python file in the PhoTorch directory and import necessary packages.
import fvcb
import pandas as pd
import torch
Load the example CSV file. The loaded data frame should have columns with titles 'CurveID', 'FittingGroup', 'Ci', 'A', 'Qin', and 'Tleaf'. Each A/Ci curve should have a unique 'CurveID'. If no 'Qin' and 'Tleaf' are available, it will be automatically set to 2000 and 25, respectively.
The data to be loaded should be:
CurveID | FittingGroup | Ci | A | Qin | Tleaf |
---|---|---|---|---|---|
1 | 1 | 200 | 20 | 2000 | 25 |
1 | 1 | 400 | 30 | 2000 | 25 |
1 | 1 | 600 | 40 | 2000 | 25 |
2 | 1 | 200 | 25 | 2000 | 30 |
2 | 1 | 400 | 35 | 2000 | 30 |
2 | 1 | 700 | 55 | 2000 | 30 |
dftest = pd.read_csv('exampledata/dfMAGIC043_lr.csv')
# remove the rows with negative A values
dftest = dftest[dftest['A'] > 0]
Then, specify the ID of the light response curve. If there is no light response curve in the dataset, ignore it (default is None).
# Specify the list of light response curve IDs, if no light response curve, input "lightresp_id = None" or ignore it.
lcd = fvcb.initLicordata(dftest, preprocess=True, lightresp_id = [118])
Default device is 'cpu'. If you have an NVIDIA GPU, set 'device_fit' to 'cuda' and execute the 'lcd.todevice(torch.device(device_fit))' line.
device_fit = 'cpu'
lcd.todevice(torch.device(device_fit)) # if device is cuda, then execute this line
If 'onefit' is set to 'True', all curves in a fitting group will share the same set of Vcmax25, Jmax25, TPU25, and Rd25. Otherwise, each curve will have its own set of these four main parameters but share the same light and temperature response parameters for the fitting group.
If no light response curve is specified, set 'LightResp_type' to 0.
LightResp_type 0: J is equal to Jmax.
LightResp_type 1: using equation
LightResp_type 2: using equation
TempResp_type 0: Vcmax, Jmax, TPU, and Rd are equal to the Vcmax25, Jmax25, TPU25, and Rd25, respectively.
TempResp_type 1: using equation
TempResp_type 2: using equation
# initialize the model
fvcbm = fvcb.model(lcd, LightResp_type = 2, TempResp_type = 2, onefit = False)
fitRd: option to fit
fitRdratio: option to fit
fitag: option to fit
fitKc: option to fit
fitKo: option to fit
fitgamma: option to fit
fitgm: option to fit
fvcbm = fvcb.model(lcd, LightResp_type = 0, TempResp_type = 1, onefit = False, fitRd = True, fitRdratio = False, fitag = False, fitgm= False, fitgamma=False, fitKo=False, fitKc=False, allparams=allparams)
allparams = fvcb.allparameters()
allparams.dHa_Vcmax = torch.tensor(40.0).to(device_fit) # If the device is cuda, then execute ".to(device_fit)"
fvcbm = fvcb.model(lcd, LightResp_type = 0, TempResp_type = 1, onefit = False, fitag = False, fitgm= False, fitgamma=False, fitKo=False, fitKc=False, allparams=allparams)
fitresult = fvcb.fit(fvcbm, learn_rate= 0.08, maxiteration = 20000, minloss= 1, recordweightsTF=False)
fvcbm = fitresult.model
The main parameters are stored in the 'fvcbm'. The temperature response parameters are in 'fvcbm.TempResponse', just like the light response parameters.
id_index = 0
id = int(lcd.IDs[id_index]) # target curve ID
fg_index = int(lcd.FGs_idx[id_index]) # index of the corresponding fitting group
if not fvcbm.onefit:
Vcmax25_id = fvcbm.Vcmax25[id_index]
Jmax25_id = fvcbm.Jmax25[id_index]
else:
Vcmax25_id = fvcbm.Vcmax25[fg_index]
Jmax25_id = fvcbm.Jmax25[fg_index]
dHa_Vcmax_id = fvcbm.TempResponse.dHa_Vcmax[fg_index]
alpha_id = fvcbm.LightResponse.alpha[fg_index]
A, Ac, Aj, Ap = fvcbm()
id_index = 0
id = lcd.IDs[id_index]
indices_id = lcd.getIndicesbyID(id)
A_id = A[indices_id]
Ac_id = Ac[indices_id]
A_id_mea, Ci_id, Q_id, Tlf_id = lcd.getDatabyID(lcd.IDs[id_index])
Three stomatal conductance model is currently available: Buckley Mott Farquhar (BMF), Medlyn (MED), and Ball Woodrow Berry (BWB). The Ball Berry Leuning (BBL) model is under development. More details about these four models can be found at: https://baileylab.ucdavis.edu/software/helios/_stomatal_doc.html.
Create a python file in the PhoTorch directory and import necessary packages.
import stomatal
import pandas as pd
import torch
The data to be loaded should be:
CurveID | gsw | VPDleaf | A | Qin | Tleaf | RHcham |
---|---|---|---|---|---|---|
0 | 0.34 | 11.32 | 55 | 2000 | 21.81 | 21.0 |
0 | 0.34 | 18.33 | 55 | 2000 | 22.71 | 30.02 |
0 | 0.35 | 29.57 | 51 | 2000 | 20.02 | 38.01 |
0 | 0.38 | 15.4 | 54 | 2000 | 22.6 | 26.99 |
0 | 0.32 | 15.44 | 54 | 1200 | 19.97 | 27.0 |
1 | 0.23 | 29.03 | 49 | 2000 | 17.93 | 35.92 |
1 | 0.29 | 20.51 | 50 | 2000 | 20.51 | 29.96 |
1 | 0.28 | 11.77 | 49 | 2000 | 18.61 | 19.99 |
'A' is not necessary for BMF model.
datasc = pd.read_csv('exampledata/steadystate_stomatalconductance.csv')
scd = stomatal.initscdata(datasc)
Initialize the BMF model and fit the parameters Emerson effect (Em), quantum yield of electron transport (i0), curvature factor (k), and intercept (b).
scm = stomatal.BMF(scd)
#scm = stomatal.BWB(scd)
#scm = stomatal.MED(scd)
fitresult = stomatal.fit(scm, learnrate = 0.5, maxiteration =20000)
scm = fitresult.model
gsw = scm()
gsw_mea = scd.gsw
id_index = 0
id = scd.IDs[id_index]
indices_id = scd.getIndicesbyID(id)
gsw_id = gsw[indices_id]
id_index = 0
id = int(scd.IDs[id_index])
Em_id = scm.Em[id_index]
i0_id = scm.i0[id_index]
k_id = scm.k[id_index]
b_id = scm.b[id_index]
The PROSPECT-X model is under development.