Skip to content

Commit

Permalink
Add ability to view gene rule using name
Browse files Browse the repository at this point in the history
This is the new gene_name_reaction_rule attribute.

Fixes #174
  • Loading branch information
aebrahim committed Aug 3, 2015
1 parent b2d2574 commit 85bbc55
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
25 changes: 19 additions & 6 deletions cobra/core/Gene.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,31 @@


# functions for gene reaction rules
def ast2str(expr, level=0):
"""convert compiled ast to gene_reaction_rule str"""
def ast2str(expr, level=0, names=None):
"""convert compiled ast to gene_reaction_rule str
expr: str of a gene reaction rule
level: internal use only
names: optional dict of {Gene.id: Gene.name}
Use this to get a rule str which uses names instead. This
should be done for display purposes only. All gene_reaction_rule
strings which are computed with should use the id.
"""
if isinstance(expr, Expression):
return ast2str(expr.body, 0) if hasattr(expr, "body") else ""
return ast2str(expr.body, 0, names) \
if hasattr(expr, "body") else ""
elif isinstance(expr, Name):
return expr.id
return names.get(expr.id, expr.id) if names else expr.id
elif isinstance(expr, BoolOp):
op = expr.op
if isinstance(op, Or):
str_exp = " or ".join(ast2str(i, level + 1) for i in expr.values)
str_exp = " or ".join(ast2str(i, level + 1, names)
for i in expr.values)
elif isinstance(op, And):
str_exp = " and ".join(ast2str(i, level + 1) for i in expr.values)
str_exp = " and ".join(ast2str(i, level + 1, names)
for i in expr.values)
else:
raise TypeError("unsupported operation " + op.__class__.__name)
return "(" + str_exp + ")" if level else str_exp
Expand Down
15 changes: 14 additions & 1 deletion cobra/core/Reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from six import string_types, iteritems

from .Object import Object
from .Gene import Gene, parse_gpr
from .Gene import Gene, parse_gpr, ast2str
from .Metabolite import Metabolite


Expand Down Expand Up @@ -125,6 +125,19 @@ def gene_reaction_rule(self, new_rule):
warn("could not remove old gene %s from reaction %s" %
(g.id, self.id))

@property
def gene_name_reaction_rule(self):
"""Display gene_reaction_rule with names intead.
Do NOT use this string for computation. It is intended to give a
representation of the rule using more familiar gene names instead of
the often cryptic ids.
"""
names = {i.id: i.name for i in self._genes}
ast = parse_gpr(self._gene_reaction_rule)[0]
return ast2str(ast, names=names)

@property
def x(self):
"""The flux through the reaction in the most recent solution
Expand Down
3 changes: 3 additions & 0 deletions cobra/test/unit_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ def testGPR_modification(self):
fake_gene = model.genes.get_by_id("fake_gene")
self.assertIn(fake_gene, reaction.genes)
self.assertIn(reaction, fake_gene.reactions)
fake_gene.name = "foo_gene"
self.assertEqual(reaction.gene_name_reaction_rule, fake_gene.name)

def test_add_metabolite(self):
"""adding a metabolite to a reaction in a model"""
Expand Down Expand Up @@ -291,6 +293,7 @@ def test_build_from_string(self):
self.assertEqual(pgi.lower_bound, 0)
pgi.reaction = "g6p_c <== f6p_c"
self.assertEqual(pgi.upper_bound, 0)
self.assertEqual(pgi.reaction.strip(), "g6p_c <-- f6p_c")
pgi.reaction = "g6p_c --> f6p_c + h2o_c"
self.assertIn(model.metabolites.h2o_c, pgi._metabolites)
pgi.build_reaction_from_string("g6p_c --> f6p_c + foo", verbose=False)
Expand Down

0 comments on commit 85bbc55

Please sign in to comment.