PyCoMo Basics

PyCoMo is a Python Community metabolic Modelling package. In this tutorial, the core features will be presented.

The expected runtime for this notebook is approximately 10-30 minutes.

Setting up PyCoMo

Clone the package from github. Next, we are going to import all the packages we need in this tutorial.

[1]:
from pathlib import Path
import sys
import cobra
import os

Importing PyCoMo

As PyCoMo is currently only available as a local package, the direct path to the package directory needs to be used on import.

[2]:
path_root = "../src"  # Change path according to your PyCoMo location
sys.path.append(str(path_root))
import pycomo
pycomo.configure_logger(level="info")
2025-02-11 16:28:11,142 - pycomo - INFO - Logger initialized.
2025-02-11 16:28:11,144 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:28:11,145 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:28:11,146 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:28:11,148 - pycomo - INFO - Log level set to info

Creating a Community Model

The creation of a community model consists of 3 steps:

  1. Loading the member models

  2. Preparing the member models for merging

  3. Creating a community model

Loading the member models

The community model creation process starts with models of the individual members. Note that the quality of the community model heavily depends on the quality of the member models!

In this tutorial we are using metabolic models from the AGORA collection. The models were retrieved from www.vmh.life, and are stored in the data folder of the repository. The selection of models and the resulting community represents a cystic fibrosis airway community, as done by Henson et al. (www.doi.org/10.1128/mSystems.00026-19)

[3]:
test_model_dir = "../data/use_case/henson"
named_models = pycomo.load_named_models_from_dir(test_model_dir)

The models and file names were extracted and stored in named_models. Let’s check the contents:

[4]:
named_models
[4]:
{'Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586': <Model Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586 at 0x7f00ac840dd0>,
 'Actinomyces_naeslundii_str_Howell_279': <Model Actinomyces_naeslundii_str_Howell_279 at 0x7f004b2c43d0>,
 'Burkholderia_cepacia_GG4': <Model Burkholderia_cepacia_GG4 at 0x7f004a9dc210>,
 'Veillonella_atypica_ACS_049_V_Sch6': <Model Veillonella_atypica_ACS_049_V_Sch6 at 0x7f0049b44bd0>,
 'Neisseria_flavescens_SK114': <Model Neisseria_flavescens_SK114 at 0x7f0049168190>,
 'Staphylococcus_aureus_subsp_aureus_USA300_FPR3757': <Model Staphylococcus_aureus_subsp_aureus_USA300_FPR3757 at 0x7f0048940050>,
 'Pseudomonas_aeruginosa_NCGM2_S1': <Model Pseudomonas_aeruginosa_NCGM2_S1 at 0x7f0047f74610>,
 'Achromobacter_xylosoxidans_NBRC_15126': <Model Achromobacter_xylosoxidans_NBRC_15126 at 0x7f00473e6810>,
 'Streptococcus_sanguinis_SK36': <Model Streptococcus_sanguinis_SK36 at 0x7f004647c310>,
 'Haemophilus_influenzae_R2846': <Model Haemophilus_influenzae_R2846 at 0x7f0045a1c110>,
 'Escherichia_coli_str_K_12_substr_MG1655': <Model Escherichia_coli_str_K_12_substr_MG1655 at 0x7f00452b04d0>,
 'Porphyromonas_endodontalis_ATCC_35406': <Model Porphyromonas_endodontalis_ATCC_35406 at 0x7f004465c150>,
 'Prevotella_melaninogenica_ATCC_25845': <Model Prevotella_melaninogenica_ATCC_25845 at 0x7f0044bbc410>,
 'Ralstonia_sp_5_7_47FAA': <Model Ralstonia_sp_5_7_47FAA at 0x7f00433d4090>,
 'Granulicatella_adiacens_ATCC_49175': <Model Granulicatella_adiacens_ATCC_49175 at 0x7f00428b0090>,
 'Gemella_haemolysans_ATCC_10379': <Model Gemella_haemolysans_ATCC_10379 at 0x7f0041f340d0>,
 'Rothia_mucilaginosa_DY_18': <Model Rothia_mucilaginosa_DY_18 at 0x7f00419dc210>}

Preparing the models for merging

With the models loaded, the next step is preparing them for merging. This is done by creating SingleOrganismModel objects. Using them, the models will be formatted for compliance with the SBML format. Further, an exchange compartment will be generated under the name medium.

One of the requirements for a community metabolic model is a common biomass function. To construct it, PyCoMo requires the biomass of each member represented as a single metabolite. This biomass metabolite ID can be specified when constructing the SingleOrganismModel objects. However, it can also be found or generated automatically, by setting the biomass reaction as the objective of the model. Let’s check if the biomass function is the objective in all the models

[5]:
for model in named_models.values():
    print(model.objective)
Maximize
1.0*biomass237 - 1.0*biomass237_reverse_f032e
Maximize
1.0*biomass492 - 1.0*biomass492_reverse_bc961
Maximize
1.0*biomass479 - 1.0*biomass479_reverse_1d1b2
Maximize
1.0*biomass116 - 1.0*biomass116_reverse_02324
Maximize
1.0*biomass339 - 1.0*biomass339_reverse_45ed6
Maximize
1.0*biomass042 - 1.0*biomass042_reverse_2a02b
Maximize
1.0*biomass345 - 1.0*biomass345_reverse_e128f
Maximize
1.0*biomass489 - 1.0*biomass489_reverse_62d1a
Maximize
1.0*biomass164 - 1.0*biomass164_reverse_ca493
Maximize
1.0*biomass252 - 1.0*biomass252_reverse_f6948
Maximize
1.0*biomass525 - 1.0*biomass525_reverse_5c178
Maximize
1.0*biomass326 - 1.0*biomass326_reverse_02060
Maximize
1.0*biomass276 - 1.0*biomass276_reverse_7f92e
Maximize
1.0*biomass525 - 1.0*biomass525_reverse_5c178
Maximize
1.0*biomass091 - 1.0*biomass091_reverse_7b6db
Maximize
1.0*biomass027 - 1.0*biomass027_reverse_af8dc
Maximize
1.0*biomass429 - 1.0*biomass429_reverse_9caa0

With the objective being the biomass function in all models, the biomass metabolite does not need to be specified.

