{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Case study iMM904 curation\n", " Using the iMM904 model as a case study, we have used Thermo-Flux and did the few manual curation steps to show how models can be converted into a combined thermodynamic-stoichiometric model.\n", "Here, we present the steps that required manual attention when following the protocol described in the publication. \"\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import cobra\n", "from cobra import Model, Reaction, Metabolite\n", "from thermo_flux.core.metabolite import ThermoMetabolite\n", "import thermo_flux\n", "from thermo_flux.io import load_excel as ex\n", "from thermo_flux.core.model import ThermoModel, ThermoReaction\n", "from equilibrator_api import Q_\n", "import pandas as pd\n", "from thermo_flux.io import load_gams as gs\n", "from thermo_flux.io import helper_load as hl\n", "from thermo_flux.utils.vis import compare_met\n", "import numpy as np\n", "import gurobipy as gp\n", "from gurobipy import GRB\n", "\n", "\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import sbml model from BiGG" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2025-02-26\n", "0.9748814206733495\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", "
fluxesreduced_costs
EX_epistest_SC_e0.0-96.275549
EX_epist_e0.0-1.676719
EX_ergst_e0.0-1.722387
EX_ergstest_SC_e0.0-96.321217
EX_13BDglcn_e0.0-0.196130
.........
EX_xyl__D_e0.0-0.163442
EX_xylt_e0.0-0.176421
EX_rib__D_e0.0-0.163442
EX_zymst_e0.0-1.620476
EX_zymstest_SC_e0.0-96.219306
\n", "

164 rows × 2 columns

\n", "
" ], "text/plain": [ " fluxes reduced_costs\n", "EX_epistest_SC_e 0.0 -96.275549\n", "EX_epist_e 0.0 -1.676719\n", "EX_ergst_e 0.0 -1.722387\n", "EX_ergstest_SC_e 0.0 -96.321217\n", "EX_13BDglcn_e 0.0 -0.196130\n", "... ... ...\n", "EX_xyl__D_e 0.0 -0.163442\n", "EX_xylt_e 0.0 -0.176421\n", "EX_rib__D_e 0.0 -0.163442\n", "EX_zymst_e 0.0 -1.620476\n", "EX_zymstest_SC_e 0.0 -96.219306\n", "\n", "[164 rows x 2 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cobra.io import load_json_model\n", "model=load_json_model('iMM904.json')\n", "\n", "#set objective to biomass\n", "model.objective = model.reactions.BIOMASS_SC5_notrace\n", "model.reactions.EX_co2_e.id='co2_EX'\n", "model.reactions.EX_o2_e.id='o2_EX'\n", "model.reactions.EX_etoh_e.id='etoh_EX'\n", "model.repair()\n", "\n", "for rxn in model.reactions:\n", " if 'EX_' not in rxn.id:\n", " rxn.lower_bound=-500 if rxn.lower_bound==-999999.0 else rxn.lower_bound\n", " rxn.upper_bound=500 if rxn.upper_bound==999999.0 else rxn.upper_bound\n", " else:\n", " rxn.lower_bound=-500 if rxn.lower_bound==-999999.0 else rxn.lower_bound\n", " rxn.upper_bound=500 if rxn.upper_bound==999999.0 else rxn.upper_bound\n", " # print(rxn.id,rxn.lower_bound,rxn.upper_bound)\n", "\n", "#reset O2 exchange bound\n", "model.optimize().to_frame().loc['BIOMASS_SC5_notrace']['fluxes']\n", "model.reactions.o2_EX.bounds=(-500,0)\n", "\n", "print(model.optimize().to_frame().loc['BIOMASS_SC5_notrace']['fluxes'])\n", "model.optimize().to_frame().loc[[rxn.id for rxn in model.boundary]]\n", "\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\tedns\\anaconda3\\envs\\thermoflux\\lib\\site-packages\\cobra\\util\\solver.py:554: UserWarning: Solver status is 'infeasible'.\n", " warn(f\"Solver status is '{status}'.\", UserWarning)\n" ] }, { "data": { "image/png": "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oCD5+/vLYrHwfigtLs1qeZC///3vRt26dY0KFSoYd911lzX6h9IzcOBAo06dOoavr68RGhpqPPTQQ8aPP/7o6rI8XlxcnCEp323IkCGGYVyPv77yyitG7dq1DT8/P6NTp07GwYMHXVu0ByrqdcjKyjK6d+9u1KxZ0/D19TXCw8ONIUOGGElJSa4u26MU9PuXZHz44YfWbXg/lA6LYRhG6bdUAAAAzsGcGwAA4FFobgAAgEehuQEAAB6F5gYAAHgUmhsAAOBRaG4AAIBHobkBAAAeheYGAAB4FJobQNdX6f38889dXUaZNW3aNLVq1crVZTjF1KlT9dxzz7m6jALFx8fLYrHo999/L3K7s2fPKiQkRCdPniyVusw6efKkLBaL9u/fX+g2X375paKiopSbm2sdy87OVnh4uPbu3VsKVaIsobmBR0tJSdGLL76ohg0bqmLFiqpVq5Y6dOig2NhYZWVlubo8t/PUU0+pX79+ri7jljjyOfzf//2f3nvvPU2ePNkhxyst8fHxqlOnjvIuQD9jxgz17t1b9erVM3UMi8Uii8UiHx8fBQUFKSoqSuPHj1dycrJ1u6+//loWiyXfSte1a9dWWFiYzdivv/4qi8Wib7/91vRz+uMf/yiLxaKlS5dax/z8/DRu3DhNmDDB9PHg2Whu4LFOnDihqKgoffvtt3r99deVkJCg7777TmPGjNEXX3yh7777ztUlwoQrV66U+s9ctGiR2rVrZ6opcAdr165Vnz59ZLFYdOnSJS1atEj/8z//U6JjHTlyRGfOnNHu3bs1YcIEfffdd2revLkOHjwoSerQoYPKly+v+Ph46z6HDx/W5cuXlZGRYbOYZ1xcnHx9fdW+ffsS1fL0009r7ty5NmNPPPGEtmzZosOHD5fomPBMNDfwWMOHD1f58uW1Z88ePfLII2ratKlatGih/v37a926derdu3eB+xV0qn///v2yWCw2p/W3bdumzp07KyAgQNWqVVOPHj10/vx5SddPl48aNUohISGqWLGiOnTooN27d1v3PX/+vJ544gnVrFlT/v7+atSokT788EPr46dPn9bAgQNVrVo11ahRQ3379i3yK4XFixeratWqNmOff/65LBaL9X7eV0f/+7//q7CwMAUEBGjAgAHW5zlt2jR99NFHWrNmjfX/2PM+sCZMmKDGjRsrICBA9evX19SpU4ts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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#plot biomass yield for stoichiometric model\n", "#GUR_range=[-0.25, -0.57, -0.6 , -1.1 , -1.67, -2.14, -2.22, -2.83, -3.24, -3.7, -4.67, -5.44, -7.62, -8.09, -8.33, -10.23, -13.18, -15.7, -22.42]\n", "GUR_range = np.linspace(-0, -23, 50)\n", "\n", "GUR_plot_range=[-x for x in GUR_range]\n", "biomass_flux=[]\n", "etoh_flux=[]\n", "o2_flux=[]\n", "co2_flux=[]\n", "for GUR in GUR_range:\n", " model.reactions.EX_glc__D_e.upper_bound=0\n", " model.reactions.EX_glc__D_e.lower_bound=GUR\n", " sol = model.optimize()\n", " #add values to list\n", " biomass_flux.append(sol.fluxes.loc['BIOMASS_SC5_notrace'])\n", " etoh_flux.append(sol.fluxes.loc['etoh_EX'])\n", " o2_flux.append(sol.fluxes.loc['o2_EX'])\n", " co2_flux.append(sol.fluxes.loc['co2_EX'])\n", "#plot biomass vs GUR in a scatter plot\n", "sns.scatterplot(x=GUR_plot_range,y=biomass_flux)\n", "plt.xlabel('Glucose uptake rate (mmol/(gDW.h))')\n", "plt.ylabel('Biomass production (mmol/(gDW.h))')\n", "fba_flux=pd.DataFrame({'biomass_EX':biomass_flux,'etoh_EX':etoh_flux,'o2_EX':o2_flux,'co2_EX':co2_flux},index=GUR_range)\n", "# plt.savefig('Figures/growth_stoichio_only.png',dpi=300)\n", "# model.optimize().to_frame().loc['BIOMASS_SC5_notrace']/model.optimize().to_frame().loc['EX_glc__D_e']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 1 - Physical and Biochemical parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initializing component contribution object...\n", "No valid license for cxcalc installed, operating in read-only mode. A local cache may be loaded, but no compounds can be created. Please obtain a ChemAxon license to enable compound creation.\n", "Loading compounds from iMM904_compound.sqlite\n", "added reaction: biomass_ce: biomass_c <=> biomass_e\n", "added reaction: biomass_EX: biomass_e <=> \n", "added reaction: charge_ce: charge_e <=> charge_c\n", "added reaction: EX_charge: charge_e <=> \n", "added reaction: charge_cm: charge_m <=> charge_c\n", "added reaction: charge_cx: charge_x <=> charge_c\n", "added reaction: charge_cr: charge_r <=> charge_c\n", "added reaction: charge_cv: charge_v <=> charge_c\n", "added reaction: charge_cg: charge_g <=> charge_c\n", "added reaction: charge_cn: charge_n <=> charge_c\n" ] } ], "source": [ "tmodel=ThermoModel(model,split_biomass=True, add_charge_exchange= True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#define the biochemical parameters of the model\n", "\n", "tmodel.phi={'ec': Q_(-0.06,'volt'), 'cm': Q_(-0.16,'volt'),'cx':Q_(0,'volt'),'cr':Q_(0,'volt'),'cv':Q_(0,'volt'),'cg':Q_(0,'volt'),'cn':Q_(0,'volt')}\n", "tmodel.pH={'c':Q_(7),'e':Q_(5),'m':Q_(7.4),'r':Q_(7),'v':Q_(5.5),'g':Q_(7),'x':Q_(7),'n':Q_(7)} #On the intracellular pH of baker’s yeast(r), Martinez-Munoz et al. 2008(v), Juan Llopis et al 1998 (g), 7 is default pH\n", "\n", "#change max drGcalc_drGt\n", "tmodel._max_drG=Q_(1e6,'kJ/mol') #max is already 1e8 shouldnt need to change\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 2 - Definition of metabolites" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[██████████████████......................] 568/1236 gsn_m \r" ] }, { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: dolichol_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 15, 'H': 28, 'O': 1}, eQuilibrator:{'C': 25, 'O': 1}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: dolmanp_r has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 21, 'H': 38, 'O': 9, 'P': 1}, eQuilibrator:{'C': 31, 'O': 9, 'P': 1}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: glycogen_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 6, 'H': 10, 'O': 5}, eQuilibrator:{'O': 21, 'C': 24}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: glycogen_v has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 6, 'H': 10, 'O': 5}, eQuilibrator:{'O': 21, 'C': 24}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[███████████████████████████.............] 843/1236 pmtcoa_c \r" ] }, { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: mhpglu_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 25, 'H': 36, 'N': 8, 'O': 12}, eQuilibrator:{'C': 30, 'N': 9, 'O': 12}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: macchitppdol_g has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 37, 'H': 64, 'N': 2, 'O': 22, 'P': 2}, eQuilibrator:{'C': 47, 'O': 22, 'P': 2, 'N': 2}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: hpglu_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'C': 24, 'H': 34, 'N': 8, 'O': 12}, eQuilibrator:{'N': 9, 'C': 29, 'O': 12}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[███████████████████████████████████████.] 1221/1236 zym_int1_c \r" ] }, { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdox_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdox_m has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdox_n has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdox_x has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdrd_c has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1, 'H': 2}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdrd_m has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1, 'H': 2}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdrd_n has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1, 'H': 2}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n", "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\2562127799.py:1: UserWarning: trdrd_x has inconsistent formula with eQuilibrator identified metabolite. COBRA:{'X': 1, 'H': 2}, eQuilibrator:{'N': 4, 'C': 10, 'S': 2, 'O': 4}. Defining as unknown compound\n", " tmodel.get_compounds(search = True)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[████████████████████████████████████████] 1236/1236 charge_n \n", "\n" ] }, { "data": { "text/plain": [ "[]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tmodel.get_compounds(search = True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#define biomass parameters \n", "#if the biomass formula is not automatically calcualted it's important to specifiy the hydrogen atoms in biomass to ensure correct proton balancing \n", "tmodel.metabolites.biomass_c.formula = 'H67'\n", "tmodel.metabolites.biomass_e.formula = 'H67'\n", "\n", "#manually define charge of cytochrome C so electron movement is correctly calcualted\n", "tmodel.metabolites.focytc_m.charge = 2\n", "tmodel.metabolites.focytc_m.redox= True #define as redox metabolite \n", "tmodel.metabolites.ficytc_m.charge = 3\n", "tmodel.metabolites.ficytc_m.redox = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 3 - metabolites formation energies" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When specifying the value of `dfGprime` for the biomass metabolite, we should plug in the values in units of **J/gDW**. This differs from all the other reactions in the model, for which values of **kJ/mol** are used.\n", "\n", "The reason for this discrepancy has to do with the units of the fluxes.\n", "\n", "For a normal reaction:\n", "$g_{diss, rxn} = \\Delta_rG \\times v = (kJ/mol) \\times (mmol/gDW/h) = (10^3 J/mol) \\times (10^{-3} mol/gDW/h) = J/gDW/h$\n", "\n", "For the biomass reaction:\n", "$g_{diss, bio} = \\Delta_fG_{bio} \\times \\mu = (J/gDW) \\times (gDW/gDW/h) = J/gDW/h $\n", "\n", "Since thermoflux handles all reactions the same when determining the gibbs energy dissipation rate (multiplying $v$ by $\\Delta_rG$), we have to **pretend** that the biomass formation energy has units of kJ/mol. E.g:\n", "`tmodel.metabolites.biomass_c.dfGprime = Q_(701.767, \"kJ/mol\")` (where 701.767 is the formation energy of E.coli biomass at cytosolic pH, in units of J/gDW)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "#define biomass properties\n", "tmodel.reactions.BIOMASS_SC5_notrace.id='biomass_c' #update biomass reaction name for convenience\n", "\n", "tmodel.metabolites.biomass_c.dfG0 = Q_(-3.04,'kJ/mol')*1000 #From Battley 1991, *1000 for mmol flux units (actual units here are J/gDW)\n", "tmodel.metabolites.biomass_e.dfG0 = Q_(-3.04,'kJ/mol')*1000\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 4 - Transporters" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ASPOcm ASPOcm: asp__L_c + fad_m --> fadh2_m + h_c + iasp_c {}\n", "ATPS ATPS: atp_c + h2o_c --> adp_c + h_e + pi_c {}\n", "DHORD4i DHORD4i: dhor__S_c + q6_m --> orot_c + q6h2_m {}\n", "DOLPMTcer DOLPMTcer: dolp_c + gdpmann_c --> dolmanp_r + gdp_c {}\n", "DXHPScm DXHPScm: h2o_c + q6_m + spmd_c --> 13dampp_c + 4abutn_c + q6h2_m {}\n", "D_LACDcm D_LACDcm: 2.0 ficytc_m + lac__D_c --> 2.0 focytc_m + pyr_c {}\n", "FDNG FDNG: for_c + h_c + q6_m --> co2_c + q6h2_m {}\n", "FRDcm FRDcm: fadh2_m + fum_c --> fad_m + succ_c {}\n", "L_LACD2cm L_LACD2cm: 2.0 ficytc_m + lac__L_c --> 2.0 focytc_m + pyr_c {}\n", "NADH2_u6cm NADH2_u6cm: h_c + nadh_c + q6_m --> nad_c + q6h2_m {}\n" ] } ], "source": [ "#idenfity transporters where the transported metabolite is empty\n", "#these could either be redox reactions or proton pumps just moving electrons (charge) and protons \n", "#or they could be transporters with chemcial transformation during the transport process\n", "for reaction in tmodel.reactions:\n", " if len(reaction.compartments) > 1:\n", " if thermo_flux.tools.drg_tools.calc_transported_mets(reaction) == {}:\n", " print(reaction.id, reaction, thermo_flux.tools.drg_tools.calc_transported_mets(reaction))\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "#DOLPMTcer involved chemcial transformation of dolp. We assume transport of dolmanp for thermodynamic calcualtion\n", "tmodel.reactions.DOLPMTcer.transported_mets = {tmodel.metabolites.dolmanp_r: -1}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 5 - charge and proton balancing" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\tedns\\AppData\\Local\\Temp\\ipykernel_1896\\1541778503.py:2: UserWarning: ATPS3v is not balanced and could not be automatically balanced, please check reaction stoichiometry or define reaction.transported_h\n", " thermo_flux.tools.drg_tools.reaction_balance(rxn, balance_charge=True, balance_mg=False)\n" ] } ], "source": [ "for rxn in tmodel.reactions:\n", " thermo_flux.tools.drg_tools.reaction_balance(rxn, balance_charge=True, balance_mg=False)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Reaction identifierATPS3v
NameATP synthase vacuole
Memory address0x16d19f17f40
Stoichiometry\n", "

adp_v + 3.0 h_c + pi_v --> atp_v + h2o_v + 2.0 h_v

\n", "

ADP C10H12N5O10P2 + 3.0 H+ + Phosphate --> ATP C10H12N5O13P3 + H2O H2O + 2.0 H+

\n", "
GPRYBR127C and YDL185W and YEL027W and YEL051W and YGR020C and YHR026W and YHR039C_A and YKL080W and...
Lower bound0.0
Upper bound500
\n", " " ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#ATPS3v is vacuolar ATP synthase transporting three protons per ATP\n", "tmodel.reactions.ATPS3v" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Reaction identifierATPS3v
NameATP synthase vacuole
Memory address0x16d19f17f40
Stoichiometry\n", "

adp_v + 3.0 charge_c + 3.0 h_c + pi_v --> atp_v + 3.0 charge_v + h2o_v + 3.021815 h_v

\n", "

ADP C10H12N5O10P2 + 3.0 charge + 3.0 H+ + Phosphate --> ATP C10H12N5O13P3 + 3.0 charge + H2O H2O + 3.021815 H+

\n", "
GPRYBR127C and YDL185W and YEL027W and YEL051W and YGR020C and YHR026W and YHR039C_A and YKL080W and...
Lower bound0.0
Upper bound500
\n", " " ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tmodel.reactions.ATPS3v.transported_h = {'v': 3.0, 'c': -3.0}\n", "thermo_flux.tools.drg_tools.reaction_balance(tmodel.reactions.ATPS3v, balance_charge=True, balance_mg=False)\n", "tmodel.reactions.ATPS3v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 6 - Calculation of Gibbs energy of reactions\n", "Add thermodynamic constraints and parameters" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "#change max flux to 500 for all reactions\n", "\n", "tmodel.reactions.get_by_id(\"biomass_EX\").bounds = (0,500)\n", "tmodel.reactions.get_by_id(\"biomass_c\").bounds = (0,500)\n", "tmodel.reactions.get_by_id(\"biomass_ce\").bounds = (0,500)\n", "\n", "\n", "for rxn in tmodel.reactions:\n", " rxn.lower_bound = -500 if rxn.lower_bound == -1000 else rxn.lower_bound\n", " rxn.upper_bound = 500 if rxn.upper_bound == 1000 else rxn.upper_bound\n", "tmodel.objective = tmodel.reactions.biomass_EX" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Identifying compounds...\n", "[████████████████████████████████████████] 1244/1244 Mg_n \n", "\n", "Estimating dfG0'...\n", "ficytc_m 0 kilojoule / mole\n", "focytc_m 0 kilojoule / mole\n", "biomass_c 0 kilojoule / mole\n", "biomass_e 0 kilojoule / mole\n", "[████████████████████████████████████████] 1244/1244 Mg_n \n", "\n", "Estimating drG0'...\n", "[████████████████████████████████████████] 1587/1587 charge_cn \n", "\n" ] } ], "source": [ "tmodel.update_thermo_info(fit_unknown_dfG0=False,search=True)\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "h2o_c True\n", "h2o_e True\n", "h2o_g True\n", "h2o_m True\n", "h2o_n True\n", "h2o_r True\n", "h2o_v True\n", "h2o_x True\n", "h_c True\n", "h_e True\n", "h_g True\n", "h_m True\n", "h_n True\n", "h_r True\n", "h_v True\n", "h_x True\n", "oh1_c True\n", "oh1_m True\n", "biomass_c True\n", "biomass_e True\n", "charge_c True\n", "charge_e True\n", "charge_m True\n", "charge_x True\n", "charge_r True\n", "charge_v True\n", "charge_g True\n", "charge_n True\n" ] } ], "source": [ "for met in tmodel.metabolites:\n", " if met.ignore_conc:\n", " print(met.id,met.ignore_conc)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "EX_epistest_SC_e True\n", "EX_epist_e True\n", "EX_ergst_e True\n", "EX_ergstest_SC_e True\n", "EX_13BDglcn_e True\n", "EX_etha_e True\n", "EX_2hb_e True\n", "etoh_EX True\n", "EX_fe2_e True\n", "EX_fecost_e True\n", "EX_2mbac_e True\n", "EX_2mbald_e True\n", "EX_2mbtoh_e True\n", "EX_2mppal_e True\n", "EX_2phetoh_e True\n", "EX_fecostest_SC_e True\n", "EX_fmn_e True\n", "EX_3c3hmp_e True\n", "EX_3mbald_e True\n", "EX_for_e True\n", "EX_fru_e True\n", "EX_3mop_e True\n", "EX_4abut_e True\n", "EX_fum_e True\n", "EX_g3pc_e True\n", "EX_4abz_e True\n", "EX_5aop_e True\n", "EX_g3pi_e True\n", "EX_gal_e True\n", "EX_8aonn_e True\n", "EX_Nbfortyr_e True\n", "EX_abt_e True\n", "EX_ac_e True\n", "EX_acald_e True\n", "EX_aces_e True\n", "EX_galur_e True\n", "EX_gam6p_e True\n", "EX_gcald_e True\n", "EX_glc__D_e True\n", "EX_gln__L_e True\n", "EX_glu__L_e True\n", "EX_glx_e True\n", "EX_ade_e True\n", "EX_adn_e True\n", "EX_akg_e True\n", "EX_ala__L_e True\n", "EX_gly_e True\n", "EX_glyc_e True\n", "EX_gsn_e True\n", "EX_gthox_e True\n", "EX_gthrd_e True\n", "EX_alltn_e True\n", "EX_alltt_e True\n", "EX_amet_e True\n", "EX_arab__D_e True\n", "EX_arab__L_e True\n", "EX_gua_e True\n", "EX_arg__L_e True\n", "EX_h2o_e True\n", "EX_h_e True\n", "EX_hdca_e True\n", "EX_hdcea_e True\n", "EX_asn__L_e True\n", "EX_asp__L_e True\n", "EX_btd_RR_e True\n", "EX_btn_e True\n", "EX_hexc_e True\n", "EX_his__L_e True\n", "EX_hxan_e True\n", "EX_iamac_e True\n", "EX_iamoh_e True\n", "EX_ibutac_e True\n", "EX_chol_e True\n", "EX_cit_e True\n", "co2_EX True\n", "EX_crn_e True\n", "EX_csn_e True\n", "EX_cys__L_e True\n", "EX_cytd_e True\n", "EX_dad_2_e True\n", "EX_dann_e True\n", "EX_ibutoh_e True\n", "EX_id3acald_e True\n", "EX_ile__L_e True\n", "EX_ind3eth_e True\n", "EX_inost_e True\n", "EX_dca_e True\n", "EX_dcyt_e True\n", "EX_ddca_e True\n", "EX_ins_e True\n", "EX_k_e True\n", "EX_dgsn_e True\n", "EX_din_e True\n", "EX_lac__D_e True\n", "EX_lac__L_e True\n", "EX_lanost_e True\n", "EX_lanostest_SC_e True\n", "EX_dttp_e True\n", "EX_duri_e True\n", "EX_leu__L_e True\n", "EX_lys__L_e True\n", "EX_mal__L_e True\n", "EX_malt_e True\n", "EX_ribflv_e True\n", "EX_sbt__D_e True\n", "EX_man_e True\n", "EX_melib_e True\n", "EX_met__L_e True\n", "EX_mmet_e True\n", "EX_na1_e True\n", "EX_nac_e True\n", "EX_sbt__L_e True\n", "EX_ser__L_e True\n", "EX_so3_e True\n", "EX_so4_e True\n", "EX_spmd_e True\n", "EX_sprm_e True\n", "EX_srb__L_e True\n", "EX_succ_e True\n", "EX_nadp_e True\n", "EX_nh4_e True\n", "EX_nmn_e True\n", "EX_sucr_e True\n", "o2_EX True\n", "EX_taur_e True\n", "EX_thm_e True\n", "EX_oaa_e True\n", "EX_ocdca_e True\n", "EX_ocdcea_e True\n", "EX_ocdcya_e True\n", "EX_orn_e True\n", "EX_thmmp_e True\n", "EX_thmpp_e True\n", "EX_thr__L_e True\n", "EX_thym_e True\n", "EX_pacald_e True\n", "EX_pap_e True\n", "EX_thymd_e True\n", "EX_tre_e True\n", "EX_trp__L_e True\n", "EX_pc_SC_e True\n", "EX_pectin_e True\n", "EX_pepd_e True\n", "EX_phe__L_e True\n", "EX_pheac_e True\n", "EX_pi_e True\n", "EX_pnto__R_e True\n", "EX_ttdca_e True\n", "EX_tyr__L_e True\n", "EX_ura_e True\n", "EX_urea_e True\n", "EX_uri_e True\n", "EX_val__L_e True\n", "EX_xan_e True\n", "EX_xtsn_e True\n", "EX_pro__L_e True\n", "EX_ptd1ino_SC_e True\n", "EX_ptrc_e True\n", "EX_pyr_e True\n", "EX_xyl__D_e True\n", "EX_xylt_e True\n", "EX_rib__D_e True\n", "EX_zymst_e True\n", "EX_zymstest_SC_e True\n", "H2Ot True\n", "H2Oter True\n", "H2Otm True\n", "H2Otn True\n", "H2Otp True\n", "H2Otv True\n", "biomass_c True\n", "biomass_ce True\n", "biomass_EX True\n", "EX_charge True\n" ] } ], "source": [ "for rxn in tmodel.reactions:\n", " if rxn.ignore_snd:\n", " print(rxn.id,rxn.ignore_snd)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "charge_ce False\n", "charge_ce True\n", "charge_cm False\n", "charge_cm True\n", "charge_cx False\n", "charge_cx True\n", "charge_cr False\n", "charge_cr True\n", "charge_cv False\n", "charge_cv True\n", "charge_cg False\n", "charge_cg True\n", "charge_cn False\n", "charge_cn True\n" ] } ], "source": [ "#ignore snd for charge ?\n", "for rxn in tmodel.reactions:\n", " if 'charge' in rxn.id and 'EX' not in rxn.id:#charge reactions are constrained by 2nd law \n", " print(rxn.id,rxn.ignore_snd)\n", " rxn.ignore_snd=True\n", " print(rxn.id,rxn.ignore_snd)\n", " \n", "\n", "#tmodel.reactions.EX_charge.ignore_snd=True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 7 - Establishment of the thermodynamic-stoichiometric solution space\n", "Note : In our curation of the iMM904 model, due to the limited information available for the membrane potential of organelles, we chose to allow the free leakage of ions (charges) across the membrane. \n", "Allowing free movement of charges between compartments prevents over-constraining the model to potentially incorrect information.\n", "For more detailed analysis of charge transport or models where more information is available on membrane physiology then a constraint on the second law could be added for these charge transport reactions. " ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter NonConvex to value 2\n", "Set parameter TimeLimit to value 10\n" ] } ], "source": [ "# add the TFBA variables to the model\n", "tmodel.m = None #reset the gurobi model object in case you're re-running this cell \n", "tmodel.add_TFBA_variables(gdiss_constraint = False, sigmac_limit = (5000/tmodel.T.m), error_type = 'covariance',qnorm=1,alpha=0.95)\n", "tmodel.m.update()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "thermo_flux.solver.gurobi.model_start(tmodel,'fixed_dir_firstTFBA_ENS_8.sol', ignore_vars=['all'],fix_vars=['qm','fluxes'],fix='start')\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter IntFeasTol to value 1e-06\n", "Set parameter TimeLimit to value 60\n", "Gurobi Optimizer version 11.0.0 build v11.0.0rc2 (win64 - Windows 11+.0 (22631.2))\n", "\n", "CPU model: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 4 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 15685 rows, 12850 columns and 350518 nonzeros\n", "Model fingerprint: 0x1b1ad44f\n", "Model has 1 general constraint\n", "Variable types: 11263 continuous, 1587 integer (1587 binary)\n", "Coefficient statistics:\n", " Matrix range [6e-06, 1e+06]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+06]\n", " RHS range [1e-05, 1e+06]\n", "\n", "Warning: Completing partial solution with 1587 unfixed non-continuous variables out of 1587\n", "User MIP start produced solution with objective 2.14592 (0.30s)\n", "Loaded user MIP start with objective 2.14592\n", "\n", "Presolve removed 8574 rows and 6443 columns\n", "Presolve time: 1.61s\n", "Presolved: 7111 rows, 6407 columns, 277793 nonzeros\n", "Variable types: 5169 continuous, 1238 integer (1238 binary)\n", "\n", "Root simplex log...\n", "\n", "Iteration Objective Primal Inf. Dual Inf. Time\n", " 6208 1.2993797e+00 3.446101e+05 0.000000e+00 5s\n", " 12785 2.1805119e+00 0.000000e+00 0.000000e+00 8s\n", "\n", "Root relaxation: objective 2.180512e+00, 12785 iterations, 5.59 seconds (7.85 work units)\n", "Total elapsed time = 31.75s (DegenMoves)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 2.18051 0 43 2.14592 2.18051 1.61% - 32s\n", " 0 0 2.18051 0 47 2.14592 2.18051 1.61% - 32s\n", " 0 0 2.18051 0 46 2.14592 2.18051 1.61% - 33s\n", " 0 0 2.18051 0 55 2.14592 2.18051 1.61% - 36s\n", " 0 0 2.18051 0 49 2.14592 2.18051 1.61% - 39s\n", " 0 0 2.18051 0 19 2.14592 2.18051 1.61% - 44s\n", " 0 0 2.18051 0 18 2.14592 2.18051 1.61% - 45s\n", " 0 0 2.18051 0 14 2.14592 2.18051 1.61% - 48s\n", " 0 0 2.18051 0 14 2.14592 2.18051 1.61% - 49s\n", " 0 0 2.18051 0 19 2.14592 2.18051 1.61% - 52s\n", " 0 0 2.18043 0 20 2.14592 2.18043 1.61% - 53s\n", " 0 0 2.18043 0 19 2.14592 2.18043 1.61% - 53s\n", " 0 0 2.18043 0 14 2.14592 2.18043 1.61% - 55s\n", " 0 0 2.18042 0 10 2.14592 2.18042 1.61% - 56s\n", " 0 0 2.18039 0 11 2.14592 2.18039 1.61% - 57s\n", " 0 0 2.18039 0 9 2.14592 2.18039 1.61% - 58s\n", " 0 0 2.18039 0 9 2.14592 2.18039 1.61% - 58s\n", " 0 0 2.18038 0 9 2.14592 2.18038 1.61% - 58s\n", "\n", "Cutting planes:\n", " Learned: 60\n", " Cover: 3\n", " Implied bound: 10\n", " MIR: 13\n", " Flow cover: 33\n", " Relax-and-lift: 4\n", "\n", "Explored 1 nodes (49500 simplex iterations) in 60.25 seconds (53.86 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 1: 2.14592 \n", "\n", "Time limit reached\n", "Best objective 2.145918254336e+00, best bound 2.180382715743e+00, gap 1.6060%\n" ] } ], "source": [ "tmodel.m.params.NonConvex=2\n", "tmodel.m.params.IntFeasTol=1e-6\n", "tmodel.m.params.OptimalityTol=1e-6\n", "tmodel.m.params.TimeLimit=60*1\n", "tmodel.m.optimize()\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "tmodel.m.write('fixed_dir_firstTFBA_ENS_9.mps')\n", "tmodel.m.write('fixed_dir_firstTFBA_ENS_9.sol')" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "drG error term\n", "Ex: 143.54648665524567\n", "Int: -143.54620102128138\n", "Diff: 0.00028563396429603927\n", "\n", "\n", "RTlnC concentration term\n", "Ex: -257.1979974465446\n", "Int: 257.19799744655256\n", "Diff: 7.958078640513122e-12\n", "\n", "\n", "drG0' term\n", "Ex: 28160.88767254069\n", "Int: -28160.88767254047\n", "Diff: 2.219167072325945e-10\n", "\n", "\n", "drG0 term non-transformed\n", "Ex: 27952.820538559\n", "Int: -27952.820538558746\n", "Diff: 2.546585164964199e-10\n", "\n", "\n", "drG0' transform term\n", "Ex: 0.0\n", "Int: 0.0\n", "Diff: 0.0\n", "\n", "\n", "drG0' total transport term\n", "Ex: 0.0\n", "Int: -0.0007508681337640155\n", "Diff: -0.0007508681337640155\n", "\n", "\n", "drG0' charge transport term\n", "Ex: 0.0\n", "Int: 7.466136594302952e-05\n", "Diff: 7.466136594302952e-05\n", "\n", "\n", "drG0'proton transport term\n", "Ex: 0.0\n", "Int: -0.0008255294998775753\n", "Diff: -0.0008255294998775753\n" ] } ], "source": [ "thermo_flux.solver.gurobi.gdiss_model(tmodel)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter NonConvex to value 2\n", "Set parameter TimeLimit to value 10\n", "Set parameter TimeLimit to value 300\n", "Gurobi Optimizer version 11.0.0 build v11.0.0rc2 (win64 - Windows 11+.0 (22631.2))\n", "\n", "CPU model: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 4 physical cores, 8 logical processors, using up to 8 threads\n", "\n", "Optimize a model with 15686 rows, 13017 columns and 350685 nonzeros\n", "Model fingerprint: 0x659902df\n", "Model has 166 quadratic constraints\n", "Model has 1 general constraint\n", "Variable types: 11430 continuous, 1587 integer (1587 binary)\n", "Coefficient statistics:\n", " Matrix range [6e-06, 1e+06]\n", " QMatrix range [1e+00, 1e+00]\n", " QLMatrix range [1e+00, 1e+00]\n", " Objective range [1e+00, 1e+00]\n", " Bounds range [5e-05, 1e+06]\n", " RHS range [1e-05, 1e+06]\n", "\n", "Solving a multi-scenario model with 50 scenarios...\n", "\n", "Presolve removed 11125 rows and 8819 columns\n", "Presolve time: 0.28s\n", "Presolved: 4888 rows, 4248 columns, 15024 nonzeros\n", "Presolved model has 81 bilinear constraint(s)\n", "Presolved model has 50 scenario(s)\n", "\n", "Solving non-convex MIQCP\n", "\n", "Variable types: 3286 continuous, 962 integer (962 binary)\n", "\n", "Root relaxation: objective 1.202063e+00, 2935 iterations, 0.20 seconds (0.10 work units)\n", "\n", " Nodes | Current Node | Objective Bounds | Work\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", "\n", " 0 0 1.20206 0 50 - 1.20206 - - 0s\n", " 0 0 1.20206 0 54 - 1.20206 - - 1s\n", " 0 0 1.20206 0 54 - 1.20206 - - 1s\n", " 0 0 1.19820 0 30 - 1.19820 - - 1s\n", " 0 0 1.19820 0 30 - 1.19820 - - 1s\n", " 0 0 1.19820 0 31 - 1.19820 - - 1s\n", " 0 0 1.19820 0 32 - 1.19820 - - 1s\n", " 0 0 1.19820 0 30 - 1.19820 - - 1s\n", " 0 0 1.19820 0 30 - 1.19820 - - 1s\n", " 0 0 1.19820 0 27 - 1.19820 - - 2s\n", " 0 0 1.19820 0 28 - 1.19820 - - 2s\n", " 0 0 1.19820 0 27 - 1.19820 - - 2s\n", " 0 0 1.02710 0 27 - 1.02710 - - 3s\n", "H 0 0 -0.0000000 1.02710 - - 3s\n", " 0 2 1.02710 0 27 -0.00000 1.02710 - - 4s\n", " 38 45 -0.00000 11 8 -0.00000 1.02700 - 23.6 5s\n", "H 839 783 0.0000000 1.02570 - 12.8 14s\n", "H 840 783 0.0000000 1.02570 - 12.8 14s\n", "H 849 811 0.1766679 1.02570 481% 12.9 14s\n", "H 867 811 0.3850917 1.02570 166% 12.9 14s\n", " 871 853 0.51994 72 11 0.38509 1.02570 166% 13.0 16s\n", "H 1131 1054 0.3914907 1.02570 162% 13.1 18s\n", " 1135 421 0.39149 31 35 0.39149 1.02570 162% 13.1 20s\n", " 1145 172 0.40662 149 42 0.39149 0.40886 4.44% 17.3 26s\n", " 1152 72 0.39149 66 40 0.39149 0.40886 4.44% 22.1 30s\n", "Scenario 3 has been solved (gap 0.0020%). 48/50 scenarios left.\n", " 1154 49 -0.00000 38 25 0.39149 0.40886 4.44% 27.2 38s\n", " 1322 169 -0.00000 62 19 0.39149 0.40885 4.43% 25.9 40s\n", " 2838 1705 0.25606 150 32 0.39149 0.40690 3.94% 19.7 45s\n", "H 3486 2294 0.4003544 0.40690 1.64% 18.6 47s\n", "H 3731 2466 0.4018819 0.40689 1.25% 18.6 48s\n", "H 3835 2560 0.4018852 0.40687 1.24% 18.6 48s\n", "H 3954 2693 0.4018853 0.40687 1.24% 18.4 49s\n", " 4185 3072 0.39547 100 40 0.40189 0.40687 1.24% 17.9 50s\n", "H 5709 4341 0.4019121 0.40682 1.22% 16.5 54s\n", " 5795 4614 0.38552 108 54 0.40191 0.40682 1.22% 16.3 55s\n", " 7998 6722 0.03982 195 20 0.40191 0.40678 1.21% 15.4 60s\n", " 9842 5587 0.40261 122 12 0.40191 0.40675 1.20% 16.7 65s\n", "*10580 5888 290 0.4019171 0.40675 1.20% 16.4 66s\n", " 12029 7125 0.27138 116 38 0.40192 0.40666 1.18% 16.3 70s\n", "H12935 7608 0.4022758 0.40657 1.07% 16.8 72s\n", " 14248 8911 infeasible 200 0.40228 0.40652 1.06% 16.8 76s\n", "H15435 9540 0.4022806 0.40617 0.97% 17.1 80s\n", "H15452 9540 0.4024703 0.40617 0.92% 17.1 80s\n", " 15506 9577 0.39308 118 29 0.40247 0.40617 0.92% 17.1 85s\n", "Scenario 1 has been solved. 47/50 scenarios left.\n", "Scenario 2 has been solved. 46/50 scenarios left.\n", "Scenario 5 has been solved. 45/50 scenarios left.\n", "Scenario 6 has been solved. 44/50 scenarios left.\n", " 15548 9579 0.39308 119 29 0.40247 0.40617 0.92% 17.1 120s\n", "Scenario 4 has been solved. 43/50 scenarios left.\n", "Scenario 7 has been solved (gap 0.0018%). 42/50 scenarios left.\n", "Scenario 8 has been solved (gap 0.0069%). 41/50 scenarios left.\n", "Scenario 9 has been solved. 40/50 scenarios left.\n", " 16277 10992 0.38948 98 35 0.40247 0.40607 0.89% 17.0 127s\n", "H17122 11379 0.4024815 0.40567 0.79% 16.6 129s\n", " 17580 11996 0.37760 141 24 0.40248 0.40557 0.77% 16.7 132s\n", " 18324 12778 0.38603 109 43 0.40248 0.40442 0.48% 16.7 135s\n", " 20342 14646 0.35600 143 41 0.40248 0.40355 0.27% 16.3 141s\n", "H21366 14798 0.4026757 0.40350 0.21% 16.3 143s\n", "H21371 14798 0.4026888 0.40350 0.20% 16.4 143s\n", " 21587 15652 0.40350 80 36 0.40269 0.40350 0.20% 16.4 146s\n", " 23746 17593 0.35200 129 34 0.40269 0.40350 0.20% 16.3 152s\n", "*24067 17593 171 0.4027681 0.40350 0.18% 16.2 152s\n", "*24759 17593 165 0.4028130 0.40350 0.17% 16.1 152s\n", " 24904 18017 0.36228 164 43 0.40281 0.40350 0.17% 16.1 155s\n", " 26619 19080 0.39076 120 49 0.40281 0.40350 0.17% 16.2 160s\n", "H26693 19080 0.4029112 0.40350 0.14% 16.2 160s\n", " 27890 20560 cutoff 105 0.40291 0.40345 0.13% 16.3 166s\n", " 28939 21573 0.39425 150 30 0.40291 0.40345 0.13% 16.0 170s\n", " 31013 23127 0.39472 195 4 0.40291 0.40345 0.13% 15.7 175s\n", " 32841 24688 0.40336 86 35 0.40291 0.40341 0.12% 15.6 182s\n", " 33978 25996 0.39189 185 23 0.40291 0.40341 0.12% 15.6 186s\n", " 35466 26987 infeasible 105 0.40291 0.40340 0.12% 15.3 190s\n", " 37764 28344 0.38396 168 25 0.40291 0.40340 0.12% 15.3 195s\n", " 39656 29782 infeasible 95 0.40291 0.40338 0.12% 15.5 202s\n", " 40905 30530 0.40155 87 52 0.40291 0.40338 0.12% 15.5 207s\n", " 41838 30924 0.38574 151 28 0.40291 0.40338 0.12% 15.4 210s\n", " 43650 32430 0.39840 118 40 0.40291 0.40337 0.11% 15.7 216s\n", " 44490 32417 0.40259 133 34 0.40291 0.40337 0.11% 15.7 224s\n", "Scenario 12 has been solved (gap 0.0079%). 39/50 scenarios left.\n", " 44498 33271 0.40259 134 33 0.40291 0.40336 0.11% 15.7 227s\n", " 45548 33460 infeasible 160 0.40291 0.40335 0.11% 15.7 230s\n", " 47272 33928 cutoff 113 0.40291 0.40333 0.10% 16.2 236s\n", " 48281 33922 0.40323 146 39 0.40291 0.40333 0.10% 16.5 241s\n", " 49414 34994 0.40329 139 32 0.40291 0.40332 0.10% 16.6 247s\n", "H49845 34994 0.4029574 0.40332 0.09% 16.6 247s\n", " 50165 35613 0.39175 104 40 0.40296 0.40332 0.09% 16.6 250s\n", " 52053 36182 0.40326 105 36 0.40296 0.40328 0.08% 16.8 268s\n", "Scenario 11 has been solved (gap 0.0056%). 38/50 scenarios left.\n", " 52092 36781 0.40326 106 37 0.40296 0.40328 0.08% 16.8 272s\n", " 52989 37366 cutoff 113 0.40296 0.40327 0.08% 16.8 276s\n", " 53864 38129 0.39532 203 22 0.40296 0.40324 0.07% 16.8 284s\n", " 55063 38537 0.40320 150 41 0.40296 0.40323 0.07% 16.8 291s\n", " 56072 39425 infeasible 110 0.40296 0.40321 0.06% 16.9 298s\n", "\n", "Cutting planes:\n", " Learned: 18\n", " Flow cover: 1\n", " RLT: 1\n", "\n", "Explored 57432 nodes (975891 simplex iterations) in 300.49 seconds (56.02 work units)\n", "Thread count was 8 (of 8 available processors)\n", "\n", "Solution count 10: 0.402957 0.402957 0.402957 ... 0.402911\n", "\n", "Time limit reached\n", "Best objective 4.029573999817e-01, best bound 4.032086474970e-01, gap 0.0624%\n" ] } ], "source": [ "# add the TFBA variables to the model\n", "tmodel.m = None #reset the gurobi model object in case you're re-running this cell \n", "tmodel.add_TFBA_variables(gdiss_constraint = True, sigmac_limit = (3700/tmodel.T.m), error_type = 'covariance',qnorm=1,alpha=0.95)\n", "tmodel.m.update()\n", "tmodel.m.params.timelimit=60*5\n", "\n", "GUR_range = np.linspace(-0, -23, 50)\n", "\n", "thermo_flux.solver.gurobi.variable_scan(tmodel, GUR_range, var = tmodel.mvars['v'][0][tmodel.reactions.index(tmodel.reactions.get_by_id('EX_glc__D_e'))]) # here we get the index for the glucose uptake reaction and use this to index the v variable in the gurobi model\n", "thermo_flux.solver.gurobi.model_start(tmodel,'fixed_dir_firstTFBA_ENS_9.sol',ignore_vars=['all'],fix_vars=['qm'],fix='bound') #fix the drG error term to that from the initial TFBA to speed up optimisations\n", "\n", "tmodel.m.optimize()\n", "\n", "fluxes_gdiss = thermo_flux.solver.gurobi.multi_scenario_sol(tmodel,var = 'v') \n", "fluxes_gdiss= pd.DataFrame(fluxes_gdiss[0].T, index = [rxn.id for rxn in tmodel.reactions])" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "image/png": "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GVPdzr9qizS5uSknKD87hwfgXoNERETGJmtIa9asWThw4ABmzJiB27dvQwiB6dOnIyUlBWvWrIGvry9eeeUVnb0+pKRQKFdj5durEQD3GiQiIjIFWT0869evR+vWrfHxxx9rXHdzc8OAAQMQGBiIxo0b46uvvsLkyZONEqgl8vJSrsZS7sOjHMZyc2OyQ0REZGyyengSExPRunXrp41YWWn05nh6euLFF1/EihUrih+hhVMolKuxWrVS/stkh4iIyPhkJTyOjo6wsnp6V2dnZ6SkpGjUcXd3R2JiYvGiIyIiIjICWQmPj4+PRjLj7++PXbt2qXt5hBDYuXMnPDw8jBMlERERUTHISng6d+6M6Oho5OTkAADCwsKQmJiIwMBAvPfee2jXrh3i4+PRv39/owZLREREJIesScsjR45ElSpVcOvWLXh4eOD111/H8ePHsXDhQsTHxwMA+vfvj+nTpxsxVAvx9LRQwMUFcHXlxB0iIiITM+rRErdu3cKVK1fg4+MDd3d3YzVrciV2tARPCyUiIjIasx0tUa1aNbRq1apMJTslpqjTQtPSzBMXERFROcCztEpKaqrubZUB5fXU1JKNh4iIqByRnfDExsaiX79+qFWrFuzt7WFtba31ZWMj+6guy8PTQomIiMxGVkbyv//9D2FhYRBCoFatWmjZsiWTm6LwtFAiIiKzkZWlfPrpp1AoFPjnn3/QokULY8dkmXhaKBERkdnIPlpi8ODBTHYMwdNCiYiIzEZWD0/NmjXx+PFjY8di+XhaKBERkVnISnhGjx6NL774Anfv3kXlypWNHZNlUyiY4BAREZUwWQnP+PHjcenSJbRt2xYff/wxGjduXOCGP97e3sUKkIiIiKi4ZC+tCggIwP/+9z8MGzaswDqSJKnP2yIiIiIyF1kJz3fffYcJEybA1tYWHTt2hIeHB5elExERUaklK0uZP38+atSogdjYWHh6eho7JiIiIiKjkrUs/caNG+jfvz+THSIiIioTZCU8tWvXxr1794wcylMLFy6Er68vKlSogGbNmmHv3r2F1t+9ezeaNWuGChUqoFatWvjpp59MFpsh0tKA8+eBgweBCxd4PigREZG5yEp4Jk6ciI0bN+K///4zdjxYs2YNJkyYgClTpuD48eNo3749evTogcTERJ31r169ip49e6J9+/Y4fvw4PvroI4wbNw7r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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#plot biomass yield for stoichiometric model with balanced reactions and pH specified\n", "df_data2 = pd.read_csv('plotting_Yeast_ALL_experimental_data.csv',index_col=0)\n", "df_data2['regression'].fillna('Not fitted',inplace=True)\n", "df_data2['regression'].replace('yes', 'Fitted', inplace=True)\n", "df_data2.rename(columns={'regression':'Exp. data'}, inplace=True)\n", "#rename index in Condition\n", "df_data2.index.rename('Condition', inplace=True)\n", "\n", "GUR_plot_range=[-x for x in GUR_range]\n", "#plot biomass vs GUR in a scatter plot\n", "\n", "sns.scatterplot(x=GUR_plot_range,y=fluxes_gdiss.loc['biomass_EX'],color='b',label='TFBA')\n", "# sns.scatterplot(x=GUR_plot_range,y=tbiomass_flux,color='b',label='FBA and balanced')\n", "# sns.scatterplot(x=GUR_plot_range,y=biomass_flux,color='g',label='FBA')\n", "sns.scatterplot(x=df_data2['glc-D_EX'], y=df_data2['biomass_EX'], color=['red'],label='Experimental data')\n", "plt.xlabel('Glucose uptake rate (mmol/(gDW.h))',fontsize=14)\n", "plt.ylabel('Biomass production rate (mmol/(gDW.h))',fontsize=14)\n", "\n", "plt.savefig('Figures/growth_all_TFBA_gdissconstraint.png',dpi=300)\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "thermoflux", "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.10.13" } }, "nbformat": 4, "nbformat_minor": 2 }