1818$(TYPEDSIGNATURES)
1919
2020Perform a max-min driving force analysis using `optimizer` on the `model` with
21- supplied ΔG⁰s in `reaction_standard_gibbs_free_energies`, as defined by Noor, et
22- al., "Pathway thermodynamics highlights kinetic obstacles in central
23- metabolism.", PLoS computational biology, 2014.
24-
25- Optionally, `reference_flux` can be used to set the directions of each reaction
26- in `model` (all reactions are assumed to proceed forward by default). The
27- supplied `reference_flux` should be free of internal cycles i.e.
28- thermodynamically consistent. This optional input is important if a reaction in
29- `model` normally runs in reverse (negative flux). Note, only the signs are
30- extracted from this input, so be careful with floating point precision near 0.
31-
32- The max-min driving force algorithm returns the Gibbs free energy of the
33- reactions, the concentrations of metabolites and the actual maximum minimum
34- driving force. The optimization problem solved is:
35- ```
36- max min -ΔᵣG
37- s.t. ΔᵣG = ΔrG⁰ + R T S' ln(C)
38- ΔᵣG ≤ 0
39- ln(Cₗ) ≤ ln(C) ≤ ln(Cᵤ)
40- ```
41- where `ΔrG` are the Gibbs energies dissipated by the reactions, R is the gas
42- constant, T is the temperature, S is the stoichiometry of the model, and C is
43- the vector of metabolite concentrations (and their respective lower and upper
44- bounds).
45-
46- In case no feasible solution exists, `nothing` is returned.
47-
48- Reactions specified in `ignore_reaction_ids` are internally ignored when
49- calculating the max-min driving force. Importantly, this should include water
50- and proton importers.
51-
52- Since biochemical thermodynamics are assumed, the `proton_metabolites` and `water_metabolites`
53- need to be specified so that they can be ignored in the calculations.
54- Effectively this assumes an aqueous environment at constant pH is used.
55-
56- `constant_concentrations` is used to fix the concentrations of certain
57- metabolites (such as CO₂) by passing a dictionary mapping metabolite id to its
58- constant value. `concentration_ratios` is used to specify additional constraints
59- on metabolite pair concentrations (typically, this is done with various
60- cofactors, such as the ATP/ADP ratio. For example, you can fix the concentration
61- of ATP to be always 5× higher than of ADP by specifying `Dict("atp_ratio" =>
62- ("atp_c","adp_c", 5.0))` if these metabolites are called `atp_c` and `adp_c` in
63- the model. `concentration_lb` and `concentration_ub` set the `Cₗ` and `Cᵤ` in
64- the optimization problems (these are overwritten by `constant_concentrations` if
65- supplied).
66-
67- `T` and `R` can be specified in the corresponding units; defaults are K and
68- kJ/K/mol. The unit of metabolite concentrations is typically molar, and the ΔG⁰s
69- have units of kJ/mol. Other units can be used, as long as they are consistent.
70- As usual, optimizer settings can be changed with `settings`.
21+ supplied reaction standard Gibbs energies in `reaction_standard_gibbs_free_energies`.
22+
23+ The method was described by by: Noor, et al., "Pathway thermodynamics highlights
24+ kinetic obstacles in central metabolism.", PLoS computational biology, 2014.
25+
26+ `reference_flux` sets the directions of each reaction in `model`. The scale of
27+ the values is not important, only the direction is examined (w.r.t.
28+ `reference_flux_atol` tolerance). Ideally, the supplied `reference_flux` should
29+ be completely free of internal cycles, which enables the thermodynamic
30+ consistency. To get the cycle-free flux, you can use
31+ [`loopless_flux_balance_analysis`](@ref) (computationally complex but gives
32+ very good fluxes), [`parsimonious_flux_balance_analysis`](@ref) or
33+ [`linear_parsimonious_flux_balance_analysis`](@ref) (computationally simplest
34+ but the consistency is not guaranteed).
35+
36+ Internally, [`fbc_log_concentration_constraints`](@ref) is used to lay out the
37+ base structure of the problem.
38+
39+ Following arguments are set optionally:
40+ - `water_metabolites`, `proton_metabolites` and `ignored_metabolites` allow to
41+ completely ignore constraints on a part of the metabolite set, which is
42+ explicitly recommended especially for water and protons (since the analyses
43+ generally assume aqueous environment of constant pH)
44+ - `constant_concentrations` can be used to fix the concentrations of the
45+ metabolites
46+ - `concentration_lower_bound` and `concentration_upper_bound` set the default
47+ concentration bounds for all other metabolites
48+ - `concentration ratios` is a dictionary that assigns a tuple of
49+ metabolite-metabolite-concentration ratio constraint names; e.g. ATP/ADP
50+ ratio can be fixed to five-times-more-ATP by setting `concentration_ratios =
51+ Dict("adenosin_ratio" => ("atp", "adp", 5.0))`
52+ - `T` and `R` default to the usual required thermodynamic constraints in the
53+ usual units (K and kJ/K/mol, respectively). These multiply the
54+ log-concentrations to obtain the actual Gibbs energies and thus driving
55+ forces.
7156"""
7257function max_min_driving_force_analysis (
7358 model:: A.AbstractFBCModel ,
@@ -82,13 +67,15 @@ function max_min_driving_force_analysis(
8267 concentration_upper_bound = 1e-1 , # M
8368 T = 298.15 , # Kelvin
8469 R = 8.31446261815324e-3 , # kJ/K/mol
70+ reference_flux_atol = 1e-6 ,
8571 check_ignored_reactions = missing ,
8672 settings = [],
8773 optimizer,
8874)
8975
90- # First let's check if all the identifiers are okay because we use quite a
91- # lot of these.
76+ # First let's just check if all the identifiers are okay because we use
77+ # quite a lot of these; the rest of the function may be a bit cleaner with
78+ # this checked properly.
9279
9380 model_reactions = Set (A. reactions (model))
9481 model_metabolites = Set (A. metabolites (model))
@@ -97,9 +84,10 @@ function max_min_driving_force_analysis(
9784 DomainError (
9885 reaction_standard_gibbs_free_energies,
9986 " unknown reactions referenced by reaction_standard_gibbs_free_energies" ,
100- o,
10187 ),
10288 )
89+ all (x -> haskey (reaction_standard_gibbs_free_energies, x), keys (reference_flux)) ||
90+ throw (DomainError (reference_flux, " some reactions have no reference flux" ))
10391 all (in (model_reactions), keys (reference_flux)) || throw (
10492 DomainError (
10593 reaction_standard_gibbs_free_energies,
@@ -154,9 +142,12 @@ function max_min_driving_force_analysis(
154142 throw (AssertionError (" check_ignored_reactions validation failed" ))
155143 end
156144
157- default_bound =
145+ # that was a lot of checking.
146+
147+ default_concentration_bound =
158148 C. Between (log (concentration_lower_bound), log (concentration_upper_bound))
159- zero_concentration_metabolites = union (
149+
150+ no_concentration_metabolites = union (
160151 Set (Symbol .(water_metabolites)),
161152 Set (Symbol .(proton_metabolites)),
162153 Set (Symbol .(ignored_metabolites)),
@@ -165,14 +156,14 @@ function max_min_driving_force_analysis(
165156 constraints =
166157 fbc_log_concentration_constraints (
167158 model,
168- concentration_bound = met -> if met in zero_concentration_metabolites
159+ concentration_bound = met -> if met in no_concentration_metabolites
169160 C. EqualTo (0 )
170161 else
171162 mid = String (met)
172163 if haskey (constant_concentrations, mid)
173164 C. EqualTo (log (constant_concentrations[mid]))
174165 else
175- default_bound
166+ default_concentration_bound
176167 end
177168 end ,
178169 ) + :max_min_driving_force ^ C. variable ()
@@ -181,7 +172,15 @@ function max_min_driving_force_analysis(
181172 let r = Symbol (rid)
182173 r => C. Constraint (
183174 value = dGr0 + (R * T) * constraints. reactant_log_concentrations[r],
184- bound = C. Between (- Inf , 0 ),
175+ bound = let rf = reference_flux[rid]
176+ if isapprox (rf, 0.0 , atol = reference_flux_atol)
177+ C. EqualTo (0 )
178+ elseif rf > 0
179+ C. Between (- Inf , 0 )
180+ else
181+ C. Between (0 , Inf )
182+ end
183+ end ,
185184 )
186185 end for (rid, dGr0) in reaction_standard_gibbs_free_energies
187186 )
0 commit comments