[6]:
single_org_models = []
for name, model in named_models.items():
    print(name)
    single_org_model = pycomo.SingleOrganismModel(model, name)
    single_org_models.append(single_org_model)
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586
Actinomyces_naeslundii_str_Howell_279
Burkholderia_cepacia_GG4
Veillonella_atypica_ACS_049_V_Sch6
Neisseria_flavescens_SK114
Staphylococcus_aureus_subsp_aureus_USA300_FPR3757
Pseudomonas_aeruginosa_NCGM2_S1
Achromobacter_xylosoxidans_NBRC_15126
Streptococcus_sanguinis_SK36
Haemophilus_influenzae_R2846
Escherichia_coli_str_K_12_substr_MG1655
Porphyromonas_endodontalis_ATCC_35406
Prevotella_melaninogenica_ATCC_25845
Ralstonia_sp_5_7_47FAA
Granulicatella_adiacens_ATCC_49175
Gemella_haemolysans_ATCC_10379
Rothia_mucilaginosa_DY_18

Creating a community model

With the member models prepared, the community model can be generated. The first step is to create a CommunityModel objects from the member models. The matching of the exchange metabolites can be achieved in two ways: matching via identical metabolite IDs, or via annotation fields. In this tutorial and as all the models come from the same source, matching via identical metabolite IDs will be used.

[7]:
community_name = "henson_community_model"
com_model_obj = pycomo.CommunityModel(single_org_models, community_name)

The cobra model of the community will generated the first time it is needed. We can enforce this now, by calling it via .model

[8]:
com_model_obj.model
2025-02-11 16:28:32,249 - pycomo - INFO - No community model generated yet. Generating now:
2025-02-11 16:28:32,428 - pycomo - INFO - Identified biomass reaction from objective: biomass237
2025-02-11 16:28:32,428 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:28:37,567 - pycomo - INFO - Identified biomass reaction from objective: biomass492
2025-02-11 16:28:37,567 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:28:44,909 - pycomo - INFO - Identified biomass reaction from objective: biomass479
2025-02-11 16:28:44,909 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:28:59,680 - pycomo - INFO - Identified biomass reaction from objective: biomass116
2025-02-11 16:28:59,681 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:29:06,508 - pycomo - INFO - Identified biomass reaction from objective: biomass339
2025-02-11 16:29:06,509 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:29:13,745 - pycomo - INFO - Identified biomass reaction from objective: biomass042
2025-02-11 16:29:13,746 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:29:24,477 - pycomo - INFO - Identified biomass reaction from objective: biomass345
2025-02-11 16:29:24,478 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:29:37,701 - pycomo - INFO - Identified biomass reaction from objective: biomass489
2025-02-11 16:29:37,702 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:29:52,668 - pycomo - INFO - Identified biomass reaction from objective: biomass164
2025-02-11 16:29:52,668 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:01,601 - pycomo - INFO - Identified biomass reaction from objective: biomass252
2025-02-11 16:30:01,601 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:11,188 - pycomo - INFO - Identified biomass reaction from objective: biomass525
2025-02-11 16:30:11,189 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:27,457 - pycomo - INFO - Identified biomass reaction from objective: biomass326
2025-02-11 16:30:27,458 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:32,670 - pycomo - INFO - Identified biomass reaction from objective: biomass276
2025-02-11 16:30:32,670 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:39,208 - pycomo - INFO - Identified biomass reaction from objective: biomass525
2025-02-11 16:30:39,209 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:49,904 - pycomo - INFO - Identified biomass reaction from objective: biomass091
2025-02-11 16:30:49,904 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:30:55,715 - pycomo - INFO - Identified biomass reaction from objective: biomass027
2025-02-11 16:30:55,715 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:31:01,518 - pycomo - INFO - Identified biomass reaction from objective: biomass429
2025-02-11 16:31:01,519 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.
2025-02-11 16:31:08,936 - pycomo - WARNING - No annotation overlap found for matching several metabolites (552). Please make sure that the matched metabolites are indeed representing the same substance in all models! The list of metaboliteswithout annotation overlap can be accessed via 'model.no_annotation_overlap'
2025-02-11 16:31:26,576 - pycomo - WARNING - Not all reactions in the model are mass and charge balanced. To check which reactions are imbalanced, please run the get_unbalanced_reactions method of this CommunityModel object
2025-02-11 16:31:26,576 - pycomo - INFO - Generated community model.
[8]:
Name henson_community_model
Memory address 7f003738de50
Number of metabolites 51664
Number of reactions 55176
Number of genes 13885
Number of groups 68
Objective expression 1.0*community_biomass - 1.0*community_biomass_reverse_44dc1
Compartments Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c, Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_e, Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_medium, medium, fraction_reaction, Actinomyces_naeslundii_str_Howell_279_c, Actinomyces_naeslundii_str_Howell_279_e, Actinomyces_naeslundii_str_Howell_279_medium, Burkholderia_cepacia_GG4_e, Burkholderia_cepacia_GG4_c, Burkholderia_cepacia_GG4_medium, Veillonella_atypica_ACS_049_V_Sch6_c, Veillonella_atypica_ACS_049_V_Sch6_e, Veillonella_atypica_ACS_049_V_Sch6_medium, Neisseria_flavescens_SK114_c, Neisseria_flavescens_SK114_e, Neisseria_flavescens_SK114_medium, Staphylococcus_aureus_subsp_aureus_USA300_FPR3757_e, Staphylococcus_aureus_subsp_aureus_USA300_FPR3757_c, Staphylococcus_aureus_subsp_aureus_USA300_FPR3757_medium, Pseudomonas_aeruginosa_NCGM2_S1_c, Pseudomonas_aeruginosa_NCGM2_S1_e, Pseudomonas_aeruginosa_NCGM2_S1_medium, Achromobacter_xylosoxidans_NBRC_15126_c, Achromobacter_xylosoxidans_NBRC_15126_e, Achromobacter_xylosoxidans_NBRC_15126_medium, Streptococcus_sanguinis_SK36_e, Streptococcus_sanguinis_SK36_c, Streptococcus_sanguinis_SK36_medium, Haemophilus_influenzae_R2846_c, Haemophilus_influenzae_R2846_e, Haemophilus_influenzae_R2846_medium, Escherichia_coli_str_K_12_substr_MG1655_e, Escherichia_coli_str_K_12_substr_MG1655_c, Escherichia_coli_str_K_12_substr_MG1655_medium, Porphyromonas_endodontalis_ATCC_35406_c, Porphyromonas_endodontalis_ATCC_35406_e, Porphyromonas_endodontalis_ATCC_35406_medium, Prevotella_melaninogenica_ATCC_25845_c, Prevotella_melaninogenica_ATCC_25845_e, Prevotella_melaninogenica_ATCC_25845_medium, Ralstonia_sp_5_7_47FAA_c, Ralstonia_sp_5_7_47FAA_e, Ralstonia_sp_5_7_47FAA_medium, Granulicatella_adiacens_ATCC_49175_e, Granulicatella_adiacens_ATCC_49175_c, Granulicatella_adiacens_ATCC_49175_medium, Gemella_haemolysans_ATCC_10379_c, Gemella_haemolysans_ATCC_10379_e, Gemella_haemolysans_ATCC_10379_medium, Rothia_mucilaginosa_DY_18_c, Rothia_mucilaginosa_DY_18_e, Rothia_mucilaginosa_DY_18_medium

