diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 98bae00d..65eeff05 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-11-22T09:46:34","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-11-27T14:53:03","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/distributed/1_functions/index.html b/dev/distributed/1_functions/index.html index e621cd81..81262133 100644 --- a/dev/distributed/1_functions/index.html +++ b/dev/distributed/1_functions/index.html @@ -1,2 +1,2 @@ -Parallel processing overview · COBREXA.jl

Parallel processing overview

Distributed processing in Julia is represented mainly by the package Distributed.jl.

COBREXA.jl is able to utilize this existing system to almost transparently run the large parallelizable analyses on multiple CPU cores and multiple computers connected through the network. Ultimately, the approach scales to thousands of computing nodes in large HPC facilities.

Users may run the analyses in parallel to gain speed-ups. The usual workflow in COBREXA.jl is quite straightforward:

  1. Import the Distributed package and add worker processes, e.g. using addprocs.
  2. Pick an analysis function that can be parallelized (such as screen or flux_variability_analysis) and prepare it to work on the data.
  3. Pass the desired set of worker IDs to the function using workers= argument, in the simplest form using e.g. screen(..., workers=workers()).
  4. Worker communication will be managed automatically, and the results will be computed "as usual", just appropriately faster.

Specific documentation is available about running parallel analysis locally and running distributed analysis in HPC clusters.

Functions that support parallelization

The functions that support parallel execution include:

Notably, the screening functions can be reused to run many other kinds of analyses which, in turn, inherit the parallelizability. This includes a wide range of use-cases that can thus be parallelized very easily:

  • single and multiple gene deletions (and other genetic modifications)
  • multiple reaction knockouts
  • envelope-like production profiles (e.g., enzyme-constrained growth profiles)
  • growth media explorations (such as explorations of metabolite depletion)

Mitigating parallel inefficiencies

Ideally, the speedup gained by parallel processing should be proportional to the amount of hardware one add as the workers. To reach that, it is beneficial to be aware of factors that reduce the parallel efficiency, which can be summarized as follows:

  • Parallelization within single runs of the linear solver is typically not supported (and if it is, it may be inefficient for common problem sizes). Normally, we want to parallelize the analyzes that comprise multiple independent runs of the solvers.
  • Some analysis function, such as flux_variability_analysis, have serial parts that can not be parallelized by default. Usually, pipelines may avoid the inefficiency by precomputing the serial analysis parts without involving the cluster of the workers.
  • Frequent worker communication may vastly reduce the efficiency of parallel processing; typically this happens if the time required for individual analysis steps is smaller than the network round-trip-time to the worker processes. Do not use parallelization for very small tasks.
  • Transferring large amounts of data among workers may hamper parallel efficiency too. Use a single loaded model data object and apply any required small modifications directly on the workers to avoid this kind of inefficiency.
Cost of the distribution and parallelization overhead

Before allocating extra resources into the distributed execution, always check that the tasks are properly parallelizable and sufficiently large to saturate the computation resources, so that the invested energy is not wasted. Amdahl's and Gustafson's laws give a better overview of the sources and consequences of the parallelization inefficiencies, and the costs of the resulting overhead.

+Parallel processing overview · COBREXA.jl

Parallel processing overview

Distributed processing in Julia is represented mainly by the package Distributed.jl.

COBREXA.jl is able to utilize this existing system to almost transparently run the large parallelizable analyses on multiple CPU cores and multiple computers connected through the network. Ultimately, the approach scales to thousands of computing nodes in large HPC facilities.

Users may run the analyses in parallel to gain speed-ups. The usual workflow in COBREXA.jl is quite straightforward:

  1. Import the Distributed package and add worker processes, e.g. using addprocs.
  2. Pick an analysis function that can be parallelized (such as screen or flux_variability_analysis) and prepare it to work on the data.
  3. Pass the desired set of worker IDs to the function using workers= argument, in the simplest form using e.g. screen(..., workers=workers()).
  4. Worker communication will be managed automatically, and the results will be computed "as usual", just appropriately faster.

Specific documentation is available about running parallel analysis locally and running distributed analysis in HPC clusters.

Functions that support parallelization

The functions that support parallel execution include:

Notably, the screening functions can be reused to run many other kinds of analyses which, in turn, inherit the parallelizability. This includes a wide range of use-cases that can thus be parallelized very easily:

  • single and multiple gene deletions (and other genetic modifications)
  • multiple reaction knockouts
  • envelope-like production profiles (e.g., enzyme-constrained growth profiles)
  • growth media explorations (such as explorations of metabolite depletion)

Mitigating parallel inefficiencies

Ideally, the speedup gained by parallel processing should be proportional to the amount of hardware one add as the workers. To reach that, it is beneficial to be aware of factors that reduce the parallel efficiency, which can be summarized as follows:

  • Parallelization within single runs of the linear solver is typically not supported (and if it is, it may be inefficient for common problem sizes). Normally, we want to parallelize the analyzes that comprise multiple independent runs of the solvers.
  • Some analysis function, such as flux_variability_analysis, have serial parts that can not be parallelized by default. Usually, pipelines may avoid the inefficiency by precomputing the serial analysis parts without involving the cluster of the workers.
  • Frequent worker communication may vastly reduce the efficiency of parallel processing; typically this happens if the time required for individual analysis steps is smaller than the network round-trip-time to the worker processes. Do not use parallelization for very small tasks.
  • Transferring large amounts of data among workers may hamper parallel efficiency too. Use a single loaded model data object and apply any required small modifications directly on the workers to avoid this kind of inefficiency.
Cost of the distribution and parallelization overhead

Before allocating extra resources into the distributed execution, always check that the tasks are properly parallelizable and sufficiently large to saturate the computation resources, so that the invested energy is not wasted. Amdahl's and Gustafson's laws give a better overview of the sources and consequences of the parallelization inefficiencies, and the costs of the resulting overhead.

diff --git a/dev/distributed/2_parallel/index.html b/dev/distributed/2_parallel/index.html index 68141148..2ed3f365 100644 --- a/dev/distributed/2_parallel/index.html +++ b/dev/distributed/2_parallel/index.html @@ -5,4 +5,4 @@ model, optimizer = HiGHS.Optimizer, workers = workers() -) +) diff --git a/dev/distributed/3_slurm/index.html b/dev/distributed/3_slurm/index.html index 3b6e9ade..b2538037 100644 --- a/dev/distributed/3_slurm/index.html +++ b/dev/distributed/3_slurm/index.html @@ -17,4 +17,4 @@ module load lang/Julia # add Julia to the environment (this may differ on different clusters and installations!) -julia myJob.jl

To run the computation, run sbatch myJob.sbatch on the cluster access node. The job will be scheduled and eventually executed. It is possible to watch the output of commands sacct and squeue in the meantime, to see the progress.

Remember that it is necessary to explicitly save the result of the Julia script computation to files, to be able to retrieve them later. Standard outputs of the jobs are often mangled and/or discarded. If we would still want to collect the standard output of the Julia script, we might need to change the last line of the batch script as follows:

julia myJob.jl > myJob.log

...and collect the output from myJob.log later. This is convenient especially if the script prints out various computation details using @info and similar macros.

+julia myJob.jl

To run the computation, run sbatch myJob.sbatch on the cluster access node. The job will be scheduled and eventually executed. It is possible to watch the output of commands sacct and squeue in the meantime, to see the progress.

Remember that it is necessary to explicitly save the result of the Julia script computation to files, to be able to retrieve them later. Standard outputs of the jobs are often mangled and/or discarded. If we would still want to collect the standard output of the Julia script, we might need to change the last line of the batch script as follows:

julia myJob.jl > myJob.log

...and collect the output from myJob.log later. This is convenient especially if the script prints out various computation details using @info and similar macros.

diff --git a/dev/distributed/index.html b/dev/distributed/index.html index 3a6b4380..4b7c380c 100644 --- a/dev/distributed/index.html +++ b/dev/distributed/index.html @@ -1,2 +1,2 @@ -Contents · COBREXA.jl
+Contents · COBREXA.jl
diff --git a/dev/examples/01-loading-and-saving/index.html b/dev/examples/01-loading-and-saving/index.html index 563eeeca..8dbb5a97 100644 --- a/dev/examples/01-loading-and-saving/index.html +++ b/dev/examples/01-loading-and-saving/index.html @@ -54,4 +54,4 @@ end |> String, "...")
7JL5Model|)&i!@=OZAbstractFBCModelsCanonicalModelD5DictND!Reaction...

The above code has saved the CanonicalModel in the way specified by the CanonicalModel structure – which is, in this case, a binary dump of the Julia objects, instead of the expected JSON. To prevent this, you can either specify the output type yourself:

save_model(model_in_julia_structures, "e_coli_saved_right.json", JSONFBCModel)

...or use save_converted_model to guess the model type automatically from the extension:

save_converted_model(model_in_julia_structures, "e_coli_saved_automatically_right.json")
 println(open("e_coli_saved_automatically_right.json") do f
     read(f, 100)
-end |> String, "...")
{"metabolites":[{"compartment":"c","name":"3-Phospho-D-glyceroyl phosphate","formula":"C3H4O10P2","i...

As with load_model, there is some overhead and uncertainty associated with save_converted_model guessing the model type from extension. For that reason, it is adviseable to rely on the guessing functionality only in interactive use in REPL, and avoid it in automated scriptage altogether.


This page was generated using Literate.jl.

+end |> String, "...")
{"metabolites":[{"compartment":"c","name":"3-Phospho-D-glyceroyl phosphate","formula":"C3H4O10P2","i...

As with load_model, there is some overhead and uncertainty associated with save_converted_model guessing the model type from extension. For that reason, it is adviseable to rely on the guessing functionality only in interactive use in REPL, and avoid it in automated scriptage altogether.


This page was generated using Literate.jl.

diff --git a/dev/examples/02a-flux-balance-analysis/index.html b/dev/examples/02a-flux-balance-analysis/index.html index 658057d2..3e68d995 100644 --- a/dev/examples/02a-flux-balance-analysis/index.html +++ b/dev/examples/02a-flux-balance-analysis/index.html @@ -32,4 +32,4 @@ :THD2 => 0.0 :TKT1 => 1.496983757261565 :TKT2 => 1.1814980932459616 - :TPI => 7.477381962160285

This page was generated using Literate.jl.

+ :TPI => 7.477381962160285

This page was generated using Literate.jl.

diff --git a/dev/examples/02b-optimizer-parameters.ipynb b/dev/examples/02b-optimizer-parameters.ipynb index eafb2cff..596ef1f3 100644 --- a/dev/examples/02b-optimizer-parameters.ipynb +++ b/dev/examples/02b-optimizer-parameters.ipynb @@ -162,7 +162,7 @@ " System : Augmented system (K2)\n", "\n", " Itn PObj DObj PFeas DFeas GFeas Mu Time\n", - " 0 -0.0000000e+00 +1.7686535e+05 1.16e+04 8.59e-02 1.77e+05 1.0e+00 0.87\n", + " 0 -0.0000000e+00 +1.7686535e+05 1.16e+04 8.59e-02 1.77e+05 1.0e+00 0.88\n", "Solver exited with status Trm_TimeLimit\n" ] } diff --git a/dev/examples/02b-optimizer-parameters/index.html b/dev/examples/02b-optimizer-parameters/index.html index 3025eced..41adca94 100644 --- a/dev/examples/02b-optimizer-parameters/index.html +++ b/dev/examples/02b-optimizer-parameters/index.html @@ -59,4 +59,4 @@ 0 -0.0000000e+00 +1.7686535e+05 1.16e+04 8.59e-02 1.77e+05 1.0e+00 0.00 1 -5.3305641e-02 +1.7675067e+05 7.98e+03 5.26e-02 1.21e+05 6.9e-01 0.00 2 -8.5532053e-02 +1.7615681e+05 2.06e+03 1.69e-02 3.13e+04 1.8e-01 0.00 -Solver exited with status Trm_IterationLimit

Applicable optimizer attributes are documented in the documentations of the respective optimizers. To browse the possibilities, one might want to see the JuMP documentation page that summarizes the references to the available optimizers.

Default solver settings can be examined and changed via Configuration.


This page was generated using Literate.jl.

+Solver exited with status Trm_IterationLimit

Applicable optimizer attributes are documented in the documentations of the respective optimizers. To browse the possibilities, one might want to see the JuMP documentation page that summarizes the references to the available optimizers.

Default solver settings can be examined and changed via Configuration.


This page was generated using Literate.jl.

diff --git a/dev/examples/02c-model-modifications/index.html b/dev/examples/02c-model-modifications/index.html index 3645acd2..a6e1d501 100644 --- a/dev/examples/02c-model-modifications/index.html +++ b/dev/examples/02c-model-modifications/index.html @@ -157,4 +157,4 @@ )

The values of any coupling constraints can be inspected directly in the solved model:

solution_with_coupling = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)
 
-solution_with_coupling.coupling.total_energy_intake
5.0

This page was generated using Literate.jl.

+solution_with_coupling.coupling.total_energy_intake
5.0

This page was generated using Literate.jl.

diff --git a/dev/examples/02d-constraint-modifications/index.html b/dev/examples/02d-constraint-modifications/index.html index 7f1b7f8a..b888adf8 100644 --- a/dev/examples/02d-constraint-modifications/index.html +++ b/dev/examples/02d-constraint-modifications/index.html @@ -73,4 +73,4 @@ solution = optimized_values(ct, objective = ct.objective.value, optimizer = HiGHS.Optimizer) -print(solution)
nothing

Several functions exist to simplify the construction of more complicated constraints. See the reference documentation for generic constraint builders for details.


This page was generated using Literate.jl.

+print(solution)
nothing

Several functions exist to simplify the construction of more complicated constraints. See the reference documentation for generic constraint builders for details.


This page was generated using Literate.jl.

diff --git a/dev/examples/03a-flux-variability-analysis/index.html b/dev/examples/03a-flux-variability-analysis/index.html index 6092f92f..37976fd7 100644 --- a/dev/examples/03a-flux-variability-analysis/index.html +++ b/dev/examples/03a-flux-variability-analysis/index.html @@ -77,4 +77,4 @@ :D_LACt2 => (-0.214512, 0.0) :ENO => (13.4361, 16.1819) :ETOHt2r => (-0.221432, 0.0) - ⋮ => ⋮
Speed up FVA with parallel processing

By default, FVA is parallelized on all workers that are available in the worker pool of the Distributed package, which may speed up the computation considerably. See the parallel processing documentation for more details.


This page was generated using Literate.jl.

+ ⋮ => ⋮
Speed up FVA with parallel processing

By default, FVA is parallelized on all workers that are available in the worker pool of the Distributed package, which may speed up the computation considerably. See the parallel processing documentation for more details.


This page was generated using Literate.jl.

diff --git a/dev/examples/03b-parsimonious-flux-balance/index.html b/dev/examples/03b-parsimonious-flux-balance/index.html index 6c5b82b3..ca66a0e7 100644 --- a/dev/examples/03b-parsimonious-flux-balance/index.html +++ b/dev/examples/03b-parsimonious-flux-balance/index.html @@ -72,4 +72,4 @@ :D_LACt2 => 0.0 :ENO => 14.7161 :ETOHt2r => 0.0 - ⋮ => ⋮

This page was generated using Literate.jl.

+ ⋮ => ⋮

This page was generated using Literate.jl.

diff --git a/dev/examples/03c-envelopes/index.html b/dev/examples/03c-envelopes/index.html index 3336a358..97b28c09 100644 --- a/dev/examples/03c-envelopes/index.html +++ b/dev/examples/03c-envelopes/index.html @@ -15,4 +15,4 @@ ["EX_o2_e", "EX_co2_e"]; breaks = 5, optimizer = HiGHS.Optimizer, -)
(breaks = Pair{String, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}["EX_o2_e" => -60.0:15.0:0.0, "EX_co2_e" => -11.104242424242429:17.776060606060632:60.0000000000001], objective_values = Union{Nothing, Float64}[nothing nothing … nothing 1.4356622286820861e-15; nothing nothing … 0.2724440832478481 nothing; … ; nothing 0.6046187247413645 … nothing nothing; 0.0 0.2019262880721721 … nothing nothing])

Documentation of the function describes ways to set custom bounds for the examined reaction flux ranges and several other customizations.


This page was generated using Literate.jl.

+)
(breaks = Pair{String, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}["EX_o2_e" => -60.0:15.0:0.0, "EX_co2_e" => -11.104242424242429:17.776060606060632:60.0000000000001], objective_values = Union{Nothing, Float64}[nothing nothing … nothing 1.4356622286820861e-15; nothing nothing … 0.2724440832478481 nothing; … ; nothing 0.6046187247413645 … nothing nothing; 0.0 0.2019262880721721 … nothing nothing])

Documentation of the function describes ways to set custom bounds for the examined reaction flux ranges and several other customizations.


This page was generated using Literate.jl.

diff --git a/dev/examples/03d-unidirectional/index.html b/dev/examples/03d-unidirectional/index.html index 19a48729..e828a0cf 100644 --- a/dev/examples/03d-unidirectional/index.html +++ b/dev/examples/03d-unidirectional/index.html @@ -133,4 +133,4 @@ :D_LACt2 => 0.0 :ENO => 14.7161 :ETOHt2r => 0.0 - ⋮ => ⋮

This page was generated using Literate.jl.

+ ⋮ => ⋮

This page was generated using Literate.jl.

diff --git a/dev/examples/04-community-models/index.html b/dev/examples/04-community-models/index.html index f69d33c0..ff4320cc 100644 --- a/dev/examples/04-community-models/index.html +++ b/dev/examples/04-community-models/index.html @@ -153,4 +153,4 @@ objective = custom_community.community_biomass.value, output = custom_community.community_biomass, optimizer = HiGHS.Optimizer, -)
0.5237157737585176

This page was generated using Literate.jl.

+)
0.5237157737585176

This page was generated using Literate.jl.

diff --git a/dev/examples/05a-minimization-of-metabolic-adjustment/index.html b/dev/examples/05a-minimization-of-metabolic-adjustment/index.html index c34449d0..61421e36 100644 --- a/dev/examples/05a-minimization-of-metabolic-adjustment/index.html +++ b/dev/examples/05a-minimization-of-metabolic-adjustment/index.html @@ -135,4 +135,4 @@ :PGM => 2.184138541733045 :PGK => 2.2174214742776375 :FRD7 => 2.982501375979094 - :SUCDi => 4.073918836637732

This page was generated using Literate.jl.

+ :SUCDi => 4.073918836637732

This page was generated using Literate.jl.

diff --git a/dev/examples/05b-enzyme-constrained-models/index.html b/dev/examples/05b-enzyme-constrained-models/index.html index 242cb364..8f996ac7 100644 --- a/dev/examples/05b-enzyme-constrained-models/index.html +++ b/dev/examples/05b-enzyme-constrained-models/index.html @@ -478,4 +478,4 @@ :b0728 => (-0.0, 0.00800682) :b0729 => (-0.0, 0.00800682) :b0733 => (-0.0, 0.0541366) - ⋮ => ⋮

This page was generated using Literate.jl.

+ ⋮ => ⋮

This page was generated using Literate.jl.

diff --git a/dev/examples/05c-mmdf/index.html b/dev/examples/05c-mmdf/index.html index e9cc8157..acc08ad3 100644 --- a/dev/examples/05c-mmdf/index.html +++ b/dev/examples/05c-mmdf/index.html @@ -115,4 +115,4 @@ :nadh_c => (-11.7753, -2.30259) :pep_c => (-13.8155, -3.12524) :pi_c => (-3.06118, -2.30259) - :pyr_c => (-13.8155, -2.30259)

This page was generated using Literate.jl.

+ :pyr_c => (-13.8155, -2.30259)

This page was generated using Literate.jl.

diff --git a/dev/examples/05d-loopless-models/index.html b/dev/examples/05d-loopless-models/index.html index cfc03e46..6677cc1a 100644 --- a/dev/examples/05d-loopless-models/index.html +++ b/dev/examples/05d-loopless-models/index.html @@ -15,4 +15,4 @@ :loopless_constraints => ConstraintTrees.Tree{Float64}(#= 5 elements =#) :loopless_directions => ConstraintTrees.Tree{Float64}(#= 75 elements =#) :loopless_driving_forces => ConstraintTrees.Tree{Float64}(#= 75 elements =#) - :objective => 0.873922

Loopless constraints can also be added to any model (e.g. enzyme constrained models). Refer to the source code of loopless_flux_balance_constraints for guidance.


This page was generated using Literate.jl.

+ :objective => 0.873922

Loopless constraints can also be added to any model (e.g. enzyme constrained models). Refer to the source code of loopless_flux_balance_constraints for guidance.


This page was generated using Literate.jl.

diff --git a/dev/examples/05e-knockouts/index.html b/dev/examples/05e-knockouts/index.html index 012a679e..eb7cbdb9 100644 --- a/dev/examples/05e-knockouts/index.html +++ b/dev/examples/05e-knockouts/index.html @@ -44,4 +44,4 @@ ("b1276", "b3919") => 0.7040369478590238 ("b4153", "b3919") => 0.7040369478590238 ("b2279", "b3919") => nothing - ("b0726", "b3919") => 0.7040369478590238

Now, how many genes are critical given b3919 is already missing?

critical_without_b3919 = count(isnothing, last.(knockouts_with_b3919))
23

This page was generated using Literate.jl.

+ ("b0726", "b3919") => 0.7040369478590238

Now, how many genes are critical given b3919 is already missing?

critical_without_b3919 = count(isnothing, last.(knockouts_with_b3919))
23

This page was generated using Literate.jl.

diff --git a/dev/examples/05f-cyclefree/index.html b/dev/examples/05f-cyclefree/index.html index 05c87fe7..f139b44e 100644 --- a/dev/examples/05f-cyclefree/index.html +++ b/dev/examples/05f-cyclefree/index.html @@ -167,4 +167,4 @@ -21.811205956007473 -21.813364572555663 -21.80963333194993 - -21.81300524702459

This page was generated using Literate.jl.

+ -21.81300524702459

This page was generated using Literate.jl.

diff --git a/dev/examples/05g-gapfilling/index.html b/dev/examples/05g-gapfilling/index.html index 9962757c..afbc301e 100644 --- a/dev/examples/05g-gapfilling/index.html +++ b/dev/examples/05g-gapfilling/index.html @@ -57,7 +57,7 @@ ) other_filled_reactions = [k for (k, v) in x2.fill_flags if v != 0]
1-element Vector{Symbol}:
- :PGI

Model debugging: which metabolite is missing?

Gap-filling is great for detecting various broken links and imbalances in metabolic models. We show how to find the metabolites are causing the imbalance for our "broken" E. coli model.

First, we construct a few completely unnatural reactions that create/remove the metabolites from/to nowhere:

magic_model = convert(CM.Model, model)
+ :PGI
Why is the gapfilling algorithm adding seemingly unneeded reactions?

By default, COBREXA does not do any "cleaning" on the universal model; all reactions that are present in that model will be potentially utilized in the new model, and all of them will need to respect their original bounds in the universal model. That becomes an issue with reactions that are bounded to non-zero flux (such as the ATPM reaction in the E. coli "core" model) – since their flux is required to be non-zero in any feasible model solution, they will also need to be in the fill set, because otherwise their flux would be zero.

As the simplest solution, all realistic uses of gapfilling should carefully check the set of universal reactions, and ideally exclude all exchanges and pseudoreactions.

Model debugging: which metabolite is missing?

Gap-filling is great for detecting various broken links and imbalances in metabolic models. We show how to find the metabolites are causing the imbalance for our "broken" E. coli model.

First, we construct a few completely unnatural reactions that create/remove the metabolites from/to nowhere:

magic_model = convert(CM.Model, model)
 empty!(magic_model.genes)
 empty!(magic_model.reactions)
 
@@ -70,4 +70,4 @@
 end

Gapfilling now points to the metabolites that need to be somehow taken care of by the modeller in order for the model to become feasible:

xm = gap_filling_analysis(infeasible_model, magic_model, 0.05, optimizer = HiGHS.Optimizer)
 
 blocking_metabolites = [k for (k, v) in xm.fill_flags if v != 0]
1-element Vector{Symbol}:
- :e4p_c

We can also have a look at how much of a given metabolite was used to make the model feasible again:

xm.universal_fluxes[first(blocking_metabolites)]
0.6866985638297876

This page was generated using Literate.jl.

+ :e4p_c

We can also have a look at how much of a given metabolite was used to make the model feasible again:

xm.universal_fluxes[first(blocking_metabolites)]
0.6866985638297876

This page was generated using Literate.jl.

diff --git a/dev/examples/06a-sampling.ipynb b/dev/examples/06a-sampling.ipynb index 77d0a8b5..6c7b6fdc 100644 --- a/dev/examples/06a-sampling.ipynb +++ b/dev/examples/06a-sampling.ipynb @@ -68,7 +68,7 @@ { "output_type": "execute_result", "data": { - "text/plain": "ConstraintTrees.Tree{Vector{Float64}} with 95 elements:\n :ACALD => [-0.0151235, -0.016959, -0.029273, -0.0132804, -…\n :ACALDt => [-0.00380377, -0.00328341, -0.00836245, -0.00306…\n :ACKr => [-0.0226167, -0.0246119, -0.0296686, -0.0220629,…\n :ACONTa => [6.09871, 6.12508, 6.21874, 5.89783, 6.14237, 5.…\n :ACONTb => [6.09871, 6.12508, 6.21874, 5.89783, 6.14237, 5.…\n :ACt2r => [-0.0226167, -0.0246119, -0.0296686, -0.0220629,…\n :ADK1 => [0.0387393, 0.0346144, 0.0094285, 0.0401418, 0.0…\n :AKGDH => [4.53272, 4.70363, 4.94867, 4.15118, 4.61469, 4.…\n :AKGt2r => [-0.00161543, -0.00253266, -0.00378415, -0.00238…\n :ALCD2x => [-0.0113197, -0.0136756, -0.0209106, -0.0102125,…\n :ATPM => [8.42732, 8.42983, 8.44163, 8.42365, 8.43029, 8.…\n :ATPS4r => [45.1228, 45.0502, 44.8095, 45.4555, 45.0738, 45…\n :BIOMASS_Ecoli_core_w_GAM => [0.865472, 0.865572, 0.865721, 0.865487, 0.86554…\n :CO2t => [-22.9322, -22.9129, -22.858, -22.9559, -22.9455…\n :CS => [6.09871, 6.12508, 6.21874, 5.89783, 6.14237, 5.…\n :CYTBD => [43.914, 43.8665, 43.7661, 43.9448, 43.9399, 43.…\n :D_LACt2 => [-0.0094216, -0.00990907, -0.0114174, -0.0076256…\n :ENO => [14.7834, 14.8156, 14.9268, 14.5789, 14.8152, 14…\n :ETOHt2r => [-0.0113197, -0.0136756, -0.0209106, -0.0102125,…\n ⋮ => ⋮" + "text/plain": "ConstraintTrees.Tree{Vector{Float64}} with 95 elements:\n :ACALD => [-0.0387419, -0.0161545, -0.0535667, -0.0121229,…\n :ACALDt => [-0.0299063, -0.00564386, -0.0441222, -0.0044472…\n :ACKr => [-0.0214974, -0.0199585, -0.0237342, -0.020044, …\n :ACONTa => [6.0618, 6.30764, 6.05175, 6.0711, 6.05899, 6.34…\n :ACONTb => [6.0618, 6.30764, 6.05175, 6.0711, 6.05899, 6.34…\n :ACt2r => [-0.0214974, -0.0199585, -0.0237342, -0.020044, …\n :ADK1 => [0.0283265, 0.0390212, 0.0239627, 0.032485, 0.03…\n :AKGDH => [4.55802, 5.10047, 4.62709, 4.46671, 4.30964, 5.…\n :AKGt2r => [-0.00129715, -0.00145558, -0.00125847, -0.00119…\n :ALCD2x => [-0.00883562, -0.0105107, -0.00944449, -0.007675…\n :ATPM => [8.4355, 8.45096, 8.42554, 8.44178, 8.42787, 8.4…\n :ATPS4r => [45.123, 44.8066, 45.0806, 45.1881, 45.2247, 44.…\n :BIOMASS_Ecoli_core_w_GAM => [0.865414, 0.865605, 0.865346, 0.86543, 0.865499…\n :CO2t => [-22.92, -22.8978, -22.9118, -22.9534, -22.9736,…\n :CS => [6.0618, 6.30764, 6.05175, 6.0711, 6.05899, 6.34…\n :CYTBD => [43.8551, 43.8539, 43.82, 43.9508, 43.9978, 43.8…\n :D_LACt2 => [-0.00702767, -0.0114787, -0.00625388, -0.008360…\n :ENO => [14.7642, 15.0001, 14.7646, 14.752, 14.7291, 15.…\n :ETOHt2r => [-0.00883562, -0.0105107, -0.00944449, -0.007675…\n ⋮ => ⋮" }, "metadata": {}, "execution_count": 2 @@ -101,7 +101,7 @@ { "output_type": "execute_result", "data": { - "text/plain": "380×2 Matrix{Float64}:\n 21.957 -22.9322\n 21.9333 -22.9129\n 21.883 -22.858\n 21.9724 -22.9559\n 21.97 -22.9455\n 21.9333 -22.944\n 21.879 -22.8562\n 21.9478 -22.9265\n 21.9761 -22.9475\n 21.9298 -22.9111\n ⋮ \n 21.9592 -22.9362\n 21.9415 -22.921\n 21.9395 -22.9146\n 21.8988 -22.8755\n 21.9457 -22.9191\n 21.9808 -22.9534\n 21.9259 -22.8916\n 21.9539 -22.9359\n 21.8757 -22.8378" + "text/plain": "380×2 Matrix{Float64}:\n 21.9275 -22.92\n 21.9269 -22.8978\n 21.91 -22.9118\n 21.9754 -22.9534\n 21.9989 -22.9736\n 21.9179 -22.8825\n 22.0023 -22.9811\n 22.0014 -22.9819\n 21.9887 -22.9675\n 21.9675 -22.9452\n ⋮ \n 21.9443 -22.9315\n 21.9616 -22.9458\n 21.8759 -22.848\n 21.9657 -22.9481\n 21.9628 -22.9474\n 21.9125 -22.9069\n 21.9693 -22.9526\n 21.9314 -22.9192\n 21.9744 -22.9473" }, "metadata": {}, "execution_count": 3 diff --git a/dev/examples/06a-sampling/index.html b/dev/examples/06a-sampling/index.html index 4b6347f4..037a905b 100644 --- a/dev/examples/06a-sampling/index.html +++ b/dev/examples/06a-sampling/index.html @@ -16,43 +16,43 @@ n_chains = 2, collect_iterations = [10], )
ConstraintTrees.Tree{Vector{Float64}} with 95 elements:
-  :ACALD                    => [-0.0184756, -0.019148, -0.0865059, -0.0147449, …
-  :ACALDt                   => [-0.00929189, -0.00653271, -0.080044, -0.0060144…
-  :ACKr                     => [-0.0151406, -0.0163737, -0.0126386, -0.0169413,…
-  :ACONTa                   => [6.07579, 6.02101, 6.02629, 6.10877, 6.10348, 6.…
-  :ACONTb                   => [6.07579, 6.02101, 6.02629, 6.10877, 6.10348, 6.…
-  :ACt2r                    => [-0.0151406, -0.0163737, -0.0126386, -0.0169413,…
-  :ADK1                     => [0.0265303, 0.0205372, 0.0205225, 0.0270841, 0.0…
-  :AKGDH                    => [4.56117, 4.33202, 4.6606, 4.60826, 4.56153, 4.6…
-  :AKGt2r                   => [-0.00230913, -0.00226784, -0.00153662, -0.00209…
-  :ALCD2x                   => [-0.00918374, -0.0126153, -0.00646192, -0.008730…
-  :ATPM                     => [8.4322, 8.43416, 8.41978, 8.43126, 8.43101, 8.4…
-  :ATPS4r                   => [45.1796, 45.2471, 45.1076, 45.1126, 45.1193, 45…
-  :BIOMASS_Ecoli_core_w_GAM => [0.865488, 0.865414, 0.865345, 0.865456, 0.86550…
-  :CO2t                     => [-22.9408, -22.9631, -22.8662, -22.9492, -22.936…
-  :CS                       => [6.07579, 6.02101, 6.02629, 6.10877, 6.10348, 6.…
-  :CYTBD                    => [43.9136, 43.9493, 43.6881, 43.939, 43.8962, 43.…
-  :D_LACt2                  => [-0.0112033, -0.00935899, -0.00557739, -0.010214…
-  :ENO                      => [14.7628, 14.706, 14.7652, 14.791, 14.7903, 14.8…
-  :ETOHt2r                  => [-0.00918374, -0.0126153, -0.00646192, -0.008730…
+  :ACALD                    => [-0.0179696, -0.0170179, -0.0128134, -0.012585, …
+  :ACALDt                   => [-0.00720956, -0.00418938, -0.000353247, -0.0044…
+  :ACKr                     => [-0.0203816, -0.0221806, -0.0219709, -0.0225474,…
+  :ACONTa                   => [6.07304, 6.11417, 6.07925, 6.11359, 6.1112, 5.8…
+  :ACONTb                   => [6.07304, 6.11417, 6.07925, 6.11359, 6.1112, 5.8…
+  :ACt2r                    => [-0.0203816, -0.0221806, -0.0219709, -0.0225474,…
+  :ADK1                     => [0.0351707, 0.0425964, 0.0426595, 0.0499103, 0.0…
+  :AKGDH                    => [4.51785, 4.6821, 4.58261, 4.59287, 4.69719, 4.0…
+  :AKGt2r                   => [-0.00237372, -0.00289809, -0.00288758, -0.00159…
+  :ALCD2x                   => [-0.01076, -0.0128285, -0.0124601, -0.0081509, -…
+  :ATPM                     => [8.42955, 8.43479, 8.43728, 8.42205, 8.42486, 8.…
+  :ATPS4r                   => [45.1901, 45.1285, 45.2069, 45.033, 45.1597, 45.…
+  :BIOMASS_Ecoli_core_w_GAM => [0.865413, 0.86544, 0.865436, 0.865396, 0.86545,…
+  :CO2t                     => [-22.9396, -22.921, -22.93, -22.9533, -22.9395, …
+  :CS                       => [6.07304, 6.11417, 6.07925, 6.11359, 6.1112, 5.8…
+  :CYTBD                    => [43.9317, 43.901, 43.9231, 43.9586, 43.9477, 43.…
+  :D_LACt2                  => [-0.0070682, -0.00664371, -0.00648625, -0.008265…
+  :ENO                      => [14.7551, 14.7989, 14.7593, 14.7935, 14.7831, 14…
+  :ETOHt2r                  => [-0.01076, -0.0128285, -0.0124601, -0.0081509, -…
   ⋮                         => ⋮

The result is a tree of vectors of sampled states for each value; the order of the values in these vectors is fixed. You can thus e.g. create a good matrix for plotting the sample as 2D scatterplot:

[s.O2t s.CO2t]
380×2 Matrix{Float64}:
- 21.9568  -22.9408
- 21.9746  -22.9631
- 21.8441  -22.8662
- 21.9695  -22.9492
- 21.9481  -22.9369
- 21.9551  -22.9376
- 21.9624  -22.9446
- 21.9121  -22.8881
- 21.9984  -22.9817
- 21.9173  -22.9012
+ 21.9659  -22.9396
+ 21.9505  -22.921
+ 21.9616  -22.93
+ 21.9793  -22.9533
+ 21.9738  -22.9395
+ 21.9927  -22.9784
+ 21.9694  -22.9401
+ 21.9514  -22.9208
+ 21.9506  -22.9194
+ 21.9044  -22.862
   ⋮       
- 21.8671  -22.8138
- 21.9522  -22.9247
- 21.9283  -22.8902
- 21.9817  -22.9416
- 21.9529  -22.9196
- 21.9353  -22.8964
- 21.9852  -22.963
- 21.9218  -22.869
- 21.9445  -22.9094

This page was generated using Literate.jl.

+ 22.0166 -22.9971 + 21.9926 -22.9702 + 21.9628 -22.9425 + 22.0679 -23.0544 + 21.9443 -22.9192 + 21.8875 -22.8532 + 22.0384 -23.0214 + 21.967 -22.9453 + 21.9831 -22.9663

This page was generated using Literate.jl.

diff --git a/dev/examples/06b-screening/index.html b/dev/examples/06b-screening/index.html index 306a8217..9a61448b 100644 --- a/dev/examples/06b-screening/index.html +++ b/dev/examples/06b-screening/index.html @@ -100,4 +100,4 @@ (:H2Ot, :EX_h2o_e, 1.0)=>0.454097 … (:H2Ot, :EX_nh4_e, 1.0)=>0.494176 (:CO2t, :EX_h2o_e, 1.0)=>0.454097 (:CO2t, :EX_nh4_e, 1.0)=>0.550176 (:O2t, :EX_h2o_e, 1.0)=>0.391648 (:O2t, :EX_nh4_e, 1.0)=>0.391648 - (:NH4t, :EX_h2o_e, 1.0)=>0.454097 (:NH4t, :EX_nh4_e, 1.0)=>0.550176

Notably, this approach makes various indexing and ordering errors quite improbable.


This page was generated using Literate.jl.

+ (:NH4t, :EX_h2o_e, 1.0)=>0.454097 (:NH4t, :EX_nh4_e, 1.0)=>0.550176

Notably, this approach makes various indexing and ordering errors quite improbable.


This page was generated using Literate.jl.

diff --git a/dev/examples/index.html b/dev/examples/index.html index 777e224f..cd8a3aac 100644 --- a/dev/examples/index.html +++ b/dev/examples/index.html @@ -1,2 +1,2 @@ -Contents · COBREXA.jl

Examples

+Contents · COBREXA.jl

Examples

diff --git a/dev/index.html b/dev/index.html index 9d01464d..edfe6a97 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · COBREXA.jl

COBREXA.jl

COBREXA.COBREXAModule
module COBREXA

COnstraint Based Reconstruction and EXascale Analysis. COBREXA provides functions for construction, modification, simulation and analysis of constraint-based metabolic models that follows the COBRA methodology.

COBREXA is built as a front-end for the combination of AbstractFBCModels.jl (provides the model I/O), ConstraintTrees.jl (provides the constraint system organization), Distributed.jl (provides HPC execution capability), and JuMP.jl (provides the solvers).

See the online documentation for a complete description of functionality aided by copy-pastable examples.

To start quickly, load your favorite JuMP-compatible solver, use load_model to read a metabolic model from the disk, and solve it with flux_balance_analysis.

source
+Home · COBREXA.jl

COBREXA.jl

COBREXA.COBREXAModule
module COBREXA

COnstraint Based Reconstruction and EXascale Analysis. COBREXA provides functions for construction, modification, simulation and analysis of constraint-based metabolic models that follows the COBRA methodology.

COBREXA is built as a front-end for the combination of AbstractFBCModels.jl (provides the model I/O), ConstraintTrees.jl (provides the constraint system organization), Distributed.jl (provides HPC execution capability), and JuMP.jl (provides the solvers).

See the online documentation for a complete description of functionality aided by copy-pastable examples.

To start quickly, load your favorite JuMP-compatible solver, use load_model to read a metabolic model from the disk, and solve it with flux_balance_analysis.

source
diff --git a/dev/reference/analysis/index.html b/dev/reference/analysis/index.html index 8b9824f7..371b212c 100644 --- a/dev/reference/analysis/index.html +++ b/dev/reference/analysis/index.html @@ -5,7 +5,7 @@ output, kwargs... ) -

Make an JuMP model out of constraints using optimization_model (most arguments are forwarded there), then apply the settings, optimize the model, and return either nothing if the optimization failed, or output substituted with the solved values (output defaults to constraints.

For a "nice" version for simpler finding of metabolic model optima, use flux_balance_analysis.

source

Parsimonious analyses

COBREXA.parsimonious_optimized_valuesMethod
parsimonious_optimized_values(
+

Make an JuMP model out of constraints using optimization_model (most arguments are forwarded there), then apply the settings, optimize the model, and return either nothing if the optimization failed, or output substituted with the solved values (output defaults to constraints.

For a "nice" version for simpler finding of metabolic model optima, use flux_balance_analysis.

source

Parsimonious analyses

COBREXA.parsimonious_optimized_valuesMethod
parsimonious_optimized_values(
     constraints::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};
     objective,
     objective_value,
@@ -18,8 +18,8 @@
     output,
     kwargs...
 )
-

Optimize the system of constraints to get the optimal objective value. Then try to find a "parsimonious" solution with the same objective value, which optimizes the parsimonious_objective (possibly also switching optimization sense, optimizer, and adding more settings).

For efficiency, everything is performed on a single instance of JuMP model.

A simpler version suitable for direct work with metabolic models is available in parsimonious_flux_balance_analysis.

source

Ensemble solving

COBREXA.screenMethod
screen(f, args...; workers) -> Any
-

Execute a function with arguments given by args on workers.

This is merely a nice shortcut for Distributed.pmap running over a Distributed.CachingPool of the given workers.

source
COBREXA.screen_optimization_modelMethod
screen_optimization_model(
+

Optimize the system of constraints to get the optimal objective value. Then try to find a "parsimonious" solution with the same objective value, which optimizes the parsimonious_objective (possibly also switching optimization sense, optimizer, and adding more settings).

For efficiency, everything is performed on a single instance of JuMP model.

A simpler version suitable for direct work with metabolic models is available in parsimonious_flux_balance_analysis.

source

Ensemble solving

COBREXA.screenMethod
screen(f, args...; workers) -> Any
+

Execute a function with arguments given by args on workers.

This is merely a nice shortcut for Distributed.pmap running over a Distributed.CachingPool of the given workers.

source
COBREXA.screen_optimization_modelMethod
screen_optimization_model(
     f,
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     args...;
@@ -29,19 +29,19 @@
     settings,
     workers
 )
-

Execute a function arguments from arrays args on workers, with a pre-cached JuMP optimization model created from constraints, objective and optimizer using optimization_model. settings are applied to the optimization model before first execution of f.

Since the model is cached and never re-created, this may be faster than just plain screen in many use cases.

The function f is supposed to take length(args)+1 arguments, the first argument is the JuMP model, and the other arguments are taken from args as with Distributed.pmap. While the model may be modified in place, one should take care to avoid modifications that change results of subsequent invocations of f, as that almost always results in data races and irreproducible executions. Ideally, all modifications of the model should be either manually reverted in the invocation of f, or the future invocations of f must be able to overwrite them.

f may use optimized_model to extract results easily w.r.t. some given ConstraintTree.

source
COBREXA.constraints_variabilityMethod
constraints_variability(
+

Execute a function arguments from arrays args on workers, with a pre-cached JuMP optimization model created from constraints, objective and optimizer using optimization_model. settings are applied to the optimization model before first execution of f.

Since the model is cached and never re-created, this may be faster than just plain screen in many use cases.

The function f is supposed to take length(args)+1 arguments, the first argument is the JuMP model, and the other arguments are taken from args as with Distributed.pmap. While the model may be modified in place, one should take care to avoid modifications that change results of subsequent invocations of f, as that almost always results in data races and irreproducible executions. Ideally, all modifications of the model should be either manually reverted in the invocation of f, or the future invocations of f must be able to overwrite them.

f may use optimized_model to extract results easily w.r.t. some given ConstraintTree.

source
COBREXA.constraints_variabilityMethod
constraints_variability(
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     targets::ConstraintTrees.Tree{ConstraintTrees.Constraint};
     kwargs...
 )
-

Simplified variant of constraints_variability that computes the variability of all values in tree targets, and returns a new tree of the same shape as targets that contains tuples for minima and maxima.

All other arguments are forwarded to the matrix-returning overload of constraints_variability.

source
COBREXA.constraints_variabilityMethod
constraints_variability(
+

Simplified variant of constraints_variability that computes the variability of all values in tree targets, and returns a new tree of the same shape as targets that contains tuples for minima and maxima.

All other arguments are forwarded to the matrix-returning overload of constraints_variability.

source
COBREXA.constraints_variabilityMethod
constraints_variability(
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     targets::Vector{<:ConstraintTrees.Value};
     output,
     output_type,
     kwargs...
 )
-

In a feasible space specified by constraints, compute the feasible range of individual targets values. The output is a matrix with one column for minima and second column for maxima of the individual target's values.

This is used e.g. to compute the flux_variability_analysis, and can be viewed as a more generalized version thereof.

output and output_type can be used to customize the information reported from the solved models.

Extra arguments are passed to screen_optimization_model.

source
COBREXA.constraints_objective_envelopeMethod
constraints_objective_envelope(
+

In a feasible space specified by constraints, compute the feasible range of individual targets values. The output is a matrix with one column for minima and second column for maxima of the individual target's values.

This is used e.g. to compute the flux_variability_analysis, and can be viewed as a more generalized version thereof.

output and output_type can be used to customize the information reported from the solved models.

Extra arguments are passed to screen_optimization_model.

source
COBREXA.constraints_objective_envelopeMethod
constraints_objective_envelope(
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     dims...;
     objective,
@@ -50,7 +50,7 @@
     settings,
     workers
 )
-

Optimize the system given by constraints and objective with optimizer (with custom settings) for all combination of constriants given by dims.

dims should be compatible with pairs that assign a sequence of breaks to a ConstraintTrees.Value: For example, organism.fluxes.PFK => 1:3 will compute optima of the model with the flux through PFK constrained to be equal to 1, 2 and 3.

In turn, all dims are converted to groups of equality constraints, and the model is solved for all combinations. Shape of the output matrix corresponds to Iterators.product(last.(dims)...).

Operation is parallelized by distribution over workers; by default all Distributed.workers() are used.

source

Sampling

COBREXA.sample_chain_achrMethod
sample_chain_achr(
+

Optimize the system given by constraints and objective with optimizer (with custom settings) for all combination of constriants given by dims.

dims should be compatible with pairs that assign a sequence of breaks to a ConstraintTrees.Value: For example, organism.fluxes.PFK => 1:3 will compute optima of the model with the flux through PFK constrained to be equal to 1, 2 and 3.

In turn, all dims are converted to groups of equality constraints, and the model is solved for all combinations. Shape of the output matrix corresponds to Iterators.product(last.(dims)...).

Operation is parallelized by distribution over workers; by default all Distributed.workers() are used.

source

Sampling

COBREXA.sample_chain_achrMethod
sample_chain_achr(
     sample_c::AbstractArray{F<:Real, 2};
     variable_lower_bounds,
     variable_upper_bounds,
@@ -61,7 +61,7 @@
     collect_iterations,
     generator
 )
-

Implementation of a single chain run for the Artificially-Centered Hit and Run algorithm (ACHR).

To use this on a model, use flux_sample or sample_constraints; most parameters are filled in correctly by these functions.

epsilon is defaulted from configuration.

source
COBREXA.sample_constraint_variablesMethod
sample_constraint_variables(
+

Implementation of a single chain run for the Artificially-Centered Hit and Run algorithm (ACHR).

To use this on a model, use flux_sample or sample_constraints; most parameters are filled in correctly by these functions.

epsilon is defaulted from configuration.

source
COBREXA.sample_constraint_variablesMethod
sample_constraint_variables(
     sampler::Function,
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};
     start_variables,
@@ -70,7 +70,7 @@
     n_chains,
     kwargs...
 )
-

Sample the feasible space constrained by constraints by sampling algorithm sampler, using the start_variables as a "warm-up" for the sampling runs. Random values are derived from the seed. Computation of individual n_chains chains by sampler is parallelized over workers using screen. Extra arguments are passed to sampler.

This function returns a matrix of the samples (one sample per row). To nicely aggregate the statistics in the constraint tree, use sample_constraints.

source
COBREXA.sample_constraintsMethod
sample_constraints(
+

Sample the feasible space constrained by constraints by sampling algorithm sampler, using the start_variables as a "warm-up" for the sampling runs. Random values are derived from the seed. Computation of individual n_chains chains by sampler is parallelized over workers using screen. Extra arguments are passed to sampler.

This function returns a matrix of the samples (one sample per row). To nicely aggregate the statistics in the constraint tree, use sample_constraints.

source
COBREXA.sample_constraintsMethod
sample_constraints(
     sampler::Function,
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};
     output,
@@ -78,7 +78,7 @@
     aggregate_type,
     kwargs...
 )
-

A front-end for sample_constraint_variables that saves the sampling results in a constraint tree of the same shape as output. Additionally, aggregate function and aggregate_type can be specified to customize the output.

All other parameters are forwarded to sample_constraint_variables.

source

Analysis front-end API helpers

COBREXA.frontend_optimized_valuesMethod
frontend_optimized_values(
+

A front-end for sample_constraint_variables that saves the sampling results in a constraint tree of the same shape as output. Additionally, aggregate function and aggregate_type can be specified to customize the output.

All other parameters are forwarded to sample_constraint_variables.

source

Analysis front-end API helpers

COBREXA.frontend_optimized_valuesMethod
frontend_optimized_values(
     builder,
     args...;
     builder_kwargs,
@@ -89,7 +89,7 @@
     settings,
     kwargs...
 )
-

A helper that converts a front-end constraint builder function (the output of which would normally be just passed through optimized_values) to front-end analysis function.

source
COBREXA.frontend_parsimonious_optimized_valuesMethod
frontend_parsimonious_optimized_values(
+

A helper that converts a front-end constraint builder function (the output of which would normally be just passed through optimized_values) to front-end analysis function.

source
COBREXA.frontend_parsimonious_optimized_valuesMethod
frontend_parsimonious_optimized_values(
     builder,
     args...;
     builder_kwargs,
@@ -106,4 +106,4 @@
     tolerances,
     kwargs...
 )
-

A helper that converts a parsimonious-style front-end constraint builder function to front-end analysis function.

Like frontend_optimized_values, but internally calls parsimonious_optimized_values.

source
+

A helper that converts a parsimonious-style front-end constraint builder function to front-end analysis function.

Like frontend_optimized_values, but internally calls parsimonious_optimized_values.

source diff --git a/dev/reference/builders/index.html b/dev/reference/builders/index.html index 720759ef..03fd1f2a 100644 --- a/dev/reference/builders/index.html +++ b/dev/reference/builders/index.html @@ -3,59 +3,59 @@ a, tree::ConstraintTrees.Tree{ConstraintTrees.Constraint} ) -> Any -

A constriant tree that makes sure that all values in tree are the same as the value of a.

Names in the output ConstraintTree match the names in the tree.

source
COBREXA.difference_constraintMethod
difference_constraint(
+

A constriant tree that makes sure that all values in tree are the same as the value of a.

Names in the output ConstraintTree match the names in the tree.

source
COBREXA.difference_constraintMethod
difference_constraint(
     a,
     b,
     difference_bound
 ) -> ConstraintTrees.Constraint
-

A constraint that makes sure that the difference from a to b is within the difference_bound. For example, difference_constraint(-1, 1, 2) will always be valid. Any type of ConstraintTree.Bound can be supplied.

source
COBREXA.equal_value_constraintMethod
equal_value_constraint(a, b) -> ConstraintTrees.Constraint
-

A constraint that makes sure that the values of a and b are the same.

source
COBREXA.greater_or_equal_constraintMethod
greater_or_equal_constraint(
+

A constraint that makes sure that the difference from a to b is within the difference_bound. For example, difference_constraint(-1, 1, 2) will always be valid. Any type of ConstraintTree.Bound can be supplied.

source
COBREXA.equal_value_constraintMethod
equal_value_constraint(a, b) -> ConstraintTrees.Constraint
+

A constraint that makes sure that the values of a and b are the same.

source
COBREXA.greater_or_equal_constraintMethod
greater_or_equal_constraint(
     a,
     b
 ) -> ConstraintTrees.Constraint
-

A constraint that makes sure that the value of a is greater than or equal to the the value of b.

source
COBREXA.less_or_equal_constraintMethod
less_or_equal_constraint(a, b) -> ConstraintTrees.Constraint
-

A constraint that makes sure that the value of a is less than or equal to the the value of b.

source

Constraint scaling

COBREXA.scale_boundsMethod
scale_bounds(
+

A constraint that makes sure that the value of a is greater than or equal to the the value of b.

source
COBREXA.less_or_equal_constraintMethod
less_or_equal_constraint(a, b) -> ConstraintTrees.Constraint
+

A constraint that makes sure that the value of a is less than or equal to the the value of b.

source

Constraint scaling

COBREXA.scale_boundsMethod
scale_bounds(
     tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     factor
 ) -> Any
-

Linearly scale all bounds in a constraint tree by the factor. This actually changes the model semantics, and may not work in surprising/improper ways with some constraint systems, esp. the MILP and QP ones.

See also scale_constraints.

source
COBREXA.scale_constraintsMethod
scale_constraints(
+

Linearly scale all bounds in a constraint tree by the factor. This actually changes the model semantics, and may not work in surprising/improper ways with some constraint systems, esp. the MILP and QP ones.

See also scale_constraints.

source
COBREXA.scale_constraintsMethod
scale_constraints(
     tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     factor
 ) -> Any
-

Linearly scale all constraints in a constraint tree by the factor.

See also scale_bounds.

source

Sign splitting

COBREXA.positive_bound_contributionMethod
positive_bound_contribution(
+

Linearly scale all constraints in a constraint tree by the factor.

See also scale_bounds.

source

Sign splitting

COBREXA.positive_bound_contributionMethod
positive_bound_contribution(
     b::ConstraintTrees.EqualTo
 ) -> ConstraintTrees.EqualTo
-

Clamp all negative values in the bound to zero, leaving only the "positive contribution" to the overall value of the constraint. Used in unsigned_positive_contribution_variables and unsigned_negative_contribution_variables to allocate unidirectional variables.

source
COBREXA.sign_split_constraintsMethod
sign_split_constraints(; positive, negative, signed)
-

A constraint tree that bound the values present in signed to be sums of pairs of positive and negative contributions to the individual values.

Keys in the result are the same as the keys of signed constraints.

Typically, this can be used to create "unidirectional" fluxes together with unsigned_negative_contribution_variables and unsigned_positive_contribution_variables.

Use sign_split_variables to allocate the variables easily.

source
COBREXA.sign_split_variablesMethod
sign_split_variables(
+

Clamp all negative values in the bound to zero, leaving only the "positive contribution" to the overall value of the constraint. Used in unsigned_positive_contribution_variables and unsigned_negative_contribution_variables to allocate unidirectional variables.

source
COBREXA.sign_split_constraintsMethod
sign_split_constraints(; positive, negative, signed)
+

A constraint tree that bound the values present in signed to be sums of pairs of positive and negative contributions to the individual values.

Keys in the result are the same as the keys of signed constraints.

Typically, this can be used to create "unidirectional" fluxes together with unsigned_negative_contribution_variables and unsigned_positive_contribution_variables.

Use sign_split_variables to allocate the variables easily.

source
COBREXA.sign_split_variablesMethod
sign_split_variables(
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};
     positive,
     negative
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Shortcut for making a pair of named variable groups created by unsigned_positive_contribution_variables and unsigned_negative_contribution_variables, in subtrees named by positive and negative.

Use sign_split_constraints to bind the new variables to existing values.

source
COBREXA.unsigned_negative_contribution_constraintsMethod
unsigned_negative_contribution_constraints(
+

Shortcut for making a pair of named variable groups created by unsigned_positive_contribution_variables and unsigned_negative_contribution_variables, in subtrees named by positive and negative.

Use sign_split_constraints to bind the new variables to existing values.

source
COBREXA.unsigned_negative_contribution_constraintsMethod
unsigned_negative_contribution_constraints(
     cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     positive::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

A constraint tree that connects positive unsigned variable contributions to signed ones, while acting as negative contributions.

source
COBREXA.unsigned_negative_contribution_variablesMethod
unsigned_negative_contribution_variables(
+

A constraint tree that connects positive unsigned variable contributions to signed ones, while acting as negative contributions.

source
COBREXA.unsigned_negative_contribution_variablesMethod
unsigned_negative_contribution_variables(
     cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

A constraint tree of variables with negative contributions to the values in cs.

source
COBREXA.unsigned_positive_contribution_constraintsMethod
unsigned_positive_contribution_constraints(
+

A constraint tree of variables with negative contributions to the values in cs.

source
COBREXA.unsigned_positive_contribution_constraintsMethod
unsigned_positive_contribution_constraints(
     cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     negative::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

A constraint tree that connects negative unsigned variable contributions to signed ones, while acting as positive contributions.

source
COBREXA.unsigned_positive_contribution_variablesMethod
unsigned_positive_contribution_variables(
+

A constraint tree that connects negative unsigned variable contributions to signed ones, while acting as positive contributions.

source
COBREXA.unsigned_positive_contribution_variablesMethod
unsigned_positive_contribution_variables(
     cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

A constraint tree of variables with positive contributions to the values in cs.

source

Objectives

COBREXA.squared_sum_error_valueMethod
squared_sum_error_value(
+

A constraint tree of variables with positive contributions to the values in cs.

source

Objectives

COBREXA.squared_sum_error_valueMethod
squared_sum_error_value(
     constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     target
 ) -> Any
-

Construct a ConstraintTrees.Value out of squared error (in the RMSE-like squared-error sense) between the values in the constraint tree and the reference target.

target is a function that takes a symbol (key) and returns either a Float64 reference value, or nothing if the error of given key should not be considered.

source
COBREXA.squared_sum_valueMethod
squared_sum_value(
+

Construct a ConstraintTrees.Value out of squared error (in the RMSE-like squared-error sense) between the values in the constraint tree and the reference target.

target is a function that takes a symbol (key) and returns either a Float64 reference value, or nothing if the error of given key should not be considered.

source
COBREXA.squared_sum_valueMethod
squared_sum_value(
     x::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

Construct a ConstraintTrees.Value out of squared sum of all values directly present in a given constraint tree.

source
COBREXA.sum_valueMethod
sum_value(
+

Construct a ConstraintTrees.Value out of squared sum of all values directly present in a given constraint tree.

source
COBREXA.sum_valueMethod
sum_value(
     x...
 ) -> Union{ConstraintTrees.LinearValue, ConstraintTrees.QuadraticValue}
-

Construct a ConstraintTrees.Value out of a sum of all values directly present in a given constraint tree.

source

Analysis-specific constriants

COBREXA.loopless_constraintsMethod
loopless_constraints(
+

Construct a ConstraintTrees.Value out of a sum of all values directly present in a given constraint tree.

source

Analysis-specific constriants

COBREXA.loopless_constraintsMethod
loopless_constraints(
 ;
     fluxes,
     loopless_direction_indicators,
@@ -66,11 +66,11 @@
     driving_force_nonzero_bound,
     driving_force_infinity_bound
 )
-

Construct the loopless constraint system that binds fluxes of all internal_reactions to direction of loopless_direction_indicators and connects them to loopless_driving_forces. The solution is bounded to lie in internal_nullspace (which is a sufficient algebraic condition for loop-less-ness).

The indicators must be discrete variables, valued 1 if the reaction flux goes forward, or 0 if the reaction flux is reversed.

The simplest (but by no means the fastest) way to obtain a good internal_nullspace is to use LinearAlgebra.nullspace with the internal reactions' stoichiometry matrix. Rows of internal_nullspace must correspond to internal_reactions.

flux_infinity_bound is used as the maximal bound for fluxes (for constraints that connect them to indicator variables); it should optimally be greater than the maximum possible absolute value of any flux in the original model.

driving_force_nonzero_bound and driving_force_infinity_bound are similarly used to limit the individual reaction's driving forces.

source
COBREXA.knockout_constraintsMethod
knockout_constraints(
+

Construct the loopless constraint system that binds fluxes of all internal_reactions to direction of loopless_direction_indicators and connects them to loopless_driving_forces. The solution is bounded to lie in internal_nullspace (which is a sufficient algebraic condition for loop-less-ness).

The indicators must be discrete variables, valued 1 if the reaction flux goes forward, or 0 if the reaction flux is reversed.

The simplest (but by no means the fastest) way to obtain a good internal_nullspace is to use LinearAlgebra.nullspace with the internal reactions' stoichiometry matrix. Rows of internal_nullspace must correspond to internal_reactions.

flux_infinity_bound is used as the maximal bound for fluxes (for constraints that connect them to indicator variables); it should optimally be greater than the maximum possible absolute value of any flux in the original model.

driving_force_nonzero_bound and driving_force_infinity_bound are similarly used to limit the individual reaction's driving forces.

source
COBREXA.knockout_constraintsMethod
knockout_constraints(
     knockout_test::Function,
     fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Make a ConstraintTree that knocks out fluxes given by the predicate knockout_test. The predicate function is called with a single parameter (the key of the flux in tree fluxes) and must return a boolean. Returning true means that the corresponding flux (usually a reaction flux) will be knocked out.

source
COBREXA.enzyme_constraintsMethod
enzyme_constraints(
+

Make a ConstraintTree that knocks out fluxes given by the predicate knockout_test. The predicate function is called with a single parameter (the key of the flux in tree fluxes) and must return a boolean. Returning true means that the corresponding flux (usually a reaction flux) will be knocked out.

source
COBREXA.enzyme_constraintsMethod
enzyme_constraints(
 ;
     fluxes_forward,
     fluxes_reverse,
@@ -86,7 +86,7 @@
     gene_product_amounts_name,
     gene_product_capacity_name
 )
-

Connect variables returned by enzyme_variables to unidirectional fluxes. This is used to construct the contraint system for enzyme_constrained_flux_balance_constraints.

Parameters fluxes_forward, fluxes_reverse, isozyme_forward_amounts, isozyme_reverse_amounts and gene_product_amounts should correspond to parameters and results of enzyme_variables.

Further, parameter functions kcat_forward and kcat_reverse specify the turnover numbers for reaction and isozyme IDs given in parameters; isozyme_gene_product_stoichiometry specifies the composition of the reaction-isozyme IDs given in parameter by returning an interable mapping of gene product IDs to numbers (such as Dict{Symbol, Float64}), and gene_product_molar_mass specifies a numeric mass for a given gene product ID. All parameter functions may return nothing, at which point the given object is considered nonexistent and is omitted from constraints.

capacity_limits is an interable container of triples (limit_id, gene_product_ids, capacity_bound) which are converted to a constraint identified by the limit_id that limits the total mass of gene_product_ids (which is any iterable container) by capacity_bound.

source
COBREXA.enzyme_variablesMethod
enzyme_variables(
+

Connect variables returned by enzyme_variables to unidirectional fluxes. This is used to construct the contraint system for enzyme_constrained_flux_balance_constraints.

Parameters fluxes_forward, fluxes_reverse, isozyme_forward_amounts, isozyme_reverse_amounts and gene_product_amounts should correspond to parameters and results of enzyme_variables.

Further, parameter functions kcat_forward and kcat_reverse specify the turnover numbers for reaction and isozyme IDs given in parameters; isozyme_gene_product_stoichiometry specifies the composition of the reaction-isozyme IDs given in parameter by returning an interable mapping of gene product IDs to numbers (such as Dict{Symbol, Float64}), and gene_product_molar_mass specifies a numeric mass for a given gene product ID. All parameter functions may return nothing, at which point the given object is considered nonexistent and is omitted from constraints.

capacity_limits is an interable container of triples (limit_id, gene_product_ids, capacity_bound) which are converted to a constraint identified by the limit_id that limits the total mass of gene_product_ids (which is any iterable container) by capacity_bound.

source
COBREXA.enzyme_variablesMethod
enzyme_variables(
 ;
     fluxes_forward,
     fluxes_reverse,
@@ -96,20 +96,20 @@
     isozyme_forward_amounts_name,
     isozyme_reverse_amounts_name
 )
-

Returns a constraint tree with enzyme capacity constraints, added for reactions in fluxes_forward and fluxes_reverse. This is used to construct the constraint system in enzyme_constrained_flux_balance_constraints.

Parameter function isozyme_ids takes a reaction ID and returns nothing if the reaction does not have isozymes associated with it, or an iterable container of all the isozyme IDs for that reaction (as Symbols).

Parameters isozyme_forward_ids and isozyme_reverse_ids can be used to fine-tune the generated isozymes in either direction; both default to isozyme_ids.

The keys in the output constraint tree can be customized by setting isozyme_forward_amounts_name, isozyme_reverse_amounts_name and gene_product_amounts_name.

source
COBREXA.isozyme_amount_variablesMethod
isozyme_amount_variables(
+

Returns a constraint tree with enzyme capacity constraints, added for reactions in fluxes_forward and fluxes_reverse. This is used to construct the constraint system in enzyme_constrained_flux_balance_constraints.

Parameter function isozyme_ids takes a reaction ID and returns nothing if the reaction does not have isozymes associated with it, or an iterable container of all the isozyme IDs for that reaction (as Symbols).

Parameters isozyme_forward_ids and isozyme_reverse_ids can be used to fine-tune the generated isozymes in either direction; both default to isozyme_ids.

The keys in the output constraint tree can be customized by setting isozyme_forward_amounts_name, isozyme_reverse_amounts_name and gene_product_amounts_name.

source
COBREXA.isozyme_amount_variablesMethod
isozyme_amount_variables(
     fluxes,
     flux_isozymes
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Create a ConstraintTree with variables for isozyme contributions to reaction fluxes. The tree has 2 levels: the first contains all reaction flux IDs that have isozymes, the second contains the isozyme IDs for each reaction flux.

fluxes should be anything that can be iterated to give reaction flux IDs.

flux_isozymes is a function that, for a given reaction flux ID, returns anything iterable that contains the isozyme IDs for the given reaction flux. Returning an empty iterable prevents allocating the subtree for the given flux.

source
COBREXA.isozyme_flux_constraintsMethod
isozyme_flux_constraints(
+

Create a ConstraintTree with variables for isozyme contributions to reaction fluxes. The tree has 2 levels: the first contains all reaction flux IDs that have isozymes, the second contains the isozyme IDs for each reaction flux.

fluxes should be anything that can be iterated to give reaction flux IDs.

flux_isozymes is a function that, for a given reaction flux ID, returns anything iterable that contains the isozyme IDs for the given reaction flux. Returning an empty iterable prevents allocating the subtree for the given flux.

source
COBREXA.isozyme_flux_constraintsMethod
isozyme_flux_constraints(
     isozyme_amounts::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     kcat
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

A constraint tree that sums up partial contributions of reaction isozymes to the fluxes of reactions.

For practical purposes, both fluxes and isozymes are here considered to be unidirectional, i.e., one would typically apply this twice to constraint both "forward" and "reverse" fluxes.

Function kcat should return the kcat value for a given reaction and isozyme (IDs of which respectively form the 2 parameters for each call).

source
COBREXA.isozyme_gene_product_amount_constraintsMethod
isozyme_gene_product_amount_constraints(
+

A constraint tree that sums up partial contributions of reaction isozymes to the fluxes of reactions.

For practical purposes, both fluxes and isozymes are here considered to be unidirectional, i.e., one would typically apply this twice to constraint both "forward" and "reverse" fluxes.

Function kcat should return the kcat value for a given reaction and isozyme (IDs of which respectively form the 2 parameters for each call).

source
COBREXA.isozyme_gene_product_amount_constraintsMethod
isozyme_gene_product_amount_constraints(
     isozyme_amounts,
     isozyme_stoichiometry
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

A constraint tree that computes the gene product amounts from given isozyme amounts their multiplicities (aka. stoichiometries, protein units, ...) given by isozyme_stoichiometry.

Values in ConstraintTree gene_product_amounts should describe the gene product allocations. Allocation for the isozyme is ignored if the gene product is missing in gene_product_amounts.

isozyme_amounts is an iterable that contains several ConstraintTrees that describe the allocated isozyme amounts (typically these would be created by isozyme_amount_variables. The multiple trees may describe several different kinds of isozyme use, e.g., you can use it to pass in both forward- and reverse-direction amounts at once. To only use a single tree, use an uni-tuple: isozyme_amounts = tuple(my_tree).

Parameter function isozyme_stoichiometry gets called with a reaction and isozyme IDs as given by the isozyme amount trees. It should return nothing in case there's no information – in such case, the isozyme is not going to be included in the calculation of gene product mass.

source
COBREXA.simplified_enzyme_constraintsMethod
simplified_enzyme_constraints(
+

A constraint tree that computes the gene product amounts from given isozyme amounts their multiplicities (aka. stoichiometries, protein units, ...) given by isozyme_stoichiometry.

Values in ConstraintTree gene_product_amounts should describe the gene product allocations. Allocation for the isozyme is ignored if the gene product is missing in gene_product_amounts.

isozyme_amounts is an iterable that contains several ConstraintTrees that describe the allocated isozyme amounts (typically these would be created by isozyme_amount_variables. The multiple trees may describe several different kinds of isozyme use, e.g., you can use it to pass in both forward- and reverse-direction amounts at once. To only use a single tree, use an uni-tuple: isozyme_amounts = tuple(my_tree).

Parameter function isozyme_stoichiometry gets called with a reaction and isozyme IDs as given by the isozyme amount trees. It should return nothing in case there's no information – in such case, the isozyme is not going to be included in the calculation of gene product mass.

source
COBREXA.simplified_enzyme_constraintsMethod
simplified_enzyme_constraints(
 ;
     fluxes_forward,
     fluxes_reverse,
@@ -117,14 +117,14 @@
     mass_cost_reverse,
     capacity_limits
 )
-

Build a constraint system that bounds fluxes according to their enzyme mass requirements, with respect to per-reaction enzyme mass costs.

Parameter functions mass_cost_forward and mass_cost_reverse take a flux ID (corresponding to a flux in fluxes_forward and fluxes_reverse) and return the enzyme mass required to catalyze one "unit" of reaction in the forward or reverse direction, respectively. Returning nothing ignores the mass cost.

capacity_limits is an iterable container of triples (limit_id, flux_ids, bound), which creates the capacity bounds over groups of fluxes (in the same manner as for gene products in enzyme_constraints).

source
COBREXA.simplified_isozyme_gene_product_amount_constraintsMethod
simplified_isozyme_gene_product_amount_constraints(
+

Build a constraint system that bounds fluxes according to their enzyme mass requirements, with respect to per-reaction enzyme mass costs.

Parameter functions mass_cost_forward and mass_cost_reverse take a flux ID (corresponding to a flux in fluxes_forward and fluxes_reverse) and return the enzyme mass required to catalyze one "unit" of reaction in the forward or reverse direction, respectively. Returning nothing ignores the mass cost.

capacity_limits is an iterable container of triples (limit_id, flux_ids, bound), which creates the capacity bounds over groups of fluxes (in the same manner as for gene products in enzyme_constraints).

source
COBREXA.simplified_isozyme_gene_product_amount_constraintsMethod
simplified_isozyme_gene_product_amount_constraints(
     x...
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Like isozyme_gene_product_amount_constraints, but works with the "simplified" view where each reaction has an uniquely determined catalytic isozyme, as with simplified_enzyme_constraints.

As the main difference, the arguments are tuples that contain first the constraint tree without the "isozyme" layer (i.e., fluxes), and second a function that returns the gene product stoichiometry and the turnover number (again in a tuple) for the given flux identifier.

source

Interfacing of constraint systems

COBREXA.interface_constraintsMethod
interface_constraints(
+

Like isozyme_gene_product_amount_constraints, but works with the "simplified" view where each reaction has an uniquely determined catalytic isozyme, as with simplified_enzyme_constraints.

As the main difference, the arguments are tuples that contain first the constraint tree without the "isozyme" layer (i.e., fluxes), and second a function that returns the gene product stoichiometry and the turnover number (again in a tuple) for the given flux identifier.

source

Interfacing of constraint systems

COBREXA.interface_constraintsMethod
interface_constraints(
     kv;
     kwargs...
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Overload of interface_constraints for general key-value containers.

source
COBREXA.interface_constraintsMethod
interface_constraints(
+

Overload of interface_constraints for general key-value containers.

source
COBREXA.interface_constraintsMethod
interface_constraints(
     ps::Pair...;
     default_interface,
     out_interface,
@@ -132,4 +132,4 @@
     ignore,
     bound
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Join multiple constraint tree modules with interfaces into a bigger module with an interface.

Modules are like usual constraint trees, but contain an explicitly declared interface part, marked properly in arguments using e.g. a tuple (the parameters should form a dictionary constructor that would generally look such as :module_name => (module, module.interface); the second tuple member may also be specified just by name as e.g. :interface, or omitted while relying on default_interface).

Interface parts get merged and constrained to create a new interface; networks are intact with disjoint variable sets.

Compatible modules with ready-made interfaces may be created e.g. by flux_balance_constraints.

ignore may be used to selectively ignore parts of interfaces given the "module name" identifier and constraint path in the interface (these form 2 parameters passed to ignore). Similarly, bound may be used to specify bounds for the new interface, if required.

source
+

Join multiple constraint tree modules with interfaces into a bigger module with an interface.

Modules are like usual constraint trees, but contain an explicitly declared interface part, marked properly in arguments using e.g. a tuple (the parameters should form a dictionary constructor that would generally look such as :module_name => (module, module.interface); the second tuple member may also be specified just by name as e.g. :interface, or omitted while relying on default_interface).

Interface parts get merged and constrained to create a new interface; networks are intact with disjoint variable sets.

Compatible modules with ready-made interfaces may be created e.g. by flux_balance_constraints.

ignore may be used to selectively ignore parts of interfaces given the "module name" identifier and constraint path in the interface (these form 2 parameters passed to ignore). Similarly, bound may be used to specify bounds for the new interface, if required.

source diff --git a/dev/reference/core/index.html b/dev/reference/core/index.html index b2592286..4093495d 100644 --- a/dev/reference/core/index.html +++ b/dev/reference/core/index.html @@ -1,66 +1,66 @@ Core functionality · COBREXA.jl

Core functionality

Model I/O

COBREXA.download_modelMethod
download_model(args...; kwargs...) -> Any
-

Safely download a model with a known hash. All arguments are forwarded to AbstractFBCModels.download_data_file – see the documentation in the AbstractFBCModels package for details.

source
COBREXA.load_modelMethod
load_model(path::String) -> Any
-

Load a FBC model representation while guessing the correct model type to load. Uses AbstractFBCModels.load.

This overload almost always involves a search over types; do not use it in environments where performance is critical.

source
COBREXA.load_modelMethod
load_model(
+

Safely download a model with a known hash. All arguments are forwarded to AbstractFBCModels.download_data_file – see the documentation in the AbstractFBCModels package for details.

source
COBREXA.load_modelMethod
load_model(path::String) -> Any
+

Load a FBC model representation while guessing the correct model type to load. Uses AbstractFBCModels.load.

This overload almost always involves a search over types; do not use it in environments where performance is critical.

source
COBREXA.load_modelMethod
load_model(
     model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},
     path::String
 ) -> Any
-

Load a FBC model representation from a known model_type. Uses AbstractFBCModels.load.

source
COBREXA.load_modelMethod
load_model(
+

Load a FBC model representation from a known model_type. Uses AbstractFBCModels.load.

source
COBREXA.load_modelMethod
load_model(
     model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},
     path::String,
     convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}
 ) -> Any
-

Overload of load_model that explicitly specifies the known input type, and immediately converts to another model type given by argument convert_to.

source
COBREXA.load_modelMethod
load_model(
+

Overload of load_model that explicitly specifies the known input type, and immediately converts to another model type given by argument convert_to.

source
COBREXA.load_modelMethod
load_model(
     path::String,
     convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}
 ) -> Any
-

Overload of load_model that guesses the input type, but immediately converts to the model type given by argument convert_to.

source
COBREXA.save_converted_modelMethod
save_converted_model(
     model::AbstractFBCModels.AbstractFBCModel,
     path::String
 ) -> Any
-

Like save_model but tries to convert the model to a type that matches the extension of the path. For example, this will convert the model to a JSON model type in case the path ends with .json.

This is an utility shortcut – if possible, it is always better to specify the output model type explicitly.

source
COBREXA.save_modelMethod
save_model(
+

Like save_model but tries to convert the model to a type that matches the extension of the path. For example, this will convert the model to a JSON model type in case the path ends with .json.

This is an utility shortcut – if possible, it is always better to specify the output model type explicitly.

source
COBREXA.save_modelMethod
save_model(
     model::AbstractFBCModels.AbstractFBCModel,
     path::String,
     convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}
 ) -> Any
-

Overload of save_model that converts the model type to convert_to before saving.

source
COBREXA.save_modelMethod
save_model(
     model::AbstractFBCModels.AbstractFBCModel,
     path::String
 ) -> Any
-

Save a FBC model representation. Uses AbstractFBCModels.save.

Use the 3-parameter overload if you need to convert the model to another representation (e.g., if you want to save a canonical model type as JSON or SBML).

source

Types

Configuration

COBREXA.configurationConstant
const configuration

The configuration object. You can change the contents of configuration to override the default behavior of some of the functions.

The available options are described by struct Configuration.

source
COBREXA.ConfigurationType
mutable struct Configuration

Global configuration options for various COBREXA functions, mainly for various non-interesting function parameters that are too inconvenient to be passed around manually.

Changing the configuration values at runtime is possible via the global configuration variable.

Fields

  • exchange_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are exchanges.
  • biomass_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are biomass reactions.
  • atp_maintenance_ids::Vector{String}: Reaction identifiers that flux_balance_constraints considers to be ATP maintenance reactions.
  • sampler_tolerance::Any: Default numerical tolerance for sampling functions.
  • default_solver_settings::Any: Default settings first applied to all JuMP Models.
source

Solver interface

COBREXA.FeasibleConstant
Maximal

Objective sense for finding the any feasible value of the objective.

Same as JuMP.FEASIBILITY_SENSE.

source
COBREXA.MaximalConstant
Maximal

Objective sense for finding the maximal value of the objective.

Same as JuMP.MAX_SENSE.

source
COBREXA.MinimalConstant
Minimal

Objective sense for finding the minimal value of the objective.

Same as JuMP.MIN_SENSE.

source
COBREXA.SwitchType
mutable struct Switch <: ConstraintTrees.Bound

Representation of a "binary switch" bound for ConstraintTrees. The value is constrained to be either the value of field a or of field b; both fields are Float64s. Upon translation to JuMP, the switches create an extra boolean variable, and the value is constrained to equal a + boolean_var * (b-a).

Switches can be offset by adding real numbers, negated, and multiplied and divided by scalar constraints. For optimizing some special cases, multiplying by exact zero returns an equality bound to zero.

Fields

  • a::Float64: One choice

  • b::Float64: The other choice

source
COBREXA.constraint_jump!Method
constraint_jump!(
+

Save a FBC model representation. Uses AbstractFBCModels.save.

Use the 3-parameter overload if you need to convert the model to another representation (e.g., if you want to save a canonical model type as JSON or SBML).

source

Types

Configuration

COBREXA.configurationConstant
const configuration

The configuration object. You can change the contents of configuration to override the default behavior of some of the functions.

The available options are described by struct Configuration.

source
COBREXA.ConfigurationType
mutable struct Configuration

Global configuration options for various COBREXA functions, mainly for various non-interesting function parameters that are too inconvenient to be passed around manually.

Changing the configuration values at runtime is possible via the global configuration variable.

Fields

  • exchange_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are exchanges.
  • biomass_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are biomass reactions.
  • atp_maintenance_ids::Vector{String}: Reaction identifiers that flux_balance_constraints considers to be ATP maintenance reactions.
  • sampler_tolerance::Any: Default numerical tolerance for sampling functions.
  • default_solver_settings::Any: Default settings first applied to all JuMP Models.
source

Solver interface

COBREXA.FeasibleConstant
Maximal

Objective sense for finding the any feasible value of the objective.

Same as JuMP.FEASIBILITY_SENSE.

source
COBREXA.MaximalConstant
Maximal

Objective sense for finding the maximal value of the objective.

Same as JuMP.MAX_SENSE.

source
COBREXA.MinimalConstant
Minimal

Objective sense for finding the minimal value of the objective.

Same as JuMP.MIN_SENSE.

source
COBREXA.SwitchType
mutable struct Switch <: ConstraintTrees.Bound

Representation of a "binary switch" bound for ConstraintTrees. The value is constrained to be either the value of field a or of field b; both fields are Float64s. Upon translation to JuMP, the switches create an extra boolean variable, and the value is constrained to equal a + boolean_var * (b-a).

Switches can be offset by adding real numbers, negated, and multiplied and divided by scalar constraints. For optimizing some special cases, multiplying by exact zero returns an equality bound to zero.

Fields

  • a::Float64: One choice

  • b::Float64: The other choice

source
COBREXA.constraint_jump!Method
constraint_jump!(
     model,
     expr,
     b::ConstraintTrees.Between
 ) -> Union{Bool, JuMP.ConstraintRef}
-

Add an interval constraint to a JuMP model.

source
COBREXA.constraint_jump!Method
constraint_jump!(
     model,
     expr,
     b::ConstraintTrees.EqualTo
 ) -> JuMP.ConstraintRef
-

Add an equality constraint to a JuMP model.

source
COBREXA.is_solvedMethod
is_solved(opt_model::JuMP.Model) -> Bool
-

true if opt_model solved successfully (solution is optimal or locally optimal). false if any other termination status is reached.

source
COBREXA.is_solvedMethod
is_solved(opt_model::JuMP.Model) -> Bool
+

true if opt_model solved successfully (solution is optimal or locally optimal). false if any other termination status is reached.

source
COBREXA.optimization_modelMethod
optimization_model(
     cs::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};
     objective,
     optimizer,
     sense
 )
-

Construct a JuMP Model that describes the precise constraint system into the JuMP Model created for solving in optimizer, with a given optional objective and optimization sense chosen from Maximal, Minimal and Feasible.

All types of values in the constraint tree must have an overload for substitute_jump.

source
COBREXA.optimized_modelMethod
optimized_model(om; output)
-

Like optimized_values, but works directly with a given JuMP model om without applying any settings or creating the optimization model.

To run the process manually, you can use optimization_model to convert the constraints into a suitable JuMP optimization model.

source
COBREXA.optimized_objectiveMethod
optimized_objective(
+

Construct a JuMP Model that describes the precise constraint system into the JuMP Model created for solving in optimizer, with a given optional objective and optimization sense chosen from Maximal, Minimal and Feasible.

All types of values in the constraint tree must have an overload for substitute_jump.

source
COBREXA.optimized_modelMethod
optimized_model(om; output)
+

Like optimized_values, but works directly with a given JuMP model om without applying any settings or creating the optimization model.

To run the process manually, you can use optimization_model to convert the constraints into a suitable JuMP optimization model.

source
COBREXA.substitute_jumpMethod
substitute_jump(
     val::ConstraintTrees.LinearValue,
     vars
 ) -> JuMP.AffExpr
-

Very efficiently substitute a ConstraintTrees' LinearValue into a JuMP expression of type AffExpr.

source
COBREXA.substitute_jumpMethod
substitute_jump(
+

Very efficiently substitute a ConstraintTrees' LinearValue into a JuMP expression of type AffExpr.

source
COBREXA.substitute_jumpMethod
substitute_jump(
     val::ConstraintTrees.QuadraticValue,
     vars
 ) -> JuMP.QuadExpr
-

Very efficiently substitute a ConstraintTrees' QuadraticValue into a JuMP expression of type QuadExpr.

source

Task distribution support

COBREXA.worker_local_dataType
mutable struct worker_local_data

Helper struct that provides access to local data that are unboxed and cached directly on distributed workers.

Use with get_worker_local_data and Distributed.CachingPool.

Fields

  • transfer_data::Any: The data that is transferred to the remote worker

  • local_data::Union{Nothing, Some}: The data that is cached on the remote worker

  • transform::Function: The function that converts the transferred data to locally-cached data on the remote worker

source
COBREXA.get_worker_local_dataMethod
get_worker_local_data(x::COBREXA.worker_local_data) -> Any
-

"Unwrap" the worker_local_data on a remote worker to get the local_data out. If required, executes the transform function.

Local copies of transfer_data are forgotten after the function executes.

source
+

Very efficiently substitute a ConstraintTrees' QuadraticValue into a JuMP expression of type QuadExpr.

source
COBREXA.variable_vectorMethod
variable_vector(opt_model::JuMP.Model) -> Any
+

Retrieve the variable vector from a JuMP model created by optimization_model.

source

Task distribution support

COBREXA.worker_local_dataType
mutable struct worker_local_data

Helper struct that provides access to local data that are unboxed and cached directly on distributed workers.

Use with get_worker_local_data and Distributed.CachingPool.

Fields

  • transfer_data::Any: The data that is transferred to the remote worker

  • local_data::Union{Nothing, Some}: The data that is cached on the remote worker

  • transform::Function: The function that converts the transferred data to locally-cached data on the remote worker

source
COBREXA.get_worker_local_dataMethod
get_worker_local_data(x::COBREXA.worker_local_data) -> Any
+

"Unwrap" the worker_local_data on a remote worker to get the local_data out. If required, executes the transform function.

Local copies of transfer_data are forgotten after the function executes.

source
diff --git a/dev/reference/frontend/index.html b/dev/reference/frontend/index.html index b687ceb2..bd7708e9 100644 --- a/dev/reference/frontend/index.html +++ b/dev/reference/frontend/index.html @@ -3,12 +3,12 @@ model::AbstractFBCModels.AbstractFBCModel; kwargs... ) -

Compute an optimal objective-optimizing solution of the given model.

Most arguments are forwarded to optimized_values.

Returns a tree with the optimization solution of the same shape as given by flux_balance_constraints.

source
COBREXA.flux_balance_constraintsMethod
flux_balance_constraints(
+

Compute an optimal objective-optimizing solution of the given model.

Most arguments are forwarded to optimized_values.

Returns a tree with the optimization solution of the same shape as given by flux_balance_constraints.

source
COBREXA.flux_balance_constraintsMethod
flux_balance_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     interface,
     interface_name
 ) -> Any
-

A constraint tree that models the content of the given instance of AbstractFBCModel.

The constructed tree contains subtrees fluxes (with the reaction-defining "variables") and flux_stoichiometry (with the metabolite-balance-defining constraints), and a single constraint objective thad describes the objective function of the model.

Optionally if interface is specified, an "interface block" will be created within the constraint tree for later use as a "module" in creating bigger models (such as communities) using interface_constraints. The possible parameter values include:

  • nothing – default, no interface is created
  • :sbo – the interface gets created from model's SBO annotations)
  • :identifier_prefixes – the interface is guesstimated from commonly occurring adhoc reaction ID prefixes used in contemporary models
  • :boundary – the interface is created from all reactions that either only consume or only produce metabolites

Output interface name can be set via interface_name.

See Configuration for fine-tuning the default interface creation.

source

Flux variability analysis

COBREXA.flux_variability_analysisMethod
flux_variability_analysis(
+

A constraint tree that models the content of the given instance of AbstractFBCModel.

The constructed tree contains subtrees fluxes (with the reaction-defining "variables") and flux_stoichiometry (with the metabolite-balance-defining constraints), and a single constraint objective thad describes the objective function of the model.

Optionally if interface is specified, an "interface block" will be created within the constraint tree for later use as a "module" in creating bigger models (such as communities) using interface_constraints. The possible parameter values include:

  • nothing – default, no interface is created
  • :sbo – the interface gets created from model's SBO annotations)
  • :identifier_prefixes – the interface is guesstimated from commonly occurring adhoc reaction ID prefixes used in contemporary models
  • :boundary – the interface is created from all reactions that either only consume or only produce metabolites

Output interface name can be set via interface_name.

See Configuration for fine-tuning the default interface creation.

source

Flux variability analysis

COBREXA.flux_variability_analysisMethod
flux_variability_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     objective_bound,
     reactions,
@@ -16,25 +16,25 @@
     settings,
     workers
 )
-

Perform a Flux Variability Analysis (FVA) on the model, and return a dictionary of flux ranges where the model is able to perform optimally.

The constraint system is constructed using flux_balance_constraints, and the variability is examined on all reaction's fluxes, or on the subset given optionally in reaction_subset (e.g., reaction_subset = ["PFK", "ACALD"]). The optimality tolerance can be specified with objective_bound using e.g. relative_tolerance_bound or absolute_tolerance_bound; the default is 99% relative tolerance.

Parameter workers may be used to enable parallel or distributed processing; the execution defaults to all available workers. Other parameters (esp. optimizer) are internally forwarded to optimized_values.

Use constraints_variability to customize the FVA execution.

source

Parsimonious flux balance analysis

COBREXA.linear_parsimonious_flux_balance_analysisMethod
linear_parsimonious_flux_balance_analysis(
+

Perform a Flux Variability Analysis (FVA) on the model, and return a dictionary of flux ranges where the model is able to perform optimally.

The constraint system is constructed using flux_balance_constraints, and the variability is examined on all reaction's fluxes, or on the subset given optionally in reaction_subset (e.g., reaction_subset = ["PFK", "ACALD"]). The optimality tolerance can be specified with objective_bound using e.g. relative_tolerance_bound or absolute_tolerance_bound; the default is 99% relative tolerance.

Parameter workers may be used to enable parallel or distributed processing; the execution defaults to all available workers. Other parameters (esp. optimizer) are internally forwarded to optimized_values.

Use constraints_variability to customize the FVA execution.

source

Parsimonious flux balance analysis

COBREXA.linear_parsimonious_flux_balance_analysisMethod
linear_parsimonious_flux_balance_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     tolerances,
     kwargs...
 )
-

Like parsimonious_flux_balance_analysis, but uses the L1-metric parsimonious system given by linear_parsimonious_flux_balance_constraints.

In turn, the solution is often faster, does not require a solver capable of quadratic objectives, and has many beneficial properties of the usual parsimonious solutions (such as the general lack of unnecessary loops). On the other hand, like with plain flux balance analysis there is no strong guarantee of uniqueness of the solution.

Solver configuration arguments are forwarded to parsimonious_optimized_values.

source
COBREXA.linear_parsimonious_flux_balance_constraintsMethod
linear_parsimonious_flux_balance_constraints(
+

Like parsimonious_flux_balance_analysis, but uses the L1-metric parsimonious system given by linear_parsimonious_flux_balance_constraints.

In turn, the solution is often faster, does not require a solver capable of quadratic objectives, and has many beneficial properties of the usual parsimonious solutions (such as the general lack of unnecessary loops). On the other hand, like with plain flux balance analysis there is no strong guarantee of uniqueness of the solution.

Solver configuration arguments are forwarded to parsimonious_optimized_values.

source
COBREXA.linear_parsimonious_flux_balance_constraintsMethod
linear_parsimonious_flux_balance_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 ) -> ConstraintTrees.Tree
-

Like parsimonious_flux_balance_constraints, but uses a L1 metric for solving the parsimonious problem. The parsimonious_objective constraint is thus linear.

Keyword arguments are forwarded to flux_balance_constraints.

source
COBREXA.parsimonious_flux_balance_analysisMethod
parsimonious_flux_balance_analysis(
+

Like parsimonious_flux_balance_constraints, but uses a L1 metric for solving the parsimonious problem. The parsimonious_objective constraint is thus linear.

Keyword arguments are forwarded to flux_balance_constraints.

source
COBREXA.parsimonious_flux_balance_analysisMethod
parsimonious_flux_balance_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     tolerances,
     kwargs...
 )
-

Compute a parsimonious flux solution for the model, using the constraints given by parsimonious_flux_balance_constraints.

In short, the objective value of the parsimonious solution should be the same as the one from flux_balance_analysis, except the squared sum of reaction fluxes is minimized. If there are multiple possible fluxes that achieve a given objective value, parsimonious flux thus represents the "minimum energy" one, which is arguably more realistic.

Solver configuration arguments are forwarded to parsimonious_optimized_values.

source
COBREXA.parsimonious_flux_balance_constraintsMethod
parsimonious_flux_balance_constraints(
+

Compute a parsimonious flux solution for the model, using the constraints given by parsimonious_flux_balance_constraints.

In short, the objective value of the parsimonious solution should be the same as the one from flux_balance_analysis, except the squared sum of reaction fluxes is minimized. If there are multiple possible fluxes that achieve a given objective value, parsimonious flux thus represents the "minimum energy" one, which is arguably more realistic.

Solver configuration arguments are forwarded to parsimonious_optimized_values.

source
COBREXA.parsimonious_flux_balance_constraintsMethod
parsimonious_flux_balance_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 ) -> Any
-

A constraint system like from flux_balance_constraints, but with the parsimonious objective present under key parsimonious_objective. Best used via parsimonious_flux_balance_analysis.

Keyword arguments are forwarded to flux_balance_constraints.

source

Minimization of metabolic adjustment

COBREXA.linear_metabolic_adjustment_minimization_analysisMethod
linear_metabolic_adjustment_minimization_analysis(
+

A constraint system like from flux_balance_constraints, but with the parsimonious objective present under key parsimonious_objective. Best used via parsimonious_flux_balance_analysis.

Keyword arguments are forwarded to flux_balance_constraints.

source

Minimization of metabolic adjustment

COBREXA.linear_metabolic_adjustment_minimization_analysisMethod
linear_metabolic_adjustment_minimization_analysis(
     model::AbstractFBCModels.AbstractFBCModel,
     args...;
     optimizer,
@@ -45,17 +45,17 @@
     reference_settings,
     kwargs...
 )
-

Perform a linear minimization of metabolic adjustment analysis (l-MOMA) on model. The reference is given by the second argument, which is either a reference_flux or a reference_model (the second argument is forwarded to linear_metabolic_adjustment_minimization_constraints).

While the solution is "less uniquely defined" than with fully quadratic metabolic_adjustment_minimization_analysis, the linear variant typically produces a sufficiently good result with much less resources. See documentation of linear_parsimonious_flux_balance_analysis for some of the considerations.

source
COBREXA.linear_metabolic_adjustment_minimization_constraintsMethod
linear_metabolic_adjustment_minimization_constraints(
+

Perform a linear minimization of metabolic adjustment analysis (l-MOMA) on model. The reference is given by the second argument, which is either a reference_flux or a reference_model (the second argument is forwarded to linear_metabolic_adjustment_minimization_constraints).

While the solution is "less uniquely defined" than with fully quadratic metabolic_adjustment_minimization_analysis, the linear variant typically produces a sufficiently good result with much less resources. See documentation of linear_parsimonious_flux_balance_analysis for some of the considerations.

source
COBREXA.linear_metabolic_adjustment_minimization_constraintsMethod
linear_metabolic_adjustment_minimization_constraints(
     model::AbstractFBCModels.AbstractFBCModel,
     reference_model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 ) -> Union{Nothing, ConstraintTrees.Tree}
-

Like metabolic_adjustment_minimization_constraints but the output constraints optimize the L1 distance from the linear-parsimonious solution of the reference_model.

source
COBREXA.linear_metabolic_adjustment_minimization_constraintsMethod
linear_metabolic_adjustment_minimization_constraints(
+

Like metabolic_adjustment_minimization_constraints but the output constraints optimize the L1 distance from the linear-parsimonious solution of the reference_model.

source
COBREXA.linear_metabolic_adjustment_minimization_constraintsMethod
linear_metabolic_adjustment_minimization_constraints(
     model::AbstractFBCModels.AbstractFBCModel,
     reference_fluxes::ConstraintTrees.Tree;
     _...
 ) -> ConstraintTrees.Tree
-

Like metabolic_adjustment_minimization_constraints but optimizes the L1 distance from reference_fluxes.

Keyword arguments are discarded for compatibility with the other overload.

source
COBREXA.metabolic_adjustment_minimization_analysisMethod
metabolic_adjustment_minimization_analysis(
+

Like metabolic_adjustment_minimization_constraints but optimizes the L1 distance from reference_fluxes.

Keyword arguments are discarded for compatibility with the other overload.

source
COBREXA.metabolic_adjustment_minimization_analysisMethod
metabolic_adjustment_minimization_analysis(
     model::AbstractFBCModels.AbstractFBCModel,
     args...;
     optimizer,
@@ -66,28 +66,28 @@
     reference_settings,
     kwargs...
 )
-

Find a solution of the "minimization of metabolic adjustment" (MOMA) analysis for the model, which is the "closest" feasible solution to the solution given in the second argument, which is either reference_fluxes or reference_model (see documentation of metabolic_adjustment_minimization_constraints), in the sense of squared-sum distance. The minimized squared distance (the objective) is present in the result tree as minimal_adjustment_objective.

If the second argument is a reference model, it is solved using a parsimonious_flux_balance_analysis with the optimizer and settings parameters for the 2 steps set by keyword arguments prefixed by reference_.

This is often used for models with smaller feasible region than the reference models (typically handicapped by a knockout, a nutritional deficiency or a similar perturbation). MOMA solution then gives an expectable "easiest" adjustment of the organism towards a somewhat working state.

Reference fluxes that do not exist in the model are ignored (internally, the objective is constructed via squared_sum_error_value).

source
COBREXA.metabolic_adjustment_minimization_constraintsMethod
metabolic_adjustment_minimization_constraints(
+

Find a solution of the "minimization of metabolic adjustment" (MOMA) analysis for the model, which is the "closest" feasible solution to the solution given in the second argument, which is either reference_fluxes or reference_model (see documentation of metabolic_adjustment_minimization_constraints), in the sense of squared-sum distance. The minimized squared distance (the objective) is present in the result tree as minimal_adjustment_objective.

If the second argument is a reference model, it is solved using a parsimonious_flux_balance_analysis with the optimizer and settings parameters for the 2 steps set by keyword arguments prefixed by reference_.

This is often used for models with smaller feasible region than the reference models (typically handicapped by a knockout, a nutritional deficiency or a similar perturbation). MOMA solution then gives an expectable "easiest" adjustment of the organism towards a somewhat working state.

Reference fluxes that do not exist in the model are ignored (internally, the objective is constructed via squared_sum_error_value).

source
COBREXA.metabolic_adjustment_minimization_constraintsMethod
metabolic_adjustment_minimization_constraints(
     model::AbstractFBCModels.AbstractFBCModel,
     reference_model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 ) -> Any
-

A slightly easier-to-use version of metabolic_adjustment_minimization_constraints that computes the reference flux as the parsimonious optimal solution of the reference_model. The reference flux is calculated using reference_optimizer and reference_modifications, which default to the optimizer and settings.

Other arguments are forwarded to the internal call of parsimonious_optimized_values.

Returns nothing if no feasible solution is found.

source
COBREXA.metabolic_adjustment_minimization_constraintsMethod
metabolic_adjustment_minimization_constraints(
+

A slightly easier-to-use version of metabolic_adjustment_minimization_constraints that computes the reference flux as the parsimonious optimal solution of the reference_model. The reference flux is calculated using reference_optimizer and reference_modifications, which default to the optimizer and settings.

Other arguments are forwarded to the internal call of parsimonious_optimized_values.

Returns nothing if no feasible solution is found.

source
COBREXA.metabolic_adjustment_minimization_constraintsMethod
metabolic_adjustment_minimization_constraints(
     model::AbstractFBCModels.AbstractFBCModel,
     reference_fluxes::ConstraintTrees.Tree;
     _...
 ) -> Any
-

Keyword arguments are discarded for compatibility with the other overload.

source

Constraint systems for metabolite concentrations

COBREXA.log_concentration_constraintsMethod
log_concentration_constraints(
+

Keyword arguments are discarded for compatibility with the other overload.

source

Constraint systems for metabolite concentrations

COBREXA.log_concentration_constraintsMethod
log_concentration_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     reactions,
     metabolites,
     metabolite_concentration_bound,
     reaction_concentration_bound
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Build log-concentration-stoichiometry constraints for the model, as used e.g. by max_min_driving_force_analysis.

The output constraint tree contains a log-concentration variable for each metabolite from model, in subtree log_concentrations. The total reactant log-concentrations for each reaction are constrained in subtree log_concentration_stoichiometry. By default, all reactions and metabolites in model are included.

A concentration bound is given by parameter function concentration_bound for each metabolite ID (the string ID is the single argument of the function); by default the function returns nothing and no bounds are installed. The same is used for reactions with reaction_concentration_bound.

source

Enzyme-mass-constrained models

COBREXA.IsozymeType
mutable struct Isozyme

A simple struct storing information about the isozyme composition, including subunit stoichiometry and turnover numbers. Use with enzyme_constrained_flux_balance_analysis.

Fields

  • gene_product_stoichiometry::Dict{String, Float64}: Mapping of gene product identifiers ("genes" in FBC model nomenclature) to their relative amount required to construct one unit of the isozyme.
  • kcat_forward::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the forward direction of the reaction.

  • kcat_reverse::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the reverse direction of the reaction.

source
COBREXA.enzyme_constrained_flux_balance_analysisMethod
enzyme_constrained_flux_balance_analysis(
+

Build log-concentration-stoichiometry constraints for the model, as used e.g. by max_min_driving_force_analysis.

The output constraint tree contains a log-concentration variable for each metabolite from model, in subtree log_concentrations. The total reactant log-concentrations for each reaction are constrained in subtree log_concentration_stoichiometry. By default, all reactions and metabolites in model are included.

A concentration bound is given by parameter function concentration_bound for each metabolite ID (the string ID is the single argument of the function); by default the function returns nothing and no bounds are installed. The same is used for reactions with reaction_concentration_bound.

source

Enzyme-mass-constrained models

COBREXA.IsozymeType
mutable struct Isozyme

A simple struct storing information about the isozyme composition, including subunit stoichiometry and turnover numbers. Use with enzyme_constrained_flux_balance_analysis.

Fields

  • gene_product_stoichiometry::Dict{String, Float64}: Mapping of gene product identifiers ("genes" in FBC model nomenclature) to their relative amount required to construct one unit of the isozyme.
  • kcat_forward::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the forward direction of the reaction.

  • kcat_reverse::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the reverse direction of the reaction.

source
COBREXA.enzyme_constrained_flux_balance_analysisMethod
enzyme_constrained_flux_balance_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 )
-

Perform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.

Arguments are forwarded to enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.

source
COBREXA.enzyme_constrained_flux_balance_constraintsMethod
enzyme_constrained_flux_balance_constraints(
+

Perform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.

Arguments are forwarded to enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.

source
COBREXA.enzyme_constrained_flux_balance_constraintsMethod
enzyme_constrained_flux_balance_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     reaction_isozymes,
     gene_product_molar_masses,
@@ -95,11 +95,11 @@
     interface,
     interface_name
 )
-

Construct a enzyme-constrained flux-balance constraint system, following the method in GECKO algorithm (refer to: Sánchez, Benjamín J., et al. "Improving the phenotype predictions of a yeast genome‐scale metabolic model by incorporating enzymatic constraints." Molecular systems biology 13.8 (2017): 935).

The enzyme mass constraints depend primarily on the available isozymes, given in parameter reaction_isozymes, which is a mapping of reaction identifiers to descriptions of Isozymes that may catalyze the particular reactions. The isozymes are built from gene products, the mass of which is specified by gene_product_molar_masses. In total, the amount of gene product building material is limited by capacity.

capacity may be a single number, which sets the mass limit for "all described enzymes". Alternatively, capacity may be a vector of identifier-genes-limit triples that together form a constraint (identified by the given identifier) that limits the total sum of the listed genes to the given limit.

interface and interface_name are forwarded to flux_balance_constraints.

source
COBREXA.simplified_enzyme_constrained_flux_balance_analysisMethod
simplified_enzyme_constrained_flux_balance_analysis(
+

Construct a enzyme-constrained flux-balance constraint system, following the method in GECKO algorithm (refer to: Sánchez, Benjamín J., et al. "Improving the phenotype predictions of a yeast genome‐scale metabolic model by incorporating enzymatic constraints." Molecular systems biology 13.8 (2017): 935).

The enzyme mass constraints depend primarily on the available isozymes, given in parameter reaction_isozymes, which is a mapping of reaction identifiers to descriptions of Isozymes that may catalyze the particular reactions. The isozymes are built from gene products, the mass of which is specified by gene_product_molar_masses. In total, the amount of gene product building material is limited by capacity.

capacity may be a single number, which sets the mass limit for "all described enzymes". Alternatively, capacity may be a vector of identifier-genes-limit triples that together form a constraint (identified by the given identifier) that limits the total sum of the listed genes to the given limit.

interface and interface_name are forwarded to flux_balance_constraints.

source
COBREXA.simplified_enzyme_constrained_flux_balance_analysisMethod
simplified_enzyme_constrained_flux_balance_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 )
-

Perform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.

Arguments are forwarded to simplified_enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.

source
COBREXA.simplified_enzyme_constrained_flux_balance_constraintsMethod
simplified_enzyme_constrained_flux_balance_constraints(
+

Perform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.

Arguments are forwarded to simplified_enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.

source
COBREXA.simplified_enzyme_constrained_flux_balance_constraintsMethod
simplified_enzyme_constrained_flux_balance_constraints(
     model;
     reaction_isozymes,
     gene_product_molar_masses,
@@ -107,8 +107,8 @@
     interface,
     interface_name
 )
-

Like enzyme_constrained_flux_balance_constraints, but automatically selects a single "fastest" isozyme for each reaction direction. In turn, the system requires much less variables in the constraint system description, and usually solves more efficiently, for the price of possibly finding suboptimal solutions. The method follows the SMOMENT algorithm described in Bekiaris, P.S., Klamt, S. Automatic construction of metabolic models with enzyme constraints. BMC Bioinformatics 21, 19 (2020). https://doi.org/10.1186/s12859-019-3329-9.

Arguments are as with enzyme_constrained_flux_balance_constraints, with a major difference in capacity handling: the identifier lists (2nd elements of the triples given in the list) are not identifiers of gene products, but identifiers of reactions.

source

Community models

COBREXA.community_flux_balance_analysisMethod
community_flux_balance_analysis(args...; kwargs...)
-

Run the Community Flux Balance Analysis on several models. All arguments are forwarded to community_flux_balance_constraints which constructs the model; this function returns the solved model.

source
COBREXA.community_flux_balance_constraintsMethod
community_flux_balance_constraints(
+

Like enzyme_constrained_flux_balance_constraints, but automatically selects a single "fastest" isozyme for each reaction direction. In turn, the system requires much less variables in the constraint system description, and usually solves more efficiently, for the price of possibly finding suboptimal solutions. The method follows the SMOMENT algorithm described in Bekiaris, P.S., Klamt, S. Automatic construction of metabolic models with enzyme constraints. BMC Bioinformatics 21, 19 (2020). https://doi.org/10.1186/s12859-019-3329-9.

Arguments are as with enzyme_constrained_flux_balance_constraints, with a major difference in capacity handling: the identifier lists (2nd elements of the triples given in the list) are not identifiers of gene products, but identifiers of reactions.

source

Community models

COBREXA.community_flux_balance_analysisMethod
community_flux_balance_analysis(args...; kwargs...)
+

Run the Community Flux Balance Analysis on several models. All arguments are forwarded to community_flux_balance_constraints which constructs the model; this function returns the solved model.

source
COBREXA.community_flux_balance_constraintsMethod
community_flux_balance_constraints(
     model_abundances,
     community_exchange_bounds;
     interface,
@@ -116,7 +116,7 @@
     interface_biomass,
     default_community_exchange_bound
 ) -> Any
-

Construct an instance of a linear community Flux Balance Analysis (cFBA) model. The relative abundances of the organisms are known in advance; this function predicts the maximum achievable community growth rate.

model_abundances is a dictionary-like object that maps model identifiers to tuples of models (usually subtypes of AbstractFBCModel) and their abundances (such as: "bug1" => (bug1, 0.5), ...). community_exchange_bounds is a dictionary-like object that can be additionally used to restrict selected community exchange reactions (keys should be reaction IDs, the values are converted to ConstraintTrees-like bounds). Bounds otherwise default to parameter default_community_exchange_bound, which itself defaults to nothing (i.e., unbounded).

If required, constraint trees may be supplied instead of AbstracFBCModels in model_abundances. These must provide an interface compatible with interface_exchanges and interface_biomass.

interface is forwarded to flux_balance_constraints. interface_exchanges and interface_biomass are used to pick up the correct interface part to contribute to the community exchanges and community biomass.

source

Production envelopes

COBREXA.objective_production_envelopeMethod
objective_production_envelope(
+

Construct an instance of a linear community Flux Balance Analysis (cFBA) model. The relative abundances of the organisms are known in advance; this function predicts the maximum achievable community growth rate.

model_abundances is a dictionary-like object that maps model identifiers to tuples of models (usually subtypes of AbstractFBCModel) and their abundances (such as: "bug1" => (bug1, 0.5), ...). community_exchange_bounds is a dictionary-like object that can be additionally used to restrict selected community exchange reactions (keys should be reaction IDs, the values are converted to ConstraintTrees-like bounds). Bounds otherwise default to parameter default_community_exchange_bound, which itself defaults to nothing (i.e., unbounded).

If required, constraint trees may be supplied instead of AbstracFBCModels in model_abundances. These must provide an interface compatible with interface_exchanges and interface_biomass.

interface is forwarded to flux_balance_constraints. interface_exchanges and interface_biomass are used to pick up the correct interface part to contribute to the community exchanges and community biomass.

source

Production envelopes

COBREXA.objective_production_envelopeMethod
objective_production_envelope(
     model::AbstractFBCModels.AbstractFBCModel,
     reactions::Vector{String};
     breaks,
@@ -124,8 +124,8 @@
     settings,
     workers
 )
-

Find the objective production envelope of the model in the dimensions given by reactions.

This runs a variability analysis of the fluxes given by flux_balance_constraints to determine an applicable range for the dimensions, then splits the dimensions to equal-sized breaks (of count breaks for each dimension, i.e. total breaks ^ length(reactions) individual "multidimensional breaks") thus forming a grid, and returns an array of fluxes through the model objective with the individual reactions fixed to flux as given by the grid.

optimizer and settings are used to construct the optimization models.

The computation is distributed to the specified workers, defaulting to all available workers.

source

Gap-filling

COBREXA.gap_filling_analysisMethod
gap_filling_analysis(args...; kwargs...)
-

Run the gap-filling analysis on a constraint system specified by gap_filling_constraints.

source
COBREXA.gap_filling_constraintsMethod
gap_filling_constraints(
+

Find the objective production envelope of the model in the dimensions given by reactions.

This runs a variability analysis of the fluxes given by flux_balance_constraints to determine an applicable range for the dimensions, then splits the dimensions to equal-sized breaks (of count breaks for each dimension, i.e. total breaks ^ length(reactions) individual "multidimensional breaks") thus forming a grid, and returns an array of fluxes through the model objective with the individual reactions fixed to flux as given by the grid.

optimizer and settings are used to construct the optimization models.

The computation is distributed to the specified workers, defaulting to all available workers.

source

Gap-filling

COBREXA.gap_filling_analysisMethod
gap_filling_analysis(args...; kwargs...)
+

Run the gap-filling analysis on a constraint system specified by gap_filling_constraints.

source
COBREXA.gap_filling_constraintsMethod
gap_filling_constraints(
     model::AbstractFBCModels.AbstractFBCModel,
     universal_model::AbstractFBCModels.AbstractFBCModel,
     objective_target::Float64;
@@ -134,7 +134,7 @@
     known_fills,
     kwargs...
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Make a gap-filling system from a FBC model with gaps and an universal FBC model that contains reactions to be added into the original model.

The output system will be constrainted to reach at least objective_target flux through the objective function. Generally, this should be set to an arbitrary small value such as 0.05.

universal_reaction_cost should assign a numeric cost of inclusion of each of the reactions in the universal_model; by default all are assigned equal weight of 1. max_cost puts an optional maximum limit on the cost, which may help the solver to avoid exploring unnecessarily complex solutions. known_fills may contain previous solutions of the same system; these will be made infeasible in the output constraint system in order to allow discovery of other ones.

Additional arguments are forwarded to flux_balance_constraints that converts model to constraints.

source
COBREXA.gap_filling_constraintsMethod
gap_filling_constraints(
+

Make a gap-filling system from a FBC model with gaps and an universal FBC model that contains reactions to be added into the original model.

The output system will be constrainted to reach at least objective_target flux through the objective function. Generally, this should be set to an arbitrary small value such as 0.05.

universal_reaction_cost should assign a numeric cost of inclusion of each of the reactions in the universal_model; by default all are assigned equal weight of 1. max_cost puts an optional maximum limit on the cost, which may help the solver to avoid exploring unnecessarily complex solutions. known_fills may contain previous solutions of the same system; these will be made infeasible in the output constraint system in order to allow discovery of other ones.

Additional arguments are forwarded to flux_balance_constraints that converts model to constraints.

source
COBREXA.gap_filling_constraintsMethod
gap_filling_constraints(
 ;
     system,
     stoichiometry,
@@ -144,41 +144,41 @@
     max_cost,
     known_fills
 )
-

Make a gap-fillign system from a non-solving system with a separated stoichiometry, filling in possible fluxes from universal_fluxes that are balanced with universal_stoichiometry

flux_cost can be used to assign a weight to each given universal flux; the total cost is bounded by max_cost.

known_fills may contain previous solutions to be avoided; these are processed by gap_filling_known_fill_constraint and attached to the system.

stoichiometry needs to be extended to construct the final constraints, thus it should not be present in the original system.

source
COBREXA.gap_filling_known_fill_constraintMethod
gap_filling_known_fill_constraint(
+

Make a gap-fillign system from a non-solving system with a separated stoichiometry, filling in possible fluxes from universal_fluxes that are balanced with universal_stoichiometry

flux_cost can be used to assign a weight to each given universal flux; the total cost is bounded by max_cost.

known_fills may contain previous solutions to be avoided; these are processed by gap_filling_known_fill_constraint and attached to the system.

stoichiometry needs to be extended to construct the final constraints, thus it should not be present in the original system.

source
COBREXA.gap_filling_known_fill_constraintMethod
gap_filling_known_fill_constraint(
     fill_flags::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     known_flags::ConstraintTrees.Tree{Float64}
 ) -> ConstraintTrees.Constraint
-

Produce a constraint that can be added to the system made by gap_filling_constraints to avoid repeating of a solution that includes reactions already generated by another solution, as represented by the solved fill_flags.

Parameter fill_flags are the gapfilling flags of the given constraint system, parameter known_flags is expected to contain the solved fill_flags for the solution that is to be avoided.

source

Knockout models

COBREXA.gene_knockout_constraintsMethod
gene_knockout_constraints(
+

Produce a constraint that can be added to the system made by gap_filling_constraints to avoid repeating of a solution that includes reactions already generated by another solution, as represented by the solved fill_flags.

Parameter fill_flags are the gapfilling flags of the given constraint system, parameter known_flags is expected to contain the solved fill_flags for the solution that is to be avoided.

source

Knockout models

COBREXA.gene_knockout_constraintsMethod
gene_knockout_constraints(
     fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     knockout_genes,
     model::AbstractFBCModels.AbstractFBCModel
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Make a ConstraintTree that simulates a gene knockout of knockout_genes in the model and disables corresponding fluxes accordingly.

Keys of the fluxes must correspond to the reaction identifiers in the model.

knockout_genes may be any collection that support element tests using in. Since the test is done many times, a Set is a preferred contained for longer lists of genes.

All constraints are equality constraints returned in a single flat ConstraintTree.

source
COBREXA.gene_knockout_constraintsMethod
gene_knockout_constraints(
+

Make a ConstraintTree that simulates a gene knockout of knockout_genes in the model and disables corresponding fluxes accordingly.

Keys of the fluxes must correspond to the reaction identifiers in the model.

knockout_genes may be any collection that support element tests using in. Since the test is done many times, a Set is a preferred contained for longer lists of genes.

All constraints are equality constraints returned in a single flat ConstraintTree.

source
COBREXA.gene_knockout_constraintsMethod
gene_knockout_constraints(
     fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},
     knockout_gene::String,
     model::AbstractFBCModels.AbstractFBCModel
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Convenience overload of gene_knockout_constraints for knocking out a single gene (without the necessity to store the gene identifier in a singleton container).

source
COBREXA.gene_knockoutsFunction
gene_knockouts(model::AbstractFBCModels.AbstractFBCModel)
+

Convenience overload of gene_knockout_constraints for knocking out a single gene (without the necessity to store the gene identifier in a singleton container).

source
COBREXA.gene_knockoutsFunction
gene_knockouts(model::AbstractFBCModels.AbstractFBCModel)
 gene_knockouts(
     model::AbstractFBCModels.AbstractFBCModel,
     gene_combinations::Vector{<:Union{String, Tuple{Vararg{String, N}} where N}};
     kwargs...
 )
-

Compute the objective value of the model for all knockouts specified by gene_combinations, which is a vector of gene IDs or tuples of gene IDs that are knocked out in groups.

Returns a vector in the same order as gene_combinations.

Extra arguments (mainly, the optimizer) are forwarded to screen_optimization_model.

source

Loopless flux balance analysis

COBREXA.loopless_flux_balance_analysisMethod
loopless_flux_balance_analysis(
+

Compute the objective value of the model for all knockouts specified by gene_combinations, which is a vector of gene IDs or tuples of gene IDs that are knocked out in groups.

Returns a vector in the same order as gene_combinations.

Extra arguments (mainly, the optimizer) are forwarded to screen_optimization_model.

source

Loopless flux balance analysis

COBREXA.loopless_flux_balance_analysisMethod
loopless_flux_balance_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 )
-

Perform the loopless flux balance analysis on the model, returning the solved constraint system.

Arguments are forwarded to loopless_flux_balance_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.

source
COBREXA.loopless_flux_balance_constraintsMethod
loopless_flux_balance_constraints(
+

Perform the loopless flux balance analysis on the model, returning the solved constraint system.

Arguments are forwarded to loopless_flux_balance_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.

source
COBREXA.loopless_flux_balance_constraintsMethod
loopless_flux_balance_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     flux_infinity_bound,
     driving_force_nonzero_bound,
     driving_force_infinity_bound
 ) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}
-

Construct a flux-balance constraint system from model with added quasi-thermodynamic constraints that ensure that thermodynamically infeasible internal cycles can not occur. The method is closer described by: Schellenberger, Lewis, and, Palsson. "Elimination of thermodynamically infeasible loops in steady-state metabolic models.", Biophysical journal, 2011`.

The loopless condition comes with a performance overhead: the computation needs to find the null space of the stoichiometry matrix (essentially inverting it); and the subsequently created optimization problem contains binary variables for each internal reaction, thus requiring a MILP solver and a potentially exponential solving time.

Internally, the system is constructed by combining flux_balance_constraints and loopless_constraints.

The arguments driving_force_max_bound and driving_force_nonzero_bound set the bounds (possibly negated ones) on the virtual "driving forces" (G_i in the paper).

source

Max-Min Driving Force analysis

COBREXA.max_min_driving_force_analysisMethod
max_min_driving_force_analysis(
+

Construct a flux-balance constraint system from model with added quasi-thermodynamic constraints that ensure that thermodynamically infeasible internal cycles can not occur. The method is closer described by: Schellenberger, Lewis, and, Palsson. "Elimination of thermodynamically infeasible loops in steady-state metabolic models.", Biophysical journal, 2011`.

The loopless condition comes with a performance overhead: the computation needs to find the null space of the stoichiometry matrix (essentially inverting it); and the subsequently created optimization problem contains binary variables for each internal reaction, thus requiring a MILP solver and a potentially exponential solving time.

Internally, the system is constructed by combining flux_balance_constraints and loopless_constraints.

The arguments driving_force_max_bound and driving_force_nonzero_bound set the bounds (possibly negated ones) on the virtual "driving forces" (G_i in the paper).

source

Max-Min Driving Force analysis

COBREXA.max_min_driving_force_analysisMethod
max_min_driving_force_analysis(
     model::AbstractFBCModels.AbstractFBCModel;
     kwargs...
 )
-

Perform the max-min driving force analysis on the model, returning the solved constraint system.

Arguments are forwarded to max_min_driving_force_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.

source
COBREXA.max_min_driving_force_constraintsMethod
max_min_driving_force_constraints(
+

Perform the max-min driving force analysis on the model, returning the solved constraint system.

Arguments are forwarded to max_min_driving_force_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.

source
COBREXA.max_min_driving_force_constraintsMethod
max_min_driving_force_constraints(
     model::AbstractFBCModels.AbstractFBCModel;
     reaction_standard_gibbs_free_energies,
     reference_flux,
@@ -193,7 +193,7 @@
     R,
     reference_flux_atol
 )
-

Create max-min driving force constraint system from model, using the supplied reaction standard Gibbs free energies in reaction_standard_gibbs_free_energies.

The method is described by: Noor, et al., "Pathway thermodynamics highlights kinetic obstacles in central metabolism.", PLoS computational biology, 2014.

reference_flux sets the directions of each reaction in model. The scale of the values is not important, only the direction is examined (w.r.t. reference_flux_atol tolerance). Ideally, the supplied reference_flux should be completely free of internal cycles, which enables the thermodynamic consistency. To get the cycle-free flux, you can use loopless_flux_balance_analysis (computationally demanding, but gives thermodynamically consistent solutions), parsimonious_flux_balance_analysis or linear_parsimonious_flux_balance_analysis (which is computationally simple, but the consistency is not guaranteed).

Internally, log_concentration_constraints is used to lay out the base structure of the problem.

Following arguments are set optionally:

  • water_metabolites, proton_metabolites and ignored_metabolites allow to completely ignore constraints on a part of the metabolite set, which is explicitly recommended especially for water and protons (since the analyses generally assume aqueous environment of constant pH)
  • constant_concentrations can be used to fix the concentrations of the metabolites
  • concentration_lower_bound and concentration_upper_bound set the default concentration bounds for all other metabolites
  • concentration ratios is a dictionary that assigns a tuple of metabolite-metabolite-concentration ratio constraint names; e.g. ATP/ADP ratio can be fixed to five-times-more-ATP by setting concentration_ratios = Dict("adenosin_ratio" => ("atp", "adp", 5.0))
  • T and R default to the usual required thermodynamic constraints in the expected units (the defaults assume the "usual" units, valuing 298.15 K and ~0.008314 kJ/K/mol, respectively). These multiply the log-concentrations to obtain the actual Gibbs energies, and thus driving forces.
source

Sampling

COBREXA.flux_sampleMethod
flux_sample(
+

Create max-min driving force constraint system from model, using the supplied reaction standard Gibbs free energies in reaction_standard_gibbs_free_energies.

The method is described by: Noor, et al., "Pathway thermodynamics highlights kinetic obstacles in central metabolism.", PLoS computational biology, 2014.

reference_flux sets the directions of each reaction in model. The scale of the values is not important, only the direction is examined (w.r.t. reference_flux_atol tolerance). Ideally, the supplied reference_flux should be completely free of internal cycles, which enables the thermodynamic consistency. To get the cycle-free flux, you can use loopless_flux_balance_analysis (computationally demanding, but gives thermodynamically consistent solutions), parsimonious_flux_balance_analysis or linear_parsimonious_flux_balance_analysis (which is computationally simple, but the consistency is not guaranteed).

Internally, log_concentration_constraints is used to lay out the base structure of the problem.

Following arguments are set optionally:

  • water_metabolites, proton_metabolites and ignored_metabolites allow to completely ignore constraints on a part of the metabolite set, which is explicitly recommended especially for water and protons (since the analyses generally assume aqueous environment of constant pH)
  • constant_concentrations can be used to fix the concentrations of the metabolites
  • concentration_lower_bound and concentration_upper_bound set the default concentration bounds for all other metabolites
  • concentration ratios is a dictionary that assigns a tuple of metabolite-metabolite-concentration ratio constraint names; e.g. ATP/ADP ratio can be fixed to five-times-more-ATP by setting concentration_ratios = Dict("adenosin_ratio" => ("atp", "adp", 5.0))
  • T and R default to the usual required thermodynamic constraints in the expected units (the defaults assume the "usual" units, valuing 298.15 K and ~0.008314 kJ/K/mol, respectively). These multiply the log-concentrations to obtain the actual Gibbs energies, and thus driving forces.
source

Sampling

COBREXA.flux_sampleMethod
flux_sample(
     model::AbstractFBCModels.AbstractFBCModel;
     seed,
     objective_bound,
@@ -205,4 +205,4 @@
     workers,
     kwargs...
 )
-

Run a sampling algorithm on the near-optimal feasible space of the model (as specified by objective_bound). By default, the sampling algorithm is ACHR (the method parameter is defaulted to sample_chain_achr). The sampling algorithm is ran for n_chains and the iterations for collecting the sampled values are specified by collect_iterations.

optimizer is used to generate the warmup (with settings) for the sampler using the usual unidimensional maximum-variability fluxes (as from flux_variability_analysis). All computations are parallelized across workers.

Extra arguments are forwarded to sample_constraints. Eventually the arguments will reach the method function, so extra arguments can be also used to customize the methods (e.g., by setting the epsilon for the ACHR sampler).

source
+

Run a sampling algorithm on the near-optimal feasible space of the model (as specified by objective_bound). By default, the sampling algorithm is ACHR (the method parameter is defaulted to sample_chain_achr). The sampling algorithm is ran for n_chains and the iterations for collecting the sampled values are specified by collect_iterations.

optimizer is used to generate the warmup (with settings) for the sampler using the usual unidimensional maximum-variability fluxes (as from flux_variability_analysis). All computations are parallelized across workers.

Extra arguments are forwarded to sample_constraints. Eventually the arguments will reach the method function, so extra arguments can be also used to customize the methods (e.g., by setting the epsilon for the ACHR sampler).

source diff --git a/dev/reference/index.html b/dev/reference/index.html index 519fd168..661a8863 100644 --- a/dev/reference/index.html +++ b/dev/reference/index.html @@ -1,2 +1,2 @@ -Contents · COBREXA.jl

API reference

+Contents · COBREXA.jl

API reference

diff --git a/dev/reference/misc/index.html b/dev/reference/misc/index.html index c88e28b4..0128a63b 100644 --- a/dev/reference/misc/index.html +++ b/dev/reference/misc/index.html @@ -1,29 +1,29 @@ Miscellaneous functions · COBREXA.jl

Miscellaneous functions

COBREXA.absolute_tolerance_boundMethod
absolute_tolerance_bound(tolerance) -> COBREXA.var"#404#405"
-

Make a function that returns absolute tolerance bounds, i.e. value - tolerance and value + tolerance in a tuple, in the increasing order.

source
COBREXA.relative_tolerance_boundMethod
relative_tolerance_bound(tolerance) -> COBREXA.var"#406#407"
-

Make a function that returns relative tolerance bounds, i.e. value / tolerance and value * tolerance in a tuple, in the increasing order.

source
COBREXA.remove_boundsMethod
remove_bounds(
+

Make a function that returns absolute tolerance bounds, i.e. value - tolerance and value + tolerance in a tuple, in the increasing order.

source
COBREXA.relative_tolerance_boundMethod
relative_tolerance_bound(tolerance) -> COBREXA.var"#406#407"
+

Make a function that returns relative tolerance bounds, i.e. value / tolerance and value * tolerance in a tuple, in the increasing order.

source
COBREXA.remove_boundsMethod
remove_bounds(
     cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}
 ) -> Any
-

Make a copy of a constraint tree with all bounds removed. This is helpful when creating large trees only for for value representation purposes, which should not directly constraint anything (and thus should not put additional stress on the constraint solver).

source
COBREXA.maybemapFunction
maybemap(f, ::Nothing)
+

Make a copy of a constraint tree with all bounds removed. This is helpful when creating large trees only for for value representation purposes, which should not directly constraint anything (and thus should not put additional stress on the constraint solver).

source
COBREXA.maybemapFunction
maybemap(f, ::Nothing)
 maybemap(f, ::Nothing, def) -> Any
-

Helper for applying functions to stuff that might be nothing.

source
COBREXA.set_optimizerMethod
set_optimizer(optimizer) -> COBREXA.var"#412#413"
-

Change the JuMP optimizer used to run the optimization.

source
COBREXA.set_optimizerMethod
set_optimizer(optimizer) -> COBREXA.var"#412#413"
+

Change the JuMP optimizer used to run the optimization.

source
COBREXA.set_optimizer_attributeMethod
set_optimizer_attribute(
     attribute_key,
     value
 ) -> COBREXA.var"#414#415"
-

Change a named JuMP optimizer attribute. The attribute names are optimizer-specific, refer to the JuMP documentation and the documentation of the specific optimizer for usable keys and values.

source
COBREXA.set_time_limitMethod
set_time_limit(limit::Real) -> COBREXA.var"#416#417"
-

Set a time limit in seconds for the optimizer computation (shortcut for set_time_limit_sec from JuMP).

source
COBREXA.silenceMethod
silence

Disable all output from the JuMP optimizer (shortcut for set_silent from JuMP).

source
COBREXA.unsilenceMethod
unsilence

Enable output from the JuMP optimizer (shortcut for unset_silent from JuMP).

source
COBREXA.tree_deflateMethod
tree_deflate(f, x::ConstraintTrees.Tree{T}) -> Vector
+

Change a named JuMP optimizer attribute. The attribute names are optimizer-specific, refer to the JuMP documentation and the documentation of the specific optimizer for usable keys and values.

source
COBREXA.set_time_limitMethod
set_time_limit(limit::Real) -> COBREXA.var"#416#417"
+

Set a time limit in seconds for the optimizer computation (shortcut for set_time_limit_sec from JuMP).

source
COBREXA.silenceMethod
silence

Disable all output from the JuMP optimizer (shortcut for set_silent from JuMP).

source
COBREXA.unsilenceMethod
unsilence

Enable output from the JuMP optimizer (shortcut for unset_silent from JuMP).

source
COBREXA.tree_deflateMethod
tree_deflate(f, x::ConstraintTrees.Tree{T}) -> Vector
 tree_deflate(
     f,
     x::ConstraintTrees.Tree{T},
     ::Type{U}
 ) -> Vector
-

Extract all elements of a ConstraintTrees.Tree in order and return them in a Vector transformed by f. If the order is not modified, one can re-insert a vector of modified elements into the same-shaped tree using tree_reinflate.

source
COBREXA.tree_reinflateMethod
tree_reinflate(
+

Extract all elements of a ConstraintTrees.Tree in order and return them in a Vector transformed by f. If the order is not modified, one can re-insert a vector of modified elements into the same-shaped tree using tree_reinflate.

source
COBREXA.tree_reinflateMethod
tree_reinflate(
     x::ConstraintTrees.Tree,
     elems::Array{T, 1}
 ) -> ConstraintTrees.Tree
-

Insert a Vector of elements into the "values" of a ConstraintTrees.Tree. The order of elements is given by tree_deflate.

source
+

Insert a Vector of elements into the "values" of a ConstraintTrees.Tree. The order of elements is given by tree_deflate.

source diff --git a/dev/search_index.js b/dev/search_index.js index 2a3f7ecb..d4f1f7ef 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"reference/analysis/#Specialized-analysis-functions","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/solver.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.optimized_values-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.optimized_values","text":"optimized_values(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n settings,\n output,\n kwargs...\n)\n\n\nMake an JuMP model out of constraints using optimization_model (most arguments are forwarded there), then apply the settings, optimize the model, and return either nothing if the optimization failed, or output substituted with the solved values (output defaults to constraints.\n\nFor a \"nice\" version for simpler finding of metabolic model optima, use flux_balance_analysis.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Parsimonious-analyses","page":"Specialized analysis functions","title":"Parsimonious analyses","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/parsimonious.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.parsimonious_optimized_values-Tuple{Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}}}","page":"Specialized analysis functions","title":"COBREXA.parsimonious_optimized_values","text":"parsimonious_optimized_values(\n constraints::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};\n objective,\n objective_value,\n settings,\n parsimonious_objective,\n parsimonious_optimizer,\n parsimonious_sense,\n parsimonious_settings,\n tolerances,\n output,\n kwargs...\n)\n\n\nOptimize the system of constraints to get the optimal objective value. Then try to find a \"parsimonious\" solution with the same objective value, which optimizes the parsimonious_objective (possibly also switching optimization sense, optimizer, and adding more settings).\n\nFor efficiency, everything is performed on a single instance of JuMP model.\n\nA simpler version suitable for direct work with metabolic models is available in parsimonious_flux_balance_analysis.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Ensemble-solving","page":"Specialized analysis functions","title":"Ensemble solving","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/screen.jl\", \"src/analysis/variability.jl\", \"src/analysis/envelope.jl\" ]","category":"page"},{"location":"reference/analysis/#COBREXA.screen-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.screen","text":"screen(f, args...; workers) -> Any\n\n\nExecute a function with arguments given by args on workers.\n\nThis is merely a nice shortcut for Distributed.pmap running over a Distributed.CachingPool of the given workers.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.screen_optimization_model-Tuple{Any, ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.screen_optimization_model","text":"screen_optimization_model(\n f,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n args...;\n objective,\n sense,\n optimizer,\n settings,\n workers\n)\n\n\nExecute a function arguments from arrays args on workers, with a pre-cached JuMP optimization model created from constraints, objective and optimizer using optimization_model. settings are applied to the optimization model before first execution of f.\n\nSince the model is cached and never re-created, this may be faster than just plain screen in many use cases.\n\nThe function f is supposed to take length(args)+1 arguments, the first argument is the JuMP model, and the other arguments are taken from args as with Distributed.pmap. While the model may be modified in place, one should take care to avoid modifications that change results of subsequent invocations of f, as that almost always results in data races and irreproducible executions. Ideally, all modifications of the model should be either manually reverted in the invocation of f, or the future invocations of f must be able to overwrite them.\n\nf may use optimized_model to extract results easily w.r.t. some given ConstraintTree.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_variability-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.constraints_variability","text":"constraints_variability(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n targets::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n kwargs...\n)\n\n\nSimplified variant of constraints_variability that computes the variability of all values in tree targets, and returns a new tree of the same shape as targets that contains tuples for minima and maxima.\n\nAll other arguments are forwarded to the matrix-returning overload of constraints_variability.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_variability-Union{Tuple{T}, Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vector{<:ConstraintTrees.Value}}} where T","page":"Specialized analysis functions","title":"COBREXA.constraints_variability","text":"constraints_variability(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n targets::Vector{<:ConstraintTrees.Value};\n output,\n output_type,\n kwargs...\n)\n\n\nIn a feasible space specified by constraints, compute the feasible range of individual targets values. The output is a matrix with one column for minima and second column for maxima of the individual target's values.\n\nThis is used e.g. to compute the flux_variability_analysis, and can be viewed as a more generalized version thereof.\n\noutput and output_type can be used to customize the information reported from the solved models.\n\nExtra arguments are passed to screen_optimization_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_objective_envelope-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.constraints_objective_envelope","text":"constraints_objective_envelope(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n dims...;\n objective,\n sense,\n optimizer,\n settings,\n workers\n)\n\n\nOptimize the system given by constraints and objective with optimizer (with custom settings) for all combination of constriants given by dims.\n\ndims should be compatible with pairs that assign a sequence of breaks to a ConstraintTrees.Value: For example, organism.fluxes.PFK => 1:3 will compute optima of the model with the flux through PFK constrained to be equal to 1, 2 and 3.\n\nIn turn, all dims are converted to groups of equality constraints, and the model is solved for all combinations. Shape of the output matrix corresponds to Iterators.product(last.(dims)...).\n\nOperation is parallelized by distribution over workers; by default all Distributed.workers() are used.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Sampling","page":"Specialized analysis functions","title":"Sampling","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/sample.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.sample_chain_achr-Union{Tuple{SM}, Tuple{M}, Tuple{V}, Tuple{F}} where {F<:Real, V<:AbstractVector{F}, M<:AbstractMatrix{F}, SM<:AbstractMatrix{F}}","page":"Specialized analysis functions","title":"COBREXA.sample_chain_achr","text":"sample_chain_achr(\n sample_c::AbstractArray{F<:Real, 2};\n variable_lower_bounds,\n variable_upper_bounds,\n coupling,\n lower_bounds,\n upper_bounds,\n epsilon,\n collect_iterations,\n generator\n)\n\n\nImplementation of a single chain run for the Artificially-Centered Hit and Run algorithm (ACHR).\n\nTo use this on a model, use flux_sample or sample_constraints; most parameters are filled in correctly by these functions.\n\nepsilon is defaulted from configuration.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.sample_constraint_variables-Tuple{Function, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.sample_constraint_variables","text":"sample_constraint_variables(\n sampler::Function,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n start_variables,\n seed,\n workers,\n n_chains,\n kwargs...\n)\n\n\nSample the feasible space constrained by constraints by sampling algorithm sampler, using the start_variables as a \"warm-up\" for the sampling runs. Random values are derived from the seed. Computation of individual n_chains chains by sampler is parallelized over workers using screen. Extra arguments are passed to sampler.\n\nThis function returns a matrix of the samples (one sample per row). To nicely aggregate the statistics in the constraint tree, use sample_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.sample_constraints-Union{Tuple{T}, Tuple{Function, ConstraintTrees.Tree{ConstraintTrees.Constraint}}} where T","page":"Specialized analysis functions","title":"COBREXA.sample_constraints","text":"sample_constraints(\n sampler::Function,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n output,\n aggregate,\n aggregate_type,\n kwargs...\n)\n\n\nA front-end for sample_constraint_variables that saves the sampling results in a constraint tree of the same shape as output. Additionally, aggregate function and aggregate_type can be specified to customize the output.\n\nAll other parameters are forwarded to sample_constraint_variables.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Analysis-front-end-API-helpers","page":"Specialized analysis functions","title":"Analysis front-end API helpers","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/frontend.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.frontend_optimized_values-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.frontend_optimized_values","text":"frontend_optimized_values(\n builder,\n args...;\n builder_kwargs,\n objective,\n output,\n sense,\n optimizer,\n settings,\n kwargs...\n)\n\n\nA helper that converts a front-end constraint builder function (the output of which would normally be just passed through optimized_values) to front-end analysis function.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.frontend_parsimonious_optimized_values-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.frontend_parsimonious_optimized_values","text":"frontend_parsimonious_optimized_values(\n builder,\n args...;\n builder_kwargs,\n objective,\n objective_value,\n output,\n sense,\n optimizer,\n settings,\n parsimonious_objective,\n parsimonious_optimizer,\n parsimonious_sense,\n parsimonious_settings,\n tolerances,\n kwargs...\n)\n\n\nA helper that converts a parsimonious-style front-end constraint builder function to front-end analysis function.\n\nLike frontend_optimized_values, but internally calls parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"EditURL = \"06b-screening.jl\"","category":"page"},{"location":"examples/06b-screening/#Screening-through-many-model-variants","page":"Screening through many model variants","title":"Screening through many model variants","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen is a function that you can use to run many different simulations on many different variants of the model efficiently in parallel.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nimport ConstraintTrees as C\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Screening is done as follows: We specify a range of values to examine (in the example below to an actual range of -10 to 0), but any vector-like list of things can be used), and write a short \"analysis\" function that takes one of the values from the range as an argument and runs an analysis for that given value.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Here, we solve 11 different optimization problems for different bounds of the oxygen exchange:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(-10:0) do o2_bound\n c = flux_balance_constraints(model)\n c.fluxes.EX_o2_e.bound = C.EqualTo(o2_bound)\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Screening-in-multiple-dimensions","page":"Screening through many model variants","title":"Screening in multiple dimensions","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"The simplest way to screen through multi-dimensional arrays is to use an iterator product. In the result, we receive a whole matrix of results instead of a vector.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(Iterators.product(-10:2:0, 0:2:10)) do (o2_bound, co2_bound)\n c = flux_balance_constraints(model)\n c.fluxes.EX_o2_e.bound = C.EqualTo(o2_bound)\n c.fluxes.EX_co2_e.bound = C.EqualTo(co2_bound)\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Screening-through-non-numeric-properties","page":"Screening through many model variants","title":"Screening through non-numeric properties","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"If the problem at hand can not be expressed with mere ranges, we can specify vectors with any values. The following code examines the inter-dependency of blocking selected transport reactions together with selected exchanges, with 2 different bounds that implement the block. Because of 3-dimensional input, the result is expectably a 3-dimensional array:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(\n Iterators.product(\n [:H2Ot, :CO2t, :O2t, :NH4t], # a set of transport reactions\n [:EX_h2o_e, :EX_co2_e, :EX_o2_e, :EX_nh4_e], # a set of exchanges\n [C.Between(-0.1, 0.1), C.Between(-1, 1)], # bounds\n ),\n) do (transport, exchange, bound)\n c = flux_balance_constraints(model)\n c.fluxes[transport].bound = 5 * bound\n c.fluxes[exchange].bound = 3 * bound\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Annotating-the-results","page":"Screening through many model variants","title":"Annotating the results","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"For reasons of tidyness, it is adviseable to annotate all values with their actual meaning directly in the arrays.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"With screen, the simplest (and usually sufficiently effective) way to do that is to return Pairs with annotation keys instead of plain values:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(\n Iterators.product(\n [:H2Ot, :CO2t, :O2t, :NH4t],\n [:EX_h2o_e, :EX_co2_e, :EX_o2_e, :EX_nh4_e],\n [C.Between(-0.1, 0.1), C.Between(-1, 1)],\n ),\n) do (transport, exchange, bound)\n c = flux_balance_constraints(model)\n c.fluxes[transport].bound = 5 * bound\n c.fluxes[exchange].bound = 3 * bound\n (transport, exchange, bound.upper) => optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Notably, this approach makes various indexing and ordering errors quite improbable.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/frontend/#Front-end-user-interface","page":"Front-end user interface","title":"Front-end user interface","text":"","category":"section"},{"location":"reference/frontend/#Flux-balance-analysis","page":"Front-end user interface","title":"Flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/balance.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_balance_analysis","text":"flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nCompute an optimal objective-optimizing solution of the given model.\n\nMost arguments are forwarded to optimized_values.\n\nReturns a tree with the optimization solution of the same shape as given by flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_balance_constraints","text":"flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n interface,\n interface_name\n) -> Any\n\n\nA constraint tree that models the content of the given instance of AbstractFBCModel.\n\nThe constructed tree contains subtrees fluxes (with the reaction-defining \"variables\") and flux_stoichiometry (with the metabolite-balance-defining constraints), and a single constraint objective thad describes the objective function of the model.\n\nOptionally if interface is specified, an \"interface block\" will be created within the constraint tree for later use as a \"module\" in creating bigger models (such as communities) using interface_constraints. The possible parameter values include:\n\nnothing – default, no interface is created\n:sbo – the interface gets created from model's SBO annotations)\n:identifier_prefixes – the interface is guesstimated from commonly occurring adhoc reaction ID prefixes used in contemporary models\n:boundary – the interface is created from all reactions that either only consume or only produce metabolites\n\nOutput interface name can be set via interface_name.\n\nSee Configuration for fine-tuning the default interface creation.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Flux-variability-analysis","page":"Front-end user interface","title":"Flux variability analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/variability.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_variability_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_variability_analysis","text":"flux_variability_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n objective_bound,\n reactions,\n optimizer,\n settings,\n workers\n)\n\n\nPerform a Flux Variability Analysis (FVA) on the model, and return a dictionary of flux ranges where the model is able to perform optimally.\n\nThe constraint system is constructed using flux_balance_constraints, and the variability is examined on all reaction's fluxes, or on the subset given optionally in reaction_subset (e.g., reaction_subset = [\"PFK\", \"ACALD\"]). The optimality tolerance can be specified with objective_bound using e.g. relative_tolerance_bound or absolute_tolerance_bound; the default is 99% relative tolerance.\n\nParameter workers may be used to enable parallel or distributed processing; the execution defaults to all available workers. Other parameters (esp. optimizer) are internally forwarded to optimized_values.\n\nUse constraints_variability to customize the FVA execution.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Parsimonious-flux-balance-analysis","page":"Front-end user interface","title":"Parsimonious flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/parsimonious.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.linear_parsimonious_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_parsimonious_flux_balance_analysis","text":"linear_parsimonious_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n tolerances,\n kwargs...\n)\n\n\nLike parsimonious_flux_balance_analysis, but uses the L1-metric parsimonious system given by linear_parsimonious_flux_balance_constraints.\n\nIn turn, the solution is often faster, does not require a solver capable of quadratic objectives, and has many beneficial properties of the usual parsimonious solutions (such as the general lack of unnecessary loops). On the other hand, like with plain flux balance analysis there is no strong guarantee of uniqueness of the solution.\n\nSolver configuration arguments are forwarded to parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_parsimonious_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_parsimonious_flux_balance_constraints","text":"linear_parsimonious_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> ConstraintTrees.Tree\n\n\nLike parsimonious_flux_balance_constraints, but uses a L1 metric for solving the parsimonious problem. The parsimonious_objective constraint is thus linear.\n\nKeyword arguments are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.parsimonious_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.parsimonious_flux_balance_analysis","text":"parsimonious_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n tolerances,\n kwargs...\n)\n\n\nCompute a parsimonious flux solution for the model, using the constraints given by parsimonious_flux_balance_constraints.\n\nIn short, the objective value of the parsimonious solution should be the same as the one from flux_balance_analysis, except the squared sum of reaction fluxes is minimized. If there are multiple possible fluxes that achieve a given objective value, parsimonious flux thus represents the \"minimum energy\" one, which is arguably more realistic.\n\nSolver configuration arguments are forwarded to parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.parsimonious_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.parsimonious_flux_balance_constraints","text":"parsimonious_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Any\n\n\nA constraint system like from flux_balance_constraints, but with the parsimonious objective present under key parsimonious_objective. Best used via parsimonious_flux_balance_analysis.\n\nKeyword arguments are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Minimization-of-metabolic-adjustment","page":"Front-end user interface","title":"Minimization of metabolic adjustment","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/moma.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_analysis-Tuple{AbstractFBCModels.AbstractFBCModel, Vararg{Any}}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_analysis","text":"linear_metabolic_adjustment_minimization_analysis(\n model::AbstractFBCModels.AbstractFBCModel,\n args...;\n optimizer,\n settings,\n reference_parsimonious_optimizer,\n reference_parsimonious_settings,\n reference_optimizer,\n reference_settings,\n kwargs...\n)\n\n\nPerform a linear minimization of metabolic adjustment analysis (l-MOMA) on model. The reference is given by the second argument, which is either a reference_flux or a reference_model (the second argument is forwarded to linear_metabolic_adjustment_minimization_constraints).\n\nWhile the solution is \"less uniquely defined\" than with fully quadratic metabolic_adjustment_minimization_analysis, the linear variant typically produces a sufficiently good result with much less resources. See documentation of linear_parsimonious_flux_balance_analysis for some of the considerations.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_constraints","text":"linear_metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Union{Nothing, ConstraintTrees.Tree}\n\n\nLike metabolic_adjustment_minimization_constraints but the output constraints optimize the L1 distance from the linear-parsimonious solution of the reference_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, ConstraintTrees.Tree}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_constraints","text":"linear_metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_fluxes::ConstraintTrees.Tree;\n _...\n) -> ConstraintTrees.Tree\n\n\nLike metabolic_adjustment_minimization_constraints but optimizes the L1 distance from reference_fluxes.\n\nKeyword arguments are discarded for compatibility with the other overload.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_analysis-Tuple{AbstractFBCModels.AbstractFBCModel, Vararg{Any}}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_analysis","text":"metabolic_adjustment_minimization_analysis(\n model::AbstractFBCModels.AbstractFBCModel,\n args...;\n optimizer,\n settings,\n reference_parsimonious_optimizer,\n reference_parsimonious_settings,\n reference_optimizer,\n reference_settings,\n kwargs...\n)\n\n\nFind a solution of the \"minimization of metabolic adjustment\" (MOMA) analysis for the model, which is the \"closest\" feasible solution to the solution given in the second argument, which is either reference_fluxes or reference_model (see documentation of metabolic_adjustment_minimization_constraints), in the sense of squared-sum distance. The minimized squared distance (the objective) is present in the result tree as minimal_adjustment_objective.\n\nIf the second argument is a reference model, it is solved using a parsimonious_flux_balance_analysis with the optimizer and settings parameters for the 2 steps set by keyword arguments prefixed by reference_.\n\nThis is often used for models with smaller feasible region than the reference models (typically handicapped by a knockout, a nutritional deficiency or a similar perturbation). MOMA solution then gives an expectable \"easiest\" adjustment of the organism towards a somewhat working state.\n\nReference fluxes that do not exist in the model are ignored (internally, the objective is constructed via squared_sum_error_value).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_constraints","text":"metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Any\n\n\nA slightly easier-to-use version of metabolic_adjustment_minimization_constraints that computes the reference flux as the parsimonious optimal solution of the reference_model. The reference flux is calculated using reference_optimizer and reference_modifications, which default to the optimizer and settings.\n\nOther arguments are forwarded to the internal call of parsimonious_optimized_values.\n\nReturns nothing if no feasible solution is found.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, ConstraintTrees.Tree}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_constraints","text":"metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_fluxes::ConstraintTrees.Tree;\n _...\n) -> Any\n\n\nKeyword arguments are discarded for compatibility with the other overload.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Constraint-systems-for-metabolite-concentrations","page":"Front-end user interface","title":"Constraint systems for metabolite concentrations","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/concentrations.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.log_concentration_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.log_concentration_constraints","text":"log_concentration_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reactions,\n metabolites,\n metabolite_concentration_bound,\n reaction_concentration_bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nBuild log-concentration-stoichiometry constraints for the model, as used e.g. by max_min_driving_force_analysis.\n\nThe output constraint tree contains a log-concentration variable for each metabolite from model, in subtree log_concentrations. The total reactant log-concentrations for each reaction are constrained in subtree log_concentration_stoichiometry. By default, all reactions and metabolites in model are included.\n\nA concentration bound is given by parameter function concentration_bound for each metabolite ID (the string ID is the single argument of the function); by default the function returns nothing and no bounds are installed. The same is used for reactions with reaction_concentration_bound.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Enzyme-mass-constrained-models","page":"Front-end user interface","title":"Enzyme-mass-constrained models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/enzymes.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.Isozyme","page":"Front-end user interface","title":"COBREXA.Isozyme","text":"mutable struct Isozyme\n\nA simple struct storing information about the isozyme composition, including subunit stoichiometry and turnover numbers. Use with enzyme_constrained_flux_balance_analysis.\n\nFields\n\ngene_product_stoichiometry::Dict{String, Float64}: Mapping of gene product identifiers (\"genes\" in FBC model nomenclature) to their relative amount required to construct one unit of the isozyme.\n\nkcat_forward::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the forward direction of the reaction.\nkcat_reverse::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the reverse direction of the reaction.\n\n\n\n\n\n","category":"type"},{"location":"reference/frontend/#COBREXA.enzyme_constrained_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.enzyme_constrained_flux_balance_analysis","text":"enzyme_constrained_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.\n\nArguments are forwarded to enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.enzyme_constrained_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.enzyme_constrained_flux_balance_constraints","text":"enzyme_constrained_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reaction_isozymes,\n gene_product_molar_masses,\n capacity,\n interface,\n interface_name\n)\n\n\nConstruct a enzyme-constrained flux-balance constraint system, following the method in GECKO algorithm (refer to: Sánchez, Benjamín J., et al. \"Improving the phenotype predictions of a yeast genome‐scale metabolic model by incorporating enzymatic constraints.\" Molecular systems biology 13.8 (2017): 935).\n\nThe enzyme mass constraints depend primarily on the available isozymes, given in parameter reaction_isozymes, which is a mapping of reaction identifiers to descriptions of Isozymes that may catalyze the particular reactions. The isozymes are built from gene products, the mass of which is specified by gene_product_molar_masses. In total, the amount of gene product building material is limited by capacity.\n\ncapacity may be a single number, which sets the mass limit for \"all described enzymes\". Alternatively, capacity may be a vector of identifier-genes-limit triples that together form a constraint (identified by the given identifier) that limits the total sum of the listed genes to the given limit.\n\ninterface and interface_name are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.simplified_enzyme_constrained_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.simplified_enzyme_constrained_flux_balance_analysis","text":"simplified_enzyme_constrained_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.\n\nArguments are forwarded to simplified_enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.simplified_enzyme_constrained_flux_balance_constraints-Tuple{Any}","page":"Front-end user interface","title":"COBREXA.simplified_enzyme_constrained_flux_balance_constraints","text":"simplified_enzyme_constrained_flux_balance_constraints(\n model;\n reaction_isozymes,\n gene_product_molar_masses,\n capacity,\n interface,\n interface_name\n)\n\n\nLike enzyme_constrained_flux_balance_constraints, but automatically selects a single \"fastest\" isozyme for each reaction direction. In turn, the system requires much less variables in the constraint system description, and usually solves more efficiently, for the price of possibly finding suboptimal solutions. The method follows the SMOMENT algorithm described in Bekiaris, P.S., Klamt, S. Automatic construction of metabolic models with enzyme constraints. BMC Bioinformatics 21, 19 (2020). https://doi.org/10.1186/s12859-019-3329-9.\n\nArguments are as with enzyme_constrained_flux_balance_constraints, with a major difference in capacity handling: the identifier lists (2nd elements of the triples given in the list) are not identifiers of gene products, but identifiers of reactions.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Community-models","page":"Front-end user interface","title":"Community models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/community.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.community_flux_balance_analysis-Tuple","page":"Front-end user interface","title":"COBREXA.community_flux_balance_analysis","text":"community_flux_balance_analysis(args...; kwargs...)\n\n\nRun the Community Flux Balance Analysis on several models. All arguments are forwarded to community_flux_balance_constraints which constructs the model; this function returns the solved model.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.community_flux_balance_constraints-Tuple{Any, Any}","page":"Front-end user interface","title":"COBREXA.community_flux_balance_constraints","text":"community_flux_balance_constraints(\n model_abundances,\n community_exchange_bounds;\n interface,\n interface_exchanges,\n interface_biomass,\n default_community_exchange_bound\n) -> Any\n\n\nConstruct an instance of a linear community Flux Balance Analysis (cFBA) model. The relative abundances of the organisms are known in advance; this function predicts the maximum achievable community growth rate.\n\nmodel_abundances is a dictionary-like object that maps model identifiers to tuples of models (usually subtypes of AbstractFBCModel) and their abundances (such as: \"bug1\" => (bug1, 0.5), ...). community_exchange_bounds is a dictionary-like object that can be additionally used to restrict selected community exchange reactions (keys should be reaction IDs, the values are converted to ConstraintTrees-like bounds). Bounds otherwise default to parameter default_community_exchange_bound, which itself defaults to nothing (i.e., unbounded).\n\nIf required, constraint trees may be supplied instead of AbstracFBCModels in model_abundances. These must provide an interface compatible with interface_exchanges and interface_biomass.\n\ninterface is forwarded to flux_balance_constraints. interface_exchanges and interface_biomass are used to pick up the correct interface part to contribute to the community exchanges and community biomass.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Production-envelopes","page":"Front-end user interface","title":"Production envelopes","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/envelope.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.objective_production_envelope-Tuple{AbstractFBCModels.AbstractFBCModel, Vector{String}}","page":"Front-end user interface","title":"COBREXA.objective_production_envelope","text":"objective_production_envelope(\n model::AbstractFBCModels.AbstractFBCModel,\n reactions::Vector{String};\n breaks,\n optimizer,\n settings,\n workers\n)\n\n\nFind the objective production envelope of the model in the dimensions given by reactions.\n\nThis runs a variability analysis of the fluxes given by flux_balance_constraints to determine an applicable range for the dimensions, then splits the dimensions to equal-sized breaks (of count breaks for each dimension, i.e. total breaks ^ length(reactions) individual \"multidimensional breaks\") thus forming a grid, and returns an array of fluxes through the model objective with the individual reactions fixed to flux as given by the grid.\n\noptimizer and settings are used to construct the optimization models.\n\nThe computation is distributed to the specified workers, defaulting to all available workers.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Gap-filling","page":"Front-end user interface","title":"Gap-filling","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/gapfill.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.gap_filling_analysis-Tuple","page":"Front-end user interface","title":"COBREXA.gap_filling_analysis","text":"gap_filling_analysis(args...; kwargs...)\n\n\nRun the gap-filling analysis on a constraint system specified by gap_filling_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel, Float64}","page":"Front-end user interface","title":"COBREXA.gap_filling_constraints","text":"gap_filling_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n universal_model::AbstractFBCModels.AbstractFBCModel,\n objective_target::Float64;\n universal_reaction_cost,\n max_cost,\n known_fills,\n kwargs...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a gap-filling system from a FBC model with gaps and an universal FBC model that contains reactions to be added into the original model.\n\nThe output system will be constrainted to reach at least objective_target flux through the objective function. Generally, this should be set to an arbitrary small value such as 0.05.\n\nuniversal_reaction_cost should assign a numeric cost of inclusion of each of the reactions in the universal_model; by default all are assigned equal weight of 1. max_cost puts an optional maximum limit on the cost, which may help the solver to avoid exploring unnecessarily complex solutions. known_fills may contain previous solutions of the same system; these will be made infeasible in the output constraint system in order to allow discovery of other ones.\n\nAdditional arguments are forwarded to flux_balance_constraints that converts model to constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_constraints-Tuple{}","page":"Front-end user interface","title":"COBREXA.gap_filling_constraints","text":"gap_filling_constraints(\n;\n system,\n stoichiometry,\n universal_fluxes,\n universal_stoichiometry,\n flux_cost,\n max_cost,\n known_fills\n)\n\n\nMake a gap-fillign system from a non-solving system with a separated stoichiometry, filling in possible fluxes from universal_fluxes that are balanced with universal_stoichiometry\n\nflux_cost can be used to assign a weight to each given universal flux; the total cost is bounded by max_cost.\n\nknown_fills may contain previous solutions to be avoided; these are processed by gap_filling_known_fill_constraint and attached to the system.\n\nstoichiometry needs to be extended to construct the final constraints, thus it should not be present in the original system.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_known_fill_constraint-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{Float64}}","page":"Front-end user interface","title":"COBREXA.gap_filling_known_fill_constraint","text":"gap_filling_known_fill_constraint(\n fill_flags::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n known_flags::ConstraintTrees.Tree{Float64}\n) -> ConstraintTrees.Constraint\n\n\nProduce a constraint that can be added to the system made by gap_filling_constraints to avoid repeating of a solution that includes reactions already generated by another solution, as represented by the solved fill_flags.\n\nParameter fill_flags are the gapfilling flags of the given constraint system, parameter known_flags is expected to contain the solved fill_flags for the solution that is to be avoided.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Knockout-models","page":"Front-end user interface","title":"Knockout models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/knockout.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.gene_knockout_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.gene_knockout_constraints","text":"gene_knockout_constraints(\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n knockout_genes,\n model::AbstractFBCModels.AbstractFBCModel\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a ConstraintTree that simulates a gene knockout of knockout_genes in the model and disables corresponding fluxes accordingly.\n\nKeys of the fluxes must correspond to the reaction identifiers in the model.\n\nknockout_genes may be any collection that support element tests using in. Since the test is done many times, a Set is a preferred contained for longer lists of genes.\n\nAll constraints are equality constraints returned in a single flat ConstraintTree.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gene_knockout_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, String, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.gene_knockout_constraints","text":"gene_knockout_constraints(\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n knockout_gene::String,\n model::AbstractFBCModels.AbstractFBCModel\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nConvenience overload of gene_knockout_constraints for knocking out a single gene (without the necessity to store the gene identifier in a singleton container).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gene_knockouts","page":"Front-end user interface","title":"COBREXA.gene_knockouts","text":"gene_knockouts(model::AbstractFBCModels.AbstractFBCModel)\ngene_knockouts(\n model::AbstractFBCModels.AbstractFBCModel,\n gene_combinations::Vector{<:Union{String, Tuple{Vararg{String, N}} where N}};\n kwargs...\n)\n\n\nCompute the objective value of the model for all knockouts specified by gene_combinations, which is a vector of gene IDs or tuples of gene IDs that are knocked out in groups.\n\nReturns a vector in the same order as gene_combinations.\n\nExtra arguments (mainly, the optimizer) are forwarded to screen_optimization_model.\n\n\n\n\n\n","category":"function"},{"location":"reference/frontend/#Loopless-flux-balance-analysis","page":"Front-end user interface","title":"Loopless flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/loopless.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.loopless_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.loopless_flux_balance_analysis","text":"loopless_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the loopless flux balance analysis on the model, returning the solved constraint system.\n\nArguments are forwarded to loopless_flux_balance_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.loopless_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.loopless_flux_balance_constraints","text":"loopless_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n flux_infinity_bound,\n driving_force_nonzero_bound,\n driving_force_infinity_bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nConstruct a flux-balance constraint system from model with added quasi-thermodynamic constraints that ensure that thermodynamically infeasible internal cycles can not occur. The method is closer described by: Schellenberger, Lewis, and, Palsson. \"Elimination of thermodynamically infeasible loops in steady-state metabolic models.\", Biophysical journal, 2011`.\n\nThe loopless condition comes with a performance overhead: the computation needs to find the null space of the stoichiometry matrix (essentially inverting it); and the subsequently created optimization problem contains binary variables for each internal reaction, thus requiring a MILP solver and a potentially exponential solving time.\n\nInternally, the system is constructed by combining flux_balance_constraints and loopless_constraints.\n\nThe arguments driving_force_max_bound and driving_force_nonzero_bound set the bounds (possibly negated ones) on the virtual \"driving forces\" (G_i in the paper).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Max-Min-Driving-Force-analysis","page":"Front-end user interface","title":"Max-Min Driving Force analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/mmdf.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.max_min_driving_force_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.max_min_driving_force_analysis","text":"max_min_driving_force_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the max-min driving force analysis on the model, returning the solved constraint system.\n\nArguments are forwarded to max_min_driving_force_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.max_min_driving_force_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.max_min_driving_force_constraints","text":"max_min_driving_force_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n concentration_ratios,\n constant_concentrations,\n ignored_metabolites,\n proton_metabolites,\n water_metabolites,\n concentration_lower_bound,\n concentration_upper_bound,\n T,\n R,\n reference_flux_atol\n)\n\n\nCreate max-min driving force constraint system from model, using the supplied reaction standard Gibbs free energies in reaction_standard_gibbs_free_energies.\n\nThe method is described by: Noor, et al., \"Pathway thermodynamics highlights kinetic obstacles in central metabolism.\", PLoS computational biology, 2014.\n\nreference_flux sets the directions of each reaction in model. The scale of the values is not important, only the direction is examined (w.r.t. reference_flux_atol tolerance). Ideally, the supplied reference_flux should be completely free of internal cycles, which enables the thermodynamic consistency. To get the cycle-free flux, you can use loopless_flux_balance_analysis (computationally demanding, but gives thermodynamically consistent solutions), parsimonious_flux_balance_analysis or linear_parsimonious_flux_balance_analysis (which is computationally simple, but the consistency is not guaranteed).\n\nInternally, log_concentration_constraints is used to lay out the base structure of the problem.\n\nFollowing arguments are set optionally:\n\nwater_metabolites, proton_metabolites and ignored_metabolites allow to completely ignore constraints on a part of the metabolite set, which is explicitly recommended especially for water and protons (since the analyses generally assume aqueous environment of constant pH)\nconstant_concentrations can be used to fix the concentrations of the metabolites\nconcentration_lower_bound and concentration_upper_bound set the default concentration bounds for all other metabolites\nconcentration ratios is a dictionary that assigns a tuple of metabolite-metabolite-concentration ratio constraint names; e.g. ATP/ADP ratio can be fixed to five-times-more-ATP by setting concentration_ratios = Dict(\"adenosin_ratio\" => (\"atp\", \"adp\", 5.0))\nT and R default to the usual required thermodynamic constraints in the expected units (the defaults assume the \"usual\" units, valuing 298.15 K and ~0.008314 kJ/K/mol, respectively). These multiply the log-concentrations to obtain the actual Gibbs energies, and thus driving forces.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Sampling","page":"Front-end user interface","title":"Sampling","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/sample.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_sample-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_sample","text":"flux_sample(\n model::AbstractFBCModels.AbstractFBCModel;\n seed,\n objective_bound,\n method,\n n_chains,\n collect_iterations,\n optimizer,\n settings,\n workers,\n kwargs...\n)\n\n\nRun a sampling algorithm on the near-optimal feasible space of the model (as specified by objective_bound). By default, the sampling algorithm is ACHR (the method parameter is defaulted to sample_chain_achr). The sampling algorithm is ran for n_chains and the iterations for collecting the sampled values are specified by collect_iterations.\n\noptimizer is used to generate the warmup (with settings) for the sampler using the usual unidimensional maximum-variability fluxes (as from flux_variability_analysis). All computations are parallelized across workers.\n\nExtra arguments are forwarded to sample_constraints. Eventually the arguments will reach the method function, so extra arguments can be also used to customize the methods (e.g., by setting the epsilon for the ACHR sampler).\n\n\n\n\n\n","category":"method"},{"location":"distributed/3_slurm/#Working-in-a-HPC-environment","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Many researchers have access to institutional HPC facilities that allow time-sharing of the capacity of a large computer cluster between many users. Julia and COBREXA.jl work well within this environment, and the COBREXA analyses usually require only minimal additional customization to be able to find and utilize the resources available from the HPC.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"When executed in a HPC environment, the analysis script must solve several relatively complex tasks:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"It needs to find out how many resources were allocated for the analysis\nIt needs to add the remote workers precisely at the allocated places","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Fortunately, the package ClusterManagers.jl does that for us. For simplicity, here we assume that the HPC is scheduled by Slurm, but other scheduling environments are supported in a very similar way.","category":"page"},{"location":"distributed/3_slurm/#Interacting-with-Slurm","page":"Working in a HPC environment","title":"Interacting with Slurm","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Utilization of the Slurm-provided resources is enabled as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"first, import the ClusterManagers package\nfind how many processes to spawn from the environment, typically from SLURM_NTASKS environment variable\nuse the function addprocs_slurm to precisely connect to the allocated computational resources","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"After adding the Slurm workers, one may continue as if the workers were added using normal addprocs –- typically, we can load the model and (for example) run the flux_variability_analysis as if we would use the local workers.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"The Julia script that does a parallel analysis in a Slurm cluster may look as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"using COBREXA, Distributed, ClusterManagers, HiGHS\n\navailable_workers = parse(Int, ENV[\"SLURM_NTASKS\"])\n\naddprocs_slurm(available_workers)\n\n# ... load models, prepare data, etc. ...\n\nresults = flux_variability_analysis(..., workers=workers())\n\n# ... save the results into a file ...","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"tip: What about the other HPC schedulers?\nClusterManagers.jl supports many other common HPC scheduling systems, including LFS, Sun Grid, SGE, PBS, and Scyld, in a way almost identical to Slurm. See the package documentation for details.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"warning: Using Julia environments with Distributed\nSometimes the project configuration is not forwarded to the workers automatically, resulting to package version mismatches and other problems. When utilizing custom project folders (by running Julia with julia --project=...), use the following form of addprocs_slurm instead:addprocs_slurm(available_workers, exeflags=`--project=$(Base.active_project())`)","category":"page"},{"location":"distributed/3_slurm/#Wrapping-a-pipeline-script-in-a-Slurm-batch-job","page":"Working in a HPC environment","title":"Wrapping a pipeline script in a Slurm batch job","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"To be able to submit a script for later processing using the sbatch Slurm command, we need to wrap it in a small \"batch\" script that tells Slurm how many resources the process needs.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Assuming we have a Julia computation script written down in myJob.jl and saved on the HPC cluster's access node, the corresponding Slurm batch script (let's call it myJob.sbatch) may look as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"#!/bin/bash -l\n#SBATCH -n 100 # the job will use 100 individual worker processes\n#SBATCH -c 1 # each worker will sit on a single CPU\n#SBATCH -t 30 # the whole job will take less than 30 minutes\n#SBATCH -J myJob # the name of the job (for own reference)\n\nmodule load lang/Julia # add Julia to the environment (this may differ on different clusters and installations!)\n\njulia myJob.jl","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"To run the computation, run sbatch myJob.sbatch on the cluster access node. The job will be scheduled and eventually executed. It is possible to watch the output of commands sacct and squeue in the meantime, to see the progress.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Remember that it is necessary to explicitly save the result of the Julia script computation to files, to be able to retrieve them later. Standard outputs of the jobs are often mangled and/or discarded. If we would still want to collect the standard output of the Julia script, we might need to change the last line of the batch script as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"julia myJob.jl > myJob.log","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"...and collect the output from myJob.log later. This is convenient especially if the script prints out various computation details using @info and similar macros.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"EditURL = \"01-loading-and-saving.jl\"","category":"page"},{"location":"examples/01-loading-and-saving/#Loading-and-saving-models","page":"Loading and saving models","title":"Loading and saving models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"using COBREXA","category":"page"},{"location":"examples/01-loading-and-saving/#Getting-the-models-reliably-from-the-repositories","page":"Loading and saving models","title":"Getting the models reliably from the repositories","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"For convenience, COBREXA provides a specific function download_model to download models from repositories that also automatically uses the cached downloaded version of the model if it's already downloaded, and verifies the checksum to improve reproducibility. It will print out a warning in case the model checksum does not match the expectation:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.xml\",\n \"e_coli_core.xml\",\n \"b4db506aeed0e434c1f5f1fdd35feda0dfe5d82badcfda0e9d1342335ab31116\",\n)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"tip: How do I get the model hash?\nWe do not need to fill in the hash values immediately – instead, it's possible to simply run the function once, and then copy the reported hash value from the warning message into the script.","category":"page"},{"location":"examples/01-loading-and-saving/#Loading-models","page":"Loading and saving models","title":"Loading models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"To load genome-scale metabolic models, COBREXA uses the AbstractFBCModels framework to import various kinds of models including SBML, JSON and the legacy Matlab-formatted \"COBRA toolbox\" models.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"All models can be loaded automatically using load_model; but one must import the model-type specific packages to load the functionality. (This step is required to keep the \"base\" COBREXA as efficient and fast-loading as possible.)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import JSONFBCModels, SBMLFBCModels\n\nmodel1 = load_model(\"e_coli_core.json\")\n\nmodel2 = load_model(\"e_coli_core.xml\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"We can now explore the contents of the models using the AbstractFBCModels' interface:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import AbstractFBCModels as A\n\nA.reactions(model1)\n\nA.reactions(model2)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Additional extractable information can be found in the documentation of the abstract models package.","category":"page"},{"location":"examples/01-loading-and-saving/#Converting-model-types","page":"Loading and saving models","title":"Converting model types","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Normally, load_model is forced to guess the model type from the filename suffix. We can specify the model type ourselves (this also allows the users to work with non-standard file suffixes, and saves some overhead and uncertainty in the guessing process):","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import JSONFBCModels: JSONFBCModel\n\nmodel = load_model(JSONFBCModel, \"e_coli_core.json\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Sometimes it is useful to convert the model data to another type, such as the SBML to a JSON model structure:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_converted_to_json = load_model(\"e_coli_core.xml\", JSONFBCModel)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Or to the \"Canonical Julia model\" from AbstractFBCModels:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_in_julia_structures =\n load_model(JSONFBCModel, \"e_coli_core.json\", A.CanonicalModel.Model)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"tip: Compatibility with COBREXA v1.x\nCanonicalModel is a newer, cleaned-up version of the StandardModel type used in COBREXA version 1. For all code that relied on StandardModel, the canonical one should work just as well.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The above command specifies all model types explicitly, leaving least room for guessing-based errors.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"If required, it is also possible to convert all model types to each other simply by using Julia's convert:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_in_json_structure = convert(JSONFBCModel, model_in_julia_structures)","category":"page"},{"location":"examples/01-loading-and-saving/#Saving-models","page":"Loading and saving models","title":"Saving models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The models can be saved to file storage by using save_model:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_converted_to_json, \"e_coli_core_from_sbml.json\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Expectably, the file will contain the JSON with the model description:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"println(open(\"e_coli_core_from_sbml.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Note that without the conversion, it may happen that you save the model in an unexpected format!","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_in_julia_structures, \"e_coli_saved_wrongly.json\")\nprintln(open(\"e_coli_saved_wrongly.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The above code has saved the CanonicalModel in the way specified by the CanonicalModel structure – which is, in this case, a binary dump of the Julia objects, instead of the expected JSON. To prevent this, you can either specify the output type yourself:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_in_julia_structures, \"e_coli_saved_right.json\", JSONFBCModel)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"...or use save_converted_model to guess the model type automatically from the extension:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_converted_model(model_in_julia_structures, \"e_coli_saved_automatically_right.json\")\nprintln(open(\"e_coli_saved_automatically_right.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"As with load_model, there is some overhead and uncertainty associated with save_converted_model guessing the model type from extension. For that reason, it is adviseable to rely on the guessing functionality only in interactive use in REPL, and avoid it in automated scriptage altogether.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"EditURL = \"05a-minimization-of-metabolic-adjustment.jl\"","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Minimization-of-metabolic-adjustment-analysis","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Minimization of metabolic adjustment analysis (MOMA) finds a flux solution that is closest to some reference solution. This may correspond to realistic adjustment of living organisms to various perturbations, such as gene knockout or environmental stress.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"To demonstrate, let's use the E. coli model.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"We shall use both quadratic and linear solvers – the \"closest to some reference solution\" typically refers to Euclidean (\"L2\") distance which requires a QP solver, but Manhattan (\"L1\") distance is also demonstrated below.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import Clarabel, HiGHS","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Because we will have to perform some perturbation, we import the model in canonical Julia structures:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import JSONFBCModels\nimport AbstractFBCModels.CanonicalModel as CM\necoli = load_model(\"e_coli_core.json\", CM.Model)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"This will be a good reaction for perturbing:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"ecoli.reactions[\"CYTBD\"]","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"To do the perturbation, we create a model of a strain which has mild issues with running the CYTBD reaction. We use deepcopy to completely avoid any reference sharing issues.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"limited_ecoli = deepcopy(ecoli)\nlimited_ecoli.reactions[\"CYTBD\"].upper_bound = 10.0","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Finding-parsimonious-solutions","page":"Minimization of metabolic adjustment analysis","title":"Finding parsimonious solutions","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Becuase we are interested in realistic flux distributions, we have to use an analysis method which gives one – in this case, the parsimonious FBA will do just right. For later comparison, we first get the optimal parsimonious flux distribution in the perturbed model:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"solution = parsimonious_flux_balance_analysis(limited_ecoli, optimizer = Clarabel.Optimizer)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Now, how much is the flux going to differ if we assume the bacterium did only minimal adjustment from the previous state with unlimited CYTBD?","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"moma_solution = metabolic_adjustment_minimization_analysis(\n limited_ecoli, # the model to be examined\n ecoli; # the model that gives the reference flux\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Comparing-the-results","page":"Minimization of metabolic adjustment analysis","title":"Comparing the results","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The difference between the naive and minimally-adjusting solutions can be extracted using the constraint tree functionality:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import ConstraintTrees as C\ndifference = C.zip(-, solution, moma_solution, Float64)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"sort(collect(difference.fluxes), by = last)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Using-a-custom-reference-flux","page":"Minimization of metabolic adjustment analysis","title":"Using a custom reference flux","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"In certain situations, one might want to examine how the model would adjust from a known reaction flux. We can supply it manually as the second argument (instead of the reference model).","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"ref = parsimonious_flux_balance_analysis(ecoli, optimizer = Clarabel.Optimizer)\n\nref_closest_solution = metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n ref.fluxes;\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The flux may even be partial (which is common with measured fluxes):","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"measured_fluxes =\n C.Tree{Float64}(:EX_ac_e => 5.0, :EX_o2_e => -2.0, :BIOMASS_Ecoli_core_w_GAM => 0.7)\n\nsolution_close_to_measurement = metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n measured_fluxes;\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Efficient-linear-metric-MOMA","page":"Minimization of metabolic adjustment analysis","title":"Efficient linear-metric MOMA","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The linear version of MOMA avoids having to use the quadratic optimizer in the process, giving more optimizer choices and (typically) much better performance. Linear MOMA has the same interface as the quadratic one:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"linear_moma_solution = linear_metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n ecoli;\n optimizer = HiGHS.Optimizer,\n)\n\nsort(collect(linear_moma_solution.fluxes), by = last)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"How much does the flux distribution differ from the L2 solution?","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"sort(\n collect(C.zip(-, linear_moma_solution.fluxes, moma_solution.fluxes, Float64)),\n by = last,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"EditURL = \"03d-unidirectional.jl\"","category":"page"},{"location":"examples/03d-unidirectional/#Split-unidirectional-reactions-in-models","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"By default, the constraint system produced by e.g. flux_balance_constraints assumes a single variable for each reaction flux that may be both positive and negative (depending on the reaction). This example explains several ways to \"split\" such bidirectional fluxes into unidirectional \"forward\" and \"reverse\" parts. This is useful in modeling of capacity constraints (such system can be found e.g. in enzyme_constrained_flux_balance_analysis and linear_parsimonious_flux_balance_analysis) and many other purposes.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"Here we show how to create such system for the toy E. coli model:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\nimport ConstraintTrees as C\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We will only work with the constraint representation of the model. The fluxes there are bidirectional:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c = flux_balance_constraints(model);\nc.fluxes","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"As the simplest approach, we can allocate 2 sets of variables for the forward and reverse fluxes via sign_split_variables and connect them to the fluxes with sign_split_constraints. These functions ensure that the bounds of the unidirectional fluxes are within the expectable limit, and, respectively, that the original fluxes are constrained to match the sum of the split directions:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c += sign_split_variables(c.fluxes, positive = :fluxes_forward, negative = :fluxes_reverse);\nc *=\n :directional_flux_balance^sign_split_constraints(\n positive = c.fluxes_forward,\n negative = c.fluxes_reverse,\n signed = c.fluxes,\n )","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We can solve this system as usual and obvserve the results as usual","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x = optimized_values(c, objective = c.objective.value, optimizer = HiGHS.Optimizer)\n\nC.zip(tuple, x.fluxes, x.fluxes_forward, x.fluxes_reverse, Tuple)","category":"page"},{"location":"examples/03d-unidirectional/#Simplifying-the-system-using-asymmetric-construction","page":"Split unidirectional reactions in models","title":"Simplifying the system using asymmetric construction","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"If used naively, the above construction uses 3 variables and many constraints for each flux, which is not quite efficient. To ameliorate the usage of solver resources, one may construct a slightly simpler (but asymmetric) system that only uses 2 variables:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c2 = flux_balance_constraints(model);\nc2 += :fluxes_forward^unsigned_positive_contribution_variables(c2.fluxes);\nc2 *=\n :fluxes_reverse^unsigned_negative_contribution_constraints(c2.fluxes, c2.fluxes_forward);\nnothing #hide","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"This way, only forward fluxes are allocated as variables, and reverse fluxes are \"computed\" as linearly dependent values. Additionally, since the bounds on the forward and reverse fluxes completely subsume the original bounds on fluxes, one can further simplify the system by removing the original bounds:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c2.fluxes = remove_bounds(c2.fluxes)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The system solves just like the \"symmetric\" one:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x2 = optimized_values(c2, objective = c2.objective.value, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We can also compare the raw variable counts:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"(C.var_count(c), C.var_count(c2))","category":"page"},{"location":"examples/03d-unidirectional/#Simplifying-the-system-by-removing-original-variables","page":"Split unidirectional reactions in models","title":"Simplifying the system by removing original variables","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"If one can assume that the original system is just allocated variables with no other semantics attached, one can reduce the variable and constraint count even in the \"nicer\" symmetric case from above.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"In particular, it is possible to substitute a combination of forward and reverse flux for the bidirectional variables, which allows them to be pruned out of the system together with their original associated bounds:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"subst_vals = [C.variable(; idx).value for idx = 1:C.var_count(c)]\n\nc.fluxes = C.zip(c.fluxes, c.fluxes_forward, c.fluxes_reverse) do f, p, n\n (var_idx,) = f.value.idxs\n subst_value = p.value - n.value\n subst_vals[var_idx] = subst_value\n C.Constraint(subst_value) # the bidirectional bound is dropped here\nend\n\nc = C.prune_variables(C.substitute(c, subst_vals))","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The variable count is now reduced, and the system again solves just as the original:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"C.var_count(c)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x = optimized_values(c, objective = c.objective.value, optimizer = HiGHS.Optimizer);\nx.objective","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The bidirectional flux values are computed transparently in the result:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x.fluxes","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"EditURL = \"02d-constraint-modifications.jl\"","category":"page"},{"location":"examples/02d-constraint-modifications/#Making-adjustments-to-the-constraint-system","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"In the previous example about model adjustments, we noted that some constraint systems may be too complex to be changed within the limits of the usual FBC model view, and we may require a sharper tool to do the changes we need. This example shows how to do that by modifying the constraint systems that are generated within COBREXA to represent the metabolic model contents.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\") # flux balance type model","category":"page"},{"location":"examples/02d-constraint-modifications/#Background:-Constraint-trees","page":"Making adjustments to the constraint system","title":"Background: Constraint trees","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"COBREXA uses ConstraintTrees to represent model structures internally. This framework provides a powerful unified interface over all constraints and variables in the model, making its manipulation much more convenient.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"import ConstraintTrees as C","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"In general, constraint-based models use fluxes as variables, and all the constraints are in terms of them (or derived quantities). We can get a constraint tree for the usual flux-balance-style models quite easily:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct = flux_balance_constraints(model)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The fluxes are represented by constraints for individual variables:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.fluxes","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The \"mass balance\" is represented as equality constraints:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.flux_stoichiometry","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The objective is represented as a \"transparent reference\" to the variables that specify the biomass. Notice that it has no bound (thus it's technically not a constraint, just a \"label\" for something that has a sensible semantic and can be constrained or optimized).","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.objective","category":"page"},{"location":"examples/02d-constraint-modifications/#Customizing-the-model","page":"Making adjustments to the constraint system","title":"Customizing the model","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"New values and constraints can be easily created from the existing ones. For example, this is a total flux through exchanges of typical fermentation products:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"total_fermentation = ct.fluxes.EX_ac_e.value + ct.fluxes.EX_etoh_e.value","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"With the value in hand, we can constraint it (enforcing that the model outputs at least some fermentation products):","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"fermentation_constraint = C.Constraint(total_fermentation, (10.0, 1000.0))","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"We can assign a name to the constraint, creating a small (singleton) constraint tree:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":":fermentation^fermentation_constraint","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Named constraints can be freely combined, and we combine our new constraint with the whole original constraint tree, getting a differently constrained system:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"fermenting_ct = ct * :fermentation^fermentation_constraint","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"tip: What if I need more complicated changes?\nAlmost all analysis functions have an associated constraint-building function that internally builds the constraint system, for example the parsimonious_flux_balance_analysis is implemented with parsimonious_flux_balance_constraints, which can be used just as flux_balance_constraints here. Additionally, to reach various custom goals, it is recommended to re-use and modify the source of the functions – use the macro @edit, such as @edit parsimonious_flux_balance_constraints, to get a working source code that serves well as a base for implementing new constraint systems.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Constraint trees can be \"solved\", simply by choosing the objective and sending them to the appropriate function. Here, optimized_values rewrites the constraints into a JuMP model, which is subsequently solved and the solved variables are transformed back into semantically labeled values, in the same structure as the original constraint tree.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"solution = optimized_values(\n fermenting_ct,\n objective = fermenting_ct.objective.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Models that can not be solved (for any reason) would instead return nothing. We demonstrate that by breaking the bounds of the original constraint trees to an unsolvable state:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.fluxes.ATPM.bound = C.Between(1000.0, 10000.0)\n\nsolution = optimized_values(ct, objective = ct.objective.value, optimizer = HiGHS.Optimizer)\n\nprint(solution)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Several functions exist to simplify the construction of more complicated constraints. See the reference documentation for generic constraint builders for details.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"EditURL = \"03a-flux-variability-analysis.jl\"","category":"page"},{"location":"examples/03a-flux-variability-analysis/#Flux-variability-analysis-(FVA)","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"","category":"section"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"FVA finds a range of fluxes through each reaction where the model can behave optimally. In brief, it first runs a FBA to get the optimal objective value, constraints the model to the optimal (or near-optimal) space, and runs a separate minimization and maximization task for each reaction to find their individual ranges.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"The \"usual\" form of FBA is available via the eponymous function:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"solution = flux_variability_analysis(model, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03a-flux-variability-analysis/#Specifying-objective-bounds","page":"Flux variability analysis (FVA)","title":"Specifying objective bounds","text":"","category":"section"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"By default, FVA computes variability from the feasible region that is bounded to be within 10% of the optimal objective value. That is not very strict, and we can force much lower tolerance.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"Here, we force the optimal region to be within 0.00001 units of the optimal objective value:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"very_close = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = absolute_tolerance_bound(1e-5),\n)","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"Here, we relax that to 1% of the optimal objective value:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"one_percent_close = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = relative_tolerance_bound(0.99),\n)","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"tip: Speed up FVA with parallel processing\nBy default, FVA is parallelized on all workers that are available in the worker pool of the Distributed package, which may speed up the computation considerably. See the parallel processing documentation for more details.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"EditURL = \"05g-gapfilling.jl\"","category":"page"},{"location":"examples/05g-gapfilling/#Gap-filling","page":"Gap filling","title":"Gap filling","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling is used to find easiest additions to the models that would make them feasible and capable of growth.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Typically, an infeasible model (\"with gaps\") is used together with an universal model (which contains \"everything\"), and the algorithm attempts to find the minimal amount of reactions from the universal model that make the gappy model happy. In turn, the gapfilling optimization problem becomes a MILP.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling is sometimes used to produce \"viable\" genome-scale reconstructions from partial ones, but without additional manual intervention the gapfilling results are almost never biologically valid. A good use of gapfilling is to find problems in a model that cause infeasibility as follows: First the modeller makes a set of (unrealistic) universal reactions that supply or remove metabolites, and after gapfilling, metabolites that had to be supplied or removed to make the model feasible mark possible problems, thus guiding the modeller towards correct solution.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"We will use a partially crippled E. coli toy model and see the minimal amount of reactions that may save it.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"First, let's produce an infeasible model:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"import AbstractFBCModels.CanonicalModel as CM\ninfeasible_model = convert(CM.Model, model)\n\nfor rxn in [\"TALA\", \"PDH\", \"PGI\", \"PYK\"]\n infeasible_model.reactions[rxn].lower_bound = 0.0\n infeasible_model.reactions[rxn].upper_bound = 0.0\nend","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"After removing the above reactions, the model will fail to solve:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"flux_balance_analysis(infeasible_model, optimizer = HiGHS.Optimizer) |> println","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"To avoid very subtle semantic issues, we are going to remove the ATP maintenance pseudoreaction from the universal model:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"universal_model = convert(CM.Model, model)\ndelete!(universal_model.reactions, \"ATPM\")","category":"page"},{"location":"examples/05g-gapfilling/#Making-the-model-feasible-with-a-minimal-set-of-reactions","page":"Gap filling","title":"Making the model feasible with a minimal set of reactions","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Which of the reactions we have to fill back to get the model working again? First, let's run gap_filling_analysis to get a solution for a system that implements the reaction patching:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"x = gap_filling_analysis(\n infeasible_model,\n universal_model,\n 0.05,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"The reactions that had to be re-added can be found from the fill_flags:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"filled_reactions = [k for (k, v) in x.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"If we want to try to generate another solution, we have to explicitly ask the system to avoid the previous solution. That is done via setting the argument known_fill. We can also set the max_cost to avoid finding too benevolent solutions:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"x2 = gap_filling_analysis(\n infeasible_model,\n universal_model,\n 0.05,\n max_cost = 2.0,\n known_fills = [x.fill_flags],\n optimizer = HiGHS.Optimizer,\n)\n\nother_filled_reactions = [k for (k, v) in x2.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/#Model-debugging:-which-metabolite-is-missing?","page":"Gap filling","title":"Model debugging: which metabolite is missing?","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gap-filling is great for detecting various broken links and imbalances in metabolic models. We show how to find the metabolites are causing the imbalance for our \"broken\" E. coli model.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"First, we construct a few completely unnatural reactions that create/remove the metabolites from/to nowhere:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"magic_model = convert(CM.Model, model)\nempty!(magic_model.genes)\nempty!(magic_model.reactions)\n\nfor mid in keys(magic_model.metabolites)\n magic_model.reactions[mid] = CM.Reaction(\n lower_bound = -100.0,\n upper_bound = 100.0,\n stoichiometry = Dict(mid => 1.0),\n )\nend","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling now points to the metabolites that need to be somehow taken care of by the modeller in order for the model to become feasible:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"xm = gap_filling_analysis(infeasible_model, magic_model, 0.05, optimizer = HiGHS.Optimizer)\n\nblocking_metabolites = [k for (k, v) in xm.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"We can also have a look at how much of a given metabolite was used to make the model feasible again:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"xm.universal_fluxes[first(blocking_metabolites)]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"EditURL = \"03b-parsimonious-flux-balance.jl\"","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Parsimonious-flux-balance-analysis","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Here, we use parsimonious_flux_balance_analysis (pFBA) to find the optimal flux distribution in the E. coli \"core\" model. In essence, pFBA first uses FBA to find an optimal objective value for the model, and then minimizes the squared distance of the flux from the zero (i.e., minimizes its L2 norm). As the main benefit, this gives a unique (and possibly more realistic) solution to the model.","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Notably, we need an optimizer that can solve quadratic (QP) models:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"import Clarabel\n\nimport JSONFBCModels\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"The pFBA is, in its most default form, implemented in function parsimonious_flux_balance_analysis:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"solution = parsimonious_flux_balance_analysis(model; optimizer = Clarabel.Optimizer)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"solution.fluxes","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Using-different-solvers-for-the-problem-stages","page":"Parsimonious flux balance analysis","title":"Using different solvers for the problem stages","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Sometimes it is useful to employ a dedicated LP solver to find the solution to the original FBA problem, and then a dedicated QP solver to minimize the fluxes. We can set the optimizer and parsimonious optimizer separately using keyword arguments:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"import HiGHS\n\nsolution = parsimonious_flux_balance_analysis(\n model;\n optimizer = HiGHS.Optimizer, # HiGHS is used only for LP here\n parsimonious_optimizer = Clarabel.Optimizer, # Clarabel is great for solving QPs\n)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Using-linear-(L1)-parsimonious-constraints","page":"Parsimonious flux balance analysis","title":"Using linear (L1) parsimonious constraints","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"For efficiency reasons, it is also possible to use a pFBA version that optimizes the L1 norm instead of the L2 one (i.e., minimizing a sum of absolute values instead of the sum of squares). In turn, the uniqueness property of the solution is lost, but we do not need a QP-capable optimizer at all:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"linear_solution =\n linear_parsimonious_flux_balance_analysis(model; optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"linear_solution.fluxes","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"EditURL = \"05c-mmdf.jl\"","category":"page"},{"location":"examples/05c-mmdf/#Thermodynamic-models","page":"Thermodynamic models","title":"Thermodynamic models","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"using COBREXA","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Here we will solve the max min driving force analysis problem using the glycolysis pathway of E. coli. In essence, the method attempts to find metabolite concentrations (NB: not fluxes) that maximize the smallest thermodynamic driving force through each reaction. See Noor, et al., \"Pathway thermodynamics highlights kinetic obstacles in central metabolism.\", PLoS computational biology, 2014, for more details.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"To do this, we will first need a model that includes glycolysis, which we can download if it is not already present.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Additionally to COBREXA, and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05c-mmdf/#Thermodynamic-data","page":"Thermodynamic models","title":"Thermodynamic data","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"We will need ΔᵣG⁰ data for each reaction we want to include in the thermodynamic model. To generate this data manually, use eQuilibrator. To generate automatically, it is possible to use the eQuilibrator.jl package.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"reaction_standard_gibbs_free_energies = Dict{String,Float64}( # units of the energies are kJ/mol\n \"ENO\" => -3.8108376097261782,\n \"FBA\" => 23.376920310319235,\n \"GAPD\" => 0.5307809794271634,\n \"GLCpts\" => -45.42430981510088,\n \"LDH_D\" => 20.04059765689044,\n \"PFK\" => -18.546314942995934,\n \"PGI\" => 2.6307087407442395,\n \"PGK\" => 19.57192102020454,\n \"PGM\" => -4.470553692565886,\n \"PYK\" => -24.48733600711958,\n \"TPI\" => 5.621932460512994,\n)","category":"page"},{"location":"examples/05c-mmdf/#Running-basic-max-min-driving-force-analysis","page":"Thermodynamic models","title":"Running basic max min driving force analysis","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"If a reference flux is not specified, it is assumed that every reaction in the model should be included in the thermodynamic model, and that each reaction proceeds in the forward direction. This is usually not intended, and can be prevented by inputting a reference flux dictionary as shown below. This dictionary can be a flux solution. The sign of each flux is used to determine if the reaction runs forward or backward.","category":"page"},{"location":"examples/05c-mmdf/#Using-a-reference-solution","page":"Thermodynamic models","title":"Using a reference solution","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Frequently it is useful to check the max-min driving force of a specific FBA solution. In this case, one is usually only interested in a subset of all the reactions in a model. These reactions can be specified as a the reference_flux, to only compute the MMDF of these reactions, and ignore all other reactions.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"reference_flux = Dict(\n \"ENO\" => 1.0,\n \"FBA\" => 1.0,\n \"GAPD\" => 1.0,\n \"GLCpts\" => 1.0,\n \"LDH_D\" => -1.0,\n \"PFK\" => 1.0,\n \"PGI\" => 1.0,\n \"PGK\" => -1.0,\n \"PGM\" => 0.0,\n \"PYK\" => 1.0,\n \"TPI\" => 1.0,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"warning: Only the signs are extracted from the reference solution\nIt is most convenient to pass a flux solution into reference_flux, but take care about the fluxes with value near 0: Their desired sign may be a subject to floating-point robustness error. By default, max_min_driving_force_analysis considers everything that is approximately zero (via isapprox) to have zero flux, with the appropriate implications to concentration balance.","category":"page"},{"location":"examples/05c-mmdf/#Solving-the-MMDF-problem","page":"Thermodynamic models","title":"Solving the MMDF problem","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"mmdf_solution = max_min_driving_force_analysis(\n model;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n constant_concentrations = Dict(\"g3p_c\" => exp(-8.5)),\n concentration_ratios = Dict(\n \"atp\" => (\"atp_c\", \"adp_c\", 10.0),\n \"nadh\" => (\"nadh_c\", \"nad_c\", 0.13),\n ),\n proton_metabolites = [\"h_c\"],\n water_metabolites = [\"h2o_c\"],\n concentration_lower_bound = 1e-6, # mol/L\n concentration_upper_bound = 1e-1, # mol/L\n T = 298.15, # Kelvin\n R = 8.31446261815324e-3, # kJ/K/mol\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"One may be also interested in seeing the FVA-like feasible concentration ranges in such model. The most straightforward way to find these is to use the associated constraint-system-building function max_min_driving_force_constraints together with constraints_variability as follows:","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"mmdf_system = max_min_driving_force_constraints(\n model;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n constant_concentrations = Dict(\"g3p_c\" => exp(-8.5)),\n concentration_ratios = Dict(\n \"atp\" => (\"atp_c\", \"adp_c\", 10.0),\n \"nadh\" => (\"nadh_c\", \"nad_c\", 0.13),\n ),\n proton_metabolites = [\"h_c\"],\n water_metabolites = [\"h2o_c\"],\n concentration_lower_bound = 1e-6, # mol/L\n concentration_upper_bound = 1e-1, # mol/L\n T = 298.15, # Kelvin\n R = 8.31446261815324e-3, # kJ/K/mol\n)\n\ncva_solution = constraints_variability(\n mmdf_system,\n mmdf_system.log_concentrations,\n objective = mmdf_system.min_driving_force.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"EditURL = \"05d-loopless-models.jl\"","category":"page"},{"location":"examples/05d-loopless-models/#Loopless-flux-balance-analysis-(ll-FBA)","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"","category":"section"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Here we wil add loopless constraints to a flux balance model to ensure that the resultant solution is thermodynamically consistent. As before, we will use the core E. coli model, which we can download using download_model:","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Additionally to COBREXA and the JSON model format package. We will also need a solver which can solve mixed-interger linear programs, such as HiGHS.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05d-loopless-models/#Running-a-loopless-FBA-(ll-FBA)","page":"Loopless flux balance analysis (ll-FBA)","title":"Running a loopless FBA (ll-FBA)","text":"","category":"section"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"One can directly use loopless_flux_balance_analysis to solve an FBA problem based on model where loopless constraints are added to all fluxes. This is the direct approach.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"solution = loopless_flux_balance_analysis(model; optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Loopless constraints can also be added to any model (e.g. enzyme constrained models). Refer to the source code of loopless_flux_balance_constraints for guidance.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"EditURL = \"02c-model-modifications.jl\"","category":"page"},{"location":"examples/02c-model-modifications/#Making-adjustments-to-the-model","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Typically, we do not need to solve the models as they come from the authors (someone else already did that!), but we want to perform various perturbations in the model structure and conditions, and explore how the model behaves in the changed conditions.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With COBREXA, there are 2 different approaches that one can take:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We can change the model structure, and use the changed metabolic model. This is better for doing simple and small, but systematic modifications, such as removing metabolites, adding reactions, etc.\nWe can intercept the pipeline that converts the metabolic model to constraints and to the optimizer representation, and make modifications along that way. This is better suited to making global model adjustments, such as using combined objectives, adding reaction-coupling constraints, and combining multiple models into a bigger one.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Here we demonstrate the first, \"modeling\" approach. The main advantage of this approach is that the modified model is still a FBC model, and we can export, save and share it via the AbstractFBCModels interace. The main disadvantage is that the \"common\" FBC model interface does not easily express various complicated constructions (communities, reaction coupling, enzyme constraints, etc.) – see the example about modifying the constraints for more details.","category":"page"},{"location":"examples/02c-model-modifications/#Getting-the-base-model","page":"Making adjustments to the model","title":"Getting the base model","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"For applying the modifications, we will use the canonical model as exported from package AbstractFBCModels. There are other possibilities, but the canonical one is easiest to use for common purposes.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"import AbstractFBCModels.CanonicalModel as CM","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We can now load the model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model = convert(CM.Model, load_model(\"e_coli_core.json\"))","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"The canonical model is quite easy to work with, made basically of the most accessible Julia structures possible. For example, we can look at a reaction as such:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"PFK\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"CS\"].stoichiometry","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"tip: Create custom model types!\nFor some applications, CanonicalModel might be too restrictive. Creating a custom model type that perfectly fits a use-case can be done simply by overloading several functions. The documentation of AbstractFBCModels describes the process closer. Further, all model types that adhere to the AbstractFBCModels' interface will \"just work\" with all analysis functions in COBREXA!","category":"page"},{"location":"examples/02c-model-modifications/#Running-FBA-on-modified-models","page":"Making adjustments to the model","title":"Running FBA on modified models","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Since the canonical model is completely mutable, we can change it in any way we like and feed the result directly into flux_balance_analysis. Let's first find a \"original\" solution, so that we have a base solution for comparing:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"import HiGHS\n\nbase_solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\nbase_solution.objective","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Now, for example, we can limit the intake of glucose by the model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"EX_glc__D_e\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Since the original intake limit is 10 units, let's try limiting that to 5:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"EX_glc__D_e\"].lower_bound = -5.0","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and solve the modified model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"low_glucose_solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\nlow_glucose_solution.objective","category":"page"},{"location":"examples/02c-model-modifications/#Preventing-reference-based-sharing-problems-with-deepcopy","page":"Making adjustments to the model","title":"Preventing reference-based sharing problems with deepcopy","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"People often want to try different perturbations with a single base model. It would therefore look feasible to save the \"unmodified\" model in a single variable, and make copies of that with the modifications applied. Let's observe what happens:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model = convert(CM.Model, load_model(\"e_coli_core.json\")) # load the base\n\nmodified_model = base_model # seemingly make a \"copy\" for modification\n\nmodified_model.reactions[\"EX_glc__D_e\"].lower_bound = -123.0 # modify the glucose intake limit","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Surprisingly, the base model got modified too!","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model.reactions[\"EX_glc__D_e\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"This is because Julia uses reference-based sharing whenever anything mutable is copied using the = operator. While this is extremely useful in many scenarios for data processing efficiency and computational speed, it unfortunately breaks this simple use-case.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"To fix this situation, we must always remember to make an actual copy of the model data, by either carefully copying the changed parts (e.g., using a similar approach as with the \"shallow\" copy()), or simply by copying the whole model structure as is with deepcopy(). Let's try again:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model = convert(CM.Model, load_model(\"e_coli_core.json\"))\nmodified_model = deepcopy(base_model) # this forces an actual copy of the data\nmodified_model.reactions[\"EX_glc__D_e\"].lower_bound = -123.0","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With deepcopy, the result works as intended:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"(\n modified_model.reactions[\"EX_glc__D_e\"].lower_bound,\n base_model.reactions[\"EX_glc__D_e\"].lower_bound,\n)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"danger: Avoid overwriting base models when using in-place modifications\nWhenever changing a copy of the model, check that the base model is not inadvertently changed via a reference. Always use some copy mechanism such as copy or deepcopy to prevent the default reference-based sharing.","category":"page"},{"location":"examples/02c-model-modifications/#Observing-the-differences","page":"Making adjustments to the model","title":"Observing the differences","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We already have a base_solution and low_glucose_solution from above. What is the easiest way to see what has changed? We can quite easily compute squared distance between all dictionary entries using Julia function for merging dictionaries (called mergewith).","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With that, we can extract the plain difference in fluxes:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"flux_differences = mergewith(-, base_solution.fluxes, low_glucose_solution.fluxes)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and see what were the biggest directional differences:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"sort(collect(flux_differences), by = last)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...or compute the squared distance, to see the \"absolute\" changes:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"flux_changes =\n mergewith((x, y) -> (x - y)^2, base_solution.fluxes, low_glucose_solution.fluxes)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and again see what changed most:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"sort(collect(flux_changes), by = last)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"tip: Always use a uniquely defined flux solutions for flux comparisons\nSince the usual flux balance allows a lot of freedom in the \"solved\" flux and the only value that is \"reproducible\" by the analysis is the objective, one should never compare the flux distributions directly. Typically, that may result in false-positive (and sometimes false-negative) differences. Use e.g. parsimonious FBA to obtain uniquely determined and safely comparable flux solutions.","category":"page"},{"location":"examples/02c-model-modifications/#Coupling-constraints","page":"Making adjustments to the model","title":"Coupling constraints","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Some model types support additional constraints over the reaction fluxes, which are historically called \"coupling\". These allow to e.g. place a bound on a total flux through several reactions.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Canonical model supports these as \"couplings\":","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.couplings[\"total_energy_intake\"] = CM.Coupling(\n lower_bound = 0,\n upper_bound = 5,\n reaction_weights = Dict(\"EX_glc__D_e\" => -1.0, \"EX_fru_e\" => -1.0, \"EX_pyr_e\" => -1.0),\n)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"The values of any coupling constraints can be inspected directly in the solved model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"solution_with_coupling = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\n\nsolution_with_coupling.coupling.total_energy_intake","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"EditURL = \"03c-envelopes.jl\"","category":"page"},{"location":"examples/03c-envelopes/#Production-envelopes","page":"Production envelopes","title":"Production envelopes","text":"","category":"section"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"Production envelopes determine the flux of the model objective at different values of specific reactions, spanning their variability. We can use the builtin function objective_production_envelope to quickly find such envelopes.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"We proceed as usual by loading the necessary models and packages:","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"The objective_production_envelope function finds the variability of the given reactons and returns a multidimensional matrix with exact number of breaks in each dimension (positioned in a linear lattice). Here we examine the inter-dependency of oxygen and carbon dioxide exchanges on a matrix of 5×5 individual \"conditions\" that form the envelope:","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"envelope = objective_production_envelope(\n model,\n [\"EX_o2_e\", \"EX_co2_e\"];\n breaks = 5,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"Documentation of the function describes ways to set custom bounds for the examined reaction flux ranges and several other customizations.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"EditURL = \"06a-sampling.jl\"","category":"page"},{"location":"examples/06a-sampling/#Flux-sampling","page":"Flux sampling","title":"Flux sampling","text":"","category":"section"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"Flux sampling gives an interesting statistical insight into the behavior of the model in the optimal feasible space, and the general \"shape\" of the optimal- or near-optimal set of feasible states of a given model.","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"For demonstration, we need the usual packages and models:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"Function flux_sample uses linear optimization to generate a set of warm-up points (by default, the method to generate the warm-up is basically FVA), and then runs the hit-and-run flux sampling algorithm on the near-optimal feasible space of the model:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"s = flux_sample(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = relative_tolerance_bound(0.99),\n n_chains = 2,\n collect_iterations = [10],\n)","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"The result is a tree of vectors of sampled states for each value; the order of the values in these vectors is fixed. You can thus e.g. create a good matrix for plotting the sample as 2D scatterplot:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"[s.O2t s.CO2t]","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"EditURL = \"02b-optimizer-parameters.jl\"","category":"page"},{"location":"examples/02b-optimizer-parameters/#Changing-optimizer-parameters","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"","category":"section"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Many optimizers require fine-tuning to produce best results. We can pass in additional optimizer settings via the settings parameter of flux_balance_analysis. These include e.g.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"set_optimizer_attribute, allowing us to tune e.g. iteration limits, tolerances, or floating-point precision (see JuMP documentation for more solver-specific settings)\nset_objective_sense, allowing the user to change and reverse the optimization direction, if required\nsilence for disabling the debug output of the optimizers\nset_optimizer for replacing the optimizer implementation used (this is not quite useful in this case, but becomes beneficial with more complex, multi-stage optimization problems)\nset_time_limit for putting a time limit on the solver computation (this is quite useful for MILP solvers)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To demonstrate this, let's use the usual toy model:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"using COBREXA\nimport JSONFBCModels, Tulip\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Running a FBA with a silent optimizer that has slightly increased iteration limit for IPM algorithm may now look as follows:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [set_optimizer_attribute(\"IPM_IterationsLimit\", 1000)],\n)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To see some of the effects of the configuration changes, we may e.g. deliberately cripple the optimizer's possibilities to a few iterations and only a little time, which will cause it to fail and return no solution:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [set_optimizer_attribute(\"IPM_IterationsLimit\", 2), set_time_limit(0.1)],\n)\n\nprintln(solution)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To see what failed, users may examine the solver output. Because all solver output is silenced by default for efficiency reasons, we need to explicitly pass in the unsilence setting:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [\n set_optimizer_attribute(\"IPM_IterationsLimit\", 2),\n set_time_limit(0.1),\n unsilence,\n ],\n)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Applicable optimizer attributes are documented in the documentations of the respective optimizers. To browse the possibilities, one might want to see the JuMP documentation page that summarizes the references to the available optimizers.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Default solver settings can be examined and changed via Configuration.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"EditURL = \"05f-cyclefree.jl\"","category":"page"},{"location":"examples/05f-cyclefree/#CycleFreeFlux","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"CycleFreeFlux essentially defines a L1-parsimonious model which can be used to run a cycle-free FBA and FVA. In COBREXA, this is best done by reusing linear_parsimonious_flux_balance_analysis.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"First, let's get a model, create a constraint tree with the model, and ask for explicitly materializing constraints for the exchanges:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nmodel = load_model(\"e_coli_core.json\")\n\ncs = flux_balance_constraints(model, interface = :identifier_prefixes)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"We will also need some existing solution of the model – CycleFreeFlux algorithm uses this one as a reference for fixing the exchange reaction flux.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"some_flux =\n optimized_values(cs, objective = cs.objective.value, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"(Ideally, we should use a solving method that gives a more unique flux, but for this example a simple FBA optimum will do.)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"With this in hand, we can start the CycleFreeFlux workflow by placing constraints on exchange reactions in a linear-parsimonious model:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"import ConstraintTrees as C\n\ncs = linear_parsimonious_flux_balance_constraints(model)\n\ncs *=\n :fixed_exchanges^C.ConstraintTree(\n k => C.Constraint(cs.fluxes[k].value, relative_tolerance_bound(0.999)(v)) for\n (k, v) in some_flux.interface.exchanges\n )","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"(We purposefully made the constraints a little less strict by using relative_tolerance_bound – the toy E. coli model would otherwise display no variability at all.)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Now we can get a L1-parsimonious (thus cycle-free) solution of the model with the predefined exchanges:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"cycle_free_flux = parsimonious_optimized_values(\n cs,\n objective = cs.objective.value,\n objective_value = some_flux.objective,\n parsimonious_objective = cs.parsimonious_objective.value,\n optimizer = HiGHS.Optimizer,\n)\n\ncycle_free_flux.fluxes","category":"page"},{"location":"examples/05f-cyclefree/#CycleFreeFVA","page":"CycleFreeFlux","title":"CycleFreeFVA","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"With this in hand, we can also run the cycle-free flux variability analysis (again with an added bit of tolerances in both the objective and parsimonious bounds):","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"cs.objective.bound = C.Between(cycle_free_flux.objective * 0.999, Inf)\ncs.parsimonious_objective.bound =\n C.Between(0, cycle_free_flux.parsimonious_objective * 1.001)\n\nvar = constraints_variability(cs, cs.fluxes, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05f-cyclefree/#CycleFree-sampling","page":"CycleFreeFlux","title":"CycleFree sampling","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Naturally, we can also run flux sampling from the above model. To implement this, we follow the implementation of flux_sample –- first we generate the warmup:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"warmup = vcat(\n (\n transpose(v) for (_, vs) in constraints_variability(\n cs,\n cs.fluxes,\n optimizer = HiGHS.Optimizer,\n output = (_, om) -> variable_vector(om),\n output_type = Vector{Float64},\n ) for v in vs\n )...,\n)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Next, we can run the sampling:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"sample = sample_constraints(\n sample_chain_achr,\n cs,\n start_variables = warmup,\n seed = UInt(1234),\n output = cs.fluxes,\n n_chains = 10,\n collect_iterations = collect(10:15),\n)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"The results can be observed (and usually plotted) from the sample vectors, such as the one for oxygen exchange:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"sample.EX_o2_e","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"EditURL = \"02a-flux-balance-analysis.jl\"","category":"page"},{"location":"examples/02a-flux-balance-analysis/#Flux-balance-analysis-(FBA)","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"","category":"section"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"Here we use flux_balance_analysis and several related functions to find an optimal flux in the E. coli \"core\" model. We will need the model, which we can download using download_model:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"Additionally to COBREXA and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/02a-flux-balance-analysis/#Running-a-FBA","page":"Flux balance analysis (FBA)","title":"Running a FBA","text":"","category":"section"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"There are many possibilities on how to arrange the metabolic model into the optimization framework and how to actually solve it. The \"usual\" assumed one is captured in the default behavior of function flux_balance_analysis:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"The result contains a tree of all optimized values in the model, including fluxes, the objective value, and possibly others (given by what the model contains).","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"We can use the dot notation to explore the solution, extracting e.g. the value of the objective:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution.objective","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"...or the value of the flux through the given reaction (note the solution is not unique in FBA):","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution.fluxes.PFK","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"tip: Browsing the model structure\nAfter typing solution. in the Julia REPL, one can press [tab] to quickly see what is in the next level of the tree. Unfortunately (due to type system limitations) this currently works only for the topmost level of the tree.","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"...or make a \"table\" of all fluxes through all reactions:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"collect(solution.fluxes)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"EditURL = \"05e-knockouts.jl\"","category":"page"},{"location":"examples/05e-knockouts/#Gene-knockouts","page":"Gene knockouts","title":"Gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"FBA is classically very good at predicting the effect of knocking out genes in an organism. Here we demonstrate the ways of using the FBA to examine knockouts in COBREXA.","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"As usual, we need packages and models:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05e-knockouts/#Single-gene-knockouts","page":"Gene knockouts","title":"Single gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"Function gene_knockouts is a convenience wrapper for FBA that computes and optimizes the knockout biomass productions for all genes:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"ko_objective_values = gene_knockouts(model, optimizer = HiGHS.Optimizer)\n\nko_dict = Dict(ko_objective_values)\n\n\nko_dict[\"b3919\"]\n\nko_dict[\"b3738\"]","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"From the result, we can see e.g. how many genes are critical:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"critical = count(isnothing, values(ko_dict))","category":"page"},{"location":"examples/05e-knockouts/#Multiple-gene-knockouts","page":"Gene knockouts","title":"Multiple gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"By default, gene_knockouts simply computes all gene knockouts. To examine multi-gene knockouts, we specify them manually as an array of tuples:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"some_double_knockouts = gene_knockouts(\n model,\n [(\"b3919\", \"b3738\"), (\"b0118\", \"b0720\")],\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"With the array processing functionality of Julia it is quite straightforward to generate the tuples for various specifications of knockout sets; for example here we specify all double knockout where the second knocked-out gene is b3919:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"knockouts_with_b3919 =\n gene_knockouts(model, tuple.(keys(ko_dict), \"b3919\"), optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"Now, how many genes are critical given b3919 is already missing?","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"critical_without_b3919 = count(isnothing, last.(knockouts_with_b3919))","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"EditURL = \"05b-enzyme-constrained-models.jl\"","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Enzyme-constrained-models","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained metabolic models include the effect of enzyme kinetics (v = k * e) and a protein capacity limitation (∑e = Etotal) on conventional mass balance (FBA) models.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"using COBREXA","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Here we will construct an enzyme constrained variant of the E. coli \"core\" model. We will need the model, which we can download if it is not already present.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Additionally to COBREXA and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"import AbstractFBCModels as A\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained models require parameters that are usually not used by conventional constraint based models. These include reaction specific turnover numbers, molar masses of enzymes, and protein capacity bounds.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Reaction-turnover-numbers","page":"Enzyme constrained models","title":"Reaction turnover numbers","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained models require reaction turnover numbers, which are often isozyme specfic. Many machine learning tools, or experimental data sets, can be used to estimate these parameters.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
Data for reaction turnover numbers","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This data is taken from: Heckmann, David, et al. \"Machine learning applied to enzyme turnover numbers reveals protein structural correlates and improves metabolic models.\" Nature communications 9.1 (2018): 1-10.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"const ecoli_core_reaction_kcats = Dict(\n \"ACALD\" => 568.11,\n \"PTAr\" => 1171.97,\n \"ALCD2x\" => 75.95,\n \"PDH\" => 529.76,\n \"MALt2_2\" => 234.03,\n \"CS\" => 113.29,\n \"PGM\" => 681.4,\n \"TKT1\" => 311.16,\n \"ACONTa\" => 191.02,\n \"GLNS\" => 89.83,\n \"ICL\" => 17.45,\n \"FBA\" => 373.42,\n \"FORt2\" => 233.93,\n \"G6PDH2r\" => 589.37,\n \"AKGDH\" => 264.48,\n \"TKT2\" => 467.42,\n \"FRD7\" => 90.20,\n \"SUCOAS\" => 18.49,\n \"ICDHyr\" => 39.62,\n \"AKGt2r\" => 234.99,\n \"GLUSy\" => 33.26,\n \"TPI\" => 698.30,\n \"FORt\" => 234.38,\n \"ACONTb\" => 159.74,\n \"GLNabc\" => 233.80,\n \"RPE\" => 1772.485,\n \"ACKr\" => 554.61,\n \"THD2\" => 24.73,\n \"PFL\" => 96.56,\n \"RPI\" => 51.77,\n \"D_LACt2\" => 233.51,\n \"TALA\" => 109.05,\n \"PPCK\" => 218.42,\n \"PGL\" => 2120.42,\n \"NADTRHD\" => 186.99,\n \"PGK\" => 57.64,\n \"LDH_D\" => 31.11,\n \"ME1\" => 487.01,\n \"PIt2r\" => 233.86,\n \"ATPS4r\" => 71.42,\n \"GLCpts\" => 233.90,\n \"GLUDy\" => 105.32,\n \"CYTBD\" => 153.18,\n \"FUMt2_2\" => 234.37,\n \"FRUpts2\" => 234.19,\n \"GAPD\" => 128.76,\n \"PPC\" => 165.52,\n \"NADH16\" => 971.74,\n \"PFK\" => 1000.46,\n \"MDH\" => 25.93,\n \"PGI\" => 468.11,\n \"ME2\" => 443.09,\n \"GND\" => 240.12,\n \"SUCCt2_2\" => 234.18,\n \"GLUN\" => 44.76,\n \"ADK1\" => 111.64,\n \"SUCDi\" => 680.31,\n \"ENO\" => 209.35,\n \"MALS\" => 252.75,\n \"GLUt2r\" => 234.22,\n \"PPS\" => 706.14,\n \"FUM\" => 1576.83,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We have these here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ecoli_core_reaction_kcats # units = 1/s","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Each reaction in a constraint-based model usually has gene reaction rules associated with it. These typically take the form of, possibly multiple, isozymes that can catalyze a reaction. A turnover number needs to be assigned to each isozyme, as shown below. Additionally, some enzymes are composed of multiple subunits, which differ in subunit stoichiometry. This also needs to be accounted for. Assuming a stoichiometry of 1 for everything tends to work just right OK if there is no better information available.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"reaction_isozymes = Dict{String,Dict{String,Isozyme}}() # a mapping from reaction IDs to isozyme IDs to isozyme structs.\nfor rid in A.reactions(model)\n grrs = A.reaction_gene_association_dnf(model, rid)\n isnothing(grrs) && continue # skip if no grr available\n haskey(ecoli_core_reaction_kcats, rid) || continue # skip if no kcat data available\n for (i, grr) in enumerate(grrs)\n d = get!(reaction_isozymes, rid, Dict{String,Isozyme}())\n d[\"isozyme_\"*string(i)] = Isozyme( # each isozyme gets a unique name\n gene_product_stoichiometry = Dict(grr .=> fill(1.0, size(grr))), # assume subunit stoichiometry of 1 for all isozymes\n kcat_forward = ecoli_core_reaction_kcats[rid] * 3.6, # forward reaction turnover number units = 1/h\n kcat_reverse = ecoli_core_reaction_kcats[rid] * 3.6, # reverse reaction turnover number units = 1/h\n )\n end\nend","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"tip: Turnover number units\nTake care with the units of the turnover numbers. In literature they are usually reported in 1/s. However, flux units are typically mmol/gDW/h, suggesting to rescale the turnover numbers to 1/h in order to use the conventional flux units.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Enzyme-molar-masses","page":"Enzyme constrained models","title":"Enzyme molar masses","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We also require the mass of each enzyme, to properly weight the contribution of each flux/isozyme in the capacity bound(s). These data can typically be found in uniprot.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
Gene product masses","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This data is downloaded from Uniprot for E. coli K12, gene mass in kDa. To obtain these data manually, go to Uniprot and search using these terms: reviewed:yes AND organism:\"Escherichia coli (strain K12) [83333]\".","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"const ecoli_core_gene_product_masses = Dict(\n \"b4301\" => 23.214,\n \"b1602\" => 48.723,\n \"b4154\" => 65.972,\n \"b3236\" => 32.337,\n \"b1621\" => 56.627,\n \"b1779\" => 35.532,\n \"b3951\" => 85.96,\n \"b1676\" => 50.729,\n \"b3114\" => 85.936,\n \"b1241\" => 96.127,\n \"b2276\" => 52.044,\n \"b1761\" => 48.581,\n \"b3925\" => 35.852,\n \"b3493\" => 53.389,\n \"b3733\" => 31.577,\n \"b2926\" => 41.118,\n \"b0979\" => 42.424,\n \"b4015\" => 47.522,\n \"b2296\" => 43.29,\n \"b4232\" => 36.834,\n \"b3732\" => 50.325,\n \"b2282\" => 36.219,\n \"b2283\" => 100.299,\n \"b0451\" => 44.515,\n \"b2463\" => 82.417,\n \"b0734\" => 42.453,\n \"b3738\" => 30.303,\n \"b3386\" => 24.554,\n \"b3603\" => 59.168,\n \"b2416\" => 63.562,\n \"b0729\" => 29.777,\n \"b0767\" => 36.308,\n \"b3734\" => 55.222,\n \"b4122\" => 60.105,\n \"b2987\" => 53.809,\n \"b2579\" => 14.284,\n \"b0809\" => 26.731,\n \"b1524\" => 33.516,\n \"b3612\" => 56.194,\n \"b3735\" => 19.332,\n \"b3731\" => 15.068,\n \"b1817\" => 35.048,\n \"b1603\" => 54.623,\n \"b1773\" => 30.81,\n \"b4090\" => 16.073,\n \"b0114\" => 99.668,\n \"b3962\" => 51.56,\n \"b2464\" => 35.659,\n \"b2976\" => 80.489,\n \"b1818\" => 27.636,\n \"b2285\" => 18.59,\n \"b1702\" => 87.435,\n \"b1849\" => 42.434,\n \"b1812\" => 50.97,\n \"b0902\" => 28.204,\n \"b3403\" => 59.643,\n \"b1612\" => 60.299,\n \"b1854\" => 51.357,\n \"b0811\" => 27.19,\n \"b0721\" => 14.299,\n \"b2914\" => 22.86,\n \"b1297\" => 53.177,\n \"b0723\" => 64.422,\n \"b3919\" => 26.972,\n \"b3115\" => 43.384,\n \"b4077\" => 47.159,\n \"b3528\" => 45.436,\n \"b0351\" => 33.442,\n \"b2029\" => 51.481,\n \"b1819\" => 30.955,\n \"b0728\" => 41.393,\n \"b2935\" => 72.212,\n \"b2415\" => 9.119,\n \"b0727\" => 44.011,\n \"b0116\" => 50.688,\n \"b0485\" => 32.903,\n \"b3736\" => 17.264,\n \"b0008\" => 35.219,\n \"b3212\" => 163.297,\n \"b3870\" => 51.904,\n \"b4014\" => 60.274,\n \"b2280\" => 19.875,\n \"b2133\" => 64.612,\n \"b2278\" => 66.438,\n \"b0118\" => 93.498,\n \"b2288\" => 16.457,\n \"b3739\" => 13.632,\n \"b3916\" => 34.842,\n \"b3952\" => 32.43,\n \"b2925\" => 39.147,\n \"b2465\" => 73.043,\n \"b2297\" => 77.172,\n \"b2417\" => 18.251,\n \"b4395\" => 24.065,\n \"b3956\" => 99.063,\n \"b0722\" => 12.868,\n \"b2779\" => 45.655,\n \"b0115\" => 66.096,\n \"b0733\" => 58.205,\n \"b1478\" => 35.38,\n \"b2492\" => 30.565,\n \"b0724\" => 26.77,\n \"b0755\" => 28.556,\n \"b1136\" => 45.757,\n \"b2286\" => 68.236,\n \"b0978\" => 57.92,\n \"b1852\" => 55.704,\n \"b2281\" => 20.538,\n \"b2587\" => 47.052,\n \"b2458\" => 36.067,\n \"b0904\" => 30.991,\n \"b1101\" => 50.677,\n \"b0875\" => 23.703,\n \"b3213\" => 52.015,\n \"b2975\" => 58.92,\n \"b0720\" => 48.015,\n \"b0903\" => 85.357,\n \"b1723\" => 32.456,\n \"b2097\" => 38.109,\n \"b3737\" => 8.256,\n \"b0810\" => 24.364,\n \"b4025\" => 61.53,\n \"b1380\" => 36.535,\n \"b0356\" => 39.359,\n \"b2277\" => 56.525,\n \"b1276\" => 97.677,\n \"b4152\" => 15.015,\n \"b1479\" => 63.197,\n \"b4153\" => 27.123,\n \"b4151\" => 13.107,\n \"b2287\" => 25.056,\n \"b0474\" => 23.586,\n \"b2284\" => 49.292,\n \"b1611\" => 50.489,\n \"b0726\" => 105.062,\n \"b2279\" => 10.845,\n \"s0001\" => 0.0,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We have the molar masses here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ecoli_core_gene_product_masses # unit kDa = kg/mol","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"tip: Molar mass units\nJust as with the turnover numbers, take extreme care about the units of the molar masses. In literature they are usually reported in Da or kDa (g/mol). However, as noted above, flux units are typically mmol/gDW/h. Since the enzyme kinetic equation is v = k * e (where k is the turnover number) it suggests that the enzyme variable will have units of mmol/gDW. The molar masses come into play when setting the capacity limitations, e.g. usually a sum over all enzymes weighted by their molar masses as e * M. Thus, if the capacity limitation has units of g/gDW, then the molar masses must have units of g/mmol (i.e., kDa).","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Capacity-limitation","page":"Enzyme constrained models","title":"Capacity limitation","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"The capacity limitation usually denotes an upper bound of protein available to the cell. Multiple capacity bounds can be used (cytosol, membrane, etc).","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"total_enzyme_capacity = 50.0 # mg of enzyme/gDW","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Running-a-basic-enzyme-constrained-model","page":"Enzyme constrained models","title":"Running a basic enzyme constrained model","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"With all the parameters specified, we can directly use the enzyme constrained convenience function to run enzyme constrained FBA in one shot:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution = enzyme_constrained_flux_balance_analysis(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We can notice that the objective function is a little lower than with unconstrained E. coli core:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.objective","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"One can also observe many interesting thing, e.g. the amount of gene product material required for the system to run. Importantly, the units of these values depend on the units used to set the turnover numbers and protein molar masses.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"The total amount of required gene product mass is, by default, present as total_capacity:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.gene_product_capacity","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Simplified-models","page":"Enzyme constrained models","title":"Simplified models","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Because most active reactions typically only use a single isozyme, we may also use a simplified representation of the problem where this fact is reflected, saving the variable allocation for the isozymes.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_enzyme_constrained_flux_balance_analysis takes similar arguments as the enzyme_constrained_flux_balance_analysis, but automatically chooses the \"fastest\" reaction isozyme for each reaction direction and builds the model with that.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution = simplified_enzyme_constrained_flux_balance_analysis(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"In this case, the result is the same as with the full analysis:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution.capacity_limits.total_capacity","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Gene product amounts are not present in the model but are reconstructed nevertheless (they are uniquely determined by the flux):","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Variability-analysis-with-enzyme-constraints","page":"Enzyme constrained models","title":"Variability analysis with enzyme constraints","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme-constrained variability analysis can be executed on a model by combining enzyme_constrained_flux_balance_constraints (or simplified_enzyme_constrained_flux_balance_constraints) with constraints_variability (or any other analysis function):","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_system = enzyme_constrained_flux_balance_constraints(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Here, we can do the FVA \"manually\", first solving the system:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_optimum = optimized_values(\n ec_system,\n output = ec_system.objective,\n objective = ec_system.objective.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...then creating a system constrained to near-optimal growth:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"import ConstraintTrees as C\n\nec_system.objective.bound = C.Between(0.99 * ec_optimum, Inf)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...and finally, finding the extremes of the near-optimal part of the feasible space:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities =\n constraints_variability(ec_system, ec_system, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"By default, the result computes variabilities of all possible values in the model. (I.e., it also computes variabilities for the variable combinations that are present in the tree!) As usual, the results can be observed in the original constraint tree structure, giving us the variabilities for reaction fluxes:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.fluxes","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...as well as for gene product requirements:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...and for the individual directional isozymes:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.isozyme_forward_amounts.PGM","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"If we do not need to compute all these values, it is often more efficient to only ask for the part of the output that is required:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_gp_amount_variabilities = constraints_variability(\n ec_system,\n ec_system.gene_product_amounts,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/core/#Core-functionality","page":"Core functionality","title":"Core functionality","text":"","category":"section"},{"location":"reference/core/#Model-I/O","page":"Core functionality","title":"Model I/O","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/io.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.download_model-Tuple","page":"Core functionality","title":"COBREXA.download_model","text":"download_model(args...; kwargs...) -> Any\n\n\nSafely download a model with a known hash. All arguments are forwarded to AbstractFBCModels.download_data_file – see the documentation in the AbstractFBCModels package for details.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Tuple{String}","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(path::String) -> Any\n\n\nLoad a FBC model representation while guessing the correct model type to load. Uses AbstractFBCModels.load.\n\nThis overload almost always involves a search over types; do not use it in environments where performance is critical.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{I}, Tuple{Type{I}, String}} where I<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},\n path::String\n) -> Any\n\n\nLoad a FBC model representation from a known model_type. Uses AbstractFBCModels.load.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{O}, Tuple{I}, Tuple{Type{I}, String, Type{O}}} where {I<:AbstractFBCModels.AbstractFBCModel, O<:AbstractFBCModels.AbstractFBCModel}","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of load_model that explicitly specifies the known input type, and immediately converts to another model type given by argument convert_to.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{O}, Tuple{String, Type{O}}} where O<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of load_model that guesses the input type, but immediately converts to the model type given by argument convert_to.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_converted_model-Union{Tuple{T}, Tuple{T, String}} where T<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.save_converted_model","text":"save_converted_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String\n) -> Any\n\n\nLike save_model but tries to convert the model to a type that matches the extension of the path. For example, this will convert the model to a JSON model type in case the path ends with .json.\n\nThis is an utility shortcut – if possible, it is always better to specify the output model type explicitly.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_model-Union{Tuple{O}, Tuple{T}, Tuple{T, String, Type{O}}} where {T<:AbstractFBCModels.AbstractFBCModel, O<:AbstractFBCModels.AbstractFBCModel}","page":"Core functionality","title":"COBREXA.save_model","text":"save_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of save_model that converts the model type to convert_to before saving.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_model-Union{Tuple{T}, Tuple{T, String}} where T<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.save_model","text":"save_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String\n) -> Any\n\n\nSave a FBC model representation. Uses AbstractFBCModels.save.\n\nUse the 3-parameter overload if you need to convert the model to another representation (e.g., if you want to save a canonical model type as JSON or SBML).\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#Types","page":"Core functionality","title":"Types","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/types.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.Maybe","page":"Core functionality","title":"COBREXA.Maybe","text":"Maybe{X}\n\nType of optional values.\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#Configuration","page":"Core functionality","title":"Configuration","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/config.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.configuration","page":"Core functionality","title":"COBREXA.configuration","text":"const configuration\n\nThe configuration object. You can change the contents of configuration to override the default behavior of some of the functions.\n\nThe available options are described by struct Configuration.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Configuration","page":"Core functionality","title":"COBREXA.Configuration","text":"mutable struct Configuration\n\nGlobal configuration options for various COBREXA functions, mainly for various non-interesting function parameters that are too inconvenient to be passed around manually.\n\nChanging the configuration values at runtime is possible via the global configuration variable.\n\nFields\n\nexchange_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are exchanges.\n\nbiomass_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are biomass reactions.\n\natp_maintenance_ids::Vector{String}: Reaction identifiers that flux_balance_constraints considers to be ATP maintenance reactions.\n\nexchange_sbos::Vector{String}: SBO numbers that label exchange reactions for flux_balance_constraints.\n\nbiomass_sbos::Vector{String}: SBO numbers that label biomass production reactions for flux_balance_constraints.\n\natp_maintenance_sbos::Vector{String}: SBO numbers that label ATP maintenance reactions for flux_balance_constraints.\n\ndemand_sbos::Vector{String}: SBO numbers that label metabolite demand reactions for flux_balance_constraints.\n\nsampler_tolerance::Any: Default numerical tolerance for sampling functions.\n\ndefault_solver_settings::Any: Default settings first applied to all JuMP Models.\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#Solver-interface","page":"Core functionality","title":"Solver interface","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/solver.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.Feasible","page":"Core functionality","title":"COBREXA.Feasible","text":"Maximal\n\nObjective sense for finding the any feasible value of the objective.\n\nSame as JuMP.FEASIBILITY_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Maximal","page":"Core functionality","title":"COBREXA.Maximal","text":"Maximal\n\nObjective sense for finding the maximal value of the objective.\n\nSame as JuMP.MAX_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Minimal","page":"Core functionality","title":"COBREXA.Minimal","text":"Minimal\n\nObjective sense for finding the minimal value of the objective.\n\nSame as JuMP.MIN_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Switch","page":"Core functionality","title":"COBREXA.Switch","text":"mutable struct Switch <: ConstraintTrees.Bound\n\nRepresentation of a \"binary switch\" bound for ConstraintTrees. The value is constrained to be either the value of field a or of field b; both fields are Float64s. Upon translation to JuMP, the switches create an extra boolean variable, and the value is constrained to equal a + boolean_var * (b-a).\n\nSwitches can be offset by adding real numbers, negated, and multiplied and divided by scalar constraints. For optimizing some special cases, multiplying by exact zero returns an equality bound to zero.\n\nFields\n\na::Float64: One choice\nb::Float64: The other choice\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, ConstraintTrees.Between}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::ConstraintTrees.Between\n) -> Union{Bool, JuMP.ConstraintRef}\n\n\nAdd an interval constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, ConstraintTrees.EqualTo}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::ConstraintTrees.EqualTo\n) -> JuMP.ConstraintRef\n\n\nAdd an equality constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, Switch}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::Switch\n) -> JuMP.ConstraintRef\n\n\nAdd a Switch constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.is_solved-Tuple{JuMP.Model}","page":"Core functionality","title":"COBREXA.is_solved","text":"is_solved(opt_model::JuMP.Model) -> Bool\n\n\ntrue if opt_model solved successfully (solution is optimal or locally optimal). false if any other termination status is reached.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimization_model-Tuple{Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}}}","page":"Core functionality","title":"COBREXA.optimization_model","text":"optimization_model(\n cs::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};\n objective,\n optimizer,\n sense\n)\n\n\nConstruct a JuMP Model that describes the precise constraint system into the JuMP Model created for solving in optimizer, with a given optional objective and optimization sense chosen from Maximal, Minimal and Feasible.\n\nAll types of values in the constraint tree must have an overload for substitute_jump.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimized_model-Tuple{Any}","page":"Core functionality","title":"COBREXA.optimized_model","text":"optimized_model(om; output)\n\n\nLike optimized_values, but works directly with a given JuMP model om without applying any settings or creating the optimization model.\n\nTo run the process manually, you can use optimization_model to convert the constraints into a suitable JuMP optimization model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimized_objective-Tuple{Any}","page":"Core functionality","title":"COBREXA.optimized_objective","text":"optimized_objective(\n om\n) -> Union{Nothing, Float64, Vector{Float64}}\n\n\nLike optimized_model but only returns the objective value (or nothing if the model is not solved).\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.substitute_jump-Tuple{ConstraintTrees.LinearValue, Any}","page":"Core functionality","title":"COBREXA.substitute_jump","text":"substitute_jump(\n val::ConstraintTrees.LinearValue,\n vars\n) -> JuMP.AffExpr\n\n\nVery efficiently substitute a ConstraintTrees' LinearValue into a JuMP expression of type AffExpr.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.substitute_jump-Tuple{ConstraintTrees.QuadraticValue, Any}","page":"Core functionality","title":"COBREXA.substitute_jump","text":"substitute_jump(\n val::ConstraintTrees.QuadraticValue,\n vars\n) -> JuMP.QuadExpr\n\n\nVery efficiently substitute a ConstraintTrees' QuadraticValue into a JuMP expression of type QuadExpr.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.variable_vector-Tuple{JuMP.Model}","page":"Core functionality","title":"COBREXA.variable_vector","text":"variable_vector(opt_model::JuMP.Model) -> Any\n\n\nRetrieve the variable vector from a JuMP model created by optimization_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#Task-distribution-support","page":"Core functionality","title":"Task distribution support","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/worker_data.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.worker_local_data","page":"Core functionality","title":"COBREXA.worker_local_data","text":"mutable struct worker_local_data\n\nHelper struct that provides access to local data that are unboxed and cached directly on distributed workers.\n\nUse with get_worker_local_data and Distributed.CachingPool.\n\nFields\n\ntransfer_data::Any: The data that is transferred to the remote worker\nlocal_data::Union{Nothing, Some}: The data that is cached on the remote worker\ntransform::Function: The function that converts the transferred data to locally-cached data on the remote worker\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#COBREXA.get_worker_local_data-Tuple{COBREXA.worker_local_data}","page":"Core functionality","title":"COBREXA.get_worker_local_data","text":"get_worker_local_data(x::COBREXA.worker_local_data) -> Any\n\n\n\"Unwrap\" the worker_local_data on a remote worker to get the local_data out. If required, executes the transform function.\n\nLocal copies of transfer_data are forgotten after the function executes.\n\n\n\n\n\n","category":"method"},{"location":"reference/#API-reference","page":"Contents","title":"API reference","text":"","category":"section"},{"location":"reference/","page":"Contents","title":"Contents","text":"Pages = [\"reference/core.md\", \"reference/frontend.md\", \"reference/builders.md\", \"reference/analysis.md\", \"reference/misc.md\"]\nDepth = 2","category":"page"},{"location":"distributed/2_parallel/#Local-parallel-processing","page":"Local parallel processing","title":"Local parallel processing","text":"","category":"section"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"To run an analysis in parallel, we first need to load the Distributed package and add a few worker processes. For example, we may start 5 local processes (that may utilize 5 CPUs) as follows","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"using Distributed\naddprocs(5)","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"note: `Distributed.jl` installation\nDistributed.jl usually comes pre-installed with Julia distribution, but one may still need to \"enable\" it by typing ] add Distributed.","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"To check that the workers are really there, use workers(). In this case, it should return a vector of worker IDs, very likely equal to [2,3,4,5,6].","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Each of the processes contains a self-sufficient image of Julia that can act independently; in turn the additional processes also consume some memory. Each process with loaded COBREXA.jl and a solver such as HiGHS may consume around 300MB of RAM, which should be taken into account when planning the analysis scale.","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"warning: Using Julia environments with Distributed\nIn certain conditions, the Distributed package does not properly forward the project configuration to the workers, resulting to package version mismatches and other problems. For pipelines that run in custom project folders, use the following form of addprocs instead:addprocs(5, exeflags=`--project=$(Base.active_project())`)","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Packages (COBREXA and the selected solver) must be loaded at all processes, which may ensured using the \"everywhere\" macro (from Distributed package):","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"@everywhere using COBREXA, HiGHS","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Utilizing the prepared worker processes is then straightforward: We pass the list of workers to the selected analysis function using the workers keyword argument, and the parallel processing is orchestrated automatically:","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"model = load_model(\"e_coli_core.xml\")\nresult = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n workers = workers()\n)","category":"page"},{"location":"distributed/#Parallel,-distributed-and-HPC-processing","page":"Contents","title":"Parallel, distributed and HPC processing","text":"","category":"section"},{"location":"distributed/","page":"Contents","title":"Contents","text":"Pages = filter(x -> endswith(x, \".md\"), readdir(\"distributed\", join=true))\nDepth = 2","category":"page"},{"location":"reference/builders/#Constraint-system-builders","page":"Constraint system builders","title":"Constraint system builders","text":"","category":"section"},{"location":"reference/builders/#Generic-constraints","page":"Constraint system builders","title":"Generic constraints","text":"","category":"section"},{"location":"reference/builders/#Comparisons","page":"Constraint system builders","title":"Comparisons","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/compare.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.all_equal_constraints-Tuple{Any, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.all_equal_constraints","text":"all_equal_constraints(\n a,\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constriant tree that makes sure that all values in tree are the same as the value of a.\n\nNames in the output ConstraintTree match the names in the tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.difference_constraint-Tuple{Any, Any, Any}","page":"Constraint system builders","title":"COBREXA.difference_constraint","text":"difference_constraint(\n a,\n b,\n difference_bound\n) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the difference from a to b is within the difference_bound. For example, difference_constraint(-1, 1, 2) will always be valid. Any type of ConstraintTree.Bound can be supplied.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.equal_value_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.equal_value_constraint","text":"equal_value_constraint(a, b) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the values of a and b are the same.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.greater_or_equal_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.greater_or_equal_constraint","text":"greater_or_equal_constraint(\n a,\n b\n) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the value of a is greater than or equal to the the value of b.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.less_or_equal_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.less_or_equal_constraint","text":"less_or_equal_constraint(a, b) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the value of a is less than or equal to the the value of b.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Constraint-scaling","page":"Constraint system builders","title":"Constraint scaling","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/scale.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.scale_bounds-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.scale_bounds","text":"scale_bounds(\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n factor\n) -> Any\n\n\nLinearly scale all bounds in a constraint tree by the factor. This actually changes the model semantics, and may not work in surprising/improper ways with some constraint systems, esp. the MILP and QP ones.\n\nSee also scale_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.scale_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.scale_constraints","text":"scale_constraints(\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n factor\n) -> Any\n\n\nLinearly scale all constraints in a constraint tree by the factor.\n\nSee also scale_bounds.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Sign-splitting","page":"Constraint system builders","title":"Sign splitting","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/unsigned.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.positive_bound_contribution-Tuple{ConstraintTrees.EqualTo}","page":"Constraint system builders","title":"COBREXA.positive_bound_contribution","text":"positive_bound_contribution(\n b::ConstraintTrees.EqualTo\n) -> ConstraintTrees.EqualTo\n\n\nClamp all negative values in the bound to zero, leaving only the \"positive contribution\" to the overall value of the constraint. Used in unsigned_positive_contribution_variables and unsigned_negative_contribution_variables to allocate unidirectional variables.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sign_split_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.sign_split_constraints","text":"sign_split_constraints(; positive, negative, signed)\n\n\nA constraint tree that bound the values present in signed to be sums of pairs of positive and negative contributions to the individual values.\n\nKeys in the result are the same as the keys of signed constraints.\n\nTypically, this can be used to create \"unidirectional\" fluxes together with unsigned_negative_contribution_variables and unsigned_positive_contribution_variables.\n\nUse sign_split_variables to allocate the variables easily.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sign_split_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.sign_split_variables","text":"sign_split_variables(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n positive,\n negative\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nShortcut for making a pair of named variable groups created by unsigned_positive_contribution_variables and unsigned_negative_contribution_variables, in subtrees named by positive and negative.\n\nUse sign_split_constraints to bind the new variables to existing values.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_negative_contribution_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_negative_contribution_constraints","text":"unsigned_negative_contribution_constraints(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n positive::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree that connects positive unsigned variable contributions to signed ones, while acting as negative contributions.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_negative_contribution_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_negative_contribution_variables","text":"unsigned_negative_contribution_variables(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree of variables with negative contributions to the values in cs.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_positive_contribution_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_positive_contribution_constraints","text":"unsigned_positive_contribution_constraints(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n negative::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree that connects negative unsigned variable contributions to signed ones, while acting as positive contributions.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_positive_contribution_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_positive_contribution_variables","text":"unsigned_positive_contribution_variables(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree of variables with positive contributions to the values in cs.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Objectives","page":"Constraint system builders","title":"Objectives","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/objectives.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.squared_sum_error_value-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.squared_sum_error_value","text":"squared_sum_error_value(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n target\n) -> Any\n\n\nConstruct a ConstraintTrees.Value out of squared error (in the RMSE-like squared-error sense) between the values in the constraint tree and the reference target.\n\ntarget is a function that takes a symbol (key) and returns either a Float64 reference value, or nothing if the error of given key should not be considered.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.squared_sum_value-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.squared_sum_value","text":"squared_sum_value(\n x::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nConstruct a ConstraintTrees.Value out of squared sum of all values directly present in a given constraint tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sum_value-Tuple","page":"Constraint system builders","title":"COBREXA.sum_value","text":"sum_value(\n x...\n) -> Union{ConstraintTrees.LinearValue, ConstraintTrees.QuadraticValue}\n\n\nConstruct a ConstraintTrees.Value out of a sum of all values directly present in a given constraint tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Analysis-specific-constriants","page":"Constraint system builders","title":"Analysis-specific constriants","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/loopless.jl\", \"src/builders/knockout.jl\", \"src/builders/enzymes.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.loopless_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.loopless_constraints","text":"loopless_constraints(\n;\n fluxes,\n loopless_direction_indicators,\n loopless_driving_forces,\n internal_reactions,\n internal_nullspace,\n flux_infinity_bound,\n driving_force_nonzero_bound,\n driving_force_infinity_bound\n)\n\n\nConstruct the loopless constraint system that binds fluxes of all internal_reactions to direction of loopless_direction_indicators and connects them to loopless_driving_forces. The solution is bounded to lie in internal_nullspace (which is a sufficient algebraic condition for loop-less-ness).\n\nThe indicators must be discrete variables, valued 1 if the reaction flux goes forward, or 0 if the reaction flux is reversed.\n\nThe simplest (but by no means the fastest) way to obtain a good internal_nullspace is to use LinearAlgebra.nullspace with the internal reactions' stoichiometry matrix. Rows of internal_nullspace must correspond to internal_reactions.\n\nflux_infinity_bound is used as the maximal bound for fluxes (for constraints that connect them to indicator variables); it should optimally be greater than the maximum possible absolute value of any flux in the original model.\n\ndriving_force_nonzero_bound and driving_force_infinity_bound are similarly used to limit the individual reaction's driving forces.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.knockout_constraints-Union{Tuple{F}, Tuple{F, ConstraintTrees.Tree{ConstraintTrees.Constraint}}} where F<:Function","page":"Constraint system builders","title":"COBREXA.knockout_constraints","text":"knockout_constraints(\n knockout_test::Function,\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a ConstraintTree that knocks out fluxes given by the predicate knockout_test. The predicate function is called with a single parameter (the key of the flux in tree fluxes) and must return a boolean. Returning true means that the corresponding flux (usually a reaction flux) will be knocked out.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.enzyme_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.enzyme_constraints","text":"enzyme_constraints(\n;\n fluxes_forward,\n fluxes_reverse,\n isozyme_forward_amounts,\n isozyme_reverse_amounts,\n kcat_forward,\n kcat_reverse,\n isozyme_gene_product_stoichiometry,\n gene_product_molar_mass,\n capacity_limits,\n isozyme_flux_forward_balance_name,\n isozyme_flux_reverse_balance_name,\n gene_product_amounts_name,\n gene_product_capacity_name\n)\n\n\nConnect variables returned by enzyme_variables to unidirectional fluxes. This is used to construct the contraint system for enzyme_constrained_flux_balance_constraints.\n\nParameters fluxes_forward, fluxes_reverse, isozyme_forward_amounts, isozyme_reverse_amounts and gene_product_amounts should correspond to parameters and results of enzyme_variables.\n\nFurther, parameter functions kcat_forward and kcat_reverse specify the turnover numbers for reaction and isozyme IDs given in parameters; isozyme_gene_product_stoichiometry specifies the composition of the reaction-isozyme IDs given in parameter by returning an interable mapping of gene product IDs to numbers (such as Dict{Symbol, Float64}), and gene_product_molar_mass specifies a numeric mass for a given gene product ID. All parameter functions may return nothing, at which point the given object is considered nonexistent and is omitted from constraints.\n\ncapacity_limits is an interable container of triples (limit_id, gene_product_ids, capacity_bound) which are converted to a constraint identified by the limit_id that limits the total mass of gene_product_ids (which is any iterable container) by capacity_bound.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.enzyme_variables-Tuple{}","page":"Constraint system builders","title":"COBREXA.enzyme_variables","text":"enzyme_variables(\n;\n fluxes_forward,\n fluxes_reverse,\n isozyme_ids,\n isozyme_forward_ids,\n isozyme_reverse_ids,\n isozyme_forward_amounts_name,\n isozyme_reverse_amounts_name\n)\n\n\nReturns a constraint tree with enzyme capacity constraints, added for reactions in fluxes_forward and fluxes_reverse. This is used to construct the constraint system in enzyme_constrained_flux_balance_constraints.\n\nParameter function isozyme_ids takes a reaction ID and returns nothing if the reaction does not have isozymes associated with it, or an iterable container of all the isozyme IDs for that reaction (as Symbols).\n\nParameters isozyme_forward_ids and isozyme_reverse_ids can be used to fine-tune the generated isozymes in either direction; both default to isozyme_ids.\n\nThe keys in the output constraint tree can be customized by setting isozyme_forward_amounts_name, isozyme_reverse_amounts_name and gene_product_amounts_name.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_amount_variables-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_amount_variables","text":"isozyme_amount_variables(\n fluxes,\n flux_isozymes\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nCreate a ConstraintTree with variables for isozyme contributions to reaction fluxes. The tree has 2 levels: the first contains all reaction flux IDs that have isozymes, the second contains the isozyme IDs for each reaction flux.\n\nfluxes should be anything that can be iterated to give reaction flux IDs.\n\nflux_isozymes is a function that, for a given reaction flux ID, returns anything iterable that contains the isozyme IDs for the given reaction flux. Returning an empty iterable prevents allocating the subtree for the given flux.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_flux_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_flux_constraints","text":"isozyme_flux_constraints(\n isozyme_amounts::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n kcat\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nA constraint tree that sums up partial contributions of reaction isozymes to the fluxes of reactions.\n\nFor practical purposes, both fluxes and isozymes are here considered to be unidirectional, i.e., one would typically apply this twice to constraint both \"forward\" and \"reverse\" fluxes.\n\nFunction kcat should return the kcat value for a given reaction and isozyme (IDs of which respectively form the 2 parameters for each call).\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_gene_product_amount_constraints-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_gene_product_amount_constraints","text":"isozyme_gene_product_amount_constraints(\n isozyme_amounts,\n isozyme_stoichiometry\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nA constraint tree that computes the gene product amounts from given isozyme amounts their multiplicities (aka. stoichiometries, protein units, ...) given by isozyme_stoichiometry.\n\nValues in ConstraintTree gene_product_amounts should describe the gene product allocations. Allocation for the isozyme is ignored if the gene product is missing in gene_product_amounts.\n\nisozyme_amounts is an iterable that contains several ConstraintTrees that describe the allocated isozyme amounts (typically these would be created by isozyme_amount_variables. The multiple trees may describe several different kinds of isozyme use, e.g., you can use it to pass in both forward- and reverse-direction amounts at once. To only use a single tree, use an uni-tuple: isozyme_amounts = tuple(my_tree).\n\nParameter function isozyme_stoichiometry gets called with a reaction and isozyme IDs as given by the isozyme amount trees. It should return nothing in case there's no information – in such case, the isozyme is not going to be included in the calculation of gene product mass.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.simplified_enzyme_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.simplified_enzyme_constraints","text":"simplified_enzyme_constraints(\n;\n fluxes_forward,\n fluxes_reverse,\n mass_cost_forward,\n mass_cost_reverse,\n capacity_limits\n)\n\n\nBuild a constraint system that bounds fluxes according to their enzyme mass requirements, with respect to per-reaction enzyme mass costs.\n\nParameter functions mass_cost_forward and mass_cost_reverse take a flux ID (corresponding to a flux in fluxes_forward and fluxes_reverse) and return the enzyme mass required to catalyze one \"unit\" of reaction in the forward or reverse direction, respectively. Returning nothing ignores the mass cost.\n\ncapacity_limits is an iterable container of triples (limit_id, flux_ids, bound), which creates the capacity bounds over groups of fluxes (in the same manner as for gene products in enzyme_constraints).\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.simplified_isozyme_gene_product_amount_constraints-Tuple","page":"Constraint system builders","title":"COBREXA.simplified_isozyme_gene_product_amount_constraints","text":"simplified_isozyme_gene_product_amount_constraints(\n x...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nLike isozyme_gene_product_amount_constraints, but works with the \"simplified\" view where each reaction has an uniquely determined catalytic isozyme, as with simplified_enzyme_constraints.\n\nAs the main difference, the arguments are tuples that contain first the constraint tree without the \"isozyme\" layer (i.e., fluxes), and second a function that returns the gene product stoichiometry and the turnover number (again in a tuple) for the given flux identifier.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Interfacing-of-constraint-systems","page":"Constraint system builders","title":"Interfacing of constraint systems","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/interface.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.interface_constraints-Tuple{Any}","page":"Constraint system builders","title":"COBREXA.interface_constraints","text":"interface_constraints(\n kv;\n kwargs...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nOverload of interface_constraints for general key-value containers.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.interface_constraints-Tuple{Vararg{Pair}}","page":"Constraint system builders","title":"COBREXA.interface_constraints","text":"interface_constraints(\n ps::Pair...;\n default_interface,\n out_interface,\n out_balance,\n ignore,\n bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nJoin multiple constraint tree modules with interfaces into a bigger module with an interface.\n\nModules are like usual constraint trees, but contain an explicitly declared interface part, marked properly in arguments using e.g. a tuple (the parameters should form a dictionary constructor that would generally look such as :module_name => (module, module.interface); the second tuple member may also be specified just by name as e.g. :interface, or omitted while relying on default_interface).\n\nInterface parts get merged and constrained to create a new interface; networks are intact with disjoint variable sets.\n\nCompatible modules with ready-made interfaces may be created e.g. by flux_balance_constraints.\n\nignore may be used to selectively ignore parts of interfaces given the \"module name\" identifier and constraint path in the interface (these form 2 parameters passed to ignore). Similarly, bound may be used to specify bounds for the new interface, if required.\n\n\n\n\n\n","category":"method"},{"location":"distributed/1_functions/#Parallel-processing-overview","page":"Parallel processing overview","title":"Parallel processing overview","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Distributed processing in Julia is represented mainly by the package Distributed.jl.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"COBREXA.jl is able to utilize this existing system to almost transparently run the large parallelizable analyses on multiple CPU cores and multiple computers connected through the network. Ultimately, the approach scales to thousands of computing nodes in large HPC facilities.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Users may run the analyses in parallel to gain speed-ups. The usual workflow in COBREXA.jl is quite straightforward:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Import the Distributed package and add worker processes, e.g. using addprocs.\nPick an analysis function that can be parallelized (such as screen or flux_variability_analysis) and prepare it to work on the data.\nPass the desired set of worker IDs to the function using workers= argument, in the simplest form using e.g. screen(..., workers=workers()).\nWorker communication will be managed automatically, and the results will be computed \"as usual\", just appropriately faster.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Specific documentation is available about running parallel analysis locally and running distributed analysis in HPC clusters.","category":"page"},{"location":"distributed/1_functions/#Functions-that-support-parallelization","page":"Parallel processing overview","title":"Functions that support parallelization","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"The functions that support parallel execution include:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"flux_variability_analysis (and the underlying constraints_variability)\nscreen and screen_optimization_model\ngene_knockouts\nflux_sample (and the underlying sample_constraints)\nobjective_production_envelope (and the underlying constraints_objective_envelope)","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Notably, the screening functions can be reused to run many other kinds of analyses which, in turn, inherit the parallelizability. This includes a wide range of use-cases that can thus be parallelized very easily:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"single and multiple gene deletions (and other genetic modifications)\nmultiple reaction knockouts\nenvelope-like production profiles (e.g., enzyme-constrained growth profiles)\ngrowth media explorations (such as explorations of metabolite depletion)","category":"page"},{"location":"distributed/1_functions/#Mitigating-parallel-inefficiencies","page":"Parallel processing overview","title":"Mitigating parallel inefficiencies","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Ideally, the speedup gained by parallel processing should be proportional to the amount of hardware one add as the workers. To reach that, it is beneficial to be aware of factors that reduce the parallel efficiency, which can be summarized as follows:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Parallelization within single runs of the linear solver is typically not supported (and if it is, it may be inefficient for common problem sizes). Normally, we want to parallelize the analyzes that comprise multiple independent runs of the solvers.\nSome analysis function, such as flux_variability_analysis, have serial parts that can not be parallelized by default. Usually, pipelines may avoid the inefficiency by precomputing the serial analysis parts without involving the cluster of the workers.\nFrequent worker communication may vastly reduce the efficiency of parallel processing; typically this happens if the time required for individual analysis steps is smaller than the network round-trip-time to the worker processes. Do not use parallelization for very small tasks.\nTransferring large amounts of data among workers may hamper parallel efficiency too. Use a single loaded model data object and apply any required small modifications directly on the workers to avoid this kind of inefficiency.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"note: Cost of the distribution and parallelization overhead\nBefore allocating extra resources into the distributed execution, always check that the tasks are properly parallelizable and sufficiently large to saturate the computation resources, so that the invested energy is not wasted. Amdahl's and Gustafson's laws give a better overview of the sources and consequences of the parallelization inefficiencies, and the costs of the resulting overhead.","category":"page"},{"location":"reference/misc/#Miscellaneous-functions","page":"Miscellaneous functions","title":"Miscellaneous functions","text":"","category":"section"},{"location":"reference/misc/","page":"Miscellaneous functions","title":"Miscellaneous functions","text":"Modules = [COBREXA]\nPages = [\"src/misc/bounds.jl\", \"src/misc/breaks.jl\", \"src/misc/maybe.jl\", \"src/misc/settings.jl\", \"src/misc/trees.jl\"]","category":"page"},{"location":"reference/misc/#COBREXA.absolute_tolerance_bound-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.absolute_tolerance_bound","text":"absolute_tolerance_bound(tolerance) -> COBREXA.var\"#404#405\"\n\n\nMake a function that returns absolute tolerance bounds, i.e. value - tolerance and value + tolerance in a tuple, in the increasing order.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.relative_tolerance_bound-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.relative_tolerance_bound","text":"relative_tolerance_bound(tolerance) -> COBREXA.var\"#406#407\"\n\n\nMake a function that returns relative tolerance bounds, i.e. value / tolerance and value * tolerance in a tuple, in the increasing order.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.remove_bounds-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Miscellaneous functions","title":"COBREXA.remove_bounds","text":"remove_bounds(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nMake a copy of a constraint tree with all bounds removed. This is helpful when creating large trees only for for value representation purposes, which should not directly constraint anything (and thus should not put additional stress on the constraint solver).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.break_interval-Tuple{Any, Any, Int64}","page":"Miscellaneous functions","title":"COBREXA.break_interval","text":"break_interval(lower, upper, breaks::Int64) -> Any\n\n\nBreak an interval into breaks (count) breaks.\n\nUsed for computing breaks in objective_production_envelope.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.maybemap","page":"Miscellaneous functions","title":"COBREXA.maybemap","text":"maybemap(f, ::Nothing)\nmaybemap(f, ::Nothing, def) -> Any\n\n\nHelper for applying functions to stuff that might be nothing.\n\n\n\n\n\n","category":"function"},{"location":"reference/misc/#COBREXA.set_objective_sense-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.set_objective_sense","text":"set_objective_sense(\n objective_sense\n) -> COBREXA.var\"#410#411\"\n\n\nChange the objective sense of optimization. Accepted arguments include Minimal, Maximal, and Feasible.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_optimizer-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.set_optimizer","text":"set_optimizer(optimizer) -> COBREXA.var\"#412#413\"\n\n\nChange the JuMP optimizer used to run the optimization.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_optimizer_attribute-Tuple{Any, Any}","page":"Miscellaneous functions","title":"COBREXA.set_optimizer_attribute","text":"set_optimizer_attribute(\n attribute_key,\n value\n) -> COBREXA.var\"#414#415\"\n\n\nChange a named JuMP optimizer attribute. The attribute names are optimizer-specific, refer to the JuMP documentation and the documentation of the specific optimizer for usable keys and values.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_time_limit-Tuple{Real}","page":"Miscellaneous functions","title":"COBREXA.set_time_limit","text":"set_time_limit(limit::Real) -> COBREXA.var\"#416#417\"\n\n\nSet a time limit in seconds for the optimizer computation (shortcut for set_time_limit_sec from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.silence-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.silence","text":"silence\n\nDisable all output from the JuMP optimizer (shortcut for set_silent from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.unsilence-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.unsilence","text":"unsilence\n\nEnable output from the JuMP optimizer (shortcut for unset_silent from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.tree_deflate-Union{Tuple{U}, Tuple{T}, Tuple{Any, ConstraintTrees.Tree{T}}, Tuple{Any, ConstraintTrees.Tree{T}, Type{U}}} where {T, U}","page":"Miscellaneous functions","title":"COBREXA.tree_deflate","text":"tree_deflate(f, x::ConstraintTrees.Tree{T}) -> Vector\ntree_deflate(\n f,\n x::ConstraintTrees.Tree{T},\n ::Type{U}\n) -> Vector\n\n\nExtract all elements of a ConstraintTrees.Tree in order and return them in a Vector transformed by f. If the order is not modified, one can re-insert a vector of modified elements into the same-shaped tree using tree_reinflate.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.tree_reinflate-Union{Tuple{T}, Tuple{ConstraintTrees.Tree, Vector{T}}} where T","page":"Miscellaneous functions","title":"COBREXA.tree_reinflate","text":"tree_reinflate(\n x::ConstraintTrees.Tree,\n elems::Array{T, 1}\n) -> ConstraintTrees.Tree\n\n\nInsert a Vector of elements into the \"values\" of a ConstraintTrees.Tree. The order of elements is given by tree_deflate.\n\n\n\n\n\n","category":"method"},{"location":"examples/#Examples","page":"Contents","title":"Examples","text":"","category":"section"},{"location":"examples/","page":"Contents","title":"Contents","text":"Pages = filter(x -> endswith(x, \".md\"), readdir(\"examples\", join=true))\nDepth = 2","category":"page"},{"location":"structure/#Logical-structure-of-COBREXA","page":"Core concepts and structure","title":"Logical structure of COBREXA","text":"","category":"section"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"COBREXA uses ConstraintTrees.jl for internal representation of all metabolic modeling problems. In short, constraint trees are \"tidy\" representations of the constraint-based modeling problems, which store information about the variables' participation in named constraints. They provide several main benefits:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"User is freed from having to allocate variables – all variables are present only implicitly, are described by their \"semantics\" by participation in constraints, and are allocated automatically whenever the user connects the constraint trees.\nThere is no need for complicated index manipulation (as with linear-algebraic \"matrixy\" model representations) nor for various identifier mangling schemes – constraint trees provide named interface for everything, and identifiers can be organized into directories to prevent name clashes in various multi-compartment and community models.\nContrary to the fixed model representations (such as SBML or JSON models), ConstraintTrees do not possess a semantic of a \"single flux-based model\" and are thus infinitely extensible, allowing easy creation, manipulation and storage of even very complicated constraint systems.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"With ConstraintTrees, the typical workflow in COBREXA is as follows:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"\"Raw\" data and base model data are loaded from semantically organized models (such as SBML, or lab measurements in CSV or other tabular format)\nCOBREXA functions are used to convert these to a constraint tree that properly describes the problem at hand\npossibly, multiple types and groups of raw data can be soaked into the constraint tree\nAnalysis functionality of COBREXA is used to solve the system described by the constraint tree, and extract useful information from the solutions.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"COBREXA mainly provides functionality to make this workflow easy to use for many various purposes:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"Front-end functions help to run the 3 above steps easily without any intermediate steps. These include:\ncommunity_flux_balance_analysis\nenzyme_constrained_flux_balance_analysis\nflux_balance_analysis\nflux_sample\ngene_knockouts\nlinear_metabolic_adjustment_minimization_analysis\nloopless_flux_balance_analysis\nmax_min_driving_force_analysis\nmetabolic_adjustment_minimization_analysis\nobjective_production_envelope\nsimplified_enzyme_constrained_flux_balance_analysis\nFront-end functions call various Front-end constraint tree builders which translate various kinds of raw data to the constraint trees, such as:\ncommunity_flux_balance_constraints\nenzyme_constrained_flux_balance_constraints\nflux_balance_constraints\nflux_variability_analysis\ngene_knockout_constraints\nlinear_metabolic_adjustment_minimization_constraints\nlog_concentration_constraints\nloopless_flux_balance_constraints\nmax_min_driving_force_constraints\nmetabolic_adjustment_minimization_constraints\nsimplified_enzyme_constrained_flux_balance_constraints\nAdditional constraint builders are provided to decorate the \"raw\" model representations with various additional semantics and limits:\nall_equal_constraints, greater_or_equal_constraint and similar ones\nknockout_constraints\nloopless_constraints\nscale_bounds\nscale_constraints\nsign_split_variables and sign_split_constraints squared_sum_error_value\nsum_value, squared_sum_value and\nSome functions are provided to join the constraint trees via interfaces, simplifying e.g. the creation of community or multi-organ models,\nflux_balance_constraints can automatically generate interfaces suitable for community-style and multi-compartment-style metabolic modeling from the annotations in the FBC models\ninterface_constraints joins the \"modules\" with prepared interfaces together\nFinally, the analysis functions simulate the model in the constraint tree mechanistically and extract analysis results:\nconstraints_objective_envelope\nparsimonious_optimized_values\nsample_constraints\nsample_constraint_variables\nscreen_optimization_model\nscreen\noptimized_values\nconstraints_variability","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"tip: Exploring and customizing the front-end analysis functions\nTo know which builder function is used to create or modify some kind of constraint tree in COBREXA, use the \"link to source code\" feature in the front-end function's individual documentation. The source code of front-end functions is written to be as easily re-usable as possible – one can simply copy-paste it into the program, and immediately start building specialized and customized front-end functions.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"Technical description of the constraint tree functionality, together with examples of basic functionality and many useful utility functions is available in dedicated documentation of ConstraintTrees.jl.","category":"page"},{"location":"#COBREXA.jl","page":"Home","title":"COBREXA.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Modules = [COBREXA]\nPages = [\"src/COBREXA.jl\"]","category":"page"},{"location":"#COBREXA.COBREXA","page":"Home","title":"COBREXA.COBREXA","text":"module COBREXA\n\nCOnstraint Based Reconstruction and EXascale Analysis. COBREXA provides functions for construction, modification, simulation and analysis of constraint-based metabolic models that follows the COBRA methodology.\n\nCOBREXA is built as a front-end for the combination of AbstractFBCModels.jl (provides the model I/O), ConstraintTrees.jl (provides the constraint system organization), Distributed.jl (provides HPC execution capability), and JuMP.jl (provides the solvers).\n\nSee the online documentation for a complete description of functionality aided by copy-pastable examples.\n\nTo start quickly, load your favorite JuMP-compatible solver, use load_model to read a metabolic model from the disk, and solve it with flux_balance_analysis.\n\n\n\n\n\n","category":"module"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"EditURL = \"04-community-models.jl\"","category":"page"},{"location":"examples/04-community-models/#Community-FBA-models","page":"Community FBA models","title":"Community FBA models","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"using COBREXA","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Here we construct a community FBA model of two E. coli \"core\" models that can interact by exchanging selected metabolites. To do this, we will need the model, which we can download if it is not already present.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Additionally to COBREXA and the model format package, we will need a solver and a few supporting packages.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"import JSONFBCModels\nimport HiGHS\nimport AbstractFBCModels.CanonicalModel as CM\nimport ConstraintTrees as C","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The core model has an artificial bound on input glucose; here we unblock that one, and we are going to add a community-global glucose intake bound later.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"ecoli = load_model(\"e_coli_core.json\", CM.Model)\necoli.reactions[\"EX_glc__D_e\"].lower_bound = -1000.0\necoli.reactions[\"EX_glc__D_e\"].upper_bound = 1000.0","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To create a community that is actually interesting, we need some diversity. Here we simply block a different reaction in each of the community members:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"ecoli1 = deepcopy(ecoli)\necoli1.reactions[\"CYTBD\"].lower_bound = ecoli1.reactions[\"CYTBD\"].upper_bound = 0.0\necoli2 = deepcopy(ecoli)\necoli2.reactions[\"FBA\"].lower_bound = ecoli2.reactions[\"FBA\"].upper_bound = 0.0","category":"page"},{"location":"examples/04-community-models/#Analysing-the-community","page":"Community FBA models","title":"Analysing the community","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To construct the community, we have to provide identifiers for the models (these will be used in the constraint tree), and corresponding models with the abundances.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"my_community = Dict(\"bug1\" => (ecoli1, 0.2), \"bug2\" => (ecoli2, 0.8))","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The community is constructed and analysed using community_flux_balance_analysis:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"solution = community_flux_balance_analysis(\n my_community,\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/04-community-models/#Investigating-the-solution","page":"Community FBA models","title":"Investigating the solution","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"We can now e.g. observe the differences in individual pairs of exchanges:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"C.zip(\n tuple,\n solution.bug1.interface.exchanges,\n solution.bug2.interface.exchanges,\n Tuple{Float64,Float64},\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"...or use screen to efficiently find out which composition is best:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"screen(0.0:0.1:1.0) do ratio2\n ratio1 = 1 - ratio2\n res = community_flux_balance_analysis(\n [(\"bug1\" => (ecoli1, ratio1)), (\"bug2\" => (ecoli2, ratio2))],\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n interface = :sbo, # usually more reproducible\n optimizer = HiGHS.Optimizer,\n )\n (ratio1, ratio2) => (isnothing(res) ? nothing : res.community_biomass)\nend","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"(The result seem like the bug1 is eventually going to be completely out-grown by the other one.)","category":"page"},{"location":"examples/04-community-models/#Note:-interfaces-of-constraint-systems","page":"Community FBA models","title":"Note: interfaces of constraint systems","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Internally, the community is connected via interfaces, which are small constraint trees (typically with no bounds attached) that describe parts of the constraint system that can be easily attached to other parts.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The best kind of interface to choose generally differs from model to model. COBREXA gives a few \"default\" choices that cover a good part of sensible metabolic modeling. For example, if the model contains SBO annotations, we can ask for the interface created using the annotated reactions:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"flux_balance_constraints(ecoli, interface = :sbo).interface","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"If there are no annotations, we can still at least detect the boundary reactions and make an interface out of them:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"flux_balance_constraints(ecoli, interface = :boundary).interface","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The default kind of interface in community_flux_balance_analysis is :identifier_prefixes, which relies on usual prefixes of reaction names (such as EX_ for exchanges).","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Even if all of these methods fail, a suitable interface yourself can be produced manually. (Additionally, we can do useful stuff, such as removing the unnecessary bounds from the exchange descriptions.)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_model = flux_balance_constraints(ecoli)\ncustom_model *= remove_bounds(\n :interface^C.ConstraintTree(\n :biomass => custom_model.fluxes.BIOMASS_Ecoli_core_w_GAM,\n :exchanges => C.ConstraintTree(\n k => v for (k, v) in custom_model.fluxes if startswith(string(k), \"EX_\")\n ),\n ),\n)\ncustom_model.interface.exchanges","category":"page"},{"location":"examples/04-community-models/#Connecting-the-community-constraints-manually","page":"Community FBA models","title":"Connecting the community constraints manually","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To connect such interfaces into a community model, simply use function interface_constraints (which is how community_flux_balance_analysis constructs the community model internally via community_flux_balance_constraints). The assembly might look roughly as follows:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_community = interface_constraints(\n \"bug1\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.CYTBD.value, 0),\n 0.2,\n ),\n \"bug2\" =>\n (custom_model * :handicap^C.Constraint(custom_model.fluxes.FBA.value, 0), 0.8),\n bound = r -> r == (:exchanges, :EX_glc__D_e) ? C.Between(-10, 0) : nothing,\n)\n\ncustom_community.interface.exchanges","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"For the model to work properly, we would need to add several other things, mainly the equal growth constraints (possibly via all_equal_constraints). community_flux_balance_constraints add these automatically, so we can equivalently just supply the constraint trees, and re-use the rest of the implementation:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_community = community_flux_balance_constraints(\n [\n \"bug1\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.CYTBD.value, 0),\n 0.2,\n ),\n \"bug2\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.FBA.value, 0),\n 0.8,\n ),\n ],\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"This can be solved with the usual means, reaching the same result as above:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_solution = optimized_values(\n custom_community,\n objective = custom_community.community_biomass.value,\n output = custom_community.community_biomass,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"This page was generated using Literate.jl.","category":"page"}] +[{"location":"reference/analysis/#Specialized-analysis-functions","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/solver.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.optimized_values-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.optimized_values","text":"optimized_values(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n settings,\n output,\n kwargs...\n)\n\n\nMake an JuMP model out of constraints using optimization_model (most arguments are forwarded there), then apply the settings, optimize the model, and return either nothing if the optimization failed, or output substituted with the solved values (output defaults to constraints.\n\nFor a \"nice\" version for simpler finding of metabolic model optima, use flux_balance_analysis.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Parsimonious-analyses","page":"Specialized analysis functions","title":"Parsimonious analyses","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/parsimonious.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.parsimonious_optimized_values-Tuple{Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}}}","page":"Specialized analysis functions","title":"COBREXA.parsimonious_optimized_values","text":"parsimonious_optimized_values(\n constraints::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};\n objective,\n objective_value,\n settings,\n parsimonious_objective,\n parsimonious_optimizer,\n parsimonious_sense,\n parsimonious_settings,\n tolerances,\n output,\n kwargs...\n)\n\n\nOptimize the system of constraints to get the optimal objective value. Then try to find a \"parsimonious\" solution with the same objective value, which optimizes the parsimonious_objective (possibly also switching optimization sense, optimizer, and adding more settings).\n\nFor efficiency, everything is performed on a single instance of JuMP model.\n\nA simpler version suitable for direct work with metabolic models is available in parsimonious_flux_balance_analysis.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Ensemble-solving","page":"Specialized analysis functions","title":"Ensemble solving","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/screen.jl\", \"src/analysis/variability.jl\", \"src/analysis/envelope.jl\" ]","category":"page"},{"location":"reference/analysis/#COBREXA.screen-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.screen","text":"screen(f, args...; workers) -> Any\n\n\nExecute a function with arguments given by args on workers.\n\nThis is merely a nice shortcut for Distributed.pmap running over a Distributed.CachingPool of the given workers.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.screen_optimization_model-Tuple{Any, ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.screen_optimization_model","text":"screen_optimization_model(\n f,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n args...;\n objective,\n sense,\n optimizer,\n settings,\n workers\n)\n\n\nExecute a function arguments from arrays args on workers, with a pre-cached JuMP optimization model created from constraints, objective and optimizer using optimization_model. settings are applied to the optimization model before first execution of f.\n\nSince the model is cached and never re-created, this may be faster than just plain screen in many use cases.\n\nThe function f is supposed to take length(args)+1 arguments, the first argument is the JuMP model, and the other arguments are taken from args as with Distributed.pmap. While the model may be modified in place, one should take care to avoid modifications that change results of subsequent invocations of f, as that almost always results in data races and irreproducible executions. Ideally, all modifications of the model should be either manually reverted in the invocation of f, or the future invocations of f must be able to overwrite them.\n\nf may use optimized_model to extract results easily w.r.t. some given ConstraintTree.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_variability-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.constraints_variability","text":"constraints_variability(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n targets::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n kwargs...\n)\n\n\nSimplified variant of constraints_variability that computes the variability of all values in tree targets, and returns a new tree of the same shape as targets that contains tuples for minima and maxima.\n\nAll other arguments are forwarded to the matrix-returning overload of constraints_variability.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_variability-Union{Tuple{T}, Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vector{<:ConstraintTrees.Value}}} where T","page":"Specialized analysis functions","title":"COBREXA.constraints_variability","text":"constraints_variability(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n targets::Vector{<:ConstraintTrees.Value};\n output,\n output_type,\n kwargs...\n)\n\n\nIn a feasible space specified by constraints, compute the feasible range of individual targets values. The output is a matrix with one column for minima and second column for maxima of the individual target's values.\n\nThis is used e.g. to compute the flux_variability_analysis, and can be viewed as a more generalized version thereof.\n\noutput and output_type can be used to customize the information reported from the solved models.\n\nExtra arguments are passed to screen_optimization_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.constraints_objective_envelope-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.constraints_objective_envelope","text":"constraints_objective_envelope(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n dims...;\n objective,\n sense,\n optimizer,\n settings,\n workers\n)\n\n\nOptimize the system given by constraints and objective with optimizer (with custom settings) for all combination of constriants given by dims.\n\ndims should be compatible with pairs that assign a sequence of breaks to a ConstraintTrees.Value: For example, organism.fluxes.PFK => 1:3 will compute optima of the model with the flux through PFK constrained to be equal to 1, 2 and 3.\n\nIn turn, all dims are converted to groups of equality constraints, and the model is solved for all combinations. Shape of the output matrix corresponds to Iterators.product(last.(dims)...).\n\nOperation is parallelized by distribution over workers; by default all Distributed.workers() are used.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Sampling","page":"Specialized analysis functions","title":"Sampling","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/sample.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.sample_chain_achr-Union{Tuple{SM}, Tuple{M}, Tuple{V}, Tuple{F}} where {F<:Real, V<:AbstractVector{F}, M<:AbstractMatrix{F}, SM<:AbstractMatrix{F}}","page":"Specialized analysis functions","title":"COBREXA.sample_chain_achr","text":"sample_chain_achr(\n sample_c::AbstractArray{F<:Real, 2};\n variable_lower_bounds,\n variable_upper_bounds,\n coupling,\n lower_bounds,\n upper_bounds,\n epsilon,\n collect_iterations,\n generator\n)\n\n\nImplementation of a single chain run for the Artificially-Centered Hit and Run algorithm (ACHR).\n\nTo use this on a model, use flux_sample or sample_constraints; most parameters are filled in correctly by these functions.\n\nepsilon is defaulted from configuration.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.sample_constraint_variables-Tuple{Function, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Specialized analysis functions","title":"COBREXA.sample_constraint_variables","text":"sample_constraint_variables(\n sampler::Function,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n start_variables,\n seed,\n workers,\n n_chains,\n kwargs...\n)\n\n\nSample the feasible space constrained by constraints by sampling algorithm sampler, using the start_variables as a \"warm-up\" for the sampling runs. Random values are derived from the seed. Computation of individual n_chains chains by sampler is parallelized over workers using screen. Extra arguments are passed to sampler.\n\nThis function returns a matrix of the samples (one sample per row). To nicely aggregate the statistics in the constraint tree, use sample_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.sample_constraints-Union{Tuple{T}, Tuple{Function, ConstraintTrees.Tree{ConstraintTrees.Constraint}}} where T","page":"Specialized analysis functions","title":"COBREXA.sample_constraints","text":"sample_constraints(\n sampler::Function,\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n output,\n aggregate,\n aggregate_type,\n kwargs...\n)\n\n\nA front-end for sample_constraint_variables that saves the sampling results in a constraint tree of the same shape as output. Additionally, aggregate function and aggregate_type can be specified to customize the output.\n\nAll other parameters are forwarded to sample_constraint_variables.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#Analysis-front-end-API-helpers","page":"Specialized analysis functions","title":"Analysis front-end API helpers","text":"","category":"section"},{"location":"reference/analysis/","page":"Specialized analysis functions","title":"Specialized analysis functions","text":"Modules = [COBREXA]\nPages = [\"src/analysis/frontend.jl\"]","category":"page"},{"location":"reference/analysis/#COBREXA.frontend_optimized_values-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.frontend_optimized_values","text":"frontend_optimized_values(\n builder,\n args...;\n builder_kwargs,\n objective,\n output,\n sense,\n optimizer,\n settings,\n kwargs...\n)\n\n\nA helper that converts a front-end constraint builder function (the output of which would normally be just passed through optimized_values) to front-end analysis function.\n\n\n\n\n\n","category":"method"},{"location":"reference/analysis/#COBREXA.frontend_parsimonious_optimized_values-Tuple{Any, Vararg{Any}}","page":"Specialized analysis functions","title":"COBREXA.frontend_parsimonious_optimized_values","text":"frontend_parsimonious_optimized_values(\n builder,\n args...;\n builder_kwargs,\n objective,\n objective_value,\n output,\n sense,\n optimizer,\n settings,\n parsimonious_objective,\n parsimonious_optimizer,\n parsimonious_sense,\n parsimonious_settings,\n tolerances,\n kwargs...\n)\n\n\nA helper that converts a parsimonious-style front-end constraint builder function to front-end analysis function.\n\nLike frontend_optimized_values, but internally calls parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"EditURL = \"06b-screening.jl\"","category":"page"},{"location":"examples/06b-screening/#Screening-through-many-model-variants","page":"Screening through many model variants","title":"Screening through many model variants","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen is a function that you can use to run many different simulations on many different variants of the model efficiently in parallel.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nimport ConstraintTrees as C\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Screening is done as follows: We specify a range of values to examine (in the example below to an actual range of -10 to 0), but any vector-like list of things can be used), and write a short \"analysis\" function that takes one of the values from the range as an argument and runs an analysis for that given value.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Here, we solve 11 different optimization problems for different bounds of the oxygen exchange:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(-10:0) do o2_bound\n c = flux_balance_constraints(model)\n c.fluxes.EX_o2_e.bound = C.EqualTo(o2_bound)\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Screening-in-multiple-dimensions","page":"Screening through many model variants","title":"Screening in multiple dimensions","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"The simplest way to screen through multi-dimensional arrays is to use an iterator product. In the result, we receive a whole matrix of results instead of a vector.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(Iterators.product(-10:2:0, 0:2:10)) do (o2_bound, co2_bound)\n c = flux_balance_constraints(model)\n c.fluxes.EX_o2_e.bound = C.EqualTo(o2_bound)\n c.fluxes.EX_co2_e.bound = C.EqualTo(co2_bound)\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Screening-through-non-numeric-properties","page":"Screening through many model variants","title":"Screening through non-numeric properties","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"If the problem at hand can not be expressed with mere ranges, we can specify vectors with any values. The following code examines the inter-dependency of blocking selected transport reactions together with selected exchanges, with 2 different bounds that implement the block. Because of 3-dimensional input, the result is expectably a 3-dimensional array:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(\n Iterators.product(\n [:H2Ot, :CO2t, :O2t, :NH4t], # a set of transport reactions\n [:EX_h2o_e, :EX_co2_e, :EX_o2_e, :EX_nh4_e], # a set of exchanges\n [C.Between(-0.1, 0.1), C.Between(-1, 1)], # bounds\n ),\n) do (transport, exchange, bound)\n c = flux_balance_constraints(model)\n c.fluxes[transport].bound = 5 * bound\n c.fluxes[exchange].bound = 3 * bound\n optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/#Annotating-the-results","page":"Screening through many model variants","title":"Annotating the results","text":"","category":"section"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"For reasons of tidyness, it is adviseable to annotate all values with their actual meaning directly in the arrays.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"With screen, the simplest (and usually sufficiently effective) way to do that is to return Pairs with annotation keys instead of plain values:","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"screen(\n Iterators.product(\n [:H2Ot, :CO2t, :O2t, :NH4t],\n [:EX_h2o_e, :EX_co2_e, :EX_o2_e, :EX_nh4_e],\n [C.Between(-0.1, 0.1), C.Between(-1, 1)],\n ),\n) do (transport, exchange, bound)\n c = flux_balance_constraints(model)\n c.fluxes[transport].bound = 5 * bound\n c.fluxes[exchange].bound = 3 * bound\n (transport, exchange, bound.upper) => optimized_values(\n c,\n objective = c.objective.value,\n optimizer = HiGHS.Optimizer,\n output = c.objective,\n )\nend","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"Notably, this approach makes various indexing and ordering errors quite improbable.","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"","category":"page"},{"location":"examples/06b-screening/","page":"Screening through many model variants","title":"Screening through many model variants","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/frontend/#Front-end-user-interface","page":"Front-end user interface","title":"Front-end user interface","text":"","category":"section"},{"location":"reference/frontend/#Flux-balance-analysis","page":"Front-end user interface","title":"Flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/balance.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_balance_analysis","text":"flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nCompute an optimal objective-optimizing solution of the given model.\n\nMost arguments are forwarded to optimized_values.\n\nReturns a tree with the optimization solution of the same shape as given by flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_balance_constraints","text":"flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n interface,\n interface_name\n) -> Any\n\n\nA constraint tree that models the content of the given instance of AbstractFBCModel.\n\nThe constructed tree contains subtrees fluxes (with the reaction-defining \"variables\") and flux_stoichiometry (with the metabolite-balance-defining constraints), and a single constraint objective thad describes the objective function of the model.\n\nOptionally if interface is specified, an \"interface block\" will be created within the constraint tree for later use as a \"module\" in creating bigger models (such as communities) using interface_constraints. The possible parameter values include:\n\nnothing – default, no interface is created\n:sbo – the interface gets created from model's SBO annotations)\n:identifier_prefixes – the interface is guesstimated from commonly occurring adhoc reaction ID prefixes used in contemporary models\n:boundary – the interface is created from all reactions that either only consume or only produce metabolites\n\nOutput interface name can be set via interface_name.\n\nSee Configuration for fine-tuning the default interface creation.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Flux-variability-analysis","page":"Front-end user interface","title":"Flux variability analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/variability.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_variability_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_variability_analysis","text":"flux_variability_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n objective_bound,\n reactions,\n optimizer,\n settings,\n workers\n)\n\n\nPerform a Flux Variability Analysis (FVA) on the model, and return a dictionary of flux ranges where the model is able to perform optimally.\n\nThe constraint system is constructed using flux_balance_constraints, and the variability is examined on all reaction's fluxes, or on the subset given optionally in reaction_subset (e.g., reaction_subset = [\"PFK\", \"ACALD\"]). The optimality tolerance can be specified with objective_bound using e.g. relative_tolerance_bound or absolute_tolerance_bound; the default is 99% relative tolerance.\n\nParameter workers may be used to enable parallel or distributed processing; the execution defaults to all available workers. Other parameters (esp. optimizer) are internally forwarded to optimized_values.\n\nUse constraints_variability to customize the FVA execution.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Parsimonious-flux-balance-analysis","page":"Front-end user interface","title":"Parsimonious flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/parsimonious.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.linear_parsimonious_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_parsimonious_flux_balance_analysis","text":"linear_parsimonious_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n tolerances,\n kwargs...\n)\n\n\nLike parsimonious_flux_balance_analysis, but uses the L1-metric parsimonious system given by linear_parsimonious_flux_balance_constraints.\n\nIn turn, the solution is often faster, does not require a solver capable of quadratic objectives, and has many beneficial properties of the usual parsimonious solutions (such as the general lack of unnecessary loops). On the other hand, like with plain flux balance analysis there is no strong guarantee of uniqueness of the solution.\n\nSolver configuration arguments are forwarded to parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_parsimonious_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_parsimonious_flux_balance_constraints","text":"linear_parsimonious_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> ConstraintTrees.Tree\n\n\nLike parsimonious_flux_balance_constraints, but uses a L1 metric for solving the parsimonious problem. The parsimonious_objective constraint is thus linear.\n\nKeyword arguments are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.parsimonious_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.parsimonious_flux_balance_analysis","text":"parsimonious_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n tolerances,\n kwargs...\n)\n\n\nCompute a parsimonious flux solution for the model, using the constraints given by parsimonious_flux_balance_constraints.\n\nIn short, the objective value of the parsimonious solution should be the same as the one from flux_balance_analysis, except the squared sum of reaction fluxes is minimized. If there are multiple possible fluxes that achieve a given objective value, parsimonious flux thus represents the \"minimum energy\" one, which is arguably more realistic.\n\nSolver configuration arguments are forwarded to parsimonious_optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.parsimonious_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.parsimonious_flux_balance_constraints","text":"parsimonious_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Any\n\n\nA constraint system like from flux_balance_constraints, but with the parsimonious objective present under key parsimonious_objective. Best used via parsimonious_flux_balance_analysis.\n\nKeyword arguments are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Minimization-of-metabolic-adjustment","page":"Front-end user interface","title":"Minimization of metabolic adjustment","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/moma.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_analysis-Tuple{AbstractFBCModels.AbstractFBCModel, Vararg{Any}}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_analysis","text":"linear_metabolic_adjustment_minimization_analysis(\n model::AbstractFBCModels.AbstractFBCModel,\n args...;\n optimizer,\n settings,\n reference_parsimonious_optimizer,\n reference_parsimonious_settings,\n reference_optimizer,\n reference_settings,\n kwargs...\n)\n\n\nPerform a linear minimization of metabolic adjustment analysis (l-MOMA) on model. The reference is given by the second argument, which is either a reference_flux or a reference_model (the second argument is forwarded to linear_metabolic_adjustment_minimization_constraints).\n\nWhile the solution is \"less uniquely defined\" than with fully quadratic metabolic_adjustment_minimization_analysis, the linear variant typically produces a sufficiently good result with much less resources. See documentation of linear_parsimonious_flux_balance_analysis for some of the considerations.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_constraints","text":"linear_metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Union{Nothing, ConstraintTrees.Tree}\n\n\nLike metabolic_adjustment_minimization_constraints but the output constraints optimize the L1 distance from the linear-parsimonious solution of the reference_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.linear_metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, ConstraintTrees.Tree}","page":"Front-end user interface","title":"COBREXA.linear_metabolic_adjustment_minimization_constraints","text":"linear_metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_fluxes::ConstraintTrees.Tree;\n _...\n) -> ConstraintTrees.Tree\n\n\nLike metabolic_adjustment_minimization_constraints but optimizes the L1 distance from reference_fluxes.\n\nKeyword arguments are discarded for compatibility with the other overload.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_analysis-Tuple{AbstractFBCModels.AbstractFBCModel, Vararg{Any}}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_analysis","text":"metabolic_adjustment_minimization_analysis(\n model::AbstractFBCModels.AbstractFBCModel,\n args...;\n optimizer,\n settings,\n reference_parsimonious_optimizer,\n reference_parsimonious_settings,\n reference_optimizer,\n reference_settings,\n kwargs...\n)\n\n\nFind a solution of the \"minimization of metabolic adjustment\" (MOMA) analysis for the model, which is the \"closest\" feasible solution to the solution given in the second argument, which is either reference_fluxes or reference_model (see documentation of metabolic_adjustment_minimization_constraints), in the sense of squared-sum distance. The minimized squared distance (the objective) is present in the result tree as minimal_adjustment_objective.\n\nIf the second argument is a reference model, it is solved using a parsimonious_flux_balance_analysis with the optimizer and settings parameters for the 2 steps set by keyword arguments prefixed by reference_.\n\nThis is often used for models with smaller feasible region than the reference models (typically handicapped by a knockout, a nutritional deficiency or a similar perturbation). MOMA solution then gives an expectable \"easiest\" adjustment of the organism towards a somewhat working state.\n\nReference fluxes that do not exist in the model are ignored (internally, the objective is constructed via squared_sum_error_value).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_constraints","text":"metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n) -> Any\n\n\nA slightly easier-to-use version of metabolic_adjustment_minimization_constraints that computes the reference flux as the parsimonious optimal solution of the reference_model. The reference flux is calculated using reference_optimizer and reference_modifications, which default to the optimizer and settings.\n\nOther arguments are forwarded to the internal call of parsimonious_optimized_values.\n\nReturns nothing if no feasible solution is found.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.metabolic_adjustment_minimization_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, ConstraintTrees.Tree}","page":"Front-end user interface","title":"COBREXA.metabolic_adjustment_minimization_constraints","text":"metabolic_adjustment_minimization_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n reference_fluxes::ConstraintTrees.Tree;\n _...\n) -> Any\n\n\nKeyword arguments are discarded for compatibility with the other overload.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Constraint-systems-for-metabolite-concentrations","page":"Front-end user interface","title":"Constraint systems for metabolite concentrations","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/concentrations.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.log_concentration_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.log_concentration_constraints","text":"log_concentration_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reactions,\n metabolites,\n metabolite_concentration_bound,\n reaction_concentration_bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nBuild log-concentration-stoichiometry constraints for the model, as used e.g. by max_min_driving_force_analysis.\n\nThe output constraint tree contains a log-concentration variable for each metabolite from model, in subtree log_concentrations. The total reactant log-concentrations for each reaction are constrained in subtree log_concentration_stoichiometry. By default, all reactions and metabolites in model are included.\n\nA concentration bound is given by parameter function concentration_bound for each metabolite ID (the string ID is the single argument of the function); by default the function returns nothing and no bounds are installed. The same is used for reactions with reaction_concentration_bound.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Enzyme-mass-constrained-models","page":"Front-end user interface","title":"Enzyme-mass-constrained models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/enzymes.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.Isozyme","page":"Front-end user interface","title":"COBREXA.Isozyme","text":"mutable struct Isozyme\n\nA simple struct storing information about the isozyme composition, including subunit stoichiometry and turnover numbers. Use with enzyme_constrained_flux_balance_analysis.\n\nFields\n\ngene_product_stoichiometry::Dict{String, Float64}: Mapping of gene product identifiers (\"genes\" in FBC model nomenclature) to their relative amount required to construct one unit of the isozyme.\n\nkcat_forward::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the forward direction of the reaction.\nkcat_reverse::Union{Nothing, Float64}: Turnover number for this isozyme catalyzing the reverse direction of the reaction.\n\n\n\n\n\n","category":"type"},{"location":"reference/frontend/#COBREXA.enzyme_constrained_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.enzyme_constrained_flux_balance_analysis","text":"enzyme_constrained_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.\n\nArguments are forwarded to enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.enzyme_constrained_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.enzyme_constrained_flux_balance_constraints","text":"enzyme_constrained_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reaction_isozymes,\n gene_product_molar_masses,\n capacity,\n interface,\n interface_name\n)\n\n\nConstruct a enzyme-constrained flux-balance constraint system, following the method in GECKO algorithm (refer to: Sánchez, Benjamín J., et al. \"Improving the phenotype predictions of a yeast genome‐scale metabolic model by incorporating enzymatic constraints.\" Molecular systems biology 13.8 (2017): 935).\n\nThe enzyme mass constraints depend primarily on the available isozymes, given in parameter reaction_isozymes, which is a mapping of reaction identifiers to descriptions of Isozymes that may catalyze the particular reactions. The isozymes are built from gene products, the mass of which is specified by gene_product_molar_masses. In total, the amount of gene product building material is limited by capacity.\n\ncapacity may be a single number, which sets the mass limit for \"all described enzymes\". Alternatively, capacity may be a vector of identifier-genes-limit triples that together form a constraint (identified by the given identifier) that limits the total sum of the listed genes to the given limit.\n\ninterface and interface_name are forwarded to flux_balance_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.simplified_enzyme_constrained_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.simplified_enzyme_constrained_flux_balance_analysis","text":"simplified_enzyme_constrained_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the enzyme-constrained flux balance analysis on the model and return the solved constraint system.\n\nArguments are forwarded to simplified_enzyme_constrained_flux_balance_constraints; solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.simplified_enzyme_constrained_flux_balance_constraints-Tuple{Any}","page":"Front-end user interface","title":"COBREXA.simplified_enzyme_constrained_flux_balance_constraints","text":"simplified_enzyme_constrained_flux_balance_constraints(\n model;\n reaction_isozymes,\n gene_product_molar_masses,\n capacity,\n interface,\n interface_name\n)\n\n\nLike enzyme_constrained_flux_balance_constraints, but automatically selects a single \"fastest\" isozyme for each reaction direction. In turn, the system requires much less variables in the constraint system description, and usually solves more efficiently, for the price of possibly finding suboptimal solutions. The method follows the SMOMENT algorithm described in Bekiaris, P.S., Klamt, S. Automatic construction of metabolic models with enzyme constraints. BMC Bioinformatics 21, 19 (2020). https://doi.org/10.1186/s12859-019-3329-9.\n\nArguments are as with enzyme_constrained_flux_balance_constraints, with a major difference in capacity handling: the identifier lists (2nd elements of the triples given in the list) are not identifiers of gene products, but identifiers of reactions.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Community-models","page":"Front-end user interface","title":"Community models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/community.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.community_flux_balance_analysis-Tuple","page":"Front-end user interface","title":"COBREXA.community_flux_balance_analysis","text":"community_flux_balance_analysis(args...; kwargs...)\n\n\nRun the Community Flux Balance Analysis on several models. All arguments are forwarded to community_flux_balance_constraints which constructs the model; this function returns the solved model.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.community_flux_balance_constraints-Tuple{Any, Any}","page":"Front-end user interface","title":"COBREXA.community_flux_balance_constraints","text":"community_flux_balance_constraints(\n model_abundances,\n community_exchange_bounds;\n interface,\n interface_exchanges,\n interface_biomass,\n default_community_exchange_bound\n) -> Any\n\n\nConstruct an instance of a linear community Flux Balance Analysis (cFBA) model. The relative abundances of the organisms are known in advance; this function predicts the maximum achievable community growth rate.\n\nmodel_abundances is a dictionary-like object that maps model identifiers to tuples of models (usually subtypes of AbstractFBCModel) and their abundances (such as: \"bug1\" => (bug1, 0.5), ...). community_exchange_bounds is a dictionary-like object that can be additionally used to restrict selected community exchange reactions (keys should be reaction IDs, the values are converted to ConstraintTrees-like bounds). Bounds otherwise default to parameter default_community_exchange_bound, which itself defaults to nothing (i.e., unbounded).\n\nIf required, constraint trees may be supplied instead of AbstracFBCModels in model_abundances. These must provide an interface compatible with interface_exchanges and interface_biomass.\n\ninterface is forwarded to flux_balance_constraints. interface_exchanges and interface_biomass are used to pick up the correct interface part to contribute to the community exchanges and community biomass.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Production-envelopes","page":"Front-end user interface","title":"Production envelopes","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/envelope.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.objective_production_envelope-Tuple{AbstractFBCModels.AbstractFBCModel, Vector{String}}","page":"Front-end user interface","title":"COBREXA.objective_production_envelope","text":"objective_production_envelope(\n model::AbstractFBCModels.AbstractFBCModel,\n reactions::Vector{String};\n breaks,\n optimizer,\n settings,\n workers\n)\n\n\nFind the objective production envelope of the model in the dimensions given by reactions.\n\nThis runs a variability analysis of the fluxes given by flux_balance_constraints to determine an applicable range for the dimensions, then splits the dimensions to equal-sized breaks (of count breaks for each dimension, i.e. total breaks ^ length(reactions) individual \"multidimensional breaks\") thus forming a grid, and returns an array of fluxes through the model objective with the individual reactions fixed to flux as given by the grid.\n\noptimizer and settings are used to construct the optimization models.\n\nThe computation is distributed to the specified workers, defaulting to all available workers.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Gap-filling","page":"Front-end user interface","title":"Gap-filling","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/gapfill.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.gap_filling_analysis-Tuple","page":"Front-end user interface","title":"COBREXA.gap_filling_analysis","text":"gap_filling_analysis(args...; kwargs...)\n\n\nRun the gap-filling analysis on a constraint system specified by gap_filling_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_constraints-Tuple{AbstractFBCModels.AbstractFBCModel, AbstractFBCModels.AbstractFBCModel, Float64}","page":"Front-end user interface","title":"COBREXA.gap_filling_constraints","text":"gap_filling_constraints(\n model::AbstractFBCModels.AbstractFBCModel,\n universal_model::AbstractFBCModels.AbstractFBCModel,\n objective_target::Float64;\n universal_reaction_cost,\n max_cost,\n known_fills,\n kwargs...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a gap-filling system from a FBC model with gaps and an universal FBC model that contains reactions to be added into the original model.\n\nThe output system will be constrainted to reach at least objective_target flux through the objective function. Generally, this should be set to an arbitrary small value such as 0.05.\n\nuniversal_reaction_cost should assign a numeric cost of inclusion of each of the reactions in the universal_model; by default all are assigned equal weight of 1. max_cost puts an optional maximum limit on the cost, which may help the solver to avoid exploring unnecessarily complex solutions. known_fills may contain previous solutions of the same system; these will be made infeasible in the output constraint system in order to allow discovery of other ones.\n\nAdditional arguments are forwarded to flux_balance_constraints that converts model to constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_constraints-Tuple{}","page":"Front-end user interface","title":"COBREXA.gap_filling_constraints","text":"gap_filling_constraints(\n;\n system,\n stoichiometry,\n universal_fluxes,\n universal_stoichiometry,\n flux_cost,\n max_cost,\n known_fills\n)\n\n\nMake a gap-fillign system from a non-solving system with a separated stoichiometry, filling in possible fluxes from universal_fluxes that are balanced with universal_stoichiometry\n\nflux_cost can be used to assign a weight to each given universal flux; the total cost is bounded by max_cost.\n\nknown_fills may contain previous solutions to be avoided; these are processed by gap_filling_known_fill_constraint and attached to the system.\n\nstoichiometry needs to be extended to construct the final constraints, thus it should not be present in the original system.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gap_filling_known_fill_constraint-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{Float64}}","page":"Front-end user interface","title":"COBREXA.gap_filling_known_fill_constraint","text":"gap_filling_known_fill_constraint(\n fill_flags::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n known_flags::ConstraintTrees.Tree{Float64}\n) -> ConstraintTrees.Constraint\n\n\nProduce a constraint that can be added to the system made by gap_filling_constraints to avoid repeating of a solution that includes reactions already generated by another solution, as represented by the solved fill_flags.\n\nParameter fill_flags are the gapfilling flags of the given constraint system, parameter known_flags is expected to contain the solved fill_flags for the solution that is to be avoided.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Knockout-models","page":"Front-end user interface","title":"Knockout models","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/knockout.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.gene_knockout_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.gene_knockout_constraints","text":"gene_knockout_constraints(\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n knockout_genes,\n model::AbstractFBCModels.AbstractFBCModel\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a ConstraintTree that simulates a gene knockout of knockout_genes in the model and disables corresponding fluxes accordingly.\n\nKeys of the fluxes must correspond to the reaction identifiers in the model.\n\nknockout_genes may be any collection that support element tests using in. Since the test is done many times, a Set is a preferred contained for longer lists of genes.\n\nAll constraints are equality constraints returned in a single flat ConstraintTree.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gene_knockout_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, String, AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.gene_knockout_constraints","text":"gene_knockout_constraints(\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n knockout_gene::String,\n model::AbstractFBCModels.AbstractFBCModel\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nConvenience overload of gene_knockout_constraints for knocking out a single gene (without the necessity to store the gene identifier in a singleton container).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.gene_knockouts","page":"Front-end user interface","title":"COBREXA.gene_knockouts","text":"gene_knockouts(model::AbstractFBCModels.AbstractFBCModel)\ngene_knockouts(\n model::AbstractFBCModels.AbstractFBCModel,\n gene_combinations::Vector{<:Union{String, Tuple{Vararg{String, N}} where N}};\n kwargs...\n)\n\n\nCompute the objective value of the model for all knockouts specified by gene_combinations, which is a vector of gene IDs or tuples of gene IDs that are knocked out in groups.\n\nReturns a vector in the same order as gene_combinations.\n\nExtra arguments (mainly, the optimizer) are forwarded to screen_optimization_model.\n\n\n\n\n\n","category":"function"},{"location":"reference/frontend/#Loopless-flux-balance-analysis","page":"Front-end user interface","title":"Loopless flux balance analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/loopless.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.loopless_flux_balance_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.loopless_flux_balance_analysis","text":"loopless_flux_balance_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the loopless flux balance analysis on the model, returning the solved constraint system.\n\nArguments are forwarded to loopless_flux_balance_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.loopless_flux_balance_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.loopless_flux_balance_constraints","text":"loopless_flux_balance_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n flux_infinity_bound,\n driving_force_nonzero_bound,\n driving_force_infinity_bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nConstruct a flux-balance constraint system from model with added quasi-thermodynamic constraints that ensure that thermodynamically infeasible internal cycles can not occur. The method is closer described by: Schellenberger, Lewis, and, Palsson. \"Elimination of thermodynamically infeasible loops in steady-state metabolic models.\", Biophysical journal, 2011`.\n\nThe loopless condition comes with a performance overhead: the computation needs to find the null space of the stoichiometry matrix (essentially inverting it); and the subsequently created optimization problem contains binary variables for each internal reaction, thus requiring a MILP solver and a potentially exponential solving time.\n\nInternally, the system is constructed by combining flux_balance_constraints and loopless_constraints.\n\nThe arguments driving_force_max_bound and driving_force_nonzero_bound set the bounds (possibly negated ones) on the virtual \"driving forces\" (G_i in the paper).\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Max-Min-Driving-Force-analysis","page":"Front-end user interface","title":"Max-Min Driving Force analysis","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/mmdf.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.max_min_driving_force_analysis-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.max_min_driving_force_analysis","text":"max_min_driving_force_analysis(\n model::AbstractFBCModels.AbstractFBCModel;\n kwargs...\n)\n\n\nPerform the max-min driving force analysis on the model, returning the solved constraint system.\n\nArguments are forwarded to max_min_driving_force_constraints (see the documentation for the description of the constraint system); solver configuration arguments are forwarded to optimized_values.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#COBREXA.max_min_driving_force_constraints-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.max_min_driving_force_constraints","text":"max_min_driving_force_constraints(\n model::AbstractFBCModels.AbstractFBCModel;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n concentration_ratios,\n constant_concentrations,\n ignored_metabolites,\n proton_metabolites,\n water_metabolites,\n concentration_lower_bound,\n concentration_upper_bound,\n T,\n R,\n reference_flux_atol\n)\n\n\nCreate max-min driving force constraint system from model, using the supplied reaction standard Gibbs free energies in reaction_standard_gibbs_free_energies.\n\nThe method is described by: Noor, et al., \"Pathway thermodynamics highlights kinetic obstacles in central metabolism.\", PLoS computational biology, 2014.\n\nreference_flux sets the directions of each reaction in model. The scale of the values is not important, only the direction is examined (w.r.t. reference_flux_atol tolerance). Ideally, the supplied reference_flux should be completely free of internal cycles, which enables the thermodynamic consistency. To get the cycle-free flux, you can use loopless_flux_balance_analysis (computationally demanding, but gives thermodynamically consistent solutions), parsimonious_flux_balance_analysis or linear_parsimonious_flux_balance_analysis (which is computationally simple, but the consistency is not guaranteed).\n\nInternally, log_concentration_constraints is used to lay out the base structure of the problem.\n\nFollowing arguments are set optionally:\n\nwater_metabolites, proton_metabolites and ignored_metabolites allow to completely ignore constraints on a part of the metabolite set, which is explicitly recommended especially for water and protons (since the analyses generally assume aqueous environment of constant pH)\nconstant_concentrations can be used to fix the concentrations of the metabolites\nconcentration_lower_bound and concentration_upper_bound set the default concentration bounds for all other metabolites\nconcentration ratios is a dictionary that assigns a tuple of metabolite-metabolite-concentration ratio constraint names; e.g. ATP/ADP ratio can be fixed to five-times-more-ATP by setting concentration_ratios = Dict(\"adenosin_ratio\" => (\"atp\", \"adp\", 5.0))\nT and R default to the usual required thermodynamic constraints in the expected units (the defaults assume the \"usual\" units, valuing 298.15 K and ~0.008314 kJ/K/mol, respectively). These multiply the log-concentrations to obtain the actual Gibbs energies, and thus driving forces.\n\n\n\n\n\n","category":"method"},{"location":"reference/frontend/#Sampling","page":"Front-end user interface","title":"Sampling","text":"","category":"section"},{"location":"reference/frontend/","page":"Front-end user interface","title":"Front-end user interface","text":"Modules = [COBREXA]\nPages = [\"src/frontend/sample.jl\"]","category":"page"},{"location":"reference/frontend/#COBREXA.flux_sample-Tuple{AbstractFBCModels.AbstractFBCModel}","page":"Front-end user interface","title":"COBREXA.flux_sample","text":"flux_sample(\n model::AbstractFBCModels.AbstractFBCModel;\n seed,\n objective_bound,\n method,\n n_chains,\n collect_iterations,\n optimizer,\n settings,\n workers,\n kwargs...\n)\n\n\nRun a sampling algorithm on the near-optimal feasible space of the model (as specified by objective_bound). By default, the sampling algorithm is ACHR (the method parameter is defaulted to sample_chain_achr). The sampling algorithm is ran for n_chains and the iterations for collecting the sampled values are specified by collect_iterations.\n\noptimizer is used to generate the warmup (with settings) for the sampler using the usual unidimensional maximum-variability fluxes (as from flux_variability_analysis). All computations are parallelized across workers.\n\nExtra arguments are forwarded to sample_constraints. Eventually the arguments will reach the method function, so extra arguments can be also used to customize the methods (e.g., by setting the epsilon for the ACHR sampler).\n\n\n\n\n\n","category":"method"},{"location":"distributed/3_slurm/#Working-in-a-HPC-environment","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Many researchers have access to institutional HPC facilities that allow time-sharing of the capacity of a large computer cluster between many users. Julia and COBREXA.jl work well within this environment, and the COBREXA analyses usually require only minimal additional customization to be able to find and utilize the resources available from the HPC.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"When executed in a HPC environment, the analysis script must solve several relatively complex tasks:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"It needs to find out how many resources were allocated for the analysis\nIt needs to add the remote workers precisely at the allocated places","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Fortunately, the package ClusterManagers.jl does that for us. For simplicity, here we assume that the HPC is scheduled by Slurm, but other scheduling environments are supported in a very similar way.","category":"page"},{"location":"distributed/3_slurm/#Interacting-with-Slurm","page":"Working in a HPC environment","title":"Interacting with Slurm","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Utilization of the Slurm-provided resources is enabled as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"first, import the ClusterManagers package\nfind how many processes to spawn from the environment, typically from SLURM_NTASKS environment variable\nuse the function addprocs_slurm to precisely connect to the allocated computational resources","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"After adding the Slurm workers, one may continue as if the workers were added using normal addprocs –- typically, we can load the model and (for example) run the flux_variability_analysis as if we would use the local workers.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"The Julia script that does a parallel analysis in a Slurm cluster may look as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"using COBREXA, Distributed, ClusterManagers, HiGHS\n\navailable_workers = parse(Int, ENV[\"SLURM_NTASKS\"])\n\naddprocs_slurm(available_workers)\n\n# ... load models, prepare data, etc. ...\n\nresults = flux_variability_analysis(..., workers=workers())\n\n# ... save the results into a file ...","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"tip: What about the other HPC schedulers?\nClusterManagers.jl supports many other common HPC scheduling systems, including LFS, Sun Grid, SGE, PBS, and Scyld, in a way almost identical to Slurm. See the package documentation for details.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"warning: Using Julia environments with Distributed\nSometimes the project configuration is not forwarded to the workers automatically, resulting to package version mismatches and other problems. When utilizing custom project folders (by running Julia with julia --project=...), use the following form of addprocs_slurm instead:addprocs_slurm(available_workers, exeflags=`--project=$(Base.active_project())`)","category":"page"},{"location":"distributed/3_slurm/#Wrapping-a-pipeline-script-in-a-Slurm-batch-job","page":"Working in a HPC environment","title":"Wrapping a pipeline script in a Slurm batch job","text":"","category":"section"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"To be able to submit a script for later processing using the sbatch Slurm command, we need to wrap it in a small \"batch\" script that tells Slurm how many resources the process needs.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Assuming we have a Julia computation script written down in myJob.jl and saved on the HPC cluster's access node, the corresponding Slurm batch script (let's call it myJob.sbatch) may look as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"#!/bin/bash -l\n#SBATCH -n 100 # the job will use 100 individual worker processes\n#SBATCH -c 1 # each worker will sit on a single CPU\n#SBATCH -t 30 # the whole job will take less than 30 minutes\n#SBATCH -J myJob # the name of the job (for own reference)\n\nmodule load lang/Julia # add Julia to the environment (this may differ on different clusters and installations!)\n\njulia myJob.jl","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"To run the computation, run sbatch myJob.sbatch on the cluster access node. The job will be scheduled and eventually executed. It is possible to watch the output of commands sacct and squeue in the meantime, to see the progress.","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"Remember that it is necessary to explicitly save the result of the Julia script computation to files, to be able to retrieve them later. Standard outputs of the jobs are often mangled and/or discarded. If we would still want to collect the standard output of the Julia script, we might need to change the last line of the batch script as follows:","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"julia myJob.jl > myJob.log","category":"page"},{"location":"distributed/3_slurm/","page":"Working in a HPC environment","title":"Working in a HPC environment","text":"...and collect the output from myJob.log later. This is convenient especially if the script prints out various computation details using @info and similar macros.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"EditURL = \"01-loading-and-saving.jl\"","category":"page"},{"location":"examples/01-loading-and-saving/#Loading-and-saving-models","page":"Loading and saving models","title":"Loading and saving models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"using COBREXA","category":"page"},{"location":"examples/01-loading-and-saving/#Getting-the-models-reliably-from-the-repositories","page":"Loading and saving models","title":"Getting the models reliably from the repositories","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"For convenience, COBREXA provides a specific function download_model to download models from repositories that also automatically uses the cached downloaded version of the model if it's already downloaded, and verifies the checksum to improve reproducibility. It will print out a warning in case the model checksum does not match the expectation:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.xml\",\n \"e_coli_core.xml\",\n \"b4db506aeed0e434c1f5f1fdd35feda0dfe5d82badcfda0e9d1342335ab31116\",\n)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"tip: How do I get the model hash?\nWe do not need to fill in the hash values immediately – instead, it's possible to simply run the function once, and then copy the reported hash value from the warning message into the script.","category":"page"},{"location":"examples/01-loading-and-saving/#Loading-models","page":"Loading and saving models","title":"Loading models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"To load genome-scale metabolic models, COBREXA uses the AbstractFBCModels framework to import various kinds of models including SBML, JSON and the legacy Matlab-formatted \"COBRA toolbox\" models.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"All models can be loaded automatically using load_model; but one must import the model-type specific packages to load the functionality. (This step is required to keep the \"base\" COBREXA as efficient and fast-loading as possible.)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import JSONFBCModels, SBMLFBCModels\n\nmodel1 = load_model(\"e_coli_core.json\")\n\nmodel2 = load_model(\"e_coli_core.xml\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"We can now explore the contents of the models using the AbstractFBCModels' interface:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import AbstractFBCModels as A\n\nA.reactions(model1)\n\nA.reactions(model2)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Additional extractable information can be found in the documentation of the abstract models package.","category":"page"},{"location":"examples/01-loading-and-saving/#Converting-model-types","page":"Loading and saving models","title":"Converting model types","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Normally, load_model is forced to guess the model type from the filename suffix. We can specify the model type ourselves (this also allows the users to work with non-standard file suffixes, and saves some overhead and uncertainty in the guessing process):","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"import JSONFBCModels: JSONFBCModel\n\nmodel = load_model(JSONFBCModel, \"e_coli_core.json\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Sometimes it is useful to convert the model data to another type, such as the SBML to a JSON model structure:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_converted_to_json = load_model(\"e_coli_core.xml\", JSONFBCModel)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Or to the \"Canonical Julia model\" from AbstractFBCModels:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_in_julia_structures =\n load_model(JSONFBCModel, \"e_coli_core.json\", A.CanonicalModel.Model)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"tip: Compatibility with COBREXA v1.x\nCanonicalModel is a newer, cleaned-up version of the StandardModel type used in COBREXA version 1. For all code that relied on StandardModel, the canonical one should work just as well.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The above command specifies all model types explicitly, leaving least room for guessing-based errors.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"If required, it is also possible to convert all model types to each other simply by using Julia's convert:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"model_in_json_structure = convert(JSONFBCModel, model_in_julia_structures)","category":"page"},{"location":"examples/01-loading-and-saving/#Saving-models","page":"Loading and saving models","title":"Saving models","text":"","category":"section"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The models can be saved to file storage by using save_model:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_converted_to_json, \"e_coli_core_from_sbml.json\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Expectably, the file will contain the JSON with the model description:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"println(open(\"e_coli_core_from_sbml.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"Note that without the conversion, it may happen that you save the model in an unexpected format!","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_in_julia_structures, \"e_coli_saved_wrongly.json\")\nprintln(open(\"e_coli_saved_wrongly.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"The above code has saved the CanonicalModel in the way specified by the CanonicalModel structure – which is, in this case, a binary dump of the Julia objects, instead of the expected JSON. To prevent this, you can either specify the output type yourself:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_model(model_in_julia_structures, \"e_coli_saved_right.json\", JSONFBCModel)","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"...or use save_converted_model to guess the model type automatically from the extension:","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"save_converted_model(model_in_julia_structures, \"e_coli_saved_automatically_right.json\")\nprintln(open(\"e_coli_saved_automatically_right.json\") do f\n read(f, 100)\nend |> String, \"...\")","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"As with load_model, there is some overhead and uncertainty associated with save_converted_model guessing the model type from extension. For that reason, it is adviseable to rely on the guessing functionality only in interactive use in REPL, and avoid it in automated scriptage altogether.","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"","category":"page"},{"location":"examples/01-loading-and-saving/","page":"Loading and saving models","title":"Loading and saving models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"EditURL = \"05a-minimization-of-metabolic-adjustment.jl\"","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Minimization-of-metabolic-adjustment-analysis","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Minimization of metabolic adjustment analysis (MOMA) finds a flux solution that is closest to some reference solution. This may correspond to realistic adjustment of living organisms to various perturbations, such as gene knockout or environmental stress.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"To demonstrate, let's use the E. coli model.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"We shall use both quadratic and linear solvers – the \"closest to some reference solution\" typically refers to Euclidean (\"L2\") distance which requires a QP solver, but Manhattan (\"L1\") distance is also demonstrated below.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import Clarabel, HiGHS","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Because we will have to perform some perturbation, we import the model in canonical Julia structures:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import JSONFBCModels\nimport AbstractFBCModels.CanonicalModel as CM\necoli = load_model(\"e_coli_core.json\", CM.Model)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"This will be a good reaction for perturbing:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"ecoli.reactions[\"CYTBD\"]","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"To do the perturbation, we create a model of a strain which has mild issues with running the CYTBD reaction. We use deepcopy to completely avoid any reference sharing issues.","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"limited_ecoli = deepcopy(ecoli)\nlimited_ecoli.reactions[\"CYTBD\"].upper_bound = 10.0","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Finding-parsimonious-solutions","page":"Minimization of metabolic adjustment analysis","title":"Finding parsimonious solutions","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Becuase we are interested in realistic flux distributions, we have to use an analysis method which gives one – in this case, the parsimonious FBA will do just right. For later comparison, we first get the optimal parsimonious flux distribution in the perturbed model:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"solution = parsimonious_flux_balance_analysis(limited_ecoli, optimizer = Clarabel.Optimizer)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"Now, how much is the flux going to differ if we assume the bacterium did only minimal adjustment from the previous state with unlimited CYTBD?","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"moma_solution = metabolic_adjustment_minimization_analysis(\n limited_ecoli, # the model to be examined\n ecoli; # the model that gives the reference flux\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Comparing-the-results","page":"Minimization of metabolic adjustment analysis","title":"Comparing the results","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The difference between the naive and minimally-adjusting solutions can be extracted using the constraint tree functionality:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"import ConstraintTrees as C\ndifference = C.zip(-, solution, moma_solution, Float64)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"sort(collect(difference.fluxes), by = last)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Using-a-custom-reference-flux","page":"Minimization of metabolic adjustment analysis","title":"Using a custom reference flux","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"In certain situations, one might want to examine how the model would adjust from a known reaction flux. We can supply it manually as the second argument (instead of the reference model).","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"ref = parsimonious_flux_balance_analysis(ecoli, optimizer = Clarabel.Optimizer)\n\nref_closest_solution = metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n ref.fluxes;\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The flux may even be partial (which is common with measured fluxes):","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"measured_fluxes =\n C.Tree{Float64}(:EX_ac_e => 5.0, :EX_o2_e => -2.0, :BIOMASS_Ecoli_core_w_GAM => 0.7)\n\nsolution_close_to_measurement = metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n measured_fluxes;\n optimizer = Clarabel.Optimizer,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/#Efficient-linear-metric-MOMA","page":"Minimization of metabolic adjustment analysis","title":"Efficient linear-metric MOMA","text":"","category":"section"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"The linear version of MOMA avoids having to use the quadratic optimizer in the process, giving more optimizer choices and (typically) much better performance. Linear MOMA has the same interface as the quadratic one:","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"linear_moma_solution = linear_metabolic_adjustment_minimization_analysis(\n limited_ecoli,\n ecoli;\n optimizer = HiGHS.Optimizer,\n)\n\nsort(collect(linear_moma_solution.fluxes), by = last)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"How much does the flux distribution differ from the L2 solution?","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"sort(\n collect(C.zip(-, linear_moma_solution.fluxes, moma_solution.fluxes, Float64)),\n by = last,\n)","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"","category":"page"},{"location":"examples/05a-minimization-of-metabolic-adjustment/","page":"Minimization of metabolic adjustment analysis","title":"Minimization of metabolic adjustment analysis","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"EditURL = \"03d-unidirectional.jl\"","category":"page"},{"location":"examples/03d-unidirectional/#Split-unidirectional-reactions-in-models","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"By default, the constraint system produced by e.g. flux_balance_constraints assumes a single variable for each reaction flux that may be both positive and negative (depending on the reaction). This example explains several ways to \"split\" such bidirectional fluxes into unidirectional \"forward\" and \"reverse\" parts. This is useful in modeling of capacity constraints (such system can be found e.g. in enzyme_constrained_flux_balance_analysis and linear_parsimonious_flux_balance_analysis) and many other purposes.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"Here we show how to create such system for the toy E. coli model:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\nimport ConstraintTrees as C\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We will only work with the constraint representation of the model. The fluxes there are bidirectional:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c = flux_balance_constraints(model);\nc.fluxes","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"As the simplest approach, we can allocate 2 sets of variables for the forward and reverse fluxes via sign_split_variables and connect them to the fluxes with sign_split_constraints. These functions ensure that the bounds of the unidirectional fluxes are within the expectable limit, and, respectively, that the original fluxes are constrained to match the sum of the split directions:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c += sign_split_variables(c.fluxes, positive = :fluxes_forward, negative = :fluxes_reverse);\nc *=\n :directional_flux_balance^sign_split_constraints(\n positive = c.fluxes_forward,\n negative = c.fluxes_reverse,\n signed = c.fluxes,\n )","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We can solve this system as usual and obvserve the results as usual","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x = optimized_values(c, objective = c.objective.value, optimizer = HiGHS.Optimizer)\n\nC.zip(tuple, x.fluxes, x.fluxes_forward, x.fluxes_reverse, Tuple)","category":"page"},{"location":"examples/03d-unidirectional/#Simplifying-the-system-using-asymmetric-construction","page":"Split unidirectional reactions in models","title":"Simplifying the system using asymmetric construction","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"If used naively, the above construction uses 3 variables and many constraints for each flux, which is not quite efficient. To ameliorate the usage of solver resources, one may construct a slightly simpler (but asymmetric) system that only uses 2 variables:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c2 = flux_balance_constraints(model);\nc2 += :fluxes_forward^unsigned_positive_contribution_variables(c2.fluxes);\nc2 *=\n :fluxes_reverse^unsigned_negative_contribution_constraints(c2.fluxes, c2.fluxes_forward);\nnothing #hide","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"This way, only forward fluxes are allocated as variables, and reverse fluxes are \"computed\" as linearly dependent values. Additionally, since the bounds on the forward and reverse fluxes completely subsume the original bounds on fluxes, one can further simplify the system by removing the original bounds:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"c2.fluxes = remove_bounds(c2.fluxes)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The system solves just like the \"symmetric\" one:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x2 = optimized_values(c2, objective = c2.objective.value, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"We can also compare the raw variable counts:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"(C.var_count(c), C.var_count(c2))","category":"page"},{"location":"examples/03d-unidirectional/#Simplifying-the-system-by-removing-original-variables","page":"Split unidirectional reactions in models","title":"Simplifying the system by removing original variables","text":"","category":"section"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"If one can assume that the original system is just allocated variables with no other semantics attached, one can reduce the variable and constraint count even in the \"nicer\" symmetric case from above.","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"In particular, it is possible to substitute a combination of forward and reverse flux for the bidirectional variables, which allows them to be pruned out of the system together with their original associated bounds:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"subst_vals = [C.variable(; idx).value for idx = 1:C.var_count(c)]\n\nc.fluxes = C.zip(c.fluxes, c.fluxes_forward, c.fluxes_reverse) do f, p, n\n (var_idx,) = f.value.idxs\n subst_value = p.value - n.value\n subst_vals[var_idx] = subst_value\n C.Constraint(subst_value) # the bidirectional bound is dropped here\nend\n\nc = C.prune_variables(C.substitute(c, subst_vals))","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The variable count is now reduced, and the system again solves just as the original:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"C.var_count(c)","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x = optimized_values(c, objective = c.objective.value, optimizer = HiGHS.Optimizer);\nx.objective","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"The bidirectional flux values are computed transparently in the result:","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"x.fluxes","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"","category":"page"},{"location":"examples/03d-unidirectional/","page":"Split unidirectional reactions in models","title":"Split unidirectional reactions in models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"EditURL = \"02d-constraint-modifications.jl\"","category":"page"},{"location":"examples/02d-constraint-modifications/#Making-adjustments-to-the-constraint-system","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"In the previous example about model adjustments, we noted that some constraint systems may be too complex to be changed within the limits of the usual FBC model view, and we may require a sharper tool to do the changes we need. This example shows how to do that by modifying the constraint systems that are generated within COBREXA to represent the metabolic model contents.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\") # flux balance type model","category":"page"},{"location":"examples/02d-constraint-modifications/#Background:-Constraint-trees","page":"Making adjustments to the constraint system","title":"Background: Constraint trees","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"COBREXA uses ConstraintTrees to represent model structures internally. This framework provides a powerful unified interface over all constraints and variables in the model, making its manipulation much more convenient.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"import ConstraintTrees as C","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"In general, constraint-based models use fluxes as variables, and all the constraints are in terms of them (or derived quantities). We can get a constraint tree for the usual flux-balance-style models quite easily:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct = flux_balance_constraints(model)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The fluxes are represented by constraints for individual variables:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.fluxes","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The \"mass balance\" is represented as equality constraints:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.flux_stoichiometry","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"The objective is represented as a \"transparent reference\" to the variables that specify the biomass. Notice that it has no bound (thus it's technically not a constraint, just a \"label\" for something that has a sensible semantic and can be constrained or optimized).","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.objective","category":"page"},{"location":"examples/02d-constraint-modifications/#Customizing-the-model","page":"Making adjustments to the constraint system","title":"Customizing the model","text":"","category":"section"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"New values and constraints can be easily created from the existing ones. For example, this is a total flux through exchanges of typical fermentation products:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"total_fermentation = ct.fluxes.EX_ac_e.value + ct.fluxes.EX_etoh_e.value","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"With the value in hand, we can constraint it (enforcing that the model outputs at least some fermentation products):","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"fermentation_constraint = C.Constraint(total_fermentation, (10.0, 1000.0))","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"We can assign a name to the constraint, creating a small (singleton) constraint tree:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":":fermentation^fermentation_constraint","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Named constraints can be freely combined, and we combine our new constraint with the whole original constraint tree, getting a differently constrained system:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"fermenting_ct = ct * :fermentation^fermentation_constraint","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"tip: What if I need more complicated changes?\nAlmost all analysis functions have an associated constraint-building function that internally builds the constraint system, for example the parsimonious_flux_balance_analysis is implemented with parsimonious_flux_balance_constraints, which can be used just as flux_balance_constraints here. Additionally, to reach various custom goals, it is recommended to re-use and modify the source of the functions – use the macro @edit, such as @edit parsimonious_flux_balance_constraints, to get a working source code that serves well as a base for implementing new constraint systems.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Constraint trees can be \"solved\", simply by choosing the objective and sending them to the appropriate function. Here, optimized_values rewrites the constraints into a JuMP model, which is subsequently solved and the solved variables are transformed back into semantically labeled values, in the same structure as the original constraint tree.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"solution = optimized_values(\n fermenting_ct,\n objective = fermenting_ct.objective.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Models that can not be solved (for any reason) would instead return nothing. We demonstrate that by breaking the bounds of the original constraint trees to an unsolvable state:","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"ct.fluxes.ATPM.bound = C.Between(1000.0, 10000.0)\n\nsolution = optimized_values(ct, objective = ct.objective.value, optimizer = HiGHS.Optimizer)\n\nprint(solution)","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"Several functions exist to simplify the construction of more complicated constraints. See the reference documentation for generic constraint builders for details.","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"","category":"page"},{"location":"examples/02d-constraint-modifications/","page":"Making adjustments to the constraint system","title":"Making adjustments to the constraint system","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"EditURL = \"03a-flux-variability-analysis.jl\"","category":"page"},{"location":"examples/03a-flux-variability-analysis/#Flux-variability-analysis-(FVA)","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"","category":"section"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"FVA finds a range of fluxes through each reaction where the model can behave optimally. In brief, it first runs a FBA to get the optimal objective value, constraints the model to the optimal (or near-optimal) space, and runs a separate minimization and maximization task for each reaction to find their individual ranges.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"The \"usual\" form of FBA is available via the eponymous function:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"solution = flux_variability_analysis(model, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03a-flux-variability-analysis/#Specifying-objective-bounds","page":"Flux variability analysis (FVA)","title":"Specifying objective bounds","text":"","category":"section"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"By default, FVA computes variability from the feasible region that is bounded to be within 10% of the optimal objective value. That is not very strict, and we can force much lower tolerance.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"Here, we force the optimal region to be within 0.00001 units of the optimal objective value:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"very_close = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = absolute_tolerance_bound(1e-5),\n)","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"Here, we relax that to 1% of the optimal objective value:","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"one_percent_close = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = relative_tolerance_bound(0.99),\n)","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"tip: Speed up FVA with parallel processing\nBy default, FVA is parallelized on all workers that are available in the worker pool of the Distributed package, which may speed up the computation considerably. See the parallel processing documentation for more details.","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"","category":"page"},{"location":"examples/03a-flux-variability-analysis/","page":"Flux variability analysis (FVA)","title":"Flux variability analysis (FVA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"EditURL = \"05g-gapfilling.jl\"","category":"page"},{"location":"examples/05g-gapfilling/#Gap-filling","page":"Gap filling","title":"Gap filling","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling is used to find easiest additions to the models that would make them feasible and capable of growth.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Typically, an infeasible model (\"with gaps\") is used together with an universal model (which contains \"everything\"), and the algorithm attempts to find the minimal amount of reactions from the universal model that make the gappy model happy. In turn, the gapfilling optimization problem becomes a MILP.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling is sometimes used to produce \"viable\" genome-scale reconstructions from partial ones, but without additional manual intervention the gapfilling results are almost never biologically valid. A good use of gapfilling is to find problems in a model that cause infeasibility as follows: First the modeller makes a set of (unrealistic) universal reactions that supply or remove metabolites, and after gapfilling, metabolites that had to be supplied or removed to make the model feasible mark possible problems, thus guiding the modeller towards correct solution.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"We will use a partially crippled E. coli toy model and see the minimal amount of reactions that may save it.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"First, let's produce an infeasible model:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"import AbstractFBCModels.CanonicalModel as CM\ninfeasible_model = convert(CM.Model, model)\n\nfor rxn in [\"TALA\", \"PDH\", \"PGI\", \"PYK\"]\n infeasible_model.reactions[rxn].lower_bound = 0.0\n infeasible_model.reactions[rxn].upper_bound = 0.0\nend","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"After removing the above reactions, the model will fail to solve:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"flux_balance_analysis(infeasible_model, optimizer = HiGHS.Optimizer) |> println","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"To avoid very subtle semantic issues, we are going to remove the ATP maintenance pseudoreaction from the universal model:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"universal_model = convert(CM.Model, model)\ndelete!(universal_model.reactions, \"ATPM\")","category":"page"},{"location":"examples/05g-gapfilling/#Making-the-model-feasible-with-a-minimal-set-of-reactions","page":"Gap filling","title":"Making the model feasible with a minimal set of reactions","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Which of the reactions we have to fill back to get the model working again? First, let's run gap_filling_analysis to get a solution for a system that implements the reaction patching:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"x = gap_filling_analysis(\n infeasible_model,\n universal_model,\n 0.05,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"The reactions that had to be re-added can be found from the fill_flags:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"filled_reactions = [k for (k, v) in x.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"If we want to try to generate another solution, we have to explicitly ask the system to avoid the previous solution. That is done via setting the argument known_fill. We can also set the max_cost to avoid finding too benevolent solutions:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"x2 = gap_filling_analysis(\n infeasible_model,\n universal_model,\n 0.05,\n max_cost = 2.0,\n known_fills = [x.fill_flags],\n optimizer = HiGHS.Optimizer,\n)\n\nother_filled_reactions = [k for (k, v) in x2.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"warning: Why is the gapfilling algorithm adding seemingly unneeded reactions?\nBy default, COBREXA does not do any \"cleaning\" on the universal model; all reactions that are present in that model will be potentially utilized in the new model, and all of them will need to respect their original bounds in the universal model. That becomes an issue with reactions that are bounded to non-zero flux (such as the ATPM reaction in the E. coli \"core\" model) – since their flux is required to be non-zero in any feasible model solution, they will also need to be in the fill set, because otherwise their flux would be zero.As the simplest solution, all realistic uses of gapfilling should carefully check the set of universal reactions, and ideally exclude all exchanges and pseudoreactions.","category":"page"},{"location":"examples/05g-gapfilling/#Model-debugging:-which-metabolite-is-missing?","page":"Gap filling","title":"Model debugging: which metabolite is missing?","text":"","category":"section"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gap-filling is great for detecting various broken links and imbalances in metabolic models. We show how to find the metabolites are causing the imbalance for our \"broken\" E. coli model.","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"First, we construct a few completely unnatural reactions that create/remove the metabolites from/to nowhere:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"magic_model = convert(CM.Model, model)\nempty!(magic_model.genes)\nempty!(magic_model.reactions)\n\nfor mid in keys(magic_model.metabolites)\n magic_model.reactions[mid] = CM.Reaction(\n lower_bound = -100.0,\n upper_bound = 100.0,\n stoichiometry = Dict(mid => 1.0),\n )\nend","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"Gapfilling now points to the metabolites that need to be somehow taken care of by the modeller in order for the model to become feasible:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"xm = gap_filling_analysis(infeasible_model, magic_model, 0.05, optimizer = HiGHS.Optimizer)\n\nblocking_metabolites = [k for (k, v) in xm.fill_flags if v != 0]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"We can also have a look at how much of a given metabolite was used to make the model feasible again:","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"xm.universal_fluxes[first(blocking_metabolites)]","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"","category":"page"},{"location":"examples/05g-gapfilling/","page":"Gap filling","title":"Gap filling","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"EditURL = \"03b-parsimonious-flux-balance.jl\"","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Parsimonious-flux-balance-analysis","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Here, we use parsimonious_flux_balance_analysis (pFBA) to find the optimal flux distribution in the E. coli \"core\" model. In essence, pFBA first uses FBA to find an optimal objective value for the model, and then minimizes the squared distance of the flux from the zero (i.e., minimizes its L2 norm). As the main benefit, this gives a unique (and possibly more realistic) solution to the model.","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Notably, we need an optimizer that can solve quadratic (QP) models:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"import Clarabel\n\nimport JSONFBCModels\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"The pFBA is, in its most default form, implemented in function parsimonious_flux_balance_analysis:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"solution = parsimonious_flux_balance_analysis(model; optimizer = Clarabel.Optimizer)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"solution.fluxes","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Using-different-solvers-for-the-problem-stages","page":"Parsimonious flux balance analysis","title":"Using different solvers for the problem stages","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"Sometimes it is useful to employ a dedicated LP solver to find the solution to the original FBA problem, and then a dedicated QP solver to minimize the fluxes. We can set the optimizer and parsimonious optimizer separately using keyword arguments:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"import HiGHS\n\nsolution = parsimonious_flux_balance_analysis(\n model;\n optimizer = HiGHS.Optimizer, # HiGHS is used only for LP here\n parsimonious_optimizer = Clarabel.Optimizer, # Clarabel is great for solving QPs\n)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/#Using-linear-(L1)-parsimonious-constraints","page":"Parsimonious flux balance analysis","title":"Using linear (L1) parsimonious constraints","text":"","category":"section"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"For efficiency reasons, it is also possible to use a pFBA version that optimizes the L1 norm instead of the L2 one (i.e., minimizing a sum of absolute values instead of the sum of squares). In turn, the uniqueness property of the solution is lost, but we do not need a QP-capable optimizer at all:","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"linear_solution =\n linear_parsimonious_flux_balance_analysis(model; optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"linear_solution.fluxes","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"","category":"page"},{"location":"examples/03b-parsimonious-flux-balance/","page":"Parsimonious flux balance analysis","title":"Parsimonious flux balance analysis","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"EditURL = \"05c-mmdf.jl\"","category":"page"},{"location":"examples/05c-mmdf/#Thermodynamic-models","page":"Thermodynamic models","title":"Thermodynamic models","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"using COBREXA","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Here we will solve the max min driving force analysis problem using the glycolysis pathway of E. coli. In essence, the method attempts to find metabolite concentrations (NB: not fluxes) that maximize the smallest thermodynamic driving force through each reaction. See Noor, et al., \"Pathway thermodynamics highlights kinetic obstacles in central metabolism.\", PLoS computational biology, 2014, for more details.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"To do this, we will first need a model that includes glycolysis, which we can download if it is not already present.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Additionally to COBREXA, and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05c-mmdf/#Thermodynamic-data","page":"Thermodynamic models","title":"Thermodynamic data","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"We will need ΔᵣG⁰ data for each reaction we want to include in the thermodynamic model. To generate this data manually, use eQuilibrator. To generate automatically, it is possible to use the eQuilibrator.jl package.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"reaction_standard_gibbs_free_energies = Dict{String,Float64}( # units of the energies are kJ/mol\n \"ENO\" => -3.8108376097261782,\n \"FBA\" => 23.376920310319235,\n \"GAPD\" => 0.5307809794271634,\n \"GLCpts\" => -45.42430981510088,\n \"LDH_D\" => 20.04059765689044,\n \"PFK\" => -18.546314942995934,\n \"PGI\" => 2.6307087407442395,\n \"PGK\" => 19.57192102020454,\n \"PGM\" => -4.470553692565886,\n \"PYK\" => -24.48733600711958,\n \"TPI\" => 5.621932460512994,\n)","category":"page"},{"location":"examples/05c-mmdf/#Running-basic-max-min-driving-force-analysis","page":"Thermodynamic models","title":"Running basic max min driving force analysis","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"If a reference flux is not specified, it is assumed that every reaction in the model should be included in the thermodynamic model, and that each reaction proceeds in the forward direction. This is usually not intended, and can be prevented by inputting a reference flux dictionary as shown below. This dictionary can be a flux solution. The sign of each flux is used to determine if the reaction runs forward or backward.","category":"page"},{"location":"examples/05c-mmdf/#Using-a-reference-solution","page":"Thermodynamic models","title":"Using a reference solution","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"Frequently it is useful to check the max-min driving force of a specific FBA solution. In this case, one is usually only interested in a subset of all the reactions in a model. These reactions can be specified as a the reference_flux, to only compute the MMDF of these reactions, and ignore all other reactions.","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"reference_flux = Dict(\n \"ENO\" => 1.0,\n \"FBA\" => 1.0,\n \"GAPD\" => 1.0,\n \"GLCpts\" => 1.0,\n \"LDH_D\" => -1.0,\n \"PFK\" => 1.0,\n \"PGI\" => 1.0,\n \"PGK\" => -1.0,\n \"PGM\" => 0.0,\n \"PYK\" => 1.0,\n \"TPI\" => 1.0,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"warning: Only the signs are extracted from the reference solution\nIt is most convenient to pass a flux solution into reference_flux, but take care about the fluxes with value near 0: Their desired sign may be a subject to floating-point robustness error. By default, max_min_driving_force_analysis considers everything that is approximately zero (via isapprox) to have zero flux, with the appropriate implications to concentration balance.","category":"page"},{"location":"examples/05c-mmdf/#Solving-the-MMDF-problem","page":"Thermodynamic models","title":"Solving the MMDF problem","text":"","category":"section"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"mmdf_solution = max_min_driving_force_analysis(\n model;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n constant_concentrations = Dict(\"g3p_c\" => exp(-8.5)),\n concentration_ratios = Dict(\n \"atp\" => (\"atp_c\", \"adp_c\", 10.0),\n \"nadh\" => (\"nadh_c\", \"nad_c\", 0.13),\n ),\n proton_metabolites = [\"h_c\"],\n water_metabolites = [\"h2o_c\"],\n concentration_lower_bound = 1e-6, # mol/L\n concentration_upper_bound = 1e-1, # mol/L\n T = 298.15, # Kelvin\n R = 8.31446261815324e-3, # kJ/K/mol\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"One may be also interested in seeing the FVA-like feasible concentration ranges in such model. The most straightforward way to find these is to use the associated constraint-system-building function max_min_driving_force_constraints together with constraints_variability as follows:","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"mmdf_system = max_min_driving_force_constraints(\n model;\n reaction_standard_gibbs_free_energies,\n reference_flux,\n constant_concentrations = Dict(\"g3p_c\" => exp(-8.5)),\n concentration_ratios = Dict(\n \"atp\" => (\"atp_c\", \"adp_c\", 10.0),\n \"nadh\" => (\"nadh_c\", \"nad_c\", 0.13),\n ),\n proton_metabolites = [\"h_c\"],\n water_metabolites = [\"h2o_c\"],\n concentration_lower_bound = 1e-6, # mol/L\n concentration_upper_bound = 1e-1, # mol/L\n T = 298.15, # Kelvin\n R = 8.31446261815324e-3, # kJ/K/mol\n)\n\ncva_solution = constraints_variability(\n mmdf_system,\n mmdf_system.log_concentrations,\n objective = mmdf_system.min_driving_force.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"","category":"page"},{"location":"examples/05c-mmdf/","page":"Thermodynamic models","title":"Thermodynamic models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"EditURL = \"05d-loopless-models.jl\"","category":"page"},{"location":"examples/05d-loopless-models/#Loopless-flux-balance-analysis-(ll-FBA)","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"","category":"section"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Here we wil add loopless constraints to a flux balance model to ensure that the resultant solution is thermodynamically consistent. As before, we will use the core E. coli model, which we can download using download_model:","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Additionally to COBREXA and the JSON model format package. We will also need a solver which can solve mixed-interger linear programs, such as HiGHS.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05d-loopless-models/#Running-a-loopless-FBA-(ll-FBA)","page":"Loopless flux balance analysis (ll-FBA)","title":"Running a loopless FBA (ll-FBA)","text":"","category":"section"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"One can directly use loopless_flux_balance_analysis to solve an FBA problem based on model where loopless constraints are added to all fluxes. This is the direct approach.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"solution = loopless_flux_balance_analysis(model; optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"Loopless constraints can also be added to any model (e.g. enzyme constrained models). Refer to the source code of loopless_flux_balance_constraints for guidance.","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"","category":"page"},{"location":"examples/05d-loopless-models/","page":"Loopless flux balance analysis (ll-FBA)","title":"Loopless flux balance analysis (ll-FBA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"EditURL = \"02c-model-modifications.jl\"","category":"page"},{"location":"examples/02c-model-modifications/#Making-adjustments-to-the-model","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Typically, we do not need to solve the models as they come from the authors (someone else already did that!), but we want to perform various perturbations in the model structure and conditions, and explore how the model behaves in the changed conditions.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With COBREXA, there are 2 different approaches that one can take:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We can change the model structure, and use the changed metabolic model. This is better for doing simple and small, but systematic modifications, such as removing metabolites, adding reactions, etc.\nWe can intercept the pipeline that converts the metabolic model to constraints and to the optimizer representation, and make modifications along that way. This is better suited to making global model adjustments, such as using combined objectives, adding reaction-coupling constraints, and combining multiple models into a bigger one.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Here we demonstrate the first, \"modeling\" approach. The main advantage of this approach is that the modified model is still a FBC model, and we can export, save and share it via the AbstractFBCModels interace. The main disadvantage is that the \"common\" FBC model interface does not easily express various complicated constructions (communities, reaction coupling, enzyme constraints, etc.) – see the example about modifying the constraints for more details.","category":"page"},{"location":"examples/02c-model-modifications/#Getting-the-base-model","page":"Making adjustments to the model","title":"Getting the base model","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"For applying the modifications, we will use the canonical model as exported from package AbstractFBCModels. There are other possibilities, but the canonical one is easiest to use for common purposes.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"import AbstractFBCModels.CanonicalModel as CM","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We can now load the model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model = convert(CM.Model, load_model(\"e_coli_core.json\"))","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"The canonical model is quite easy to work with, made basically of the most accessible Julia structures possible. For example, we can look at a reaction as such:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"PFK\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"CS\"].stoichiometry","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"tip: Create custom model types!\nFor some applications, CanonicalModel might be too restrictive. Creating a custom model type that perfectly fits a use-case can be done simply by overloading several functions. The documentation of AbstractFBCModels describes the process closer. Further, all model types that adhere to the AbstractFBCModels' interface will \"just work\" with all analysis functions in COBREXA!","category":"page"},{"location":"examples/02c-model-modifications/#Running-FBA-on-modified-models","page":"Making adjustments to the model","title":"Running FBA on modified models","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Since the canonical model is completely mutable, we can change it in any way we like and feed the result directly into flux_balance_analysis. Let's first find a \"original\" solution, so that we have a base solution for comparing:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"import HiGHS\n\nbase_solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\nbase_solution.objective","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Now, for example, we can limit the intake of glucose by the model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"EX_glc__D_e\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Since the original intake limit is 10 units, let's try limiting that to 5:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.reactions[\"EX_glc__D_e\"].lower_bound = -5.0","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and solve the modified model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"low_glucose_solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\nlow_glucose_solution.objective","category":"page"},{"location":"examples/02c-model-modifications/#Preventing-reference-based-sharing-problems-with-deepcopy","page":"Making adjustments to the model","title":"Preventing reference-based sharing problems with deepcopy","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"People often want to try different perturbations with a single base model. It would therefore look feasible to save the \"unmodified\" model in a single variable, and make copies of that with the modifications applied. Let's observe what happens:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model = convert(CM.Model, load_model(\"e_coli_core.json\")) # load the base\n\nmodified_model = base_model # seemingly make a \"copy\" for modification\n\nmodified_model.reactions[\"EX_glc__D_e\"].lower_bound = -123.0 # modify the glucose intake limit","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Surprisingly, the base model got modified too!","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model.reactions[\"EX_glc__D_e\"]","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"This is because Julia uses reference-based sharing whenever anything mutable is copied using the = operator. While this is extremely useful in many scenarios for data processing efficiency and computational speed, it unfortunately breaks this simple use-case.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"To fix this situation, we must always remember to make an actual copy of the model data, by either carefully copying the changed parts (e.g., using a similar approach as with the \"shallow\" copy()), or simply by copying the whole model structure as is with deepcopy(). Let's try again:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"base_model = convert(CM.Model, load_model(\"e_coli_core.json\"))\nmodified_model = deepcopy(base_model) # this forces an actual copy of the data\nmodified_model.reactions[\"EX_glc__D_e\"].lower_bound = -123.0","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With deepcopy, the result works as intended:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"(\n modified_model.reactions[\"EX_glc__D_e\"].lower_bound,\n base_model.reactions[\"EX_glc__D_e\"].lower_bound,\n)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"danger: Avoid overwriting base models when using in-place modifications\nWhenever changing a copy of the model, check that the base model is not inadvertently changed via a reference. Always use some copy mechanism such as copy or deepcopy to prevent the default reference-based sharing.","category":"page"},{"location":"examples/02c-model-modifications/#Observing-the-differences","page":"Making adjustments to the model","title":"Observing the differences","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"We already have a base_solution and low_glucose_solution from above. What is the easiest way to see what has changed? We can quite easily compute squared distance between all dictionary entries using Julia function for merging dictionaries (called mergewith).","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"With that, we can extract the plain difference in fluxes:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"flux_differences = mergewith(-, base_solution.fluxes, low_glucose_solution.fluxes)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and see what were the biggest directional differences:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"sort(collect(flux_differences), by = last)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...or compute the squared distance, to see the \"absolute\" changes:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"flux_changes =\n mergewith((x, y) -> (x - y)^2, base_solution.fluxes, low_glucose_solution.fluxes)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"...and again see what changed most:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"sort(collect(flux_changes), by = last)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"tip: Always use a uniquely defined flux solutions for flux comparisons\nSince the usual flux balance allows a lot of freedom in the \"solved\" flux and the only value that is \"reproducible\" by the analysis is the objective, one should never compare the flux distributions directly. Typically, that may result in false-positive (and sometimes false-negative) differences. Use e.g. parsimonious FBA to obtain uniquely determined and safely comparable flux solutions.","category":"page"},{"location":"examples/02c-model-modifications/#Coupling-constraints","page":"Making adjustments to the model","title":"Coupling constraints","text":"","category":"section"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Some model types support additional constraints over the reaction fluxes, which are historically called \"coupling\". These allow to e.g. place a bound on a total flux through several reactions.","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"Canonical model supports these as \"couplings\":","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"model.couplings[\"total_energy_intake\"] = CM.Coupling(\n lower_bound = 0,\n upper_bound = 5,\n reaction_weights = Dict(\"EX_glc__D_e\" => -1.0, \"EX_fru_e\" => -1.0, \"EX_pyr_e\" => -1.0),\n)","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"The values of any coupling constraints can be inspected directly in the solved model:","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"solution_with_coupling = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)\n\nsolution_with_coupling.coupling.total_energy_intake","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"","category":"page"},{"location":"examples/02c-model-modifications/","page":"Making adjustments to the model","title":"Making adjustments to the model","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"EditURL = \"03c-envelopes.jl\"","category":"page"},{"location":"examples/03c-envelopes/#Production-envelopes","page":"Production envelopes","title":"Production envelopes","text":"","category":"section"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"Production envelopes determine the flux of the model objective at different values of specific reactions, spanning their variability. We can use the builtin function objective_production_envelope to quickly find such envelopes.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"We proceed as usual by loading the necessary models and packages:","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"The objective_production_envelope function finds the variability of the given reactons and returns a multidimensional matrix with exact number of breaks in each dimension (positioned in a linear lattice). Here we examine the inter-dependency of oxygen and carbon dioxide exchanges on a matrix of 5×5 individual \"conditions\" that form the envelope:","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"envelope = objective_production_envelope(\n model,\n [\"EX_o2_e\", \"EX_co2_e\"];\n breaks = 5,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"Documentation of the function describes ways to set custom bounds for the examined reaction flux ranges and several other customizations.","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"","category":"page"},{"location":"examples/03c-envelopes/","page":"Production envelopes","title":"Production envelopes","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"EditURL = \"06a-sampling.jl\"","category":"page"},{"location":"examples/06a-sampling/#Flux-sampling","page":"Flux sampling","title":"Flux sampling","text":"","category":"section"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"Flux sampling gives an interesting statistical insight into the behavior of the model in the optimal feasible space, and the general \"shape\" of the optimal- or near-optimal set of feasible states of a given model.","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"For demonstration, we need the usual packages and models:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"Function flux_sample uses linear optimization to generate a set of warm-up points (by default, the method to generate the warm-up is basically FVA), and then runs the hit-and-run flux sampling algorithm on the near-optimal feasible space of the model:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"s = flux_sample(\n model,\n optimizer = HiGHS.Optimizer,\n objective_bound = relative_tolerance_bound(0.99),\n n_chains = 2,\n collect_iterations = [10],\n)","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"The result is a tree of vectors of sampled states for each value; the order of the values in these vectors is fixed. You can thus e.g. create a good matrix for plotting the sample as 2D scatterplot:","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"[s.O2t s.CO2t]","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"","category":"page"},{"location":"examples/06a-sampling/","page":"Flux sampling","title":"Flux sampling","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"EditURL = \"02b-optimizer-parameters.jl\"","category":"page"},{"location":"examples/02b-optimizer-parameters/#Changing-optimizer-parameters","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"","category":"section"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Many optimizers require fine-tuning to produce best results. We can pass in additional optimizer settings via the settings parameter of flux_balance_analysis. These include e.g.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"set_optimizer_attribute, allowing us to tune e.g. iteration limits, tolerances, or floating-point precision (see JuMP documentation for more solver-specific settings)\nset_objective_sense, allowing the user to change and reverse the optimization direction, if required\nsilence for disabling the debug output of the optimizers\nset_optimizer for replacing the optimizer implementation used (this is not quite useful in this case, but becomes beneficial with more complex, multi-stage optimization problems)\nset_time_limit for putting a time limit on the solver computation (this is quite useful for MILP solvers)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To demonstrate this, let's use the usual toy model:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"using COBREXA\nimport JSONFBCModels, Tulip\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Running a FBA with a silent optimizer that has slightly increased iteration limit for IPM algorithm may now look as follows:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [set_optimizer_attribute(\"IPM_IterationsLimit\", 1000)],\n)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To see some of the effects of the configuration changes, we may e.g. deliberately cripple the optimizer's possibilities to a few iterations and only a little time, which will cause it to fail and return no solution:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [set_optimizer_attribute(\"IPM_IterationsLimit\", 2), set_time_limit(0.1)],\n)\n\nprintln(solution)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"To see what failed, users may examine the solver output. Because all solver output is silenced by default for efficiency reasons, we need to explicitly pass in the unsilence setting:","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"solution = flux_balance_analysis(\n model,\n optimizer = Tulip.Optimizer,\n settings = [\n set_optimizer_attribute(\"IPM_IterationsLimit\", 2),\n set_time_limit(0.1),\n unsilence,\n ],\n)","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Applicable optimizer attributes are documented in the documentations of the respective optimizers. To browse the possibilities, one might want to see the JuMP documentation page that summarizes the references to the available optimizers.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"Default solver settings can be examined and changed via Configuration.","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"","category":"page"},{"location":"examples/02b-optimizer-parameters/","page":"Changing optimizer parameters","title":"Changing optimizer parameters","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"EditURL = \"05f-cyclefree.jl\"","category":"page"},{"location":"examples/05f-cyclefree/#CycleFreeFlux","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"CycleFreeFlux essentially defines a L1-parsimonious model which can be used to run a cycle-free FBA and FVA. In COBREXA, this is best done by reusing linear_parsimonious_flux_balance_analysis.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"First, let's get a model, create a constraint tree with the model, and ask for explicitly materializing constraints for the exchanges:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels, HiGHS\nmodel = load_model(\"e_coli_core.json\")\n\ncs = flux_balance_constraints(model, interface = :identifier_prefixes)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"We will also need some existing solution of the model – CycleFreeFlux algorithm uses this one as a reference for fixing the exchange reaction flux.","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"some_flux =\n optimized_values(cs, objective = cs.objective.value, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"(Ideally, we should use a solving method that gives a more unique flux, but for this example a simple FBA optimum will do.)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"With this in hand, we can start the CycleFreeFlux workflow by placing constraints on exchange reactions in a linear-parsimonious model:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"import ConstraintTrees as C\n\ncs = linear_parsimonious_flux_balance_constraints(model)\n\ncs *=\n :fixed_exchanges^C.ConstraintTree(\n k => C.Constraint(cs.fluxes[k].value, relative_tolerance_bound(0.999)(v)) for\n (k, v) in some_flux.interface.exchanges\n )","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"(We purposefully made the constraints a little less strict by using relative_tolerance_bound – the toy E. coli model would otherwise display no variability at all.)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Now we can get a L1-parsimonious (thus cycle-free) solution of the model with the predefined exchanges:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"cycle_free_flux = parsimonious_optimized_values(\n cs,\n objective = cs.objective.value,\n objective_value = some_flux.objective,\n parsimonious_objective = cs.parsimonious_objective.value,\n optimizer = HiGHS.Optimizer,\n)\n\ncycle_free_flux.fluxes","category":"page"},{"location":"examples/05f-cyclefree/#CycleFreeFVA","page":"CycleFreeFlux","title":"CycleFreeFVA","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"With this in hand, we can also run the cycle-free flux variability analysis (again with an added bit of tolerances in both the objective and parsimonious bounds):","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"cs.objective.bound = C.Between(cycle_free_flux.objective * 0.999, Inf)\ncs.parsimonious_objective.bound =\n C.Between(0, cycle_free_flux.parsimonious_objective * 1.001)\n\nvar = constraints_variability(cs, cs.fluxes, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05f-cyclefree/#CycleFree-sampling","page":"CycleFreeFlux","title":"CycleFree sampling","text":"","category":"section"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Naturally, we can also run flux sampling from the above model. To implement this, we follow the implementation of flux_sample –- first we generate the warmup:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"warmup = vcat(\n (\n transpose(v) for (_, vs) in constraints_variability(\n cs,\n cs.fluxes,\n optimizer = HiGHS.Optimizer,\n output = (_, om) -> variable_vector(om),\n output_type = Vector{Float64},\n ) for v in vs\n )...,\n)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"Next, we can run the sampling:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"sample = sample_constraints(\n sample_chain_achr,\n cs,\n start_variables = warmup,\n seed = UInt(1234),\n output = cs.fluxes,\n n_chains = 10,\n collect_iterations = collect(10:15),\n)","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"The results can be observed (and usually plotted) from the sample vectors, such as the one for oxygen exchange:","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"sample.EX_o2_e","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"","category":"page"},{"location":"examples/05f-cyclefree/","page":"CycleFreeFlux","title":"CycleFreeFlux","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"EditURL = \"02a-flux-balance-analysis.jl\"","category":"page"},{"location":"examples/02a-flux-balance-analysis/#Flux-balance-analysis-(FBA)","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"","category":"section"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"Here we use flux_balance_analysis and several related functions to find an optimal flux in the E. coli \"core\" model. We will need the model, which we can download using download_model:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"Additionally to COBREXA and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"import JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/02a-flux-balance-analysis/#Running-a-FBA","page":"Flux balance analysis (FBA)","title":"Running a FBA","text":"","category":"section"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"There are many possibilities on how to arrange the metabolic model into the optimization framework and how to actually solve it. The \"usual\" assumed one is captured in the default behavior of function flux_balance_analysis:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution = flux_balance_analysis(model, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"The result contains a tree of all optimized values in the model, including fluxes, the objective value, and possibly others (given by what the model contains).","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"We can use the dot notation to explore the solution, extracting e.g. the value of the objective:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution.objective","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"...or the value of the flux through the given reaction (note the solution is not unique in FBA):","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"solution.fluxes.PFK","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"tip: Browsing the model structure\nAfter typing solution. in the Julia REPL, one can press [tab] to quickly see what is in the next level of the tree. Unfortunately (due to type system limitations) this currently works only for the topmost level of the tree.","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"...or make a \"table\" of all fluxes through all reactions:","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"collect(solution.fluxes)","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"","category":"page"},{"location":"examples/02a-flux-balance-analysis/","page":"Flux balance analysis (FBA)","title":"Flux balance analysis (FBA)","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"EditURL = \"05e-knockouts.jl\"","category":"page"},{"location":"examples/05e-knockouts/#Gene-knockouts","page":"Gene knockouts","title":"Gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"FBA is classically very good at predicting the effect of knocking out genes in an organism. Here we demonstrate the ways of using the FBA to examine knockouts in COBREXA.","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"As usual, we need packages and models:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"using COBREXA\n\ndownload_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)\n\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05e-knockouts/#Single-gene-knockouts","page":"Gene knockouts","title":"Single gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"Function gene_knockouts is a convenience wrapper for FBA that computes and optimizes the knockout biomass productions for all genes:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"ko_objective_values = gene_knockouts(model, optimizer = HiGHS.Optimizer)\n\nko_dict = Dict(ko_objective_values)\n\n\nko_dict[\"b3919\"]\n\nko_dict[\"b3738\"]","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"From the result, we can see e.g. how many genes are critical:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"critical = count(isnothing, values(ko_dict))","category":"page"},{"location":"examples/05e-knockouts/#Multiple-gene-knockouts","page":"Gene knockouts","title":"Multiple gene knockouts","text":"","category":"section"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"By default, gene_knockouts simply computes all gene knockouts. To examine multi-gene knockouts, we specify them manually as an array of tuples:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"some_double_knockouts = gene_knockouts(\n model,\n [(\"b3919\", \"b3738\"), (\"b0118\", \"b0720\")],\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"With the array processing functionality of Julia it is quite straightforward to generate the tuples for various specifications of knockout sets; for example here we specify all double knockout where the second knocked-out gene is b3919:","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"knockouts_with_b3919 =\n gene_knockouts(model, tuple.(keys(ko_dict), \"b3919\"), optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"Now, how many genes are critical given b3919 is already missing?","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"critical_without_b3919 = count(isnothing, last.(knockouts_with_b3919))","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"","category":"page"},{"location":"examples/05e-knockouts/","page":"Gene knockouts","title":"Gene knockouts","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"EditURL = \"05b-enzyme-constrained-models.jl\"","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Enzyme-constrained-models","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained metabolic models include the effect of enzyme kinetics (v = k * e) and a protein capacity limitation (∑e = Etotal) on conventional mass balance (FBA) models.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"using COBREXA","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Here we will construct an enzyme constrained variant of the E. coli \"core\" model. We will need the model, which we can download if it is not already present.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Additionally to COBREXA and the model format package, we will need a solver – let's use HiGHS here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"import AbstractFBCModels as A\nimport JSONFBCModels\nimport HiGHS\n\nmodel = load_model(\"e_coli_core.json\")","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained models require parameters that are usually not used by conventional constraint based models. These include reaction specific turnover numbers, molar masses of enzymes, and protein capacity bounds.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Reaction-turnover-numbers","page":"Enzyme constrained models","title":"Reaction turnover numbers","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme constrained models require reaction turnover numbers, which are often isozyme specfic. Many machine learning tools, or experimental data sets, can be used to estimate these parameters.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
Data for reaction turnover numbers","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This data is taken from: Heckmann, David, et al. \"Machine learning applied to enzyme turnover numbers reveals protein structural correlates and improves metabolic models.\" Nature communications 9.1 (2018): 1-10.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"const ecoli_core_reaction_kcats = Dict(\n \"ACALD\" => 568.11,\n \"PTAr\" => 1171.97,\n \"ALCD2x\" => 75.95,\n \"PDH\" => 529.76,\n \"MALt2_2\" => 234.03,\n \"CS\" => 113.29,\n \"PGM\" => 681.4,\n \"TKT1\" => 311.16,\n \"ACONTa\" => 191.02,\n \"GLNS\" => 89.83,\n \"ICL\" => 17.45,\n \"FBA\" => 373.42,\n \"FORt2\" => 233.93,\n \"G6PDH2r\" => 589.37,\n \"AKGDH\" => 264.48,\n \"TKT2\" => 467.42,\n \"FRD7\" => 90.20,\n \"SUCOAS\" => 18.49,\n \"ICDHyr\" => 39.62,\n \"AKGt2r\" => 234.99,\n \"GLUSy\" => 33.26,\n \"TPI\" => 698.30,\n \"FORt\" => 234.38,\n \"ACONTb\" => 159.74,\n \"GLNabc\" => 233.80,\n \"RPE\" => 1772.485,\n \"ACKr\" => 554.61,\n \"THD2\" => 24.73,\n \"PFL\" => 96.56,\n \"RPI\" => 51.77,\n \"D_LACt2\" => 233.51,\n \"TALA\" => 109.05,\n \"PPCK\" => 218.42,\n \"PGL\" => 2120.42,\n \"NADTRHD\" => 186.99,\n \"PGK\" => 57.64,\n \"LDH_D\" => 31.11,\n \"ME1\" => 487.01,\n \"PIt2r\" => 233.86,\n \"ATPS4r\" => 71.42,\n \"GLCpts\" => 233.90,\n \"GLUDy\" => 105.32,\n \"CYTBD\" => 153.18,\n \"FUMt2_2\" => 234.37,\n \"FRUpts2\" => 234.19,\n \"GAPD\" => 128.76,\n \"PPC\" => 165.52,\n \"NADH16\" => 971.74,\n \"PFK\" => 1000.46,\n \"MDH\" => 25.93,\n \"PGI\" => 468.11,\n \"ME2\" => 443.09,\n \"GND\" => 240.12,\n \"SUCCt2_2\" => 234.18,\n \"GLUN\" => 44.76,\n \"ADK1\" => 111.64,\n \"SUCDi\" => 680.31,\n \"ENO\" => 209.35,\n \"MALS\" => 252.75,\n \"GLUt2r\" => 234.22,\n \"PPS\" => 706.14,\n \"FUM\" => 1576.83,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We have these here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ecoli_core_reaction_kcats # units = 1/s","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Each reaction in a constraint-based model usually has gene reaction rules associated with it. These typically take the form of, possibly multiple, isozymes that can catalyze a reaction. A turnover number needs to be assigned to each isozyme, as shown below. Additionally, some enzymes are composed of multiple subunits, which differ in subunit stoichiometry. This also needs to be accounted for. Assuming a stoichiometry of 1 for everything tends to work just right OK if there is no better information available.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"reaction_isozymes = Dict{String,Dict{String,Isozyme}}() # a mapping from reaction IDs to isozyme IDs to isozyme structs.\nfor rid in A.reactions(model)\n grrs = A.reaction_gene_association_dnf(model, rid)\n isnothing(grrs) && continue # skip if no grr available\n haskey(ecoli_core_reaction_kcats, rid) || continue # skip if no kcat data available\n for (i, grr) in enumerate(grrs)\n d = get!(reaction_isozymes, rid, Dict{String,Isozyme}())\n d[\"isozyme_\"*string(i)] = Isozyme( # each isozyme gets a unique name\n gene_product_stoichiometry = Dict(grr .=> fill(1.0, size(grr))), # assume subunit stoichiometry of 1 for all isozymes\n kcat_forward = ecoli_core_reaction_kcats[rid] * 3.6, # forward reaction turnover number units = 1/h\n kcat_reverse = ecoli_core_reaction_kcats[rid] * 3.6, # reverse reaction turnover number units = 1/h\n )\n end\nend","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"tip: Turnover number units\nTake care with the units of the turnover numbers. In literature they are usually reported in 1/s. However, flux units are typically mmol/gDW/h, suggesting to rescale the turnover numbers to 1/h in order to use the conventional flux units.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Enzyme-molar-masses","page":"Enzyme constrained models","title":"Enzyme molar masses","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We also require the mass of each enzyme, to properly weight the contribution of each flux/isozyme in the capacity bound(s). These data can typically be found in uniprot.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
Gene product masses","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This data is downloaded from Uniprot for E. coli K12, gene mass in kDa. To obtain these data manually, go to Uniprot and search using these terms: reviewed:yes AND organism:\"Escherichia coli (strain K12) [83333]\".","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"const ecoli_core_gene_product_masses = Dict(\n \"b4301\" => 23.214,\n \"b1602\" => 48.723,\n \"b4154\" => 65.972,\n \"b3236\" => 32.337,\n \"b1621\" => 56.627,\n \"b1779\" => 35.532,\n \"b3951\" => 85.96,\n \"b1676\" => 50.729,\n \"b3114\" => 85.936,\n \"b1241\" => 96.127,\n \"b2276\" => 52.044,\n \"b1761\" => 48.581,\n \"b3925\" => 35.852,\n \"b3493\" => 53.389,\n \"b3733\" => 31.577,\n \"b2926\" => 41.118,\n \"b0979\" => 42.424,\n \"b4015\" => 47.522,\n \"b2296\" => 43.29,\n \"b4232\" => 36.834,\n \"b3732\" => 50.325,\n \"b2282\" => 36.219,\n \"b2283\" => 100.299,\n \"b0451\" => 44.515,\n \"b2463\" => 82.417,\n \"b0734\" => 42.453,\n \"b3738\" => 30.303,\n \"b3386\" => 24.554,\n \"b3603\" => 59.168,\n \"b2416\" => 63.562,\n \"b0729\" => 29.777,\n \"b0767\" => 36.308,\n \"b3734\" => 55.222,\n \"b4122\" => 60.105,\n \"b2987\" => 53.809,\n \"b2579\" => 14.284,\n \"b0809\" => 26.731,\n \"b1524\" => 33.516,\n \"b3612\" => 56.194,\n \"b3735\" => 19.332,\n \"b3731\" => 15.068,\n \"b1817\" => 35.048,\n \"b1603\" => 54.623,\n \"b1773\" => 30.81,\n \"b4090\" => 16.073,\n \"b0114\" => 99.668,\n \"b3962\" => 51.56,\n \"b2464\" => 35.659,\n \"b2976\" => 80.489,\n \"b1818\" => 27.636,\n \"b2285\" => 18.59,\n \"b1702\" => 87.435,\n \"b1849\" => 42.434,\n \"b1812\" => 50.97,\n \"b0902\" => 28.204,\n \"b3403\" => 59.643,\n \"b1612\" => 60.299,\n \"b1854\" => 51.357,\n \"b0811\" => 27.19,\n \"b0721\" => 14.299,\n \"b2914\" => 22.86,\n \"b1297\" => 53.177,\n \"b0723\" => 64.422,\n \"b3919\" => 26.972,\n \"b3115\" => 43.384,\n \"b4077\" => 47.159,\n \"b3528\" => 45.436,\n \"b0351\" => 33.442,\n \"b2029\" => 51.481,\n \"b1819\" => 30.955,\n \"b0728\" => 41.393,\n \"b2935\" => 72.212,\n \"b2415\" => 9.119,\n \"b0727\" => 44.011,\n \"b0116\" => 50.688,\n \"b0485\" => 32.903,\n \"b3736\" => 17.264,\n \"b0008\" => 35.219,\n \"b3212\" => 163.297,\n \"b3870\" => 51.904,\n \"b4014\" => 60.274,\n \"b2280\" => 19.875,\n \"b2133\" => 64.612,\n \"b2278\" => 66.438,\n \"b0118\" => 93.498,\n \"b2288\" => 16.457,\n \"b3739\" => 13.632,\n \"b3916\" => 34.842,\n \"b3952\" => 32.43,\n \"b2925\" => 39.147,\n \"b2465\" => 73.043,\n \"b2297\" => 77.172,\n \"b2417\" => 18.251,\n \"b4395\" => 24.065,\n \"b3956\" => 99.063,\n \"b0722\" => 12.868,\n \"b2779\" => 45.655,\n \"b0115\" => 66.096,\n \"b0733\" => 58.205,\n \"b1478\" => 35.38,\n \"b2492\" => 30.565,\n \"b0724\" => 26.77,\n \"b0755\" => 28.556,\n \"b1136\" => 45.757,\n \"b2286\" => 68.236,\n \"b0978\" => 57.92,\n \"b1852\" => 55.704,\n \"b2281\" => 20.538,\n \"b2587\" => 47.052,\n \"b2458\" => 36.067,\n \"b0904\" => 30.991,\n \"b1101\" => 50.677,\n \"b0875\" => 23.703,\n \"b3213\" => 52.015,\n \"b2975\" => 58.92,\n \"b0720\" => 48.015,\n \"b0903\" => 85.357,\n \"b1723\" => 32.456,\n \"b2097\" => 38.109,\n \"b3737\" => 8.256,\n \"b0810\" => 24.364,\n \"b4025\" => 61.53,\n \"b1380\" => 36.535,\n \"b0356\" => 39.359,\n \"b2277\" => 56.525,\n \"b1276\" => 97.677,\n \"b4152\" => 15.015,\n \"b1479\" => 63.197,\n \"b4153\" => 27.123,\n \"b4151\" => 13.107,\n \"b2287\" => 25.056,\n \"b0474\" => 23.586,\n \"b2284\" => 49.292,\n \"b1611\" => 50.489,\n \"b0726\" => 105.062,\n \"b2279\" => 10.845,\n \"s0001\" => 0.0,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"
","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We have the molar masses here:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ecoli_core_gene_product_masses # unit kDa = kg/mol","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"tip: Molar mass units\nJust as with the turnover numbers, take extreme care about the units of the molar masses. In literature they are usually reported in Da or kDa (g/mol). However, as noted above, flux units are typically mmol/gDW/h. Since the enzyme kinetic equation is v = k * e (where k is the turnover number) it suggests that the enzyme variable will have units of mmol/gDW. The molar masses come into play when setting the capacity limitations, e.g. usually a sum over all enzymes weighted by their molar masses as e * M. Thus, if the capacity limitation has units of g/gDW, then the molar masses must have units of g/mmol (i.e., kDa).","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Capacity-limitation","page":"Enzyme constrained models","title":"Capacity limitation","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"The capacity limitation usually denotes an upper bound of protein available to the cell. Multiple capacity bounds can be used (cytosol, membrane, etc).","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"total_enzyme_capacity = 50.0 # mg of enzyme/gDW","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Running-a-basic-enzyme-constrained-model","page":"Enzyme constrained models","title":"Running a basic enzyme constrained model","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"With all the parameters specified, we can directly use the enzyme constrained convenience function to run enzyme constrained FBA in one shot:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution = enzyme_constrained_flux_balance_analysis(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"We can notice that the objective function is a little lower than with unconstrained E. coli core:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.objective","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"One can also observe many interesting thing, e.g. the amount of gene product material required for the system to run. Importantly, the units of these values depend on the units used to set the turnover numbers and protein molar masses.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"The total amount of required gene product mass is, by default, present as total_capacity:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_solution.gene_product_capacity","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Simplified-models","page":"Enzyme constrained models","title":"Simplified models","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Because most active reactions typically only use a single isozyme, we may also use a simplified representation of the problem where this fact is reflected, saving the variable allocation for the isozymes.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_enzyme_constrained_flux_balance_analysis takes similar arguments as the enzyme_constrained_flux_balance_analysis, but automatically chooses the \"fastest\" reaction isozyme for each reaction direction and builds the model with that.","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution = simplified_enzyme_constrained_flux_balance_analysis(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"In this case, the result is the same as with the full analysis:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution.capacity_limits.total_capacity","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Gene product amounts are not present in the model but are reconstructed nevertheless (they are uniquely determined by the flux):","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"simplified_ec_solution.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/#Variability-analysis-with-enzyme-constraints","page":"Enzyme constrained models","title":"Variability analysis with enzyme constraints","text":"","category":"section"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Enzyme-constrained variability analysis can be executed on a model by combining enzyme_constrained_flux_balance_constraints (or simplified_enzyme_constrained_flux_balance_constraints) with constraints_variability (or any other analysis function):","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_system = enzyme_constrained_flux_balance_constraints(\n model;\n reaction_isozymes,\n gene_product_molar_masses = ecoli_core_gene_product_masses,\n capacity = total_enzyme_capacity,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"Here, we can do the FVA \"manually\", first solving the system:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_optimum = optimized_values(\n ec_system,\n output = ec_system.objective,\n objective = ec_system.objective.value,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...then creating a system constrained to near-optimal growth:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"import ConstraintTrees as C\n\nec_system.objective.bound = C.Between(0.99 * ec_optimum, Inf)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...and finally, finding the extremes of the near-optimal part of the feasible space:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities =\n constraints_variability(ec_system, ec_system, optimizer = HiGHS.Optimizer)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"By default, the result computes variabilities of all possible values in the model. (I.e., it also computes variabilities for the variable combinations that are present in the tree!) As usual, the results can be observed in the original constraint tree structure, giving us the variabilities for reaction fluxes:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.fluxes","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...as well as for gene product requirements:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.gene_product_amounts","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"...and for the individual directional isozymes:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_variabilities.isozyme_forward_amounts.PGM","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"If we do not need to compute all these values, it is often more efficient to only ask for the part of the output that is required:","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"ec_gp_amount_variabilities = constraints_variability(\n ec_system,\n ec_system.gene_product_amounts,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"","category":"page"},{"location":"examples/05b-enzyme-constrained-models/","page":"Enzyme constrained models","title":"Enzyme constrained models","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/core/#Core-functionality","page":"Core functionality","title":"Core functionality","text":"","category":"section"},{"location":"reference/core/#Model-I/O","page":"Core functionality","title":"Model I/O","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/io.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.download_model-Tuple","page":"Core functionality","title":"COBREXA.download_model","text":"download_model(args...; kwargs...) -> Any\n\n\nSafely download a model with a known hash. All arguments are forwarded to AbstractFBCModels.download_data_file – see the documentation in the AbstractFBCModels package for details.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Tuple{String}","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(path::String) -> Any\n\n\nLoad a FBC model representation while guessing the correct model type to load. Uses AbstractFBCModels.load.\n\nThis overload almost always involves a search over types; do not use it in environments where performance is critical.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{I}, Tuple{Type{I}, String}} where I<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},\n path::String\n) -> Any\n\n\nLoad a FBC model representation from a known model_type. Uses AbstractFBCModels.load.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{O}, Tuple{I}, Tuple{Type{I}, String, Type{O}}} where {I<:AbstractFBCModels.AbstractFBCModel, O<:AbstractFBCModels.AbstractFBCModel}","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n model_type::Type{I<:AbstractFBCModels.AbstractFBCModel},\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of load_model that explicitly specifies the known input type, and immediately converts to another model type given by argument convert_to.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.load_model-Union{Tuple{O}, Tuple{String, Type{O}}} where O<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.load_model","text":"load_model(\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of load_model that guesses the input type, but immediately converts to the model type given by argument convert_to.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_converted_model-Union{Tuple{T}, Tuple{T, String}} where T<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.save_converted_model","text":"save_converted_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String\n) -> Any\n\n\nLike save_model but tries to convert the model to a type that matches the extension of the path. For example, this will convert the model to a JSON model type in case the path ends with .json.\n\nThis is an utility shortcut – if possible, it is always better to specify the output model type explicitly.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_model-Union{Tuple{O}, Tuple{T}, Tuple{T, String, Type{O}}} where {T<:AbstractFBCModels.AbstractFBCModel, O<:AbstractFBCModels.AbstractFBCModel}","page":"Core functionality","title":"COBREXA.save_model","text":"save_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String,\n convert_to::Type{O<:AbstractFBCModels.AbstractFBCModel}\n) -> Any\n\n\nOverload of save_model that converts the model type to convert_to before saving.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.save_model-Union{Tuple{T}, Tuple{T, String}} where T<:AbstractFBCModels.AbstractFBCModel","page":"Core functionality","title":"COBREXA.save_model","text":"save_model(\n model::AbstractFBCModels.AbstractFBCModel,\n path::String\n) -> Any\n\n\nSave a FBC model representation. Uses AbstractFBCModels.save.\n\nUse the 3-parameter overload if you need to convert the model to another representation (e.g., if you want to save a canonical model type as JSON or SBML).\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#Types","page":"Core functionality","title":"Types","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/types.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.Maybe","page":"Core functionality","title":"COBREXA.Maybe","text":"Maybe{X}\n\nType of optional values.\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#Configuration","page":"Core functionality","title":"Configuration","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/config.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.configuration","page":"Core functionality","title":"COBREXA.configuration","text":"const configuration\n\nThe configuration object. You can change the contents of configuration to override the default behavior of some of the functions.\n\nThe available options are described by struct Configuration.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Configuration","page":"Core functionality","title":"COBREXA.Configuration","text":"mutable struct Configuration\n\nGlobal configuration options for various COBREXA functions, mainly for various non-interesting function parameters that are too inconvenient to be passed around manually.\n\nChanging the configuration values at runtime is possible via the global configuration variable.\n\nFields\n\nexchange_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are exchanges.\n\nbiomass_id_prefixes::Vector{String}: Prefixes that flux_balance_constraints uses for guessing which reactions are biomass reactions.\n\natp_maintenance_ids::Vector{String}: Reaction identifiers that flux_balance_constraints considers to be ATP maintenance reactions.\n\nexchange_sbos::Vector{String}: SBO numbers that label exchange reactions for flux_balance_constraints.\n\nbiomass_sbos::Vector{String}: SBO numbers that label biomass production reactions for flux_balance_constraints.\n\natp_maintenance_sbos::Vector{String}: SBO numbers that label ATP maintenance reactions for flux_balance_constraints.\n\ndemand_sbos::Vector{String}: SBO numbers that label metabolite demand reactions for flux_balance_constraints.\n\nsampler_tolerance::Any: Default numerical tolerance for sampling functions.\n\ndefault_solver_settings::Any: Default settings first applied to all JuMP Models.\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#Solver-interface","page":"Core functionality","title":"Solver interface","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/solver.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.Feasible","page":"Core functionality","title":"COBREXA.Feasible","text":"Maximal\n\nObjective sense for finding the any feasible value of the objective.\n\nSame as JuMP.FEASIBILITY_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Maximal","page":"Core functionality","title":"COBREXA.Maximal","text":"Maximal\n\nObjective sense for finding the maximal value of the objective.\n\nSame as JuMP.MAX_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Minimal","page":"Core functionality","title":"COBREXA.Minimal","text":"Minimal\n\nObjective sense for finding the minimal value of the objective.\n\nSame as JuMP.MIN_SENSE.\n\n\n\n\n\n","category":"constant"},{"location":"reference/core/#COBREXA.Switch","page":"Core functionality","title":"COBREXA.Switch","text":"mutable struct Switch <: ConstraintTrees.Bound\n\nRepresentation of a \"binary switch\" bound for ConstraintTrees. The value is constrained to be either the value of field a or of field b; both fields are Float64s. Upon translation to JuMP, the switches create an extra boolean variable, and the value is constrained to equal a + boolean_var * (b-a).\n\nSwitches can be offset by adding real numbers, negated, and multiplied and divided by scalar constraints. For optimizing some special cases, multiplying by exact zero returns an equality bound to zero.\n\nFields\n\na::Float64: One choice\nb::Float64: The other choice\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, ConstraintTrees.Between}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::ConstraintTrees.Between\n) -> Union{Bool, JuMP.ConstraintRef}\n\n\nAdd an interval constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, ConstraintTrees.EqualTo}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::ConstraintTrees.EqualTo\n) -> JuMP.ConstraintRef\n\n\nAdd an equality constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.constraint_jump!-Tuple{Any, Any, Switch}","page":"Core functionality","title":"COBREXA.constraint_jump!","text":"constraint_jump!(\n model,\n expr,\n b::Switch\n) -> JuMP.ConstraintRef\n\n\nAdd a Switch constraint to a JuMP model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.is_solved-Tuple{JuMP.Model}","page":"Core functionality","title":"COBREXA.is_solved","text":"is_solved(opt_model::JuMP.Model) -> Bool\n\n\ntrue if opt_model solved successfully (solution is optimal or locally optimal). false if any other termination status is reached.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimization_model-Tuple{Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}}}","page":"Core functionality","title":"COBREXA.optimization_model","text":"optimization_model(\n cs::Union{ConstraintTrees.Constraint, ConstraintTrees.Tree{ConstraintTrees.Constraint}};\n objective,\n optimizer,\n sense\n)\n\n\nConstruct a JuMP Model that describes the precise constraint system into the JuMP Model created for solving in optimizer, with a given optional objective and optimization sense chosen from Maximal, Minimal and Feasible.\n\nAll types of values in the constraint tree must have an overload for substitute_jump.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimized_model-Tuple{Any}","page":"Core functionality","title":"COBREXA.optimized_model","text":"optimized_model(om; output)\n\n\nLike optimized_values, but works directly with a given JuMP model om without applying any settings or creating the optimization model.\n\nTo run the process manually, you can use optimization_model to convert the constraints into a suitable JuMP optimization model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.optimized_objective-Tuple{Any}","page":"Core functionality","title":"COBREXA.optimized_objective","text":"optimized_objective(\n om\n) -> Union{Nothing, Float64, Vector{Float64}}\n\n\nLike optimized_model but only returns the objective value (or nothing if the model is not solved).\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.substitute_jump-Tuple{ConstraintTrees.LinearValue, Any}","page":"Core functionality","title":"COBREXA.substitute_jump","text":"substitute_jump(\n val::ConstraintTrees.LinearValue,\n vars\n) -> JuMP.AffExpr\n\n\nVery efficiently substitute a ConstraintTrees' LinearValue into a JuMP expression of type AffExpr.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.substitute_jump-Tuple{ConstraintTrees.QuadraticValue, Any}","page":"Core functionality","title":"COBREXA.substitute_jump","text":"substitute_jump(\n val::ConstraintTrees.QuadraticValue,\n vars\n) -> JuMP.QuadExpr\n\n\nVery efficiently substitute a ConstraintTrees' QuadraticValue into a JuMP expression of type QuadExpr.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#COBREXA.variable_vector-Tuple{JuMP.Model}","page":"Core functionality","title":"COBREXA.variable_vector","text":"variable_vector(opt_model::JuMP.Model) -> Any\n\n\nRetrieve the variable vector from a JuMP model created by optimization_model.\n\n\n\n\n\n","category":"method"},{"location":"reference/core/#Task-distribution-support","page":"Core functionality","title":"Task distribution support","text":"","category":"section"},{"location":"reference/core/","page":"Core functionality","title":"Core functionality","text":"Modules = [COBREXA]\nPages = [\"src/worker_data.jl\"]","category":"page"},{"location":"reference/core/#COBREXA.worker_local_data","page":"Core functionality","title":"COBREXA.worker_local_data","text":"mutable struct worker_local_data\n\nHelper struct that provides access to local data that are unboxed and cached directly on distributed workers.\n\nUse with get_worker_local_data and Distributed.CachingPool.\n\nFields\n\ntransfer_data::Any: The data that is transferred to the remote worker\nlocal_data::Union{Nothing, Some}: The data that is cached on the remote worker\ntransform::Function: The function that converts the transferred data to locally-cached data on the remote worker\n\n\n\n\n\n","category":"type"},{"location":"reference/core/#COBREXA.get_worker_local_data-Tuple{COBREXA.worker_local_data}","page":"Core functionality","title":"COBREXA.get_worker_local_data","text":"get_worker_local_data(x::COBREXA.worker_local_data) -> Any\n\n\n\"Unwrap\" the worker_local_data on a remote worker to get the local_data out. If required, executes the transform function.\n\nLocal copies of transfer_data are forgotten after the function executes.\n\n\n\n\n\n","category":"method"},{"location":"reference/#API-reference","page":"Contents","title":"API reference","text":"","category":"section"},{"location":"reference/","page":"Contents","title":"Contents","text":"Pages = [\"reference/core.md\", \"reference/frontend.md\", \"reference/builders.md\", \"reference/analysis.md\", \"reference/misc.md\"]\nDepth = 2","category":"page"},{"location":"distributed/2_parallel/#Local-parallel-processing","page":"Local parallel processing","title":"Local parallel processing","text":"","category":"section"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"To run an analysis in parallel, we first need to load the Distributed package and add a few worker processes. For example, we may start 5 local processes (that may utilize 5 CPUs) as follows","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"using Distributed\naddprocs(5)","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"note: `Distributed.jl` installation\nDistributed.jl usually comes pre-installed with Julia distribution, but one may still need to \"enable\" it by typing ] add Distributed.","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"To check that the workers are really there, use workers(). In this case, it should return a vector of worker IDs, very likely equal to [2,3,4,5,6].","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Each of the processes contains a self-sufficient image of Julia that can act independently; in turn the additional processes also consume some memory. Each process with loaded COBREXA.jl and a solver such as HiGHS may consume around 300MB of RAM, which should be taken into account when planning the analysis scale.","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"warning: Using Julia environments with Distributed\nIn certain conditions, the Distributed package does not properly forward the project configuration to the workers, resulting to package version mismatches and other problems. For pipelines that run in custom project folders, use the following form of addprocs instead:addprocs(5, exeflags=`--project=$(Base.active_project())`)","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Packages (COBREXA and the selected solver) must be loaded at all processes, which may ensured using the \"everywhere\" macro (from Distributed package):","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"@everywhere using COBREXA, HiGHS","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"Utilizing the prepared worker processes is then straightforward: We pass the list of workers to the selected analysis function using the workers keyword argument, and the parallel processing is orchestrated automatically:","category":"page"},{"location":"distributed/2_parallel/","page":"Local parallel processing","title":"Local parallel processing","text":"model = load_model(\"e_coli_core.xml\")\nresult = flux_variability_analysis(\n model,\n optimizer = HiGHS.Optimizer,\n workers = workers()\n)","category":"page"},{"location":"distributed/#Parallel,-distributed-and-HPC-processing","page":"Contents","title":"Parallel, distributed and HPC processing","text":"","category":"section"},{"location":"distributed/","page":"Contents","title":"Contents","text":"Pages = filter(x -> endswith(x, \".md\"), readdir(\"distributed\", join=true))\nDepth = 2","category":"page"},{"location":"reference/builders/#Constraint-system-builders","page":"Constraint system builders","title":"Constraint system builders","text":"","category":"section"},{"location":"reference/builders/#Generic-constraints","page":"Constraint system builders","title":"Generic constraints","text":"","category":"section"},{"location":"reference/builders/#Comparisons","page":"Constraint system builders","title":"Comparisons","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/compare.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.all_equal_constraints-Tuple{Any, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.all_equal_constraints","text":"all_equal_constraints(\n a,\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constriant tree that makes sure that all values in tree are the same as the value of a.\n\nNames in the output ConstraintTree match the names in the tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.difference_constraint-Tuple{Any, Any, Any}","page":"Constraint system builders","title":"COBREXA.difference_constraint","text":"difference_constraint(\n a,\n b,\n difference_bound\n) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the difference from a to b is within the difference_bound. For example, difference_constraint(-1, 1, 2) will always be valid. Any type of ConstraintTree.Bound can be supplied.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.equal_value_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.equal_value_constraint","text":"equal_value_constraint(a, b) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the values of a and b are the same.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.greater_or_equal_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.greater_or_equal_constraint","text":"greater_or_equal_constraint(\n a,\n b\n) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the value of a is greater than or equal to the the value of b.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.less_or_equal_constraint-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.less_or_equal_constraint","text":"less_or_equal_constraint(a, b) -> ConstraintTrees.Constraint\n\n\nA constraint that makes sure that the value of a is less than or equal to the the value of b.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Constraint-scaling","page":"Constraint system builders","title":"Constraint scaling","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/scale.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.scale_bounds-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.scale_bounds","text":"scale_bounds(\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n factor\n) -> Any\n\n\nLinearly scale all bounds in a constraint tree by the factor. This actually changes the model semantics, and may not work in surprising/improper ways with some constraint systems, esp. the MILP and QP ones.\n\nSee also scale_constraints.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.scale_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.scale_constraints","text":"scale_constraints(\n tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n factor\n) -> Any\n\n\nLinearly scale all constraints in a constraint tree by the factor.\n\nSee also scale_bounds.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Sign-splitting","page":"Constraint system builders","title":"Sign splitting","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/unsigned.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.positive_bound_contribution-Tuple{ConstraintTrees.EqualTo}","page":"Constraint system builders","title":"COBREXA.positive_bound_contribution","text":"positive_bound_contribution(\n b::ConstraintTrees.EqualTo\n) -> ConstraintTrees.EqualTo\n\n\nClamp all negative values in the bound to zero, leaving only the \"positive contribution\" to the overall value of the constraint. Used in unsigned_positive_contribution_variables and unsigned_negative_contribution_variables to allocate unidirectional variables.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sign_split_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.sign_split_constraints","text":"sign_split_constraints(; positive, negative, signed)\n\n\nA constraint tree that bound the values present in signed to be sums of pairs of positive and negative contributions to the individual values.\n\nKeys in the result are the same as the keys of signed constraints.\n\nTypically, this can be used to create \"unidirectional\" fluxes together with unsigned_negative_contribution_variables and unsigned_positive_contribution_variables.\n\nUse sign_split_variables to allocate the variables easily.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sign_split_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.sign_split_variables","text":"sign_split_variables(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint};\n positive,\n negative\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nShortcut for making a pair of named variable groups created by unsigned_positive_contribution_variables and unsigned_negative_contribution_variables, in subtrees named by positive and negative.\n\nUse sign_split_constraints to bind the new variables to existing values.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_negative_contribution_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_negative_contribution_constraints","text":"unsigned_negative_contribution_constraints(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n positive::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree that connects positive unsigned variable contributions to signed ones, while acting as negative contributions.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_negative_contribution_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_negative_contribution_variables","text":"unsigned_negative_contribution_variables(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree of variables with negative contributions to the values in cs.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_positive_contribution_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_positive_contribution_constraints","text":"unsigned_positive_contribution_constraints(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n negative::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree that connects negative unsigned variable contributions to signed ones, while acting as positive contributions.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.unsigned_positive_contribution_variables-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.unsigned_positive_contribution_variables","text":"unsigned_positive_contribution_variables(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nA constraint tree of variables with positive contributions to the values in cs.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Objectives","page":"Constraint system builders","title":"Objectives","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/objectives.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.squared_sum_error_value-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.squared_sum_error_value","text":"squared_sum_error_value(\n constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n target\n) -> Any\n\n\nConstruct a ConstraintTrees.Value out of squared error (in the RMSE-like squared-error sense) between the values in the constraint tree and the reference target.\n\ntarget is a function that takes a symbol (key) and returns either a Float64 reference value, or nothing if the error of given key should not be considered.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.squared_sum_value-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Constraint system builders","title":"COBREXA.squared_sum_value","text":"squared_sum_value(\n x::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nConstruct a ConstraintTrees.Value out of squared sum of all values directly present in a given constraint tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.sum_value-Tuple","page":"Constraint system builders","title":"COBREXA.sum_value","text":"sum_value(\n x...\n) -> Union{ConstraintTrees.LinearValue, ConstraintTrees.QuadraticValue}\n\n\nConstruct a ConstraintTrees.Value out of a sum of all values directly present in a given constraint tree.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Analysis-specific-constriants","page":"Constraint system builders","title":"Analysis-specific constriants","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/loopless.jl\", \"src/builders/knockout.jl\", \"src/builders/enzymes.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.loopless_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.loopless_constraints","text":"loopless_constraints(\n;\n fluxes,\n loopless_direction_indicators,\n loopless_driving_forces,\n internal_reactions,\n internal_nullspace,\n flux_infinity_bound,\n driving_force_nonzero_bound,\n driving_force_infinity_bound\n)\n\n\nConstruct the loopless constraint system that binds fluxes of all internal_reactions to direction of loopless_direction_indicators and connects them to loopless_driving_forces. The solution is bounded to lie in internal_nullspace (which is a sufficient algebraic condition for loop-less-ness).\n\nThe indicators must be discrete variables, valued 1 if the reaction flux goes forward, or 0 if the reaction flux is reversed.\n\nThe simplest (but by no means the fastest) way to obtain a good internal_nullspace is to use LinearAlgebra.nullspace with the internal reactions' stoichiometry matrix. Rows of internal_nullspace must correspond to internal_reactions.\n\nflux_infinity_bound is used as the maximal bound for fluxes (for constraints that connect them to indicator variables); it should optimally be greater than the maximum possible absolute value of any flux in the original model.\n\ndriving_force_nonzero_bound and driving_force_infinity_bound are similarly used to limit the individual reaction's driving forces.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.knockout_constraints-Union{Tuple{F}, Tuple{F, ConstraintTrees.Tree{ConstraintTrees.Constraint}}} where F<:Function","page":"Constraint system builders","title":"COBREXA.knockout_constraints","text":"knockout_constraints(\n knockout_test::Function,\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nMake a ConstraintTree that knocks out fluxes given by the predicate knockout_test. The predicate function is called with a single parameter (the key of the flux in tree fluxes) and must return a boolean. Returning true means that the corresponding flux (usually a reaction flux) will be knocked out.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.enzyme_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.enzyme_constraints","text":"enzyme_constraints(\n;\n fluxes_forward,\n fluxes_reverse,\n isozyme_forward_amounts,\n isozyme_reverse_amounts,\n kcat_forward,\n kcat_reverse,\n isozyme_gene_product_stoichiometry,\n gene_product_molar_mass,\n capacity_limits,\n isozyme_flux_forward_balance_name,\n isozyme_flux_reverse_balance_name,\n gene_product_amounts_name,\n gene_product_capacity_name\n)\n\n\nConnect variables returned by enzyme_variables to unidirectional fluxes. This is used to construct the contraint system for enzyme_constrained_flux_balance_constraints.\n\nParameters fluxes_forward, fluxes_reverse, isozyme_forward_amounts, isozyme_reverse_amounts and gene_product_amounts should correspond to parameters and results of enzyme_variables.\n\nFurther, parameter functions kcat_forward and kcat_reverse specify the turnover numbers for reaction and isozyme IDs given in parameters; isozyme_gene_product_stoichiometry specifies the composition of the reaction-isozyme IDs given in parameter by returning an interable mapping of gene product IDs to numbers (such as Dict{Symbol, Float64}), and gene_product_molar_mass specifies a numeric mass for a given gene product ID. All parameter functions may return nothing, at which point the given object is considered nonexistent and is omitted from constraints.\n\ncapacity_limits is an interable container of triples (limit_id, gene_product_ids, capacity_bound) which are converted to a constraint identified by the limit_id that limits the total mass of gene_product_ids (which is any iterable container) by capacity_bound.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.enzyme_variables-Tuple{}","page":"Constraint system builders","title":"COBREXA.enzyme_variables","text":"enzyme_variables(\n;\n fluxes_forward,\n fluxes_reverse,\n isozyme_ids,\n isozyme_forward_ids,\n isozyme_reverse_ids,\n isozyme_forward_amounts_name,\n isozyme_reverse_amounts_name\n)\n\n\nReturns a constraint tree with enzyme capacity constraints, added for reactions in fluxes_forward and fluxes_reverse. This is used to construct the constraint system in enzyme_constrained_flux_balance_constraints.\n\nParameter function isozyme_ids takes a reaction ID and returns nothing if the reaction does not have isozymes associated with it, or an iterable container of all the isozyme IDs for that reaction (as Symbols).\n\nParameters isozyme_forward_ids and isozyme_reverse_ids can be used to fine-tune the generated isozymes in either direction; both default to isozyme_ids.\n\nThe keys in the output constraint tree can be customized by setting isozyme_forward_amounts_name, isozyme_reverse_amounts_name and gene_product_amounts_name.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_amount_variables-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_amount_variables","text":"isozyme_amount_variables(\n fluxes,\n flux_isozymes\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nCreate a ConstraintTree with variables for isozyme contributions to reaction fluxes. The tree has 2 levels: the first contains all reaction flux IDs that have isozymes, the second contains the isozyme IDs for each reaction flux.\n\nfluxes should be anything that can be iterated to give reaction flux IDs.\n\nflux_isozymes is a function that, for a given reaction flux ID, returns anything iterable that contains the isozyme IDs for the given reaction flux. Returning an empty iterable prevents allocating the subtree for the given flux.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_flux_constraints-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}, ConstraintTrees.Tree{ConstraintTrees.Constraint}, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_flux_constraints","text":"isozyme_flux_constraints(\n isozyme_amounts::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},\n kcat\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nA constraint tree that sums up partial contributions of reaction isozymes to the fluxes of reactions.\n\nFor practical purposes, both fluxes and isozymes are here considered to be unidirectional, i.e., one would typically apply this twice to constraint both \"forward\" and \"reverse\" fluxes.\n\nFunction kcat should return the kcat value for a given reaction and isozyme (IDs of which respectively form the 2 parameters for each call).\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.isozyme_gene_product_amount_constraints-Tuple{Any, Any}","page":"Constraint system builders","title":"COBREXA.isozyme_gene_product_amount_constraints","text":"isozyme_gene_product_amount_constraints(\n isozyme_amounts,\n isozyme_stoichiometry\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nA constraint tree that computes the gene product amounts from given isozyme amounts their multiplicities (aka. stoichiometries, protein units, ...) given by isozyme_stoichiometry.\n\nValues in ConstraintTree gene_product_amounts should describe the gene product allocations. Allocation for the isozyme is ignored if the gene product is missing in gene_product_amounts.\n\nisozyme_amounts is an iterable that contains several ConstraintTrees that describe the allocated isozyme amounts (typically these would be created by isozyme_amount_variables. The multiple trees may describe several different kinds of isozyme use, e.g., you can use it to pass in both forward- and reverse-direction amounts at once. To only use a single tree, use an uni-tuple: isozyme_amounts = tuple(my_tree).\n\nParameter function isozyme_stoichiometry gets called with a reaction and isozyme IDs as given by the isozyme amount trees. It should return nothing in case there's no information – in such case, the isozyme is not going to be included in the calculation of gene product mass.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.simplified_enzyme_constraints-Tuple{}","page":"Constraint system builders","title":"COBREXA.simplified_enzyme_constraints","text":"simplified_enzyme_constraints(\n;\n fluxes_forward,\n fluxes_reverse,\n mass_cost_forward,\n mass_cost_reverse,\n capacity_limits\n)\n\n\nBuild a constraint system that bounds fluxes according to their enzyme mass requirements, with respect to per-reaction enzyme mass costs.\n\nParameter functions mass_cost_forward and mass_cost_reverse take a flux ID (corresponding to a flux in fluxes_forward and fluxes_reverse) and return the enzyme mass required to catalyze one \"unit\" of reaction in the forward or reverse direction, respectively. Returning nothing ignores the mass cost.\n\ncapacity_limits is an iterable container of triples (limit_id, flux_ids, bound), which creates the capacity bounds over groups of fluxes (in the same manner as for gene products in enzyme_constraints).\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.simplified_isozyme_gene_product_amount_constraints-Tuple","page":"Constraint system builders","title":"COBREXA.simplified_isozyme_gene_product_amount_constraints","text":"simplified_isozyme_gene_product_amount_constraints(\n x...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nLike isozyme_gene_product_amount_constraints, but works with the \"simplified\" view where each reaction has an uniquely determined catalytic isozyme, as with simplified_enzyme_constraints.\n\nAs the main difference, the arguments are tuples that contain first the constraint tree without the \"isozyme\" layer (i.e., fluxes), and second a function that returns the gene product stoichiometry and the turnover number (again in a tuple) for the given flux identifier.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#Interfacing-of-constraint-systems","page":"Constraint system builders","title":"Interfacing of constraint systems","text":"","category":"section"},{"location":"reference/builders/","page":"Constraint system builders","title":"Constraint system builders","text":"Modules = [COBREXA]\nPages = [\"src/builders/interface.jl\"]","category":"page"},{"location":"reference/builders/#COBREXA.interface_constraints-Tuple{Any}","page":"Constraint system builders","title":"COBREXA.interface_constraints","text":"interface_constraints(\n kv;\n kwargs...\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nOverload of interface_constraints for general key-value containers.\n\n\n\n\n\n","category":"method"},{"location":"reference/builders/#COBREXA.interface_constraints-Tuple{Vararg{Pair}}","page":"Constraint system builders","title":"COBREXA.interface_constraints","text":"interface_constraints(\n ps::Pair...;\n default_interface,\n out_interface,\n out_balance,\n ignore,\n bound\n) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}\n\n\nJoin multiple constraint tree modules with interfaces into a bigger module with an interface.\n\nModules are like usual constraint trees, but contain an explicitly declared interface part, marked properly in arguments using e.g. a tuple (the parameters should form a dictionary constructor that would generally look such as :module_name => (module, module.interface); the second tuple member may also be specified just by name as e.g. :interface, or omitted while relying on default_interface).\n\nInterface parts get merged and constrained to create a new interface; networks are intact with disjoint variable sets.\n\nCompatible modules with ready-made interfaces may be created e.g. by flux_balance_constraints.\n\nignore may be used to selectively ignore parts of interfaces given the \"module name\" identifier and constraint path in the interface (these form 2 parameters passed to ignore). Similarly, bound may be used to specify bounds for the new interface, if required.\n\n\n\n\n\n","category":"method"},{"location":"distributed/1_functions/#Parallel-processing-overview","page":"Parallel processing overview","title":"Parallel processing overview","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Distributed processing in Julia is represented mainly by the package Distributed.jl.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"COBREXA.jl is able to utilize this existing system to almost transparently run the large parallelizable analyses on multiple CPU cores and multiple computers connected through the network. Ultimately, the approach scales to thousands of computing nodes in large HPC facilities.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Users may run the analyses in parallel to gain speed-ups. The usual workflow in COBREXA.jl is quite straightforward:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Import the Distributed package and add worker processes, e.g. using addprocs.\nPick an analysis function that can be parallelized (such as screen or flux_variability_analysis) and prepare it to work on the data.\nPass the desired set of worker IDs to the function using workers= argument, in the simplest form using e.g. screen(..., workers=workers()).\nWorker communication will be managed automatically, and the results will be computed \"as usual\", just appropriately faster.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Specific documentation is available about running parallel analysis locally and running distributed analysis in HPC clusters.","category":"page"},{"location":"distributed/1_functions/#Functions-that-support-parallelization","page":"Parallel processing overview","title":"Functions that support parallelization","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"The functions that support parallel execution include:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"flux_variability_analysis (and the underlying constraints_variability)\nscreen and screen_optimization_model\ngene_knockouts\nflux_sample (and the underlying sample_constraints)\nobjective_production_envelope (and the underlying constraints_objective_envelope)","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Notably, the screening functions can be reused to run many other kinds of analyses which, in turn, inherit the parallelizability. This includes a wide range of use-cases that can thus be parallelized very easily:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"single and multiple gene deletions (and other genetic modifications)\nmultiple reaction knockouts\nenvelope-like production profiles (e.g., enzyme-constrained growth profiles)\ngrowth media explorations (such as explorations of metabolite depletion)","category":"page"},{"location":"distributed/1_functions/#Mitigating-parallel-inefficiencies","page":"Parallel processing overview","title":"Mitigating parallel inefficiencies","text":"","category":"section"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Ideally, the speedup gained by parallel processing should be proportional to the amount of hardware one add as the workers. To reach that, it is beneficial to be aware of factors that reduce the parallel efficiency, which can be summarized as follows:","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"Parallelization within single runs of the linear solver is typically not supported (and if it is, it may be inefficient for common problem sizes). Normally, we want to parallelize the analyzes that comprise multiple independent runs of the solvers.\nSome analysis function, such as flux_variability_analysis, have serial parts that can not be parallelized by default. Usually, pipelines may avoid the inefficiency by precomputing the serial analysis parts without involving the cluster of the workers.\nFrequent worker communication may vastly reduce the efficiency of parallel processing; typically this happens if the time required for individual analysis steps is smaller than the network round-trip-time to the worker processes. Do not use parallelization for very small tasks.\nTransferring large amounts of data among workers may hamper parallel efficiency too. Use a single loaded model data object and apply any required small modifications directly on the workers to avoid this kind of inefficiency.","category":"page"},{"location":"distributed/1_functions/","page":"Parallel processing overview","title":"Parallel processing overview","text":"note: Cost of the distribution and parallelization overhead\nBefore allocating extra resources into the distributed execution, always check that the tasks are properly parallelizable and sufficiently large to saturate the computation resources, so that the invested energy is not wasted. Amdahl's and Gustafson's laws give a better overview of the sources and consequences of the parallelization inefficiencies, and the costs of the resulting overhead.","category":"page"},{"location":"reference/misc/#Miscellaneous-functions","page":"Miscellaneous functions","title":"Miscellaneous functions","text":"","category":"section"},{"location":"reference/misc/","page":"Miscellaneous functions","title":"Miscellaneous functions","text":"Modules = [COBREXA]\nPages = [\"src/misc/bounds.jl\", \"src/misc/breaks.jl\", \"src/misc/maybe.jl\", \"src/misc/settings.jl\", \"src/misc/trees.jl\"]","category":"page"},{"location":"reference/misc/#COBREXA.absolute_tolerance_bound-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.absolute_tolerance_bound","text":"absolute_tolerance_bound(tolerance) -> COBREXA.var\"#404#405\"\n\n\nMake a function that returns absolute tolerance bounds, i.e. value - tolerance and value + tolerance in a tuple, in the increasing order.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.relative_tolerance_bound-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.relative_tolerance_bound","text":"relative_tolerance_bound(tolerance) -> COBREXA.var\"#406#407\"\n\n\nMake a function that returns relative tolerance bounds, i.e. value / tolerance and value * tolerance in a tuple, in the increasing order.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.remove_bounds-Tuple{ConstraintTrees.Tree{ConstraintTrees.Constraint}}","page":"Miscellaneous functions","title":"COBREXA.remove_bounds","text":"remove_bounds(\n cs::ConstraintTrees.Tree{ConstraintTrees.Constraint}\n) -> Any\n\n\nMake a copy of a constraint tree with all bounds removed. This is helpful when creating large trees only for for value representation purposes, which should not directly constraint anything (and thus should not put additional stress on the constraint solver).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.break_interval-Tuple{Any, Any, Int64}","page":"Miscellaneous functions","title":"COBREXA.break_interval","text":"break_interval(lower, upper, breaks::Int64) -> Any\n\n\nBreak an interval into breaks (count) breaks.\n\nUsed for computing breaks in objective_production_envelope.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.maybemap","page":"Miscellaneous functions","title":"COBREXA.maybemap","text":"maybemap(f, ::Nothing)\nmaybemap(f, ::Nothing, def) -> Any\n\n\nHelper for applying functions to stuff that might be nothing.\n\n\n\n\n\n","category":"function"},{"location":"reference/misc/#COBREXA.set_objective_sense-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.set_objective_sense","text":"set_objective_sense(\n objective_sense\n) -> COBREXA.var\"#410#411\"\n\n\nChange the objective sense of optimization. Accepted arguments include Minimal, Maximal, and Feasible.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_optimizer-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.set_optimizer","text":"set_optimizer(optimizer) -> COBREXA.var\"#412#413\"\n\n\nChange the JuMP optimizer used to run the optimization.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_optimizer_attribute-Tuple{Any, Any}","page":"Miscellaneous functions","title":"COBREXA.set_optimizer_attribute","text":"set_optimizer_attribute(\n attribute_key,\n value\n) -> COBREXA.var\"#414#415\"\n\n\nChange a named JuMP optimizer attribute. The attribute names are optimizer-specific, refer to the JuMP documentation and the documentation of the specific optimizer for usable keys and values.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.set_time_limit-Tuple{Real}","page":"Miscellaneous functions","title":"COBREXA.set_time_limit","text":"set_time_limit(limit::Real) -> COBREXA.var\"#416#417\"\n\n\nSet a time limit in seconds for the optimizer computation (shortcut for set_time_limit_sec from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.silence-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.silence","text":"silence\n\nDisable all output from the JuMP optimizer (shortcut for set_silent from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.unsilence-Tuple{Any}","page":"Miscellaneous functions","title":"COBREXA.unsilence","text":"unsilence\n\nEnable output from the JuMP optimizer (shortcut for unset_silent from JuMP).\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.tree_deflate-Union{Tuple{U}, Tuple{T}, Tuple{Any, ConstraintTrees.Tree{T}}, Tuple{Any, ConstraintTrees.Tree{T}, Type{U}}} where {T, U}","page":"Miscellaneous functions","title":"COBREXA.tree_deflate","text":"tree_deflate(f, x::ConstraintTrees.Tree{T}) -> Vector\ntree_deflate(\n f,\n x::ConstraintTrees.Tree{T},\n ::Type{U}\n) -> Vector\n\n\nExtract all elements of a ConstraintTrees.Tree in order and return them in a Vector transformed by f. If the order is not modified, one can re-insert a vector of modified elements into the same-shaped tree using tree_reinflate.\n\n\n\n\n\n","category":"method"},{"location":"reference/misc/#COBREXA.tree_reinflate-Union{Tuple{T}, Tuple{ConstraintTrees.Tree, Vector{T}}} where T","page":"Miscellaneous functions","title":"COBREXA.tree_reinflate","text":"tree_reinflate(\n x::ConstraintTrees.Tree,\n elems::Array{T, 1}\n) -> ConstraintTrees.Tree\n\n\nInsert a Vector of elements into the \"values\" of a ConstraintTrees.Tree. The order of elements is given by tree_deflate.\n\n\n\n\n\n","category":"method"},{"location":"examples/#Examples","page":"Contents","title":"Examples","text":"","category":"section"},{"location":"examples/","page":"Contents","title":"Contents","text":"Pages = filter(x -> endswith(x, \".md\"), readdir(\"examples\", join=true))\nDepth = 2","category":"page"},{"location":"structure/#Logical-structure-of-COBREXA","page":"Core concepts and structure","title":"Logical structure of COBREXA","text":"","category":"section"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"COBREXA uses ConstraintTrees.jl for internal representation of all metabolic modeling problems. In short, constraint trees are \"tidy\" representations of the constraint-based modeling problems, which store information about the variables' participation in named constraints. They provide several main benefits:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"User is freed from having to allocate variables – all variables are present only implicitly, are described by their \"semantics\" by participation in constraints, and are allocated automatically whenever the user connects the constraint trees.\nThere is no need for complicated index manipulation (as with linear-algebraic \"matrixy\" model representations) nor for various identifier mangling schemes – constraint trees provide named interface for everything, and identifiers can be organized into directories to prevent name clashes in various multi-compartment and community models.\nContrary to the fixed model representations (such as SBML or JSON models), ConstraintTrees do not possess a semantic of a \"single flux-based model\" and are thus infinitely extensible, allowing easy creation, manipulation and storage of even very complicated constraint systems.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"With ConstraintTrees, the typical workflow in COBREXA is as follows:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"\"Raw\" data and base model data are loaded from semantically organized models (such as SBML, or lab measurements in CSV or other tabular format)\nCOBREXA functions are used to convert these to a constraint tree that properly describes the problem at hand\npossibly, multiple types and groups of raw data can be soaked into the constraint tree\nAnalysis functionality of COBREXA is used to solve the system described by the constraint tree, and extract useful information from the solutions.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"COBREXA mainly provides functionality to make this workflow easy to use for many various purposes:","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"Front-end functions help to run the 3 above steps easily without any intermediate steps. These include:\ncommunity_flux_balance_analysis\nenzyme_constrained_flux_balance_analysis\nflux_balance_analysis\nflux_sample\ngene_knockouts\nlinear_metabolic_adjustment_minimization_analysis\nloopless_flux_balance_analysis\nmax_min_driving_force_analysis\nmetabolic_adjustment_minimization_analysis\nobjective_production_envelope\nsimplified_enzyme_constrained_flux_balance_analysis\nFront-end functions call various Front-end constraint tree builders which translate various kinds of raw data to the constraint trees, such as:\ncommunity_flux_balance_constraints\nenzyme_constrained_flux_balance_constraints\nflux_balance_constraints\nflux_variability_analysis\ngene_knockout_constraints\nlinear_metabolic_adjustment_minimization_constraints\nlog_concentration_constraints\nloopless_flux_balance_constraints\nmax_min_driving_force_constraints\nmetabolic_adjustment_minimization_constraints\nsimplified_enzyme_constrained_flux_balance_constraints\nAdditional constraint builders are provided to decorate the \"raw\" model representations with various additional semantics and limits:\nall_equal_constraints, greater_or_equal_constraint and similar ones\nknockout_constraints\nloopless_constraints\nscale_bounds\nscale_constraints\nsign_split_variables and sign_split_constraints squared_sum_error_value\nsum_value, squared_sum_value and\nSome functions are provided to join the constraint trees via interfaces, simplifying e.g. the creation of community or multi-organ models,\nflux_balance_constraints can automatically generate interfaces suitable for community-style and multi-compartment-style metabolic modeling from the annotations in the FBC models\ninterface_constraints joins the \"modules\" with prepared interfaces together\nFinally, the analysis functions simulate the model in the constraint tree mechanistically and extract analysis results:\nconstraints_objective_envelope\nparsimonious_optimized_values\nsample_constraints\nsample_constraint_variables\nscreen_optimization_model\nscreen\noptimized_values\nconstraints_variability","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"tip: Exploring and customizing the front-end analysis functions\nTo know which builder function is used to create or modify some kind of constraint tree in COBREXA, use the \"link to source code\" feature in the front-end function's individual documentation. The source code of front-end functions is written to be as easily re-usable as possible – one can simply copy-paste it into the program, and immediately start building specialized and customized front-end functions.","category":"page"},{"location":"structure/","page":"Core concepts and structure","title":"Core concepts and structure","text":"Technical description of the constraint tree functionality, together with examples of basic functionality and many useful utility functions is available in dedicated documentation of ConstraintTrees.jl.","category":"page"},{"location":"#COBREXA.jl","page":"Home","title":"COBREXA.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Modules = [COBREXA]\nPages = [\"src/COBREXA.jl\"]","category":"page"},{"location":"#COBREXA.COBREXA","page":"Home","title":"COBREXA.COBREXA","text":"module COBREXA\n\nCOnstraint Based Reconstruction and EXascale Analysis. COBREXA provides functions for construction, modification, simulation and analysis of constraint-based metabolic models that follows the COBRA methodology.\n\nCOBREXA is built as a front-end for the combination of AbstractFBCModels.jl (provides the model I/O), ConstraintTrees.jl (provides the constraint system organization), Distributed.jl (provides HPC execution capability), and JuMP.jl (provides the solvers).\n\nSee the online documentation for a complete description of functionality aided by copy-pastable examples.\n\nTo start quickly, load your favorite JuMP-compatible solver, use load_model to read a metabolic model from the disk, and solve it with flux_balance_analysis.\n\n\n\n\n\n","category":"module"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"EditURL = \"04-community-models.jl\"","category":"page"},{"location":"examples/04-community-models/#Community-FBA-models","page":"Community FBA models","title":"Community FBA models","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"using COBREXA","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Here we construct a community FBA model of two E. coli \"core\" models that can interact by exchanging selected metabolites. To do this, we will need the model, which we can download if it is not already present.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"download_model(\n \"http://bigg.ucsd.edu/static/models/e_coli_core.json\",\n \"e_coli_core.json\",\n \"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8\",\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Additionally to COBREXA and the model format package, we will need a solver and a few supporting packages.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"import JSONFBCModels\nimport HiGHS\nimport AbstractFBCModels.CanonicalModel as CM\nimport ConstraintTrees as C","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The core model has an artificial bound on input glucose; here we unblock that one, and we are going to add a community-global glucose intake bound later.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"ecoli = load_model(\"e_coli_core.json\", CM.Model)\necoli.reactions[\"EX_glc__D_e\"].lower_bound = -1000.0\necoli.reactions[\"EX_glc__D_e\"].upper_bound = 1000.0","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To create a community that is actually interesting, we need some diversity. Here we simply block a different reaction in each of the community members:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"ecoli1 = deepcopy(ecoli)\necoli1.reactions[\"CYTBD\"].lower_bound = ecoli1.reactions[\"CYTBD\"].upper_bound = 0.0\necoli2 = deepcopy(ecoli)\necoli2.reactions[\"FBA\"].lower_bound = ecoli2.reactions[\"FBA\"].upper_bound = 0.0","category":"page"},{"location":"examples/04-community-models/#Analysing-the-community","page":"Community FBA models","title":"Analysing the community","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To construct the community, we have to provide identifiers for the models (these will be used in the constraint tree), and corresponding models with the abundances.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"my_community = Dict(\"bug1\" => (ecoli1, 0.2), \"bug2\" => (ecoli2, 0.8))","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The community is constructed and analysed using community_flux_balance_analysis:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"solution = community_flux_balance_analysis(\n my_community,\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/04-community-models/#Investigating-the-solution","page":"Community FBA models","title":"Investigating the solution","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"We can now e.g. observe the differences in individual pairs of exchanges:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"C.zip(\n tuple,\n solution.bug1.interface.exchanges,\n solution.bug2.interface.exchanges,\n Tuple{Float64,Float64},\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"...or use screen to efficiently find out which composition is best:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"screen(0.0:0.1:1.0) do ratio2\n ratio1 = 1 - ratio2\n res = community_flux_balance_analysis(\n [(\"bug1\" => (ecoli1, ratio1)), (\"bug2\" => (ecoli2, ratio2))],\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n interface = :sbo, # usually more reproducible\n optimizer = HiGHS.Optimizer,\n )\n (ratio1, ratio2) => (isnothing(res) ? nothing : res.community_biomass)\nend","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"(The result seem like the bug1 is eventually going to be completely out-grown by the other one.)","category":"page"},{"location":"examples/04-community-models/#Note:-interfaces-of-constraint-systems","page":"Community FBA models","title":"Note: interfaces of constraint systems","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Internally, the community is connected via interfaces, which are small constraint trees (typically with no bounds attached) that describe parts of the constraint system that can be easily attached to other parts.","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The best kind of interface to choose generally differs from model to model. COBREXA gives a few \"default\" choices that cover a good part of sensible metabolic modeling. For example, if the model contains SBO annotations, we can ask for the interface created using the annotated reactions:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"flux_balance_constraints(ecoli, interface = :sbo).interface","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"If there are no annotations, we can still at least detect the boundary reactions and make an interface out of them:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"flux_balance_constraints(ecoli, interface = :boundary).interface","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"The default kind of interface in community_flux_balance_analysis is :identifier_prefixes, which relies on usual prefixes of reaction names (such as EX_ for exchanges).","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"Even if all of these methods fail, a suitable interface yourself can be produced manually. (Additionally, we can do useful stuff, such as removing the unnecessary bounds from the exchange descriptions.)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_model = flux_balance_constraints(ecoli)\ncustom_model *= remove_bounds(\n :interface^C.ConstraintTree(\n :biomass => custom_model.fluxes.BIOMASS_Ecoli_core_w_GAM,\n :exchanges => C.ConstraintTree(\n k => v for (k, v) in custom_model.fluxes if startswith(string(k), \"EX_\")\n ),\n ),\n)\ncustom_model.interface.exchanges","category":"page"},{"location":"examples/04-community-models/#Connecting-the-community-constraints-manually","page":"Community FBA models","title":"Connecting the community constraints manually","text":"","category":"section"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"To connect such interfaces into a community model, simply use function interface_constraints (which is how community_flux_balance_analysis constructs the community model internally via community_flux_balance_constraints). The assembly might look roughly as follows:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_community = interface_constraints(\n \"bug1\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.CYTBD.value, 0),\n 0.2,\n ),\n \"bug2\" =>\n (custom_model * :handicap^C.Constraint(custom_model.fluxes.FBA.value, 0), 0.8),\n bound = r -> r == (:exchanges, :EX_glc__D_e) ? C.Between(-10, 0) : nothing,\n)\n\ncustom_community.interface.exchanges","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"For the model to work properly, we would need to add several other things, mainly the equal growth constraints (possibly via all_equal_constraints). community_flux_balance_constraints add these automatically, so we can equivalently just supply the constraint trees, and re-use the rest of the implementation:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_community = community_flux_balance_constraints(\n [\n \"bug1\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.CYTBD.value, 0),\n 0.2,\n ),\n \"bug2\" => (\n custom_model * :handicap^C.Constraint(custom_model.fluxes.FBA.value, 0),\n 0.8,\n ),\n ],\n [\"EX_glc__D_e\" => (-10.0, 0.0)],\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"This can be solved with the usual means, reaching the same result as above:","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"custom_solution = optimized_values(\n custom_community,\n objective = custom_community.community_biomass.value,\n output = custom_community.community_biomass,\n optimizer = HiGHS.Optimizer,\n)","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"","category":"page"},{"location":"examples/04-community-models/","page":"Community FBA models","title":"Community FBA models","text":"This page was generated using Literate.jl.","category":"page"}] } diff --git a/dev/structure/index.html b/dev/structure/index.html index 97bc9748..d869ea00 100644 --- a/dev/structure/index.html +++ b/dev/structure/index.html @@ -1,2 +1,2 @@ -Core concepts and structure · COBREXA.jl

Logical structure of COBREXA

COBREXA uses ConstraintTrees.jl for internal representation of all metabolic modeling problems. In short, constraint trees are "tidy" representations of the constraint-based modeling problems, which store information about the variables' participation in named constraints. They provide several main benefits:

  • User is freed from having to allocate variables – all variables are present only implicitly, are described by their "semantics" by participation in constraints, and are allocated automatically whenever the user connects the constraint trees.
  • There is no need for complicated index manipulation (as with linear-algebraic "matrixy" model representations) nor for various identifier mangling schemes – constraint trees provide named interface for everything, and identifiers can be organized into directories to prevent name clashes in various multi-compartment and community models.
  • Contrary to the fixed model representations (such as SBML or JSON models), ConstraintTrees do not possess a semantic of a "single flux-based model" and are thus infinitely extensible, allowing easy creation, manipulation and storage of even very complicated constraint systems.

With ConstraintTrees, the typical workflow in COBREXA is as follows:

  1. "Raw" data and base model data are loaded from semantically organized models (such as SBML, or lab measurements in CSV or other tabular format)
  2. COBREXA functions are used to convert these to a constraint tree that properly describes the problem at hand
    • possibly, multiple types and groups of raw data can be soaked into the constraint tree
  3. Analysis functionality of COBREXA is used to solve the system described by the constraint tree, and extract useful information from the solutions.

COBREXA mainly provides functionality to make this workflow easy to use for many various purposes:

Exploring and customizing the front-end analysis functions

To know which builder function is used to create or modify some kind of constraint tree in COBREXA, use the "link to source code" feature in the front-end function's individual documentation. The source code of front-end functions is written to be as easily re-usable as possible – one can simply copy-paste it into the program, and immediately start building specialized and customized front-end functions.

Technical description of the constraint tree functionality, together with examples of basic functionality and many useful utility functions is available in dedicated documentation of ConstraintTrees.jl.

+Core concepts and structure · COBREXA.jl

Logical structure of COBREXA

COBREXA uses ConstraintTrees.jl for internal representation of all metabolic modeling problems. In short, constraint trees are "tidy" representations of the constraint-based modeling problems, which store information about the variables' participation in named constraints. They provide several main benefits:

  • User is freed from having to allocate variables – all variables are present only implicitly, are described by their "semantics" by participation in constraints, and are allocated automatically whenever the user connects the constraint trees.
  • There is no need for complicated index manipulation (as with linear-algebraic "matrixy" model representations) nor for various identifier mangling schemes – constraint trees provide named interface for everything, and identifiers can be organized into directories to prevent name clashes in various multi-compartment and community models.
  • Contrary to the fixed model representations (such as SBML or JSON models), ConstraintTrees do not possess a semantic of a "single flux-based model" and are thus infinitely extensible, allowing easy creation, manipulation and storage of even very complicated constraint systems.

With ConstraintTrees, the typical workflow in COBREXA is as follows:

  1. "Raw" data and base model data are loaded from semantically organized models (such as SBML, or lab measurements in CSV or other tabular format)
  2. COBREXA functions are used to convert these to a constraint tree that properly describes the problem at hand
    • possibly, multiple types and groups of raw data can be soaked into the constraint tree
  3. Analysis functionality of COBREXA is used to solve the system described by the constraint tree, and extract useful information from the solutions.

COBREXA mainly provides functionality to make this workflow easy to use for many various purposes:

Exploring and customizing the front-end analysis functions

To know which builder function is used to create or modify some kind of constraint tree in COBREXA, use the "link to source code" feature in the front-end function's individual documentation. The source code of front-end functions is written to be as easily re-usable as possible – one can simply copy-paste it into the program, and immediately start building specialized and customized front-end functions.

Technical description of the constraint tree functionality, together with examples of basic functionality and many useful utility functions is available in dedicated documentation of ConstraintTrees.jl.