build based on 5cb7a77d
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
%% Cell type:markdown id: tags: | ||
# Loading, converting, and saving models | ||
%% Cell type:markdown id: tags: | ||
`COBREXA` can load models stored in `.mat`, `.json`, and `.xml` formats (with | ||
the latter denoting SBML formatted models). | ||
%% Cell type:markdown id: tags: | ||
We will primarily use the *E. Coli* "core" model to demonstrate the utilities | ||
found in `COBREXA`. First, let's download the model in several formats. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
# Downloads the model files if they don't already exist | ||
!isfile("e_coli_core.mat") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.mat", "e_coli_core.mat"); | ||
!isfile("e_coli_core.json") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.json", "e_coli_core.json"); | ||
!isfile("e_coli_core.xml") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.xml", "e_coli_core.xml"); | ||
``` | ||
%% Cell type:markdown id: tags: | ||
Now, load the package: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using COBREXA | ||
``` | ||
%% Cell type:markdown id: tags: | ||
## Loading models | ||
%% Cell type:markdown id: tags: | ||
Load the models using the `load_model` function. Each model is able to | ||
"pretty-print" itself, hiding the inner complexity. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
mat_model = load_model("e_coli_core.mat") | ||
``` | ||
%% Output | ||
Metabolic model of type MATModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type MATModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:code id: tags: | ||
``` julia | ||
json_model = load_model("e_coli_core.json") | ||
``` | ||
%% Output | ||
Metabolic model of type JSONModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type JSONModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:code id: tags: | ||
``` julia | ||
sbml_model = load_model("e_coli_core.xml") | ||
``` | ||
%% Output | ||
Metabolic model of type SBMLModel\n\n⠀⠈⢀⠀⡀⠀⠀⠀⠀⡠⠂⠀⠀⠀⠀⠈⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⢀⠐⡀⠀⠀⠀⠀⠄\n⠀⠐⠀⠀⠀⠀⠀⠀⡠⠂⠀⠀⠀⠀⢰⠱⣀⠀⡄⢐⠀⠀⢀⠀⠀⠀⡂⠄⠔⠁⠰⠀⠠⠀⣆⠀⠄⢠⢀⠄\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠠⠀⠀⠐⠀⠀⠀⠀⠀⠀⢀⠀⠀⠐⠀⠂⠀⠀⠀⠄⠀⠐⠀⢁⠄⠀⠀⠀⠀⠀\n⠀⢀⠀⠐⡈⠀⡀⠀⠂⠀⣀⠀⠑⡈⢀⠀⠀⠀⠀⠀⡀⡠⠀⡀⠰⠁⠈⠂⠁⠀⠠⠀⠀⠂⡂⠀⠂⠂⠀⠀\n⠠⠀⠐⠀⠂⠀⠀⢀⠀⠀⠀⠀⠊⠀⡐⠊⠐⠀⠀⠀⠀⠀⠐⠀⠂⠀⠀⠐⠀⠀⠀⠀⠀⠁⠃⠠⠀⠁⠐⠀\n⠀⠠⠀⡀⠄⠀⠀⠂⠀⠀⠀⠠⠀⠠⠀⠀⠄⠀⠨⠀⠀⠀⠐⠀⠀⠄⢀⠀⠀⠀⠈⠀⠀⠀⠁⠄⠀⠀⠀⠀\n⠀⢐⠐⠀⠄⠀⡂⠀⢐⠀⠀⠀⠀⠂⢀⢀⠐⠂⡀⠈⠀⠀⠀⠂⠀⠈⠀⡀⡐⠀⢄⠀⢀⠀⡆⠀⡀⣀⡀⡐\n⠀⠈⠀⠀⠀⠀⠀⠐⢂⠀⢀⠀⠈⠀⠀⠀⠀⠀⠠⠀⠀⠠⠀⠀⠀⠈⠂⠀⠀⠀⠄⠐⠐⠀⠁⠀⠀⠑⠁⠀\n⠂⠠⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠠⠈⠀⠀⠀⠀⠀⠁⠀⠀⠠⠐⠀⠁⠈⠀⠁⢀⠀⠀⠀⠀⠀⠀⠀⠀⠌⠀\n⠀⠀⠂⢨⠀⡀⠀⠐⠁⠐⠀⠐⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠢⠒⠈⠐⠐⠁⠂⠀⠀⠀⠄⠓⠕⠂⠃⠁⠀⠐\n⠠⠀⠨⠀⠁⠤⠄⠀⠁⡄⠀⠂⠠⠄⢈⠌⠠⠄⠀⢀⠀⠀⠀⠄⠨⠀⡤⠀⢀⠀⢀⠠⠀⠁⡔⠨⠀⠈⠄⠀\n⠀⢀⢀⣀⠀⡠⡒⢀⢀⣀⠀⢀⣀⡀⢀⠀⢀⠀⡀⠀⡀⠀⠈⣀⠀⢀⣀⠀⡀⠀⢀⠁⢀⣀⣀⡀⡠⡀⡀⣀\n⠀⠄⠀⠀⠀⠀⠀⠀⠀⠂⠁⠀⠀⠀⠀⠀⠀⣠⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀\n⢀⠂⠀⠀⠂⠀⠈⠀⠐⠀⠀⠀⠁⠀⠀⠀⡀⠔⠑⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠢⠀⠀⡀⠂⠈⠀⠀⠀⠄\n⠀⠐⠀⠀⡂⠀⠂⠀⠀⠀⠒⠐⠄⠂⠐⠀⠘⡀⠀⠠⡂⠃⠀⠂⠄⠂⠀⠀⠀⠀⡀⠀⡀⠀⡂⠂⠀⠀⢀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type SBMLModel\nsparse([41, 23, 51, 67, 61, 65, 1, 7, 19, 28 … 72, 3, 8, 33, 57, 66, 31, 45, 46, 57], [1, 2, 2, 2, 3, 3, 4, 4, 4, 4 … 93, 94, 94, 94, 94, 94, 95, 95, 95, 95], [-1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0 … 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
You can directly inspect the model objects, although only with a specific way | ||
for each specific type. | ||
%% Cell type:markdown id: tags: | ||
JSON models contain their corresponding JSON: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
json_model.json | ||
``` | ||
%% Output | ||
Dict{String, Any} with 6 entries:\n "metabolites" => Any[Dict{String, Any}("compartment"=>"e", "name"=>"D-Glucos…\n "id" => "e_coli_core"\n "compartments" => Dict{String, Any}("c"=>"cytosol", "e"=>"extracellular space…\n "reactions" => Any[Dict{String, Any}("name"=>"Phosphofructokinase", "metab…\n "version" => "1"\n "genes" => Any[Dict{String, Any}("name"=>"adhE", "id"=>"b1241", "notes… | ||
%% Cell type:markdown id: tags: | ||
SBML models contain a complicated structure from [`SBML.jl` | ||
package](https://github.com/LCSB-BioCore/SBML.jl): | ||
%% Cell type:code id: tags: | ||
``` julia | ||
typeof(sbml_model.sbml) | ||
``` | ||
%% Output | ||
SBML.Model | ||
%% Cell type:markdown id: tags: | ||
MAT models contain MATLAB data: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
mat_model.mat | ||
``` | ||
%% Output | ||
Dict{String, Any} with 17 entries:\n "description" => "e_coli_core"\n "c" => [0.0; 0.0; … ; 0.0; 0.0]\n "rev" => [0; 0; … ; 1; 0]\n "mets" => Any["glc__D_e"; "gln__L_c"; … ; "g3p_c"; "g6p_c"]\n "grRules" => Any["b3916 or b1723"; "((b0902 and b0903) and b2579) or (b09…\n "subSystems" => Any["Glycolysis/Gluconeogenesis"; "Pyruvate Metabolism"; … ;…\n "b" => [0.0; 0.0; … ; 0.0; 0.0]\n "metFormulas" => Any["C6H12O6"; "C5H10N2O3"; … ; "C3H5O6P"; "C6H11O9P"]\n "rxnGeneMat" => …\n "S" => [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0…\n "metNames" => Any["D-Glucose"; "L-Glutamine"; … ; "Glyceraldehyde 3-phosph…\n "lb" => [0.0; 0.0; … ; -1000.0; 0.0]\n "metCharge" => [0.0; 0.0; … ; -2.0; -2.0]\n "ub" => [1000.0; 1000.0; … ; 1000.0; 1000.0]\n "rxnNames" => Any["Phosphofructokinase"; "Pyruvate formate lyase"; … ; "O2…\n "rxns" => Any["PFK"; "PFL"; … ; "O2t"; "PDH"]\n "genes" => Any["b1241"; "b0351"; … ; "b2935"; "b3919"] | ||
Dict{String, Any} with 17 entries:\n "description" => "e_coli_core"\n "c" => [0.0; 0.0; … ; 0.0; 0.0;;]\n "rev" => [0; 0; … ; 1; 0;;]\n "mets" => Any["glc__D_e"; "gln__L_c"; … ; "g3p_c"; "g6p_c";;]\n "grRules" => Any["b3916 or b1723"; "((b0902 and b0903) and b2579) or (b09…\n "subSystems" => Any["Glycolysis/Gluconeogenesis"; "Pyruvate Metabolism"; … ;…\n "b" => [0.0; 0.0; … ; 0.0; 0.0;;]\n "metFormulas" => Any["C6H12O6"; "C5H10N2O3"; … ; "C3H5O6P"; "C6H11O9P";;]\n "rxnGeneMat" => sparse([6, 10, 6, 11, 27, 82, 93, 94, 12, 12 … 37, 38, 38,…\n "S" => [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0…\n "metNames" => Any["D-Glucose"; "L-Glutamine"; … ; "Glyceraldehyde 3-phosph…\n "lb" => [0.0; 0.0; … ; -1000.0; 0.0;;]\n "metCharge" => [0.0; 0.0; … ; -2.0; -2.0;;]\n "ub" => [1000.0; 1000.0; … ; 1000.0; 1000.0;;]\n "rxnNames" => Any["Phosphofructokinase"; "Pyruvate formate lyase"; … ; "O2…\n "rxns" => Any["PFK"; "PFL"; … ; "O2t"; "PDH";;]\n "genes" => Any["b1241"; "b0351"; … ; "b2935"; "b3919";;] | ||
%% Cell type:markdown id: tags: | ||
## Using the generic interface to access model details | ||
%% Cell type:markdown id: tags: | ||
To prevent the complexities of object representation, `COBREXA.jl` uses a set | ||
of generic interface functions that extract various important information | ||
from all supported model types. This approach ensures that the analysis | ||
functions can work on any data. | ||
%% Cell type:markdown id: tags: | ||
For example, you can check the reactions and metabolites contained in SBML | ||
and JSON models using the same accessor: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
reactions(json_model) | ||
``` | ||
%% Output | ||
95-element Vector{String}:\n "PFK"\n "PFL"\n "PGI"\n "PGK"\n "PGL"\n "ACALD"\n "AKGt2r"\n "PGM"\n "PIt2r"\n "ALCD2x"\n ⋮\n "MALt2_2"\n "MDH"\n "ME1"\n "ME2"\n "NADH16"\n "NADTRHD"\n "NH4t"\n "O2t"\n "PDH" | ||
%% Cell type:code id: tags: | ||
``` julia | ||
reactions(sbml_model) | ||
``` | ||
%% Output | ||
95-element Vector{String}:\n "R_EX_fum_e"\n "R_ACONTb"\n "R_TPI"\n "R_SUCOAS"\n "R_GLNS"\n "R_EX_pi_e"\n "R_PPC"\n "R_O2t"\n "R_G6PDH2r"\n "R_TALA"\n ⋮\n "R_THD2"\n "R_EX_h2o_e"\n "R_GLUSy"\n "R_ME1"\n "R_GLUN"\n "R_EX_o2_e"\n "R_FRUpts2"\n "R_ALCD2x"\n "R_PIt2r" | ||
%% Cell type:code id: tags: | ||
``` julia | ||
issetequal(reactions(json_model), reactions(mat_model)) # do models contain the same reactions? | ||
``` | ||
%% Output | ||
true | ||
%% Cell type:markdown id: tags: | ||
All accessors are defined in a single file in COBREXA source code; you may | ||
therefore get a list of all accessors as follows: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using InteractiveUtils | ||
for method in filter( | ||
x -> endswith(string(x.file), "MetabolicModel.jl"), | ||
InteractiveUtils.methodswith(MetabolicModel, COBREXA), | ||
) | ||
println(method.name) | ||
end | ||
``` | ||
%% Output | ||
balance | ||
bounds | ||
coupling | ||
coupling_bounds | ||
gene_annotations | ||
gene_notes | ||
genes | ||
metabolite_annotations | ||
metabolite_charge | ||
metabolite_compartment | ||
metabolite_formula | ||
metabolite_notes | ||
metabolites | ||
n_coupling_constraints | ||
n_genes | ||
n_metabolites | ||
n_reactions | ||
objective | ||
precache! | ||
reaction_annotations | ||
reaction_gene_association | ||
reaction_notes | ||
reaction_stoichiometry | ||
reaction_subsystem | ||
reactions | ||
stoichiometry | ||
%% Cell type:markdown id: tags: | ||
## Converting between model types | ||
%% Cell type:markdown id: tags: | ||
It is possible to convert model types to-and-fro. To do this, use the | ||
`convert` function, which is overloaded from Julia's `Base`. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
m = convert(MATModel, json_model) | ||
``` | ||
%% Output | ||
Metabolic model of type MATModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type MATModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
`m` will now contain the MATLAB-style matrix representation of the model: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
Matrix(m.mat["S"]) | ||
``` | ||
%% Output | ||
72×95 Matrix{Float64}:\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 1.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 -4.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 -1.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0\n ⋮ ⋮ ⋱ ⋮ \n -1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 | ||
%% Cell type:markdown id: tags: | ||
The loading and conversion can be combined using a shortcut: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
m = load_model(MATModel, "e_coli_core.json") | ||
``` | ||
%% Output | ||
Metabolic model of type MATModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type MATModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
## Saving and exporting models | ||
%% Cell type:markdown id: tags: | ||
`COBREXA.jl` supports exporting the models in JSON and MAT format, using `save_model`. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
save_model(m, "converted_model.json") | ||
save_model(m, "converted_model.mat") | ||
``` | ||
%% Cell type:markdown id: tags: | ||
If you need a non-standard suffix, use the type-specific saving functions: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
save_json_model(m, "file.without.a.good.suffix") | ||
save_mat_model(m, "another.file.matlab") | ||
``` | ||
%% Cell type:markdown id: tags: | ||
If you are saving the models only for future processing in Julia environment, | ||
it is often wasteful to encode the models to external formats and decode them | ||
back. Instead, you can use the "native" Julia data format, accessible with | ||
package `Serialization`. | ||
This way, you can use `serialize` to save even the `StandardModel` | ||
that has no file format associated: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using Serialization | ||
sm = convert(StandardModel, m) | ||
open(f -> serialize(f, sm), "myModel.stdmodel", "w") | ||
``` | ||
%% Cell type:markdown id: tags: | ||
The models can then be loaded back using `deserialize`: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
sm2 = deserialize("myModel.stdmodel") | ||
issetequal(metabolites(sm), metabolites(sm2)) | ||
``` | ||
%% Output | ||
true | ||
%% Cell type:markdown id: tags: | ||
This form of loading operation is usually pretty quick: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
t = @elapsed deserialize("myModel.stdmodel") | ||
@info "Deserialization took $t seconds" | ||
``` | ||
%% Output | ||
┌ Info: Deserialization took 0.001999536 seconds | ||
└ @ Main.##258 string:2 | ||
┌ Info: Deserialization took 0.002294876 seconds | ||
└ @ Main.##275 string:2 | ||
%% Cell type:markdown id: tags: | ||
Notably, large and complicated models with thousands of reactions and | ||
annotations can take seconds to decode properly. Serialization allows you to | ||
almost completely remove this overhead, and scales well to tens of millions | ||
of reactions. | ||
%% Cell type:markdown id: tags: | ||
--- | ||
*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* |
This diff is collapsed.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
%% Cell type:markdown id: tags: | ||
# Finding balance and variability of constraint-based models | ||
%% Cell type:markdown id: tags: | ||
Here we will use `flux_balance_analysis`, `flux_variability_analysis`, | ||
`parsimonious_flux_balance_analysis`, and | ||
`minimize_metabolic_adjustment_analysis`, along with the modification functions of | ||
`COBREXA.jl`, to analyze a toy model of *E. coli*. | ||
%% Cell type:markdown id: tags: | ||
If it is not already present, download the model. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
!isfile("e_coli_core.xml") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.xml", "e_coli_core.xml") | ||
using COBREXA | ||
model = load_model("e_coli_core.xml") | ||
``` | ||
%% Output | ||
Metabolic model of type SBMLModel\n\n⠀⠈⢀⠀⡀⠀⠀⠀⠀⡠⠂⠀⠀⠀⠀⠈⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⢀⠐⡀⠀⠀⠀⠀⠄\n⠀⠐⠀⠀⠀⠀⠀⠀⡠⠂⠀⠀⠀⠀⢰⠱⣀⠀⡄⢐⠀⠀⢀⠀⠀⠀⡂⠄⠔⠁⠰⠀⠠⠀⣆⠀⠄⢠⢀⠄\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠠⠀⠀⠐⠀⠀⠀⠀⠀⠀⢀⠀⠀⠐⠀⠂⠀⠀⠀⠄⠀⠐⠀⢁⠄⠀⠀⠀⠀⠀\n⠀⢀⠀⠐⡈⠀⡀⠀⠂⠀⣀⠀⠑⡈⢀⠀⠀⠀⠀⠀⡀⡠⠀⡀⠰⠁⠈⠂⠁⠀⠠⠀⠀⠂⡂⠀⠂⠂⠀⠀\n⠠⠀⠐⠀⠂⠀⠀⢀⠀⠀⠀⠀⠊⠀⡐⠊⠐⠀⠀⠀⠀⠀⠐⠀⠂⠀⠀⠐⠀⠀⠀⠀⠀⠁⠃⠠⠀⠁⠐⠀\n⠀⠠⠀⡀⠄⠀⠀⠂⠀⠀⠀⠠⠀⠠⠀⠀⠄⠀⠨⠀⠀⠀⠐⠀⠀⠄⢀⠀⠀⠀⠈⠀⠀⠀⠁⠄⠀⠀⠀⠀\n⠀⢐⠐⠀⠄⠀⡂⠀⢐⠀⠀⠀⠀⠂⢀⢀⠐⠂⡀⠈⠀⠀⠀⠂⠀⠈⠀⡀⡐⠀⢄⠀⢀⠀⡆⠀⡀⣀⡀⡐\n⠀⠈⠀⠀⠀⠀⠀⠐⢂⠀⢀⠀⠈⠀⠀⠀⠀⠀⠠⠀⠀⠠⠀⠀⠀⠈⠂⠀⠀⠀⠄⠐⠐⠀⠁⠀⠀⠑⠁⠀\n⠂⠠⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠠⠈⠀⠀⠀⠀⠀⠁⠀⠀⠠⠐⠀⠁⠈⠀⠁⢀⠀⠀⠀⠀⠀⠀⠀⠀⠌⠀\n⠀⠀⠂⢨⠀⡀⠀⠐⠁⠐⠀⠐⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠢⠒⠈⠐⠐⠁⠂⠀⠀⠀⠄⠓⠕⠂⠃⠁⠀⠐\n⠠⠀⠨⠀⠁⠤⠄⠀⠁⡄⠀⠂⠠⠄⢈⠌⠠⠄⠀⢀⠀⠀⠀⠄⠨⠀⡤⠀⢀⠀⢀⠠⠀⠁⡔⠨⠀⠈⠄⠀\n⠀⢀⢀⣀⠀⡠⡒⢀⢀⣀⠀⢀⣀⡀⢀⠀⢀⠀⡀⠀⡀⠀⠈⣀⠀⢀⣀⠀⡀⠀⢀⠁⢀⣀⣀⡀⡠⡀⡀⣀\n⠀⠄⠀⠀⠀⠀⠀⠀⠀⠂⠁⠀⠀⠀⠀⠀⠀⣠⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀\n⢀⠂⠀⠀⠂⠀⠈⠀⠐⠀⠀⠀⠁⠀⠀⠀⡀⠔⠑⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠢⠀⠀⡀⠂⠈⠀⠀⠀⠄\n⠀⠐⠀⠀⡂⠀⠂⠀⠀⠀⠒⠐⠄⠂⠐⠀⠘⡀⠀⠠⡂⠃⠀⠂⠄⠂⠀⠀⠀⠀⡀⠀⡀⠀⡂⠂⠀⠀⢀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type SBMLModel\nsparse([41, 23, 51, 67, 61, 65, 1, 7, 19, 28 … 72, 3, 8, 33, 57, 66, 31, 45, 46, 57], [1, 2, 2, 2, 3, 3, 4, 4, 4, 4 … 93, 94, 94, 94, 94, 94, 95, 95, 95, 95], [-1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0 … 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
## Optimization solvers in `COBREXA` | ||
To actually perform any optimization based analysis we need to load an | ||
optimizer. Any [`JuMP.jl`-supported | ||
optimizers](https://jump.dev/JuMP.jl/stable/installation/#Supported-solvers) | ||
will work. Here, we will use [`Tulip.jl`](https://github.com/ds4dm/Tulip.jl) | ||
to optimize linear programs and | ||
[`OSQP.jl`](https://osqp.org/docs/get_started/julia.html) to optimize quadratic | ||
programs. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using Tulip, OSQP, GLPK | ||
``` | ||
%% Cell type:markdown id: tags: | ||
## Flux balance analysis (FBA) | ||
Most analysis functions come in several variants that produce different types | ||
of output. All of them usually require a model and `JuMP.jl`-compatible | ||
optimizer to work in the model. | ||
In the case of FBA, you may choose from these variants (here using the | ||
`Tulip` optimizer): | ||
%% Cell type:code id: tags: | ||
``` julia | ||
vec_soln = flux_balance_analysis_vec(model, Tulip.Optimizer) | ||
``` | ||
%% Output | ||
95-element Vector{Float64}:\n -0.0\n 6.00724956649032\n 7.477381918907127\n -5.064375360152338\n 0.2234617471432185\n -3.214895030387032\n 2.504309432010867\n 21.799492758475754\n 4.959985078874371\n 1.496983802869297\n ⋮\n 3.375438217960911e-7\n 29.175827202685298\n 9.054357964341115e-9\n 4.817965631705414e-8\n 9.959461594581987e-9\n -21.799492758475754\n -0.0\n -1.4340676616267298e-9\n 3.214895030387032 | ||
%% Cell type:code id: tags: | ||
``` julia | ||
dict_soln = flux_balance_analysis_dict(model, Tulip.Optimizer) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 95 entries:\n "R_EX_fum_e" => -0.0\n "R_ACONTb" => 6.00725\n "R_TPI" => 7.47738\n "R_SUCOAS" => -5.06438\n "R_GLNS" => 0.223462\n "R_EX_pi_e" => -3.2149\n "R_PPC" => 2.50431\n "R_O2t" => 21.7995\n "R_G6PDH2r" => 4.95999\n "R_TALA" => 1.49698\n "R_PPCK" => 5.88317e-8\n "R_EX_lac__D_e" => 2.39394e-9\n "R_PGL" => 4.95999\n "R_H2Ot" => -29.1758\n "R_GLNabc" => -0.0\n "R_EX_co2_e" => 22.8098\n "R_EX_gln__L_e" => -0.0\n "R_EX_nh4_e" => -4.76532\n "R_MALt2_2" => -0.0\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
## Extending FBA with modifications | ||
%% Cell type:markdown id: tags: | ||
Often it is desirable to add a slight modification to the problem before | ||
performing analysis, to see e.g. differences of the model behavior caused by | ||
the change introduced. | ||
`COBREXA.jl` supports several modifications by default, which include changing objective | ||
sense, optimizer attributes, flux constraints, optimization objective, reaction and gene | ||
knockouts, and others. These modifications are applied in the order they are specified. It | ||
is up to the user to ensure that the changes are sensible. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
dict_soln = flux_balance_analysis_dict( | ||
model, | ||
OSQP.Optimizer; | ||
modifications = [ # modifications are applied in order | ||
# this changes the objective to maximize the biomass production | ||
change_objective("R_BIOMASS_Ecoli_core_w_GAM"), | ||
# this fixes a specific rate of the glucose exchange | ||
change_constraint("R_EX_glc__D_e"; lb = -12, ub = -12), | ||
# this knocks out two genes, i.e. constrains their associated reactions to zero. | ||
knockout(["b0978", "b0734"]), ## the gene IDs are cytochrome oxidase (CYTBD) | ||
# ignore the optimizer specified above and change it to Tulip | ||
change_optimizer(Tulip.Optimizer), | ||
# set a custom attribute of the Tulip optimizer (see Tulip docs for more possibilities) | ||
change_optimizer_attribute("IPM_IterationsLimit", 110), | ||
# explicitly tell the optimizer to maximize the new objective | ||
change_sense(MAX_SENSE), | ||
], | ||
) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 95 entries:\n "R_EX_fum_e" => -0.0\n "R_ACONTb" => 7.03277\n "R_TPI" => 8.90908\n "R_SUCOAS" => -5.8921\n "R_GLNS" => 0.270339\n "R_EX_pi_e" => -3.88931\n "R_PPC" => 3.02966\n "R_O2t" => 25.7859\n "R_G6PDH2r" => 6.11782\n "R_TALA" => 1.85013\n "R_PPCK" => 5.26409e-10\n "R_EX_lac__D_e" => 4.37341e-12\n "R_PGL" => 6.11782\n "R_H2Ot" => -34.7096\n "R_GLNabc" => -0.0\n "R_EX_co2_e" => 27.0082\n "R_EX_gln__L_e" => -0.0\n "R_EX_nh4_e" => -5.76498\n "R_MALt2_2" => -0.0\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
This solution can be display using `flux_summary`. Note, this pretty printing only works | ||
on flux solutions that are represented as dictionaries. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
flux_summary(dict_soln) | ||
``` | ||
%% Output | ||
Biomass\n R_BIOMASS_Ecoli_core_w_GAM: 1.0573\nImport\n R_EX_o2_e: -25.7859\n R_EX_glc__D_e: -12.0\n R_EX_nh4_e: -5.765\n R_EX_pi_e: -3.8893\nExport\n R_EX_h_e: 21.2085\n R_EX_co2_e: 27.0082\n R_EX_h2o_e: 34.7096\n | ||
%% Cell type:markdown id: tags: | ||
## Flux variability analysis (FVA) | ||
%% Cell type:markdown id: tags: | ||
The default FVA in `flux_variability_analysis` returns maximized and | ||
minimized reaction fluxes in a matrix. Here we use the dictionary variant in | ||
flux_variability_analysis_dict, to show how to easily access specific fluxes | ||
from its results. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fva_mins, fva_maxs = flux_variability_analysis_dict( | ||
model, | ||
Tulip.Optimizer; | ||
bounds = objective_bounds(0.99), # the objective function is allowed to vary by ~1% from the FBA optimum | ||
modifications = [ | ||
change_optimizer_attribute("IPM_IterationsLimit", 500), | ||
change_constraint("R_EX_glc__D_e"; lb = -10, ub = -10), | ||
change_constraint("R_EX_o2_e"; lb = 0.0, ub = 0.0), | ||
], | ||
) | ||
``` | ||
%% Output | ||
(Dict("R_EX_fum_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975681246428646, "R_TPI" => 9.758987664410151, "R_SUCOAS" => -0.0032176953711697304, "R_GLNS" => 0.060200571606221165, "R_EX_pi_e" => -0.7710723486676665, "R_PPC" => 0.648511462789616, "R_O2t" => 4.7620907185810674e-17, "R_G6PDH2r" => 0.09755599563531388, "R_TALA" => -0.004979593188388901…), "R_ACONTb" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952399025047, "R_TPI" => 9.751315002264594, "R_SUCOAS" => -5.7476116849648756e-11, "R_GLNS" => 0.062181345572819555, "R_EX_pi_e" => -0.7708580440964182, "R_PPC" => 0.6578793157880826, "R_O2t" => 9.410658208197004e-15, "R_G6PDH2r" => 0.1207478223560313, "R_TALA" => 0.002761437630187624…), "R_TPI" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952434490422, "R_TPI" => 9.485804104911805, "R_SUCOAS" => -8.335641656995056e-11, "R_GLNS" => 0.053580994933664666, "R_EX_pi_e" => -0.7708580445468374, "R_PPC" => 0.6004759354089005, "R_O2t" => 5.507347171694764e-15, "R_G6PDH2r" => 0.9172805135279788, "R_TALA" => 0.2682723346211751…), "R_SUCOAS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2955704771566707, "R_TPI" => 9.791564276285534, "R_SUCOAS" => -0.06949095362639839, "R_GLNS" => 0.05358099381935753, "R_EX_pi_e" => -0.7708580432289044, "R_PPC" => 0.6699668853183516, "R_O2t" => 3.13394692633907e-15, "R_G6PDH2r" => 9.897941427456658e-10, "R_TALA" => -0.03748783611687239…), "R_GLNS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2406424227465452, "R_TPI" => 9.757081490883413, "R_SUCOAS" => -0.0034442967413112913, "R_GLNS" => 0.05358099373941643, "R_EX_pi_e" => -0.7708580432437482, "R_PPC" => 0.6515935275838877, "R_O2t" => 2.1426954824772113e-16, "R_G6PDH2r" => 0.10344835719616492, "R_TALA" => -0.0030050507146060132…), "R_EX_pi_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22836315673274257, "R_TPI" => 9.78945886346248, "R_SUCOAS" => -7.227000020845847e-11, "R_GLNS" => 0.05412221657627899, "R_EX_pi_e" => -0.7786444930367454, "R_PPC" => 0.6065413498231926, "R_O2t" => 4.51046301140303e-15, "R_G6PDH2r" => 1.4292033457498604e-9, "R_TALA" => -0.03786650122403871…), "R_PPC" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24854826185014645, "R_TPI" => 9.758144304106896, "R_SUCOAS" => -1.7527365950313536e-13, "R_GLNS" => 0.060711429288066124, "R_EX_pi_e" => -0.7708580432063145, "R_PPC" => 0.6004759313481499, "R_O2t" => 1.0676969754863362e-16, "R_G6PDH2r" => 0.10025991755604913, "R_TALA" => -0.004067863926160701…), "R_O2t" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2397547670699771, "R_TPI" => 9.758984098152247, "R_SUCOAS" => -0.003217059763568135, "R_GLNS" => 0.06020007476474629, "R_EX_pi_e" => -0.7710723341748742, "R_PPC" => 0.6485122957709831, "R_O2t" => 4.9009916436786396e-17, "R_G6PDH2r" => 0.09756670616534588, "R_TALA" => -0.004976022306907555…), "R_G6PDH2r" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2413098384035294, "R_TPI" => 9.791500043356482, "R_SUCOAS" => -0.003585425307283908, "R_GLNS" => 0.06121279515312429, "R_EX_pi_e" => -0.7710955971575917, "R_PPC" => 0.6545319804571721, "R_O2t" => 2.1562429801722262e-16, "R_G6PDH2r" => 9.283567622367387e-12, "R_TALA" => -0.03749938900160984…), "R_TALA" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22836318744798303, "R_TPI" => 9.789458867641589, "R_SUCOAS" => -8.182422356774574e-9, "R_GLNS" => 0.054122216635179424, "R_EX_pi_e" => -0.7786444672236877, "R_PPC" => 0.6065415024301886, "R_O2t" => 4.108918888876329e-14, "R_G6PDH2r" => 9.828550567579093e-9, "R_TALA" => -0.03786649716846829…)…), Dict("R_EX_fum_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975681246428646, "R_TPI" => 9.758987664410151, "R_SUCOAS" => -0.0032176953711697304, "R_GLNS" => 0.060200571606221165, "R_EX_pi_e" => -0.7710723486676665, "R_PPC" => 0.648511462789616, "R_O2t" => 4.7620907185810674e-17, "R_G6PDH2r" => 0.09755599563531388, "R_TALA" => -0.004979593188388901…), "R_ACONTb" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.29557047721986357, "R_TPI" => 9.791564276452807, "R_SUCOAS" => -0.06949095088677924, "R_GLNS" => 0.053580993802476364, "R_EX_pi_e" => -0.7708580432014581, "R_PPC" => 0.669966885055626, "R_O2t" => 5.4867723002985896e-15, "R_G6PDH2r" => 5.200538446278462e-10, "R_TALA" => -0.0374878362714213…), "R_TPI" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24177376951630916, "R_TPI" => 9.791564276596803, "R_SUCOAS" => -0.0037135796370060203, "R_GLNS" => 0.06144138338428863, "R_EX_pi_e" => -0.7708580432384102, "R_PPC" => 0.655928636691913, "R_O2t" => 3.503241648282044e-16, "R_G6PDH2r" => 6.012119002464294e-11, "R_TALA" => -0.0374878364263768…), "R_SUCOAS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23694450009958637, "R_TPI" => 9.7578541338508, "R_SUCOAS" => -4.213751498134161e-12, "R_GLNS" => 0.06046918564757093, "R_EX_pi_e" => -0.7710794677351324, "R_PPC" => 0.6491018708187021, "R_O2t" => 2.0203965226776368e-16, "R_G6PDH2r" => 0.10095081244472187, "R_TALA" => -0.0038483337948307357…), "R_GLNS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952365569617, "R_TPI" => 9.791564276059317, "R_SUCOAS" => -5.4673258263777484e-11, "R_GLNS" => 0.24468111476697532, "R_EX_pi_e" => -0.7708580432075716, "R_PPC" => 0.6004759321859329, "R_O2t" => 1.2604324269135335e-14, "R_G6PDH2r" => 1.6926999040525598e-9, "R_TALA" => -0.037487835880989515…), "R_EX_pi_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24017982085639003, "R_TPI" => 9.758339902976445, "R_SUCOAS" => -0.003337567801679041, "R_GLNS" => 0.06044010139704514, "R_EX_pi_e" => -0.7708580432135336, "R_PPC" => 0.6496831096146779, "R_O2t" => 4.733798443891441e-16, "R_G6PDH2r" => 0.09967312094148192, "R_TALA" => -0.004263462798038352…), "R_PPC" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952347654484, "R_TPI" => 9.791564276535054, "R_SUCOAS" => -1.2665682284481008e-11, "R_GLNS" => 0.05358099376103458, "R_EX_pi_e" => -0.7708580432220014, "R_PPC" => 0.9826761788036762, "R_O2t" => -7.451157181351547e-16, "R_G6PDH2r" => 2.4914584091711995e-10, "R_TALA" => -0.03748783636345861…), "R_O2t" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975885844590922, "R_TPI" => 9.758991247095977, "R_SUCOAS" => -0.0032183313066518893, "R_GLNS" => 0.060201087253185896, "R_EX_pi_e" => -0.7710723630386553, "R_PPC" => 0.6485106398373328, "R_O2t" => 4.6259878518155594e-17, "R_G6PDH2r" => 0.09754523592034138, "R_TALA" => -0.0049831804589255705…), "R_G6PDH2r" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952341995713, "R_TPI" => 9.485804077754599, "R_SUCOAS" => -7.70632409774389e-14, "R_GLNS" => 0.053580993733477245, "R_EX_pi_e" => -0.7708580431955058, "R_PPC" => 0.6004759313306891, "R_O2t" => 2.491455505240063e-17, "R_G6PDH2r" => 0.9172805966214608, "R_TALA" => 0.2682723624294833…), "R_TALA" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2260795234203813, "R_TPI" => 9.485804077764492, "R_SUCOAS" => -2.2070646706247915e-14, "R_GLNS" => 0.05358099373347766, "R_EX_pi_e" => -0.7708580431970373, "R_PPC" => 0.6004759313313932, "R_O2t" => 2.2011253936851523e-18, "R_G6PDH2r" => 0.9172805965899173, "R_TALA" => 0.2682723624188306…)…)) | ||
(Dict("R_EX_fum_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975681252388875, "R_TPI" => 9.758987670019215, "R_SUCOAS" => -0.003217695420622425, "R_GLNS" => 0.06020057742388561, "R_EX_pi_e" => -0.7710723486299674, "R_PPC" => 0.6485114654496659, "R_O2t" => 4.7636840466449975e-17, "R_G6PDH2r" => 0.09755597883871935, "R_TALA" => -0.004979598785419143…), "R_ACONTb" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952399024103, "R_TPI" => 9.751314994785577, "R_SUCOAS" => -5.747711214668542e-11, "R_GLNS" => 0.062181323693887736, "R_EX_pi_e" => -0.7708580440960587, "R_PPC" => 0.6578792778328494, "R_O2t" => 9.411084212042624e-15, "R_G6PDH2r" => 0.12074784479375521, "R_TALA" => 0.0027614451094113016…), "R_TPI" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2260795243453041, "R_TPI" => 9.485804104877825, "R_SUCOAS" => -8.319304757951892e-11, "R_GLNS" => 0.05358099493359015, "R_EX_pi_e" => -0.7708580445453711, "R_PPC" => 0.6004759354091982, "R_O2t" => 5.359934820339382e-15, "R_G6PDH2r" => 0.9172805136407763, "R_TALA" => 0.2682723346609655…), "R_SUCOAS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.29557047715224044, "R_TPI" => 9.791564276282955, "R_SUCOAS" => -0.06949095362117334, "R_GLNS" => 0.05358099381978238, "R_EX_pi_e" => -0.7708580432292014, "R_PPC" => 0.6699668853159306, "R_O2t" => 3.191211084827664e-15, "R_G6PDH2r" => 9.982382324749958e-10, "R_TALA" => -0.037487836114279326…), "R_GLNS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24064242596917626, "R_TPI" => 9.75708160792236, "R_SUCOAS" => -0.0034442975170188377, "R_GLNS" => 0.0535809937394168, "R_EX_pi_e" => -0.7708580432437464, "R_PPC" => 0.6515935674935543, "R_O2t" => 2.1424377258038788e-16, "R_G6PDH2r" => 0.10344800607932744, "R_TALA" => -0.003005167753552366…), "R_EX_pi_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22836315673272758, "R_TPI" => 9.789458863462334, "R_SUCOAS" => -7.227058044154967e-11, "R_GLNS" => 0.05412221657624835, "R_EX_pi_e" => -0.7786444930369882, "R_PPC" => 0.606541349823176, "R_O2t" => 4.510775788338821e-15, "R_G6PDH2r" => 1.429168215925255e-9, "R_TALA" => -0.03786650122407263…), "R_PPC" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2485481901699732, "R_TPI" => 9.758144252473867, "R_SUCOAS" => -1.75099877155713e-13, "R_GLNS" => 0.0607114201940413, "R_EX_pi_e" => -0.770858043206322, "R_PPC" => 0.6004759313481519, "R_O2t" => 1.0686845246346513e-16, "R_G6PDH2r" => 0.10026007245513789, "R_TALA" => -0.00406781229313153…), "R_O2t" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975476417384725, "R_TPI" => 9.758984092418991, "R_SUCOAS" => -0.0032170588900653063, "R_GLNS" => 0.06020006640693463, "R_EX_pi_e" => -0.771072334219399, "R_PPC" => 0.6485122872632033, "R_O2t" => 4.902121164864372e-17, "R_G6PDH2r" => 0.09756672332899578, "R_TALA" => -0.004976016587856012…), "R_G6PDH2r" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24130980459385273, "R_TPI" => 9.791500043279633, "R_SUCOAS" => -0.0035854151174607306, "R_GLNS" => 0.0612127234286182, "R_EX_pi_e" => -0.7710955974418061, "R_PPC" => 0.6545319530113679, "R_O2t" => 2.155552554181346e-16, "R_G6PDH2r" => 9.283759662954366e-12, "R_TALA" => -0.037499389015432455…), "R_TALA" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22836318744775283, "R_TPI" => 9.789458867641438, "R_SUCOAS" => -8.182361733333499e-9, "R_GLNS" => 0.05412221663518293, "R_EX_pi_e" => -0.7786444672239631, "R_PPC" => 0.6065415024286762, "R_O2t" => 4.108935134143224e-14, "R_G6PDH2r" => 9.828422042686805e-9, "R_TALA" => -0.03786649716850727…)…), Dict("R_EX_fum_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975681252388875, "R_TPI" => 9.758987670019215, "R_SUCOAS" => -0.003217695420622425, "R_GLNS" => 0.06020057742388561, "R_EX_pi_e" => -0.7710723486299674, "R_PPC" => 0.6485114654496659, "R_O2t" => 4.7636840466449975e-17, "R_G6PDH2r" => 0.09755597883871935, "R_TALA" => -0.004979598785419143…), "R_ACONTb" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.29557047721975777, "R_TPI" => 9.79156427645274, "R_SUCOAS" => -0.06949095088621661, "R_GLNS" => 0.0535809938024699, "R_EX_pi_e" => -0.7708580432015065, "R_PPC" => 0.669966885055497, "R_O2t" => 5.486413767863138e-15, "R_G6PDH2r" => 5.199963828733239e-10, "R_TALA" => -0.03748783627143602…), "R_TPI" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24177375362265355, "R_TPI" => 9.791564276596777, "R_SUCOAS" => -0.003713574820679652, "R_GLNS" => 0.061441374870044536, "R_EX_pi_e" => -0.7708580432384676, "R_PPC" => 0.6559286179163718, "R_O2t" => 3.505736433264738e-16, "R_G6PDH2r" => 6.015355388027829e-11, "R_TALA" => -0.037487836426367944…), "R_SUCOAS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23694450651847213, "R_TPI" => 9.757854115958603, "R_SUCOAS" => -4.214391845861122e-12, "R_GLNS" => 0.060469177452495845, "R_EX_pi_e" => -0.7710794678567561, "R_PPC" => 0.6491017899927606, "R_O2t" => 2.0205854785849238e-16, "R_G6PDH2r" => 0.10095086602264308, "R_TALA" => -0.0038483159414384595…), "R_GLNS" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952365568096, "R_TPI" => 9.791564276059372, "R_SUCOAS" => -5.4667871707558614e-11, "R_GLNS" => 0.2446811147673207, "R_EX_pi_e" => -0.7708580432075332, "R_PPC" => 0.6004759321858603, "R_O2t" => 1.2603107594234158e-14, "R_G6PDH2r" => 1.6925839005206303e-9, "R_TALA" => -0.037487835881007216…), "R_EX_pi_e" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.24017982501148905, "R_TPI" => 9.758339870110252, "R_SUCOAS" => -0.003337568935484476, "R_GLNS" => 0.06044007540384528, "R_EX_pi_e" => -0.7708580432135304, "R_PPC" => 0.6496831008287483, "R_O2t" => 4.734147830827286e-16, "R_G6PDH2r" => 0.09967321954006271, "R_TALA" => -0.004263429931844625…), "R_PPC" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2260795234766408, "R_TPI" => 9.791564276535304, "R_SUCOAS" => -1.2654557928695605e-11, "R_GLNS" => 0.05358099376104628, "R_EX_pi_e" => -0.7708580432217733, "R_PPC" => 0.9826761788053896, "R_O2t" => -7.447072296632647e-16, "R_G6PDH2r" => 2.491419059931445e-10, "R_TALA" => -0.03748783636349198…), "R_O2t" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.23975885956391524, "R_TPI" => 9.75899124531553, "R_SUCOAS" => -0.0032183316533536104, "R_GLNS" => 0.06020108774390654, "R_EX_pi_e" => -0.7710723630183868, "R_PPC" => 0.6485106412140964, "R_O2t" => 4.6256792172025116e-17, "R_G6PDH2r" => 0.09754524127813421, "R_TALA" => -0.004983178672009124…), "R_G6PDH2r" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.22607952341983936, "R_TPI" => 9.48580407775266, "R_SUCOAS" => -9.208178288767948e-14, "R_GLNS" => 0.05358099373346173, "R_EX_pi_e" => -0.7708580431951753, "R_PPC" => 0.6004759313305169, "R_O2t" => 2.4880501477390976e-17, "R_G6PDH2r" => 0.9172805966276716, "R_TALA" => 0.26827236243157754…), "R_TALA" => Dict("R_EX_fum_e" => -0.0, "R_ACONTb" => 0.2260795234198597, "R_TPI" => 9.485804077755438, "R_SUCOAS" => -3.829553161833575e-14, "R_GLNS" => 0.053580993733406364, "R_EX_pi_e" => -0.7708580431954954, "R_PPC" => 0.6004759313306914, "R_O2t" => 1.978575548982736e-18, "R_G6PDH2r" => 0.9172805966189224, "R_TALA" => 0.2682723624286374…)…)) | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fva_maxs["R_EX_ac_e"]["R_EX_ac_e"] # get the maximal acetate exchange flux | ||
``` | ||
%% Output | ||
8.518549434877563 | ||
8.518549434877523 | ||
%% Cell type:markdown id: tags: | ||
Another option is to display this information using `flux_variability_summary`. This | ||
pretty printing only works on flux variability analysis results where dictionary keys indicate | ||
which flux is optimized and the associated value is a flux dictionary. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
flux_variability_summary((fva_mins, fva_maxs)) | ||
``` | ||
%% Output | ||
Biomass Lower bound Upper bound\n R_BIOMASS_Ecoli_core_w_GAM: 0.2095 0.2095\nExchange\n R_EX_h_e: 28.2555 30.7398\n R_EX_for_e: 16.2978 17.8266\n R_EX_glc__D_e: -10.0 -10.0\n R_EX_etoh_e: 8.0419 9.0611\n R_EX_ac_e: 7.4484 8.5185\n R_EX_h2o_e: -7.1446 -6.3802\n R_EX_nh4_e: -1.2063 -1.1426\n R_EX_co2_e: -0.5655 1.1544\n R_EX_pi_e: -0.7786 -0.7709\n R_EX_lac__D_e: 0.0 0.5096\n R_EX_acald_e: 0.0 0.3058\n R_EX_pyr_e: 0.0 0.2548\n R_EX_succ_e: 0.0 0.1911\n R_EX_akg_e: 0.0 0.0665\n R_EX_glu__L_e: 0.0 0.0637\n R_EX_fum_e: -0.0 -0.0\n R_EX_mal__L_e: -0.0 -0.0\n R_EX_gln__L_e: -0.0 -0.0\n R_EX_o2_e: 0.0 0.0\n R_EX_fru_e: -0.0 -0.0\n | ||
%% Cell type:markdown id: tags: | ||
More sophisticated variants of `flux_variability_analysis` can be used to extract | ||
specific pieces of information from the solved optimization problems. Here the objective | ||
value of the minimized flux and the associated biomass growth rate is returned instead | ||
of every flux. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
biomass_idx = first(indexin(["R_BIOMASS_Ecoli_core_w_GAM"], reactions(model))) # index of biomass function | ||
vs = flux_variability_analysis( | ||
model, | ||
Tulip.Optimizer; | ||
bounds = objective_bounds(0.50), # biomass can vary up to 50% less than optimum | ||
modifications = [ | ||
change_optimizer_attribute("IPM_IterationsLimit", 500), | ||
change_constraint("R_EX_glc__D_e"; lb = -10, ub = -10), | ||
change_constraint("R_EX_o2_e"; lb = 0.0, ub = 0.0), | ||
], | ||
ret = m -> | ||
(COBREXA.JuMP.objective_value(m), COBREXA.JuMP.value(m[:x][biomass_idx])), # m is the model and m[:x] extracts the fluxes from the model | ||
) | ||
``` | ||
%% Output | ||
95×2 Matrix{Tuple{Float64, Float64}}:\n (0.0, 0.112692) (-0.0, 0.112692)\n (0.114182, 0.105831) (3.4504, 0.105831)\n (7.25136, 0.105831) (9.89473, 0.105831)\n (-3.08393, 0.105831) (-1.29492e-11, 0.112787)\n (0.0270611, 0.105831) (9.58206, 0.105831)\n (-0.778644, 0.211663) (-0.389322, 0.105831)\n (0.303271, 0.105831) (10.7656, 0.105831)\n (-5.49068e-18, 0.112692) (-5.53641e-18, 0.112692)\n (4.67779e-13, 0.112782) (7.93011, 0.105831)\n (-0.0378665, 0.211663) (2.62444, 0.105831)\n ⋮ \n (3.0129e-11, 0.112701) (20.9246, 0.105831)\n (-8.5579, 0.105831) (5.65485, 0.105831)\n (3.50341e-11, 0.112866) (9.555, 0.105831)\n (1.5999e-11, 0.112882) (9.37857, 0.105831)\n (6.05059e-11, 0.112888) (9.555, 0.105831)\n (0.0, 0.112692) (-0.0, 0.112692)\n (0.0, 0.112692) (-0.0, 0.112692)\n (-18.3915, 0.105831) (-1.59455e-11, 0.107865)\n (0.389322, 0.105831) (0.778644, 0.211663) | ||
95×2 Matrix{Tuple{Float64, Float64}}:\n (0.0, 0.112692) (-0.0, 0.112692)\n (0.114182, 0.105831) (3.4504, 0.105831)\n (7.25136, 0.105831) (9.89473, 0.105831)\n (-3.08393, 0.105831) (-1.29494e-11, 0.112787)\n (0.0270611, 0.105831) (9.58206, 0.105831)\n (-0.778644, 0.211663) (-0.389322, 0.105831)\n (0.303271, 0.105831) (10.7656, 0.105831)\n (-5.4901e-18, 0.112692) (-5.53601e-18, 0.112692)\n (4.67779e-13, 0.112782) (7.93011, 0.105831)\n (-0.0378665, 0.211663) (2.62444, 0.105831)\n ⋮ \n (3.01295e-11, 0.112701) (20.9246, 0.105831)\n (-8.5579, 0.105831) (5.65485, 0.105831)\n (3.50341e-11, 0.112866) (9.555, 0.105831)\n (1.5999e-11, 0.112882) (9.37857, 0.105831)\n (6.05062e-11, 0.112888) (9.555, 0.105831)\n (0.0, 0.112692) (-0.0, 0.112692)\n (0.0, 0.112692) (-0.0, 0.112692)\n (-18.3915, 0.105831) (-1.59455e-11, 0.107865)\n (0.389322, 0.105831) (0.778644, 0.211663) | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fva_mins = Dict(rxn => flux for (rxn, flux) in zip(reactions(model), vs[:, 1])) | ||
``` | ||
%% Output | ||
Dict{String, Tuple{Float64, Float64}} with 95 entries:\n "R_EX_fum_e" => (0.0, 0.112692)\n "R_ACONTb" => (0.114182, 0.105831)\n "R_TPI" => (7.25136, 0.105831)\n "R_SUCOAS" => (-3.08393, 0.105831)\n "R_GLNS" => (0.0270611, 0.105831)\n "R_EX_pi_e" => (-0.778644, 0.211663)\n "R_PPC" => (0.303271, 0.105831)\n "R_O2t" => (-5.49068e-18, 0.112692)\n "R_G6PDH2r" => (4.67779e-13, 0.112782)\n "R_TALA" => (-0.0378665, 0.211663)\n "R_PPCK" => (1.41777e-11, 0.112871)\n "R_EX_lac__D_e" => (6.27487e-11, 0.11313)\n "R_PGL" => (4.67543e-13, 0.112782)\n "R_H2Ot" => (-5.65485, 0.105831)\n "R_GLNabc" => (0.0, 0.112692)\n "R_EX_co2_e" => (-9.38627, 0.105831)\n "R_EX_gln__L_e" => (0.0, 0.112692)\n "R_EX_nh4_e" => (-3.76208, 0.105831)\n "R_MALt2_2" => (0.0, 0.112692)\n ⋮ => ⋮ | ||
Dict{String, Tuple{Float64, Float64}} with 95 entries:\n "R_EX_fum_e" => (0.0, 0.112692)\n "R_ACONTb" => (0.114182, 0.105831)\n "R_TPI" => (7.25136, 0.105831)\n "R_SUCOAS" => (-3.08393, 0.105831)\n "R_GLNS" => (0.0270611, 0.105831)\n "R_EX_pi_e" => (-0.778644, 0.211663)\n "R_PPC" => (0.303271, 0.105831)\n "R_O2t" => (-5.4901e-18, 0.112692)\n "R_G6PDH2r" => (4.67779e-13, 0.112782)\n "R_TALA" => (-0.0378665, 0.211663)\n "R_PPCK" => (1.41777e-11, 0.112871)\n "R_EX_lac__D_e" => (6.27486e-11, 0.11313)\n "R_PGL" => (4.67543e-13, 0.112782)\n "R_H2Ot" => (-5.65485, 0.105831)\n "R_GLNabc" => (0.0, 0.112692)\n "R_EX_co2_e" => (-9.38627, 0.105831)\n "R_EX_gln__L_e" => (0.0, 0.112692)\n "R_EX_nh4_e" => (-3.76208, 0.105831)\n "R_MALt2_2" => (0.0, 0.112692)\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
## Parsimonious flux balance analysis (pFBA) | ||
%% Cell type:markdown id: tags: | ||
Parsimonious flux balance analysis (here in | ||
`parsimonious_flux_balance_analysis` finds a unique flux solution | ||
that minimizes the squared sum of fluxes of the system subject, while | ||
maintaining the same objective value as the flux balance analysis solution. | ||
Since we are optimizing a quadratic objective, we also need to switch to a | ||
quadratic optimizer. In this case, OSQP will work. We demonstrate it on the | ||
dictionary-returning variant of pFBA, | ||
`parsimonious_flux_balance_analysis_dict`: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
dict_soln = parsimonious_flux_balance_analysis_dict( | ||
model, | ||
OSQP.Optimizer; | ||
modifications = [ | ||
silence, # silence the optimizer (OSQP is very verbose by default) | ||
change_constraint("R_EX_glc__D_e"; lb = -12, ub = -12), | ||
change_optimizer_attribute("polish", true), | ||
], | ||
) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 95 entries:\n "R_EX_fum_e" => -0.0054306\n "R_ACONTb" => 6.51108\n "R_TPI" => 8.90211\n "R_SUCOAS" => -5.41568\n "R_GLNS" => 0.250914\n "R_EX_pi_e" => -3.85013\n "R_PPC" => 2.94799\n "R_O2t" => 25.1823\n "R_G6PDH2r" => 6.27109\n "R_TALA" => 1.90314\n "R_PPCK" => -0.00186526\n "R_EX_lac__D_e" => -0.00399055\n "R_PGL" => 6.27111\n "R_H2Ot" => -33.9472\n "R_GLNabc" => 0.0126618\n "R_EX_co2_e" => 26.4219\n "R_EX_gln__L_e" => -0.0126492\n "R_EX_nh4_e" => -5.67116\n "R_MALt2_2" => 0.00493596\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
The function also has the expectable second variant that returns a vector of | ||
solutions, in `parsimonious_flux_balance_analysis_vec`. Here, we | ||
utilize it to show how to use different optimizers for finding the optimum | ||
and for solving the quadratic problem. That may be preferable if the | ||
optimizer qualities differ for the differing tasks. pFBA allows you to | ||
specify `qp_modifications` that are applied after the original optimum is | ||
found, and before the quadratic part of the problem solving begins. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
vec_soln = parsimonious_flux_balance_analysis_vec( | ||
model, | ||
Tulip.Optimizer; # start with Tulip | ||
modifications = [ | ||
change_constraint("R_EX_glc__D_e"; lb = -12, ub = -12), | ||
change_optimizer_attribute("IPM_IterationsLimit", 500), # we may change Tulip-specific attributes here | ||
], | ||
qp_modifications = [ | ||
change_optimizer(OSQP.Optimizer), # now switch to OSQP (Tulip wouldn't be able to finish the computation) | ||
change_optimizer_attribute("polish", true), # get an accurate solution, see OSQP's documentation | ||
silence, # and make it quiet. | ||
], | ||
) | ||
``` | ||
%% Output | ||
95-element Vector{Float64}:\n -0.006231402533094581\n 6.847122967587614\n 8.914435875871503\n -5.738183656745528\n 0.25363156710733\n -3.8887743417980833\n 2.977310372502161\n 25.64208341306474\n 6.1991009754149715\n 1.877264043236841\n ⋮\n -0.0002197051126034427\n 34.49592944330335\n -0.0020752886988600542\n -0.0014018715428246171\n -0.002009900868927077\n -25.642083259145206\n 0.0161569956400718\n 0.004729690379188246\n 3.8887743479784547 | ||
%% Cell type:markdown id: tags: | ||
## Minimizing metabolic adjustment analysis (MOMA) | ||
%% Cell type:markdown id: tags: | ||
MOMA is a technique used to find a flux distribution that is closest to some reference | ||
distribution with respect to the Euclidian norm. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
reference_fluxes = parsimonious_flux_balance_analysis_dict( # reference distribution | ||
model, | ||
OSQP.Optimizer; | ||
modifications = [silence, change_optimizer_attribute("polish", true)], | ||
) | ||
moma = minimize_metabolic_adjustment_analysis_dict( | ||
model, | ||
reference_fluxes, | ||
OSQP.Optimizer; | ||
modifications = [ | ||
silence, | ||
change_optimizer_attribute("polish", true), | ||
change_constraint("R_CYTBD"; lb = 0.0, ub = 0.0), # find flux distribution closest to the CYTBD knockout | ||
], | ||
) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 95 entries:\n "R_EX_fum_e" => -0.000110206\n "R_ACONTb" => 1.02916\n "R_TPI" => 8.96839\n "R_SUCOAS" => -0.000880332\n "R_GLNS" => 0.0157708\n "R_EX_pi_e" => -0.228594\n "R_PPC" => 7.04745\n "R_O2t" => -0.000135095\n "R_G6PDH2r" => 0.532365\n "R_TALA" => 0.166338\n "R_PPCK" => -0.000128188\n "R_EX_lac__D_e" => 0.000160938\n "R_PGL" => 0.532365\n "R_H2Ot" => -5.77982\n "R_GLNabc" => 2.40923e-5\n "R_EX_co2_e" => 5.23659\n "R_EX_gln__L_e" => -2.40628e-5\n "R_EX_nh4_e" => -1.29924\n "R_MALt2_2" => 4.47106e-5\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
## Composing (more complicated) modifications | ||
%% Cell type:markdown id: tags: | ||
`COBREXA.jl` contains a number of modifications that allow the user to analyze | ||
non-standard variants of the classic FBA problem. These include thermodynamic | ||
(`add_loopless_constraints`), capacity (`add_crowding_constraints`), and | ||
kinetic/capacity (`add_moment_constraints`) modifications. The documentation of | ||
each modification details what their purpose is. Here, we will demonstrate how these | ||
modifications can be composed to generate even more interesting analyses. | ||
%% Cell type:markdown id: tags: | ||
Download the json formatted model so that the reaction identifiers correspond to the Escher map. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
!isfile("e_coli_core.json") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.json", "e_coli_core.json") | ||
model = load_model("e_coli_core.json") | ||
``` | ||
%% Output | ||
Metabolic model of type JSONModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type JSONModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
First find a flux distribution that is thermodyamically loopless and incorporates enzyme | ||
capacity constraints by composing loopless FBA and FBAwMC. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
rid_crowding_weight = Dict(# crowding needs a weight for each flux | ||
rid => 0.004 for rid in reactions(model) if | ||
!looks_like_biomass_reaction(rid) && !looks_like_exchange_reaction(rid) | ||
) | ||
loopless_crowding_fluxes = flux_balance_analysis_dict( | ||
model, | ||
GLPK.Optimizer; | ||
modifications = [ | ||
add_crowding_constraints(rid_crowding_weight), | ||
add_loopless_constraints(), | ||
], | ||
) | ||
flux_summary(loopless_crowding_fluxes) | ||
``` | ||
%% Output | ||
Biomass\n BIOMASS_Ecoli_core_w_GAM: 0.5131\nImport\n EX_o2_e: -11.0901\n EX_glc__D_e: -7.4944\n EX_nh4_e: -2.7976\n EX_pi_e: -1.8874\nExport\n EX_ac_e: 5.7251\n EX_co2_e: 11.6832\n EX_h2o_e: 15.4205\n EX_h_e: 16.017\n | ||
%% Cell type:markdown id: tags: | ||
Next find a flux distribution that satisfies kinetic/capacity constraints using the moment | ||
algorithm that is closest (using MOMA) to the loopless crowding solution. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
ksas = Dict(rid => 1000.0 for rid in reactions(model)) # make up specific activities of the enyzmes | ||
protein_mass_fraction = 0.56 | ||
moment_moma = minimize_metabolic_adjustment_analysis_dict( | ||
model, | ||
loopless_crowding_fluxes, | ||
OSQP.Optimizer; | ||
modifications = [ | ||
silence, | ||
change_optimizer_attribute("polish", true), | ||
change_optimizer_attribute("max-iter", 10_000), | ||
change_constraint("EX_glc__D_e", lb = -1000), | ||
change_constraint("CYTBD"; lb = 0, ub = 0), | ||
add_moment_constraints(ksas, protein_mass_fraction;), | ||
], | ||
) | ||
flux_summary(moment_moma) | ||
``` | ||
%% Output | ||
Biomass\n BIOMASS_Ecoli_core_w_GAM: 0.031\nImport\n EX_glc__D_e: -6.5805\n EX_nh4_e: -0.1544\n EX_pi_e: -0.1139\n EX_akg_e: -0.0065\n EX_glu__L_e: -0.0065\n EX_gln__L_e: -0.0039\n EX_lac__D_e: -0.0\n EX_for_e: -0.0\nExport\n EX_pyr_e: 0.0\n EX_fru_e: 0.0\n EX_fum_e: 0.0\n EX_mal__L_e: 0.0\n EX_acald_e: 1.1165\n EX_ac_e: 1.5923\n EX_co2_e: 2.8226\n EX_h2o_e: 3.351\n EX_etoh_e: 4.7745\n EX_succ_e: 5.1153\n EX_h_e: 12.4099\n | ||
%% Cell type:markdown id: tags: | ||
Finally, plot the results to inspect the flux distributions visually | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using CairoMakie, Escher, ColorSchemes | ||
!isfile("e_coli_core_map.json") && download( # download escher map | ||
"http://bigg.ucsd.edu/escher_map_json/e_coli_core.Core%20metabolism", | ||
"e_coli_core_map.json", | ||
) | ||
maxflux = maximum(abs.(values(moment_moma))) | ||
minflux = minimum(abs.(values(moment_moma))) | ||
color_interp(x) = begin # Scale color of reaction edges to fluxes (manually binned) | ||
normed_x = (abs(x) - minflux) / (maxflux - minflux) | ||
if 0 <= normed_x < 0.01 | ||
ColorSchemes.RdYlBu_4[4] | ||
elseif 0.01 <= normed_x < 0.25 | ||
ColorSchemes.RdYlBu_4[3] | ||
elseif 0.25 <= normed_x < 0.5 | ||
ColorSchemes.RdYlBu_4[2] | ||
else | ||
ColorSchemes.RdYlBu_4[1] | ||
end | ||
end | ||
rc = Dict(k => color_interp(v) for (k, v) in moment_moma) # map reaction id to reaction edge color | ||
fig = Figure(); | ||
ax = Axis(fig[1, 1]); | ||
escherplot!(ax, "e_coli_core_map.json", reaction_edge_colors = rc) | ||
hidexdecorations!(ax) | ||
hideydecorations!(ax) | ||
fig | ||
``` | ||
%% Output | ||
Figure() | ||
%% Cell type:markdown id: tags: | ||
--- | ||
*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* |
This diff is collapsed.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
%% Cell type:markdown id: tags: | ||
# Basic usage of `StandardModel` | ||
%% Cell type:markdown id: tags: | ||
In this tutorial we will use `COBREXA`'s `StandardModel` and functions that | ||
specifically operate on it. As usual we will use the toy model of *E. coli* | ||
for demonstration. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
!isfile("e_coli_core.json") && | ||
download("http://bigg.ucsd.edu/static/models/e_coli_core.json", "e_coli_core.json") | ||
using COBREXA | ||
``` | ||
%% Cell type:markdown id: tags: | ||
## Loading a model | ||
%% Cell type:code id: tags: | ||
``` julia | ||
model = load_model(StandardModel, "e_coli_core.json") # we specifically want to load a StandardModel from the model file | ||
``` | ||
%% Output | ||
Metabolic model of type StandardModel\n\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠈⠶⠴⡆⠀⠀⠀⠀⠀⠀\n⡀⢐⣀⢀⡀⡒⢒⣐⠀⣂⣂⠀⣂⣂⢂⠀⢀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⢂⠀⢂⣀⣐⡒⡀⠆⢙⣀⠀⡀⠀\n⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠈⢑⣀⣀⠀⠀\n⠀⠀⠃⠀⠃⠀⠀⠀⠘⠀⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⡜⠀⡄⣤⢠⠘⠙⢣⡇⠘\n⠀⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠐⠁⠉⠀⠀⠀⠀⠀⠘⠄\n⠀⢐⠀⠂⠀⠄⠠⠠⠀⠠⠆⠀⠄⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠠⠀⠠⠀⠀⢀⠀⠀⠠⠀⠀⠁\n⢀⠐⠀⠨⢀⠁⠈⣈⠀⢁⣁⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠁⢀⠀⢊⠉⠀⠀⠀⢀⠀⣀⠀⢀\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⡀⠆⠀⠆⠀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠆⠀\n⠀⠀⠂⠀⡂⠀⠀⠁⠀⠀⠀⠈⠁⠀⠀⠀⠄⠄⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀\n⠈⠀⠁⠀⠀⢀⡀⠀⠠⠁⠁⠀⠑⠀⠐⠲⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠂⠀⠀⠀⠀⠀⠀⠊⠀⠀⠀⠈\n⠄⠠⢠⠀⠰⠀⠠⠀⠤⠦⠄⠈⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠄⠄⠠⠀⠀⠀⠀⠀\n⠂⠐⠀⠀⠐⡠⢐⠘⢃⠒⠂⡀⠄⠀⠀⠐⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠒⠀⢀⢀⠀⠀⣀⠀⢀\n⠈⠀⠁⠀⡀⠀⠀⠀⠈⠁⠅⠀⠁⠀⢀⠈⠄⠔⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠈\n⠣⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠈⠀⠁⠁⠀⠈⡀⠀⠀⠀⠀⠀⠐⢣⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠂⠄⠤⠀⠀⠈⠂⠀⠀⠀⠀⠠⠀⠊⠒⣠⠀⠀⠀⠀⠀⠀⠀⠀⠀\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
Metabolic model of type StandardModel\nsparse([9, 51, 55, 64, 65, 34, 44, 59, 66, 64 … 20, 22, 23, 25, 16, 17, 34, 44, 57, 59], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 93, 93, 94, 94, 95, 95, 95, 95, 95, 95], [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0 … 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0], 72, 95)\nNumber of reactions: 95\nNumber of metabolites: 72\n | ||
%% Cell type:markdown id: tags: | ||
When using `load_model(StandardModel, file_location)` the model at | ||
`file_location` is first loaded into its inferred format and is then | ||
converted to a `StandardModel` using the generic accessor interface. | ||
Thus, data loss may occur. Always check your model to ensure that | ||
nothing important has been lost. | ||
%% Cell type:markdown id: tags: | ||
## Basic analysis | ||
%% Cell type:markdown id: tags: | ||
As before, for optimization based analysis we need to load an optimizer. Here we | ||
will use [`Tulip.jl`](https://github.com/ds4dm/Tulip.jl) to solve the linear | ||
programs of this tutorial. Refer to the basic constraint-based analysis | ||
tutorial for more informaiton. | ||
%% Cell type:markdown id: tags: | ||
All the normal analysis functions work on `StandardModel`, due to it also | ||
having the same generic accessor interface as all the other model types. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
using Tulip | ||
fluxes = flux_balance_analysis_dict( | ||
model, | ||
Tulip.Optimizer; | ||
modifications = [ | ||
change_objective("BIOMASS_Ecoli_core_w_GAM"), | ||
change_constraint("EX_glc__D_e"; lb = -12, ub = -12), | ||
change_constraint("EX_o2_e"; lb = 0, ub = 0), | ||
], | ||
) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 95 entries:\n "ACALD" => -9.78427\n "PTAr" => 10.0729\n "ALCD2x" => -9.78427\n "PDH" => 1.98381e-9\n "PYK" => 9.94501\n "CO2t" => 0.487021\n "EX_nh4_e" => -1.48633\n "MALt2_2" => -0.0\n "CS" => 0.294088\n "PGM" => -22.8676\n "TKT1" => -0.0487648\n "EX_mal__L_e" => -0.0\n "ACONTa" => 0.294088\n "EX_pi_e" => -1.00274\n "GLNS" => 0.069699\n "ICL" => 5.34932e-11\n "EX_o2_e" => -0.0\n "FBA" => 11.7289\n "EX_gln__L_e" => -0.0\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
This is not very exciting yet, since every other model type can also do this. | ||
However, deeper inspection of flux results is possible when using | ||
`StandardModel`. | ||
%% Cell type:markdown id: tags: | ||
## Inspecting the flux solution: `atom_fluxes` | ||
%% Cell type:markdown id: tags: | ||
It is sometimes interesting to keep track of the atoms entering and leaving | ||
the system through boundary reactions. This can be inspected by calling | ||
`atom_fluxes`. That gives you the flux of individual atoms getting | ||
consumed and produced by all reactions, based on `fluxes`. We erase the | ||
reaction that consumes the atoms for creating biomass, to see how much mass | ||
the "rest" of the reaction produces for it: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fluxes_without_biomass = copy(fluxes); | ||
delete!(fluxes_without_biomass, "BIOMASS_Ecoli_core_w_GAM"); | ||
atom_fluxes(model, fluxes_without_biomass) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 6 entries:\n "S" => 0.0\n "C" => 11.5998\n "N" => 1.48633\n "P" => 1.00274\n "H" => 20.7086\n "O" => 12.995 | ||
%% Cell type:markdown id: tags: | ||
## Inspecting the flux solution: `metabolite_fluxes` | ||
%% Cell type:markdown id: tags: | ||
Another useful flux result analysis function is `metabolite_fluxes`. | ||
This function gives an overview of reactions consuming and producing each | ||
metabolite. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
consuming, producing = metabolite_fluxes(model, fluxes) | ||
consuming["atp_c"] # reactions consuming `atp_c` | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 8 entries:\n "PFK" => -11.7289\n "BIOMASS_Ecoli_core_w_GAM" => -16.3031\n "GLNS" => -0.069699\n "ATPM" => -8.39\n "ADK1" => -1.66663e-10\n "PPCK" => -5.66231e-11\n "PPS" => -1.66662e-10\n "ATPS4r" => -6.80168 | ||
%% Cell type:markdown id: tags: | ||
## Internals of `StandardModel` | ||
%% Cell type:markdown id: tags: | ||
Another benefit of `StandardModel` is that it supports a richer internal | ||
infrastructure that can be used to manipulate internal model attributes in a | ||
systematic way. Specifically, the genes, reactions, and metabolites with of a | ||
model each have a type. This is particularly useful when modifying or even | ||
constructing a model from scratch. | ||
%% Cell type:markdown id: tags: | ||
## `Gene`s, `Reaction`s, and `Metabolite`s | ||
%% Cell type:markdown id: tags: | ||
`StandardModel` is composed of ordered dictionaries of `Gene`s, `Metabolite`s | ||
and `Reaction`s. Ordered dictionaries are used because the order of the | ||
reactions and metabolites are important for constructing a stoichiometric | ||
matrix since the rows and columns should correspond to the order of the metabolites | ||
and reactions returned by calling the accessors `metabolites` and `reactions`. | ||
%% Cell type:markdown id: tags: | ||
Each `StandardModel` is composed of the following fields: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fieldnames(StandardModel) # fields of a StandardModel | ||
``` | ||
%% Output | ||
(:id, :reactions, :metabolites, :genes) | ||
%% Cell type:markdown id: tags: | ||
The `:genes` field of a `StandardModel` contains an ordered dictionary of gene ids mapped to `Gene`s. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
model.genes # the keys of this dictionary are the same as genes(model) | ||
``` | ||
%% Output | ||
OrderedCollections.OrderedDict{String, Gene} with 137 entries:\n "b1241" => Gene("b1241", Dict("original_bigg_ids"=>["b1241"]), Dict("sbo"=>["…\n "b0351" => Gene("b0351", Dict("original_bigg_ids"=>["b0351"]), Dict("sbo"=>["…\n "s0001" => Gene("s0001", Dict("original_bigg_ids"=>["s0001"]), Dict("sbo"=>["…\n "b1849" => Gene("b1849", Dict("original_bigg_ids"=>["b1849"]), Dict("sbo"=>["…\n "b3115" => Gene("b3115", Dict("original_bigg_ids"=>["b3115"]), Dict("sbo"=>["…\n "b2296" => Gene("b2296", Dict("original_bigg_ids"=>["b2296"]), Dict("sbo"=>["…\n "b1276" => Gene("b1276", Dict("original_bigg_ids"=>["b1276"]), Dict("sbo"=>["…\n "b0118" => Gene("b0118", Dict("original_bigg_ids"=>["b0118"]), Dict("sbo"=>["…\n "b0474" => Gene("b0474", Dict("original_bigg_ids"=>["b0474"]), Dict("sbo"=>["…\n "b0116" => Gene("b0116", Dict("original_bigg_ids"=>["b0116"]), Dict("sbo"=>["…\n "b0727" => Gene("b0727", Dict("original_bigg_ids"=>["b0727"]), Dict("sbo"=>["…\n "b0726" => Gene("b0726", Dict("original_bigg_ids"=>["b0726"]), Dict("sbo"=>["…\n "b2587" => Gene("b2587", Dict("original_bigg_ids"=>["b2587"]), Dict("sbo"=>["…\n "b0356" => Gene("b0356", Dict("original_bigg_ids"=>["b0356"]), Dict("sbo"=>["…\n "b1478" => Gene("b1478", Dict("original_bigg_ids"=>["b1478"]), Dict("sbo"=>["…\n "b3734" => Gene("b3734", Dict("original_bigg_ids"=>["b3734"]), Dict("sbo"=>["…\n "b3733" => Gene("b3733", Dict("original_bigg_ids"=>["b3733"]), Dict("sbo"=>["…\n "b3736" => Gene("b3736", Dict("original_bigg_ids"=>["b3736"]), Dict("sbo"=>["…\n "b3737" => Gene("b3737", Dict("original_bigg_ids"=>["b3737"]), Dict("sbo"=>["…\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
The `Gene` type is a struct that can be used to store information about genes | ||
in a `StandardModel`. Each `Gene` is composed of the following fields: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
fieldnames(Gene) | ||
``` | ||
%% Output | ||
(:id, :notes, :annotations) | ||
%% Cell type:markdown id: tags: | ||
Use <tab> to quickly explore the fields of a struct. For example, | ||
Gene.<tab> will list all the fields shown above. | ||
%% Cell type:markdown id: tags: | ||
The keys used in the ordered dictionaries in | ||
`model.genes` are the ids returned using the generic accessor `genes`. `Gene`s | ||
have pretty printing, as demonstrated below for a random gene drawn from the | ||
model: | ||
%% Cell type:code id: tags: | ||
``` julia | ||
random_gene_id = genes(model)[rand(1:n_genes(model))] | ||
model.genes[random_gene_id] | ||
``` | ||
%% Output | ||
Gene.id: b1849\nGene.notes: \n original_bigg_ids: ["b1849"]\nGene.annotations: \n sbo: ["SBO:0000243"]\n uniprot: ["P33221"]\n ecogene: ["EG11809"]\n ncbigene: ["946368"]\n ncbigi: ["16129802"]\n refseq_locus_tag: ["b1849"]\n refseq_name: ["purT"]\n asap: ["ABE-0006162"]\n refseq_synonym: ["JW1838", "ECK1850"]\n | ||
Gene.id: b3870\nGene.notes: \n original_bigg_ids: ["b3870"]\nGene.annotations: \n sbo: ["SBO:0000243"]\n uniprot: ["P0A9C5"]\n ecogene: ["EG10383"]\n ncbigene: ["948370"]\n ncbigi: ["16131710"]\n refseq_locus_tag: ["b3870"]\n refseq_name: ["glnA"]\n asap: ["ABE-0012640"]\n refseq_synonym: ["ECK3863", "JW3841"]\n | ||
%% Cell type:markdown id: tags: | ||
The same idea holds for both metabolites (stored as `Metabolite`s) and | ||
reactions (stored as `Reaction`s). This is demonstrated below. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
random_metabolite_id = metabolites(model)[rand(1:n_metabolites(model))] | ||
model.metabolites[random_metabolite_id] | ||
``` | ||
%% Output | ||
Metabolite.id: q8_c\nMetabolite.formula: C49H74O4\nMetabolite.charge: 0\nMetabolite.compartment: c\nMetabolite.notes: \n original_bigg_ids: ["q8_c"]\nMetabolite.annotations: \n chebi: ["CHEBI:61683"]\n metanetx.chemical: ["MNXM232"]\n inchi_key: ICFIZJQGJAJRSU-SGHXU...\n kegg.compound: ["C17569"]\n sbo: ["SBO:0000247"]\n bigg.metabolite: ["q8"]\n biocyc: ["META:UBIQUINONE-8"]\n lipidmaps: ["LMPR02010005"]\n seed.compound: ["cpd15560"]\n | ||
Metabolite.id: pi_c\nMetabolite.formula: P1H1O4\nMetabolite.charge: -2\nMetabolite.compartment: c\nMetabolite.notes: \n original_bigg_ids: ["pi_c"]\nMetabolite.annotations: \n envipath: 650babc9-9d68-4b73-9...\n kegg.drug: ["D05467"]\n kegg.compound: ["C00009"]\n sbo: ["SBO:0000247"]\n sabiork: ["36"]\n biocyc: META:Pi, ..., META:PHOSPHATE-GROUP\n chebi: CHEBI:26078, ..., CHEBI:7793\n metanetx.chemical: ["MNXM9"]\n inchi_key: NBIIXXVUZAFLBC-UHFFF...\n hmdb: HMDB02105, ..., HMDB05947\n bigg.metabolite: ["pi"]\n seed.compound: ["cpd27787", "cpd00009"]\n reactome.compound: 5228339, ..., 113548\n | ||
%% Cell type:code id: tags: | ||
``` julia | ||
random_reaction_id = reactions(model)[rand(1:n_reactions(model))] | ||
model.reactions[random_reaction_id] | ||
``` | ||
%% Output | ||
Reaction.id: PTAr\nReaction.metabolites: 1.0 accoa_c + 1.0 pi_c ↔ 1.0 coa_c + 1.0 actp_c\nReaction.lb: -1000.0\nReaction.ub: 1000.0\nReaction.grr: (b2297) or (b2458)\nReaction.subsystem: Pyruvate Metabolism\nReaction.notes: \n original_bigg_ids: ["PTAr"]\nReaction.annotations: \n bigg.reaction: ["PTAr"]\n sabiork: ["72"]\n metanetx.reaction: ["MNXR103319"]\n rhea: 19521, ..., 19524\n sbo: ["SBO:0000176"]\n seed.reaction: ["rxn00173"]\n kegg.reaction: ["R00230"]\n biocyc: META:PHOSACETYLTRANS...\n ec-code: ["2.3.1.8"]\nReaction.objective_coefficient: 0.0\n | ||
Reaction.id: SUCOAS\nReaction.metabolites: 1.0 succ_c + 1.0 atp_c + 1.0 coa_c ↔ 1.0 adp_c + 1.0 succoa_c + 1.0 pi_c\nReaction.lb: -1000.0\nReaction.ub: 1000.0\nReaction.grr: (b0728 and b0729)\nReaction.subsystem: Citric Acid Cycle\nReaction.notes: \n original_bigg_ids: ["SUCOAS"]\nReaction.annotations: \n bigg.reaction: ["SUCOAS"]\n sabiork: ["260"]\n metanetx.reaction: ["MNXR104635"]\n rhea: 17664, ..., 17661\n sbo: ["SBO:0000176"]\n seed.reaction: ["rxn00285"]\n kegg.reaction: ["R00405"]\n biocyc: ["META:SUCCCOASYN-RXN"]\n reactome.reaction: R-BTA-70997, ..., R-MMU-70997\n ec-code: ["6.2.1.5"]\nReaction.objective_coefficient: 0.0\n | ||
%% Cell type:markdown id: tags: | ||
`StandardModel` can be used to build your own metabolic model or modify an | ||
existing one. One of the main use cases for `StandardModel` is that it can be | ||
used to merge multiple models or parts of multiple models together. Since the | ||
internals are uniform inside each `StandardModel`, attributes of other model | ||
types are squashed into the required format (using the generic accessors). | ||
This ensures that the internals of all `StandardModel`s are the same - | ||
allowing easy systematic evaluation. | ||
%% Cell type:markdown id: tags: | ||
## Checking the internals of `StandardModel`s: `annotation_index` | ||
%% Cell type:markdown id: tags: | ||
Often when models are automatically reconstructed duplicate genes, reactions | ||
or metabolites end up in a model. `COBREXA` exports `annotation_index` to | ||
check for cases where the id of a struct may be different, but the annotations | ||
the same (possibly suggesting a duplication). `annotation_index` builds a | ||
dictionary mapping annotation features to the ids of whatever struct you are | ||
inspecting. This makes it easy to find structs that share certain annotation features. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
rxn_annotations = annotation_index(model.reactions) | ||
``` | ||
%% Output | ||
Dict{String, Dict{String, Set{String}}} with 10 entries:\n "ec-code" => Dict("3.6.3.37"=>Set(["ATPM"]), "3.6.3.42"=>Set(["ATPM…\n "sabiork" => Dict("109"=>Set(["PGL"]), "762"=>Set(["GLUN"]), "155"=…\n "metanetx.reaction" => Dict("MNXR104869"=>Set(["TKT2"]), "MNXR99715"=>Set(["E…\n "rhea" => Dict("27626"=>Set(["TKT2"]), "10229"=>Set(["ACONTa"]),…\n "sbo" => Dict("SBO:0000627"=>Set(["EX_for_e", "EX_nh4_e", "EX_p…\n "seed.reaction" => Dict("rxn05297"=>Set(["GLUt2r"]), "rxn09717"=>Set(["PY…\n "kegg.reaction" => Dict("R00114"=>Set(["GLUSy"]), "R00199"=>Set(["PPS"]),…\n "biocyc" => Dict("META:TRANS-RXN-121B"=>Set(["FUMt2_2"]), "META:PE…\n "reactome.reaction" => Dict("R-TGU-71397"=>Set(["PDH"]), "R-XTR-70449"=>Set([…\n "bigg.reaction" => Dict("ACALD"=>Set(["ACALD"]), "PTAr"=>Set(["PTAr"]), "… | ||
%% Cell type:code id: tags: | ||
``` julia | ||
rxn_annotations["ec-code"] | ||
``` | ||
%% Output | ||
Dict{String, Set{String}} with 141 entries:\n "3.6.3.37" => Set(["ATPM"])\n "3.6.3.42" => Set(["ATPM"])\n "3.6.3.38" => Set(["ATPM"])\n "3.6.3.19" => Set(["ATPM"])\n "2.3.3.1" => Set(["CS"])\n "1.6.1.2" => Set(["NADTRHD"])\n "3.6.3.35" => Set(["ATPM"])\n "6.2.1.5" => Set(["SUCOAS"])\n "6.3.5.4" => Set(["GLUN"])\n "3.6.3.49" => Set(["ATPM"])\n "3.6.3.51" => Set(["ATPM"])\n "1.2.1.12" => Set(["GAPD"])\n "3.6.3.32" => Set(["ATPM"])\n "2.3.3.3" => Set(["CS"])\n "2.7.4.3" => Set(["ADK1"])\n "6.3.5.5" => Set(["GLUN"])\n "3.5.1.2" => Set(["GLUN"])\n "1.1.1.49" => Set(["G6PDH2r"])\n "5.3.1.9" => Set(["PGI"])\n ⋮ => ⋮ | ||
%% Cell type:markdown id: tags: | ||
The `annotation_index` function can also be used on `Reaction`s and | ||
`Gene`s in the same way. | ||
%% Cell type:markdown id: tags: | ||
## Checking the internals of `StandardModel`s: `check_duplicate_reaction` | ||
%% Cell type:markdown id: tags: | ||
Another useful function is `check_duplicate_reaction`, which checks for | ||
reactions that have duplicate (or similar) reaction equations. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
pgm_duplicate = Reaction() | ||
pgm_duplicate.id = "pgm2" # Phosphoglycerate mutase | ||
pgm_duplicate.metabolites = Dict{String,Float64}("3pg_c" => 1, "2pg_c" => -1) | ||
pgm_duplicate | ||
``` | ||
%% Output | ||
Reaction.id: pgm2\nReaction.metabolites: 1.0 2pg_c ↔ 1.0 3pg_c\nReaction.lb: -1000.0\nReaction.ub: 1000.0\nReaction.grr: ---\nReaction.subsystem: ---\nReaction.notes: ---\nReaction.annotations: ---\nReaction.objective_coefficient: 0.0\n | ||
%% Cell type:code id: tags: | ||
``` julia | ||
check_duplicate_reaction(pgm_duplicate, model.reactions; only_metabolites = false) # can also just check if only the metabolites are the same but different stoichiometry is used | ||
``` | ||
%% Output | ||
"PGM" | ||
%% Cell type:markdown id: tags: | ||
## Checking the internals of `StandardModel`s: `reaction_mass_balanced` | ||
%% Cell type:markdown id: tags: | ||
Finally, `reaction_mass_balanced` can be used to check if a reaction is mass | ||
balanced based on the formulas of the reaction equation. | ||
%% Cell type:code id: tags: | ||
``` julia | ||
rxn_dict = Dict{String,Float64}("3pg_c" => 1, "2pg_c" => -1, "h2o_c" => 1) | ||
reaction_mass_balanced(model, rxn_dict) | ||
``` | ||
%% Output | ||
false | ||
%% Cell type:markdown id: tags: | ||
Now to determine which atoms are unbalanced, you can use `reaction_atom_balance` | ||
%% Cell type:code id: tags: | ||
``` julia | ||
reaction_atom_balance(model, rxn_dict) | ||
``` | ||
%% Output | ||
Dict{String, Float64} with 4 entries:\n "C" => 0.0\n "P" => 0.0\n "H" => 2.0\n "O" => 1.0 | ||
%% Cell type:markdown id: tags: | ||
Note, since `pgm_duplicate` is not in the model, we cannot use the other variants of this | ||
function because they find the reaction equation stored inside the `model`. | ||
%% Cell type:markdown id: tags: | ||
--- | ||
*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* |