The output of the community model creation contains quite some lines of info and warnings. This is to be expected. Let’s have a look at the different types of info:

  1. Ignoring reaction ‘EX_4abz_medium’ since it already exists. This line will come up if a reaction is present in two different community member models under the same ID. This will only happen for exchange reactions in the exchange compartment and are therefor correct behaviour.

  2. WARNING: no annotation overlap found for matching metabolite mn2. Please make sure that the metabolite with this ID is indeed representing the same substance in all models! This warning comes up if exchange metabolites do not contain any matching annotation field. This can be an indicator that metabolites with the same ID are merged, but they represent different chemicals. Another common cause is that no annotation was given for this metabolite in one of the models.

  3. WARNING: matching of the metabolite CO2_EX is unbalanced (mass and/or charge). Please manually curate this metabolite for a mass and charge balanced model! This warning means that the formula of an exchange metabolite was different between member models. This can be due to the formula being omitted in some of the models. The other reason is that the metabolites differ in their mass or charge. As this would lead to generation or loss of matter from nothing, these issues need to be resolved for a consistent metabolic model.

Summary and report

The community model object has two utility methods to display information on the model.

  • Summary behaves the same as the summary method of COBRApy, displaying the the solution of FBA and its exchange metabolites. In the CommunityModel summary, the exchange reactions of metabolites responsible for scaling the flux bounds to the community composition are hidden.

  • The report function displays information on the model structure: the number of metabolites, reactions, genes, etc., but also quality control measures on mass and charge balance and internal loops.

[9]:
com_model_obj.summary()
[9]:

Objective

1.0 community_biomass = 1.0

Uptake

Metabolite Reaction Flux C-Number C-Flux
_26dap_M_medium EX__26dap_M_medium 0.02501 7 0.06%
_2dmmq8_medium EX__2dmmq8_medium 0.003097 50 0.05%
adn_medium EX_adn_medium 3.582 10 12.59%
ala_L_medium EX_ala_L_medium 0.503 3 0.53%
amp_medium EX_amp_medium 0.8121 10 2.86%
arg_L_medium EX_arg_L_medium 8.031 6 16.94%
asn_L_medium EX_asn_L_medium 0.2008 4 0.28%
asp_L_medium EX_asp_L_medium 0.2008 4 0.28%
ca2_medium EX_ca2_medium 0.003097 0 0.00%
cgly_medium EX_cgly_medium 0.003097 5 0.01%
cl_medium EX_cl_medium 0.003097 0 0.00%
cobalt2_medium EX_cobalt2_medium 0.003096 0 0.00%
cu2_medium EX_cu2_medium 0.003097 0 0.00%
cys_L_medium EX_cys_L_medium 0.08234 3 0.09%
cytd_medium EX_cytd_medium 0.09933 9 0.31%
dad_2_medium EX_dad_2_medium 7.679 10 27.00%
dgsn_medium EX_dgsn_medium 0.1599 10 0.56%
fe2_medium EX_fe2_medium 0.003096 0 0.00%
fe3_medium EX_fe3_medium 0.003097 0 0.00%
gln_L_medium EX_gln_L_medium 0.2074 5 0.36%
glyleu_medium EX_glyleu_medium 0.4606 8 1.30%
h_medium EX_h_medium 1.543 0 0.00%
his_L_medium EX_his_L_medium 0.3013 6 0.64%
ile_L_medium EX_ile_L_medium 0.327 6 0.69%
k_medium EX_k_medium 0.003097 0 0.00%
lys_L_medium EX_lys_L_medium 0.2854 6 0.60%
met_L_medium EX_met_L_medium 0.134 5 0.24%
mg2_medium EX_mg2_medium 0.003096 0 0.00%
mn2_medium EX_mn2_medium 0.003096 0 0.00%
mqn8_medium EX_mqn8_medium 0.003097 51 0.06%
nac_medium EX_nac_medium 0.006193 6 0.01%
o2_medium EX_o2_medium 0.003097 0 0.00%
phe_L_medium EX_phe_L_medium 0.1545 9 0.49%
pheme_medium EX_pheme_medium 0.003097 34 0.04%
pnto_R_medium EX_pnto_R_medium 0.006193 9 0.02%
pro_L_medium EX_pro_L_medium 0.1844 5 0.32%
ptrc_medium EX_ptrc_medium 0.003097 4 0.00%
q8_medium EX_q8_medium 0.003097 49 0.05%
ribflv_medium EX_ribflv_medium 0.006193 17 0.04%
sheme_medium EX_sheme_medium 0.003097 42 0.05%
so4_medium EX_so4_medium 0.003096 0 0.00%
spmd_medium EX_spmd_medium 0.003096 7 0.01%
succ_medium EX_succ_medium 0.0462 4 0.06%
thm_medium EX_thm_medium 0.003097 12 0.01%
thr_L_medium EX_thr_L_medium 0.4718 4 0.66%
trp_L_medium EX_trp_L_medium 0.0472 11 0.18%
ttdca_medium EX_ttdca_medium 0.1501 14 0.74%
tyr_L_medium EX_tyr_L_medium 0.1207 9 0.38%
uri_medium EX_uri_medium 9.752 9 30.86%
val_L_medium EX_val_L_medium 0.3522 5 0.62%
zn2_medium EX_zn2_medium 0.003096 0 0.00%

