Source code for indra.assemblers.pysb_assembler

from __future__ import absolute_import, print_function, unicode_literals
from builtins import dict, str
import re
import logging
import itertools
from indra.util import fast_deepcopy

from pysb import (Model, Monomer, Parameter, Expression, Observable, Rule,
        Annotation, ComponentDuplicateNameError, ComplexPattern,
        ReactionPattern, ANY, WILD, InvalidInitialConditionError)
from pysb.core import SelfExporter
import pysb.export

from indra import statements as ist
from indra.databases import context_client, get_identifiers_url
from indra.preassembler.hierarchy_manager import entity_hierarchy as enth
from indra.tools.expand_families import _agent_from_uri

# Python 2
try:
    basestring
# Python 3
except:
    basestring = str

logger = logging.getLogger('pysb_assembler')

SelfExporter.do_export = False

# Here we define the types of INDRA statements that are meant to be
# assembled using the PySB assembler. If a type of statement appears
# in this list then we require that there is at least one default
# policy implemented to assemble that type of statement.
statement_whitelist = [ist.Modification, ist.SelfModification, ist.Complex,
                       ist.RegulateActivity, ist.ActiveForm,
                       ist.Gef, ist.Gap, ist.Translocation,
                       ist.IncreaseAmount, ist.DecreaseAmount,
                       ist.Conversion]

def _n(name):
    """Return valid PySB name."""
    n = name.encode('ascii', errors='ignore').decode('ascii')
    n = re.sub('[^A-Za-z0-9_]', '_', n)
    n = re.sub(r'(^[0-9].*)', r'p\1', n)
    return n

def _is_whitelisted(stmt):
    """Return True if the statement type is in the whitelist."""
    for s in statement_whitelist:
        if isinstance(stmt, s):
            return True
    return False

# BaseAgent classes ####################################################
class _BaseAgentSet(object):
    """Container for a dict of BaseAgents with their names as keys."""
    def __init__(self):
        self.agents = {}

    def get_create_base_agent(self, agent):
        """Return base agent with given name, creating it if needed."""
        try:
            base_agent = self.agents[_n(agent.name)]
        except KeyError:
            base_agent = _BaseAgent(_n(agent.name))
            self.agents[_n(agent.name)] = base_agent

        # Handle bound conditions
        for bc in agent.bound_conditions:
            bound_base_agent = self.get_create_base_agent(bc.agent)
            bound_base_agent.create_site(get_binding_site_name(agent))
            base_agent.create_site(get_binding_site_name(bc.agent))

        # Handle modification conditions
        for mc in agent.mods:
            base_agent.create_mod_site(mc)

        # Handle mutation conditions
        for mc in agent.mutations:
            res_from = mc.residue_from if mc.residue_from else 'mut'
            res_to = mc.residue_to if mc.residue_to else 'X'
            if mc.position is None:
                mut_site_name = res_from
            else:
                mut_site_name = res_from + mc.position

            base_agent.create_site(mut_site_name, states=['WT', res_to])

        # Handle location condition
        if agent.location is not None:
            base_agent.create_site('loc', [_n(agent.location)])

        # Handle activity
        if agent.activity is not None:
            site_name = agent.activity.activity_type
            base_agent.create_site(site_name, ['inactive', 'active'])

        # There might be overwrites here
        for db_name, db_ref in agent.db_refs.items():
            base_agent.db_refs[db_name] = db_ref

        return base_agent

    def items(self):
        """Return items for the set of BaseAgents that this class wraps.
        """
        return self.agents.items()

    def __getitem__(self, name):
        return self.agents[name]


class _BaseAgent(object):
    """A BaseAgent aggregates the global properties of an Agent.

    The BaseAgent class aggregates the name, sites, site states, active forms,
    inactive forms and database references of Agents from individual INDRA
    Statements. This allows the PySB Assembler to correctly assemble the
    Monomer signatures in the model.
    """

    def __init__(self, name):
        self.name = name
        self.sites = []
        self.site_states = {}
        self.site_annotations = []
        # The list of site/state configurations that lead to this agent
        # being active (where the agent is currently assumed to have only
        # one type of activity)
        self.active_forms = []
        self.activity_types = []
        self.inactive_forms = []
        self.db_refs = {}

    def create_site(self, site, states=None):
        """Create a new site on an agent if it doesn't already exist."""
        if site not in self.sites:
            self.sites.append(site)
        if states is not None:
            self.site_states.setdefault(site, [])
            try:
                states = list(states)
            except TypeError:
                return
            self.add_site_states(site, states)

    def create_mod_site(self, mc):
        """Create modification site for the BaseAgent from a ModCondition."""
        site_name = get_mod_site_name(mc.mod_type,
                                      mc.residue, mc.position)
        (unmod_site_state, mod_site_state) = states[mc.mod_type]
        self.create_site(site_name, (unmod_site_state, mod_site_state))
        site_anns = [Annotation((site_name, mod_site_state), mc.mod_type,
                                'is_modification')]
        if mc.residue:
            site_anns.append(Annotation(site_name, mc.residue, 'is_residue'))
        if mc.position:
            site_anns.append(Annotation(site_name, mc.position, 'is_position'))
        self.site_annotations += site_anns

    def add_site_states(self, site, states):
        """Create new states on an agent site if the state doesn't exist."""
        for state in states:
            if state not in self.site_states[site]:
                self.site_states[site].append(state)

    def add_activity_form(self, activity_pattern, is_active):
        """Adds the pattern as an active or inactive form to an Agent.

        Parameters
        ----------
        activity_pattern : dict
            A dictionary of site names and their states.
        is_active : bool
            Is True if the given pattern corresponds to an active state.
        """
        if is_active:
            if activity_pattern not in self.active_forms:
                self.active_forms.append(activity_pattern)
        else:
            if activity_pattern not in self.inactive_forms:
                self.inactive_forms.append(activity_pattern)

    def add_activity_type(self, activity_type):
        """Adds an activity type to an Agent.

        Parameters
        ----------
        activity_type : str
            The type of activity to add such as 'activity', 'kinase',
            'gtpbound'
        """
        if activity_type not in self.activity_types:
            self.activity_types.append(activity_type)

# Site/state information ###############################################

abbrevs = {
    'phosphorylation': 'phospho',
    'ubiquitination': 'ub',
    'farnesylation': 'farnesyl',
    'hydroxylation': 'hydroxyl',
    'acetylation': 'acetyl',
    'sumoylation': 'sumo',
    'glycosylation': 'glycosyl',
    'methylation': 'methyl',
    'ribosylation': 'ribosyl',
    'geranylgeranylation': 'geranylgeranyl',
    'palmitoylation': 'palmitoyl',
    'myristoylation': 'myristoyl',
    'modification': 'mod',
}

states = {
    'phosphorylation': ['u', 'p'],
    'ubiquitination': ['n', 'y'],
    'farnesylation': ['n', 'y'],
    'hydroxylation': ['n', 'y'],
    'acetylation': ['n', 'y'],
    'sumoylation': ['n', 'y'],
    'glycosylation': ['n', 'y'],
    'methylation': ['n', 'y'],
    'geranylgeranylation': ['n', 'y'],
    'palmitoylation': ['n', 'y'],
    'myristoylation': ['n', 'y'],
    'ribosylation': ['n', 'y'],
    'modification': ['n', 'y'],
}

mod_acttype_map = {
    ist.Phosphorylation: 'kinase',
    ist.Dephosphorylation: 'phosphatase',
    ist.Hydroxylation: 'catalytic',
    ist.Dehydroxylation: 'catalytic',
    ist.Sumoylation: 'catalytic',
    ist.Desumoylation: 'catalytic',
    ist.Acetylation: 'catalytic',
    ist.Deacetylation: 'catalytic',
    ist.Glycosylation: 'catalytic',
    ist.Deglycosylation: 'catalytic',
    ist.Ribosylation: 'catalytic',
    ist.Deribosylation: 'catalytic',
    ist.Ubiquitination: 'catalytic',
    ist.Deubiquitination: 'catalytic',
    ist.Farnesylation: 'catalytic',
    ist.Defarnesylation: 'catalytic',
    ist.Palmitoylation: 'catalytic',
    ist.Depalmitoylation: 'catalytic',
    ist.Myristoylation: 'catalytic',
    ist.Demyristoylation: 'catalytic',
    ist.Geranylgeranylation: 'catalytic',
    ist.Degeranylgeranylation: 'catalytic',
    ist.Methylation: 'catalytic',
    ist.Demethylation: 'catalytic',
}


[docs]def get_binding_site_name(agent): """Return a binding site name from a given agent.""" # Try to construct a binding site name based on parent grounding = agent.get_grounding() if grounding != (None, None): uri = enth.get_uri(grounding[0], grounding[1]) # Get highest level parents in hierarchy parents = enth.get_parents(uri, 'top') if parents: # Choose the first parent if there are more than one parent_uri = sorted(list(parents))[0] parent_agent = _agent_from_uri(parent_uri) binding_site = _n(parent_agent.name).lower() return binding_site # Fall back to Agent's own name if one from parent can't be constructed binding_site = _n(agent.name).lower()
return binding_site
[docs]def get_mod_site_name(mod_type, residue, position): """Return site names for a modification.""" names = [] if residue is None: mod_str = abbrevs[mod_type] else: mod_str = residue mod_pos = position if position is not None else '' name = ('%s%s' % (mod_str, mod_pos))
return name # PySB model elements ##################################################
[docs]def get_agent_rule_str(agent): """Construct a string from an Agent as part of a PySB rule name.""" rule_str_list = [_n(agent.name)] for mod in agent.mods: mstr = abbrevs[mod.mod_type] if mod.residue is not None: mstr += mod.residue if mod.position is not None: mstr += mod.position rule_str_list.append('%s' % mstr) for mut in agent.mutations: res_from = mut.residue_from if mut.residue_from else 'mut' res_to = mut.residue_to if mut.residue_to else 'X' if mut.position is None: mut_site_name = res_from else: mut_site_name = res_from + mut.position mstr = mut_site_name + res_to rule_str_list.append(mstr) if agent.bound_conditions: for b in agent.bound_conditions: if b.is_bound: rule_str_list.append(_n(b.agent.name)) else: rule_str_list.append('n' + _n(b.agent.name)) if agent.location is not None: rule_str_list.append(_n(agent.location)) rule_str = '_'.join(rule_str_list)
return rule_str
[docs]def add_rule_to_model(model, rule, annotations=None): """Add a Rule to a PySB model and handle duplicate component errors.""" try: model.add_component(rule) # If the rule was actually added, also add the annotations if annotations: model.annotations += annotations # If this rule is already in the model, issue a warning and continue except ComponentDuplicateNameError: msg = "Rule %s already in model! Skipping." % rule.name
logger.warning(msg)
[docs]def get_create_parameter(model, name, value, unique=True): """Return parameter with given name, creating it if needed. If unique is false and the parameter exists, the value is not changed; if it does not exist, it will be created. If unique is true then upon conflict a number is added to the end of the parameter name. """ norm_name = _n(name) parameter = model.parameters.get(norm_name) if not unique and parameter is not None: return parameter if unique: pnum = 1 while True: pname = norm_name + '_%d' % pnum if model.parameters.get(pname) is None: break pnum += 1 else: pname = norm_name parameter = Parameter(pname, value) model.add_component(parameter)
return parameter
[docs]def get_uncond_agent(agent): """Construct the unconditional state of an Agent. The unconditional Agent is a copy of the original agent but without any bound conditions and modification conditions. Mutation conditions, however, are preserved since they are static. """ agent_uncond = ist.Agent(_n(agent.name), mutations=agent.mutations)
return agent_uncond
[docs]def grounded_monomer_patterns(model, agent): """Get monomer patterns for the agent accounting for grounding information. """ # Iterate over all model annotations to identify the monomer associated # with this agent monomer = None for ann in model.annotations: if monomer: break if not ann.predicate == 'is': continue if not isinstance(ann.subject, Monomer): continue (ns, id) = parse_identifiers_url(ann.object) if ns is None and id is None: continue # We now have an identifiers.org namespace/ID for a given monomer; # we check to see if there is a matching identifier in the db_refs # for this agent for db_ns, db_id in agent.db_refs.items(): # We've found a match! Return first match # FIXME Could also update this to check for alternative # FIXME matches, or make sure that all grounding IDs match, # FIXME etc. if db_ns == ns and db_id == id: monomer = ann.subject break # We looked at all the annotations in the model and didn't find a # match if monomer is None: logger.info('No monomer found corresponding to agent %s' % agent) return # Now that we have a monomer for the agent, look for site/state # combinations corresponding to the state of the agent. For every one of # the modifications specified in the agent signature, check to see if it # can be satisfied based on the agent's annotations. For every one we find # that is consistent, we yield it--there may be more than one. # FIXME # Create a list of tuples, each one representing the site conditions # that can satisfy a particular agent condition. Each entry in the list # will contain a list of dicts associated with a particular mod/activity # condition. Each dict will represent a site/state combination satisfying # the constraints imposed by that mod/activity condition. sc_list = [] for mod in agent.mods: # Find all site/state combinations that have the appropriate # modification type # As we iterate, build up a dict identifying the annotations of # particular sites mod_sites = {} res_sites = set([]) pos_sites = set([]) for ann in monomer.site_annotations: # Don't forget to handle Nones! if ann.predicate == 'is_modification' and \ ann.object == mod.mod_type: site_state = ann.subject assert isinstance(site_state, tuple) assert len(site_state) == 2 mod_sites[site_state[0]] = site_state[1] elif ann.predicate == 'is_residue' and \ ann.object == mod.residue: res_sites.add(ann.subject) elif ann.predicate == 'is_position' and \ ann.object == mod.position: pos_sites.add(ann.subject) # If the residue field of the agent is specified, viable_sites = set(mod_sites.keys()) if mod.residue is not None: viable_sites = viable_sites.intersection(res_sites) if mod.position is not None: viable_sites = viable_sites.intersection(pos_sites) # If there are no viable sites annotated in the model matching the # available info in the mod condition, then we won't be able to # satisfy the conditions on this agent if not viable_sites: return # Otherwise, update the # If there are any sites left after we subject them to residue # and position constraints, then return the relevant monomer patterns! pattern_list = [] for site_name in viable_sites: pattern_list.append({site_name: (mod_sites[site_name], WILD)}) sc_list.append(pattern_list) # Now check for monomer patterns satisfying the agent's activity condition if agent.activity: # Iterate through annotations with this monomer as the subject # and a has_active_pattern or has_inactive_pattern relationship # FIXME: Currently activity type is not annotated/checked # FIXME act_type = agent.activity.activity_type rel_type = 'has_active_pattern' if agent.activity.is_active \ else 'has_inactive_pattern' active_form_list = [] for ann in model.annotations: if ann.subject == monomer and ann.predicate == rel_type: # The annotation object contains the active/inactive pattern active_form_list.append(ann.object) sc_list.append(active_form_list) # Now that we've got a list of conditions for pattern_combo in itertools.product(*sc_list): mp_sc = {} for pattern in pattern_combo: mp_sc.update(pattern) if mp_sc: yield monomer(**mp_sc) if not sc_list:
yield monomer() def rules_with_annotation(model, monomer_name, predicate): rules = [] for ann in model.annotations: if not ann.predicate == predicate: continue if ann.object == monomer_name: rules.append(model.rules[ann.subject]) return rules
[docs]def get_monomer_pattern(model, agent, extra_fields=None): """Construct a PySB MonomerPattern from an Agent.""" try: monomer = model.monomers[_n(agent.name)] except KeyError as e: logger.warning('Monomer with name %s not found in model' % _n(agent.name)) return None # Get the agent site pattern pattern = get_site_pattern(agent) if extra_fields is not None: for k, v in extra_fields.items(): pattern[k] = v # If a model is given, return the Monomer with the generated pattern, # otherwise just return the pattern try: monomer_pattern = monomer(**pattern) except Exception as e: logger.info("Invalid site pattern %s for monomer %s" % (pattern, monomer)) return None
return monomer_pattern
[docs]def get_site_pattern(agent): """Construct a dictionary of Monomer site states from an Agent. This crates the mapping to the associated PySB monomer from an INDRA Agent object.""" pattern = {} # Handle bound conditions for bc in agent.bound_conditions: # Here we make the assumption that the binding site # is simply named after the binding partner if bc.is_bound: pattern[get_binding_site_name(bc.agent)] = ANY else: pattern[get_binding_site_name(bc.agent)] = None # Handle modifications for mod in agent.mods: mod_site_str = abbrevs[mod.mod_type] if mod.residue is not None: mod_site_str = mod.residue mod_pos_str = mod.position if mod.position is not None else '' mod_site = ('%s%s' % (mod_site_str, mod_pos_str)) site_states = states[mod.mod_type] if mod.is_modified: pattern[mod_site] = (site_states[1], WILD) else: pattern[mod_site] = (site_states[0], WILD) # Handle mutations for mc in agent.mutations: res_from = mc.residue_from if mc.residue_from else 'mut' res_to = mc.residue_to if mc.residue_to else 'X' if mc.position is None: mut_site_name = res_from else: mut_site_name = res_from + mc.position pattern[mut_site_name] = res_to # Handle location if agent.location is not None: pattern['loc'] = _n(agent.location) # Handle activity if agent.activity is not None: active_site_name = agent.activity.activity_type if agent.activity.is_active: active_site_state = 'active' else: active_site_state = 'inactive' pattern[active_site_name] = active_site_state
return pattern
[docs]def set_base_initial_condition(model, monomer, value): """Set an initial condition for a monomer in its 'default' state.""" # Build up monomer pattern dict sites_dict = {} for site in monomer.sites: if site in monomer.site_states: sites_dict[site] = monomer.site_states[site][0] else: sites_dict[site] = None mp = monomer(**sites_dict) pname = monomer.name + '_0' try: p = model.parameters[pname] p.value = value except KeyError: p = Parameter(pname, value) model.add_component(p)
model.initial(mp, p)
[docs]def set_extended_initial_condition(model, monomer=None, value=0): """Set an initial condition for monomers in "modified" state. This is useful when using downstream analysis that relies on reactions being active in the model. One example is BioNetGen-based reaction network diagram generation. """ if not monomer: monomers = model.monomers else: monomers = [monomer] for monomer in monomers: # Build up monomer pattern dict for default state sites_dict = {} for site in monomer.sites: if site in monomer.site_states: sites_dict[site] = monomer.site_states[site][-1] else: sites_dict[site] = None mp = monomer(**sites_dict) pname = monomer.name + '_0_mod' try: p = model.parameters[pname] p.value = value except KeyError: p = Parameter(pname, value) model.add_component(p) try: model.initial(mp, p) except InvalidInitialConditionError:
pass
[docs]def get_annotation(component, db_name, db_ref): """Construct model Annotations for each component. Annotation formats follow guidelines at http://identifiers.org/. """ url = get_identifiers_url(db_name, db_ref) if not url: return None subj = component ann = Annotation(subj, url, 'is')
return ann
[docs]def parse_identifiers_url(url): """Parse an identifiers.org URL into (namespace, ID) tuple.""" url_pattern = 'http://identifiers.org/([A-Za-z]+)/([A-Za-z0-9:]+)' match = re.match(url_pattern, url) if match is not None: g = match.groups() if not len(g) == 2: return (None, None) ns_map = {'hgnc': 'HGNC', 'uniprot': 'UP', 'chebi':'CHEBI', 'interpro':'IP', 'pfam':'XFAM'} ns = g[0] id = g[1] if not ns in ns_map.keys(): return (None, None) if ns == 'hgnc': if id.startswith('HGNC:'): id = id[5:] else: logger.warning('HGNC URL missing "HGNC:" prefix: %s' % url) return (None, None) indra_ns = ns_map[ns] return (indra_ns, id)
return (None, None) # PysbAssembler #######################################################
[docs]class UnknownPolicyError(Exception):
pass
[docs]class PysbAssembler(object): """Assembler creating a PySB model from a set of INDRA Statements. Parameters ---------- policies : Optional[Union[str, dict]] A string or dictionary that defines one or more assembly policies. If policies is a string, it defines a global assembly policy that applies to all Statement types. Example: one_step, interactions_only A dictionary of policies has keys corresponding to Statement types and values to the policy to be applied to that type of Statement. For Statement types whose policy is undefined, the 'default' policy is applied. Example: {'Phosphorylation': 'two_step'} Attributes ---------- policies : dict A dictionary of policies that defines assembly policies for Statement types. It is assigned in the constructor. statements : list A list of INDRA statements to be assembled. model : pysb.Model A PySB model object that is assembled by this class. agent_set : _BaseAgentSet A set of BaseAgents used during the assembly process. """ def __init__(self, policies=None): self.statements = [] self.agent_set = None self.model = None self.default_initial_amount = 10000.0 if policies is None: self.policies = {'other': 'default'} elif isinstance(policies, basestring): self.policies = {'other': policies} else: self.policies = {'other': 'default'} self.policies.update(policies)
[docs] def add_statements(self, stmts): """Add INDRA Statements to the assembler's list of statements. Parameters ---------- stmts : list[indra.statements.Statement] A list of :py:class:`indra.statements.Statement` to be added to the statement list of the assembler. """
self.statements += stmts
[docs] def make_model(self, policies=None, initial_conditions=True, reverse_effects=False): """Assemble the PySB model from the collected INDRA Statements. This method assembles a PySB model from the set of INDRA Statements. The assembled model is both returned and set as the assembler's model argument. Parameters ---------- policies : Optional[Union[str, dict]] A string or dictionary of policies, as defined in :py:class:`indra.assemblers.PysbAssembler`. This set of policies locally supersedes the default setting in the assembler. This is useful when this function is called multiple times with different policies. initial_conditions : Optional[bool] If True, default initial conditions are generated for the Monomers in the model. Returns ------- model : pysb.Model The assembled PySB model object. """ ppa = PysbPreassembler(self.statements) ppa.replace_activities() if reverse_effects: ppa.add_reverse_effects() self.statements = ppa.statements # Set local policies for this make_model call that overwrite # the global policies of the PySB assembler if policies is not None: global_policies = self.policies if isinstance(policies, basestring): local_policies = {'other': policies} else: local_policies = {'other': 'default'} local_policies.update(policies) self.policies = local_policies self.model = Model() self.agent_set = _BaseAgentSet() # Collect information about the monomers/self.agent_set from the # statements self._monomers() # Add the monomers to the model based on our BaseAgentSet for agent_name, agent in self.agent_set.items(): m = Monomer(_n(agent_name), agent.sites, agent.site_states) m.site_annotations = agent.site_annotations self.model.add_component(m) for db_name, db_ref in agent.db_refs.items(): a = get_annotation(m, db_name, db_ref) if a is not None: self.model.add_annotation(a) # Iterate over the active_forms for af in agent.active_forms: self.model.add_annotation(Annotation(m, af, 'has_active_pattern')) for iaf in agent.inactive_forms: self.model.add_annotation(Annotation(m, iaf, 'has_inactive_pattern')) for at in agent.activity_types: act_site_cond = {at: 'active'} self.model.add_annotation(Annotation(m, act_site_cond, 'has_active_pattern')) inact_site_cond = {at: 'inactive'} self.model.add_annotation(Annotation(m, inact_site_cond, 'has_inactive_pattern')) # Iterate over the statements to generate rules self._assemble() # Add initial conditions if initial_conditions: self.add_default_initial_conditions() # If local policies were applied, revert to the global one if policies is not None: self.policies = global_policies
return self.model
[docs] def add_default_initial_conditions(self, value=None): """Set default initial conditions in the PySB model. Parameters ---------- value : Optional[float] Optionally a value can be supplied which will be the initial amount applied. Otherwise a built-in default is used. """ if value is not None: try: value_num = float(value) except ValueError: logger.error('Invalid initial condition value.') return else: value_num = self.default_initial_amount if self.model is None: return for m in self.model.monomers:
set_base_initial_condition(self.model, m, value_num)
[docs] def set_context(self, cell_type): """Set protein expression data as initial conditions. This method uses :py:mod:`indra.databases.context_client` to get protein expression levels for a given cell type and set initial conditions for Monomers in the model accordingly. Parameters ---------- cell_type : str Cell type name for which expression levels are queried. The cell type name follows the CCLE database conventions. Example: LOXIMVI_SKIN, BT20_BREAST """ if self.model is None: return monomer_names = [m.name for m in self.model.monomers] res = context_client.get_protein_expression(monomer_names, [cell_type]) amounts = res.get(cell_type) if not amounts: logger.warning('Could not get context for %s cell type.' % cell_type) self.add_default_initial_conditions() return monomers_found = [] monomers_notfound = [] for m in self.model.monomers: init = amounts.get(m.name) if init is not None: init_round = round(init) set_base_initial_condition(self.model, m, init_round) monomers_found.append(m.name) else: set_base_initial_condition(self.model, m, self.default_initial_amount) monomers_notfound.append(m.name) logger.info('Monomers set to %s context' % cell_type) logger.info('--------------------------------') for m in monomers_found: logger.info('%s' % m) if monomers_notfound: logger.info('') logger.info('Monomers not found in %s context' % cell_type) logger.info('-----------------------------------------') for m in monomers_notfound:
logger.info('%s' % m)
[docs] def print_model(self): """Print the assembled model as a PySB program string. This function is useful when the model needs to be passed as a string to another component. """ model_str = pysb.export.export(self.model, 'pysb_flat')
return model_str
[docs] def save_model(self, file_name='pysb_model.py'): """Save the assembled model as a PySB program file. Parameters ---------- file_name : Optional[str] The name of the file to save the model program code in. Default: pysb-model.py """ if self.model is not None: model_str = self.print_model() with open(file_name, 'wt') as fh:
fh.write(model_str)
[docs] def export_model(self, format, file_name=None): """Save the assembled model in a modeling formalism other than PySB. For more details on exporting PySB models, see http://pysb.readthedocs.io/en/latest/modules/export/index.html Parameters ---------- format : str The format to export into, for instance "kappa", "bngl", "sbml", "matlab", "mathematica", "potterswheel". See http://pysb.readthedocs.io/en/latest/modules/export/index.html for a list of supported formats. In addition to the formats supported by PySB itself, this method also provides "sbgn" output. file_name : Optional[str] An optional file name to save the exported model into. Returns ------- exp_str : str The exported model string """ # Handle SBGN as special case if format == 'sbgn': exp_str = export_sbgn(self.model) else: try: exp_str = pysb.export.export(self.model, format) except KeyError: logging.error('Unknown export format: %s' % format) return None if file_name: with open(file_name, 'wb') as fh: fh.write(exp_str.encode('utf-8'))
return exp_str
[docs] def save_rst(self, file_name='pysb_model.rst', module_name='pysb_module'): """Save the assembled model as an RST file for literate modeling. Parameters ---------- file_name : Optional[str] The name of the file to save the RST in. Default: pysb_model.rst module_name : Optional[str] The name of the python function defining the module. Default: pysb_module """ if self.model is not None: with open(file_name, 'wt') as fh: fh.write('.. _%s:\n\n' % module_name) fh.write('Module\n======\n\n') fh.write('INDRA-assembled model\n---------------------\n\n') fh.write('::\n\n') model_str = pysb.export.export(self.model, 'pysb_flat') model_str = '\t' + model_str.replace('\n', '\n\t')
fh.write(model_str) def _dispatch(self, stmt, stage, *args): """Construct and call an assembly function. This function constructs the name of the assembly function based on the type of statement, the corresponding policy and the stage of assembly. It then calls that function to perform the assembly task.""" class_name = stmt.__class__.__name__ try: policy = self.policies[class_name] except KeyError: policy = self.policies['other'] func_name = '%s_%s_%s' % (class_name.lower(), stage, policy) func = globals().get(func_name) if func is None: # The specific policy is not implemented for the # given statement type. # We try to apply a default policy next. func_name = '%s_%s_default' % (class_name.lower(), stage) func = globals().get(func_name) if func is None: # The given statement type doesn't have a default # policy. raise UnknownPolicyError('%s function %s not defined' % (stage, func_name)) return func(stmt, *args) def _monomers(self): """Calls the appropriate monomers method based on policies.""" for stmt in self.statements: if _is_whitelisted(stmt): self._dispatch(stmt, 'monomers', self.agent_set) def _assemble(self): """Calls the appropriate assemble method based on policies.""" for stmt in self.statements: if _is_whitelisted(stmt):
self._dispatch(stmt, 'assemble', self.model, self.agent_set) # COMPLEX ############################################################
[docs]def complex_monomers_one_step(stmt, agent_set): """In this (very simple) implementation, proteins in a complex are each given site names corresponding to each of the other members of the complex (lower case). So the resulting complex can be "fully connected" in that each member can be bound to all the others.""" for i, member in enumerate(stmt.members): gene_mono = agent_set.get_create_base_agent(member) # Specify a binding site for each of the other complex members # bp = abbreviation for "binding partner" for j, bp in enumerate(stmt.members): # The protein doesn't bind to itstmt! if i == j: continue
gene_mono.create_site(get_binding_site_name(bp)) complex_monomers_default = complex_monomers_one_step def complex_assemble_one_step(stmt, model, agent_set): pairs = itertools.combinations(stmt.members, 2) for pair in pairs: agent1 = pair[0] agent2 = pair[1] param_name = agent1.name[0].lower() + \ agent2.name[0].lower() + '_bind' kf_bind = get_create_parameter(model, 'kf_' + param_name, 1e-6) kr_bind = get_create_parameter(model, 'kr_' + param_name, 1e-1) # Make a rule name rule_name = '_'.join([get_agent_rule_str(m) for m in pair]) rule_name += '_bind' # Construct full patterns of each agent with conditions agent1_pattern = get_monomer_pattern(model, agent1) agent2_pattern = get_monomer_pattern(model, agent2) agent1_bs = get_binding_site_name(agent2) agent2_bs = get_binding_site_name(agent1) r = Rule(rule_name, agent1_pattern(**{agent1_bs: None}) + \ agent2_pattern(**{agent2_bs: None}) >> agent1_pattern(**{agent1_bs: 1}) % \ agent2_pattern(**{agent2_bs: 1}), kf_bind) anns = [Annotation(rule_name, agent1_pattern.monomer.name, 'rule_has_subject'), Annotation(rule_name, agent1_pattern.monomer.name, 'rule_has_object'), Annotation(rule_name, agent2_pattern.monomer.name, 'rule_has_subject'), Annotation(rule_name, agent2_pattern.monomer.name, 'rule_has_object'), Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # In reverse reaction, assume that dissocition is unconditional agent1_uncond = get_uncond_agent(agent1) agent1_rule_str = get_agent_rule_str(agent1_uncond) monomer1_uncond = get_monomer_pattern(model, agent1_uncond) agent2_uncond = get_uncond_agent(agent2) agent2_rule_str = get_agent_rule_str(agent2_uncond) monomer2_uncond = get_monomer_pattern(model, agent2_uncond) rule_name = '%s_%s_dissociate' % (agent1_rule_str, agent2_rule_str) r = Rule(rule_name, monomer1_uncond(**{agent1_bs: 1}) % \ monomer2_uncond(**{agent2_bs: 1}) >> monomer1_uncond(**{agent1_bs: None}) + \ monomer2_uncond(**{agent2_bs: None}), kr_bind) anns = [Annotation(rule_name, monomer1_uncond.monomer.name, 'rule_has_subject'), Annotation(rule_name, monomer1_uncond.monomer.name, 'rule_has_object'), Annotation(rule_name, monomer2_uncond.monomer.name, 'rule_has_subject'), Annotation(rule_name, monomer2_uncond.monomer.name, 'rule_has_object'), Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) def complex_assemble_multi_way(stmt, model, agent_set): # Get the rate parameter abbr_name = ''.join([m.name[0].lower() for m in stmt.members]) kf_bind = get_create_parameter(model, 'kf_' + abbr_name + '_bind', 1e-6) kr_bind = get_create_parameter(model, 'kr_' + abbr_name + '_bind', 1e-1) # Make a rule name rule_name = '_'.join([get_agent_rule_str(m) for m in stmt.members]) rule_name += '_bind' # Initialize the left and right-hand sides of the rule lhs = ReactionPattern([]) rhs = ComplexPattern([], None) # We need a unique bond index for each pair of proteins in the # complex, resulting in n(n-1)/2 bond indices for a n-member complex. # We keep track of the bond indices using the bond_indices dict, # which maps each unique pair of members to a bond index. bond_indices = {} bond_counter = 1 for i, member in enumerate(stmt.members): gene_name = member.name mono = model.monomers[gene_name] # Specify free and bound states for binding sites for each of # the other complex members # (bp = abbreviation for "binding partner") left_site_dict = {} right_site_dict = {} for j, bp in enumerate(stmt.members): bp_bs = get_binding_site_name(bp) # The protein doesn't bind to itstmt! if i == j: continue # Check to see if we've already created a bond index for these # two binding partners bp_set = frozenset([i, j]) if bp_set in bond_indices: bond_ix = bond_indices[bp_set] # If we haven't see this pair of proteins yet, add a new bond # index to the dict else: bond_ix = bond_counter bond_indices[bp_set] = bond_ix bond_counter += 1 # Fill in the entries for the site dicts left_site_dict[bp_bs] = None right_site_dict[bp_bs] = bond_ix # Add the pattern for the modifications of the member for mod in member.mods: if mod.residue is None: mod_str = abbrevs[mod.mod_type] else: mod_str = mod.residue mod_pos = mod.position if mod.position is not None else '' mod_site = ('%s%s' % (mod_str, mod_pos)) left_site_dict[mod_site] = states[mod.mod_type][1] right_site_dict[mod_site] = states[mod.mod_type][1] # Add the pattern for the member being bound for bc in member.bound_conditions: bound_name = _n(bc.agent.name) bound_bs = get_binding_site_name(bc.agent) gene_bs = get_binding_site_name(member) if bc.is_bound: bound = model.monomers[bound_name] left_site_dict[bound_bs] = \ bond_counter right_site_dict[bound_bs] = \ bond_counter left_pattern = mono(**left_site_dict) % \ bound(**{gene_bs: bond_counter}) right_pattern = mono(**right_site_dict) % \ bound(**{gene_bs: bond_counter}) bond_counter += 1 else: left_site_dict[bound_bs] = None right_site_dict[bound_bs] = None left_pattern = mono(**left_site_dict) right_pattern = mono(**right_site_dict) else: left_pattern = mono(**left_site_dict) right_pattern = mono(**right_site_dict) # Build up the left- and right-hand sides of the rule from # monomer patterns with the appropriate site dicts lhs = lhs + left_pattern rhs = rhs % right_pattern # Finally, create the rule and add it to the model rule_fwd = Rule(rule_name + '_fwd', lhs >> rhs, kf_bind) rule_rev = Rule(rule_name + '_rev', rhs >> lhs, kr_bind) anns = [Annotation(rule_fwd.name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, rule_fwd, anns) anns = [Annotation(rule_rev.name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, rule_rev, anns) complex_assemble_default = complex_assemble_one_step # MODIFICATION ################################################### def modification_monomers_interactions_only(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) act_type = mod_acttype_map[stmt.__class__] active_site = act_type enz.create_site(active_site) sub = agent_set.get_create_base_agent(stmt.sub) # See NOTE in monomers_one_step, below mod_condition_name = stmt.__class__.__name__.lower() sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) def modification_monomers_one_step(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) # NOTE: This assumes that a Modification statement will only ever # involve a single phosphorylation site on the substrate (typically # if there is more than one site, they will be parsed into separate # Phosphorylation statements, i.e., phosphorylation is assumed to be # distributive. If this is not the case, this assumption will need to # be revisited. mod_condition_name = stmt.__class__.__name__.lower() sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) def modification_monomers_two_step(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) mod_condition_name = stmt.__class__.__name__.lower() sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) # Create site for binding the substrate enz.create_site(get_binding_site_name(stmt.sub)) sub.create_site(get_binding_site_name(stmt.enz)) def modification_assemble_interactions_only(stmt, model, agent_set): if stmt.enz is None: return kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) kr_bind = get_create_parameter(model, 'kr_bind', 1.0, unique=False) enz = model.monomers[stmt.enz.name] sub = model.monomers[stmt.sub.name] # See NOTE in monomers_one_step mod_condition_name = stmt.__class__.__name__.lower() mod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) rule_name = '%s_%s_%s_%s' % (rule_enz_str, mod_condition_name, rule_sub_str, mod_site) active_site = mod_acttype_map[stmt.__class__] # Create a rule specifying that the substrate binds to the kinase at # its active site lhs = enz(**{active_site: None}) + sub(**{mod_site: None}) rhs = enz(**{active_site: 1}) % sub(**{mod_site: 1}) r_fwd = Rule(rule_name + '_fwd', lhs >> rhs, kf_bind) add_rule_to_model(model, r_fwd) def modification_assemble_one_step(stmt, model, agent_set, rate_law=None): if stmt.enz is None: return mod_condition_name = stmt.__class__.__name__.lower() # See NOTE in monomers_one_step mod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) rule_name = '%s_%s_%s_%s' % \ (rule_enz_str, mod_condition_name, rule_sub_str, mod_site) # Remove pre-set activity flag enz_pattern = get_monomer_pattern(model, stmt.enz) unmod_site_state = states[mod_condition_name][0] mod_site_state = states[mod_condition_name][1] sub_unmod = get_monomer_pattern(model, stmt.sub, extra_fields={mod_site: unmod_site_state}) sub_mod = get_monomer_pattern(model, stmt.sub, extra_fields={mod_site: mod_site_state}) if not rate_law: param_name = 'kf_%s%s_%s' % (stmt.enz.name[0].lower(), stmt.sub.name[0].lower(), mod_condition_name) mod_rate = get_create_parameter(model, param_name, 1e-6) elif rate_law == 'michaelis_menten': # Parameters param_name = ('Km_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_' + mod_condition_name) Km = get_create_parameter(model, param_name, 1e8) param_name = ('kc_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_' + mod_condition_name) kcat = get_create_parameter(model, param_name, 100) # We need an observable for the substrate to use in the rate law sub_obs = Observable(rule_name + '_sub_obs', sub_unmod) model.add_component(sub_obs) # Note that [E0]*[S] is automatically multiplied into this rate # as the product of the reactants therefore they don't appear # in this expression # v = Vmax*[S]/(Km+[S]) = kcat*[E0]*[S]/(Km + [S]) mod_rate = Expression(rule_name + '_rate', kcat / (Km + sub_obs)) model.add_component(mod_rate) r = Rule(rule_name, enz_pattern + sub_unmod >> enz_pattern + sub_mod, mod_rate) anns = [Annotation(rule_name, enz_pattern.monomer.name, 'rule_has_subject'), Annotation(rule_name, sub_unmod.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) def modification_assemble_two_step(stmt, model, agent_set): mod_condition_name = stmt.__class__.__name__.lower() if stmt.enz is None: return sub_bs = get_binding_site_name(stmt.sub) enz_bound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: 1}) enz_unbound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: None}) sub_pattern = get_monomer_pattern(model, stmt.sub) param_name = ('kf_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_bind') kf_bind = get_create_parameter(model, param_name, 1e-6) param_name = ('kr_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_bind') kr_bind = get_create_parameter(model, param_name, 1e-1) param_name = ('kc_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_' + mod_condition_name) kf_mod = get_create_parameter(model, param_name, 100) mod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) enz_bs = get_binding_site_name(stmt.enz) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) unmod_site_state = states[mod_condition_name][0] mod_site_state = states[mod_condition_name][1] rule_name = '%s_%s_bind_%s_%s' % \ (rule_enz_str, mod_condition_name, rule_sub_str, mod_site) r = Rule(rule_name, enz_unbound() + \ sub_pattern(**{mod_site: unmod_site_state, enz_bs: None}) >> enz_bound() % \ sub_pattern(**{mod_site: unmod_site_state, enz_bs: 1}), kf_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) rule_name = '%s_%s_%s_%s' % \ (rule_enz_str, mod_condition_name, rule_sub_str, mod_site) r = Rule(rule_name, enz_bound() % \ sub_pattern(**{mod_site: unmod_site_state, enz_bs: 1}) >> enz_unbound() + \ sub_pattern(**{mod_site: mod_site_state, enz_bs: None}), kf_mod) anns = [Annotation(rule_name, enz_bound.monomer.name, 'rule_has_subject'), Annotation(rule_name, sub_pattern.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) enz_uncond = get_uncond_agent(stmt.enz) enz_rule_str = get_agent_rule_str(enz_uncond) enz_mon_uncond = get_monomer_pattern(model, enz_uncond) sub_uncond = get_uncond_agent(stmt.sub) sub_rule_str = get_agent_rule_str(sub_uncond) sub_mon_uncond = get_monomer_pattern(model, sub_uncond) rule_name = '%s_dissoc_%s' % (enz_rule_str, sub_rule_str) r = Rule(rule_name, enz_mon_uncond(**{sub_bs: 1}) % \ sub_mon_uncond(**{enz_bs: 1}) >> enz_mon_uncond(**{sub_bs: None}) + \ sub_mon_uncond(**{enz_bs: None}), kr_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) modification_monomers_default = modification_monomers_one_step modification_assemble_default = modification_assemble_one_step # PHOSPHORYLATION ################################################### def phosphorylation_monomers_atp_dependent(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) sub.create_mod_site(ist.ModCondition('phosphorylation', stmt.residue, stmt.position)) # Create site for binding the substrate enz.create_site(get_binding_site_name(stmt.sub)) sub.create_site(get_binding_site_name(stmt.enz)) # Make ATP base agent and create binding sites atp = agent_set.get_create_base_agent(ist.Agent('ATP')) atp.create_site('b') enz.create_site('ATP') def phosphorylation_assemble_atp_dependent(stmt, model, agent_set): if stmt.enz is None: return # ATP atp = model.monomers['ATP'] atp_bs = 'ATP' # ATP-bound enzyme enz_atp_bound = get_monomer_pattern(model, stmt.enz, extra_fields={atp_bs: 1}) # ATP-free enzyme enz_atp_unbound = get_monomer_pattern(model, stmt.enz, extra_fields={atp_bs: None}) # Substrate-bound enzyme sub_bs = get_binding_site_name(stmt.sub) enz_sub_bound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: 1}) # Substrte and ATP-bound enzyme enz_sub_atp_bound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: 1, atp_bs: 2}) enz_sub_atp_unbound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: None, atp_bs: None}) # Substrate-free enzyme enz_sub_unbound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: None}) enz_bs = get_binding_site_name(stmt.enz) # Unconditional enzyme enz_uncond = get_uncond_agent(stmt.enz) enz_rule_str = get_agent_rule_str(enz_uncond) enz_mon_uncond = get_monomer_pattern(model, enz_uncond) # Substrate sub_uncond = get_uncond_agent(stmt.sub) sub_rule_str = get_agent_rule_str(sub_uncond) sub_mon_uncond = get_monomer_pattern(model, sub_uncond) sub_pattern = get_monomer_pattern(model, stmt.sub) # Enzyme binding ATP param_name = ('kf_' + stmt.enz.name[0].lower() + '_atp_bind') kf_bind_atp = get_create_parameter(model, param_name, 1e-6) param_name = ('kr_' + stmt.enz.name[0].lower() + '_atp_bind') kr_bind_atp = get_create_parameter(model, param_name, 1.) rule_name = '%s_phospho_bind_atp' % (enz_rule_str) r = Rule(rule_name, enz_atp_unbound() + atp(b=None) >> enz_atp_bound() % atp(b=1), kf_bind_atp) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # Enzyme releasing ATP rule_name = '%s_phospho_dissoc_atp' % (enz_rule_str) r = Rule(rule_name, enz_mon_uncond({atp_bs: 1}) % atp(b=1) >> enz_mon_uncond({atp_bs: None}) + atp(b=None), kr_bind_atp) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # Enzyme binding substrate param_name = ('kf_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_bind') kf_bind = get_create_parameter(model, param_name, 1e-6) param_name = ('kr_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_bind') kr_bind = get_create_parameter(model, param_name, 1e-1) param_name = ('kc_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_phos') kf_phospho = get_create_parameter(model, param_name, 100) phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) rule_name = '%s_phospho_bind_%s_%s' % \ (rule_enz_str, rule_sub_str, phos_site) r = Rule(rule_name, enz_sub_unbound() + \ sub_pattern(**{phos_site: 'u', enz_bs: None}) >> enz_sub_bound() % \ sub_pattern(**{phos_site: 'u', enz_bs: 1}), kf_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # Enzyme phosphorylating substrate rule_name = '%s_phospho_%s_%s' % \ (rule_enz_str, rule_sub_str, phos_site) r = Rule(rule_name, enz_sub_atp_bound() % atp(b=2) % \ sub_pattern(**{phos_site: 'u', enz_bs: 1}) >> enz_sub_atp_unbound() + atp(b=None) + \ sub_pattern(**{phos_site: 'p', enz_bs: None}), kf_phospho) anns = [Annotation(rule_name, enz_sub_atp_bound.monomer.name, 'rule_has_subject'), Annotation(rule_name, sub_pattern.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # Add rule annotations to model # Enzyme dissociating from substrate rule_name = '%s_dissoc_%s' % (enz_rule_str, sub_rule_str) r = Rule(rule_name, enz_mon_uncond(**{sub_bs: 1}) % \ sub_mon_uncond(**{enz_bs: 1}) >> enz_mon_uncond(**{sub_bs: None}) + \ sub_mon_uncond(**{enz_bs: None}), kr_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # DEMODIFICATION ##################################################### def demodification_monomers_interactions_only(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) active_site = mod_acttype_map[stmt.__class__] enz.create_site(active_site) mod_condition_name = stmt.__class__.__name__.lower()[2:] sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) def demodification_monomers_one_step(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) mod_condition_name = stmt.__class__.__name__.lower()[2:] sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) def demodification_monomers_two_step(stmt, agent_set): if stmt.enz is None: return enz = agent_set.get_create_base_agent(stmt.enz) sub = agent_set.get_create_base_agent(stmt.sub) mod_condition_name = stmt.__class__.__name__.lower()[2:] sub.create_mod_site(ist.ModCondition(mod_condition_name, stmt.residue, stmt.position)) # Create site for binding the substrate enz.create_site(get_binding_site_name(stmt.sub)) sub.create_site(get_binding_site_name(stmt.enz)) def demodification_assemble_interactions_only(stmt, model, agent_set): if stmt.enz is None: return kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) enz = model.monomers[stmt.enz.name] sub = model.monomers[stmt.sub.name] active_site = mod_acttype_map[stmt.__class__] # See NOTE in Phosphorylation.monomers_one_step demod_condition_name = stmt.__class__.__name__.lower() mod_condition_name = demod_condition_name[2:] demod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) r = Rule('%s_%s_%s_%s' % (rule_enz_str, demod_condition_name, rule_sub_str, demod_site), enz(**{active_site: None}) + sub(**{demod_site: None}) >> enz(**{active_site: 1}) % sub(**{demod_site: 1}), kf_bind) add_rule_to_model(model, r) def demodification_assemble_one_step(stmt, model, agent_set, rate_law=None): if stmt.enz is None: return demod_condition_name = stmt.__class__.__name__.lower() mod_condition_name = demod_condition_name[2:] demod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) enz_pattern = get_monomer_pattern(model, stmt.enz) unmod_site_state = states[mod_condition_name][0] mod_site_state = states[mod_condition_name][1] sub_unmod = get_monomer_pattern(model, stmt.sub, extra_fields={demod_site: unmod_site_state}) sub_mod = get_monomer_pattern(model, stmt.sub, extra_fields={demod_site: mod_site_state}) rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) rule_name = '%s_%s_%s_%s' % \ (rule_enz_str, demod_condition_name, rule_sub_str, demod_site) if not rate_law: param_name = 'kf_%s%s_%s' % (stmt.enz.name[0].lower(), stmt.sub.name[0].lower(), demod_condition_name) mod_rate = get_create_parameter(model, param_name, 1e-6) elif rate_law == 'michaelis_menten': # Parameters param_name = ('Km_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_' + mod_condition_name) Km = get_create_parameter(model, param_name, 1e8) param_name = ('kc_' + stmt.enz.name[0].lower() + stmt.sub.name[0].lower() + '_' + mod_condition_name) kcat = get_create_parameter(model, param_name, 100) # We need an observable for the substrate to use in the rate law sub_obs = Observable(rule_name + '_sub_obs', sub_mod) model.add_component(sub_obs) mod_rate = Expression(rule_name + '_rate', kcat / (Km + sub_obs)) model.add_component(mod_rate) r = Rule(rule_name, enz_pattern() + sub_mod >> enz_pattern() + sub_unmod, mod_rate) anns = [Annotation(r.name, enz_pattern.monomer.name, 'rule_has_subject'), Annotation(r.name, sub_mod.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) def demodification_assemble_two_step(stmt, model, agent_set): if stmt.enz is None: return demod_condition_name = stmt.__class__.__name__.lower() mod_condition_name = demod_condition_name[2:] sub_bs = get_binding_site_name(stmt.sub) enz_bs = get_binding_site_name(stmt.enz) enz_bound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: 1}) enz_unbound = get_monomer_pattern(model, stmt.enz, extra_fields={sub_bs: None}) sub_pattern = get_monomer_pattern(model, stmt.sub) param_name = 'kf_' + stmt.enz.name[0].lower() + \ stmt.sub.name[0].lower() + '_bind' kf_bind = get_create_parameter(model, param_name, 1e-6) param_name = 'kr_' + stmt.enz.name[0].lower() + \ stmt.sub.name[0].lower() + '_bind' kr_bind = get_create_parameter(model, param_name, 1e-1) param_name = 'kc_' + stmt.enz.name[0].lower() + \ stmt.sub.name[0].lower() + '_' + demod_condition_name kf_demod = get_create_parameter(model, param_name, 100) demod_site = get_mod_site_name(mod_condition_name, stmt.residue, stmt.position) unmod_site_state = states[mod_condition_name][0] mod_site_state = states[mod_condition_name][1] rule_enz_str = get_agent_rule_str(stmt.enz) rule_sub_str = get_agent_rule_str(stmt.sub) rule_name = '%s_%s_bind_%s_%s' % \ (rule_enz_str, demod_condition_name, rule_sub_str, demod_site) r = Rule(rule_name, enz_unbound() + \ sub_pattern(**{demod_site: mod_site_state, enz_bs: None}) >> enz_bound() % \ sub_pattern(**{demod_site: mod_site_state, enz_bs: 1}), kf_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) rule_name = '%s_%s_%s_%s' % \ (rule_enz_str, demod_condition_name, rule_sub_str, demod_site) r = Rule(rule_name, enz_bound() % \ sub_pattern(**{demod_site: mod_site_state, enz_bs: 1}) >> enz_unbound() + \ sub_pattern(**{demod_site: unmod_site_state, enz_bs: None}), kf_demod) anns = [Annotation(r.name, enz_bound.monomer.name, 'rule_has_subject'), Annotation(r.name, sub_pattern.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) enz_uncond = get_uncond_agent(stmt.enz) enz_rule_str = get_agent_rule_str(enz_uncond) enz_mon_uncond = get_monomer_pattern(model, enz_uncond) sub_uncond = get_uncond_agent(stmt.sub) sub_rule_str = get_agent_rule_str(sub_uncond) sub_mon_uncond = get_monomer_pattern(model, sub_uncond) rule_name = '%s_dissoc_%s' % (enz_rule_str, sub_rule_str) r = Rule(rule_name, enz_mon_uncond(**{sub_bs: 1}) % \ sub_mon_uncond(**{enz_bs: 1}) >> enz_mon_uncond(**{sub_bs: None}) + \ sub_mon_uncond(**{enz_bs: None}), kr_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) demodification_monomers_default = demodification_monomers_one_step demodification_assemble_default = demodification_assemble_one_step # Map specific modification monomer/assembly functions to the generic # Modification assembly function policies = ['interactions_only', 'one_step', 'two_step', 'default'] mod_classes = [cls for cls in ist.AddModification.__subclasses__()] for mc, func_type, pol in itertools.product(mod_classes, ('monomers', 'assemble'), policies): code = '{mc}_{func_type}_{pol} = ' \ 'modification_{func_type}_{pol}'.format( mc=ist.modclass_to_modtype[mc], func_type=func_type, pol=pol) exec(code) demod_classes = [cls for cls in ist.RemoveModification.__subclasses__()] for mc, func_type, pol in itertools.product(demod_classes, ('monomers', 'assemble'), policies): code = '{mc}_{func_type}_{pol} = ' \ 'demodification_{func_type}_{pol}'.format( mc=ist.modclass_to_modtype[mc], func_type=func_type, pol=pol) exec(code) rate_laws = ['michaelis_menten'] for mc, rate_law in itertools.product(mod_classes, rate_laws): code = '{mc}_monomers_{rate_law} = {mc}_monomers_one_step'.format( mc=ist.modclass_to_modtype[mc], rate_law=rate_law) exec(code) code = '{mc}_assemble_{rate_law} = ' \ 'lambda a, b, c: modification_assemble_' \ 'one_step(a, b, c, "{rate_law}")'.format( mc=ist.modclass_to_modtype[mc], rate_law=rate_law) exec(code) for mc, rate_law in itertools.product(demod_classes, rate_laws): code = '{mc}_monomers_{rate_law} = {mc}_monomers_one_step'.format( mc=ist.modclass_to_modtype[mc], rate_law=rate_law) exec(code) code = '{mc}_assemble_{rate_law} = ' \ 'lambda a, b, c: demodification_assemble_' \ 'one_step(a, b, c, "{rate_law}")'.format( mc=ist.modclass_to_modtype[mc], rate_law=rate_law) exec(code) # CIS-AUTOPHOSPHORYLATION ################################################### def autophosphorylation_monomers_interactions_only(stmt, agent_set): enz = agent_set.get_create_base_agent(stmt.enz) phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) enz.create_site(phos_site, ('u', 'p')) def autophosphorylation_monomers_one_step(stmt, agent_set): enz = agent_set.get_create_base_agent(stmt.enz) # NOTE: This assumes that a Phosphorylation statement will only ever # involve a single phosphorylation site on the substrate (typically # if there is more than one site, they will be parsed into separate # Phosphorylation statements, i.e., phosphorylation is assumed to be # distributive. If this is not the case, this assumption will need to # be revisited. phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) enz.create_site(phos_site, ('u', 'p')) autophosphorylation_monomers_default = autophosphorylation_monomers_one_step def autophosphorylation_assemble_interactions_only(stmt, model, agent_set): stmt.assemble_one_step(model, agent_set) def autophosphorylation_assemble_one_step(stmt, model, agent_set): param_name = 'kf_' + stmt.enz.name[0].lower() + '_autophos' # http://www.jbc.org/content/286/4/2689.full kf_autophospho = get_create_parameter(model, param_name, 1e-2) # See NOTE in monomers_one_step phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) pattern_unphos = get_monomer_pattern(model, stmt.enz, extra_fields={phos_site: 'u'}) pattern_phos = get_monomer_pattern(model, stmt.enz, extra_fields={phos_site: 'p'}) rule_enz_str = get_agent_rule_str(stmt.enz) rule_name = '%s_autophospho_%s_%s' % (rule_enz_str, rule_enz_str, phos_site) r = Rule(rule_name, pattern_unphos >> pattern_phos, kf_autophospho) anns = [Annotation(rule_name, pattern_unphos.monomer.name, 'rule_has_subject'), Annotation(rule_name, pattern_phos.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) autophosphorylation_assemble_default = autophosphorylation_assemble_one_step # TRANSPHOSPHORYLATION ################################################### def transphosphorylation_monomers_interactions_only(stmt, agent_set): enz = agent_set.get_create_base_agent(stmt.enz) # Assume there is exactly one bound_to species sub = agent_set.get_create_base_agent(stmt.enz) phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) sub.create_site(phos_site, ('u', 'p')) def transphosphorylation_monomers_one_step(stmt, agent_set): enz = agent_set.get_create_base_agent(stmt.enz) # NOTE: This assumes that a Phosphorylation statement will only ever # involve a single phosphorylation site on the substrate (typically # if there is more than one site, they will be parsed into separate # Phosphorylation statements, i.e., phosphorylation is assumed to be # distributive. If this is not the case, this assumption will need to # be revisited. sub = agent_set.get_create_base_agent(stmt.enz.bound_conditions[0].agent) phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) sub.create_site(phos_site, ('u', 'p')) transphosphorylation_monomers_default = transphosphorylation_monomers_one_step def transphosphorylation_assemble_interactions_only(stmt, model, agent_set): stmt.assemble_one_step(model, agent_set) def transphosphorylation_assemble_one_step(stmt, model, agent_set): param_name = ('kf_' + stmt.enz.name[0].lower() + _n(stmt.enz.bound_conditions[0].agent.name[0]).lower() + '_transphos') kf = get_create_parameter(model, param_name, 1e-6) phos_site = get_mod_site_name('phosphorylation', stmt.residue, stmt.position) enz_pattern = get_monomer_pattern(model, stmt.enz) bound_agent = stmt.enz.bound_conditions[0].agent sub_unphos = get_monomer_pattern(model, bound_agent, extra_fields={phos_site: 'u'}) sub_phos = get_monomer_pattern(model, bound_agent, extra_fields={phos_site: 'p'}) rule_enz_str = get_agent_rule_str(stmt.enz) rule_bound_str = get_agent_rule_str(bound_agent) rule_name = '%s_transphospho_%s_%s' % (rule_enz_str, rule_bound_str, phos_site) r = Rule(rule_name, enz_pattern % sub_unphos >> \ enz_pattern % sub_phos, kf) anns = [Annotation(rule_name, enz_pattern.monomer.name, 'rule_has_subject'), Annotation(rule_name, sub_unphos.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) transphosphorylation_assemble_default = transphosphorylation_assemble_one_step # ACTIVATION ###################################################### def regulateactivity_monomers_interactions_only(stmt, agent_set): subj = agent_set.get_create_base_agent(stmt.subj) obj = agent_set.get_create_base_agent(stmt.obj) if stmt.subj.activity is not None: subj_activity = stmt.subj.activity.activity_type else: subj_activity = 'activity' subj.create_site(subj_activity) obj.create_site(stmt.obj_activity) obj.create_site(stmt.obj_activity) def regulateactivity_monomers_one_step(stmt, agent_set): subj = agent_set.get_create_base_agent(stmt.subj) obj = agent_set.get_create_base_agent(stmt.obj) # if stmt.subj_activity is not None: # # Add the new active state flag to the list of active forms # subj.add_activity_form({stmt.subj_activity: 'active'}, True) # subj.add_activity_form({stmt.subj_activity: 'inactive'}, False) obj.create_site(stmt.obj_activity, ('inactive', 'active')) # Add the new active state flag to the list of active forms obj.add_activity_type(stmt.obj_activity) def regulateactivity_assemble_interactions_only(stmt, model, agent_set): kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) subj = model.monomers[stmt.subj.name] obj = model.monomers[stmt.obj.name] if stmt.subj.activity: subj_activity = stmt.subj.activity.activity_type else: subj_activity = 'activity' subj_active_site = subj_activity obj_mod_site = stmt.obj_activity rule_obj_str = get_agent_rule_str(stmt.obj) rule_subj_str = get_agent_rule_str(stmt.subj) polarity_str = 'activates' if stmt.is_activation else 'deactivates' rule_name = '%s_%s_%s_%s' %\ (rule_subj_str, polarity_str, rule_obj_str, stmt.obj_activity) r = Rule(rule_name, subj(**{subj_active_site: None}) + obj(**{obj_mod_site: None}) >> subj(**{subj_active_site: 1}) % obj(**{obj_mod_site: 1}), kf_bind) add_rule_to_model(model, r) def regulateactivity_assemble_one_step(stmt, model, agent_set, rate_law=None): # This is the pattern coming directly from the subject Agent state # TODO: handle context here in conjunction with active forms subj_pattern = get_monomer_pattern(model, stmt.subj) obj_inactive = get_monomer_pattern(model, stmt.obj, extra_fields={stmt.obj_activity: 'inactive'}) obj_active = get_monomer_pattern(model, stmt.obj, extra_fields={stmt.obj_activity: 'active'}) rule_obj_str = get_agent_rule_str(stmt.obj) rule_subj_str = get_agent_rule_str(stmt.subj) polarity_str = 'activates' if stmt.is_activation else 'deactivates' rule_name = '%s_%s_%s_%s' % \ (rule_subj_str, polarity_str, rule_obj_str, stmt.obj_activity) if not rate_law: param_name = 'kf_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_act' act_rate = get_create_parameter(model, param_name, 1e-6) elif rate_law == 'michaelis_menten': # Parameters param_name = ('Km_' + stmt.subj.name[0].lower() + stmt.obj.name[0].lower() + '_act') Km = get_create_parameter(model, param_name, 1e8) param_name = ('kc_' + stmt.subj.name[0].lower() + stmt.obj.name[0].lower() + '_act') kcat = get_create_parameter(model, param_name, 100) # We need an observable for the substrate to use in the rate law obj_to_observe = obj_active if stmt.is_activation else obj_inactive obj_obs = Observable(rule_name + '_obj_obs', obj_to_observe) model.add_component(obj_obs) act_rate = Expression(rule_name + '_rate', kcat / (Km * obj_obs)) model.add_component(act_rate) obj_from, obj_to = (obj_inactive, obj_active) if stmt.is_activation else \ (obj_active, obj_inactive) r = Rule(rule_name, subj_pattern() + obj_from >> subj_pattern() + obj_to, act_rate) anns = [Annotation(rule_name, subj_pattern.monomer.name, 'rule_has_subject'), Annotation(rule_name, obj_active.monomer.name, 'rule_has_object')] anns += [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) regulateactivity_monomers_default = regulateactivity_monomers_one_step regulateactivity_assemble_default = regulateactivity_assemble_one_step activation_monomers_interactions_only = \ regulateactivity_monomers_interactions_only activation_assemble_interactions_only = \ regulateactivity_assemble_interactions_only activation_monomers_one_step = regulateactivity_monomers_one_step activation_assemble_one_step = regulateactivity_assemble_one_step activation_monomers_default = regulateactivity_monomers_one_step activation_assemble_default = regulateactivity_assemble_one_step activation_monomers_michaelis_menten = regulateactivity_monomers_one_step activation_assemble_michaelis_menten = lambda a, b, c: \ regulateactivity_assemble_one_step(a, b, c, 'michaelis_menten') inhibition_monomers_interactions_only = \ regulateactivity_monomers_interactions_only inhibition_assemble_interactions_only = \ regulateactivity_assemble_interactions_only inhibition_monomers_one_step = regulateactivity_monomers_one_step inhibition_assemble_one_step = regulateactivity_assemble_one_step inhibition_monomers_default = regulateactivity_monomers_one_step inhibition_assemble_default = regulateactivity_assemble_one_step inhibition_monomers_michaelis_menten = regulateactivity_monomers_one_step inhibition_assemble_michaelis_menten = lambda a, b, c: \ regulateactivity_assemble_one_step(a, b, c, 'michaelis_menten') # GEF ##################################################### def gef_monomers_interactions_only(stmt, agent_set): gef = agent_set.get_create_base_agent(stmt.gef) gef.create_site('gef_site') ras = agent_set.get_create_base_agent(stmt.ras) ras.create_site('p_loop') def gef_monomers_one_step(stmt, agent_set): # Gef gef = agent_set.get_create_base_agent(stmt.gef) # Ras ras = agent_set.get_create_base_agent(stmt.ras) ras.create_site('gtpbound', ('inactive', 'active')) ras.add_activity_form({'gtpbound': 'active'}, True) ras.add_activity_form({'gtpbound': 'inactive'}, False) gef_monomers_default = gef_monomers_one_step def gef_assemble_interactions_only(stmt, model, agent_set): kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) gef = model.monomers[stmt.gef.name] ras = model.monomers[stmt.ras.name] rule_gef_str = get_agent_rule_str(stmt.gef) rule_ras_str = get_agent_rule_str(stmt.ras) r = Rule('%s_activates_%s' % (rule_gef_str, rule_ras_str), gef(**{'gef_site': None}) + ras(**{'p_loop': None}) >> gef(**{'gef_site': 1}) % ras(**{'p_loop': 1}), kf_bind) add_rule_to_model(model, r) def gef_assemble_one_step(stmt, model, agent_set): gef_pattern = get_monomer_pattern(model, stmt.gef) ras_inactive = get_monomer_pattern(model, stmt.ras, extra_fields={'gtpbound': 'inactive'}) ras_active = get_monomer_pattern(model, stmt.ras, extra_fields={'gtpbound': 'active'}) param_name = 'kf_' + stmt.gef.name[0].lower() + \ stmt.ras.name[0].lower() + '_gef' kf_gef = get_create_parameter(model, param_name, 1e-6) rule_gef_str = get_agent_rule_str(stmt.gef) rule_ras_str = get_agent_rule_str(stmt.ras) r = Rule('%s_activates_%s' % (rule_gef_str, rule_ras_str), gef_pattern + ras_inactive >> gef_pattern + ras_active, kf_gef) anns = [Annotation(r.name, gef_pattern.monomer.name, 'rule_has_subject'), Annotation(r.name, ras_inactive.monomer.name, 'rule_has_object')] anns += [Annotation(r.name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) gef_assemble_default = gef_assemble_one_step # GAP #################################################### def gap_monomers_interactions_only(stmt, agent_set): gap = agent_set.get_create_base_agent(stmt.gap) gap.create_site('gap_site') ras = agent_set.get_create_base_agent(stmt.ras) ras.create_site('gtp_site') def gap_monomers_one_step(stmt, agent_set): # Gap gap = agent_set.get_create_base_agent(stmt.gap) # Ras ras = agent_set.get_create_base_agent(stmt.ras) ras.create_site('gtpbound', ('inactive', 'active')) ras.add_activity_form({'gtpbound': 'active'}, True) ras.add_activity_form({'gtpbound': 'inactive'}, False) gap_monomers_default = gap_monomers_one_step def gap_assemble_interactions_only(stmt, model, agent_set): kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) gap = model.monomers[stmt.gap.name] ras = model.monomers[stmt.ras.name] rule_gap_str = get_agent_rule_str(stmt.gap) rule_ras_str = get_agent_rule_str(stmt.ras) r = Rule('%s_inactivates_%s' % (rule_gap_str, rule_ras_str), gap(**{'gap_site': None}) + ras(**{'gtp_site': None}) >> gap(**{'gap_site': 1}) % ras(**{'gtp_site': 1}), kf_bind) add_rule_to_model(model, r) def gap_assemble_one_step(stmt, model, agent_set): gap_pattern = get_monomer_pattern(model, stmt.gap) ras_inactive = get_monomer_pattern(model, stmt.ras, extra_fields={'gtpbound': 'inactive'}) ras_active = get_monomer_pattern(model, stmt.ras, extra_fields={'gtpbound': 'active'}) param_name = 'kf_' + stmt.gap.name[0].lower() + \ stmt.ras.name[0].lower() + '_gap' kf_gap = get_create_parameter(model, param_name, 1e-6) rule_gap_str = get_agent_rule_str(stmt.gap) rule_ras_str = get_agent_rule_str(stmt.ras) r = Rule('%s_deactivates_%s' % (rule_gap_str, rule_ras_str), gap_pattern + ras_active >> gap_pattern + ras_inactive, kf_gap) anns = [Annotation(r.name, gap_pattern.monomer.name, 'rule_has_subject'), Annotation(r.name, ras_inactive.monomer.name, 'rule_has_object')] anns += [Annotation(r.name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) gap_assemble_default = gap_assemble_one_step # ACTIVEFORM ############################################ def activeform_monomers_interactions_only(stmt, agent_set): pass def activeform_monomers_one_step(stmt, agent_set): agent = agent_set.get_create_base_agent(stmt.agent) site_conditions = get_site_pattern(stmt.agent) # Add this activity pattern explicitly to the agent's list # of active states agent.add_activity_form(site_conditions, stmt.is_active) activeform_monomers_default = activeform_monomers_one_step def activeform_assemble_interactions_only(stmt, model, agent_set): pass def activeform_assemble_one_step(stmt, model, agent_set): pass activeform_assemble_default = activeform_assemble_one_step # GTPACTIVATION ###################################### gtpactivation_monomers_default = activation_monomers_default gtpactivation_assemble_default = activation_assemble_default # TRANSLOCATION ############################################### def translocation_monomers_default(stmt, agent_set): # Skip if either from or to locations are missing if stmt.to_location is None: return agent = agent_set.get_create_base_agent(stmt.agent) from_loc = stmt.from_location if stmt.from_location else 'cytoplasm' states = [_n(from_loc), _n(stmt.to_location)] agent.create_site('loc', states) def translocation_assemble_default(stmt, model, agent_set): if stmt.to_location is None: return from_loc = stmt.from_location if stmt.from_location else 'cytoplasm' param_name = 'kf_%s_%s_%s' % (_n(stmt.agent.name).lower(), _n(from_loc), _n(stmt.to_location)) kf_trans = get_create_parameter(model, param_name, 1.0, unique=True) monomer = model.monomers[_n(stmt.agent.name)] rule_agent_str = get_agent_rule_str(stmt.agent) rule_name = '%s_translocates_%s_to_%s' % (rule_agent_str, _n(from_loc), _n(stmt.to_location)) agent_from = get_monomer_pattern(model, stmt.agent, extra_fields={'loc': _n(from_loc)}) agent_to = get_monomer_pattern(model, stmt.agent, extra_fields={'loc': _n(stmt.to_location)}) r = Rule(rule_name, agent_from >> agent_to, kf_trans) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) # DEGRADATION ############################################### def decreaseamount_monomers_interactions_only(stmt, agent_set): if stmt.subj is None: return subj = agent_set.get_create_base_agent(stmt.subj) obj = agent_set.get_create_base_agent(stmt.obj) subj.create_site(get_binding_site_name(stmt.obj)) obj.create_site(get_binding_site_name(stmt.subj)) def decreaseamount_monomers_one_step(stmt, agent_set): obj = agent_set.get_create_base_agent(stmt.obj) if stmt.subj is not None: subj = agent_set.get_create_base_agent(stmt.subj) def decreaseamount_assemble_interactions_only(stmt, model, agent_set): # No interaction when subj is None if stmt.subj is None: return kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) subj_base_agent = agent_set.get_create_base_agent(stmt.subj) obj_base_agent = agent_set.get_create_base_agent(stmt.obj) subj = model.monomers[subj_base_agent.name] obj = model.monomers[obj_base_agent.name] rule_subj_str = get_agent_rule_str(stmt.subj) rule_obj_str = get_agent_rule_str(stmt.obj) rule_name = '%s_degrades_%s' % (rule_subj_str, rule_obj_str) subj_site_name = get_binding_site_name(stmt.obj) obj_site_name = get_binding_site_name(stmt.subj) r = Rule(rule_name, subj(**{subj_site_name: None}) + obj(**{obj_site_name: None}) >> subj(**{subj_site_name: 1}) % obj(**{obj_site_name: 1}), kf_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] anns += [Annotation(rule_name, obj.name, 'rule_has_object')] if stmt.subj: anns += [Annotation(rule_name, subj.name, 'rule_has_subject')] add_rule_to_model(model, r, anns) def decreaseamount_assemble_one_step(stmt, model, agent_set): obj_pattern = get_monomer_pattern(model, stmt.obj) rule_obj_str = get_agent_rule_str(stmt.obj) if stmt.subj is None: # See U. Alon paper on proteome dynamics at 10.1126/science.1199784 param_name = 'kf_' + stmt.obj.name[0].lower() + '_deg' kf_one_step_degrade = get_create_parameter(model, param_name, 2e-5, unique=True) rule_name = '%s_degraded' % rule_obj_str r = Rule(rule_name, obj_pattern >> None, kf_one_step_degrade) else: subj_pattern = get_monomer_pattern(model, stmt.subj) # See U. Alon paper on proteome dynamics at 10.1126/science.1199784 param_name = 'kf_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_deg' # Scale the average apparent decreaseamount rate by the default # protein initial condition kf_one_step_degrade = get_create_parameter(model, param_name, 2e-9) rule_subj_str = get_agent_rule_str(stmt.subj) rule_name = '%s_degrades_%s' % (rule_subj_str, rule_obj_str) r = Rule(rule_name, subj_pattern + obj_pattern >> subj_pattern + None, kf_one_step_degrade) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] anns += [Annotation(rule_name, obj_pattern.monomer.name, 'rule_has_object')] if stmt.subj: anns += [Annotation(rule_name, subj_pattern.monomer.name, 'rule_has_subject')] add_rule_to_model(model, r, anns) decreaseamount_assemble_default = decreaseamount_assemble_one_step decreaseamount_monomers_default = decreaseamount_monomers_one_step # SYNTHESIS ############################################### increaseamount_monomers_interactions_only = \ decreaseamount_monomers_interactions_only increaseamount_monomers_one_step = decreaseamount_monomers_one_step def increaseamount_assemble_interactions_only(stmt, model, agent_set): # No interaction when subj is None if stmt.subj is None: return kf_bind = get_create_parameter(model, 'kf_bind', 1.0, unique=False) subj_base_agent = agent_set.get_create_base_agent(stmt.subj) obj_base_agent = agent_set.get_create_base_agent(stmt.obj) subj = model.monomers[subj_base_agent.name] obj = model.monomers[obj_base_agent.name] rule_subj_str = get_agent_rule_str(stmt.subj) rule_obj_str = get_agent_rule_str(stmt.obj) rule_name = '%s_synthesizes_%s' % (rule_subj_str, rule_obj_str) subj_site_name = get_binding_site_name(stmt.obj) obj_site_name = get_binding_site_name(stmt.subj) r = Rule(rule_name, subj(**{subj_site_name: None}) + obj(**{obj_site_name: None}) >> subj(**{subj_site_name: 1}) % obj(**{obj_site_name: 1}), kf_bind) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] anns += [Annotation(rule_name, obj.name, 'rule_has_object')] if stmt.subj: anns += [Annotation(rule_name, subj.name, 'rule_has_subject')] add_rule_to_model(model, r, anns) def increaseamount_assemble_one_step(stmt, model, agent_set, rate_law=None): if stmt.subj is not None and (stmt.subj.name == stmt.obj.name): logger.warning('%s transcribes itself, skipping' % stmt.obj.name) return # We get the monomer pattern just to get a valid monomer # otherwise the patter will be replaced obj_pattern = get_monomer_pattern(model, stmt.obj) obj_monomer = obj_pattern.monomer # The obj Monomer needs to be synthesized in its "base" state # but it needs a fully specified monomer pattern sites_dict = {} for site in obj_monomer.sites: if site in obj_monomer.site_states: sites_dict[site] = obj_monomer.site_states[site][0] else: sites_dict[site] = None obj_pattern = obj_monomer(**sites_dict) rule_obj_str = get_agent_rule_str(stmt.obj) if stmt.subj is None: rule_name = '%s_synthesized' % rule_obj_str param_name = 'kf_' + stmt.obj.name[0].lower() + '_synth' kf_one_step_synth = get_create_parameter(model, param_name, 2, unique=True) r = Rule(rule_name, None >> obj_pattern, kf_one_step_synth) else: subj_pattern = get_monomer_pattern(model, stmt.subj) rule_subj_str = get_agent_rule_str(stmt.subj) rule_name = '%s_synthesizes_%s' % (rule_subj_str, rule_obj_str) if not rate_law: param_name = 'kf_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_synth' # Scale the average apparent increaseamount rate by the default # protein initial condition synth_rate = get_create_parameter(model, param_name, 2e-4) if rate_law == 'hill': # k * [subj]**n / (K_A**n + [subj]**n) param_name = 'kf_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_synth' kf = get_create_parameter(model, param_name, 4) param_name = 'Ka_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_synth' Ka = get_create_parameter(model, param_name, 1e4) param_name = 'n_' + stmt.subj.name[0].lower() + \ stmt.obj.name[0].lower() + '_synth' n_hill = get_create_parameter(model, param_name, 1) subj_obs = Observable(rule_name + '_subj_obs', subj_pattern) model.add_component(subj_obs) synth_rate = Expression(rule_name + '_rate', kf * (subj_obs ** (n_hill-1)) / (Ka**n_hill + subj_obs**n_hill)) model.add_component(synth_rate) r = Rule(rule_name, subj_pattern + None >> subj_pattern + obj_pattern, synth_rate) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] anns += [Annotation(rule_name, obj_pattern.monomer.name, 'rule_has_object')] if stmt.subj: anns += [Annotation(rule_name, subj_pattern.monomer.name, 'rule_has_subject')] add_rule_to_model(model, r, anns) increaseamount_monomers_default = increaseamount_monomers_one_step increaseamount_assemble_default = increaseamount_assemble_one_step increaseamount_monomers_hill = increaseamount_monomers_one_step increaseamount_assemble_hill = lambda a, b, c: \ increaseamount_assemble_one_step(a, b, c, 'hill') # INFLUENCE ################################################### influence_monomers_one_step = increaseamount_monomers_one_step def influence_assemble_one_step(stmt, *args): if stmt.overall_polarity() == -1: return decreaseamount_assemble_one_step(stmt, *args) else: return increaseamount_assemble_one_step(stmt, *args, rate_law='hill') influence_monomers_default = influence_monomers_one_step influence_assemble_default = influence_assemble_one_step # CONVERSION ################################################### def conversion_monomers_one_step(stmt, agent_set): # Skip statements with more than one from object due to complications # with rate law if len(stmt.obj_from) > 1: return if stmt.subj is not None: agent_set.get_create_base_agent(stmt.subj) for obj in stmt.obj_from: agent_set.get_create_base_agent(obj) for obj in stmt.obj_to: agent_set.get_create_base_agent(obj) def conversion_assemble_one_step(stmt, model, agent_set): # Skip statements with more than one from object due to complications # with rate law if len(stmt.obj_from) != 1: return # Create pieces needed for from object obj_from = stmt.obj_from[0] obj_from_pattern = get_monomer_pattern(model, obj_from) obj_from_monomer = obj_from_pattern.monomer rule_obj_from_str = get_agent_rule_str(obj_from) obj_to_monomers = [get_monomer_pattern(model, o).monomer for o in stmt.obj_to] # Create pieces needed for to object # The obj Monomer needs to be synthesized in its "base" state # but it needs a fully specified monomer pattern obj_to_patterns = [] for obj_to_monomer in obj_to_monomers: sites_dict = {} for site in obj_to_monomer.sites: if site in obj_to_monomer.site_states: sites_dict[site] = obj_to_monomer.site_states[site][0] else: sites_dict[site] = None obj_to_pattern = obj_to_monomer(**sites_dict) obj_to_patterns.append(obj_to_pattern) obj_to_pattern = ReactionPattern(obj_to_patterns) rule_obj_to_str = '_'.join([get_agent_rule_str(o) for o in stmt.obj_to]) if stmt.subj is None: rule_name = '%s_converted_to_%s' % (rule_obj_from_str, rule_obj_to_str) param_name = 'kf_%s%s_convert' % (obj_from.name[0].lower(), obj_to_monomers[0].name[0].lower()) kf_one_step_convert = get_create_parameter(model, param_name, 2, unique=True) r = Rule(rule_name, obj_from_pattern >> obj_to_pattern, kf_one_step_convert) else: subj_pattern = get_monomer_pattern(model, stmt.subj) result_pattern = obj_to_pattern result_pattern.complex_patterns.insert(0, subj_pattern) rule_subj_str = get_agent_rule_str(stmt.subj) rule_name = '%s_catalyzes_%s_converted_to_%s' % \ (rule_subj_str, rule_obj_from_str, rule_obj_to_str) param_name = 'kf_%s%s%s_convert' % \ (stmt.subj.name[0].lower(), obj_from.name[0].lower(), obj_to_monomers[0].name[0].lower()) # Scale the average apparent increaseamount rate by the default # protein initial condition kf_one_step_convert = get_create_parameter(model, param_name, 2e-4) r = Rule(rule_name, subj_pattern + obj_from_pattern >> result_pattern, kf_one_step_convert) anns = [Annotation(rule_name, stmt.uuid, 'from_indra_statement')] add_rule_to_model(model, r, anns) conversion_monomers_default = conversion_monomers_one_step conversion_assemble_default = conversion_assemble_one_step class PysbPreassembler(object): def __init__(self, stmts=None): if not stmts: stmts = [] self.statements = stmts self.agent_set = _BaseAgentSet() def add_statements(self, stmts): self.statements = stmts def _gather_active_forms(self): for stmt in self.statements: if isinstance(stmt, ist.ActiveForm): base_agent = self.agent_set.get_create_base_agent(stmt.agent) # Handle the case where an activity flag is set agent_to_add = stmt.agent if stmt.agent.activity: new_agent = fast_deepcopy(stmt.agent) new_agent.activity = None agent_to_add = new_agent base_agent.add_activity_form(agent_to_add, stmt.is_active) def replace_activities(self): # TODO: handle activity hierarchies # First collect all explicit active forms self._gather_active_forms() new_stmts = [] # Iterate over all statements for stmt in self.statements: stmt_agents = stmt.agent_list() num_agents = len(stmt_agents) # Make a list with an empty list for each Agent so that later # we can build combinations of Agent forms agent_forms = [[] for a in stmt_agents] for i, agent in enumerate(stmt_agents): # This is the case where there is an activity flag on an # Agent which we will attempt to replace with an explicit # active form if agent is not None and agent.activity is not None: base_agent = self.agent_set.get_create_base_agent(agent) # If it is an "active" state if agent.activity.is_active: active_forms = base_agent.active_forms # If no explicit active forms are known then we use # the generic one if not active_forms: active_forms = [agent] # If it is an "inactive" state else: active_forms = base_agent.inactive_forms # If no explicit inactive forms are known then we use # the generic one if not active_forms: active_forms = [agent] # We now iterate over the active agent forms and create # new agents for af in active_forms: new_agent = fast_deepcopy(agent) self._set_agent_context(af, new_agent) agent_forms[i].append(new_agent) # Otherwise we just copy over the agent as is else: agent_forms[i].append(agent) # Now create all possible combinations of the agents and create new # statements as needed agent_combs = itertools.product(*agent_forms) for agent_comb in agent_combs: new_stmt = fast_deepcopy(stmt) new_stmt.set_agent_list(agent_comb) new_stmts.append(new_stmt) self.statements = new_stmts def add_reverse_effects(self): # TODO: generalize to other modification sites pos_mod_sites = {} neg_mod_sites = {} syntheses = [] degradations = [] for stmt in self.statements: if isinstance(stmt, ist.Phosphorylation): agent = stmt.sub.name try: pos_mod_sites[agent].append((stmt.residue, stmt.position)) except KeyError: pos_mod_sites[agent] = [(stmt.residue, stmt.position)] elif isinstance(stmt, ist.Dephosphorylation): agent = stmt.sub.name try: neg_mod_sites[agent].append((stmt.residue, stmt.position)) except KeyError: neg_mod_sites[agent] = [(stmt.residue, stmt.position)] elif isinstance(stmt, ist.IncreaseAmount): syntheses.append(stmt.obj.name) elif isinstance(stmt, ist.DecreaseAmount): degradations.append(stmt.obj.name) new_stmts = [] for agent_name, pos_sites in pos_mod_sites.items(): neg_sites = neg_mod_sites.get(agent_name, []) no_neg_site = set(pos_sites).difference(set(neg_sites)) for residue, position in no_neg_site: st = ist.Dephosphorylation(ist.Agent('phosphatase'), ist.Agent(agent_name), residue, position) new_stmts.append(st) for agent_name in syntheses: if agent_name not in degradations: st = ist.DecreaseAmount(None, ist.Agent(agent_name)) new_stmts.append(st) self.statements += new_stmts @staticmethod def _set_agent_context(from_agent, to_agent): # TODO: what can we do about semantic conflicts here like the same # bound condition with True/False is_bound appearing in the # two contexts? def add_no_duplicate(from_lst, to_lst): for fm in from_lst: found = False for tm in to_lst: if fm.matches(tm): found = True break if not found: to_lst.append(fm) return to_lst to_agent.bound_conditions = \ add_no_duplicate(to_agent.bound_conditions, from_agent.bound_conditions) to_agent.mods = add_no_duplicate(to_agent.mods, from_agent.mods) to_agent.mutations = add_no_duplicate(to_agent.mutations, from_agent.mutations) to_agent.location = from_agent.location to_agent.activity = from_agent.activity
[docs]def export_sbgn(model): """Return an SBGN model string corresponding to the PySB model. This function first calls generate_equations on the PySB model to obtain a reaction network (i.e. individual species, reactions). It then iterates over each reaction and and instantiates its reactants, products, and the process itself as SBGN glyphs and arcs. Parameters ---------- model : pysb.core.Model A PySB model to be exported into SBGN Returns ------- sbgn_str : str An SBGN model as string """ import lxml.etree import lxml.builder from pysb.bng import generate_equations from indra.assemblers.sbgn_assembler import SBGNAssembler logger.info('Generating reaction network with BNG for SBGN export. ' + 'This could take a long time.') generate_equations(model) sa = SBGNAssembler() glyphs = {} for idx, species in enumerate(model.species): glyph = sa._glyph_for_complex_pattern(species) if glyph is None: continue sa._map.append(glyph) glyphs[idx] = glyph for reaction in model.reactions: # Get all the reactions / products / controllers of the reaction reactants = set(reaction['reactants']) - set(reaction['products']) products = set(reaction['products']) - set(reaction['reactants']) controllers = set(reaction['reactants']) & set(reaction['products']) # Add glyph for reaction process_glyph = sa._process_glyph('process') # Connect reactants with arcs for r in reactants: glyph = glyphs.get(r) if glyph is None: glyph_id = sa._none_glyph() else: glyph_id = glyph.attrib['id'] sa._arc('consumption', glyph_id, process_glyph) # Connect products with arcs for p in products: glyph = glyphs.get(p) if glyph is None: glyph_id = sa._none_glyph() else: glyph_id = glyph.attrib['id'] sa._arc('production', process_glyph, glyph_id) # Connect controllers with arcs for c in controllers: glyph = glyphs[c] sa._arc('catalysis', glyph.attrib['id'], process_glyph) sbgn_str = sa.print_model().decode('utf-8')
return sbgn_str