def test_self_displacement_02(self):
        complexes, reactions = read_pil("""
        length x = 10
        length y = 10
        T = x( y x + ) y* x*
        T1 = x( y x + x* y* )
        T2 = x y x( + ) y* x*
        T3 = x( y( x( + ) ) )
        T4 = x y x( + x* y* )
        """)
        T = complexes['T']
        T1 = complexes['T1']
        T2 = complexes['T2']
        T3 = complexes['T3']
        T4 = complexes['T4']
        path1 = PepperReaction([T], [T1], 'branch-3way')
        path1r = PepperReaction([T1], [T], 'branch-3way')
        path2 = PepperReaction([T], [T2], 'branch-3way')
        path2r = PepperReaction([T2], [T], 'branch-3way')
        path3 = PepperReaction([T1], [T3], 'bind11')
        path4 = PepperReaction([T2], [T3], 'bind11')
        path5 = PepperReaction([T1], [T4], 'branch-3way')
        path5r = PepperReaction([T4], [T1], 'branch-3way')
        path6 = PepperReaction([T2], [T4], 'branch-3way')
        path6r = PepperReaction([T4], [T2], 'branch-3way')

        enum = Enumerator([T])
        enum.max_helix = True
        enum.enumerate()
        self.assertEqual(
            sorted(enum.reactions),
            sorted([
                path1, path1r, path2, path2r, path3, path4, path5, path5r,
                path6, path6r
            ]))
    def test_open1N_01(self):
        complexes, reactions = read_pil("""
        length a = 8
        length t = 5

        X = a( t( + ) )
        Y = a( t + t* )
        Z = a t( + ) a*
        S1 = a t 
        S2 = t* a*
        """)
        X = complexes['X']
        Y = complexes['Y']
        Z = complexes['Z']
        S1 = complexes['S1']
        S2 = complexes['S2']
        rxnYS = PepperReaction([Y], [S1, S2], 'open')
        rxnXS = PepperReaction([X], [S1, S2], 'open')
        # max helix semantics ON -> no reactions vs dissociation
        out = open1N(Y, max_helix=True, release_11=7, release_1N=7)
        assert out == []
        out = open1N(Y, max_helix=True, release_11=8, release_1N=8)
        assert out == [rxnYS]
        out = open1N(X, max_helix=True, release_11=13, release_1N=13)
        assert out == [rxnXS]

        rxnXY = PepperReaction([X], [Y], 'open')
        rxnXZ = PepperReaction([X], [Z], 'open')
        # max helix semantics OFF -> domains dissociate, but at most one at a time
        out = open1N(X, max_helix=False, release_11=7, release_1N=7)
        self.assertEqual(out, [rxnXY])
        out = open1N(X, max_helix=False, release_11=8, release_1N=8)
        self.assertEqual(out, sorted([rxnXY, rxnXZ]))
        out = open1N(X, max_helix=False, release_11=13, release_1N=13)
        self.assertEqual(out, sorted([rxnXY, rxnXZ]))
    def test_bind_and_displace3way(self):
        complexes, reactions = read_pil("""
        length a = 10
        length b = 10
        length c = 10
        length t = 5

        I = a b c
        J = b c
        C = b( c( + ) ) a*
        B = a( b c + b( c( + ) ) )
        D = a( b( c( + ) ) )
        """)
        I = complexes['I']
        J = complexes['J']
        C = complexes['C']
        B = complexes['B']
        D = complexes['D']

        # DSD-pathway "bind21"
        path1 = PepperReaction([I, C], [B], 'bind21')
        # DSD-pathway "branch3way"
        path2 = PepperReaction([B], [D, J], 'branch-3way')

        enum = Enumerator(list(complexes.values()))
        enum.enumerate()
        self.assertEqual(sorted(enum.reactions), sorted([path1, path2]))
    def test_bind21_01(self):
        complexes, reactions = read_pil("""
        length a = 10
        length t = 5
        S1 = a t 
        S2 = t* a*
        X = a( t + t* )
        Y = a t( + ) a*
        Z = a( t( + ) )
        """)
        S1 = complexes['S1']
        S2 = complexes['S2']
        X = complexes['X']
        Y = complexes['Y']
        Z = complexes['Z']
        singles = sorted([S1, S2])

        rxn1 = PepperReaction([S2, S1], [X], 'bind21')
        rxn2 = PepperReaction([S1, S2], [Y], 'bind21')
        out = bind21(S1, S2, max_helix=False)
        #for o in out: print(o.kernel_string)
        self.assertEqual(out, sorted([rxn1, rxn2]))

        rxn3 = PepperReaction([S2, S1], [Z], 'bind21')
        out = bind21(S1, S2, max_helix=True)
        self.assertEqual(out, [rxn3])
