{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Building a Model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Building form Metabolite and Reaction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A metabolic network consists of metabolites and their reactions, which can be constructed using the Metabolite and Reaction constructor, respectively. For example, let's construct the reaction PPS:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ATP$_c$ + H2O$_c$ + Pyr$_c$ -> AMP$c$ + 2.0H$_c^+$ + PEP$_c$ + Pi$c$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "by phosphoenolpyruvate synthase:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0 atp_c + 1.0 h2o_c + 1.0 pyr_c => 1.0 amp_c + 1.0 pep_c + 1.0 pi_c + 2.0 h_c\n" ] } ], "source": [ "from etfba import Metabolite, Reaction\n", "\n", "pyr_c = Metabolite(metabid='pyr_c', name='Pyruvate', compartment='c')\n", "pep_c = Metabolite('pep_c', 'Phosphoenolpyruvate', 'c')\n", "atp_c = Metabolite('atp_c', 'ATP', 'c')\n", "amp_c = Metabolite('amp_c', 'AMP', 'c')\n", "h2o_c = Metabolite('h2o_c', 'H2O', 'c', is_h2o=True)\n", "h_c = Metabolite('h_c', 'H+', 'c', is_h=True)\n", "pi_c = Metabolite('pi_c', 'Phosphate', 'c')\n", "\n", "PPS = Reaction(\n", " rxnid='PPS', \n", " enzyme_name='phosphoenolpyruvate synthase', \n", " category='Glycolysis',\n", " forward_kcat=30.5, \n", " molecular_weight=87.4,\n", " standard_gibbs_energy=-22.1,\n", " reversible=False\n", ")\n", "PPS.add_substrates({pyr_c: 1., atp_c: 1., h2o_c: 1.})\n", "PPS.add_products({pep_c: 1., amp_c: 1., h_c: 2., pi_c: 1.})\n", "print(PPS)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When constructing enzymatic reactions, the catalytic constant, k$_{cat}$, in s$^{-1}$, can be specified using the \"forward_kcat\" or \"fkcat\" argument. The k$_{cat}$ value of the reaction in the reverse direction is set using \"backward_kcat\" or \"bkcat\", depending on the reaction's reversibility." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Note:

In practice, the effective or apparent turnover number k$_{app}$ should be provided, which reflects the actual enzyme activity *in vivo*, accounting for imcomplete substrate saturation, thermodynamic effects, and regulation effects, limited by the *in vitro* measured k$_{cat}$.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The molecular weight (kDa) of the catalyzing enzyme can be provided using the \"molecular_weight\" argument. The standard Gibbs energy change with all reactants in 1 mM concentrations, [ΔrG'm](https://equilibrator.weizmann.ac.il/static/classic_rxns/faq.html#what-does-the-m-in-rg-m-fg-m-and-e-m-mean), can be set using \"standard_gibbs_energy\". The convertion of Δ$_r$G'$^0$ with 1 M concentrations to Δ$_r$G'$^m$ can be made using the following equation:
\n", "
\n", " \n", "
\n", "Here, $n_{s,i}$ and $n_{p,j}$ are the stoichiometric coefficients of the i$^{th}$ and j$^{th}$ substrate and product (excluding H$_2$O and proton) in the reaction, respectively. $R$ is the gas constant and $T$ is the temperature in K." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The thermodynamic and kinetic properties of the enzyme can be assigned or modified using the corresponding attributes directly. For example," ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "PPS.standard_gibbs_energy = -12.1\n", "PPS.forward_kcat = 103.0\n", "PPS.molecular_weight = 85.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Note:

There is no need to set the enzymatic properties for all reactions, for example, the exchange reactions, non-enzymatic transport reactions, and the biomass formation reaction in the model.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can add the above reaction to the model using the `add_reactions` method:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from etfba import Model\n", "\n", "model = Model('demo')\n", "model.add_reactions(PPS) # can accept a sequence of Reactions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can also delete substrates and/or products from a Reaction using the `remove_substrates` and `remove_products`, respectively, and remove reaction(s) from a Model using the `remove_reactions` method." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we can add the reaction PYK: ADP$_c$ + H$_c^+$ + PEP$_c$ -> ATP$_c$ + Pyr$_c$ catalyzed by pyruvate kinase to further enrich the model." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "model demo with 2 reactions and 8 metabolites\n" ] } ], "source": [ "adp_c = Metabolite('adp_c', 'ADP', 'c')\n", "\n", "PYK = Reaction(\n", " rxnid='PYK', \n", " enzyme_name='pyruvate kinase', \n", " category='Glycolysis',\n", " forward_kcat=38.8, \n", " molecular_weight=51.0,\n", " standard_gibbs_energy=-25.0,\n", " reversible=False\n", ")\n", "PYK.add_substrates({pep_c: 1., adp_c: 1., h_c: 1.})\n", "PYK.add_products({pyr_c: 1., atp_c: 1.})\n", "model.add_reactions([PYK])\n", "print(model)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The building process described above can be conducted iteratively until the complete metabolic network is read into the model. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The complete sets of metabolites and reactions involved in the model can be accessed using the `metabolites` and `reactions` attributes, respectively. Both return a dictionary containing id => Metabolite/Reaction object." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "pyr_c: Pyruvate\n", "atp_c: ATP\n", "h2o_c: H2O\n", "pep_c: Phosphoenolpyruvate\n", "amp_c: AMP\n", "h_c: H+\n", "pi_c: Phosphate\n", "adp_c: ADP\n" ] } ], "source": [ "print(model.metabolites)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PPS: 1.0 atp_c + 1.0 h2o_c + 1.0 pyr_c => 1.0 amp_c + 1.0 pep_c + 1.0 pi_c + 2.0 h_c\n", "PYK: 1.0 adp_c + 1.0 h_c + 1.0 pep_c => 1.0 atp_c + 1.0 pyr_c\n" ] } ], "source": [ "print(model.reactions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The stoichiometric coefficients of metabolites in a reaction can be accessed using:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-1.0\n" ] } ], "source": [ "print(model.metabolites['pyr_c'].coes['PPS'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, negative value denotes pyr_c functions as a substrate of reaction PPS." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, you can also access the stoichiometric coefficient like this:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "print(model.reactions['PPS'].substrates['pyr_c'].coe)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The end metabolites, typically representing the initial substrates or final products of the network, can be accessed by:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "adp_c: ADP\n", "amp_c: AMP\n", "h2o_c: H2O\n", "pi_c: Phosphate\n" ] } ], "source": [ "print(model.end_metabolites)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The stoichiometric metrix of the netowrk can be accessed using `stoichiometric_matrix`. None zero entity in location (i, j) indicate the occurence of metabolite i in reaction j. Negative and postive values denote the role of the correspond metabolite as substrate or product in that reaction. " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " PPS PYK\n", "adp_c 0.0 -1.0\n", "amp_c 1.0 0.0\n", "atp_c -1.0 1.0\n", "h2o_c -1.0 0.0\n", "h_c 2.0 -1.0\n", "pep_c 1.0 -1.0\n", "pi_c 1.0 0.0\n", "pyr_c -1.0 1.0\n" ] } ], "source": [ "print(model.stoichiometric_matrix)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Translating from COBRA Model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When constructing a model from scratch becomes challenging or impractical, leveraging an existing [COBRA](https://cobrapy.readthedocs.io/en/latest/io.html) model and translating it into an ETFBA model by incorporating thermodynamic and enzymatic properties can be advantageous. You can find a script demonstrating the conversion of the *E. coli* [iML1515 model](http://bigg.ucsd.edu/models/iML1515) into the corresponding ETFBA model [here](https://github.com/Chaowu88/etfba/blob/main/models/e_coli/build_from_cobra_model.py). Additionally, the translated *E. coli* model can be accessed [here](https://github.com/Chaowu88/etfba/blob/main/models/e_coli/etfba_iML1515.bin)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Saving and Loading a Model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To save a model:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "model.save('demo.bin')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To load a pickled model:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "model iML1515 with 2712 reactions and 1877 metabolites\n" ] } ], "source": [ "model_file = '../../models/e_coli/etfba_iML1515.bin'\n", "ecoli_model = Model.load(model_file)\n", "print(ecoli_model)" ] } ], "metadata": { "kernelspec": { "display_name": "etfba-py38", "language": "python", "name": "etfba-py38" }, "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.8.19" } }, "nbformat": 4, "nbformat_minor": 4 }