示例#1
0
def rules_using_parameter(model, parameter):
    """Return a ComponentSet of rules in the model which make use of the given parameter"""
    cset = ComponentSet()
    for rule in model.rules:
        if rule.rate_forward is parameter or rule.rate_reverse is parameter:
            cset.add(rule)
    return cset
示例#2
0
def rules_using_parameter(model, parameter):
    """Return a ComponentSet of rules in the model which make use of the given parameter"""
    cset = ComponentSet()
    for rule in model.rules:
        if rule.rate_forward is parameter or rule.rate_reverse is parameter:
            cset.add(rule)
    return cset
示例#3
0
def rules_using_parameter(model, parameter):
    """Return a ComponentSet of rules in the model which make use of the given parameter"""
    if not isinstance(parameter, pysb.core.Parameter):
        # Try getting the parameter by name
        parameter = model.parameters.get(parameter)
    cset = ComponentSet()
    for rule in model.rules:
        if rule.rate_forward is parameter or rule.rate_reverse is parameter:
            cset.add(rule)
    return cset
示例#4
0
def rules_using_parameter(model, parameter):
    """Return a ComponentSet of rules in the model which make use of the given parameter"""
    if not isinstance(parameter, pysb.core.Parameter):
        # Try getting the parameter by name
        parameter = model.parameters.get(parameter)
    cset = ComponentSet()
    for rule in model.rules:
        if rule.rate_forward is parameter or rule.rate_reverse is parameter:
            cset.add(rule)
    return cset
示例#5
0
def merge_parameters(model, new_name, parameters):
    unique_values = {parameter.value for parameter in parameters}
    if len(unique_values) > 1:
        raise ValueError("Given parameters have different values: %s" %
                         (', '.join('%s=%g' % (p.name, p.value)
                                    for p in parameters)))
    value = parameters[0].value
    rules = ComponentSet()
    for parameter in parameters:
        rules |= rules_using_parameter(model, parameter)
    if not rules:
        raise ValueError("Model has no rules using given parameters: %s" %
                         ', '.join(p.name for p in parameters))
    try:
        new_parameter = model.parameters[new_name]
        if new_parameter.value != value:
            raise ValueError("Parameter %s is already present in the model "
                             "with the value %g, which differs from the "
                             "common value of the given parameters, %g" %
                             (new_parameter.name, new_parameter.value, value))
    except KeyError:
        new_parameter = Parameter(new_name, value)
        model.add_component(new_parameter)
    for rule in rules:
        for attr in 'rate_forward', 'rate_reverse':
            if getattr(rule, attr) in parameters:
                setattr(rule, attr, new_parameter)
示例#6
0
def pore_bind(subunit, sp_site1, sp_site2, sc_site, size, cargo, c_site,
              klist):
    """Generate rules to bind a monomer to a circular homomeric pore.

    The pore structure is defined by the `pore_species` macro -- `subunit`
    monomers bind to each other from `sp_site1` to `sp_site2` to form a closed
    ring. The binding reaction takes the form pore + cargo <> pore:cargo.

    Parameters
    ----------
    subunit : Monomer or MonomerPattern
        Subunit of which the pore is composed.
    sp_site1, sp_site2 : string
        Names of the sites where one copy of `subunit` binds to the next.
    sc_site : string
        Name of the site on `subunit` where it binds to the cargo `cargo`.
    size : integer
        Number of subunits in the pore at which binding will occur.
    cargo : Monomer or MonomerPattern
        Cargo that binds to the pore complex.
    c_site : string
        Name of the site on `cargo` where it binds to `subunit`.
    klist : list of Parameters or numbers
        List containing forward and reverse rate constants for the binding
        reaction (in that order). Rate constants should either be both Parameter
        objects or both numbers. If Parameters are passed, they will be used
        directly in the generated Rules. If numbers are passed, Parameters
        will be created with automatically generated names based on <TODO>
        and these parameters will be included at the end of the returned
        component list.
    """

    macros._verify_sites(subunit, sc_site)
    macros._verify_sites(cargo, c_site)

    def pore_bind_rule_name(rule_expression, size):
        # Get ReactionPatterns
        react_p = rule_expression.reactant_pattern
        prod_p = rule_expression.product_pattern
        # Build the label components
        # Pore is always first complex of LHS due to how we build the rules
        subunit = react_p.complex_patterns[0].monomer_patterns[0].monomer
        if len(react_p.complex_patterns) == 2:
            # This is the complexation reaction
            cargo = react_p.complex_patterns[1].monomer_patterns[0]
        else:
            # This is the dissociation reaction
            cargo = prod_p.complex_patterns[1].monomer_patterns[0]
        return '%s_%d_%s' % (subunit.name, size,
                             macros._monomer_pattern_label(cargo))

    components = ComponentSet()
    # Set up some aliases that are invariant with pore size
    subunit_free = subunit({sc_site: None})
    cargo_free = cargo({c_site: None})

    #for size, klist in zip(range(min_size, max_size + 1), ktable):

    # More aliases which do depend on pore size
    pore_free = macros.pore_species(subunit_free, sp_site1, sp_site2, size)

    # This one is a bit tricky. The pore:cargo complex must only introduce
    # one additional bond even though there are multiple subunits in the
    # pore. We create partial patterns for bound pore and cargo, using a
    # bond number that is high enough not to conflict with the bonds within
    # the pore ring itself.
    # Start by copying pore_free, which has all cargo binding sites empty
    pore_bound = pore_free.copy()
    # Get the next bond number not yet used in the pore structure itself
    cargo_bond_num = size + 1
    # Assign that bond to the first subunit in the pore
    pore_bound.monomer_patterns[0].site_conditions[sc_site] = cargo_bond_num
    # Create a cargo source pattern with that same bond
    cargo_bound = cargo({c_site: cargo_bond_num})
    # Finally we can define the complex trivially; the bond numbers are
    # already present in the patterns
    pc_complex = pore_bound % cargo_bound

    # Create the rules
    name_func = functools.partial(pore_bind_rule_name, size=size)
    components |= macros._macro_rule('pore_bind',
                                     pore_free + cargo_free | pc_complex,
                                     klist[0:2], ['kf', 'kr'],
                                     name_func=name_func)

    return components