def bind21(reactant1, reactant2, max_helix=True, remote=None):
    """
    Returns a list of reaction pathways which can be produced by 2-1 binding
    reactions of the argument complexes. The 2-1 binding reaction is the
    hybridization of two complementary unpaired domains, each in a different
    complex, to produce a single, unpseudoknotted product complex containing
    all of the strands contained in either of the original complexes.

    Note: remote is ineffective, but may be set for convencience
    """
    r1_doms = reactant1.available_domains
    r2_doms = reactant2.available_domains

    reactions = []

    # Iterate through all the free domains in reactant1
    for (dom1, strand_num1, dom_num1) in r1_doms:
        # For each, find any domains in reactant2 that could bind
        for (dom2, strand_num2, dom_num2) in r2_doms:
            # If it can pair, this is one possible reaction (this kind of
            # reaction cannot possibly produce a pseudoknotted structure)
            if (dom1.can_pair(dom2)):
                # combine the two complexes into one, but do not perform the association
                reactions.append(
                    join_complexes_21(reactant1, (strand_num1, dom_num1),
                                      reactant2, (strand_num2, dom_num2)))

    output = []
    for complex, location1, location2 in reactions:
        # build "before" and "after" loop structures via find_on_loop ...
        out = find_on_loop(
            complex, location1, lambda (dom1, struct1, loc1),
            (dom2, struct2, loc2): loc1 == location1 and loc2 == location2)

        [(loc1s, before, loc2s, after)] = out

        # zipper for max-helix semantics
        if max_helix:
            loc1s, before, loc2s, after = zipper(complex, loc1s[0], before,
                                                 loc2s[0], after,
                                                 filter_bind11)

        [loc1s, before, loc2s, after] = map(Loop,
                                            [loc1s, before, loc2s, after])

        (product, rotations) = do_bind11(complex, loc1s.locs, loc2s.locs)

        try:
            reaction = PepperReaction(sorted([reactant1, reactant2]),
                                      [product], 'bind21')
        except DSDDuplicationError, e:
            #assert opening_rate(length) == PepperReaction.dictionary[e.solution].rate
            reaction = e.existing

        length = len(loc1s)
        reaction.rate = bimolecular_binding_rate(length)

        output.append(reaction)
示例#6
0
    def rxn(self, string, k = 1, rtype = 'condensed'):
       """ Dummy function for generating reactions between formal species """
       reactants, products = string.split('->')
       reactants = reactants.split('+')
       products = products.split('+')

       reactants = [self.cplx(x) for x in reactants]
       products  = [self.cplx(x) for x in products]
       rxn = PepperReaction(reactants, products, rtype.strip())
       rxn.rate_constant = k
       self.reactions.add(rxn)
    def test_max_helix_02(self):
        complexes, reactions = read_pil("""
        length d1 = 15
        length d4 = 15
        length d6 = 15
        length d7 = 15
        length h8 = 15
        length t0 = 6
        length t2 = 6
        length t3 = 6
        length t5 = 6

        # Initial Complexes
        B2 = d7 t3 d4 t5 
        helper = t3 d7 t3
        PR_FL_B2  = d1 t2( d6( + d7( t3( d4 t5 + ) ) t3* ) )  @ initial 0 M
        
        # Intermediate Complexes
        PR_FLh1B2 = d1 t2( d6( + t3( d7 t3 + d7( t3( d4 t5 + ) ) ) ) )  @ initial 0 M
        PR_FLh2B2 = d1 t2( d6( + t3 d7 t3( + d7( t3( d4 t5 + ) ) ) ) )  @ initial 0 M
        PR_FL_h1w = d1 t2( d6( + t3( d7( t3( + ) ) ) ) )  @ initial 0 M
        
        # sidestuff
        PR_FLB2B2 = d1 t2( d6( + d7 t3( d4 t5 + d7( t3( d4 t5 + ) ) ) ) )  @ initial 0 M

        # casey-semantics
        PR_FLh2B2_v2 = d1 t2( d6( + t3( d7( t3 + d7 t3( d4 t5 + ) ) ) ) )  @ initial 0 M
        PR_FLh2w =     d1 t2( d6( + t3( d7( t3 + t3* ) ) ) )  @ initial 0 M

        """)
        B2 = complexes['B2']
        helper = complexes['helper']
        PR_FL_B2 = complexes['PR_FL_B2']
        PR_FLh1B2 = complexes['PR_FLh1B2']
        PR_FLh2B2 = complexes['PR_FLh2B2']
        PR_FL_h1w = complexes['PR_FL_h1w']
        PR_FLB2B2 = complexes['PR_FLB2B2']
        PR_FLh2B2_v2 = complexes['PR_FLh2B2_v2']
        PR_FLh2w = complexes['PR_FLh2w']

        path1 = PepperReaction([PR_FL_B2, helper], [PR_FLh1B2], 'bind21')
        path1r = PepperReaction([PR_FLh1B2], [PR_FL_B2, helper], 'open')
        path2 = PepperReaction([PR_FL_B2, helper], [PR_FLh2B2], 'bind21')
        path2r = PepperReaction([PR_FLh2B2], [PR_FL_B2, helper], 'open')
        path3 = PepperReaction([PR_FLh1B2], [PR_FL_h1w, B2], 'branch-3way')
        path4 = PepperReaction([PR_FL_B2, B2], [PR_FLB2B2], 'bind21')
        path4r = PepperReaction([PR_FLB2B2], [PR_FL_B2, B2], 'open')
        path5 = PepperReaction([PR_FLh1B2], [PR_FLh2B2], 'branch-3way')
        path6 = PepperReaction([PR_FLh2B2], [PR_FLh1B2], 'branch-3way')

        enum = Enumerator([B2, helper, PR_FL_B2])
        enum.max_helix = True
        enum.enumerate()
        assert sorted(enum.reactions) == sorted(
            [path1, path1r, path2, path2r, path3, path4, path4r, path5, path6])