Secretion

Metabolite Reaction Flux C-Number C-Flux
acald_medium EX_acald_medium -8.505 2 6.94%
ade_medium EX_ade_medium -11.93 5 24.33%
but_medium EX_but_medium -5.478 4 8.94%
co2_medium EX_co2_medium -20.76 1 8.47%
dcyt_medium EX_dcyt_medium -9.644 9 35.42%
gcald_medium EX_gcald_medium -0.00929 2 0.01%
nh4_medium EX_nh4_medium -6.363 0 0.00%
orn_medium EX_orn_medium -7.785 5 15.88%
cpd11416_medium community_biomass -1 0 0.00%
[10]:
com_model_obj.report();
2025-02-11 16:32:21,033 - pycomo - INFO - Note: The model has more than 5000 reactions. Calculation of loops is skipped, as this would take some time. If needed, please run manually via .get_loops()
Name: henson_community_model
------------------
Model overview
Model structure: fixed growth rate
# Metabolites: 51664
# Constraint (f-) Metabolites: 31974
# Model Metabolites: 19690
# Reactions: 55176
# Constraint (f-) Reactions: 31973
# Model Reactions: 23203
# Genes: 13885
# Members: 17
Members:
        Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586
        Actinomyces_naeslundii_str_Howell_279
        Burkholderia_cepacia_GG4
        Veillonella_atypica_ACS_049_V_Sch6
        Neisseria_flavescens_SK114
        Staphylococcus_aureus_subsp_aureus_USA300_FPR3757
        Pseudomonas_aeruginosa_NCGM2_S1
        Achromobacter_xylosoxidans_NBRC_15126
        Streptococcus_sanguinis_SK36
        Haemophilus_influenzae_R2846
        Escherichia_coli_str_K_12_substr_MG1655
        Porphyromonas_endodontalis_ATCC_35406
        Prevotella_melaninogenica_ATCC_25845
        Ralstonia_sp_5_7_47FAA
        Granulicatella_adiacens_ATCC_49175
        Gemella_haemolysans_ATCC_10379
        Rothia_mucilaginosa_DY_18
Objective in direction max:
        1.0*community_biomass - 1.0*community_biomass_reverse_44dc1
------------------
Model quality
# Reactions unbalanced: 235
# Reactions able to carry flux without a medium: NaN

Setting the growth rate

By default the community model object will have the structure of fixe growth rate. This means, the fractions of the community member abundance is allowed to vary during simulations, but the individual and community growth rate is set to a fixed value (default: 1.0). The next thing we will try is to set the community growth rate to a different value and do a FBA.

[11]:
com_model_obj.apply_fixed_growth_rate(0.5)
com_model_obj.summary()
[11]:

Objective

1.0 community_biomass = 0.5

Uptake

Metabolite Reaction Flux C-Number C-Flux
_26dap_M_medium EX__26dap_M_medium 0.01251 7 0.06%
_2dmmq8_medium EX__2dmmq8_medium 0.001548 50 0.05%
adn_medium EX_adn_medium 1.791 10 12.59%
ala_L_medium EX_ala_L_medium 0.2515 3 0.53%
amp_medium EX_amp_medium 0.406 10 2.86%
arg_L_medium EX_arg_L_medium 4.016 6 16.94%
asn_L_medium EX_asn_L_medium 0.1004 4 0.28%
asp_L_medium EX_asp_L_medium 0.1004 4 0.28%
ca2_medium EX_ca2_medium 0.001548 0 0.00%
cgly_medium EX_cgly_medium 0.001548 5 0.01%
cl_medium EX_cl_medium 0.001548 0 0.00%
cobalt2_medium EX_cobalt2_medium 0.001548 0 0.00%
cu2_medium EX_cu2_medium 0.001548 0 0.00%
cys_L_medium EX_cys_L_medium 0.04117 3 0.09%
cytd_medium EX_cytd_medium 0.04967 9 0.31%
dad_2_medium EX_dad_2_medium 3.839 10 27.00%
dgsn_medium EX_dgsn_medium 0.07996 10 0.56%
fe2_medium EX_fe2_medium 0.001548 0 0.00%
fe3_medium EX_fe3_medium 0.001548 0 0.00%
gln_L_medium EX_gln_L_medium 0.1037 5 0.36%
glyleu_medium EX_glyleu_medium 0.2303 8 1.30%
h_medium EX_h_medium 0.7715 0 0.00%
his_L_medium EX_his_L_medium 0.1506 6 0.64%
ile_L_medium EX_ile_L_medium 0.1635 6 0.69%
k_medium EX_k_medium 0.001548 0 0.00%
lys_L_medium EX_lys_L_medium 0.1427 6 0.60%
met_L_medium EX_met_L_medium 0.067 5 0.24%
mg2_medium EX_mg2_medium 0.001548 0 0.00%
mn2_medium EX_mn2_medium 0.001548 0 0.00%
mqn8_medium EX_mqn8_medium 0.001548 51 0.06%
nac_medium EX_nac_medium 0.003096 6 0.01%
o2_medium EX_o2_medium 0.001548 0 0.00%
phe_L_medium EX_phe_L_medium 0.07726 9 0.49%
pheme_medium EX_pheme_medium 0.001548 34 0.04%
pnto_R_medium EX_pnto_R_medium 0.003096 9 0.02%
pro_L_medium EX_pro_L_medium 0.09218 5 0.32%
ptrc_medium EX_ptrc_medium 0.001548 4 0.00%
q8_medium EX_q8_medium 0.001548 49 0.05%
ribflv_medium EX_ribflv_medium 0.003097 17 0.04%
sheme_medium EX_sheme_medium 0.001548 42 0.05%
so4_medium EX_so4_medium 0.001548 0 0.00%
spmd_medium EX_spmd_medium 0.001548 7 0.01%
succ_medium EX_succ_medium 0.0231 4 0.06%
thm_medium EX_thm_medium 0.001548 12 0.01%
thr_L_medium EX_thr_L_medium 0.2359 4 0.66%
trp_L_medium EX_trp_L_medium 0.0236 11 0.18%
ttdca_medium EX_ttdca_medium 0.07503 14 0.74%
tyr_L_medium EX_tyr_L_medium 0.06034 9 0.38%
uri_medium EX_uri_medium 4.876 9 30.86%
val_L_medium EX_val_L_medium 0.1761 5 0.62%
zn2_medium EX_zn2_medium 0.001548 0 0.00%