示例#7
0
    def get_im(self, force_update=False):
        """Get the influence map for the model, generating it if necessary.

        Parameters
        ----------
        force_update : bool
            Whether to generate the influence map when the function is called.
            If False, returns the previously generated influence map if
            available. Defaults to True.

        Returns
        -------
        pygraphviz AGraph object containing the influence map.
            The influence map can be rendered as a pdf using the dot layout
            program as follows::

                influence_map.draw('influence_map.pdf', prog='dot')
        """
        if self._im and not force_update:
            return self._im
        if not self.model:
            raise Exception("Cannot get influence map if there is no model.")

        def add_obs_for_agent(agent):
            obj_mps = list(pa.grounded_monomer_patterns(self.model, agent))
            if not obj_mps:
                logger.debug(
                    'No monomer patterns found in model for agent %s, '
                    'skipping' % agent)
                return
            obs_list = []
            for obj_mp in obj_mps:
                obs_name = _monomer_pattern_label(obj_mp) + '_obs'
                # Add the observable
                obj_obs = Observable(obs_name, obj_mp, _export=False)
                obs_list.append(obs_name)
                try:
                    self.model.add_component(obj_obs)
                except ComponentDuplicateNameError as e:
                    pass
            return obs_list

        # Create observables for all statements to check, and add to model
        # Remove any existing observables in the model
        self.model.observables = ComponentSet([])
        for stmt in self.statements:
            # Generate observables for Modification statements
            if isinstance(stmt, Modification):
                mod_condition_name = modclass_to_modtype[stmt.__class__]
                if isinstance(stmt, RemoveModification):
                    mod_condition_name = modtype_to_inverse[mod_condition_name]
                # Add modification to substrate agent
                modified_sub = _add_modification_to_agent(
                    stmt.sub, mod_condition_name, stmt.residue, stmt.position)
                obs_list = add_obs_for_agent(modified_sub)
                # Associate this statement with this observable
                self.stmt_to_obs[stmt] = obs_list
            # Generate observables for Activation/Inhibition statements
            elif isinstance(stmt, RegulateActivity):
                regulated_obj, polarity = \
                        _add_activity_to_agent(stmt.obj, stmt.obj_activity,
                                               stmt.is_activation)
                obs_list = add_obs_for_agent(regulated_obj)
                # Associate this statement with this observable
                self.stmt_to_obs[stmt] = obs_list
            elif isinstance(stmt, RegulateAmount):
                obs_list = add_obs_for_agent(stmt.obj)
                self.stmt_to_obs[stmt] = obs_list
        # Add observables for each agent
        for ag in self.agent_obs:
            obs_list = add_obs_for_agent(ag)
            self.agent_to_obs[ag] = obs_list

        logger.info("Generating influence map")
        self._im = kappa.influence_map(self.model)
        #self._im.is_multigraph = lambda: False
        # Now, for every rule in the model, check if there are any observables
        # downstream
        # Alternatively, for every observable in the model, get a list of rules
        # We'll need the dictionary to check if nodes are observables
        node_attributes = nx.get_node_attributes(self._im, 'shape')
        for rule in self.model.rules:
            obs_list = []
            # Get successors of the rule node
            for neighb in self._im.neighbors(rule.name):
                # Check if the node is an observable
                if node_attributes[neighb] != 'ellipse':
                    continue
                # Get the edge and check the polarity
                edge_sign = _get_edge_sign(self._im, (rule.name, neighb))
                obs_list.append((neighb, edge_sign))
            self.rule_obs_dict[rule.name] = obs_list
        return self._im
示例#8
0
    def _find_im_paths(self, subj_mp, obj_obs, target_polarity):
        """Check for a source/target path in the influence map.

        Parameters
        ----------
        subj_mp : pysb.MonomerPattern
            MonomerPattern corresponding to the subject of the Statement
            being checked.
        obj_obs : pysb.Observable
            Observable corresponding to the object/target of the Statement
            being checked.
        target_polarity : 1 or -1
            Whether the influence in the Statement is positive (1) or negative
            (-1).

        Returns
        -------
        boolean
            Whether there is a path from a rule matching the subject
            MonomerPattern to the object Observable with the appropriate
            polarity.
        """
        # Reset the observables list
        self.model.observables = ComponentSet([])
        self.model.add_component(obj_obs)
        # Find rules in the model corresponding to the input
        logger.info('Finding paths between %s and %s with polarity %s' %
                    (subj_mp, obj_obs, target_polarity))
        if subj_mp is None:
            input_rule_set = None
        else:
            input_rules = _match_lhs(subj_mp, self.model.rules)
            logger.info('Found %s input rules matching %s' %
                        (len(input_rules), str(subj_mp)))
            # Filter to include only rules where the subj_mp is actually the
            # subject (i.e., don't pick up upstream rules where the subject
            # is itself a substrate/object)
            # FIXME: Note that this will eliminate rules where the subject
            # being checked is included on the left hand side as
            # a bound condition rather than as an enzyme.
            subj_rules = pa.rules_with_annotation(self.model,
                                                  subj_mp.monomer.name,
                                                  'rule_has_subject')
            logger.info('%d rules with %s as subject' %
                        (len(subj_rules), subj_mp.monomer.name))
            input_rule_set = set([r.name for r in input_rules]).intersection(
                set([r.name for r in subj_rules]))
            logger.info('Final input rule set contains %d rules' %
                        len(input_rule_set))
            # If we have enzyme information but there are no input rules
            # matching the enzyme, then there is no path
            if not input_rule_set:
                return False
        # Generate the predecessors to our observable and count the paths
        # TODO: Make it optionally possible to return on the first path?
        num_paths = 0
        for path in _find_sources(self.get_im(), obj_obs.name, input_rule_set,
                                  target_polarity):
            num_paths += 1
        #for path in _find_sources_with_paths(self.get_im(), obj_obs.name,
        #                                     input_rule_set, target_polarity):
        #    num_paths += 1
        if num_paths > 0:
            return True
        else:
            return False
