2. Building a Model¶
2.1. Building form Metabolite and Reaction¶
A metabolic network consists of metabolites and their reactions, which can be constructed using the Metabolite and Reaction constructor, respectively. For example, let’s construct the reaction PPS:
ATP\(_c\) + H2O\(_c\) + Pyr\(_c\) -> AMP\(c\) + 2.0H\(_c^+\) + PEP\(_c\) + Pi\(c\)
by phosphoenolpyruvate synthase:
[1]:
from etfba import Metabolite, Reaction
pyr_c = Metabolite(metabid='pyr_c', name='Pyruvate', compartment='c')
pep_c = Metabolite('pep_c', 'Phosphoenolpyruvate', 'c')
atp_c = Metabolite('atp_c', 'ATP', 'c')
amp_c = Metabolite('amp_c', 'AMP', 'c')
h2o_c = Metabolite('h2o_c', 'H2O', 'c', is_h2o=True)
h_c = Metabolite('h_c', 'H+', 'c', is_h=True)
pi_c = Metabolite('pi_c', 'Phosphate', 'c')
PPS = Reaction(
rxnid='PPS',
enzyme_name='phosphoenolpyruvate synthase',
category='Glycolysis',
forward_kcat=30.5,
molecular_weight=87.4,
standard_gibbs_energy=-22.1,
reversible=False
)
PPS.add_substrates({pyr_c: 1., atp_c: 1., h2o_c: 1.})
PPS.add_products({pep_c: 1., amp_c: 1., h_c: 2., pi_c: 1.})
print(PPS)
1.0 atp_c + 1.0 h2o_c + 1.0 pyr_c => 1.0 amp_c + 1.0 pep_c + 1.0 pi_c + 2.0 h_c
When constructing enzymatic reactions, the catalytic constant, k\(_{cat}\), in s\(^{-1}\), can be specified using the “forward_kcat” or “fkcat” argument. The k\(_{cat}\) value of the reaction in the reverse direction is set using “backward_kcat” or “bkcat”, depending on the reaction’s reversibility.
Note: In practice, the effective or apparent turnover number k\(_{app}\) should be provided, which reflects the actual enzyme activity in vivo, accounting for imcomplete substrate saturation, thermodynamic effects, and regulation effects, limited by the in vitro measured k\(_{cat}\).
The molecular weight (kDa) of the catalyzing enzyme can be provided using the “molecular_weight” argument. The standard Gibbs energy change with all reactants in 1 mM concentrations, ΔrG’m, can be set using “standard_gibbs_energy”. The convertion of Δ\(_r\)G’\(^0\) with 1 M concentrations to Δ\(_r\)G’\(^m\) can be made using the following equation:

Here, \(n_{s,i}\) and \(n_{p,j}\) are the stoichiometric coefficients of the i\(^{th}\) and j\(^{th}\) substrate and product (excluding H\(_2\)O and proton) in the reaction, respectively. \(R\) is the gas constant and \(T\) is the temperature in K.
The thermodynamic and kinetic properties of the enzyme can be assigned or modified using the corresponding attributes directly. For example,
[2]:
PPS.standard_gibbs_energy = -12.1
PPS.forward_kcat = 103.0
PPS.molecular_weight = 85.2
Note: There is no need to set the enzymatic properties for all reactions, for example, the exchange reactions, non-enzymatic transport reactions, and the biomass formation reaction in the model.
Now we can add the above reaction to the model using the add_reactions method:
[3]:
from etfba import Model
model = Model('demo')
model.add_reactions(PPS) # can accept a sequence of Reactions
One can also delete substrates and/or products from a Reaction using the remove_substrates and remove_products, respectively, and remove reaction(s) from a Model using the remove_reactions method.
Similarly, we can add the reaction PYK: ADP\(_c\) + H\(_c^+\) + PEP\(_c\) -> ATP\(_c\) + Pyr\(_c\) catalyzed by pyruvate kinase to further enrich the model.
[4]:
adp_c = Metabolite('adp_c', 'ADP', 'c')
PYK = Reaction(
rxnid='PYK',
enzyme_name='pyruvate kinase',
category='Glycolysis',
forward_kcat=38.8,
molecular_weight=51.0,
standard_gibbs_energy=-25.0,
reversible=False
)
PYK.add_substrates({pep_c: 1., adp_c: 1., h_c: 1.})
PYK.add_products({pyr_c: 1., atp_c: 1.})
model.add_reactions([PYK])
print(model)
model demo with 2 reactions and 8 metabolites
The building process described above can be conducted iteratively until the complete metabolic network is read into the model.
The complete sets of metabolites and reactions involved in the model can be accessed using the metabolites and reactions attributes, respectively. Both return a dictionary containing id => Metabolite/Reaction object.
[5]:
print(model.metabolites)
pyr_c: Pyruvate
atp_c: ATP
h2o_c: H2O
pep_c: Phosphoenolpyruvate
amp_c: AMP
h_c: H+
pi_c: Phosphate
adp_c: ADP
[6]:
print(model.reactions)
PPS: 1.0 atp_c + 1.0 h2o_c + 1.0 pyr_c => 1.0 amp_c + 1.0 pep_c + 1.0 pi_c + 2.0 h_c
PYK: 1.0 adp_c + 1.0 h_c + 1.0 pep_c => 1.0 atp_c + 1.0 pyr_c
The stoichiometric coefficients of metabolites in a reaction can be accessed using:
[7]:
print(model.metabolites['pyr_c'].coes['PPS'])
-1.0
Here, negative value denotes pyr_c functions as a substrate of reaction PPS.
Alternatively, you can also access the stoichiometric coefficient like this:
[8]:
print(model.reactions['PPS'].substrates['pyr_c'].coe)
1.0
The end metabolites, typically representing the initial substrates or final products of the network, can be accessed by:
[9]:
print(model.end_metabolites)
adp_c: ADP
amp_c: AMP
h2o_c: H2O
pi_c: Phosphate
The stoichiometric metrix of the netowrk can be accessed using stoichiometric_matrix. None zero entity in location (i, j) indicate the occurence of metabolite i in reaction j. Negative and postive values denote the role of the correspond metabolite as substrate or product in that reaction.
[10]:
print(model.stoichiometric_matrix)
PPS PYK
adp_c 0.0 -1.0
amp_c 1.0 0.0
atp_c -1.0 1.0
h2o_c -1.0 0.0
h_c 2.0 -1.0
pep_c 1.0 -1.0
pi_c 1.0 0.0
pyr_c -1.0 1.0
2.2. Translating from COBRA Model¶
When constructing a model from scratch becomes challenging or impractical, leveraging an existing COBRA model and translating it into an ETFBA model by incorporating thermodynamic and enzymatic properties can be advantageous. You can find a script demonstrating the conversion of the E. coli iML1515 model into the corresponding ETFBA model here. Additionally, the translated E. coli model can be accessed here.
2.3. Saving and Loading a Model¶
To save a model:
[11]:
model.save('demo.bin')
To load a pickled model:
[12]:
model_file = '../../models/e_coli/etfba_iML1515.bin'
ecoli_model = Model.load(model_file)
print(ecoli_model)
model iML1515 with 2712 reactions and 1877 metabolites