Secretion

Metabolite Reaction Flux C-Number C-Flux
acald_medium EX_acald_medium -4.252 2 6.94%
ade_medium EX_ade_medium -5.963 5 24.33%
but_medium EX_but_medium -2.739 4 8.94%
co2_medium EX_co2_medium -10.38 1 8.47%
dcyt_medium EX_dcyt_medium -4.822 9 35.42%
gcald_medium EX_gcald_medium -0.004645 2 0.01%
nh4_medium EX_nh4_medium -3.182 0 0.00%
orn_medium EX_orn_medium -3.892 5 15.88%
cpd11416_medium community_biomass -0.5 0 0.00%

Setting the community member composition

The model structure can be changed to fixed abundance, but variable growth rate. To do so, a conversion function needs to be called. Here we then change the community abundance to equal abundances.

[12]:
com_model_obj.convert_to_fixed_abundance()
abundance_dict = com_model_obj.generate_equal_abundance_dict()
com_model_obj.apply_fixed_abundance(abundance_dict)
com_model_obj.summary()
[12]:

Objective

1.0 community_biomass = 43.84820241414374

Uptake

Metabolite Reaction Flux C-Number C-Flux
_12dgr180_medium EX__12dgr180_medium 0.3429 39 0.19%
_26dap_M_medium EX__26dap_M_medium 0.4749 7 0.05%
_2dmmq8_medium EX__2dmmq8_medium 0.1014 50 0.07%
_2obut_medium EX__2obut_medium 106.7 4 6.13%
_3mop_medium EX__3mop_medium 18.17 6 1.57%
_4abz_medium EX__4abz_medium 0.0854 7 0.01%
_4hbz_medium EX__4hbz_medium 0.05693 7 0.01%
_5mta_medium EX__5mta_medium 0.3696 11 0.06%
acgam_medium EX_acgam_medium 36.1 8 4.15%
acnam_medium EX_acnam_medium 1.502 11 0.24%
actn_R_medium EX_actn_R_medium 52.66 4 3.02%
adn_medium EX_adn_medium 10.79 10 1.55%
alagln_medium EX_alagln_medium 48.97 8 5.63%
alahis_medium EX_alahis_medium 13.11 9 1.69%
alathr_medium EX_alathr_medium 6.241 7 0.63%
amp_medium EX_amp_medium 6.277 10 0.90%
arab_D_medium EX_arab_D_medium 0.1935 5 0.01%
arg_L_medium EX_arg_L_medium 46.94 6 4.04%
asn_L_medium EX_asn_L_medium 6.255 4 0.36%
ca2_medium EX_ca2_medium 0.2225 0 0.00%
cgly_medium EX_cgly_medium 0.5141 5 0.04%
chtbs_medium EX_chtbs_medium 7.657 16 1.76%
cit_medium EX_cit_medium 17.49 6 1.51%
cl_medium EX_cl_medium 0.2225 0 0.00%
cobalt2_medium EX_cobalt2_medium 0.2225 0 0.00%
cu2_medium EX_cu2_medium 0.2225 0 0.00%
cys_L_medium EX_cys_L_medium 2.619 3 0.11%
cytd_medium EX_cytd_medium 2.429 9 0.31%
dad_2_medium EX_dad_2_medium 48.65 10 6.99%
ddca_medium EX_ddca_medium 0.6451 12 0.11%
dgsn_medium EX_dgsn_medium 14.45 10 2.08%
duri_medium EX_duri_medium 0.02266 9 0.00%
fe2_medium EX_fe2_medium 0.1406 0 0.00%
fe3_medium EX_fe3_medium 0.3489 0 0.00%
fol_medium EX_fol_medium 0.3895 19 0.11%
fru_medium EX_fru_medium 56.58 6 4.87%
fum_medium EX_fum_medium 15.89 4 0.91%
gam_medium EX_gam_medium 6.405 6 0.55%
gcald_medium EX_gcald_medium 0.05684 2 0.00%
glc_D_medium EX_glc_D_medium 2.409 6 0.21%
gln_L_medium EX_gln_L_medium 52.68 5 3.78%
glyasn_medium EX_glyasn_medium 55.54 6 4.78%
glyc3p_medium EX_glyc3p_medium 88.1 3 3.79%
glycys_medium EX_glycys_medium 0.5636 5 0.04%
glyleu_medium EX_glyleu_medium 76 8 8.73%
glymet_medium EX_glymet_medium 0.7749 7 0.08%
glyphe_medium EX_glyphe_medium 1.818 11 0.29%
glypro_medium EX_glypro_medium 11.66 7 1.17%
glytyr_medium EX_glytyr_medium 1.146 11 0.18%
gsn_medium EX_gsn_medium 0.3892 10 0.06%
gthox_medium EX_gthox_medium 0.003993 20 0.00%
gthrd_medium EX_gthrd_medium 0.03195 10 0.00%
his_L_medium EX_his_L_medium 2.319 6 0.20%
hxan_medium EX_hxan_medium 2.697 5 0.19%
inulin_medium EX_inulin_medium 0.6138 180 1.59%
k_medium EX_k_medium 0.2225 0 0.00%
lys_L_medium EX_lys_L_medium 13.26 6 1.14%
man_medium EX_man_medium 16.75 6 1.44%
met_L_medium EX_met_L_medium 2.034 5 0.15%
metala_medium EX_metala_medium 2.891 8 0.33%
mg2_medium EX_mg2_medium 0.2225 0 0.00%
mn2_medium EX_mn2_medium 0.2225 0 0.00%
mqn7_medium EX_mqn7_medium 0.04792 46 0.03%
mqn8_medium EX_mqn8_medium 0.1173 51 0.09%
ncam_medium EX_ncam_medium 0.01597 6 0.00%
nmn_medium EX_nmn_medium 12.43 11 1.96%
no3_medium EX_no3_medium 0.4119 0 0.00%
o2_medium EX_o2_medium 227 0 0.00%
ocdca_medium EX_ocdca_medium 2.289 18 0.59%
phe_L_medium EX_phe_L_medium 4.973 9 0.64%
pheme_medium EX_pheme_medium 0.1823 34 0.09%
phpyr_medium EX_phpyr_medium 0.3986 9 0.05%
pnto_R_medium EX_pnto_R_medium 0.243 9 0.03%
pro_L_medium EX_pro_L_medium 21.15 5 1.52%
ptrc_medium EX_ptrc_medium 0.1184 4 0.01%
pullulan1200_medium EX_pullulan1200_medium 0.02527 7200 2.61%
pydx_medium EX_pydx_medium 0.1864 8 0.02%
pyr_medium EX_pyr_medium 38.37 3 1.65%
q8_medium EX_q8_medium 0.1094 49 0.08%
ribflv_medium EX_ribflv_medium 0.1958 17 0.05%
ser_L_medium EX_ser_L_medium 48.29 3 2.08%
sheme_medium EX_sheme_medium 0.1378 42 0.08%
so4_medium EX_so4_medium 0.2225 0 0.00%
spmd_medium EX_spmd_medium 0.1743 7 0.02%
stys_medium EX_stys_medium 0.2655 24 0.09%
sucr_medium EX_sucr_medium 26.43 12 4.55%
thm_medium EX_thm_medium 0.1823 12 0.03%
thr_L_medium EX_thr_L_medium 11.84 4 0.68%
thymd_medium EX_thymd_medium 0.3716 10 0.05%
trp_L_medium EX_trp_L_medium 1.641 11 0.26%
ttdca_medium EX_ttdca_medium 2.129 14 0.43%
tyr_L_medium EX_tyr_L_medium 12.37 9 1.60%
uri_medium EX_uri_medium 14.92 9 1.93%
val_L_medium EX_val_L_medium 13.35 5 0.96%
zn2_medium EX_zn2_medium 0.2225 0 0.00%

