{ "cells": [ { "cell_type": "markdown", "id": "287f0572", "metadata": {}, "source": [ "# PyCoMo Basics #\n", "PyCoMo is a **Py**thon **Co**mmunity metabolic **Mo**delling package. In this tutorial, the core features will be presented.\n", "\n", "The expected runtime for this notebook is approximately 10-30 minutes.\n", "\n", "## Setting up PyCoMo ##\n", "Clone the package from github. Next, we are going to import all the packages we need in this tutorial." ] }, { "cell_type": "code", "execution_count": 1, "id": "44deb93c", "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "import sys\n", "import cobra\n", "import os" ] }, { "cell_type": "markdown", "id": "5831a9de", "metadata": {}, "source": [ "### Importing PyCoMo ###\n", "As PyCoMo is currently only available as a local package, the direct path to the package directory needs to be used on import." ] }, { "cell_type": "code", "execution_count": 2, "id": "70fb1e07", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-02-11 16:28:11,142 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:28:11,144 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:28:11,145 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:28:11,146 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:28:11,148 - pycomo - INFO - Log level set to info\n" ] } ], "source": [ "path_root = \"../src\" # Change path according to your PyCoMo location\n", "sys.path.append(str(path_root))\n", "import pycomo\n", "pycomo.configure_logger(level=\"info\")" ] }, { "cell_type": "markdown", "id": "e2a2f74a", "metadata": {}, "source": [ "## Creating a Community Model ##\n", "The creation of a community model consists of 3 steps:\n", "1. Loading the member models\n", "2. Preparing the member models for merging\n", "3. Creating a community model\n", "\n", "### Loading the member models ###\n", "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!\n", "\n", "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)" ] }, { "cell_type": "code", "execution_count": 3, "id": "ec853706", "metadata": {}, "outputs": [], "source": [ "test_model_dir = \"../data/use_case/henson\"\n", "named_models = pycomo.load_named_models_from_dir(test_model_dir)" ] }, { "cell_type": "markdown", "id": "9073f98d", "metadata": {}, "source": [ "The models and file names were extracted and stored in named_models. Let's check the contents:" ] }, { "cell_type": "code", "execution_count": 4, "id": "dd10c4ed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586': ,\n", " 'Actinomyces_naeslundii_str_Howell_279': ,\n", " 'Burkholderia_cepacia_GG4': ,\n", " 'Veillonella_atypica_ACS_049_V_Sch6': ,\n", " 'Neisseria_flavescens_SK114': ,\n", " 'Staphylococcus_aureus_subsp_aureus_USA300_FPR3757': ,\n", " 'Pseudomonas_aeruginosa_NCGM2_S1': ,\n", " 'Achromobacter_xylosoxidans_NBRC_15126': ,\n", " 'Streptococcus_sanguinis_SK36': ,\n", " 'Haemophilus_influenzae_R2846': ,\n", " 'Escherichia_coli_str_K_12_substr_MG1655': ,\n", " 'Porphyromonas_endodontalis_ATCC_35406': ,\n", " 'Prevotella_melaninogenica_ATCC_25845': ,\n", " 'Ralstonia_sp_5_7_47FAA': ,\n", " 'Granulicatella_adiacens_ATCC_49175': ,\n", " 'Gemella_haemolysans_ATCC_10379': ,\n", " 'Rothia_mucilaginosa_DY_18': }" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "named_models" ] }, { "cell_type": "markdown", "id": "9ef303a1", "metadata": {}, "source": [ "### Preparing the models for merging ###\n", "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_." ] }, { "cell_type": "markdown", "id": "4d5bb946", "metadata": {}, "source": [ "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" ] }, { "cell_type": "code", "execution_count": 5, "id": "9cf08dfe", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Maximize\n", "1.0*biomass237 - 1.0*biomass237_reverse_f032e\n", "Maximize\n", "1.0*biomass492 - 1.0*biomass492_reverse_bc961\n", "Maximize\n", "1.0*biomass479 - 1.0*biomass479_reverse_1d1b2\n", "Maximize\n", "1.0*biomass116 - 1.0*biomass116_reverse_02324\n", "Maximize\n", "1.0*biomass339 - 1.0*biomass339_reverse_45ed6\n", "Maximize\n", "1.0*biomass042 - 1.0*biomass042_reverse_2a02b\n", "Maximize\n", "1.0*biomass345 - 1.0*biomass345_reverse_e128f\n", "Maximize\n", "1.0*biomass489 - 1.0*biomass489_reverse_62d1a\n", "Maximize\n", "1.0*biomass164 - 1.0*biomass164_reverse_ca493\n", "Maximize\n", "1.0*biomass252 - 1.0*biomass252_reverse_f6948\n", "Maximize\n", "1.0*biomass525 - 1.0*biomass525_reverse_5c178\n", "Maximize\n", "1.0*biomass326 - 1.0*biomass326_reverse_02060\n", "Maximize\n", "1.0*biomass276 - 1.0*biomass276_reverse_7f92e\n", "Maximize\n", "1.0*biomass525 - 1.0*biomass525_reverse_5c178\n", "Maximize\n", "1.0*biomass091 - 1.0*biomass091_reverse_7b6db\n", "Maximize\n", "1.0*biomass027 - 1.0*biomass027_reverse_af8dc\n", "Maximize\n", "1.0*biomass429 - 1.0*biomass429_reverse_9caa0\n" ] } ], "source": [ "for model in named_models.values():\n", " print(model.objective)" ] }, { "cell_type": "markdown", "id": "d9dfb23f", "metadata": {}, "source": [ "With the objective being the biomass function in all models, the biomass metabolite does not need to be specified." ] }, { "cell_type": "code", "execution_count": 6, "id": "36875e60", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586\n", "Actinomyces_naeslundii_str_Howell_279\n", "Burkholderia_cepacia_GG4\n", "Veillonella_atypica_ACS_049_V_Sch6\n", "Neisseria_flavescens_SK114\n", "Staphylococcus_aureus_subsp_aureus_USA300_FPR3757\n", "Pseudomonas_aeruginosa_NCGM2_S1\n", "Achromobacter_xylosoxidans_NBRC_15126\n", "Streptococcus_sanguinis_SK36\n", "Haemophilus_influenzae_R2846\n", "Escherichia_coli_str_K_12_substr_MG1655\n", "Porphyromonas_endodontalis_ATCC_35406\n", "Prevotella_melaninogenica_ATCC_25845\n", "Ralstonia_sp_5_7_47FAA\n", "Granulicatella_adiacens_ATCC_49175\n", "Gemella_haemolysans_ATCC_10379\n", "Rothia_mucilaginosa_DY_18\n" ] } ], "source": [ "single_org_models = []\n", "for name, model in named_models.items():\n", " print(name)\n", " single_org_model = pycomo.SingleOrganismModel(model, name)\n", " single_org_models.append(single_org_model)" ] }, { "cell_type": "markdown", "id": "5da570d0", "metadata": {}, "source": [ "### Creating a community model ###\n", "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." ] }, { "cell_type": "code", "execution_count": 7, "id": "652b4d73", "metadata": {}, "outputs": [], "source": [ "community_name = \"henson_community_model\"\n", "com_model_obj = pycomo.CommunityModel(single_org_models, community_name)" ] }, { "cell_type": "markdown", "id": "b237ca69", "metadata": {}, "source": [ "The cobra model of the community will generated the first time it is needed. We can enforce this now, by calling it via .model" ] }, { "cell_type": "code", "execution_count": 8, "id": "a7d9d60f", "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-02-11 16:28:32,249 - pycomo - INFO - No community model generated yet. Generating now:\n", "2025-02-11 16:28:32,428 - pycomo - INFO - Identified biomass reaction from objective: biomass237\n", "2025-02-11 16:28:32,428 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:28:37,567 - pycomo - INFO - Identified biomass reaction from objective: biomass492\n", "2025-02-11 16:28:37,567 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:28:44,909 - pycomo - INFO - Identified biomass reaction from objective: biomass479\n", "2025-02-11 16:28:44,909 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:28:59,680 - pycomo - INFO - Identified biomass reaction from objective: biomass116\n", "2025-02-11 16:28:59,681 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:29:06,508 - pycomo - INFO - Identified biomass reaction from objective: biomass339\n", "2025-02-11 16:29:06,509 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:29:13,745 - pycomo - INFO - Identified biomass reaction from objective: biomass042\n", "2025-02-11 16:29:13,746 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:29:24,477 - pycomo - INFO - Identified biomass reaction from objective: biomass345\n", "2025-02-11 16:29:24,478 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:29:37,701 - pycomo - INFO - Identified biomass reaction from objective: biomass489\n", "2025-02-11 16:29:37,702 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:29:52,668 - pycomo - INFO - Identified biomass reaction from objective: biomass164\n", "2025-02-11 16:29:52,668 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:01,601 - pycomo - INFO - Identified biomass reaction from objective: biomass252\n", "2025-02-11 16:30:01,601 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:11,188 - pycomo - INFO - Identified biomass reaction from objective: biomass525\n", "2025-02-11 16:30:11,189 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:27,457 - pycomo - INFO - Identified biomass reaction from objective: biomass326\n", "2025-02-11 16:30:27,458 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:32,670 - pycomo - INFO - Identified biomass reaction from objective: biomass276\n", "2025-02-11 16:30:32,670 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:39,208 - pycomo - INFO - Identified biomass reaction from objective: biomass525\n", "2025-02-11 16:30:39,209 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:49,904 - pycomo - INFO - Identified biomass reaction from objective: biomass091\n", "2025-02-11 16:30:49,904 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:30:55,715 - pycomo - INFO - Identified biomass reaction from objective: biomass027\n", "2025-02-11 16:30:55,715 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "2025-02-11 16:31:01,518 - pycomo - INFO - Identified biomass reaction from objective: biomass429\n", "2025-02-11 16:31:01,519 - pycomo - INFO - Note: no products in the objective function, adding biomass to it.\n", "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'\n", "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\n", "2025-02-11 16:31:26,576 - pycomo - INFO - Generated community model.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Namehenson_community_model
Memory address7f003738de50
Number of metabolites51664
Number of reactions55176
Number of genes13885
Number of groups68
Objective expression1.0*community_biomass - 1.0*community_biomass_reverse_44dc1
CompartmentsFusobacterium_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
" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj.model" ] }, { "cell_type": "markdown", "id": "f5b46f81", "metadata": {}, "source": [ "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:\n", "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.\n", "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.\n", "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." ] }, { "cell_type": "markdown", "id": "b0fb9a41", "metadata": {}, "source": [ "### Summary and report ###\n", "The community model object has two utility methods to display information on the model. \n", "- 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.\n", "- 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." ] }, { "cell_type": "code", "execution_count": 9, "id": "d4777b0e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "

Objective

1.0 community_biomass = 1.0

Uptake

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
_26dap_M_mediumEX__26dap_M_medium0.0250170.06%
_2dmmq8_mediumEX__2dmmq8_medium0.003097500.05%
adn_mediumEX_adn_medium3.5821012.59%
ala_L_mediumEX_ala_L_medium0.50330.53%
amp_mediumEX_amp_medium0.8121102.86%
arg_L_mediumEX_arg_L_medium8.031616.94%
asn_L_mediumEX_asn_L_medium0.200840.28%
asp_L_mediumEX_asp_L_medium0.200840.28%
ca2_mediumEX_ca2_medium0.00309700.00%
cgly_mediumEX_cgly_medium0.00309750.01%
cl_mediumEX_cl_medium0.00309700.00%
cobalt2_mediumEX_cobalt2_medium0.00309600.00%
cu2_mediumEX_cu2_medium0.00309700.00%
cys_L_mediumEX_cys_L_medium0.0823430.09%
cytd_mediumEX_cytd_medium0.0993390.31%
dad_2_mediumEX_dad_2_medium7.6791027.00%
dgsn_mediumEX_dgsn_medium0.1599100.56%
fe2_mediumEX_fe2_medium0.00309600.00%
fe3_mediumEX_fe3_medium0.00309700.00%
gln_L_mediumEX_gln_L_medium0.207450.36%
glyleu_mediumEX_glyleu_medium0.460681.30%
h_mediumEX_h_medium1.54300.00%
his_L_mediumEX_his_L_medium0.301360.64%
ile_L_mediumEX_ile_L_medium0.32760.69%
k_mediumEX_k_medium0.00309700.00%
lys_L_mediumEX_lys_L_medium0.285460.60%
met_L_mediumEX_met_L_medium0.13450.24%
mg2_mediumEX_mg2_medium0.00309600.00%
mn2_mediumEX_mn2_medium0.00309600.00%
mqn8_mediumEX_mqn8_medium0.003097510.06%
nac_mediumEX_nac_medium0.00619360.01%
o2_mediumEX_o2_medium0.00309700.00%
phe_L_mediumEX_phe_L_medium0.154590.49%
pheme_mediumEX_pheme_medium0.003097340.04%
pnto_R_mediumEX_pnto_R_medium0.00619390.02%
pro_L_mediumEX_pro_L_medium0.184450.32%
ptrc_mediumEX_ptrc_medium0.00309740.00%
q8_mediumEX_q8_medium0.003097490.05%
ribflv_mediumEX_ribflv_medium0.006193170.04%
sheme_mediumEX_sheme_medium0.003097420.05%
so4_mediumEX_so4_medium0.00309600.00%
spmd_mediumEX_spmd_medium0.00309670.01%
succ_mediumEX_succ_medium0.046240.06%
thm_mediumEX_thm_medium0.003097120.01%
thr_L_mediumEX_thr_L_medium0.471840.66%
trp_L_mediumEX_trp_L_medium0.0472110.18%
ttdca_mediumEX_ttdca_medium0.1501140.74%
tyr_L_mediumEX_tyr_L_medium0.120790.38%
uri_mediumEX_uri_medium9.752930.86%
val_L_mediumEX_val_L_medium0.352250.62%
zn2_mediumEX_zn2_medium0.00309600.00%

Secretion

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
acald_mediumEX_acald_medium-8.50526.94%
ade_mediumEX_ade_medium-11.93524.33%
but_mediumEX_but_medium-5.47848.94%
co2_mediumEX_co2_medium-20.7618.47%
dcyt_mediumEX_dcyt_medium-9.644935.42%
gcald_mediumEX_gcald_medium-0.0092920.01%
nh4_mediumEX_nh4_medium-6.36300.00%
orn_mediumEX_orn_medium-7.785515.88%
cpd11416_mediumcommunity_biomass-100.00%
" ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj.summary()" ] }, { "cell_type": "code", "execution_count": 10, "id": "edcc65e6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "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()\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Name: henson_community_model\n", "------------------\n", "Model overview\n", "Model structure: fixed growth rate\n", "# Metabolites: 51664\n", "# Constraint (f-) Metabolites: 31974\n", "# Model Metabolites: 19690\n", "# Reactions: 55176\n", "# Constraint (f-) Reactions: 31973\n", "# Model Reactions: 23203\n", "# Genes: 13885\n", "# Members: 17\n", "Members:\n", "\tFusobacterium_nucleatum_subsp_nucleatum_ATCC_25586\n", "\tActinomyces_naeslundii_str_Howell_279\n", "\tBurkholderia_cepacia_GG4\n", "\tVeillonella_atypica_ACS_049_V_Sch6\n", "\tNeisseria_flavescens_SK114\n", "\tStaphylococcus_aureus_subsp_aureus_USA300_FPR3757\n", "\tPseudomonas_aeruginosa_NCGM2_S1\n", "\tAchromobacter_xylosoxidans_NBRC_15126\n", "\tStreptococcus_sanguinis_SK36\n", "\tHaemophilus_influenzae_R2846\n", "\tEscherichia_coli_str_K_12_substr_MG1655\n", "\tPorphyromonas_endodontalis_ATCC_35406\n", "\tPrevotella_melaninogenica_ATCC_25845\n", "\tRalstonia_sp_5_7_47FAA\n", "\tGranulicatella_adiacens_ATCC_49175\n", "\tGemella_haemolysans_ATCC_10379\n", "\tRothia_mucilaginosa_DY_18\n", "Objective in direction max:\n", "\t1.0*community_biomass - 1.0*community_biomass_reverse_44dc1\n", "------------------\n", "Model quality\n", "# Reactions unbalanced: 235\n", "# Reactions able to carry flux without a medium: NaN\n" ] } ], "source": [ "com_model_obj.report();" ] }, { "cell_type": "markdown", "id": "5f666c80", "metadata": {}, "source": [ "### Setting the growth rate ###\n", "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." ] }, { "cell_type": "code", "execution_count": 11, "id": "dc552490", "metadata": {}, "outputs": [ { "data": { "text/html": [ "

Objective

1.0 community_biomass = 0.5

Uptake

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
_26dap_M_mediumEX__26dap_M_medium0.0125170.06%
_2dmmq8_mediumEX__2dmmq8_medium0.001548500.05%
adn_mediumEX_adn_medium1.7911012.59%
ala_L_mediumEX_ala_L_medium0.251530.53%
amp_mediumEX_amp_medium0.406102.86%
arg_L_mediumEX_arg_L_medium4.016616.94%
asn_L_mediumEX_asn_L_medium0.100440.28%
asp_L_mediumEX_asp_L_medium0.100440.28%
ca2_mediumEX_ca2_medium0.00154800.00%
cgly_mediumEX_cgly_medium0.00154850.01%
cl_mediumEX_cl_medium0.00154800.00%
cobalt2_mediumEX_cobalt2_medium0.00154800.00%
cu2_mediumEX_cu2_medium0.00154800.00%
cys_L_mediumEX_cys_L_medium0.0411730.09%
cytd_mediumEX_cytd_medium0.0496790.31%
dad_2_mediumEX_dad_2_medium3.8391027.00%
dgsn_mediumEX_dgsn_medium0.07996100.56%
fe2_mediumEX_fe2_medium0.00154800.00%
fe3_mediumEX_fe3_medium0.00154800.00%
gln_L_mediumEX_gln_L_medium0.103750.36%
glyleu_mediumEX_glyleu_medium0.230381.30%
h_mediumEX_h_medium0.771500.00%
his_L_mediumEX_his_L_medium0.150660.64%
ile_L_mediumEX_ile_L_medium0.163560.69%
k_mediumEX_k_medium0.00154800.00%
lys_L_mediumEX_lys_L_medium0.142760.60%
met_L_mediumEX_met_L_medium0.06750.24%
mg2_mediumEX_mg2_medium0.00154800.00%
mn2_mediumEX_mn2_medium0.00154800.00%
mqn8_mediumEX_mqn8_medium0.001548510.06%
nac_mediumEX_nac_medium0.00309660.01%
o2_mediumEX_o2_medium0.00154800.00%
phe_L_mediumEX_phe_L_medium0.0772690.49%
pheme_mediumEX_pheme_medium0.001548340.04%
pnto_R_mediumEX_pnto_R_medium0.00309690.02%
pro_L_mediumEX_pro_L_medium0.0921850.32%
ptrc_mediumEX_ptrc_medium0.00154840.00%
q8_mediumEX_q8_medium0.001548490.05%
ribflv_mediumEX_ribflv_medium0.003097170.04%
sheme_mediumEX_sheme_medium0.001548420.05%
so4_mediumEX_so4_medium0.00154800.00%
spmd_mediumEX_spmd_medium0.00154870.01%
succ_mediumEX_succ_medium0.023140.06%
thm_mediumEX_thm_medium0.001548120.01%
thr_L_mediumEX_thr_L_medium0.235940.66%
trp_L_mediumEX_trp_L_medium0.0236110.18%
ttdca_mediumEX_ttdca_medium0.07503140.74%
tyr_L_mediumEX_tyr_L_medium0.0603490.38%
uri_mediumEX_uri_medium4.876930.86%
val_L_mediumEX_val_L_medium0.176150.62%
zn2_mediumEX_zn2_medium0.00154800.00%

Secretion

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
acald_mediumEX_acald_medium-4.25226.94%
ade_mediumEX_ade_medium-5.963524.33%
but_mediumEX_but_medium-2.73948.94%
co2_mediumEX_co2_medium-10.3818.47%
dcyt_mediumEX_dcyt_medium-4.822935.42%
gcald_mediumEX_gcald_medium-0.00464520.01%
nh4_mediumEX_nh4_medium-3.18200.00%
orn_mediumEX_orn_medium-3.892515.88%
cpd11416_mediumcommunity_biomass-0.500.00%
" ], "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj.apply_fixed_growth_rate(0.5)\n", "com_model_obj.summary()" ] }, { "cell_type": "markdown", "id": "d6b898f2", "metadata": {}, "source": [ "### Setting the community member composition ###\n", "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." ] }, { "cell_type": "code", "execution_count": 12, "id": "db4aa796", "metadata": {}, "outputs": [ { "data": { "text/html": [ "

Objective

1.0 community_biomass = 43.84820241414374

Uptake

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
_12dgr180_mediumEX__12dgr180_medium0.3429390.19%
_26dap_M_mediumEX__26dap_M_medium0.474970.05%
_2dmmq8_mediumEX__2dmmq8_medium0.1014500.07%
_2obut_mediumEX__2obut_medium106.746.13%
_3mop_mediumEX__3mop_medium18.1761.57%
_4abz_mediumEX__4abz_medium0.085470.01%
_4hbz_mediumEX__4hbz_medium0.0569370.01%
_5mta_mediumEX__5mta_medium0.3696110.06%
acgam_mediumEX_acgam_medium36.184.15%
acnam_mediumEX_acnam_medium1.502110.24%
actn_R_mediumEX_actn_R_medium52.6643.02%
adn_mediumEX_adn_medium10.79101.55%
alagln_mediumEX_alagln_medium48.9785.63%
alahis_mediumEX_alahis_medium13.1191.69%
alathr_mediumEX_alathr_medium6.24170.63%
amp_mediumEX_amp_medium6.277100.90%
arab_D_mediumEX_arab_D_medium0.193550.01%
arg_L_mediumEX_arg_L_medium46.9464.04%
asn_L_mediumEX_asn_L_medium6.25540.36%
ca2_mediumEX_ca2_medium0.222500.00%
cgly_mediumEX_cgly_medium0.514150.04%
chtbs_mediumEX_chtbs_medium7.657161.76%
cit_mediumEX_cit_medium17.4961.51%
cl_mediumEX_cl_medium0.222500.00%
cobalt2_mediumEX_cobalt2_medium0.222500.00%
cu2_mediumEX_cu2_medium0.222500.00%
cys_L_mediumEX_cys_L_medium2.61930.11%
cytd_mediumEX_cytd_medium2.42990.31%
dad_2_mediumEX_dad_2_medium48.65106.99%
ddca_mediumEX_ddca_medium0.6451120.11%
dgsn_mediumEX_dgsn_medium14.45102.08%
duri_mediumEX_duri_medium0.0226690.00%
fe2_mediumEX_fe2_medium0.140600.00%
fe3_mediumEX_fe3_medium0.348900.00%
fol_mediumEX_fol_medium0.3895190.11%
fru_mediumEX_fru_medium56.5864.87%
fum_mediumEX_fum_medium15.8940.91%
gam_mediumEX_gam_medium6.40560.55%
gcald_mediumEX_gcald_medium0.0568420.00%
glc_D_mediumEX_glc_D_medium2.40960.21%
gln_L_mediumEX_gln_L_medium52.6853.78%
glyasn_mediumEX_glyasn_medium55.5464.78%
glyc3p_mediumEX_glyc3p_medium88.133.79%
glycys_mediumEX_glycys_medium0.563650.04%
glyleu_mediumEX_glyleu_medium7688.73%
glymet_mediumEX_glymet_medium0.774970.08%
glyphe_mediumEX_glyphe_medium1.818110.29%
glypro_mediumEX_glypro_medium11.6671.17%
glytyr_mediumEX_glytyr_medium1.146110.18%
gsn_mediumEX_gsn_medium0.3892100.06%
gthox_mediumEX_gthox_medium0.003993200.00%
gthrd_mediumEX_gthrd_medium0.03195100.00%
his_L_mediumEX_his_L_medium2.31960.20%
hxan_mediumEX_hxan_medium2.69750.19%
inulin_mediumEX_inulin_medium0.61381801.59%
k_mediumEX_k_medium0.222500.00%
lys_L_mediumEX_lys_L_medium13.2661.14%
man_mediumEX_man_medium16.7561.44%
met_L_mediumEX_met_L_medium2.03450.15%
metala_mediumEX_metala_medium2.89180.33%
mg2_mediumEX_mg2_medium0.222500.00%
mn2_mediumEX_mn2_medium0.222500.00%
mqn7_mediumEX_mqn7_medium0.04792460.03%
mqn8_mediumEX_mqn8_medium0.1173510.09%
ncam_mediumEX_ncam_medium0.0159760.00%
nmn_mediumEX_nmn_medium12.43111.96%
no3_mediumEX_no3_medium0.411900.00%
o2_mediumEX_o2_medium22700.00%
ocdca_mediumEX_ocdca_medium2.289180.59%
phe_L_mediumEX_phe_L_medium4.97390.64%
pheme_mediumEX_pheme_medium0.1823340.09%
phpyr_mediumEX_phpyr_medium0.398690.05%
pnto_R_mediumEX_pnto_R_medium0.24390.03%
pro_L_mediumEX_pro_L_medium21.1551.52%
ptrc_mediumEX_ptrc_medium0.118440.01%
pullulan1200_mediumEX_pullulan1200_medium0.0252772002.61%
pydx_mediumEX_pydx_medium0.186480.02%
pyr_mediumEX_pyr_medium38.3731.65%
q8_mediumEX_q8_medium0.1094490.08%
ribflv_mediumEX_ribflv_medium0.1958170.05%
ser_L_mediumEX_ser_L_medium48.2932.08%
sheme_mediumEX_sheme_medium0.1378420.08%
so4_mediumEX_so4_medium0.222500.00%
spmd_mediumEX_spmd_medium0.174370.02%
stys_mediumEX_stys_medium0.2655240.09%
sucr_mediumEX_sucr_medium26.43124.55%
thm_mediumEX_thm_medium0.1823120.03%
thr_L_mediumEX_thr_L_medium11.8440.68%
thymd_mediumEX_thymd_medium0.3716100.05%
trp_L_mediumEX_trp_L_medium1.641110.26%
ttdca_mediumEX_ttdca_medium2.129140.43%
tyr_L_mediumEX_tyr_L_medium12.3791.60%
uri_mediumEX_uri_medium14.9291.93%
val_L_mediumEX_val_L_medium13.3550.96%
zn2_mediumEX_zn2_medium0.222500.00%

Secretion

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MetaboliteReactionFluxC-NumberC-Flux
_4hphac_mediumEX__4hphac_medium-8.2881.26%
ac_mediumEX_ac_medium-576.1221.93%
ade_mediumEX_ade_medium-61.5755.86%
ala_L_mediumEX_ala_L_medium-1.96930.11%
asp_L_mediumEX_asp_L_medium-94.3747.18%
but_mediumEX_but_medium-23.241.77%
co2_mediumEX_co2_medium-101.811.94%
etoh_mediumEX_etoh_medium-71.4722.72%
for_mediumEX_for_medium-384.417.32%
glu_L_mediumEX_glu_L_medium-112.3510.69%
gly_mediumEX_gly_medium-116.324.43%
gua_mediumEX_gua_medium-10.1750.97%
h2o_mediumEX_h2o_medium-521.800.00%
h2s_mediumEX_h2s_medium-0.146800.00%
ile_L_mediumEX_ile_L_medium-4.34560.50%
lac_D_mediumEX_lac_D_medium-72.1834.12%
lac_L_mediumEX_lac_L_medium-13.830.79%
leu_L_mediumEX_leu_L_medium-56.7466.48%
mal_L_mediumEX_mal_L_medium-66.1245.03%
nac_mediumEX_nac_medium-1261.37%
nh4_mediumEX_nh4_medium-336.800.00%
orn_mediumEX_orn_medium-33.5753.19%
pi_mediumEX_pi_medium-32.800.00%
ppa_mediumEX_ppa_medium-109.636.26%
ppi_mediumEX_ppi_medium-15.500.00%
succ_mediumEX_succ_medium-66.7145.08%
ura_mediumEX_ura_medium-11.1240.85%
urea_mediumEX_urea_medium-8.37710.16%
cpd11416_mediumcommunity_biomass-43.8500.00%
" ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj.convert_to_fixed_abundance()\n", "abundance_dict = com_model_obj.generate_equal_abundance_dict()\n", "com_model_obj.apply_fixed_abundance(abundance_dict)\n", "com_model_obj.summary()" ] }, { "cell_type": "markdown", "id": "5c2c0e78", "metadata": {}, "source": [ "## Saving and loading community models ##\n", "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:" ] }, { "cell_type": "code", "execution_count": 13, "id": "2c1b8efa", "metadata": {}, "outputs": [], "source": [ "com_model_obj.save(\"../data/toy/output/henson_com_model.xml\")" ] }, { "cell_type": "code", "execution_count": 14, "id": "d49ff797", "metadata": {}, "outputs": [], "source": [ "com_model_obj_loaded = pycomo.CommunityModel.load(\"../data/toy/output/henson_com_model.xml\")" ] }, { "cell_type": "code", "execution_count": 15, "id": "d8b3e5c4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj_loaded" ] }, { "cell_type": "code", "execution_count": 16, "id": "9fd59273", "metadata": {}, "outputs": [ { "data": { "text/html": [ "Optimal solution with objective value 43.848
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
fluxesreduced_costs
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__15DAPt0.0000000.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__1P4H2CBXLAH_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c0.0000000.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__26DAPLLAT_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c-7.8309323.083408e-33
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__2DHPL_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c0.0000000.000000e+00
Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586__2DMMQ8abc0.007987-2.157042e-32
.........
SK_Rothia_mucilaginosa_DY_18_biomass429_ub0.5624420.000000e+00
SK_Rothia_mucilaginosa_DY_18_to_community_biomass_ub0.5624420.000000e+00
f_final1.0000000.000000e+00
abundance_reaction43.8482024.302114e-16
community_biomass43.8482020.000000e+00
\n", "

55176 rows × 2 columns

\n", "
" ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj_loaded.model.optimize()" ] }, { "cell_type": "markdown", "id": "4374c3d5", "metadata": {}, "source": [ "### Quality Checks ###\n", "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." ] }, { "cell_type": "code", "execution_count": 17, "id": "22319695", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "235 unbalanced reactions\n", "Example reactions:\n", "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}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_DM_dhptd_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'C': -5.0, 'H': -8.0, 'O': -4.0}\n", "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}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_EX_biomass_e_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': -1.0}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_NADH8: {'H': 3.552713678800501e-15}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_SHCHCC2_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'charge': -2.0}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_dreplication_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_pbiosynthesis_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}\n", "Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_rtranscription_Fusobacterium_nucleatum_subsp_nucleatum_ATCC_25586_c: {'X': 1.0}\n", "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}\n" ] } ], "source": [ "unbalanced_reactions = com_model_obj.get_unbalanced_reactions()\n", "\n", "print(f\"{len(unbalanced_reactions)} unbalanced reactions\")\n", "print(f\"Example reactions:\")\n", "for rxn in list(unbalanced_reactions.keys())[:10]:\n", " print(f\"{rxn.id}: {unbalanced_reactions[rxn]}\")" ] }, { "cell_type": "markdown", "id": "0d552782", "metadata": {}, "source": [ "## Analysis of community models ##\n", "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.\n", "\n", "### Creating the community model ###\n", "We repeat the steps as before." ] }, { "cell_type": "code", "execution_count": 18, "id": "9a52fc57", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "'3PG' is not a valid SBML 'SId'.\n", "'2PG' is not a valid SBML 'SId'.\n", "'2PG__PEP' is not a valid SBML 'SId'.\n", "'3PG__2PG' is not a valid SBML 'SId'.\n", "'0Pyr__AcCoA' is not a valid SBML 'SId'.\n", "'3PG' is not a valid SBML 'SId'.\n", "'2PG' is not a valid SBML 'SId'.\n", "'5CHOMPT' is not a valid SBML 'SId'.\n", "'3PG__2PG__3PG' is not a valid SBML 'SId'.\n", "'5CHOMPT__CHH4MPT' is not a valid SBML 'SId'.\n", "'5CHOMPT' is not a valid SBML 'SId'.\n", "'3PG' is not a valid SBML 'SId'.\n", "'2PG' is not a valid SBML 'SId'.\n", "'2PG__3PG' is not a valid SBML 'SId'.\n", "'3PG__DPG' is not a valid SBML 'SId'.\n", "'5CHOMPT__CHH4MPT' is not a valid SBML 'SId'.\n" ] } ], "source": [ "test_model_dir = \"../data/use_case/koch\"\n", "named_models = pycomo.load_named_models_from_dir(test_model_dir)" ] }, { "cell_type": "code", "execution_count": 19, "id": "ebd03a6b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'dv': ,\n", " 'mb': ,\n", " 'mh': }" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "named_models" ] }, { "cell_type": "code", "execution_count": 20, "id": "c8513767", "metadata": {}, "outputs": [], "source": [ "single_org_models = []\n", "for name, model in named_models.items():\n", " single_org_model = pycomo.SingleOrganismModel(model, name)\n", " single_org_models.append(single_org_model)\n", " \n", "community_name = \"koch_community_model\"\n", "com_model_obj = pycomo.CommunityModel(single_org_models, community_name)" ] }, { "cell_type": "markdown", "id": "e67a2a02", "metadata": {}, "source": [ "With the community model generated, we set the medium for the analysis, as done by Koch et al." ] }, { "cell_type": "code", "execution_count": 21, "id": "5d64c8e6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-02-11 16:36:37,472 - pycomo - INFO - No community model generated yet. Generating now:\n", "2025-02-11 16:36:37,495 - pycomo - INFO - Identified biomass reaction from objective: r_BMDV2BMc\n", "2025-02-11 16:36:37,646 - pycomo - INFO - Identified biomass reaction from objective: BM_Synth\n", "2025-02-11 16:36:37,836 - pycomo - INFO - Identified biomass reaction from objective: BM_Synth\n", "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'\n", "2025-02-11 16:36:38,088 - pycomo - INFO - Generated community model.\n" ] } ], "source": [ "medium = {\n", " 'EX_CO2_EX_medium': 1000.0,\n", " 'EX_Eth_EX_medium': 1000.0,\n", " 'EX_BM_tot_medium': 1000.0\n", "}\n", "com_model_obj.medium = medium\n", "com_model_obj.apply_medium()\n", "\n", "# Some metabolites are not allowed to accumulate in the medium.\n", "com_model_obj.model.reactions.get_by_id(\"EX_Form_EX_medium\").upper_bound = 0.\n", "com_model_obj.model.reactions.get_by_id(\"EX_H2_EX_medium\").upper_bound = 0." ] }, { "cell_type": "markdown", "id": "b5ec19ea", "metadata": {}, "source": [ "### Calculating potential metabolite exchange ###\n", "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." ] }, { "cell_type": "code", "execution_count": 22, "id": "05c43910", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-02-11 16:36:41,581 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:41,581 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:41,581 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:41,583 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:42,374 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:42,411 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:42,411 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:42,413 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:43,251 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:43,252 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:43,252 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:43,254 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:44,118 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:44,118 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:44,118 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:44,122 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:45,089 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:45,091 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:45,091 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:45,093 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:46,027 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:46,028 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:46,028 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:46,029 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:46,956 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:46,957 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:46,957 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:46,959 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:47,001 - pycomo - INFO - Processed 2.82% of find loops steps\n", "2025-02-11 16:36:47,053 - pycomo - INFO - Processed 5.63% of find loops steps\n", "2025-02-11 16:36:47,075 - pycomo - INFO - Processed 8.45% of find loops steps\n", "2025-02-11 16:36:47,095 - pycomo - INFO - Processed 11.27% of find loops steps\n", "2025-02-11 16:36:47,114 - pycomo - INFO - Processed 14.08% of find loops steps\n", "2025-02-11 16:36:47,156 - pycomo - INFO - Processed 16.9% of find loops steps\n", "2025-02-11 16:36:47,206 - pycomo - INFO - Processed 19.72% of find loops steps\n", "2025-02-11 16:36:47,217 - pycomo - INFO - Processed 22.54% of find loops steps\n", "2025-02-11 16:36:47,246 - pycomo - INFO - Processed 25.35% of find loops steps\n", "2025-02-11 16:36:47,275 - pycomo - INFO - Processed 28.17% of find loops steps\n", "2025-02-11 16:36:47,319 - pycomo - INFO - Processed 30.99% of find loops steps\n", "2025-02-11 16:36:47,336 - pycomo - INFO - Processed 33.8% of find loops steps\n", "2025-02-11 16:36:47,372 - pycomo - INFO - Processed 36.62% of find loops steps\n", "2025-02-11 16:36:47,412 - pycomo - INFO - Processed 39.44% of find loops steps\n", "2025-02-11 16:36:47,449 - pycomo - INFO - Processed 42.25% of find loops steps\n", "2025-02-11 16:36:47,458 - pycomo - INFO - Processed 45.07% of find loops steps\n", "2025-02-11 16:36:47,495 - pycomo - INFO - Processed 47.89% of find loops steps\n", "2025-02-11 16:36:47,540 - pycomo - INFO - Processed 50.7% of find loops steps\n", "2025-02-11 16:36:47,570 - pycomo - INFO - Processed 53.52% of find loops steps\n", "2025-02-11 16:36:47,603 - pycomo - INFO - Processed 56.34% of find loops steps\n", "2025-02-11 16:36:47,659 - pycomo - INFO - Processed 59.15% of find loops steps\n", "2025-02-11 16:36:47,678 - pycomo - INFO - Processed 61.97% of find loops steps\n", "2025-02-11 16:36:47,714 - pycomo - INFO - Processed 64.79% of find loops steps\n", "2025-02-11 16:36:47,762 - pycomo - INFO - Processed 67.61% of find loops steps\n", "2025-02-11 16:36:47,786 - pycomo - INFO - Processed 70.42% of find loops steps\n", "2025-02-11 16:36:47,799 - pycomo - INFO - Processed 73.24% of find loops steps\n", "2025-02-11 16:36:47,837 - pycomo - INFO - Processed 76.06% of find loops steps\n", "2025-02-11 16:36:47,886 - pycomo - INFO - Processed 78.87% of find loops steps\n", "2025-02-11 16:36:47,908 - pycomo - INFO - Processed 81.69% of find loops steps\n", "2025-02-11 16:36:47,919 - pycomo - INFO - Processed 84.51% of find loops steps\n", "2025-02-11 16:36:47,970 - pycomo - INFO - Processed 87.32% of find loops steps\n", "2025-02-11 16:36:48,010 - pycomo - INFO - Processed 90.14% of find loops steps\n", "2025-02-11 16:36:48,028 - pycomo - INFO - Processed 92.96% of find loops steps\n", "2025-02-11 16:36:48,045 - pycomo - INFO - Processed 95.77% of find loops steps\n", "2025-02-11 16:36:48,063 - pycomo - INFO - Processed 98.59% of find loops steps\n", "2025-02-11 16:36:48,071 - pycomo - INFO - Processed 100.0% of find loops steps\n", "2025-02-11 16:36:49,148 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:49,149 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:49,149 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:49,151 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:49,278 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:50,030 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:50,031 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:50,031 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:50,032 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:50,144 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:50,881 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:50,882 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:50,882 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:50,884 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:50,995 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:51,730 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:51,730 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:51,730 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:51,732 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:51,843 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:52,583 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:52,584 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:52,584 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:52,585 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:52,696 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:53,432 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:53,432 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:53,433 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:53,434 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:53,546 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:54,279 - pycomo - INFO - Logger initialized.\n", "2025-02-11 16:36:54,279 - pycomo - INFO - Process Pool Logger initialized.\n", "2025-02-11 16:36:54,280 - pycomo - INFO - Utils Logger initialized.\n", "2025-02-11 16:36:54,281 - pycomo - INFO - Multiprocess Logger initialized.\n", "2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_H2_TF_dv_External_Species\n", "2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_CO2_TF_dv_External_Species\n", "2025-02-11 16:36:54,289 - pycomo - INFO - Loop correction will be applied on dv_TF_Form_TF_dv_External_Species\n", "2025-02-11 16:36:54,574 - pycomo - INFO - Processed 27.78% of fva steps\n", "2025-02-11 16:36:54,596 - pycomo - INFO - Processed 55.56% of fva steps\n", "2025-02-11 16:36:54,608 - pycomo - INFO - Loop correction will be applied on mh_TF_H2_TF_mh_External_Species\n", "2025-02-11 16:36:54,622 - pycomo - INFO - Loop correction will be applied on mh_TF_CO2_TF_mh_External_Species\n", "2025-02-11 16:36:54,623 - pycomo - INFO - Log level set to 20\n", "2025-02-11 16:36:54,628 - pycomo - INFO - Loop correction will be applied on mh_TF_Form_TF_mh_External_Species\n", "2025-02-11 16:36:54,747 - pycomo - INFO - Processed 83.33% of fva steps\n", "2025-02-11 16:36:54,749 - pycomo - INFO - Processed 100.0% of fva steps\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
metabolite_idmetabolite_namecross_feedingproduced_byconsumed_by
0H2_EX_mediumH2_externalTrue[dv][mb, mh]
1Ac_EX_mediumacetate_externalTrue[dv][mb]
2CO2_EX_mediumCO2_externalTrue[mb, mh][dv, mb, mh]
3Form_EX_mediumformate_externalTrue[dv][mh]
4SO4_EX_mediumsulfate_externalFalse[][]
5H2S_EX_mediumhydrogensulfide_externalFalse[][]
6Eth_EX_mediumethanol_externalFalse[][dv]
7Lac_EX_mediumlactate_externalFalse[][]
8Pyr_EX_mediumpyruvate_externalFalse[][]
9CH4_EX_mediumnethane_externalFalse[mb, mh][]
10MetOH_EX_mediumnethanol_externalFalse[][]
11BM_tot_mediumtotal_biomassFalse[][]
12cpd11416_mediumCommunity BiomassFalse[dv, mb, mh][]
\n", "
" ], "text/plain": [ " metabolite_id metabolite_name cross_feeding produced_by \\\n", "0 H2_EX_medium H2_external True [dv] \n", "1 Ac_EX_medium acetate_external True [dv] \n", "2 CO2_EX_medium CO2_external True [mb, mh] \n", "3 Form_EX_medium formate_external True [dv] \n", "4 SO4_EX_medium sulfate_external False [] \n", "5 H2S_EX_medium hydrogensulfide_external False [] \n", "6 Eth_EX_medium ethanol_external False [] \n", "7 Lac_EX_medium lactate_external False [] \n", "8 Pyr_EX_medium pyruvate_external False [] \n", "9 CH4_EX_medium nethane_external False [mb, mh] \n", "10 MetOH_EX_medium nethanol_external False [] \n", "11 BM_tot_medium total_biomass False [] \n", "12 cpd11416_medium Community Biomass False [dv, mb, mh] \n", "\n", " consumed_by \n", "0 [mb, mh] \n", "1 [mb] \n", "2 [dv, mb, mh] \n", "3 [mh] \n", "4 [] \n", "5 [] \n", "6 [dv] \n", "7 [] \n", "8 [] \n", "9 [] \n", "10 [] \n", "11 [] \n", "12 [] " ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "com_model_obj.potential_metabolite_exchanges()" ] }, { "cell_type": "markdown", "id": "f1dce5f2", "metadata": {}, "source": [ "### Plotting the maxiumum growth rate over the composition space ###" ] }, { "cell_type": "code", "execution_count": 23, "id": "9b2886bd", "metadata": { "scrolled": true }, "outputs": [], "source": [ "import pandas as pd\n", "\n", "# Iterate over the fractions in steps of 0.01\n", "com_model_obj.convert_to_fixed_abundance()\n", "rows = []\n", "for i in range (0,100,1): # fraction of D. vulgaris\n", " for j in range (0, 100-i, 1): # fraction of M. hungatei\n", " if (100-i-j) < 0:\n", " continue\n", "\n", " abundances = {\"dv\": i/100., \"mh\": j/100., \"mb\": (100-i-j)/100.}\n", " \n", " # Apply the abuyndances\n", " com_model_obj.apply_fixed_abundance(abundances)\n", " \n", " # Reapply the bound restrictions of the exchange reactions\n", " com_model_obj.model.reactions.get_by_id(\"EX_Form_EX_medium\").upper_bound = 0.\n", " com_model_obj.model.reactions.get_by_id(\"EX_H2_EX_medium\").upper_bound = 0.\n", " \n", " # Calculate the optimal growth rate\n", " solution = com_model_obj.model.optimize()\n", " growth = 0. if str(solution.status) == \"infeasible\" else solution.objective_value\n", " rows.append({\"dv\": i/100., \"mh\": j/100., \"growth\": growth})\n", " \n", "growth_df = pd.DataFrame(rows)" ] }, { "cell_type": "code", "execution_count": 24, "id": "17759afb", "metadata": {}, "outputs": [ { "data": { "image/png": "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04mJEyd2KcaFmve2tjZs2rQJP/7xj72vXX/99ejXrx92796N7Oxs7/ju3buRkZEBozHi/wp8sBsrERERUc8K9AzmhdcuvvZC5ce3r/33f/93TJo0CQMHDsRf//pXrFmzBv/xH/+BP/zhD975XRHxlWt+fj6qqqpQVFSEoqIinDp1CjabDdOnT/fZNS8pKYHdbsfhw4e9Y1VVVYiPj8eVV16J48eP45VXXkFsbCwWLFjgnWMymVBUVISysjIkJCRg9OjRePfdd/Hee+/hxRdf7NF7JSIiIur1wljzrrWzHqhLncG84OI5Ho/Hb/zXv/61959vvPFG3HDDDbjjjjuwceNGn7XrpUR88a4oCiorK2G1WlFcXAyz2Yzc3FxYLBafeW63Gy6X7/M7nU4nVq1ahX/84x/o378/brvtNjz88MPo06ePz7x77rkHOp0Or776KlavXo2hQ4fi17/+NW655Zaw3x8RERERyS3QM5jf3mG/cN4SgDeWaDf/gu9+97tIT0/HoUOHupVrxBfvAJCeno6KiopO59hsNthsNp+xe++9F/fee2+XfkZBQQEKCgoCzpGIiIiIQkDCR0UGegbzQq17XV2dzyLf4XBAp9P51cJf7MIOfXdI+PBPErky5bt+X0REREQUvOzsbPz5z39GU1OTd6wrZzCHDh2KYcOGobq62md869atGDVqVKdPmvnLX/6Cv/3tbxg5cmS3cpVi552IiIiIegm369JzelgwZzAXLlyIRYsWITU1FePGjcM777yD2tpavPzyy945FRUVOHr0KH7wgx8gKSkJn3/+OdauXYsrrrjC50ErXcHFOxERERH1HAnLZoI5g3n77bejra0Na9euRUVFBdLS0vD888/7NGhKT0/HW2+9herqapw+fRqJiYmYOHEifv7zn3daFy/CxTsRERER9XqBnsEEgFmzZmHWrFma19188824+eabg84R4OKdiIiIiHpSGB8V2RtIsXivr6+H1WrF3r17ERcXh2nTpsFiscBsNnd6ndPpxIoVK/CHP/wBqqriO9/5Dh555BFkZWX5xK6qqsLu3btx4sQJJCYmIisrC4sWLcKgQYPCfWthxYZORERERL1LxBfvqqqioKAAycnJKC8vR2NjI0pLS9Hc3IyysrJOr33mmWfwhz/8AT//+c8xbNgw/P73v8eCBQvw+uuv47rrrgMA1NbW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W1uLl19+2edn7NmzB42NjThy5AgA4M9//jOOHz+OlJSUbnValWLxHmg72urqamzbtg379+/HV199hV/84heYP3++cO7nn3+O5557Dh999BHcbjfS09Px5JNPYuzYseG4pZATfUSi2aQpxiAOEiM4nKrXmEsUbUL0/FwiCh4bOlFnwvmoyEAF+lhyALj99tvR1taGtWvXoqKiAmlpaXj++ed9GjQBwMqVK7Fnzx7v9xc6t86aNcvnaYmXEvHFe7DtaI8ePYof/ehHeP311zXnffrpp5g9ezYmTZqE5cuXw2g04tChQ2hrawv17RARERFRFArkseQXzJo1C7Nmzer02vXr1weV3wURX7wH0472hRde8Har6mzxvmTJEkyaNAnPPfecd2z8+PEhugMiIiIi6qpwPiqyN4j458yBtqMFutZm1uFwYN++fZgzZ07QuRIRERERRVLEF+8Oh8Nvd70r7Wi7av/+/QDOP6dz5syZuPbaa3HzzTeH7KMLIiIiIuo6Nzxh++oNIl42E2g72q46efIkAODRRx/Fvffei9GjR2Pnzp2wWq3o168fZsyYEfTPCJSo65bWuymD4PdRLxoEAKPGf1ZT5weAiYiIwokHWYmCF/HFu5autqO9FLf7/BNZ8vLycP/99wMAMjMz0dDQgLVr10Z08U5ERESA0aiHwXB+++rCn4G4XGLIkEM4BfM8dpJg8d5ZO9rODqt21YW2tZmZmT7jmZmZqKmpQXt7O2JiYoL+OURERBSYxMS+3n9WlLig410uMWTIIRzcPLAalIgv3jtrR5uXlxeS+Fr0en1IdveJiIgocE1Np2Ew6KEocVDVs3C5Amt0f7nECEcO336DRNEt4ov37OxsrFmzBk1NTUhMTATQtXa0XXX99dejX79+2L17N7Kzs73ju3fvRkZGBoxa9eERooP4zYSwSZNeq0mTxj2JmjQRERFF2KDB3/EbC6YO3uVyo6MjsEWvTDFkyCEcuO8enIivXINpR3vkyBFvi1kA+Otf/4rt27cjLi7Ou/A3mUwoKipCWVkZEhISMHr0aLz77rt477338OKLL/bcjRIRERERBSnii/dg2tFu27YNq1at8n5vt9tht9uRkpKCnTt3esfvuece6HQ6vPrqq1i9ejWGDh2KX//617jlllvCe3NERERE5KO3PNIxXCK+eAcCb0dbXFyM4uLiLv2M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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "sns.set_theme()\n", "\n", "# Restructure dataframe for heatmap\n", "growth_df_pivot = growth_df.pivot(index=\"mh\", columns=\"dv\", values=\"growth\")\n", "\n", "# Draw a heatmap with the numeric values in each cell\n", "f, ax = plt.subplots(figsize=(9, 6))\n", "sns.heatmap(growth_df_pivot, ax=ax)\n", "ax.invert_yaxis()" ] }, { "cell_type": "code", "execution_count": null, "id": "92ecc48f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 5 }