示例#8
0
    def test_condense_simple(self):
        complexes, reactions = read_pil("""
        # File generated by peppercorn-v0.5.0
        
        # Domain Specifications 
        length d1 = 15
        length t0 = 5
        
        # Resting-set Complexes 
        c1 = t0 d1 
        c2 = d1( + ) t0* 
        c4 = t0( d1( + ) ) 
        c5 = d1 
        
        # Transient Complexes 
        c3 = t0( d1 + d1( + ) ) 
        
        # Detailed Reactions 
        reaction [bind21         =      100 /M/s ] c1 + c2 -> c3
        reaction [open           =       50 /s   ] c3 -> c1 + c2
        reaction [branch-3way    =       50 /s   ] c3 -> c4 + c5
        """)

        # (rs1) c1                c4 (rs3)
        #         \              /
        #          <---> c3 ---->
        #         /              \
        # (rs2) c2                c5 (rs4)

        enum = Enumerator(complexes.values(), reactions)
        enum.enumerate() 
        enum.condense()
        for con in enum.condensed_reactions:
            assert con.rate_constant[0] == 50
        del enum

        # old interface ...
        c1 = PepperMacrostate([complexes['c1']])
        c2 = PepperMacrostate([complexes['c2']])
        c4 = PepperMacrostate([complexes['c4']])
        c5 = PepperMacrostate([complexes['c5']])
        cond_react = PepperReaction([c1, c2], [c4, c5], 'condensed')
        cond_react.rate_constant = 20, None

        enum = Enumerator(complexes.values(), reactions)
        enum.dry_run()
        enumRG = PepperCondensation(enum)
        enumRG.condense()
        for con in enumRG.condensed_reactions:
            assert con.rate_constant[0] == 20
    def test_4way_reject_remote(self):
        # Standard 4way junction, no end-dissociation
        complexes, reactions = read_pil("""
        length a = 10
        length b = 10
        length c = 10
        length d = 10
        length x = 10
        length y = 10
        length z = 10
        A0 = a( x( y( z( b(  + ) ) ) ) c*( + ) x( y( z( d( + ) ) ) ) )
        A1 = a( x( y( z( b(  + ) ) ) x*( c*( + ) ) y( z( d( + ) ) ) ) )
        A2 = a( x( y( z( b(  + ) ) y*( x*( c*( + ) ) ) z( d( + ) ) ) ) )
        A3 = a( x( y( z( b(  + ) z*( y*( x*( c*( + ) ) ) ) d( + ) ) ) ) )
        """)
        A0 = complexes['A0']
        A1 = complexes['A1']
        A2 = complexes['A2']
        A3 = complexes['A3']

        path1 = PepperReaction([A1], [A3], 'branch-4way')
        path2 = PepperReaction([A1], [A0], 'branch-4way')
        output = branch_4way(A1, max_helix=True, remote=False)
        self.assertEqual(output, sorted([path1, path2]))

        path1 = PepperReaction([A2], [A0], 'branch-4way')
        path2 = PepperReaction([A2], [A3], 'branch-4way')
        output = branch_4way(A2, max_helix=True, remote=False)
        self.assertEqual(output, sorted([path1, path2]))

        path = PepperReaction([A3], [A0], 'branch-4way')
        output = branch_4way(A3, max_helix=True, remote=False)
        self.assertEqual(output, [path])

        path1 = PepperReaction([A2], [A0], 'branch-4way')
        path2 = PepperReaction([A2], [A3], 'branch-4way')
        output = branch_4way(A2, max_helix=True, remote=False)
        self.assertEqual(output, sorted([path1, path2]))

        path1 = PepperReaction([A1], [A3], 'branch-4way')
        path2 = PepperReaction([A1], [A0], 'branch-4way')
        output = branch_4way(A1, max_helix=True, remote=True)
        self.assertEqual(output, sorted([path1, path2]))

        path = PepperReaction([A3], [A0], 'branch-4way')
        output = branch_4way(A3, max_helix=True, remote=False)
        self.assertEqual(output, [path])
 def test_3way_02(self):
     complexes, reactions = read_pil("""
     length b = 7
     A = b( b*( b b*( + ) b* ) )
     B = b( b*( b( ) + b b* ) )
     C = b( b*( ) b*( + ) b* b )
     D = b( b*( b b* + b( ) ) )
     """)
     A = complexes['A']
     B = complexes['B']
     C = complexes['C']
     D = complexes['D']
     rxn1 = PepperReaction([A], [B], 'branch-3way')
     rxn2 = PepperReaction([A], [C], 'branch-3way')
     rxn3 = PepperReaction([A], [D], 'branch-3way')
     out = branch_3way(A, max_helix=False)
     assert sorted(out) == sorted([rxn1, rxn2, rxn3])
    def test_cooperative_binding(self):
        complexes, reactions = read_pil("""
        length a = 5
        length x = 10
        length y = 10
        length b = 5

        C = x( y( + b* ) ) a*
        L = a x
        R = y b
        T = x y

        LC = a( x + x( y( + b* ) ) )
         CR = x( y( + y b( + ) ) ) a*
        LCR = a( x + x( y( + y b( + ) ) ) )
        LCF = a( x( + x y( + b* ) ) )
         CRF = x( y + y( b( + ) ) ) a*

        LCRF1 = a( x( + x y( + y b( + ) ) ) )
        LCRF2 = a( x + x( y + y( b( + ) ) ) )
        LR = a( x( + y( b( + ) ) ) )
        """)

        C = complexes['C']
        L = complexes['L']
        R = complexes['R']
        T = complexes['T']
        LC = complexes['LC']
        LCF = complexes['LCF']
        CR = complexes['CR']
        CRF = complexes['CRF']
        LCRF1 = complexes['LCRF1']
        LR = complexes['LR']

        path1 = PepperReaction([L, C], [LC], 'bind21')
        path1r = PepperReaction([LC], [L, C], 'open')
        path2 = PepperReaction([LC], [LCF], 'branch-3way')
        path3 = PepperReaction([R, LCF], [LCRF1], 'bind21')
        path4 = PepperReaction([LCRF1], [LR, T], 'branch-3way')

        enum = Enumerator(list(complexes.values()))
        enum.k_fast = float('inf')
        enum.k_slow = 0
        enum.max_helix = True
        enum.enumerate()
        self.assertEqual(len(list(enum.reactions)), 22)
    def test_open1N_02(self):
        # NOTE this used to be a test for breathing ...
        # Should release-cutoff of 4 mean:
        #   "max-helix-semantics up to length 4"?
        complexes, reactions = read_pil("""
        length a = 3
        length b = 1
        length c = 4
        length ab = 4

        X = a( b( c( + ) ) )
        Y = ab( c( + ) )

        S1 = a b c 
        S2 = c* b* a*
        X1 = a b( c( + ) )  a*
        X2 = a( b  c( + ) b* )
        X3 = a( b( c + c* ) )
        Y1 = ab c( + ) ab*
        Y2 = ab( c + c* )
        """)
        X = complexes['X']
        Y = complexes['Y']
        S1 = complexes['S1']
        S2 = complexes['S2']
        X1 = complexes['X1']
        X2 = complexes['X2']
        X3 = complexes['X3']
        Y1 = complexes['Y1']
        Y2 = complexes['Y2']

        rxn1 = PepperReaction([X], [X1], 'open')
        rxn2 = PepperReaction([X], [X2], 'open')
        rxn3 = PepperReaction([X], [X3], 'open')
        out = open1N(X, max_helix=False, release_11=6, release_1N=6)
        assert sorted(out) == sorted([rxn1, rxn2, rxn3])

        rxn4 = PepperReaction([X], [S1, S2], 'open')
        out = open1N(X, max_helix=True, release_11=8, release_1N=8)
        assert out == [rxn4]

        out = open1N(Y, max_helix=True, release_11=6, release_1N=6)
        assert out == []
 def test_3way_multiple_choice_02(self):
     complexes, reactions = read_pil("""
     length a = 10
     length b = 10
     length c = 10
     length x = 10
     length y = 10
     length z = 10
     N = a( x( b x y + y( z( + ) ) ) )
     P1 = a( x b x( y + y( z( + ) ) ) )
     P2 = a( x( b x y( + y z( + ) ) ) )
     """)
     N = complexes['N']
     P1 = complexes['P1']
     P2 = complexes['P2']
     forward1 = PepperReaction([N], [P1], 'branch-3way')
     forward2 = PepperReaction([N], [P2], 'branch-3way')
     output = branch_3way(N, max_helix=True, remote=True)
     self.assertEqual(sorted(output), sorted([forward1, forward2]))
    def testBranch3wayC(self):
        # 3wayC: ? b*(?) ? b ? <-> ? b*(? b ?) ?
        complexes, _ = read_pil("""
        length b = 15
        length d1 = 15
        length d2 = 15
        length d3 = 15
        length d4 = 15
        A1 = d1( ) b*( d2( ) ) d3( ) b d4( )
        A2 = d1( ) b*( d2( ) b d3( ) ) d4( )
        """)
        forward = branch_3way(complexes['A1'])
        self.assertEqual(forward, [
            PepperReaction([complexes['A1']], [complexes['A2']], 'branch-3way')
        ])

        reverse = branch_3way(complexes['A2'])
        self.assertEqual(reverse, [
            PepperReaction([complexes['A2']], [complexes['A1']], 'branch-3way')
        ])
    def test_bind11_01(self):
        complexes, reactions = read_pil("""
        length a = 10
        length t = 5
        X = a( t + t* )
        Y = a t( + ) a*
        Z = a( t( + ) )
        """)
        X = complexes['X']
        Y = complexes['Y']
        Z = complexes['Z']

        rxnXZ = PepperReaction([X], [Z], 'bind11')
        rxnYZ = PepperReaction([Y], [Z], 'bind11')
        assert bind11(X, max_helix=True) == [rxnXZ]
        assert bind11(Y, max_helix=True) == [rxnYZ]
        assert bind11(Z, max_helix=True) == []
        assert bind11(X, max_helix=True) == [rxnXZ]
        assert bind11(Y, max_helix=True) == [rxnYZ]
        assert bind11(Z, max_helix=True) == []
    def test_3way_remote(self):
        """ 
        A remote 3way branch migration reaction.
        """
        # INPUT
        complexes, reactions = read_pil("""
        length a = 10
        length b = 10
        length c = 10
        length x = 10
        length y = 10
        length z = 10
        X  = a( b x y z + x( y( z( c( + ) ) ) ) )
        I1 = a( b x( y z + x y( z( c( + ) ) ) ) )
        I2 = a( b x( y( z + x y z( c( + ) ) ) ) )
        Y  = a( b x( y( z( + x y z c( + ) ) ) ) )
        """)
        reactant = complexes['X']
        inter1 = complexes['I1']
        inter2 = complexes['I2']
        product = complexes['Y']

        # ~~~~~~~~~~~~~ #
        # OUTPUT REMOTE #
        # ~~~~~~~~~~~~~ #
        forward = PepperReaction([reactant], [product], 'branch-3way')
        backward = PepperReaction([product], [reactant], 'branch-3way')

        output = branch_3way(reactant, max_helix=True, remote=True)
        self.assertEqual(output, [forward])

        output = branch_3way(product, max_helix=True, remote=True)
        self.assertEqual(output, [backward])

        forward = PepperReaction([inter1], [product], 'branch-3way')
        backward = PepperReaction([inter1], [reactant], 'branch-3way')

        output = branch_3way(inter1, max_helix=True, remote=True)
        self.assertEqual(sorted(output), sorted([backward, forward]))

        # ~~~~~~~~~~~~~~~~~~~~ #
        # OUTPUT REJECT REMOTE #
        # ~~~~~~~~~~~~~~~~~~~~ #
        backward = PepperReaction([product], [reactant], 'branch-3way')

        output = branch_3way(reactant, max_helix=True, remote=False)
        self.assertEqual(output, [])
        output = branch_3way(product, max_helix=True, remote=False)
        self.assertEqual(output, [backward])

        forward = PepperReaction([inter1], [product], 'branch-3way')
        backward = PepperReaction([inter1], [reactant], 'branch-3way')

        output = branch_3way(inter1, max_helix=True, remote=False)
        self.assertEqual(sorted(output), sorted([forward, backward]))
    def test_self_displacement_01(self):
        complexes, reactions = read_pil("""
        length x = 10
        length y = 10
        B1 = x( y( x( y x + ) ) )
        B2 = x y x( y( x( + ) ) )
        B3 = x( y( x y x( + ) ) )
        B4 = x( y x y( x( + ) ) )
        """)
        B1 = complexes['B1']
        B2 = complexes['B2']
        B3 = complexes['B3']
        B4 = complexes['B4']
        path1 = PepperReaction([B1], [B4], 'branch-3way')
        path1r = PepperReaction([B4], [B1], 'branch-3way')
        path2 = PepperReaction([B4], [B2], 'branch-3way')
        path3 = PepperReaction([B2], [B3], 'branch-3way')
        path3r = PepperReaction([B3], [B2], 'branch-3way')
        path4 = PepperReaction([B3], [B1], 'branch-3way')

        enum = Enumerator([B1])
        enum.max_helix = True
        enum.enumerate()
        self.assertEqual(sorted(enum.reactions),
                         sorted([path1, path1r, path2, path3, path3r, path4]))
    def test_self_displacement_03(self):
        complexes, reactions = read_pil("""
        length x1 = 10
        length x2 = 10
        length y1 = 10
        length y2 = 10
        B1 = x1( x2( y1( y2( x1( x2( y1 y2 x1 x2 + ) ) ) ) ) )
        B2 = x1 x2 y1 y2 x1( x2( y1( y2( x1( x2( + ) ) ) ) ) )
        i1 = x1( x2( y1 y2 x1 x2 y1( y2( x1( x2( + ) ) ) ) ) )
        i2 = x1( x2( y1( y2( x1 x2 y1 y2 x1( x2( + ) ) ) ) ) )
        """)
        B1 = complexes['B1']
        B2 = complexes['B2']
        i1 = complexes['i1']
        i2 = complexes['i2']
        path1 = PepperReaction([B1], [i1], 'branch-3way')
        path1r = PepperReaction([i1], [B1], 'branch-3way')
        path1f = PepperReaction([i1], [B2], 'branch-3way')
        path2 = PepperReaction([B2], [i2], 'branch-3way')
        path2r = PepperReaction([i2], [B2], 'branch-3way')
        path2f = PepperReaction([i2], [B1], 'branch-3way')

        enum = Enumerator([B1])
        enum.max_helix = True
        enum.enumerate()
        self.assertEqual(
            sorted(enum.reactions),
            sorted([path1, path1r, path1f, path2, path2r, path2f]))
    def test_4way_05(self):
        # Unconventional multi-state 4way junction, no end-dissociation
        complexes, reactions = read_pil("""
        length a = 10
        length b = 10
        length c = 10
        length x = 10
        A1 = a( a*( b( + ) ) a*( x*( + ) ) b( c( + ) ) )
        A2 = a( ) b( + ) a( a*( x*( + ) ) b( c( + ) ) )
        A3 = a( a*( b( + ) a( ) x*( + ) ) b( c( + ) ) )
        A4 = a( a*( b( + ) ) ) x*( + ) a( b( c( + ) ) )
        """)
        A1 = complexes['A1']
        A2 = complexes['A2']
        A3 = complexes['A3']
        A4 = complexes['A4']

        path1 = PepperReaction([A1], [A2], 'branch-4way')
        path2 = PepperReaction([A1], [A3], 'branch-4way')
        path3 = PepperReaction([A1], [A4], 'branch-4way')
        output = branch_4way(A1, max_helix=False)
        self.assertEqual(output, sorted([path1, path2, path3]))

        path1 = PepperReaction([A1], [A2], 'branch-4way')
        path2 = PepperReaction([A1], [A3], 'branch-4way')
        path3 = PepperReaction([A1], [A4], 'branch-4way')
        output = branch_4way(A1, max_helix=True)
        self.assertEqual(output, sorted([path1, path2, path3]))
    def test_bind11_02(self):
        complexes, reactions = read_pil("""
        length a = 10
        length t = 5
        S0  = a a t t* a* a*
        SG1 = a( a t t* ) a* 
        SG2 = a a( t t* a* ) 
        SG3 = a( a( t( ) ) )
        SI1 = a( a t t* a* )
        SI2 = a a( t t* ) a*
        SI3 = a a t( ) a* a*
        """)
        S0 = complexes['S0']
        SG1 = complexes['SG1']
        SG2 = complexes['SG2']
        SG3 = complexes['SG3']
        SI1 = complexes['SI1']
        SI2 = complexes['SI2']
        SI3 = complexes['SI3']

        rg1 = PepperReaction([S0], [SG1], 'bind11')
        rg2 = PepperReaction([S0], [SG2], 'bind11')
        rg3 = PepperReaction([S0], [SG3], 'bind11')
        out = bind11(S0, max_helix=True)
        #for o in out: print(o.kernel_string)
        assert sorted(out) == sorted([rg1, rg2, rg3])

        ri1 = PepperReaction([S0], [SI1], 'bind11')
        ri2 = PepperReaction([S0], [SI2], 'bind11')
        ri3 = PepperReaction([S0], [SI3], 'bind11')
        out = bind11(S0, max_helix=False)
        #for o in out: print(o.kernel_string)
        assert sorted(out) == sorted([rg1, rg2, ri1, ri2, ri3])
    def testBranch4wayA(self):
        # 4way: b( ? ) ? b ( ? ) --> b( ? b*( ? ) ? )
        complexes, _ = read_pil("""
        length b = 15
        length d1 = 15
        length d2 = 15
        length d3 = 15
        length d4 = 15
        length d5 = 15
        A1 = d1( ) b( d2( )  )  d3( ) b( d4( ) ) d5( )
        A2 = d1( ) b( d2( ) b*( d3( ) )  d4( ) ) d5( )
        """)

        forward = branch_4way(complexes['A1'])
        self.assertEqual(forward, [
            PepperReaction([complexes['A1']], [complexes['A2']], 'branch-4way')
        ])

        reverse = branch_4way(complexes['A2'])
        self.assertEqual(reverse, [
            PepperReaction([complexes['A2']], [complexes['A1']], 'branch-4way')
        ])
 def test_4way_01(self):
     complexes, reactions = read_pil("""
     length t0 = short
     length d3 = long
     length d4 = long
     A1 = t0*( d3*( d4*( + ) ) + d3*( t0* d3*( d4*( + ) ) + ) )
     A2 = t0*( d3*( d4*( + ) d3( + ) t0* d3*( d4*( + ) ) + ) )
     """)
     A1 = complexes['A1']
     A2 = complexes['A2']
     rxn = PepperReaction([A1], [A2], 'branch-4way')
     out = branch_4way(A1, max_helix=True, remote=True)
     assert out == [rxn]
    def testOpenNoMaxHelix(self):
        # open:  ? a( ? ) ? -> ? a ? a* ?
        complexes, _ = read_pil("""
        length a = 5
        length b = 5

        # A1 = a( b( ) )
        A1 = a( b( ) )
        A2 = a( b b* )
        A3 = a b( ) a*
        """)

        # Zipping possible
        rxns = open1N(complexes['A1'],
                      max_helix=False,
                      release_11=10,
                      release_1N=10)
        self.assertEqual(
            rxns,
            sorted([
                PepperReaction([complexes['A1']], [complexes['A2']], 'open'),
                PepperReaction([complexes['A1']], [complexes['A3']], 'open')
            ]))
    def testBind11A(self):
        # bind11: a ? a* ? -> a( ? ) ?
        complexes, _ = read_pil("""
        length a = 10
        length b = 10
        length x = 10
        A1 = x( ) a  x( ) a* x( )
        A2 = x( ) a( x( ) )  x( )
        A3 = x( ) a  b  x( ) b* a* x( )
        A4 = x( ) a( b( x( ) )  )  x( )
        """)

        # No zipping possible
        rxns = bind11(complexes['A1'])
        self.assertEqual(
            rxns,
            [PepperReaction([complexes['A1']], [complexes['A2']], 'bind11')])

        # Zipping possible
        rxns = bind11(complexes['A3'])
        self.assertEqual(
            rxns,
            [PepperReaction([complexes['A3']], [complexes['A4']], 'bind11')])
    def test_3way_single(self):
        # A single 3-way branch migration reaction.
        complexes, reactions = read_pil("""
        length a = 10
        length b = 10
        length d = 10
        length x = 10
        X = a( b x + b( d( + ) ) )
        Y = a( b( x + b d( + ) ) )
        """)
        X = complexes['X']
        Y = complexes['Y']
        fw = PepperReaction([X], [Y], 'branch-3way')
        bw = PepperReaction([Y], [X], 'branch-3way')

        out = branch_3way(X, max_helix=True)
        self.assertEqual(out, [fw])
        out = branch_3way(Y, max_helix=True)
        self.assertEqual(out, [bw])
        out = branch_3way(X, max_helix=False)
        self.assertEqual(out, [fw])
        out = branch_3way(Y, max_helix=False)
        self.assertEqual(out, [bw])
    def testOpenB(self):
        # open:  ? a( ? ) ? -> ? a ? a* ?
        complexes, _ = read_pil("""
        length a = 5
        length b = 5
        length x = 15
        length y = 15
        length z = 15

        A1 = x a( y )   z
        A2 = x a  y a* z

        A3 = x a( b( y )  )  z
        A4 = x a  b( y )  a* z
        A5 = x a( b  y b* )  z
        """)

        # No zipping possible
        rxns = open1N(complexes['A1'],
                      max_helix=False,
                      release_11=7,
                      release_1N=7)
        self.assertEqual(
            rxns,
            [PepperReaction([complexes['A1']], [complexes['A2']], 'open')])

        # Zipping possible
        rxns = open1N(complexes['A3'],
                      max_helix=False,
                      release_11=7,
                      release_1N=7)
        self.assertEqual(
            rxns,
            sorted([
                PepperReaction([complexes['A3']], [complexes['A4']], 'open'),
                PepperReaction([complexes['A3']], [complexes['A5']], 'open')
            ]))
 def test_4way_02(self):
     complexes, reactions = read_pil("""
     length a = 10
     length b = 10
     length c = 10
     length x = 10
     length y = 10
     length Y1 = 10
     length Y2 = 10
     length X1 = 10
     length X2 = 10
     B = y*( b*( a*( Y1* + ) b( c( + ) ) Y2* Y1*( + ) a ) )
     A = c* b* X2* X1*( + ) X2 b c y*( b*( a*( Y1* + ) b( c( + ) ) Y2* Y1*( + ) a ) )
     R = c* b* X2* X1*( + ) X2 b c y*( b*( a*( Y1* + ) ) c( + ) b*( Y2* Y1*( + ) a ) )
     """)
     A = complexes['A']
     R = complexes['R']
     fw = PepperReaction([A], [R], 'branch-4way')
     bw = PepperReaction([R], [A], 'branch-4way')
     out = branch_4way(A, max_helix=True, remote=True)
     assert out == [fw]
     #for o in out: print(o, o.kernel_string)
     out = branch_4way(R, max_helix=True, remote=True)
     assert out == [bw]
 def test_3way_01(self):
     complexes, reaction = read_pil("""
     length d11 = long
     length d12 = long
     length d7 = long
     length t6 = short
     length t8 = short
     A = d11  t6( d7 t8 + d12( t6( d7 t8 + ) ) ) d11*( t8*( + d7 ) )
     B = d11( t6( d7 t8 + d12( t6( d7 t8 + ) ) ) )     t8*( + d7 ) d11
     """)
     A = complexes['A']
     B = complexes['B']
     rxn = PepperReaction([A], [B], 'branch-3way')
     out = branch_3way(A, max_helix=True)
     assert out == [rxn]
    def testOpenA(self):
        # open:  ? a( ? ) ? -> ? a ? a* ?
        complexes, _ = read_pil("""
        length a = 5
        length b = 5
        length x = 15
        length y = 15
        length z = 15

        A1 = x( ) a( x )  x( )
        A2 = x( ) a  x a* x( )
        A3 = x a( b( y )  )  z
        A4 = x a  b  y b* a* z
        """)

        # No zipping possible
        self.assertEqual(
            open1N(complexes['A1']),
            [PepperReaction([complexes['A1']], [complexes['A2']], 'open')])

        # Zipping possible
        self.assertEqual(
            open1N(complexes['A3'], release_11=13, release_1N=13),
            [PepperReaction([complexes['A3']], [complexes['A4']], 'open')])
 def test_4way_03(self):
     complexes, reactions = read_pil("""
     # Domain Specifications
     length d1 = 15
     length d2 = 15
     length d3 = 15
     length d4 = 15
     length d5 = 15
     length d6 = 15
     length t0 = 6
     BUG = d4*( t0* + ) t0( + ) d4*( t0*( + ) ) 
     FIX = d4*( t0* + d4( t0( + ) ) t0*( + ) )
     """)
     BUG = complexes['BUG']
     FIX = complexes['FIX']
     rxn = PepperReaction([BUG], [FIX], 'branch-4way')
     output = branch_4way(BUG, max_helix=True, remote=True)
     self.assertEqual(output, [rxn])