Secretion

Metabolite Reaction Flux C-Number C-Flux
_4hphac_medium EX__4hphac_medium -8.28 8 1.26%
ac_medium EX_ac_medium -576.1 2 21.93%
ade_medium EX_ade_medium -61.57 5 5.86%
ala_L_medium EX_ala_L_medium -1.969 3 0.11%
asp_L_medium EX_asp_L_medium -94.37 4 7.18%
but_medium EX_but_medium -23.2 4 1.77%
co2_medium EX_co2_medium -101.8 1 1.94%
etoh_medium EX_etoh_medium -71.47 2 2.72%
for_medium EX_for_medium -384.4 1 7.32%
glu_L_medium EX_glu_L_medium -112.3 5 10.69%
gly_medium EX_gly_medium -116.3 2 4.43%
gua_medium EX_gua_medium -10.17 5 0.97%
h2o_medium EX_h2o_medium -521.8 0 0.00%
h2s_medium EX_h2s_medium -0.1468 0 0.00%
ile_L_medium EX_ile_L_medium -4.345 6 0.50%
lac_D_medium EX_lac_D_medium -72.18 3 4.12%
lac_L_medium EX_lac_L_medium -13.8 3 0.79%
leu_L_medium EX_leu_L_medium -56.74 6 6.48%
mal_L_medium EX_mal_L_medium -66.12 4 5.03%
nac_medium EX_nac_medium -12 6 1.37%
nh4_medium EX_nh4_medium -336.8 0 0.00%
orn_medium EX_orn_medium -33.57 5 3.19%
pi_medium EX_pi_medium -32.8 0 0.00%
ppa_medium EX_ppa_medium -109.6 3 6.26%
ppi_medium EX_ppi_medium -15.5 0 0.00%
succ_medium EX_succ_medium -66.71 4 5.08%
ura_medium EX_ura_medium -11.12 4 0.85%
urea_medium EX_urea_medium -8.377 1 0.16%
cpd11416_medium community_biomass -43.85 0 0.00%

Saving and loading community models

Community model objects can be saved and loaded into SBML files. This is different from the other available option to save the cobra model of the community model objects, as the abundance fractions of the organisms are written into the file as well. Saving and loading the community model can be done like this:

[13]:
com_model_obj.save("../data/toy/output/henson_com_model.xml")
[14]:
com_model_obj_loaded = pycomo.CommunityModel.load("../data/toy/output/henson_com_model.xml")
[15]:
com_model_obj_loaded
[15]:
<pycomo.pycomo_models.CommunityModel at 0x7efffe53f450>
[16]:
com_model_obj_loaded.model.optimize()
[16]:
Optimal solution with objective value 43.848
fluxes reduced_costs
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__15DAPt 0.000000 0.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__1P4H2CBXLAH_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c 0.000000 0.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__26DAPLLAT_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c -7.830932 3.083408e-33
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__2DHPL_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c 0.000000 0.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__2DMMQ8abc 0.007987 -2.157042e-32
... ... ...
SK_Rothia_mucilaginosa_DY_18_biomass429_ub 0.562442 0.000000e+00
SK_Rothia_mucilaginosa_DY_18_to_community_biomass_ub 0.562442 0.000000e+00
f_final 1.000000 0.000000e+00
abundance_reaction 43.848202 4.302114e-16
community_biomass 43.848202 0.000000e+00

55176 rows × 2 columns

Quality Checks

One of the quality checks that should be done is to look into all unbalanced reactions (mass and charge) in the entire model. As said before, such reactions should only exist in the case of boundary reactions, such as exchange, sink and source reactions.

[17]:
unbalanced_reactions = com_model_obj.get_unbalanced_reactions()

print(f"{len(unbalanced_reactions)} unbalanced reactions")
print(f"Example reactions:")
for rxn in list(unbalanced_reactions.keys())[:10]:
    print(f"{rxn.id}: {unbalanced_reactions[rxn]}")
