Source code for indra.explanation.model_checker.pybel

import logging
from copy import deepcopy
from . import ModelChecker, NodesContainer
from indra.statements import *
from indra.ontology.bio import bio_ontology
from .model_checker import signed_edges_to_signed_nodes

logger = logging.getLogger(__name__)


[docs]class PybelModelChecker(ModelChecker): """Check a PyBEL model against a set of INDRA statements. Parameters ---------- model : pybel.BELGraph A Pybel model to check. statements : Optional[list[indra.statements.Statement]] A list of INDRA Statements to check the model against. do_sampling : bool Whether to use breadth-first search or weighted sampling to generate paths. Default is False (breadth-first search). seed : int Random seed for sampling (optional, default is None). nodes_to_agents : dict A dictionary mapping nodes of intermediate signed edges graph to INDRA agents. Attributes ---------- graph : nx.Digraph A DiGraph with signed nodes to find paths in. """ def __init__(self, model, statements=None, do_sampling=False, seed=None, nodes_to_agents=None): super().__init__(model, statements, do_sampling, seed, nodes_to_agents)
[docs] def get_graph(self, include_variants=False, symmetric_variant_links=False, include_components=True, symmetric_component_links=True, edge_filter_func=None): """Convert a PyBELGraph to a graph with signed nodes.""" # This import is done here rather than at the top level to avoid # making pybel an implicit dependency of the model checker from indra.assemblers.pybel.assembler import belgraph_to_signed_graph if self.graph: return self.graph # NOTE edge_filter_func is not currently used in PyBEL signed_edges = belgraph_to_signed_graph( self.model, include_variants=include_variants, symmetric_variant_links=symmetric_variant_links, include_components=include_components, symmetric_component_links=symmetric_component_links, propagate_annotations=True) self.graph = signed_edges_to_signed_nodes( signed_edges, copy_edge_data={'belief'}) self.get_nodes_to_agents() return self.graph
[docs] def process_statement(self, stmt): # Check if this is one of the statement types that we can check if not isinstance(stmt, (Modification, RegulateAmount, RegulateActivity, Influence)): logger.info('Statement type %s not handled' % stmt.__class__.__name__) return (None, None, 'STATEMENT_TYPE_NOT_HANDLED') subj, obj = stmt.agent_list() if obj is None: # Cannot check modifications for statements without object if isinstance(stmt, Modification): return (None, None, 'STATEMENT_TYPE_NOT_HANDLED') subj_nodes = self.get_nodes(subj, self.graph, 0) obj_nodes = self.get_nodes(obj, self.graph, 0) else: # Get the polarity for the statement if isinstance(stmt, Modification): target_polarity = 1 if isinstance(stmt, RemoveModification) \ else 0 obj_agent = deepcopy(obj) obj_agent.mods.append(stmt._get_mod_condition()) obj = obj_agent elif isinstance(stmt, RegulateActivity): target_polarity = 0 if stmt.is_activation else 1 obj_agent = deepcopy(obj) obj_agent.activity = stmt._get_activity_condition() obj_agent.activity.is_active = True obj = obj_agent elif isinstance(stmt, RegulateAmount): target_polarity = 1 if isinstance(stmt, DecreaseAmount) else 0 elif isinstance(stmt, Influence): target_polarity = 1 if stmt.overall_polarity() == -1 else 0 subj_nodes = self.get_nodes(subj, self.graph, 0) obj_nodes = self.get_nodes(obj, self.graph, target_polarity) # Statement has object but it's not in the graph if not obj_nodes.all_nodes: return (None, None, 'OBJECT_NOT_FOUND') if not subj_nodes.all_nodes: return (None, None, 'SUBJECT_NOT_FOUND') return (subj_nodes, obj_nodes, None)
[docs] def get_nodes(self, agent, graph, target_polarity): """Get all nodes corresponding to a given agent.""" # This import is done here rather than at the top level to avoid # making pybel an implicit dependency of the model checker from indra.assemblers.pybel.assembler import _get_agent_node nc = NodesContainer(agent) if agent is None: nc.all_nodes = None return nc # First get exact match agent_node = _get_agent_node(agent)[0] if agent_node: node = (agent_node, target_polarity) if node in graph.nodes: nc.main_nodes.append(node) # Try get refined versions for n, ag in self.nodes_to_agents.items(): if ag is not None and not ag.matches(agent) and ag.refinement_of( agent, bio_ontology): node = (n, target_polarity) if node in graph.nodes: nc.ref_nodes.append(node) nc.get_all_nodes() return nc
[docs] def get_nodes_to_agents(self): """Return a dictionary mapping PyBEL nodes to INDRA agents.""" if self.nodes_to_agents: return self.nodes_to_agents # This import is done here rather than at the top level to avoid # making pybel an implicit dependency of the model checker from indra.sources.bel.processor import get_agent self.nodes_to_agents = { node: get_agent(node) for node in self.model.nodes} return self.nodes_to_agents