Example #1
0
def one_step_conv(sub1, sub2, product, klist, site='bf'):
    """ Bind sub1 and sub2 to form one product: sub1 + sub2 <> product.
    """

    kf, kr = klist

    # Make sure that the substrates have the site:
    macros._verify_sites(sub1, site)
    macros._verify_sites(sub2, site)

    return macros._macro_rule(
        'convert',
        sub1({site: None}) + sub2({site: None}) | product, klist, ['kf', 'kr'])
Example #2
0
File: shared.py Project: LoLab/anrm
def one_step_conv(sub1, sub2, product, klist, site='bf'):
    """ Bind sub1 and sub2 to form one product: sub1 + sub2 <> product.
    """

    kf, kr = klist

    # Make sure that the substrates have the site:
    macros._verify_sites(sub1, site)
    macros._verify_sites(sub2, site)

    return macros._macro_rule('convert',
                       sub1({site: None}) + sub2({site: None}) <> product,
                       klist, ['kf', 'kr'])
Example #3
0
def catalyze_convert(sub1, sub2, product, klist, site='bf'):
    """Automation of the Sub1 + Sub2 <> Sub1:Sub2 >> Prod two-step reaction.

    Because product is created by the function, it must be fully specified.
    """

    # Make sure that the substrates have the site:
    macros._verify_sites(sub1, site)
    macros._verify_sites(sub2, site)

    components = macros._macro_rule(
        'bind',
        sub1({site: None}) + sub2({site: None})
        | sub1({site: 1}) % sub2({site: 1}), klist[0:2], ['kf', 'kr'])
    components |= macros._macro_rule(
        'convert',
        sub1({site: 1}) % sub2({site: 1}) >> product, [klist[2]], ['kc'])
    return components
Example #4
0
File: shared.py Project: LoLab/anrm
def catalyze_convert(sub1, sub2, product, klist, site='bf'):
    """Automation of the Sub1 + Sub2 <> Sub1:Sub2 >> Prod two-step reaction.

    Because product is created by the function, it must be fully specified.
    """

    # Make sure that the substrates have the site:
    macros._verify_sites(sub1, site)
    macros._verify_sites(sub2, site)

    components = macros._macro_rule('bind',
                             sub1({site: None}) + sub2({site: None}) <>
                             sub1({site: 1}) % sub2({site: 1}),
                             klist[0:2], ['kf', 'kr'])
    components |= macros._macro_rule('convert',
                              sub1({site: 1}) % sub2({site: 1}) >> product,
                              [klist[2]], ['kc'])
    return components
Example #5
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
Example #6
0
File: shared.py Project: LoLab/anrm
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
Example #7
0
def cleave_complex(enzyme,
                   e_site,
                   substrate,
                   s_site,
                   product,
                   klist,
                   m1=None,
                   m2=None):
    """Generate the two-step cleaving reaction
    E + S:S2 | E:S:S2 >> E + S + S2, while allowing complexes to serve as
    enzyme, substrate and/or product.

    E:S1 + S:S2 | E:S1:S:S2 >> E:S1 + S + S2

    Parameters
    ----------
    enzyme, substrate, product : Monomer, MonomerPattern, or ComplexPattern
        Monomers or complexes participating in the binding reaction.

    e_site, s_site : string
        The names of the sites on `enzyme` and `substrate` (respectively) where
        they bind each other to form the E:S complex.

    klist : list of 3 Parameters or list of 3 numbers
        Forward, reverse and cleaving rate constants (in that order). 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 the names and states of enzyme,
        substrate and product and these parameters will be included at the end
        of the returned component list.

    m1, m2 : Monomer or MonomerPattern
        If enzyme or substrate binding site is present in multiple monomers
        within a complex, the specific monomer desired for binding must be
        specified.

    Notes
    -----
    Binding site between enzyme and substrate is using edge 50, so this
    edge must be free to use.

    Returns
    -------
    components : ComponentSet
        The generated components. Contains the bidirectional binding Rule
        and optionally three Parameters if klist was given as numbers.
    """
    if isinstance(m1, Monomer):
        m1 = m1()
    if isinstance(m2, Monomer):
        m2 = m2()

    def build_complex(s1, site1, m1):
        _verify_sites_complex(s1, site1)
        # Retrieve a dictionary specifying the MonomerPattern within the
        # complex that contains the given binding site.
        specsitesdict = _verify_sites_complex(s1, site1)
        s1complexpatub, s1complexpatb = check_sites_comp_build(
            s1, site1, m1, specsitesdict)
        return s1complexpatb, s1complexpatub

    def check_sites_comp_build(s1, site1, m1, specsitesdict):
        # Return error if binding site exists on multiple monomers and a
        # monomer for binding (m1) hasn't been specified.
        if len(specsitesdict) > 1 and m1 is None:
            raise ValueError(
                f"Binding site {site1} present in more than one monomer in complex {s1}."  # noqa: E501
                "Specify variable m1, the monomer used for binding within the complex."
            )
        if not s1.is_concrete:
            raise ValueError("Complex '%s' must be concrete." % (s1))
            # If the given binding site is only present in one monomer in the complex:
        if m1 is None:
            # Build up ComplexPattern for use in rule
            # (with state of given binding site specified).
            s1complexpatub = list(specsitesdict.keys())[0]({site1: None})
            s1complexpatb = list(specsitesdict.keys())[0]({site1: 50})
            for monomer in s1.monomer_patterns:
                if monomer not in specsitesdict.keys():
                    s1complexpatub %= monomer
                    s1complexpatb %= monomer

        # If the binding site is present on more than one monomer in the
        # complex, the monomer must be specified by the user.  Use specified m1
        # to build ComplexPattern.
        else:
            # Make sure binding states of MonomerPattern m1 match those of the
            # monomer within the ComplexPattern s1 (ComplexPattern monomer
            # takes precedence if not).
            i = 0
            identical_monomers = []
            for mon in s1.monomer_patterns:
                # Only change the binding site for the first monomer that
                # matches.  Keep any others unchanged to add to final complex
                # that is returned.
                if mon.monomer.name == m1.monomer.name:
                    i += 1
                    if i == 1:
                        s1complexpatub = m1({site1: None})
                        s1complexpatb = m1({site1: 50})
                    else:
                        identical_monomers.append(mon)
            # Build up ComplexPattern for use in rule (with state of given
            # binding site  on m1 specified).
            for mon in s1.monomer_patterns:
                if mon.monomer.name != m1.monomer.name:
                    s1complexpatub %= mon
                    s1complexpatb %= mon
            if identical_monomers:
                for i in range(len(identical_monomers)):
                    s1complexpatub %= identical_monomers[i]
                    s1complexpatb %= identical_monomers[i]

        return s1complexpatub, s1complexpatb

    # If no complexes exist in the reaction, revert to catalyze().
    if (isinstance(enzyme, MonomerPattern)
            or isinstance(enzyme, Monomer)) and (isinstance(
                substrate, MonomerPattern) or isinstance(substrate, Monomer)):
        _verify_sites(enzyme, e_site)
        _verify_sites(substrate, s_site)
        return catalyze(
            enzyme,
            e_site,
            substrate,
            s_site,
            product,
            klist,
        )

    # Build E:S
    if isinstance(enzyme, ComplexPattern):
        enzymepatb, enzyme_free = build_complex(enzyme, e_site, m1)
    else:
        enzymepatb, enzyme_free = enzyme({e_site: 50}), enzyme({e_site: None})

    if isinstance(substrate, ComplexPattern):
        substratepatb, substratepatub = build_complex(substrate, s_site, m2)
    else:
        substratepatb = substrate({s_site: 50})

    es_complex = enzymepatb % substratepatb

    if isinstance(product, ReactionPattern):
        final_product = product
        final_product += enzyme_free
    else:
        final_product = enzyme_free + product

    # Use bind complex to binding rule.

    components = bind_complex(enzyme, e_site, substrate, s_site, klist[0:2],
                              m1, m2)
    components |= _macro_rule("cleave", es_complex >> final_product,
                              [klist[2]], ["kc"])
    return components