235 unbalanced reactions
Example reactions:
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_DM_5MTR_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'C': -6.0, 'H': -12.0, 'O': -4.0, 'S': -1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_DM_dhptd_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'C': -5.0, 'H': -8.0, 'O': -4.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_DM_hcys_L_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'C': -4.0, 'H': -9.0, 'N': -1.0, 'O': -2.0, 'S': -1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_EX_biomass_e_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': -1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_NADH8: {'H': 3.552713678800501e-15}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_SHCHCC2_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'charge': -2.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_dreplication_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_pbiosynthesis_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_rtranscription_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_sink_gthrd_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'charge': 1.0, 'C': -10.0, 'H': -16.0, 'N': -3.0, 'O': -6.0, 'S': -1.0}

Analysis of community models

PyCoMo offers the option to calculate all potential exchange metabolites and cross-feeding interactions in a community, independent of the community composition. The example for this part will be a three member community published by Koch et al. 2019 (https://doi.org/10.1371/journal.pcbi.1006759). The three member organisms are representatives of functional guilds in a biogas community.

Creating the community model

We repeat the steps as before.

[18]:
test_model_dir = "../data/use_case/koch"
named_models = pycomo.load_named_models_from_dir(test_model_dir)
'3PG' is not a valid SBML 'SId'.
'2PG' is not a valid SBML 'SId'.
'2PG__PEP' is not a valid SBML 'SId'.
'3PG__2PG' is not a valid SBML 'SId'.
'0Pyr__AcCoA' is not a valid SBML 'SId'.
'3PG' is not a valid SBML 'SId'.
'2PG' is not a valid SBML 'SId'.
'5CHOMPT' is not a valid SBML 'SId'.
'3PG__2PG__3PG' is not a valid SBML 'SId'.
'5CHOMPT__CHH4MPT' is not a valid SBML 'SId'.
'5CHOMPT' is not a valid SBML 'SId'.
'3PG' is not a valid SBML 'SId'.
'2PG' is not a valid SBML 'SId'.
'2PG__3PG' is not a valid SBML 'SId'.
'3PG__DPG' is not a valid SBML 'SId'.
'5CHOMPT__CHH4MPT' is not a valid SBML 'SId'.
[19]:
named_models
[19]:
{'dv': <Model CNA_DV at 0x7effe098f590>,
 'mb': <Model CNA_MB at 0x7effe087aad0>,
 'mh': <Model CNA_MM at 0x7effe08453d0>}
[20]:
single_org_models = []
for name, model in named_models.items():
    single_org_model = pycomo.SingleOrganismModel(model, name)
    single_org_models.append(single_org_model)

community_name = "koch_community_model"
com_model_obj = pycomo.CommunityModel(single_org_models, community_name)

With the community model generated, we set the medium for the analysis, as done by Koch et al.

[21]:
medium = {
    'EX_CO2_EX_medium': 1000.0,
    'EX_Eth_EX_medium': 1000.0,
    'EX_BM_tot_medium': 1000.0
}
com_model_obj.medium = medium
com_model_obj.apply_medium()

# Some metabolites are not allowed to accumulate in the medium.
com_model_obj.model.reactions.get_by_id("EX_Form_EX_medium").upper_bound = 0.
com_model_obj.model.reactions.get_by_id("EX_H2_EX_medium").upper_bound = 0.
2025-02-11 16:36:37,472 - pycomo - INFO - No community model generated yet. Generating now:
2025-02-11 16:36:37,495 - pycomo - INFO - Identified biomass reaction from objective: r_BMDV2BMc
2025-02-11 16:36:37,646 - pycomo - INFO - Identified biomass reaction from objective: BM_Synth
2025-02-11 16:36:37,836 - pycomo - INFO - Identified biomass reaction from objective: BM_Synth
2025-02-11 16:36:38,015 - pycomo - WARNING - No annotation overlap found for matching several metabolites (8). Please make sure that the matched metabolites are indeed representing the same substance in all models! The list of metaboliteswithout annotation overlap can be accessed via 'model.no_annotation_overlap'
2025-02-11 16:36:38,088 - pycomo - INFO - Generated community model.

Calculating potential metabolite exchange

All potential exchange metabolite fluxes and cross-feeding interactions can be calculated with the potential_metabolite_exchanges method. This is a single FVA, but with a minimum objective of 0 and relaxed constraints. All reaction constraints are changed to include the value 0, which circumvents cases where a specific flux through a reaction is required, leading to infeasible solutions for certain community compositions.

[22]:
com_model_obj.potential_metabolite_exchanges()
2025-02-11 16:36:41,581 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:41,581 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:41,581 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:41,583 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:42,374 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:42,411 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:42,411 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:42,413 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:43,251 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:43,252 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:43,252 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:43,254 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:44,118 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:44,118 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:44,118 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:44,122 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:45,089 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:45,091 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:45,091 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:45,093 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:46,027 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:46,028 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:46,028 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:46,029 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:46,956 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:46,957 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:46,957 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:46,959 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:47,001 - pycomo - INFO - Processed 2.82% of find loops steps
2025-02-11 16:36:47,053 - pycomo - INFO - Processed 5.63% of find loops steps
2025-02-11 16:36:47,075 - pycomo - INFO - Processed 8.45% of find loops steps
2025-02-11 16:36:47,095 - pycomo - INFO - Processed 11.27% of find loops steps
2025-02-11 16:36:47,114 - pycomo - INFO - Processed 14.08% of find loops steps
2025-02-11 16:36:47,156 - pycomo - INFO - Processed 16.9% of find loops steps
2025-02-11 16:36:47,206 - pycomo - INFO - Processed 19.72% of find loops steps
2025-02-11 16:36:47,217 - pycomo - INFO - Processed 22.54% of find loops steps
2025-02-11 16:36:47,246 - pycomo - INFO - Processed 25.35% of find loops steps
2025-02-11 16:36:47,275 - pycomo - INFO - Processed 28.17% of find loops steps
2025-02-11 16:36:47,319 - pycomo - INFO - Processed 30.99% of find loops steps
2025-02-11 16:36:47,336 - pycomo - INFO - Processed 33.8% of find loops steps
2025-02-11 16:36:47,372 - pycomo - INFO - Processed 36.62% of find loops steps
2025-02-11 16:36:47,412 - pycomo - INFO - Processed 39.44% of find loops steps
2025-02-11 16:36:47,449 - pycomo - INFO - Processed 42.25% of find loops steps
2025-02-11 16:36:47,458 - pycomo - INFO - Processed 45.07% of find loops steps
2025-02-11 16:36:47,495 - pycomo - INFO - Processed 47.89% of find loops steps
2025-02-11 16:36:47,540 - pycomo - INFO - Processed 50.7% of find loops steps
2025-02-11 16:36:47,570 - pycomo - INFO - Processed 53.52% of find loops steps
2025-02-11 16:36:47,603 - pycomo - INFO - Processed 56.34% of find loops steps
2025-02-11 16:36:47,659 - pycomo - INFO - Processed 59.15% of find loops steps
2025-02-11 16:36:47,678 - pycomo - INFO - Processed 61.97% of find loops steps
2025-02-11 16:36:47,714 - pycomo - INFO - Processed 64.79% of find loops steps
2025-02-11 16:36:47,762 - pycomo - INFO - Processed 67.61% of find loops steps
2025-02-11 16:36:47,786 - pycomo - INFO - Processed 70.42% of find loops steps
2025-02-11 16:36:47,799 - pycomo - INFO - Processed 73.24% of find loops steps
2025-02-11 16:36:47,837 - pycomo - INFO - Processed 76.06% of find loops steps
2025-02-11 16:36:47,886 - pycomo - INFO - Processed 78.87% of find loops steps
2025-02-11 16:36:47,908 - pycomo - INFO - Processed 81.69% of find loops steps
2025-02-11 16:36:47,919 - pycomo - INFO - Processed 84.51% of find loops steps
2025-02-11 16:36:47,970 - pycomo - INFO - Processed 87.32% of find loops steps
2025-02-11 16:36:48,010 - pycomo - INFO - Processed 90.14% of find loops steps
2025-02-11 16:36:48,028 - pycomo - INFO - Processed 92.96% of find loops steps
2025-02-11 16:36:48,045 - pycomo - INFO - Processed 95.77% of find loops steps
2025-02-11 16:36:48,063 - pycomo - INFO - Processed 98.59% of find loops steps
2025-02-11 16:36:48,071 - pycomo - INFO - Processed 100.0% of find loops steps
2025-02-11 16:36:49,148 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:49,149 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:49,149 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:49,151 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:49,278 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:50,030 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:50,031 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:50,031 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:50,032 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:50,144 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:50,881 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:50,882 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:50,882 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:50,884 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:50,995 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:51,730 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:51,730 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:51,730 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:51,732 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:51,843 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:52,583 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:52,584 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:52,584 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:52,585 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:52,696 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:53,432 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:53,432 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:53,433 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:53,434 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:53,546 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:54,279 - pycomo - INFO - Logger initialized.
2025-02-11 16:36:54,279 - pycomo - INFO - Process Pool Logger initialized.
2025-02-11 16:36:54,280 - pycomo - INFO - Utils Logger initialized.
2025-02-11 16:36:54,281 - pycomo - INFO - Multiprocess Logger initialized.
2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_H2_TF_dv_External_Species
2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_CO2_TF_dv_External_Species
2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_Form_TF_dv_External_Species
2025-02-11 16:36:54,574 - pycomo - INFO - Processed 27.78% of fva steps
2025-02-11 16:36:54,596 - pycomo - INFO - Processed 55.56% of fva steps
2025-02-11 16:36:54,608 - pycomo - INFO - Loop correction will be applied on mh_TF_H2_TF_mh_External_Species
2025-02-11 16:36:54,622 - pycomo - INFO - Loop correction will be applied on mh_TF_CO2_TF_mh_External_Species
2025-02-11 16:36:54,623 - pycomo - INFO - Log level set to 20
2025-02-11 16:36:54,628 - pycomo - INFO - Loop correction will be applied on mh_TF_Form_TF_mh_External_Species
2025-02-11 16:36:54,747 - pycomo - INFO - Processed 83.33% of fva steps
2025-02-11 16:36:54,749 - pycomo - INFO - Processed 100.0% of fva steps
[22]:
metabolite_id metabolite_name cross_feeding produced_by consumed_by
0 H2_EX_medium H2_external True [dv] [mb, mh]
1 Ac_EX_medium acetate_external True [dv] [mb]
2 CO2_EX_medium CO2_external True [mb, mh] [dv, mb, mh]
3 Form_EX_medium formate_external True [dv] [mh]
4 SO4_EX_medium sulfate_external False [] []
5 H2S_EX_medium hydrogensulfide_external False [] []
6 Eth_EX_medium ethanol_external False [] [dv]
7 Lac_EX_medium lactate_external False [] []
8 Pyr_EX_medium pyruvate_external False [] []
9 CH4_EX_medium nethane_external False [mb, mh] []
10 MetOH_EX_medium nethanol_external False [] []
11 BM_tot_medium total_biomass False [] []
12 cpd11416_medium Community Biomass False [dv, mb, mh] []

Plotting the maxiumum growth rate over the composition space

[23]:
import pandas as pd

# Iterate over the fractions in steps of 0.01
com_model_obj.convert_to_fixed_abundance()
rows = []
for i in range (0,100,1):  # fraction of D. vulgaris
    for j in range (0, 100-i, 1): # fraction of M. hungatei
        if (100-i-j) < 0:
            continue

        abundances = {"dv": i/100., "mh": j/100., "mb": (100-i-j)/100.}

        # Apply the abuyndances
        com_model_obj.apply_fixed_abundance(abundances)

        # Reapply the bound restrictions of the exchange reactions
        com_model_obj.model.reactions.get_by_id("EX_Form_EX_medium").upper_bound = 0.
        com_model_obj.model.reactions.get_by_id("EX_H2_EX_medium").upper_bound = 0.

        # Calculate the optimal growth rate
        solution = com_model_obj.model.optimize()
        growth = 0. if str(solution.status) == "infeasible" else solution.objective_value
        rows.append({"dv": i/100., "mh": j/100., "growth": growth})

growth_df = pd.DataFrame(rows)
[24]:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme()

# Restructure dataframe for heatmap
growth_df_pivot = growth_df.pivot(index="mh", columns="dv", values="growth")

# Draw a heatmap with the numeric values in each cell
f, ax = plt.subplots(figsize=(9, 6))
sns.heatmap(growth_df_pivot, ax=ax)
ax.invert_yaxis()
_images/PyCoMo_basics_42_0.png
[ ]: