import cobra
import pandas as pd
from mmon_gcm.buildingediting import (
add_linkers,
add_metabolite,
add_metabolites_to_reaction_multi,
add_reaction,
check_number_of_models,
set_bounds_multi,
split_model, )
Building model
Set up
= cobra.io.read_sbml_model("../models/PlantCoreMetabolism_v1_2_2_3fbc.xml") model
No objective coefficients in model. Unclear what should be optimized
Add charge to model
= pd.read_csv("../inputs/charges.csv")
charges "Metabolite")
charges.set_index(for index, row in charges.iterrows():
1]).charge = row[0] model.metabolites.get_by_id(row[
Changes to Both Cells
K+
for metabolite in model.metabolites:
if "KI_" in metabolite.id:
id = metabolite.id[:1] + metabolite.id[-2:]
metabolite.= metabolite.id
metabolite.name = "K_cv"
model.reactions.K_rev_vc.name id = "K_cv"
model.reactions.K_rev_vc.= 1 model.metabolites.K_e.charge
Cl-
"Cl_e", "e", multi=False)
add_metabolite(model, "Cl_c", "c", multi=False)
add_metabolite(model, "Cl_v", "v", multi=False)
add_metabolite(model, = {"INCHI": ["InChI=1S/ClH/h1H/p-1"], "SMILES": ["Cl-"]}
model.metabolites.Cl_e.notes = -1
model.metabolites.Cl_e.charge = model.metabolites.Cl_e.notes.copy()
model.metabolites.Cl_c.notes = -1
model.metabolites.Cl_c.charge = model.metabolites.Cl_e.notes.copy()
model.metabolites.Cl_v.notes = -1
model.metabolites.Cl_v.charge
"Cl_tx", multi=False)
add_reaction(model, "Cl_e": 1})
model.reactions.Cl_tx.add_metabolites({= -1000 model.reactions.Cl_tx.lower_bound
CIT
for metabolite in model.metabolites:
if "CIT_" in metabolite.id and "aCIT" not in metabolite.id:
= -3 metabolite.charge
= -2 model.metabolites.aCIT_v.charge
MAL
for metabolite in model.metabolites:
if "MAL_" in metabolite.id and "aMAL" not in metabolite.id:
= -2 metabolite.charge
= -1 model.metabolites.aMAL_v.charge
"MAL_e", "e", multi=False)
add_metabolite(model, "aMAL_e", "e", multi=False) add_metabolite(model,
Metabolite identifier | aMAL_e |
Name | aMAL_e |
Memory address | 0x7e0687d07f40 |
Formula | None |
Compartment | e |
In 0 reaction(s) |
= model.metabolites.MAL_v.notes.copy()
model.metabolites.MAL_e.notes = model.metabolites.aMAL_v.notes.copy()
model.metabolites.aMAL_e.notes = model.metabolites.MAL_v.charge
model.metabolites.MAL_e.charge = model.metabolites.aMAL_v.charge model.metabolites.aMAL_e.charge
"MAL_tx", multi=False)
add_reaction(model,
model.reactions.MAL_tx.add_metabolites(
{"MAL_e": 0.7,
"aMAL_e": 0.3,
}
)= -1000 model.reactions.MAL_tx.lower_bound
MAL Anion Export Channel (Cl/Mal)
"MAL_ce", multi=False)
add_reaction(model, = "MAL R/S-Type Anion Channel"
model.reactions.MAL_ce.name
model.reactions.MAL_ce.add_metabolites("MAL_c": -1, "MAL_e": 0.7, "aMAL_e": 0.3, "PROTON_e": -0.3}
{ )
NADPHox
# change names to make consistent with the rest of the model
for reaction in model.reactions:
if "NADPHox" in reaction.id:
= reaction.id[:7] + "_" + reaction.id[7:]
reaction.name id = reaction.id[:7] + "_" + reaction.id[7:] reaction.
Remove reactions only active in germinating seeds
Arabidopsis Peroxisomal Citrate Synthase Is Required for Fatty Acid Respiration and Seed Germination Itsara Pracharoenwattana, Johanna E. Cornah, Steven M. Smith The Plant Cell Jul 2005, 17 (7) 2037-2048; DOI: 10.1105/tpc.105.031856
Coordinate expression of transcriptionally regulated isocitrate lyase and malate synthase genes in Brassica napus L. L Comai, R A Dietrich, D J Maslyar, C S Baden, J J Harada The Plant Cell Mar 1989, 1 (3) 293-300; DOI: 10.1105/tpc.1.3.293
= 0, 0
model.reactions.MALSYN_RXN_x.bounds = 0, 0 model.reactions.CITSYN_RXN_x.bounds
Setting disproportionating enzyme irreversible in the direction of maltose degradation
Critchley, J.H., Zeeman, S.C., Takaha, T., Smith, A.M. and Smith, S.M. (2001), A critical role for disproportionating enzyme in starch breakdown is revealed by a knock-out mutation in Arabidopsis. The Plant Journal, 26: 89-100. https://doi.org/10.1046/j.1365-313x.2001.01012.x
= 0, cobra.Configuration().upper_bound model.reactions.MALTODEG_RXN_c.bounds
Split Model into Mesophyll (me) and Guard Cell (gc)
Usesplit_model
to duplicate the model and add the tags “me” and “gc” to each one
"me", "gc"]) split_model(model, [
/home/maurice/miniconda3/envs/mmon-gcm/lib/python3.9/site-packages/cobra/core/group.py:147: UserWarning: need to pass in a list
warn("need to pass in a list")
Adding GC-specific transporters
model.reactions.PROTON_ATPase_c_gc
Reaction identifier | PROTON_ATPase_c_gc |
Name | PROTON_ATPase_c_gc |
Memory address | 0x7e0686ad35b0 |
Stoichiometry | 0.65 ATP_c_gc + 0.45 PROTON_c_gc + WATER_c_gc + 0.35 aATP_c_gc --> 0.5 ADP_c_gc + PROTON_e_gc + 0.7 Pi_c_gc + 0.5 aADP_c_gc + 0.3 aPi_c_gc 0.65 ATP_gc + 0.45 PROTON_gc + WATER_gc + 0.35 aATP[c]_gc --> 0.5 ADP_gc + PROTON_gc + 0.7 Pi[c]_gc + 0.5 aADP[c]_gc + 0.3 aPi[c]_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Inward-rectifying K+ Channel
Remove dependence for protons
= "Apoplastic Inward-Rectifying K+ Channel"
model.reactions.K_ec_gc.name "PROTON_e_gc": 1, "PROTON_c_gc": -1}) model.reactions.K_ec_gc.add_metabolites({
model.reactions.K_ec_gc
Reaction identifier | K_ec_gc |
Name | Apoplastic Inward-Rectifying K+ Channel |
Memory address | 0x7e0686b12bb0 |
Stoichiometry | K_e_gc --> K_c_gc K_e_gc --> K_c_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Outward-rectifying K+ Channel
"K_ce_gc", multi=False)
add_reaction(model, = "Apoplastic Outward-Rectifying K+ Channel"
model.reactions.K_ce_gc.name "K_c_gc": -1, "K_e_gc": 1}) model.reactions.K_ce_gc.add_metabolites({
H+-coupled K+ Symport
"K_PROTON_ec_gc", multi=False)
add_reaction(model, = "H+-Coupled K+ Symport"
model.reactions.K_PROTON_ec_gc.name
model.reactions.K_PROTON_ec_gc.add_metabolites("K_e_gc": -1, "K_c_gc": 1, "PROTON_e_gc": -1, "PROTON_c_gc": 1}
{
) model.reactions.K_PROTON_ec_gc
Reaction identifier | K_PROTON_ec_gc |
Name | H+-Coupled K+ Symport |
Memory address | 0x7e0687d43760 |
Stoichiometry | K_e_gc + PROTON_e_gc --> K_c_gc + PROTON_c_gc K_e_gc + PROTON_gc --> K_c_gc + PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Cl- Import Channel
"Cl_ec_gc", multi=False)
add_reaction(model, = "Cl Apoplastic Import Channel"
model.reactions.Cl_ec_gc.name "Cl_e_gc": -1, "Cl_c_gc": 1}) model.reactions.Cl_ec_gc.add_metabolites({
H+-Coupled Cl- Symport
"Cl_PROTON_ec_gc", multi=False)
add_reaction(model, = "H+-Coupled Cl- Symport"
model.reactions.Cl_PROTON_ec_gc.name
model.reactions.Cl_PROTON_ec_gc.add_metabolites("Cl_e_gc": -2, "Cl_c_gc": 2, "PROTON_e_gc": -1, "PROTON_c_gc": 1}
{ )
Cl- Anion Export Channel (Cl/Mal)
"Cl_ce_gc", multi=False)
add_reaction(model, = "Cl- R/S-Type Anion Channel"
model.reactions.Cl_ce_gc.name "Cl_c_gc": -1, "Cl_e_gc": 1}) model.reactions.Cl_ce_gc.add_metabolites({
ATPase Malate Importer
"MAL_ATPASE_ec_gc", multi=False)
add_reaction(model,
model.reactions.MAL_ATPASE_ec_gc.add_metabolites(
{"MAL_e_gc": -0.7,
"aMAL_e_gc": -0.3,
"MAL_c_gc": 1,
"ATP_c_gc": -0.65,
"aATP_c_gc": -0.35,
"WATER_c_gc": -1,
"ADP_c_gc": 1,
"Pi_c_gc": 0.7,
"aPi_c_gc": 0.3,
"PROTON_c_gc": +0.85,
} )
Glucose Apoplastic Symport Channel
id = "GLC_PROTON_ec_gc"
model.reactions.GLC_ec_gc.= "H+-Coupled Glucose Symport"
model.reactions.GLC_PROTON_ec_gc.name model.reactions.GLC_PROTON_ec_gc
Reaction identifier | GLC_PROTON_ec_gc |
Name | H+-Coupled Glucose Symport |
Memory address | 0x7e0686c9c8e0 |
Stoichiometry | GLC_e_gc + PROTON_e_gc --> GLC_c_gc + PROTON_c_gc GLC_gc + PROTON_gc --> GLC_gc + PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Glucose Exporter
"GLC_ce_gc", multi=False)
add_reaction(model, = "Glucose Apoplastic Exporter"
model.reactions.GLC_ce_gc.name "GLC_c_gc": -1, "GLC_e_gc": 1}) model.reactions.GLC_ce_gc.add_metabolites({
Sucrose Apoplastic Symport Channel
# Renaming Sucrose_tx
id = "SUCROSE_tx_gc" model.reactions.Sucrose_tx_gc.
id = "SUCROSE_PROTON_ec_gc"
model.reactions.Sucrose_ec_gc.= "H+-Coupled Sucrose Symport"
model.reactions.SUCROSE_PROTON_ec_gc.name = 1000
model.reactions.SUCROSE_PROTON_ec_gc.upper_bound model.reactions.SUCROSE_PROTON_ec_gc
Reaction identifier | SUCROSE_PROTON_ec_gc |
Name | H+-Coupled Sucrose Symport |
Memory address | 0x7e06869a2cd0 |
Stoichiometry | PROTON_e_gc + SUCROSE_e_gc --> PROTON_c_gc + SUCROSE_c_gc PROTON_gc + SUCROSE_gc --> PROTON_gc + SUCROSE_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000 |
Sucrose Exporter
"SUCROSE_ce_gc", multi=False)
add_reaction(model, = "Sucrose Apoplastic Exporter"
model.reactions.SUCROSE_ce_gc.name "SUCROSE_c_gc": -1, "SUCROSE_e_gc": 1}) model.reactions.SUCROSE_ce_gc.add_metabolites({
Fructose Apoplastic Symport Channel
"FRU_e_gc", "e", multi=False)
add_metabolite(model, = model.metabolites.FRU_c_gc.notes.copy()
model.metabolites.FRU_e_gc.notes = 0 model.metabolites.FRU_e_gc.charge
"FRU_PROTON_ec_gc", multi=False)
add_reaction(model, = "H+-Coupled Fructose Symport"
model.reactions.FRU_PROTON_ec_gc.name
model.reactions.FRU_PROTON_ec_gc.add_metabolites("FRU_e_gc": -1, "FRU_c_gc": 1, "PROTON_e_gc": -1, "PROTON_c_gc": 1}
{ )
Fructose Exporter
"FRU_ce_gc", multi=False)
add_reaction(model, = "Fructose Apoplastic Exporter"
model.reactions.FRU_ce_gc.name "FRU_c_gc": -1, "FRU_e_gc": 1}) model.reactions.FRU_ce_gc.add_metabolites({
Cell-Wall Invertase
"cwINV_gc", multi=False) add_reaction(model,
Reaction identifier | cwINV_gc |
Name | cwINV_gc |
Memory address | 0x7e0687d43a60 |
Stoichiometry | --> --> |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
model.reactions.cwINV_gc.add_metabolites("SUCROSE_e_gc": -1, "WATER_e_gc": -1, "FRU_e_gc": 1, "GLC_e_gc": 1}
{ )
K+ Import Channel
(TPK-Type and Fast-vacuolar)
= "K+ Tonoplastic Import Channel"
model.reactions.K_cv_gc.name model.reactions.K_cv_gc
Reaction identifier | K_cv_gc |
Name | K+ Tonoplastic Import Channel |
Memory address | 0x7e0686aa7dc0 |
Stoichiometry | K_c_gc + PROTON_v_gc --> K_v_gc + PROTON_c_gc K_c_gc + PROTON_gc --> K_v_gc + PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
NHX-Type K+/H+ Antiport
"K_PROTON_cv_gc", multi=False)
add_reaction(model, = "NHX-Type K+/H+ Antiport"
model.reactions.K_PROTON_cv_gc.name
model.reactions.K_PROTON_cv_gc.add_metabolites("K_c_gc": -1, "K_v_gc": 1, "PROTON_v_gc": -1, "PROTON_c_gc": 1}
{ )
K+ Tonoplastic Export Channel
Slow Vacuolar Channel
"K_vc_gc", multi=False)
add_reaction(model, = "K+ Tonoplastic Export Slow Vacuolar Channel"
model.reactions.K_vc_gc.name "K_v_gc": -1, "K_c_gc": 1}) model.reactions.K_vc_gc.add_metabolites({
CLC-Type Cl-/H+ Antiport Vacoular Import Channel
"Cl_PROTON_cv_gc", multi=False)
add_reaction(model, = (
model.reactions.Cl_PROTON_cv_gc.name "CLC-Type Cl-/H+ Antiport Vacoular Import Channel"
)
model.reactions.Cl_PROTON_cv_gc.add_metabolites(
{"Cl_v_gc": 1,
"Cl_c_gc": -1,
"PROTON_c_gc": 2,
"PROTON_v_gc": -2,
} )
VCL Cl- Vacuolar Import Channel
"Cl_cv_gc", multi=False)
add_reaction(model, = "VCL Cl- Vacuolar Import Channel"
model.reactions.Cl_cv_gc.name "Cl_c_gc": -1, "Cl_v_gc": 1}) model.reactions.Cl_cv_gc.add_metabolites({
Cl- Vacuolar Export Channel
= -1000 model.reactions.Cl_cv_gc.lower_bound
MAL Import Channel (AMLT)
id = "MAL_cv_gc"
model.reactions.MAL_PROTON_vc_gc.= "VMAL-type MAL Channel (Import)"
model.reactions.MAL_cv_gc.name model.reactions.MAL_cv_gc
Reaction identifier | MAL_cv_gc |
Name | VMAL-type MAL Channel (Import) |
Memory address | 0x7e0686ab9190 |
Stoichiometry | MAL_c_gc + 0.3 PROTON_v_gc --> 0.7 MAL_v_gc + 0.3 aMAL_v_gc MAL_gc + 0.3 PROTON_gc --> 0.7 MAL_gc + 0.3 aMAL[v]_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
MAL Export Channel (AMLT)
"MAL_vc_gc", multi=False)
add_reaction(model, = "VMAL-type MAL Channel (Export)"
model.reactions.MAL_vc_gc.name
model.reactions.MAL_vc_gc.add_metabolites(
{"MAL_v_gc": -0.7,
"aMAL_v_gc": -0.3,
"MAL_c_gc": 1,
"PROTON_c_gc": 0.3,
} )
MAL Export Symporter
Already in Model
= "MAL Export Symporter"
model.reactions.MAL_PROTON_rev_vc_gc.name model.reactions.MAL_PROTON_rev_vc_gc
Reaction identifier | MAL_PROTON_rev_vc_gc |
Name | MAL Export Symporter |
Memory address | 0x7e068696ca90 |
Stoichiometry | 0.7 MAL_v_gc + 1.7 PROTON_v_gc + 0.3 aMAL_v_gc --> MAL_c_gc + 2.0 PROTON_c_gc 0.7 MAL_gc + 1.7 PROTON_gc + 0.3 aMAL[v]_gc --> MAL_gc + 2.0 PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Fructose Import Antiporter
Previously in the model
id = "FRU_PROTON_rev_cv_gc"
model.reactions.FRU_PROTON_rev_vc_gc.= "Fructose Tonoplastic Import Antiporter"
model.reactions.FRU_PROTON_rev_cv_gc.name model.reactions.FRU_PROTON_rev_cv_gc
Reaction identifier | FRU_PROTON_rev_cv_gc |
Name | Fructose Tonoplastic Import Antiporter |
Memory address | 0x7e0686ea8fa0 |
Stoichiometry | FRU_c_gc + PROTON_v_gc --> FRU_v_gc + PROTON_c_gc FRU[c]_gc + PROTON_gc --> FRU[v]_gc + PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Fructose Import Symporter
"FRU_PROTON_cv_gc", multi=False)
add_reaction(model, = "Fructose Tonoplastic Import Symporter"
model.reactions.FRU_PROTON_cv_gc.name
model.reactions.FRU_PROTON_cv_gc.add_metabolites("PROTON_c_gc": -1, "PROTON_v_gc": 1, "FRU_c_gc": -1, "FRU_v_gc": 1}
{ )
Fructose Export
model.reactions.FRU_vc_gc
Reaction identifier | FRU_vc_gc |
Name | FRU_vc_gc |
Memory address | 0x7e0686b245e0 |
Stoichiometry | FRU_v_gc --> FRU_c_gc FRU[v]_gc --> FRU[c]_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Glucose Tonoplastic Antiporter
id = "GLC_PROTON_rev_cv_gc"
model.reactions.GLC_PROTON_rev_vc_gc.= "Glucose Tonoplastic Import Antiporter"
model.reactions.GLC_PROTON_rev_cv_gc.name model.reactions.GLC_PROTON_rev_cv_gc
Reaction identifier | GLC_PROTON_rev_cv_gc |
Name | Glucose Tonoplastic Import Antiporter |
Memory address | 0x7e0686d1de50 |
Stoichiometry | GLC_c_gc + PROTON_v_gc --> GLC_v_gc + PROTON_c_gc GLC_gc + PROTON_gc --> GLC_gc + PROTON_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Glucose Tonoplastic Symporter
"GLC_PROTON_cv_gc", multi=False)
add_reaction(model, = "Glucose Tonoplastic Import Symporter"
model.reactions.GLC_PROTON_cv_gc.name
model.reactions.GLC_PROTON_cv_gc.add_metabolites("PROTON_c_gc": -1, "PROTON_v_gc": 1, "GLC_c_gc": -1, "GLC_v_gc": 1}
{ )
Glucose Export Channel
model.reactions.GLC_vc_gc
Reaction identifier | GLC_vc_gc |
Name | GLC_vc_gc |
Memory address | 0x7e0686a9df70 |
Stoichiometry | GLC_v_gc --> GLC_c_gc GLC_gc --> GLC_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Sucrose Tonoplastic Importer
"SUCROSE_cv_gc", multi=False)
add_reaction(model, = "Sucrose Free Tonoplastic Import"
model.reactions.SUCROSE_cv_gc.name
model.reactions.SUCROSE_cv_gc.add_metabolites(
{"SUCROSE_c_gc": -1,
"SUCROSE_v_gc": 1,
} )
Sucrose Tonoplastic Import Antiporter
Already in the model
id = "SUCROSE_PROTON_cv_gc"
model.reactions.SUCROSE_PROTON_vc_gc.= "Sucrose Tonoplastic Import Antiporter"
model.reactions.SUCROSE_PROTON_cv_gc.name model.reactions.SUCROSE_PROTON_cv_gc
Reaction identifier | SUCROSE_PROTON_cv_gc |
Name | Sucrose Tonoplastic Import Antiporter |
Memory address | 0x7e0686f28d30 |
Stoichiometry | PROTON_v_gc + SUCROSE_c_gc --> PROTON_c_gc + SUCROSE_v_gc PROTON_gc + SUCROSE_gc --> PROTON_gc + SUCROSE_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Sucrose Tonoplastic Export Symporter
id = "SUCROSE_PROTON_vc_gc"
model.reactions.SUCROSE_PROTON_rev_vc_gc.= "Sucrose Tonoplastic Export Symporter" model.reactions.SUCROSE_PROTON_vc_gc.name
Tonoplastic PPase
model.reactions.PROTON_PPi_rev_vc_gc
Reaction identifier | PROTON_PPi_rev_vc_gc |
Name | PROTON_PPi_rev_vc_gc |
Memory address | 0x7e06869e5670 |
Stoichiometry | 0.65 PPI_c_gc + 0.25 PROTON_c_gc + WATER_c_gc + 0.35 aPPI_c_gc --> PROTON_v_gc + 1.4 Pi_c_gc + 0.6 aPi_c_gc 0.65 PPI_gc + 0.25 PROTON_gc + WATER_gc + 0.35 aPPI[c]_gc --> PROTON_gc + 1.4 Pi[c]_gc + 0.6 aPi[c]_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
Tonoplastic H+ ATPase
model.reactions.PROTONATP_rev_vc_gc
Reaction identifier | PROTONATP_rev_vc_gc |
Name | PROTONATP_rev_vc_gc |
Memory address | 0x7e0686febb20 |
Stoichiometry | 0.65 ATP_c_gc + 1.45 PROTON_c_gc + WATER_c_gc + 0.35 aATP_c_gc --> 0.5 ADP_c_gc + 2.0 PROTON_v_gc + 0.7 Pi_c_gc + 0.5 aADP_c_gc + 0.3 aPi_c_gc 0.65 ATP_gc + 1.45 PROTON_gc + WATER_gc + 0.35 aATP[c]_gc --> 0.5 ADP_gc + 2.0 PROTON_gc + 0.7 Pi[c]_gc + 0.5 aADP[c]_gc + 0.3 aPi[c]_gc |
GPR | |
Lower bound | 0.0 |
Upper bound | 1000.0 |
"PROTON_ec_gc", multi=False)
add_reaction(model, = "Plasma membrane proton leakage"
model.reactions.PROTON_ec_gc.name
model.reactions.PROTON_ec_gc.add_metabolites(
{"PROTON_e_gc": -1,
"PROTON_c_gc": 1,
} )
"PROTON_vc_gc", multi=False)
add_reaction(model, = "Tonoplast membrane proton leakage"
model.reactions.PROTON_vc_gc.name
model.reactions.PROTON_vc_gc.add_metabolites(
{"PROTON_v_gc": -1,
"PROTON_c_gc": 1,
} )
Constrain Channels in Guard Cell
for channel in ["Cl_ec", "K_cv", "FRU_PROTON_cv", "GLC_PROTON_cv", "SUCROSE_cv"]:
+ "_gc").bounds = 0, 0 model.reactions.get_by_id(channel
Adding apoplast and exchanges
In this section we add an apoplastic compartment and set the influx of osmolites to be from this compartment rather than as boundary reactions.
Removing tx_me
Here we remove all the boundary reactions from the mesophyll cell except for: - Maintenance reactions - Photon influx - Phloem output - Gas transfer (O2 and CO2)
= []
tx_me for reaction in model.reactions:
if "_tx_me" in reaction.id:
tx_me.append(reaction)= [
keep "Photon_tx_me",
"Phloem_output_tx_me",
"NADPHox_c_tx_me",
"NADPHox_m_tx_me",
"NADPHox_p_tx_me",
"O2_tx_me",
"CO2_tx_me",
"ATPase_tx_me",
]for reaction in keep:
tx_me.remove(model.reactions.get_by_id(reaction))
model.remove_reactions(tx_me)
Removing tx_gc
See above for removing tx_me reactions, only difference is in this case we don’t have a phloem output reaction
= []
tx_gc for reaction in model.reactions:
if "_tx_gc" in reaction.id:
tx_gc.append(reaction)= [
keep "Photon_tx_gc",
"NADPHox_c_tx_gc",
"NADPHox_m_tx_gc",
"NADPHox_p_tx_gc",
"O2_tx_gc",
"CO2_tx_gc",
"ATPase_tx_gc",
]for reaction in keep:
tx_gc.remove(model.reactions.get_by_id(reaction))
model.remove_reactions(tx_gc)
Adding tx to apo and adding exchanges
Now for the species that are present in the extracellular compartment of the guard cell we: - Add the species to the apoplastic compartment with the tag “a” - Add a boundary reaction into this compartment for the species - Add a transfer reaction to allow them to be transferred between the guard cell extracellular compartment and the apoplast - Add a transfer reaction to allow them to be transferred between the mesophyll cell extracellular compartment and the apoplast
All these actions are free and reversible, as we are assuming that really the extracellular space and the apoplast are all the same. The apoplastic compartment just gives us an easy way to track influx/efflux of metabolites as well as osmolite levels in that compartment.
# fructose wasn't in the extracellular compartment of mesophyll before
"FRU_e_me", "e", multi=False) add_metabolite(model,
Metabolite identifier | FRU_e_me |
Name | FRU_e_me |
Memory address | 0x7e0687e36250 |
Formula | None |
Compartment | e |
In 0 reaction(s) |
"Sucrose_ce_me", multi=False) # sucrose transport out of the mesophyll cell wasn't allowed before
add_reaction(model, "SUCROSE_c_me": -1, "SUCROSE_e_me": 1}) model.reactions.Sucrose_ce_me.add_metabolites({
= []
ea_reactions for metabolite in model.metabolites:
if "_e_gc" in metabolite.id:
ea_reactions.append(metabolite)
print(ea_reactions)
# don't want these to be transferred in the apoplast, they already have individual boundary reactions in each cell type
= ["Photon", "OXYGEN_MOLECULE", "CARBON_DIOXIDE", "PROTON"]
remove for name in remove:
+ "_e_gc"))
ea_reactions.remove(model.metabolites.get_by_id(name
for metabolite in ea_reactions:
id[:-4] + "a", "a", multi=False)
add_metabolite(model, metabolite.id[:-4] + "a").charge = metabolite.charge
model.metabolites.get_by_id(metabolite.id[:-4] + "a").notes = metabolite.notes
model.metabolites.get_by_id(metabolite.
id[:-4] + "a_tx", multi=False)
add_reaction(model, metabolite.id[:-4] + "a_tx").add_metabolites(
model.reactions.get_by_id(metabolite.id[:-4] + "a": 1}
{metabolite.
)id[:-4] + "a_tx").lower_bound = -1000
model.reactions.get_by_id(metabolite.
id[:-4] + "ae_gc", multi=False)
add_reaction(model, metabolite.id[:-4] + "ae_gc").add_metabolites(
model.reactions.get_by_id(metabolite.1, metabolite.id[:-4] + "a": -1}
{metabolite:
)id[:-4] + "ae_gc").lower_bound = -1000
model.reactions.get_by_id(metabolite.
id[:-4] + "ae_me", multi=False)
add_reaction(model, metabolite.id[:-4] + "ae_me").add_metabolites(
model.reactions.get_by_id(metabolite.id[:-4] + "e_me": 1, metabolite.id[:-4] + "a": -1}
{metabolite.
)id[:-4] + "ae_me").lower_bound = -1000 model.reactions.get_by_id(metabolite.
[<Metabolite NITRATE_e_gc at 0x7e06872203a0>, <Metabolite SUCROSE_e_gc at 0x7e0687220b20>, <Metabolite WATER_e_gc at 0x7e0687236be0>, <Metabolite MGII_e_gc at 0x7e06871c25e0>, <Metabolite GLC_e_gc at 0x7e06871d5b20>, <Metabolite PROTON_e_gc at 0x7e06871dc8e0>, <Metabolite CARBON_DIOXIDE_e_gc at 0x7e068719acd0>, <Metabolite CAII_e_gc at 0x7e06871bd910>, <Metabolite Pi_e_gc at 0x7e06871bdf10>, <Metabolite SULFATE_e_gc at 0x7e0687154250>, <Metabolite OXYGEN_MOLECULE_e_gc at 0x7e0687154fd0>, <Metabolite Photon_e_gc at 0x7e0687119280>, <Metabolite K_e_gc at 0x7e0687125a00>, <Metabolite AMMONIUM_e_gc at 0x7e06870e0580>, <Metabolite Cl_e_gc at 0x7e06870f8b80>, <Metabolite MAL_e_gc at 0x7e06870f8dc0>, <Metabolite aMAL_e_gc at 0x7e06870f8e80>, <Metabolite FRU_e_gc at 0x7e0687c417f0>]
List of all boundary reactions:
for reaction in model.reactions:
if "_tx" in reaction.id:
print(reaction.id)
Photon_tx_me
Photon_tx_gc
NADPHox_m_tx_me
NADPHox_m_tx_gc
CO2_tx_me
CO2_tx_gc
O2_tx_me
O2_tx_gc
Phloem_output_tx_me
NADPHox_c_tx_me
NADPHox_c_tx_gc
ATPase_tx_me
ATPase_tx_gc
NADPHox_p_tx_me
NADPHox_p_tx_gc
NITRATE_a_tx
SUCROSE_a_tx
WATER_a_tx
MGII_a_tx
GLC_a_tx
CAII_a_tx
Pi_a_tx
SULFATE_a_tx
K_a_tx
AMMONIUM_a_tx
Cl_a_tx
MAL_a_tx
aMAL_a_tx
FRU_a_tx
Constrain free exchange and starch breakdown
Prevent: - Free import into the apoplast of energy-carrying metabolites like Glucose, malate, sucrose, fructose. - Free exchange of protons. - Alpha-glucosidase starch degradation pathway as it isn’t used
for reaction in [
"GLC_a_tx",
"MAL_a_tx",
"SUCROSE_a_tx",
"FRU_a_tx",
"RXN_1826_p_me",
"RXN_1826_p_gc",
"MALTODEXGLUCOSID_RXN_p_me",
"MALTODEXGLUCOSID_RXN_p_gc",
]:= (0, 0) model.reactions.get_by_id(reaction).bounds
Quadruple model into 4 phases
range(1, 5)) split_model(model,
Add Linker Reactions With Pseudometabolites (Osmolarity and Charge)
Set phase times here
= ["c", "v", "p", "a"]
compartments
= [
cells "gc",
"me",
]= [6.0, 0.5, 11.5, 6.0] phase_times
"../inputs/osmolytes.csv", compartments, cells, phase_times) add_linkers(model,
= {
prefix_metabolites "a": {
"v_gc": {
"MAL": 0.7,
"CIT": 0.5,
},"a": {
"MAL": 0.7,
},"v_me": {
"MAL": 0.7,
"CIT": 0.5,
},
},"b": {"v_me": {"HIS": 0}, "v_gc": {"HIS": 0}},
}
for prefix, compartments in prefix_metabolites.items():
for compartment, metabolites in compartments.items():
for metabolite, ratio in metabolites.items():
if ratio == 0:
set_bounds_multi(+ "_" + compartment + "_Linker", 0, 0
model, metabolite
)elif ratio == 1:
set_bounds_multi(+ model, metabolite + "_" + compartment + "_Linker", 0, 0
prefix
)else:
add_metabolite(+ "_" + compartment + "_prefixpseudometabolite"
model, metabolite
)for phase in range(check_number_of_models(model)):
model.reactions.get_by_id(f"{metabolite}_{compartment}_Linker_" + str(phase + 1)
).add_metabolites(
{
model.metabolites.get_by_id(f"{metabolite}_{compartment}_prefixpseudometabolite_" +
str(phase + 1)
1 -
):
ratio
}
)
model.reactions.get_by_id(f"{prefix}{metabolite}_{compartment}_Linker_" + str(phase + 1)
).add_metabolites(
{
model.metabolites.get_by_id(f"{metabolite}_{compartment}_prefixpseudometabolite_"
+ str(phase + 1)
-ratio
):
} )
Add Maintenance Reactions
Remove maintenance phase constraint (no forcing same maintenance for each phase)
= check_number_of_models(model)
number_of_models for cell in ["gc", "me"]:
"maintenance_ratio_constraint_" + cell, "pseudo")
add_metabolite(model, #add_metabolite(model, "maintenance_phase_constraint_" + cell, "pseudo")
"maintenance_phase_overall_" + cell, multi="")
add_reaction(model, for i in range(1, number_of_models + 1):
for x in ["c", "m", "p"]:
= model.reactions.get_by_id(f"NADPHox_{x}_tx_{cell}_" + str(i))
reaction
reaction.add_metabolites(f"maintenance_ratio_constraint_{cell}_" + str(i): -3}
{
)= model.reactions.get_by_id(f"ATPase_tx_{cell}_" + str(i))
reaction
reaction.add_metabolites(
{f"maintenance_ratio_constraint_{cell}_" + str(i): 1,
#f"maintenance_phase_constraint_{cell}_" + str(i): 1,
}
)#model.reactions.get_by_id(f"maintenance_phase_overall_{cell}").add_metabolites(
# {f"maintenance_phase_constraint_{cell}_" + str(i): -1}
#)
Add Phloem_tx Overall
= check_number_of_models(model)
number_of_models = [2, 3]
day = [1, 4]
night "pseudoPhloem_me", "pseudo")
add_metabolite(model, "pseudoPhloem_day_me", "pseudo", multi="")
add_metabolite(model, "pseudoPhloem_night_me", "pseudo", multi="")
add_metabolite(model, "Phloem_constraint_day", multi="")
add_reaction(model, "Phloem_constraint_night", multi="")
add_reaction(model, "Phloem_tx_overall", multi="")
add_reaction(model, for i in range(1, number_of_models + 1):
= 1 / (
length_of_phase -model.reactions.get_by_id(f"SUCROSE_v_gc_Linker_{i}").get_coefficient(
f"SUCROSE_v_gc_{i}"
)
)f"Phloem_output_tx_me_{i}").add_metabolites(
model.reactions.get_by_id(f"pseudoPhloem_me_{i}": 1}
{
)if i in day:
f"Phloem_output_tx_me_{i}").add_metabolites(
model.reactions.get_by_id("pseudoPhloem_day_me": 1 * length_of_phase}
{
)
model.reactions.Phloem_constraint_day.add_metabolites(f"pseudoPhloem_me_{i}": -1}
{
)elif i in night:
f"Phloem_output_tx_me_{i}").add_metabolites(
model.reactions.get_by_id("pseudoPhloem_night_me": 1 * length_of_phase}
{
)
model.reactions.Phloem_constraint_night.add_metabolites(f"pseudoPhloem_me_{i}": -1}
{
)else:
raise ValueError("Make sure all phases are either assigned to day or night")
model.reactions.Phloem_constraint_day.add_metabolites({})
model.reactions.Phloem_tx_overall.add_metabolites(
{"pseudoPhloem_day_me": -3,
"pseudoPhloem_night_me": -1,
} )
Add pseudoreactions for total metabolite counting and FVA
Essentially, here we add a ‘total’ pseudometabolite in the guard cel for each of a list of metabolites. We can use this metabolite to see the sum of the linker reactions for the vacuole and cytoplasm, but most importantly we can perform FVA on this reaction to see if the total transfer of a metabolite matters. Otherwise, we end up in a situation where we can do FVA on the cytoplasmic and vacuolar reactions separately but it could be the case that when cytoplasm goes down the vacuole compensates etc.
"total" added as keyword to getweightings in order to prevent these reactions from contributing to sum of fluxes constraint
= ["SUCROSE", "GLC", "MAL", "FRU", "K", "Cl", "CIT"] # "NITRATE", "CIT"]
metabolites
for metabolite in metabolites:
if metabolite == "MAL" or metabolite == "CIT":
f"{metabolite}_total_pseudolinker")
add_reaction(model, f"{metabolite}_total_pseudometabolite")
add_metabolite(model,
add_metabolites_to_reaction_multi(
model,f"{metabolite}_total_pseudolinker",
f"{metabolite}_total_pseudometabolite": -1},
{
)
add_metabolites_to_reaction_multi(
model,f"{metabolite}_c_gc_Linker",
f"{metabolite}_total_pseudometabolite": 1},
{
)
add_metabolites_to_reaction_multi(
model,f"{metabolite}_v_gc_Linker",
f"{metabolite}_total_pseudometabolite": 1},
{
)
add_metabolites_to_reaction_multi(
model,f"a{metabolite}_v_gc_Linker",
f"{metabolite}_total_pseudometabolite": 1},
{
)else:
f"{metabolite}_total_pseudolinker")
add_reaction(model, f"{metabolite}_total_pseudometabolite")
add_metabolite(model,
add_metabolites_to_reaction_multi(
model,f"{metabolite}_total_pseudolinker",
f"{metabolite}_total_pseudometabolite": -1},
{
)
add_metabolites_to_reaction_multi(
model,f"{metabolite}_c_gc_Linker",
f"{metabolite}_total_pseudometabolite": 1},
{
)
add_metabolites_to_reaction_multi(
model,f"{metabolite}_v_gc_Linker",
f"{metabolite}_total_pseudometabolite": 1},
{ )
Export Model
"../models/4_stage_GC.xml")
cobra.io.write_sbml_model(model, "../models/4_stage_GC.json") cobra.io.save_json_model(model,