{ "cells": [ { "cell_type": "markdown", "id": "2035e1d8-d4c4-4894-bf65-2795562619f6", "metadata": {}, "source": [ "# Building a model\n", "## Building through individual reactions\n", "We begin by constructing a kinetic model for a metabolic system, which consists of biochemical reactions governed by user-defined rate laws.\n", "\n", "First, initialize an empty model:" ] }, { "cell_type": "code", "execution_count": 1, "id": "8ac2ea83-775c-4ea8-8d6b-21a85277e46e", "metadata": {}, "outputs": [], "source": [ "from robustnet import Model\n", "\n", "model = Model('demo')\n", "print(model)" ] }, { "cell_type": "markdown", "id": "b89925e6-2ddf-44b0-ad57-2a500417e498", "metadata": {}, "source": [ "Then a reaction can be created and added to the model by specifying reaction ID, catalytic enzyme ID (None for non-enzymatic reations), substrate and product stoichiometry, as well as kinetic rate expression.\n", "\n", "Below is an example of adding the glucose phosphotransferase system reaction using a generalized reversible Hill-type rate law:\n", "\n", "
glucose (GLC) + phosphoenolpyruvate (PEP) <-> glucose 6-phosphate (G6P) + pyruvate (PYR)
" ] }, { "cell_type": "code", "execution_count": 2, "id": "925a3469-863c-44db-b2a1-516666afeea8", "metadata": {}, "outputs": [], "source": [ "model.add_reaction(\n", " 'GlcPTS',\n", " enzyme='GlcPTS',\n", " substrates={'GLC': 1, 'PEP': 1},\n", " products={'G6P': 1, 'PYR': 1},\n", " rate_expression='kcat_vGlcPTS * GlcPTS * '\n", " '(GLC * PEP / (Km_GLC_vGlcPTS * Km_PEP_vGlcPTS)) * '\n", " '(1 - G6P * PYR / (GLC * PEP) / Keq_vGlcPTS) / '\n", " '((1 + PEP / Km_PEP_vGlcPTS + PYR / Km_PYR_vGlcPTS) * '\n", " '(1 + GLC / Km_GLC_vGlcPTS + G6P / Km_G6P_vGlcPTS))'\n", ")" ] }, { "cell_type": "markdown", "id": "7318ecc3-4fe6-4bdc-aa2b-2759324aec9a", "metadata": {}, "source": [ "Rate expressions can be provided as plain strings. Metabolite variables, enzyme variables, and kinetic parameters are automatically parsed from the expression. \n", "\n", "Kinetic parameter names can be arbitrary, although the following naming are recommended for clarity:\n", "- catalytic constants: \"kcat_{reaction_id}\"\n", "- Michaelis constants: \"Km_{metabolite_id}\\_{reaction_id}\"\n", "- equilibrium constants: \"Keq_{reaction_id}\"\n", "\n", "
\n", "Note:

\n", "Metabolite IDs cannot start with a number and must not overlap with enzyme IDs.\n", "Enzyme and metabolite identifiers should remain consistent with those used in the rate expressions.\n", "
" ] }, { "cell_type": "markdown", "id": "cb237b3c-0a6f-49c2-88fe-1517aaf4fbe5", "metadata": {}, "source": [ "Next, we we add the reaction catalyzed by glucose-6-phosphate isomerase:\n", "\n", "
glucose 6-phosphate (G6P) <-> fructose 6-phosphate (F6P)
\n", "\n", "using a reversible Michaelis–Menten rate law with competitive inhibition by PEP and mixed inhibition by 6-phospho-D-gluconate (PGlc):" ] }, { "cell_type": "code", "execution_count": 3, "id": "1a3d86c0-a759-4316-ba25-89465f1c79c8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Model demo with 2 reactions and 5 metabolites\n" ] } ], "source": [ "model.add_reaction(\n", " 'PGI',\n", " enzyme='PGI',\n", " substrates={'G6P': 1},\n", " products={'F6P': 1},\n", " rate_expression='kcat_vPGI * PGI * '\n", " '(G6P / Km_G6P_vPGI) * '\n", " '(1 - F6P / G6P / Keq_vPGI) / '\n", " '(1 + G6P / Km_G6P_vPGI + F6P / Km_F6P_vPGI + PEP/Ki_PEP_vPGI + PGlc/Ki_PGlc_vPGI) * '\n", " '(Ki_PGlc_vPGI / (Ki_PGlc_vPGI + PGlc))'\n", ")\n", "print(model)" ] }, { "cell_type": "markdown", "id": "fbc29505-78ba-475f-b159-d49b4a03a3bf", "metadata": {}, "source": [ "The parsed kinetic parameters from all added reactions can then be inspected as follows:" ] }, { "cell_type": "code", "execution_count": 4, "id": "5820e85f-718f-416f-abf2-af2f82603322", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'GlcPTS': ['Keq_vGlcPTS',\n", " 'Km_G6P_vGlcPTS',\n", " 'Km_GLC_vGlcPTS',\n", " 'Km_PEP_vGlcPTS',\n", " 'Km_PYR_vGlcPTS',\n", " 'kcat_vGlcPTS'],\n", " 'PGI': ['Keq_vPGI',\n", " 'Ki_PEP_vPGI',\n", " 'Ki_PGlc_vPGI',\n", " 'Km_F6P_vPGI',\n", " 'Km_G6P_vPGI',\n", " 'PGlc',\n", " 'kcat_vPGI']}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.parsed_kinetic_parameters()" ] }, { "cell_type": "markdown", "id": "4bb34a46-3433-4387-9242-7554865338df", "metadata": {}, "source": [ "
\n", "Note:

\n", "In the PGI reaction, \"PGlc\" interpreted as a kinetic parameter because it appears only in the rate expression. Once it is introduced as a substrate or product in another reaction, it will instead be treated as a metabolite variable.\n", "
\n", "\n", "More generally, after all reactions are added, any variable that appears only in rate expressions but not in the `substrates`, `products`, or `enzyme` argument, is automatically classified as a kinetic parameter.\n", "\n", "To remove reaction(s) from model, use `remove_reaction` method:" ] }, { "cell_type": "code", "execution_count": 5, "id": "06c67b6d-1528-4052-a84c-fca53e0c9973", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Model demo with 1 reactions and 4 metabolites\n" ] } ], "source": [ "model.remove_reaction(['PGI'])\n", "print(model)" ] }, { "cell_type": "markdown", "id": "5b1eb61d-fba3-4d2f-ab6b-8248ac4e437a", "metadata": {}, "source": [ "## Reading from file\n", "Alternatively, an entire model can be loaded directly from a file containing the following required fields: \"Reaction\", \"Enzyme\", \"Substrates\", \"Products\" and \"Rate expression\". \n", "\n", "An example [*E .coli* model](https://github.com/Chaowu88/robustnet/blob/main/models/e_coli/e_coli_model.xlsx) is available in the repository for reference." ] }, { "cell_type": "code", "execution_count": 6, "id": "e18a0ec9-c8f1-4642-b0c9-b0cfca824c4b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Model ecoli with 64 reactions and 50 metabolites\n" ] } ], "source": [ "MODEL_FILE = '../../models/e_coli/e_coli_model.xlsx'\n", "\n", "model = Model('ecoli')\n", "model.read_from_file(MODEL_FILE)\n", "print(model)" ] }, { "cell_type": "markdown", "id": "617f5112-4d22-4856-9778-5a0185d6eae2", "metadata": {}, "source": [ "The reaction information stored in the model can then be inspected as follows (showing the first five reactions):" ] }, { "cell_type": "code", "execution_count": 7, "id": "0b12fd06-ed19-48a3-9f21-4aeee80b942a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GlcPTS \n", " Reaction(enzyme='GlcPTS', substrates={'GLC': 1.0, 'PEP': 1.0}, products={'G6P': 1.0, 'PYR': 1.0}, ratelaw=Ratelaw(enz='GlcPTS', metabs=['G6P', 'GLC', 'PEP', 'PYR'], kparams=['Keq_vGlcPTS', 'Km_G6P_vGlcPTS', 'Km_GLC_vGlcPTS', 'Km_PEP_vGlcPTS', 'Km_PYR_vGlcPTS', 'kcat_vGlcPTS'], expr=GLC*GlcPTS*PEP*kcat_vGlcPTS*(-G6P*PYR/(GLC*Keq_vGlcPTS*PEP) + 1)/(Km_GLC_vGlcPTS*Km_PEP_vGlcPTS*(1 + PYR/Km_PYR_vGlcPTS + PEP/Km_PEP_vGlcPTS)*(G6P/Km_G6P_vGlcPTS + GLC/Km_GLC_vGlcPTS + 1))))\n", "PGI \n", " Reaction(enzyme='PGI', substrates={'G6P': 1.0}, products={'F6P': 1.0}, ratelaw=Ratelaw(enz='PGI', metabs=['F6P', 'G6P', 'PEP', 'PGlc'], kparams=['Keq_vPGI', 'Ki_PEP_vPGI', 'Ki_PGlc_vPGI', 'Km_F6P_vPGI', 'Km_G6P_vPGI', 'kcat_vPGI'], expr=G6P*Ki_PGlc_vPGI*PGI*kcat_vPGI*(-F6P/(G6P*Keq_vPGI) + 1)/(Km_G6P_vPGI*(Ki_PGlc_vPGI + PGlc)*(F6P/Km_F6P_vPGI + G6P/Km_G6P_vPGI + 1 + PGlc/Ki_PGlc_vPGI + PEP/Ki_PEP_vPGI))))\n", "PFK \n", " Reaction(enzyme='PFK', substrates={'ATP': 1.0, 'F6P': 1.0}, products={'ADP': 1.0, 'FBP': 1.0}, ratelaw=Ratelaw(enz='PFK', metabs=['ADP', 'ATP', 'F6P', 'FBP', 'PEP'], kparams=['Keq_vPFK', 'Ki_PEP_vPFK', 'Km_ADP_vPFK', 'Km_ATP_vPFK', 'Km_F6P_vPFK', 'Km_FBP_vPFK', 'kcat_vPFK'], expr=ATP*F6P*PFK*kcat_vPFK*(-ADP*FBP/(ATP*F6P*Keq_vPFK) + 1)/(Km_ATP_vPFK*Km_F6P_vPFK*((ADP/Km_ADP_vPFK + ATP/Km_ATP_vPFK + 1)*(F6P/Km_F6P_vPFK + FBP/Km_FBP_vPFK + 1) + PEP/Ki_PEP_vPFK))))\n", "FBPase \n", " Reaction(enzyme='FBPase', substrates={'FBP': 1.0}, products={'F6P': 1.0, 'Pi': 1.0}, ratelaw=Ratelaw(enz='FBPase', metabs=['ADP', 'AMP', 'F6P', 'FBP', 'PEP', 'Pi'], kparams=['Ka_PEP_vFBPase', 'Keq_vFBPase', 'Ki_ADP_vFBPase', 'Ki_AMP_vFBPase', 'Ki_Pi_vFBPase', 'Km_F6P_vFBPase', 'Km_FBP_vFBPase', 'Km_Pi_vFBPase', 'kcat_vFBPase'], expr=FBP*FBPase*Ki_ADP_vFBPase*Ki_AMP_vFBPase*PEP*kcat_vFBPase*(-F6P*Pi/(FBP*Keq_vFBPase) + 1)/(Km_FBP_vFBPase*(ADP + Ki_ADP_vFBPase)*(AMP + Ki_AMP_vFBPase)*(Ka_PEP_vFBPase + PEP)*(ADP/Ki_ADP_vFBPase + AMP/Ki_AMP_vFBPase + F6P/Km_F6P_vFBPase + F6P*Pi/(Km_F6P_vFBPase*Km_Pi_vFBPase) + FBP/Km_FBP_vFBPase + 1 + Pi/Km_Pi_vFBPase + Pi/Ki_Pi_vFBPase))))\n", "FBA \n", " Reaction(enzyme='FBA', substrates={'FBP': 1.0}, products={'DHAP': 1.0, 'GAP': 1.0}, ratelaw=Ratelaw(enz='FBA', metabs=['DHAP', 'FBP', 'GAP'], kparams=['Keq_vFBA', 'Ki_DHAP_vFBA', 'Km_DHAP_vFBA', 'Km_FBP_vFBA', 'Km_GAP_vFBA', 'kcat_vFBA'], expr=FBA*FBP*Ki_DHAP_vFBA*kcat_vFBA*(-DHAP*GAP/(FBP*Keq_vFBA) + 1)/(Km_FBP_vFBA*(DHAP + Ki_DHAP_vFBA)*(DHAP*GAP/(Km_DHAP_vFBA*Km_GAP_vFBA) + DHAP/Km_DHAP_vFBA + DHAP/Ki_DHAP_vFBA + FBP/Km_FBP_vFBA + GAP/Km_GAP_vFBA + 1))))\n" ] } ], "source": [ "for rxn_id, rxn_info in list(model.reaction_info.items())[:5]:\n", " print(rxn_id, '\\n', rxn_info)" ] }, { "cell_type": "markdown", "id": "cbecb3dc-48ff-4c02-a659-37316bfd1a0b", "metadata": {}, "source": [ "PGlc is now recognized as a metabolite in the model." ] }, { "cell_type": "code", "execution_count": 8, "id": "87ae38bd-dfaf-438d-b4c9-86a96f090f09", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'PGlc': 1.0}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.reaction_info['PGL'].products" ] }, { "cell_type": "code", "execution_count": 9, "id": "90b931b5-30de-4e14-a42b-72279709e019", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'PGI': ['Keq_vPGI',\n", " 'Ki_PEP_vPGI',\n", " 'Ki_PGlc_vPGI',\n", " 'Km_F6P_vPGI',\n", " 'Km_G6P_vPGI',\n", " 'kcat_vPGI']}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.parsed_kinetic_parameters('PGI')" ] } ], "metadata": { "kernelspec": { "display_name": "robustnet-py311", "language": "python", "name": "robustnet-py311" }, "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.15" } }, "nbformat": 4, "nbformat_minor": 5 }