-
Notifications
You must be signed in to change notification settings - Fork 62
/
reporting.py
228 lines (207 loc) · 8.09 KB
/
reporting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
from collections import namedtuple
from indra.sources.indra_db_rest.api import get_statements_by_hash
from indra.statements import *
from indra.assemblers.english.assembler import _assemble_agent_str, \
SentenceBuilder
def stmts_from_pysb_path(path, model, stmts):
"""Return source Statements corresponding to a path in a model.
Parameters
----------
path : list[tuple[str, int]]
A list of tuples where the first element of the tuple is the
name of a rule, and the second is the associated polarity along
a path.
model : pysb.core.Model
A PySB model which contains the rules along the path.
stmts : list[indra.statements.Statement]
A list of INDRA Statements from which the model was assembled.
Returns
-------
path_stmts : list[indra.statements.Statement]
The Statements from which the rules along the path were obtained.
"""
path_stmts = []
for path_rule, sign in path:
for rule in model.rules:
if rule.name == path_rule:
stmt = stmt_from_rule(path_rule, model, stmts)
assert stmt is not None
path_stmts.append(stmt)
return path_stmts
def stmts_from_indranet_path(path, model, signed, from_db=True, stmts=None):
"""Return source Statements corresponding to a path in an IndraNet model
(found by SignedGraphModelChecker or UnsignedGraphModelChecker).
Parameters
----------
path : list[tuple[str, int]]
A list of tuples where the first element of the tuple is the
name of an agent, and the second is the associated polarity along
a path.
model : nx.Digraph or nx.MultiDiGraph
An IndraNet model flattened into an unsigned DiGraph or signed
MultiDiGraph.
signed : bool
Whether the model and path are signed.
from_db : bool
If True, uses statement hashes to query the database. Otherwise, looks
for path statements in provided stmts.
stmts : Optional[list[indra.statements.Statement]]
A list of INDRA Statements from which the model was assembled. Required
if from_db is set to False.
Returns
-------
path_stmts : list[[indra.statements.Statement]]
A list of lists of INDRA statements explaining the path (each inner
corresponds to one step in the path because the flattened model can
have multiple statements per edge).
"""
steps = []
for i in range(len(path[:-1])):
source = path[i]
target = path[i+1]
if signed:
if source[1] == target[1]:
sign = 0
else:
sign = 1
stmt_data = model[source[0]][target[0]][sign]['statements']
else:
stmt_data = model[source[0]][target[0]]['statements']
hashes = [stmt['stmt_hash'] for stmt in stmt_data]
if from_db:
statements = get_statements_by_hash(hashes, simple_response=True)
else:
statements = [
stmt for stmt in stmts if stmt.get_hash() in hashes]
steps.append(statements)
return steps
PybelEdge = namedtuple(
'PybelEdge', ['source', 'target', 'relation', 'reverse'])
def pybel_edge_to_english(pybel_edge):
source_str = _assemble_agent_str(pybel_edge.source)
target_str = _assemble_agent_str(pybel_edge.target)
sb = SentenceBuilder()
if pybel_edge.relation == 'partOf':
if pybel_edge.reverse:
rel_str = ' has a component '
else:
rel_str = ' is a part of '
elif pybel_edge.relation == 'hasVariant':
if pybel_edge.reverse:
rel_str = ' is a variant of '
else:
rel_str = ' has a variant '
sb.append_as_sentence([source_str, rel_str, target_str])
sb.make_sentence()
return sb.sentence
def stmts_from_pybel_path(path, model, from_db=True, stmts=None):
"""Return source Statements corresponding to a path in a PyBEL model.
Parameters
----------
path : list[tuple[str, int]]
A list of tuples where the first element of the tuple is the
name of an agent, and the second is the associated polarity along
a path.
model : pybel.BELGraph
A PyBEL BELGraph model.
from_db : bool
If True, uses statement hashes to query the database. Otherwise, looks
for path statements in provided stmts.
stmts : Optional[list[indra.statements.Statement]]
A list of INDRA Statements from which the model was assembled. Required
if from_db is set to False.
Returns
-------
path_stmts : list[[indra.statements.Statement]]
A list of lists of INDRA statements explaining the path (each inner
corresponds to one step in the path because PyBEL model can have
multiple edges representing multiple statements and evidences between
two nodes).
"""
import pybel.constants as pc
from indra.sources.bel.processor import get_agent
steps = []
for i in range(len(path[:-1])):
source = path[i]
target = path[i+1]
# Check if the signs of source and target nodes are the same
positive = (source[1] == target[1])
reverse = False
try:
all_edges = model[source[0]][target[0]]
except KeyError:
# May be a symmetric edge
all_edges = model[target[0]][source[0]]
reverse = True
# Only keep the edges with correct sign or non-causal
edges = {}
key = 0
for edge_data in all_edges.values():
if edge_data['relation'] not in pc.CAUSAL_RELATIONS:
edges[key] = edge_data
key += 1
if positive and \
edge_data['relation'] in pc.CAUSAL_INCREASE_RELATIONS:
edges[key] = edge_data
key += 1
elif not positive and \
edge_data['relation'] in pc.CAUSAL_DECREASE_RELATIONS:
edges[key] = edge_data
key += 1
else:
continue
hashes = set()
for j in range(len(edges)):
try:
hashes.add(edges[j]['annotations']['stmt_hash'])
# partOf and hasVariant edges don't have hashes
except KeyError:
continue
# If we didn't get any hashes, we can get PybelEdge object from
# partOf and hasVariant edges
if not hashes:
statements = []
# Can't get statements without hash from db
for edge_v in edges.values():
rel = edge_v['relation']
edge = PybelEdge(get_agent(source[0]),
get_agent(target[0]), rel, reverse)
statements.append(edge)
# Stop if we have an edge to avoid duplicates
if len(statements) > 0:
break
# If we have hashes, retrieve statements from them
else:
if from_db:
statements = get_statements_by_hash(list(hashes),
simple_response=True)
else:
statements = [
stmt for stmt in stmts if stmt.get_hash() in hashes]
steps.append(statements)
return steps
def stmt_from_rule(rule_name, model, stmts):
"""Return the source INDRA Statement corresponding to a rule in a model.
Parameters
----------
rule_name : str
The name of a rule in the given PySB model.
model : pysb.core.Model
A PySB model which contains the given rule.
stmts : list[indra.statements.Statement]
A list of INDRA Statements from which the model was assembled.
Returns
-------
stmt : indra.statements.Statement
The Statement from which the given rule in the model was obtained.
"""
stmt_uuid = None
for ann in model.annotations:
if ann.subject == rule_name:
if ann.predicate == 'from_indra_statement':
stmt_uuid = ann.object
break
if stmt_uuid:
for stmt in stmts:
if stmt.uuid == stmt_uuid:
return stmt