示例#9
0
    def get_im(self, force_update=False):
        """Get the influence map for the model, generating it if necessary.

        Parameters
        ----------
        force_update : bool
            Whether to generate the influence map when the function is called.
            If False, returns the previously generated influence map if
            available. Defaults to True.

        Returns
        -------
        networkx MultiDiGraph object containing the influence map.
            The influence map can be rendered as a pdf using the dot layout
            program as follows::

                im_agraph = nx.nx_agraph.to_agraph(influence_map)
                im_agraph.draw('influence_map.pdf', prog='dot')
        """
        if self._im and not force_update:
            return self._im
        if not self.model:
            raise Exception("Cannot get influence map if there is no model.")

        def add_obs_for_agents(main_agent, ref_agents=None):
            if ref_agents:
                all_agents = [main_agent] + ref_agents
            else:
                all_agents = [main_agent]
            ag_to_obj_mps = self.get_all_mps(all_agents, mapping=True)
            if all([not v for v in ag_to_obj_mps.values()]):
                logger.debug('No monomer patterns found in model for agents %s'
                             ', skipping' % all_agents)
                return
            obs_nodes = NodesContainer(main_agent, ref_agents)
            main_obs_set = set()
            ref_obs_set = set()
            for agent in ag_to_obj_mps:
                for obj_mp in ag_to_obj_mps[agent]:
                    obs_name = _monomer_pattern_label(obj_mp) + '_obs'
                    self.obs_to_agents[obs_name] = agent
                    # Add the observable
                    obj_obs = Observable(obs_name, obj_mp, _export=False)
                    if agent.matches(main_agent):
                        main_obs_set.add(obs_name)
                    else:
                        ref_obs_set.add(obs_name)
                    try:
                        self.model.add_component(obj_obs)
                        self.model.add_annotation(
                            Annotation(obs_name, agent.name,
                                       'from_indra_agent'))
                    except ComponentDuplicateNameError as e:
                        pass
            obs_nodes.main_interm = main_obs_set
            obs_nodes.ref_interm = ref_obs_set
            return obs_nodes

        # Create observables for all statements to check, and add to model
        # Remove any existing observables in the model
        self.model.observables = ComponentSet([])
        for stmt in self.statements:
            # Generate observables for Modification statements
            if isinstance(stmt, Modification) or \
               isinstance(stmt, SelfModification):
                # If the statement is a regular Mod, the target is stmt.sub
                if isinstance(stmt, Modification):
                    sub = stmt.sub
                # If it's a SelfMod, the target is stmt.enz
                elif isinstance(stmt, SelfModification):
                    sub = stmt.enz
                # Add the mod for the agent
                if sub is None:
                    self.stmt_to_obs[stmt] = NodesContainer(None)
                else:
                    mod_condition_name = modclass_to_modtype[stmt.__class__]
                    if isinstance(stmt, RemoveModification):
                        mod_condition_name = modtype_to_inverse[
                            mod_condition_name]
                    # Add modification to substrate agent
                    modified_sub = _add_modification_to_agent(
                        sub, mod_condition_name, stmt.residue, stmt.position)
                    # Get all refinements of substrate agent
                    ref_subs = self.get_refinements(modified_sub)
                    obs_nodes = add_obs_for_agents(modified_sub, ref_subs)
                    # Associate this statement with this observable
                    self.stmt_to_obs[stmt] = obs_nodes
            # Generate observables for Activation/Inhibition statements
            elif isinstance(stmt, RegulateActivity):
                if stmt.obj is None:
                    self.stmt_to_obs[stmt] = NodesContainer(None)
                else:
                    # Add activity to object agent
                    regulated_obj = _add_activity_to_agent(
                        stmt.obj, stmt.obj_activity, stmt.is_activation)
                    # Get all refinements of object agent
                    ref_objs = self.get_refinements(stmt.obj)
                    obs_nodes = add_obs_for_agents(regulated_obj, ref_objs)
                    # Associate this statement with this observable
                    self.stmt_to_obs[stmt] = obs_nodes
            elif isinstance(stmt, RegulateAmount):
                if stmt.obj is None:
                    self.stmt_to_obs[stmt] = NodesContainer(None)
                else:
                    # Get all refinements of object agent
                    ref_objs = self.get_refinements(stmt.obj)
                    obs_nodes = add_obs_for_agents(stmt.obj, ref_objs)
                    self.stmt_to_obs[stmt] = obs_nodes
            elif isinstance(stmt, Influence):
                if stmt.obj is None:
                    self.stmt_to_obs[stmt] = NodesContainer(None)
                else:
                    # Get all refinements of object agent
                    ref_objs = self.get_refinements(stmt.obj)
                    concepts = [obj.concept for obj in ref_objs]
                    obs_nodes = add_obs_for_agents(stmt.obj.concept, concepts)
                    self.stmt_to_obs[stmt] = obs_nodes
        # Add observables for each agent
        for ag in self.agent_obs:
            obs_nodes = add_obs_for_agents(ag)
            self.agent_to_obs[ag] = obs_nodes

        logger.info("Generating influence map")
        self._im = self.generate_im(self.model)
        # self._im.is_multigraph = lambda: False
        # Now, for every rule in the model, check if there are any observables
        # downstream; alternatively, for every observable in the model, get a
        # list of rules.
        # We'll need the dictionary to check if nodes are observables
        node_attributes = nx.get_node_attributes(self._im, 'node_type')
        for rule in self.model.rules:
            obs_list = []
            # Get successors of the rule node
            for neighb in self._im.neighbors(rule.name):
                # Check if the node is an observable
                if node_attributes[neighb] != 'variable':
                    continue
                # Get the edge and check the polarity
                edge_sign = _get_edge_sign(self._im, (rule.name, neighb))
                obs_list.append((neighb, edge_sign))
            self.rule_obs_dict[rule.name] = obs_list
        return self._im