Skip to content

Commit

Permalink
Refactor thermo (#540)
Browse files Browse the repository at this point in the history
* wip

* fix: correct annotation finding

* test: adjust cases to new functions

* refactor: temporarily disable name matching

* refactor: disable name matching

* test: adapt tests to lack of name matching

* refactor: sort output

* chore: change test title

* test: adjust test description and data

* test: adjust description

* chore: make entry in changelog
  • Loading branch information
Midnighter committed Dec 10, 2018
1 parent bb70952 commit 5d68ff7
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 172 deletions.
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ History

Next Release
------------
* Adjust the reversibility index test to not use name matching and increase
the threshold slightly. Also adjust the description of the test.
* Adjust tests to the change in the ``add_boundary`` interface.
* Identify blocked reactions using the cobrapy built-in function.

Expand Down
2 changes: 1 addition & 1 deletion memote/suite/templates/test_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ cards:
- test_gene_protein_reaction_rule_presence
- test_find_pure_metabolic_reactions
- test_find_constrained_pure_metabolic_reactions
- test_find_incorrect_thermodynamic_reversibility
- test_find_candidate_irreversible_reactions
- test_find_duplicate_reactions
- test_find_transport_reactions
- test_find_constrained_transport_reactions
Expand Down
92 changes: 47 additions & 45 deletions memote/suite/tests/test_thermodynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,71 +27,73 @@
pytest.skip("Thermodynamic tests require at least Python version 3.5.",
allow_module_level=True)

import memote.support.thermodynamics as thermo # noqa
import memote.support.basic as basic # noqa
from memote.utils import (annotate, get_ids, truncate) # noqa
import memote.support.thermodynamics as thermo # noqa
import memote.support.basic as basic # noqa
from memote.utils import annotate, get_ids, wrapper # noqa


@annotate(title="Thermodynamic Reversibility of Purely Metabolic Reactions",
format_type="percent")
def test_find_incorrect_thermodynamic_reversibility(read_only_model):
def test_find_candidate_irreversible_reactions(read_only_model):
u"""
Expect reversibility of metabolic reactions to agree with thermodynamics.
Identify reversible reactions that could be irreversible.
If a reaction is neither a transport reaction, a biomass reaction nor a
boundary reaction, it is counted as a purely metabolic reaction.
This test checks if the reversibility attribute of each reaction
in a list of cobrapy reactions agrees with a thermodynamics-based
agrees with a thermodynamics-based
calculation of reversibility. To determine reversibility we calculate
the reversibility index ln_gamma of each reaction
using the eQuilibrator API. The default cutoff for ln_gamma of 3
"corresponds to allowing concentrations to span three orders of magnitude
around 100 μM (~3 μM—3 mM)" at "pH = 7, I = 0.1 M and T = 298 K". This
means that a reaction is considered irreversible if the concentration of
an individual metabolite would have to change more than three orders of
magnitude i.e. from 3 µM to 3 mM to reverse the direction of flux. For
further information on the thermodynamic and implementational details
the reversibility index ln_gamma (natural logarithm of gamma) of each
reaction
using the eQuilibrator API. We consider reactions, whose reactants'
concentrations would need to change by more than three orders of
magnitude for the reaction flux to reverse direction, to be likely
candidates of irreversible reactions. This assume default concentrations
around 100 μM (~3 μM—3 mM) at pH = 7, I = 0.1 M and T = 298 K. The
corresponding reversibility index is approximately 7. For
further information on the thermodynamic and implementation details
please refer to
https://doi.org/10.1093/bioinformatics/bts317 and
https://gitlab.com/elad.noor/equilibrator-api/tree/master.
https://pypi.org/project/equilibrator-api/.
Please note that currently eQuilibrator can only determine the
reversibility index for chemically and redox balanced reactions whose
metabolites can be mapped to KEGG compound IDs (e.g. C00001). In addition
metabolites can be mapped to KEGG compound identifiers (e.g. C00001). In
addition
to not being mappable to KEGG or the reaction not being balanced,
there is a possibility that the metabolite cannot be broken down into
chemical groups which is essential for the calculation of Gibbs energy
using component contributions. This test collects each exceptional reaction
using group contributions. This test collects each erroneous reaction
and returns them as a tuple containing each list in the following order:
1. Reactions with incorrect **rev**ersibility
2. Reactions with incomplete **mapping** to KEGG
3. Reactions with Metabolites that are problematic
during **calc**ulation
4. Chemically or redox un**bal**anced Reactions (after mapping to KEGG)
1. Reactions with reversibility index
2. Reactions with incomplete mapping to KEGG
3. Reactions with metabolites that are problematic during calculation
4. Chemically or redox unbalanced Reactions (after mapping to KEGG)
This test simply reports the number of metabolic reactions that disagree
with thermodynamic calculations i.e. are irreversible even though they
should not be (and vice versa), considering the above fluctuations of
metabolite concentrations. It does not have a mandatory 'pass' criterium.
This test simply reports the number of reversible reactions that, according
to the reversibility index, are likely to be irreversible.
"""
ann = test_find_incorrect_thermodynamic_reversibility.annotation
# With gamma = 1000, ln_gamma ~ 6.9. We use 7 as the cut-off.
threshold = 7.0
ann = test_find_candidate_irreversible_reactions.annotation
met_rxns = basic.find_pure_metabolic_reactions(read_only_model)
rev, mapping, calc, bal = \
thermo.find_incorrect_thermodynamic_reversibility(met_rxns)
ann["data"] = (get_ids(rev), get_ids(mapping), get_ids(calc), get_ids(bal))
ann["message"] = "Out of {} purely metabolic reactions the reversibility "\
"of {} does not agree with the calculated ln_gamma " \
"cutoff ({:.2%}), and thus ought to be inverted. " \
"{} reactions " \
"could not be mapped to KEGG completely, " \
"{} contained 'problematic' metabolites, and " \
"{} are chemically or redox imbalanced: {}" \
"".format(len(met_rxns), len(ann["data"][0]),
ann["metric"], len(ann["data"][1]),
len(ann["data"][2]), len(ann["data"][3]),
truncate(ann["data"][0]))
ann["metric"] = (len(ann["data"][0]) +
len(ann["data"][1]) +
len(ann["data"][2]) +
len(ann["data"][3])) / len(met_rxns)
rev_index, incomplete, problematic, unbalanced = \
thermo.find_thermodynamic_reversibility_index(met_rxns)
ann["data"] = (
[(r.id, i) for r, i in rev_index],
get_ids(incomplete),
get_ids(problematic),
get_ids(unbalanced)
)
num_irrev = sum(1 for r, i in rev_index if abs(i) >= threshold)
ann["message"] = wrapper.fill(
"""Out of {} purely metabolic reactions, {} have an absolute
reversibility index greater or equal to 7 and are therefore likely
candidates for being irreversible.
{} reactions could not be mapped to KEGG completely, {} contained
'problematic' metabolites, and {} are chemically or redox imbalanced.
""".format(len(met_rxns), num_irrev, len(incomplete), len(problematic),
len(unbalanced))
)
ann["metric"] = num_irrev / len(rev_index)

0 comments on commit 5d68ff7

Please sign in to comment.