1) Ebrahim, A., Lerman, J.A., Palsson, B.O. & Hyduke, D. R. (2013). COBRApy: COnstraints-Based Reconstruction and Analysis for Python. BMC Systems Biology, 7(74). https://doi.org/10.1186/1752-0509-7-74
Parsimonious FBA (pFBA) solves a two stage optimization problem. First, a classic FBA problem is solved to identify the unique maximum of the objective.
However, it should be noted that the fluxes from FBA are not unique (i.e. many fluxes may yield the objective optimum).
...
...
@@ -47,15 +61,15 @@ To yield a unique set of fluxes, and remove internal futile cycles, a secondary
Suppose that FBA has found the optimum of ``v_\mu = \mu``, pFBA then solves,
```math
\begin{aligned}
& \underset{v}{\text{max}}
& \underset{v}{\text{min}}
& \sum_{i} {v_i^2} \\
& \text{s. t.}
& Sv = 0 \\
& & v_{\text{LB}} \leq v \leq v_{\text{UB}} \\
& v_\mu = \mu
& & v_\mu = \mu
\end{aligned}
```
again using any JuMP compatible solver(s). If multiple solvers are given, the first solver is used to solve the LP, and the second solver the QP, otherwise the same solver is used to solve both problems.
again using any JuMP compatible solver(s). In the `CobraTools.jl` implementation of pFBA, both the FBA and QP problem are solved internally in `pfba`, using similar input arguments as in `fba`. If multiple solvers are given, the first solver is used to solve the LP, and the second solver the QP, otherwise the same solver is used to solve both problems.
This is useful if the QP solver does not handle the LP problem well, as with OSQP.
An alternative, related formulation of this idea exists, called "CycleFreeFlux".
...
...
@@ -64,7 +78,7 @@ really have much benefit beyond only solving two linear programs. See [Building
```@docs
pfba
```
Here, we use `Tulip.jl` followed by `OSQP.jl`, with the `pfba` function from `CobraTools.jl`. Note that `OSQP.jl` has iffy performance, and is only included here because it is open source. We strongly recommend that a commercial solver, e.g. `Gubobi.jl` be used to simplify your user experience.
Here, we use `Tulip.jl` followed by `OSQP.jl`, with the `pfba` function from `CobraTools.jl`. Note that `OSQP.jl` has iffy performance, and is only included here because it is open source. We recommend that a commercial solver, e.g. `Gubobi.jl`, be used to simplify your user experience.
Flux variability analysis can also be used to investigate the degeneracy associated with flux balance analysis derived solutions (see also [Sampling Tools](@ref)).
`CobraTools.jl` exposes `fva` that sequentially maximizes and minimizes each reaction in a model subject to the constraint that each optimization problem also satisfies an initial FBA type objective optimum, below denoted by ``v_{\mu}=\mu``,
```math
\begin{aligned}
& \underset{v}{\text{max or min}}
& v_i \\
& \text{s. t.}
& Sv = 0 \\
& & v_{\text{LB}} \leq v \leq v_{\text{UB}} \\
& & v_{\mu} = \mu \\
\end{aligned}
```
```@docs
fva
```
## Building your own optimization analysis script
CobraTools.jl makes it simple to access the
`CobraTools.jl` also makes it simple to construct customized optimization problems by making judicious use of [JuMP](https://jump.dev/).
Convenience functions make optimization problem construction, modification and data extraction from JuMP result objects easy.
Numerous external databases exist that can add functionality to constraint based models.
Currently, `CobraTools.jl` tries to make it easier to incorporate two such databases in analyses.
The first is Brenda, a database that maps enzymes to kinetic data.
The second is Equilibrator, a database that allows one to calculate thermodynamic information, e.g. ``\Delta G``, from reactions.
`CobraTools.jl` includes lightweight interfaces to these sources.
## Brenda Interface
To use the Brenda interface functions, you will need to download the database as a txt file [available here](https://www.brenda-enzymes.org/download_brenda_without_registration.php)(~250 MB).
Once the database has been downloaded, it can be parsed by `parse_brenda`.
```@docs
parse_brenda
```
This function returns an array of `BrendaEntry` structs, which are composed of `EnzymeParams` for each field extracted from the Brenda database.
Currently, only the ID (=EC number), TN (=turn over number), KM (=Michaelis-Menten constant, ``K_M``), KI (=Inhibition term for Michaelis-Menten kintics), and KMM (=ratio of TN/KM) numbers for each enzyme class (ID, or EC number) are extracted. All the structs have pretty printing enabled.
The Equilibrator interface requires that the Equilibrator-API has been installed and can be accessed through Julia's PyCall package. Refer to the [Equilibrator-API website](https://gitlab.com/equilibrator/equilibrator-api) for installation instructions. Within Julia, if you can call `pyimport("equilibrator_api")` successfully, then you will be able to use the functions exposed here. To actually use the functions insert `using PyCall` in your main level script (before or after `using CobraTools`).
It is well known that the FBA does not yield a unique solution, i.e. many flux distributions are capable of satisfying the system constraints as well as optimizing the imposed objective function.
Let the feasible space be defined by ``\mathcal{P} = \left\{ v : Sv = 0 \cap v_{\text{min}} \leq v \leq v_{\text{max}} \right\}``.
Sampling methods have been developed to uniformly sample from this feasible solution space.
`CobraTools.jl` implements both `hit_and_run` and `achr` to sample from ``\mathcal{P}``.
The standard (temperature 25 °C, pressue 1 bar, concentration 1M) Gibbs energies of biochemical reactions at various pH levels (ionic strength = 0.1M) mapped to the KEGG database are made available from [Equilibrator](http://equilibrator.weizmann.ac.il/download).
Return a dict of rxn.id => ΔG of the specified dgtype.
Takes as inputs an array of reactions, `rxns`, and optional keyword arguments `dgtype`, which specifies which type of ΔG calculation should be returned.
Valid options for `dgtype` are "phys" and "prime" (anything else is "zero").
Ionic strength can be set through `ionic_str` which takes a string input, e.g. "150mM".
Only BIGG and KEGG metabolite identifiers are supported, i.e. the reaction needs to have a KEGG or BIGG `id` listed in the annotation field in the reaction struct.
By default KEGG annotations are used to build the reaction strings that are fed to Equilibrator. Note that the first metabolite `id` is used.
"""
function map_gibbs_rxns(rxns::Array{Reaction,1};dgtype="zero",ph=7.0,ionic_str="100 mM",usekegg=true)
ifusekegg
...
...
@@ -115,33 +120,4 @@ function map_gibbs_internal(fluxres::Dict{String, Float64}, gibbs, biomassid="BI
end
end
returntotal_ΔG,missing_flux/(missing_flux+found_flux)# units J/gDW/h
Run flux balance analysis (FBA) on the `model` with `objective_rxn(s)` and optionally specifying their `weights` (empty `weights` mean equal weighting per reaction).
Optionally also specify any additional flux constraints with `constraints`, a dictionary mapping reaction `id`s to tuples of (ub, lb) flux constraints.
Note, the `optimizer` must be set to perform the analysis, any JuMP solver will work.
The `solver_attributes` can also be specified in the form of a dictionary where each (key, value) pair will be passed to `set_optimizer_attribute(cbmodel, key, value)`.
This function builds the optimization problem from the model, and hence uses the constraints implied by the model object.
sol = fba(model, biomass, optimizer; solver_attributes=atts)
"""
function fba(model::CobraTools.Model,objective_rxns::Union{Reaction,Array{Reaction,1}},optimizer;weights=Float64[],solver_attributes=Dict{Any,Any}())
cbm,_,_,_,_=build_cbm(model)# get the base constraint based model
function fba(model::CobraTools.Model,objective_rxns::Union{Reaction,Array{Reaction,1}},optimizer;weights=Float64[],solver_attributes=Dict{Any,Any}(),constraints=Dict{String,Tuple{Float64,Float64}}())
cbm,_,_,ubcons,lbcons=build_cbm(model)# get the base constraint based model
set_optimizer(cbm,optimizer)# choose optimizer
if!isempty(solver_attributes)# set other attributes
Run parsimonious flux balance analysis (pFBA) on the `model` with `objective_rxn(s)` and optionally specifying their `weights` (empty `weights` mean equal weighting per reaction) for the initial FBA problem.
Note, the `optimizer` must be set to perform the analysis, any JuMP solver will work.
Optionally also specify any additional flux constraints with `constraints`, a dictionary mapping reaction `id`s to tuples of (ub, lb) flux constraints.
When `optimizer` is an array of optimizers, e.g. `[opt1, opt2]`, then `opt1` is used to solve the FBA problem, and `opt2` is used to solve the QP problem.
This strategy is useful when the QP solver is not good at solving the LP problem.
The `solver_attributes` can also be specified in the form of a dictionary where each (key, value) pair will be passed to `set_optimizer_attribute(cbmodel, k, v)`.
sol = pfba(model, biomass, optimizer; solver_attributes=atts)
"""
function pfba(model::CobraTools.Model,objective_rxns::Union{Reaction,Array{Reaction,1}},optimizer;weights=Float64[],solver_attributes=Dict{Any,Any}())
function pfba(model::CobraTools.Model,objective_rxns::Union{Reaction,Array{Reaction,1}},optimizer;weights=Float64[],solver_attributes=Dict{Any,Any}(),constraints=Dict{String,Tuple{Float64,Float64}}())
Run flux variability analysis (FVA) on the `model` with `objective_rxn(s)` and optionally specifying their `weights` (empty `weights` mean equal weighting per reaction).
It runs fba on the model once to determine the optimum of the objective.
Optionally also specify any additional flux constraints with `constraints`, a dictionary mapping reaction `id`s to tuples of (ub, lb) flux constraints.
The model is then constrained to produce objective flux bounded by `optimum_bound` from below (set to slightly less than 1.0 for stability) and each flux in the model sequentially minimized and maximized.
Note, the `optimizer` must be set to perform the analysis, any JuMP solver will work.
The `solver_attributes` can also be specified in the form of a dictionary where each (key, value) pair will be passed to `set_optimizer_attribute(cbmodel, key, value)`.
This function builds the optimization problem from the model, and hence uses the constraints implied by the model object.
Returns two dictionaries (fva_max and fva_min) that each reaction `id`s to dictionaries of the resultant flux distributions (if solved successfully) when that `id` is optimized.
function fva(model::CobraTools.Model,objective_rxns::Union{Reaction,Array{Reaction,1}},optimizer;optimum_bound=0.9999,weights=Float64[],solver_attributes=Dict{Any,Any}(),constraints=Dict{String,Tuple{Float64,Float64}}())
cbm,_,_,ubcons,lbcons=build_cbm(model)# get the base constraint based model
set_optimizer(cbm,optimizer)# choose optimizer
if!isempty(solver_attributes)# set other attributes