Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 76 additions & 9 deletions bioagents/mra/mra.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pysb.tools import render_reactions
from pysb.export import export
from indra.util.kappa_util import im_json_to_graph, cm_json_to_graph
from indra.assemblers.english_assembler import EnglishAssembler


logger = logging.getLogger('MRA')
Expand Down Expand Up @@ -64,7 +65,8 @@ def build_model_from_ekb(self, model_ekb):
res['ambiguities'] = ambiguities
model_exec = self.assemble_pysb(stmts)
res['model_exec'] = model_exec
res['diagrams'] = make_diagrams(model_exec, model_id)
res['diagrams'] = make_diagrams(model_exec, model_id,
self.models[model_id])
return res

def build_model_from_json(self, model_json):
Expand All @@ -77,7 +79,8 @@ def build_model_from_json(self, model_json):
return res
model_exec = self.assemble_pysb(stmts)
res['model_exec'] = model_exec
res['diagrams'] = make_diagrams(model_exec, model_id)
res['diagrams'] = make_diagrams(model_exec, model_id,
self.models[model_id])
return res

def expand_model_from_ekb(self, model_ekb, model_id):
Expand All @@ -99,7 +102,8 @@ def expand_model_from_ekb(self, model_ekb, model_id):
res['model_new'] = new_stmts
model_exec = self.assemble_pysb(model_stmts)
res['model_exec'] = model_exec
res['diagrams'] = make_diagrams(model_exec, new_model_id)
res['diagrams'] = make_diagrams(model_exec, new_model_id,
self.models[model_id])
return res

def expand_model_from_json(self, model_json, model_id):
Expand All @@ -116,7 +120,8 @@ def expand_model_from_json(self, model_json, model_id):
res['model_new'] = new_stmts
model_exec = self.assemble_pysb(model_stmts)
res['model_exec'] = model_exec
res['diagrams'] = make_diagrams(model_exec, new_model_id)
res['diagrams'] = make_diagrams(model_exec, new_model_id,
self.models[model_id])
return res

def has_mechanism(self, mech_ekb, model_id):
Expand Down Expand Up @@ -159,7 +164,8 @@ def remove_mechanism(self, mech_ekb, model_id):
res['model_exec'] = model_exec
if removed_stmts:
res['removed'] = removed_stmts
res['diagrams'] = make_diagrams(model_exec, model_id)
res['diagrams'] = make_diagrams(model_exec, model_id,
self.models[model_id])
self.new_model(new_stmts)
return res

Expand All @@ -181,7 +187,8 @@ def model_undo(self):
if not stmts:
return res
res['ambiguities'] = []
res['diagrams'] = make_diagrams(model_exec, new_model_id)
res['diagrams'] = make_diagrams(model_exec, new_model_id,
self.models[new_model_id])
return res

def get_upstream(self, target, model_id):
Expand Down Expand Up @@ -249,11 +256,11 @@ def get_ambiguities(tp):
return all_ambiguities


def make_diagrams(pysb_model, model_id):
def make_diagrams(pysb_model, model_id, indra_model):
sbgn = make_sbgn(pysb_model, model_id)
rxn = draw_reaction_network(pysb_model, model_id)
cm = draw_contact_map(pysb_model, model_id)
im = draw_influence_map(pysb_model, model_id)
im = draw_influence_map(pysb_model, model_id, indra_model)
diagrams = {'reactionnetwork': rxn, 'contactmap': cm,
'influencemap': im, 'sbgn': sbgn}
return diagrams
Expand All @@ -272,10 +279,12 @@ def make_sbgn(pysb_model, model_id):
return sbgn_str


def draw_influence_map(pysb_model, model_id):
def draw_influence_map(pysb_model, model_id, indra_model):
"""Generate a Kappa influence map, draw it and save it as a PNG."""
try:
im = make_influence_map(pysb_model)
im = make_influence_map_labels_natural_language(im, pysb_model,
indra_model)
fname = 'model%d_im' % model_id
abs_path = os.path.abspath(os.getcwd())
full_path = os.path.join(abs_path, fname + '.png')
Expand Down Expand Up @@ -304,6 +313,64 @@ def make_influence_map(pysb_model):
return im


def get_statement_by_uuid(statements, uuid):
"""Returns the first statement in statements with the given uuid, or None
if no such statements are in the provided list."""
for statement in statements:
if statement.uuid == uuid:
return statement
return None


def dict_value_appears_multiple_times(d, value):
"""Returns True iff the given value is mapped to multiple times in this
dictionary."""
count = 0
for k, v in d.items():
if v == value:
count += 1
return count > 1

def make_influence_map_labels_natural_language(im, pysb_model, indra_model):
"""Replaces the labels of the influence map with natural language labels.
"""
# Get the name of all the rules in the pysb model
rule_names = [rule.name for rule in pysb_model.rules]

relabel_map_english = {}
relabel_map_english_and_rule = {}
for annotation in pysb_model.annotations:
if annotation.subject in rule_names:
name = annotation.subject
if annotation.predicate == 'from_indra_statement':
# We found the INDRA statement uuid corresponding to a rule
statement_uuid = annotation.object
s = get_statement_by_uuid(indra_model, statement_uuid)

# Convert the statement into English
assembler = EnglishAssembler([s])

english_text = assembler.make_model()
english_and_rule = english_text + ' (' + name + ')'

relabel_map_english[name] = english_text
relabel_map_english_and_rule[name] = english_and_rule

# Use only the English text if that is unambiguous, otherwise include
# the rule name too
relabel_map = {}
for before in relabel_map_english:
english_text = relabel_map_english[before]
if dict_value_appears_multiple_times(relabel_map_english,
english_text):
relabel_map[before] = relabel_map_english_and_rule[before]
else:
relabel_map[before] = english_text

im = networkx.relabel_nodes(im, relabel_map)
return im


def draw_contact_map(pysb_model, model_id):
try:
cm = make_contact_map(pysb_model)
Expand Down
Loading