Example #1
0
def computeG(rna,F,Z):
  G = {}; n = len(rna); rna = '$'+rna
  #-------------------------------------------
  #Initialization to zero
  for d in range(n):         #d in [0,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d
      for ch in NUCL:
        for x in range(n+1):
          G[(i,j,ch,x)] = 0
  #-------------------------------------------
  #Recursions
  for d in range(4,n):       #d in [4,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d                #note that num elements in [i,j] is d+1
      for ch in NUCL:
        for x in range(d+1-4+1):   #x in [0,d+1-4]
          #Case 1: positions j-3,j-2,j-1,j are unpaired in S
          G[(i,j,ch,x)] = F[(i,j-4,ch,x)]
          #Case 2: j-4+u is paired, but j-4+u+1,...,j are unpaired in S
          for u in range(1,5):     #u in [1,4], consider 4-u unpaired in suffix
            #Subcase A: (i,j-4+u) is base pair in S
            if x==0 and j-4+u-i>THETA and basePair(rna[i],rna[j-4+u]):
              G[(i,j,ch,x)] += Z[(i+1,j-4+u-1)]
            #Subcase B: (k,j-4+u) is base pair in S, some k in [i+1,j-4+u-4]
            for k in range(i+1,j-4+u-4+1):     #k in [i+1,(j-4+u)-4]
              if j-4+u-k>THETA and basePair(rna[k],rna[j-4+u]):
                G[(i,j,ch,x)] += F[(i,k-1,ch,x)]*Z[(k+1,j-4+u-1)]
  return G
Example #2
0
def computeJ(rna,Z,FF):
  #J(i,j,ch,x) is num str S on [i,j] having x visible occ of a nucl [i,j-4]
  #which can basepair with rna[j] and in which j is unpaired in S.
  #WARNING: J(i,j,ch,0) defined to be zero if i <= j <= i+3
  J = {}; n = len(rna); rna = '$'+rna
  #-------------------------------------------
  #Initialization to zero
  for d in range(n):         #d in [0,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d
      for ch in NUCL:
        for x in range(n+1):
          J[(i,j,ch,x)] = 0
  #-------------------------------------------
  #Recursions
  for d in range(4,n):       #d in [4,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d                #note that num elements in [i,j] is d+1
      for ch in NUCL:
        for x in range(d+1-4+1):   #x in [0,d+1-4]
          #Case 1: positions j-3,j-2,j-1,j are unpaired in S
          J[(i,j,ch,x)] = FF[(i,j-4,ch,x)]
          #Case 2: j-4+u is paired, but j-4+u+1,...,j are unpaired in S
          for u in range(1,4):     #u in [1,3], consider 4-u unpaired in suffix
            #Subcase A: (i,j-4+u) is base pair in S
            if x==0 and j-4+u-i>THETA and basePair(rna[i],rna[j-4+u]):
              J[(i,j,ch,x)] += Z[(i+1,j-4+u-1)]
            #Subcase B: (k,j-4+u) is base pair in S, some k in [i+1,j-4+u-4]
            for k in range(i+1,j-4+u-4+1):     #k in [i+1,(j-4+u)-4]
              if j-4+u-k>THETA and basePair(rna[k],rna[j-4+u]):
                J[(i,j,ch,x)] += FF[(i,k-1,ch,x)]*Z[(k+1,j-4+u-1)]
  return J 
Example #3
0
def computeEprime(rna,Z,E): 
  #Eprime(i,j) is sum over str on [i,j] sum over base pairs (x,y) in S
  #I[(x,y) external in S and y <= j-4, AND j unpaired in S]
  Eprime = {}; n = len(rna); rna = '$'+rna
  #-------------------------------------------
  #Initialization to zero
  for d in range(n):         #d in [0,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d
      Eprime[(i,j)] = 0
  #-------------------------------------------
  #Recursions
  for d in range(4,n):       #d in [4,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d                #note that num elements in [i,j] is d+1
      #Case 1: positions j-3,j-2,j-1,j are unpaired in S
      Eprime[(i,j)] = E[(i,j-4)]
      #Case 2: j-4+u is paired, but j-4+u+1,...,j are unpaired in S
      for u in range(1,4):     #u in [1,3], consider 4-u unpaired in suffix
        #Subcase A: (i,j-4+u) is base pair in S
        if j-4+u-i>THETA and basePair(rna[i],rna[j-4+u]):
          Eprime[(i,j)] += 0   #left here for clarity
        #Subcase B: (k,j-4+u) is base pair in S, some k in [i+1,j-4+u-4]
        for k in range(i+1,j-4+u-4+1):     #k in [i+1,(j-4+u)-4]
          if j-4+u-k>THETA and basePair(rna[k],rna[j-4+u]):
            Eprime[(i,j)] += E[(i,k-1)]*Z[(k+1,j-4+u-1)]
  return Eprime
Example #4
0
def computeERprime(rna,Z,ER): 
  #ERprime(i,j,ch) is sum over str on [i,j] sum over base pairs (x,y) in S 
  #I[ S on [i,j], (x,y) external in S, y <= j-4, j unpaired in S and
  #   y basepairs with ch]
  ERprime = {}; n = len(rna); rna = '$'+rna
  #-------------------------------------------
  #Initialization to zero
  for d in range(n):         #d in [0,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      for ch in NUCL:
        j = i+d
        ERprime[(i,j,ch)] = 0
  #-------------------------------------------
  #Recursions
  for ch in NUCL:
    for d in range(4,n):       #d in [4,n-1]
      for i in range(1,n+1-d): #i in [1,n-d]
        j = i+d                #note that num elements in [i,j] is d+1
        #Case 1: positions j-3,j-2,j-1,j are unpaired in S
        ERprime[(i,j,ch)] = ER[(i,j-4,ch)]
        #Case 2: j-4+u is paired, but j-4+u+1,...,j are unpaired in S
        for u in range(1,4):     #u in [1,3], consider 4-u unpaired in suffix
          #Subcase A: (i,j-4+u) is base pair in S
          if j-4+u-i>THETA and basePair(rna[i],rna[j-4+u]):
            ERprime[(i,j,ch)] += 0   #left here for clarity
          #Subcase B: (k,j-4+u) is base pair in S, some k in [i+1,j-4+u-4]
          for k in range(i+1,j-4+u-4+1):     #k in [i+1,(j-4+u)-4]
            ok = j-4+u-k>THETA and basePair(rna[k],rna[j-4+u])
            #WARNING: It is an ERROR to additionally require that
            #basePair(ch,rna[j-4+u]), since j-4+u too close to j and so
            #can't base pair with it.
            if ok:
              ERprime[(i,j,ch)] += ER[(i,k-1,ch)]*Z[(k+1,j-4+u-1)]
  return ERprime
Example #5
0
def numNborsNoShift(rna, Z):
    #Q[(i,j)] = sum_x N(x), where x is sec str of rna[i:j+1] without shift
    #Z[(i,j)] = number of sec str of rna[i:j+1]
    Q = {}
    n = len(rna)
    rna = '$' + rna  #add dummy character
    #base case j-i in [0,1,2,3]
    for i in range(1, n + 1):
        for d in range(0, min(THETA, n - i) + 1):
            j = i + d
            Q[(i, j)] = 0.0
    #inductive case j-i > 3, compute Q[(i,j)] all 1<=i<=j<=n
    for d in range(THETA + 1, n + 1):
        for i in range(1, n + 1):
            j = i + d
            if (j > n): break
            q = Q[(i, j - 1)]
            if basePair(rna[i], rna[j]):
                q += 2 * Z[(i + 1, j - 1)] + Q[(i + 1, j - 1)]
            for k in range(i + 1, j - THETA):
                if basePair(rna[k], rna[j]):
                    q += 2 * Z[(i, k - 1)] * Z[(k + 1, j - 1)] + Z[
                        (i, k - 1)] * Q[(k + 1, j - 1)] + Q[(i, k - 1)] * Z[
                            (k + 1, j - 1)]
            Q[(i, j)] = q
    return Q[(1, n)]
Example #6
0
def computeEright(rna,Z): 
  #ER(i,j,ch) = sum_S sum_{(x,y)} 
  #   I[(x,y) external in S, y basepairs with ch]
  ER  = {}
  n   = len(rna)
  rna = '$'+rna
  #initialize
  for i in range(1,n+1):
    for j in range(i,n+1):
      for ch in NUCL:
        ER[(i,j,ch)] = 0
  #fill
  for ch in NUCL:             
    for d in range(THETA+1,n): #d in [4,n-1]
      for i in range(1,n-d+1): #i in [1,n-d]
        j = i+d
        sum = ER[(i,j-1,ch)]
        if basePair(rna[i],rna[j]) and basePair(rna[j],ch):
          sum += Z[(i+1,j-1)]
        for k in range(i+1,j-THETA):# k in [i+1..j-THETA-1]
          if basePair(rna[k],rna[j]):
            sum += ER[(i,k-1,ch)]*Z[(k+1,j-1)]
            if basePair(rna[j],ch):
              sum += Z[(i,k-1)]*Z[(k+1,j-1)]
#            sum += (ER[(i,k-1,ch)]+Z[(i,k-1)])*Z[(k+1,j-1)]
        ER[(i,j,ch)] = sum
  return ER
Example #7
0
def computeFF(rna,Z):  
  #Compute the function FF(i,j,ch,x) defined to be the
  #num str on [i,j] having x visible occurrences of a nucleotide 
  #which can basepair with x. Note the difference with computeF(rna,Z)!!!
  FF  = {}
  n   = len(rna)
  rna = '$'+rna
  #initialization
  #----------------------------------------------
  #initialize all entries to 0
  for i in range(1,n+1):        #i in [1,n]
    for j in range(i,n+1):      #j in [i,n]
      for ch in NUCL:
        for x in range(n+1):    #x in [0,n]
          FF[(i,j,ch,x)] = 0
  #----------------------------------------------
  #Base case: define FF(i,j,ch,x) for i=j
  for i in range(1,n+1):        #i in [1,n]
    for ch in NUCL:
      if basePair(ch,rna[i]):
        FF[(i,i,ch,1)] = 1
      else:
        FF[(i,i,ch,0)] = 1
  #----------------------------------------------
  #Base case: define FF(i,j,ch,x) for i<j<i+4
  for i in range(1,n+1):        #i in [1,n]
    for j in range(i+1,min(n,i+3)+1):    #j in [i+1,min(n,i+3)]
      for ch in NUCL:
        for x in range(j-i+2): #x in [0,j-i+1]
          if basePair(ch,rna[j]):
            if x>0:
              FF[(i,j,ch,x)] = FF[(i,j-1,ch,x-1)]
          else:
            FF[(i,j,ch,x)]   = FF[(i,j-1,ch,x)]
  #----------------------------------------------
  #Inductive case: define FF(i,j,ch,x) for j>=i+4
  for d in range(4,n):       #d in [4,n-1]
    for i in range(1,n-d+1): #i in [1,n-d]
      j = i+d                #note that [i,j] contains d+1 elements
      #Case 1: j unpaired in [i,j]
      for ch in NUCL:
        for x in range(d+2):              #x in [0,d+1]
          if basePair(ch,rna[j]):
            if x>0:
              FF[(i,j,ch,x)] = FF[(i,j-1,ch,x-1)]
          else:
            FF[(i,j,ch,x)]   = FF[(i,j-1,ch,x)]
      #Case 2: (i,j) is base pair in S
      if basePair(rna[i],rna[j]):
        for ch in NUCL:
          FF[(i,j,ch,0)] += Z[(i+1,j-1)] 
      #Case 3: (k,j) is base pair in S for k in [i+1,j-4]
      for k in range(i+1,j-3):       #k in [i+1,j-4]
        if basePair(rna[k],rna[j]):
          for ch in NUCL:
            for x in range(k-i+1):  #x in [0,k-i], where k-i num elem in [i,k-1]
              FF[(i,j,ch,x)] += FF[(i,k-1,ch,x)]*Z[(k+1,j-1)]
  return FF
Example #8
0
def numShifts(rna, secStr):  #brute force computation of number shifts
    #rna and secStr is 1-indexed
    if VERBOSE_PRINT:
        print "Sec str: %s" % secStr
    n = len(rna)
    rna0 = rna
    secStr0 = secStr
    rna = '$' + rna
    secStr = '$' + secStr
    SS = basePairList(secStr)
    num = 0
    tempSS = copy.deepcopy(SS)
    for (i, j) in SS:
        tempSS.remove((i, j))
        if VERBOSE_PRINT:
            print "Remove (%d,%d) from %s" % (i, j, secStr[1:])
        for x in range(1, n + 1):
            if abs(i - x) > THETA and x != j and basePair(rna[i], rna[x]):
                if i < x:
                    tempSS.append((i, x))
                    if isSecStr(tempSS):
                        num += 1
                        if VERBOSE_PRINT:
                            ss = basePairList2dotBracketNotation(rna0, tempSS)
                            print '(%d,%d)\t%s' % (i, x, ss)
                    tempSS.remove((i, x))
                else:  #i>x
                    tempSS.append((x, i))
                    if isSecStr(tempSS):
                        num += 1
                        if VERBOSE_PRINT:
                            ss = basePairList2dotBracketNotation(rna0, tempSS)
                            print '(%d,%d)\t%s' % (x, i, ss)
                    tempSS.remove((x, i))
            elif abs(j - x) > THETA and x != i and basePair(rna[j], rna[x]):
                if j < x:
                    tempSS.append((j, x))
                    if isSecStr(tempSS):
                        num += 1
                        if VERBOSE_PRINT:
                            ss = basePairList2dotBracketNotation(rna0, tempSS)
                            print '(%d,%d)\t%s' % (j, x, ss)
                    tempSS.remove((j, x))
                else:  #j>x
                    tempSS.append((x, j))
                    if isSecStr(tempSS):
                        num += 1
                        if VERBOSE_PRINT:
                            ss = basePairList2dotBracketNotation(rna0, tempSS)
                            print '(%d,%d)\t%s' % (x, j, ss)
                    tempSS.remove((x, j))
        tempSS.append((i, j))  #put back the base pair temporarily removed
    if PRINT:
        print "%s has %s shifts" % (secStr[1:], num
                                    )  #recall '$' prepended to secStr
    return num
def numShifts(rna,secStr): #brute force computation of number shifts
  #rna and secStr is 1-indexed
  if VERBOSE_PRINT:
    print "Sec str: %s" % secStr
  n      = len(rna)
  rna0   = rna
  secStr0= secStr
  rna    = '$'+rna
  secStr = '$'+secStr
  SS   = basePairList(secStr)
  num  = 0; tempSS = copy.deepcopy(SS)
  for (i,j) in SS:
    tempSS.remove( (i,j) )
    if VERBOSE_PRINT:
      print "Remove (%d,%d) from %s" % (i,j,secStr[1:])
    for x in range(1,n+1):
      if abs(i-x)>THETA and x!=j and basePair(rna[i],rna[x]):
        if i<x:
          tempSS.append( (i,x) )
          if isSecStr(tempSS): 
            num += 1
            if VERBOSE_PRINT:
              ss = basePairList2dotBracketNotation(rna0,tempSS)
              print '(%d,%d)\t%s' % (i,x,ss)
          tempSS.remove( (i,x) )
        else: #i>x
          tempSS.append( (x,i) )
          if isSecStr(tempSS): 
            num += 1
            if VERBOSE_PRINT:
              ss = basePairList2dotBracketNotation(rna0,tempSS)
              print '(%d,%d)\t%s' % (x,i,ss)
          tempSS.remove( (x,i) )
      elif abs(j-x)>THETA and x!= i and basePair(rna[j],rna[x]):
        if j<x:
          tempSS.append( (j,x) )
          if isSecStr(tempSS): 
            num += 1
            if VERBOSE_PRINT:
              ss = basePairList2dotBracketNotation(rna0,tempSS)
              print '(%d,%d)\t%s' % (j,x,ss)
          tempSS.remove( (j,x) )
        else: #j>x
          tempSS.append( (x,j) )
          if isSecStr(tempSS): 
            num += 1
            if VERBOSE_PRINT:
              ss = basePairList2dotBracketNotation(rna0,tempSS)
              print '(%d,%d)\t%s' % (x,j,ss)
          tempSS.remove( (x,j) )
    tempSS.append( (i,j) ) #put back the base pair temporarily removed
  if PRINT: 
    print "%s has %s shifts" % (secStr[1:],num) #recall '$' prepended to secStr
  return num
Example #10
0
def computeE(rna,Z): 
  #function E(i,j) = sum_S sum_{(x,y)} I[ (x,y) external in S] 
  E   = {}
  n   = len(rna)
  rna = '$'+rna
  #initialize
  for i in range(1,n+1):
    for j in range(i,n+1):
      E[(i,j)] = 0
  #fill
  for d in range(THETA+1,n): #d in [4,n-1]
    for i in range(1,n-d+1): #i in [1,n-d]
      j = i+d
      sum = E[(i,j-1)]
      if basePair(rna[i],rna[j]):
        sum += Z[(i+1,j-1)]
      for k in range(i+1,j-THETA):# k in [i+1..j-THETA-1]
        if basePair(rna[k],rna[j]):
          sum += (E[(i,k-1)]+Z[(i,k-1)])*Z[(k+1,j-1)]
      E[(i,j)] = sum
  return E
def partFunInner(rna):  
  #Z[(i,j)] is number of sec str of rna[i...j], using array n x n
  Z   = {}
  n   = len(rna)
  rna = '$'+rna
  #initialize
  for i in range(1,n+1):
    for j in range(1,n+1):
      Z[(i,j)] = 1L
  #fill
  for d in range(THETA+1,n): #d in [4,n-1]
    for i in range(1,n-THETA): #i in [1,n-THETA-1]
      j = i+d
      if j>n: break
      sum = Z[(i,j-1)]
      if (j-i>THETA):
        if basePair(rna[i],rna[j]):
          sum += Z[(i+1,j-1)]
        for k in range(i+1,j-THETA):# k in [i+1..j-THETA-1]
          if basePair(rna[k],rna[j]):
            sum += Z[(i,k-1)]*Z[(k+1,j-1)]
        Z[(i,j)] = sum
  return Z
Example #12
0
def partFunInner(rna):
    #Z[(i,j)] is number of sec str of rna[i...j], using array n x n
    Z = {}
    n = len(rna)
    rna = '$' + rna
    #initialize
    for i in range(1, n + 1):
        for j in range(1, n + 1):
            Z[(i, j)] = 1L
    #fill
    for d in range(THETA + 1, n):  #d in [4,n-1]
        for i in range(1, n - THETA):  #i in [1,n-THETA-1]
            j = i + d
            if j > n: break
            sum = Z[(i, j - 1)]
            if (j - i > THETA):
                if basePair(rna[i], rna[j]):
                    sum += Z[(i + 1, j - 1)]
                for k in range(i + 1, j - THETA):  # k in [i+1..j-THETA-1]
                    if basePair(rna[k], rna[j]):
                        sum += Z[(i, k - 1)] * Z[(k + 1, j - 1)]
                Z[(i, j)] = sum
    return Z
def numNborsNoShift(rna,Z):  
  #Q[(i,j)] = sum_x N(x), where x is sec str of rna[i:j+1] without shift
  #Z[(i,j)] = number of sec str of rna[i:j+1]
  Q = {}; 
  n   = len(rna)
  rna = '$'+rna #add dummy character
  #base case j-i in [0,1,2,3]
  for i in range(1,n+1):
    for d in range(0,min(THETA,n-i)+1):
      j = i+d
      Q[(i,j)]=0.0
  #inductive case j-i > 3, compute Q[(i,j)] all 1<=i<=j<=n
  for d in range(THETA+1,n+1):
    for i in range(1,n+1):
      j = i+d
      if (j>n): break
      q = Q[(i,j-1)] 
      if basePair(rna[i],rna[j]):
        q += 2*Z[(i+1,j-1)]+Q[(i+1,j-1)]
      for k in range(i+1,j-THETA):
        if basePair(rna[k],rna[j]):
          q += 2*Z[(i,k-1)]*Z[(k+1,j-1)]+Z[(i,k-1)]*Q[(k+1,j-1)]+Q[(i,k-1)]*Z[(k+1,j-1)]
      Q[(i,j)] = q
  return Q[(1,n)]
def computeEold(rna,Z): 
  #function E(i,j) = sum_S sum_{(x,y)} I[ (x,y) external in S] 
  E   = {}
  n   = len(rna)
  rna = '$'+rna
  #initialize
  for i in range(1,n+1):
    for j in range(1,n+1):
      E[(i,j)] = 0L
  #fill
  for d in range(THETA+1,n): #d in [4,n-1]
    for i in range(1,n-THETA): #i in [1,n-THETA-1]
      j = i+d
      if j>n: break
      sum = E[(i,j-1)]
      if basePair(rna[i],rna[j]):
        sum += Z[(i+1,j-1)] 
        #Tricky: contribution comes from 3rd term in derivation of E
        #Contribution from 2nd term in derivation of E is ZERO
      for k in range(i+1,j-THETA):# k in [i+1..j-THETA-1]
        if basePair(rna[k],rna[j]):
          sum += (E[(i,k-1)]+Z[(i,k-1)])*Z[(k+1,j-1)]
      E[(i,j)] = sum
  return E
Example #15
0
def computeEold(rna, Z):
    #function E(i,j) = sum_S sum_{(x,y)} I[ (x,y) external in S]
    E = {}
    n = len(rna)
    rna = '$' + rna
    #initialize
    for i in range(1, n + 1):
        for j in range(1, n + 1):
            E[(i, j)] = 0L
    #fill
    for d in range(THETA + 1, n):  #d in [4,n-1]
        for i in range(1, n - THETA):  #i in [1,n-THETA-1]
            j = i + d
            if j > n: break
            sum = E[(i, j - 1)]
            if basePair(rna[i], rna[j]):
                sum += Z[(i + 1, j - 1)]
                #Tricky: contribution comes from 3rd term in derivation of E
                #Contribution from 2nd term in derivation of E is ZERO
            for k in range(i + 1, j - THETA):  # k in [i+1..j-THETA-1]
                if basePair(rna[k], rna[j]):
                    sum += (E[(i, k - 1)] + Z[(i, k - 1)]) * Z[(k + 1, j - 1)]
            E[(i, j)] = sum
    return E
def numBasePairAdditionsRemovals(rna,secStr): #brute force
  #rna and secStr is 1-indexed
  if PRINTbasepairadditionsremovals: 
    print "Sec str: %s" % secStr
  n      = len(rna)
  rna0   = rna
  rna    = '$'+rna
  secStr = '$'+secStr
  SS     = basePairList(secStr)
  num    = len(SS); tempSS = copy.deepcopy(SS)
  for x in range(1,n-THETA):
    for y in range(x+THETA+1,n+1):
      if basePair(rna[x],rna[y]):
        if (x,y) not in tempSS:
          tempSS.append( (x,y) )
          if isSecStr(tempSS): 
            num += 1
            if PRINTbasepairadditionsremovals: 
              ss = basePairList2dotBracketNotation(rna0,tempSS)
              print '(%d,%d)\t%s' % (x,y,ss)
          tempSS.remove( (x,y) )
  return num
Example #17
0
def numBasePairAdditionsRemovals(rna, secStr):  #brute force
    #rna and secStr is 1-indexed
    if PRINTbasepairadditionsremovals:
        print "Sec str: %s" % secStr
    n = len(rna)
    rna0 = rna
    rna = '$' + rna
    secStr = '$' + secStr
    SS = basePairList(secStr)
    num = len(SS)
    tempSS = copy.deepcopy(SS)
    for x in range(1, n - THETA):
        for y in range(x + THETA + 1, n + 1):
            if basePair(rna[x], rna[y]):
                if (x, y) not in tempSS:
                    tempSS.append((x, y))
                    if isSecStr(tempSS):
                        num += 1
                        if PRINTbasepairadditionsremovals:
                            ss = basePairList2dotBracketNotation(rna0, tempSS)
                            print '(%d,%d)\t%s' % (x, y, ss)
                    tempSS.remove((x, y))
    return num
Example #18
0
def computeQ(rna, Z):
    FF = computeFF(rna, Z)
    J = computeJ(rna, Z, FF)
    EL = computeEleft(rna, Z)
    ER = computeEright(rna, Z)
    ERprime = computeERprime(rna, Z, ER)
    #--------------------------------------------
    #E[(i,j) = sum_S sum_{(x,y)} I[(x,y) external in S]
    #
    #Ebis[(i,j) = sum_S sum_{(x,y)} I[(x,y) external in S, y<n]
    #
    #Eprime[(i,j) = sum_S sum_{(x,y)}
    #        I[(x,y) external in S, y <= j-4, j unpaired]
    #EL[(i,j) = sum_S sum_{(x,y)}
    #        I[(x,y) external in S, x basepairs with rna[n]]
    #ER[(i,j) = sum_S sum_{(x,y)}
    #        I[(x,y) external in S, y basepairs with rna[n]]
    #ERprime[(i,j) = sum_S sum_{(x,y)}
    #  I[(x,y) external in S, y basepairs with rna[n], y<=j-4, n unpaired in S]
    Q = {}
    n = len(rna)
    rna = '$' + rna
    #-------------------------------------------
    #Initialization to zero
    for d in range(n):  #d in [0,n-1]
        for i in range(1, n + 1 - d):  #i in [1,n-d]
            j = i + d
            Q[(i, j)] = 0
    #-------------------------------------------
    #Recursions
    for d in range(THETA + 1, n):  #d in [4,n-1]
        for i in range(1, n + 1 - d):  #i in [1,n-d]
            j = i + d
            #Case 1: first term Q(i,j-1)
            Q[(i, j)] = Q[(i, j - 1)]
            if PRINT:
                print "\n\n", Q[(i, j - 1)], "\tQ(%d,%d)" % (i, j - 1)
            #Case 2: second term 2 * sum_k z(i,k-1)*z(k+1,j-1)
            sum = 0
            if basePair(rna[i], rna[j]):
                sum += Z[(i + 1, j - 1)]
            for k in range(i + 1, j - 3):  #k in [i+1,j-4]
                if basePair(rna[k], rna[j]):
                    sum += Z[(i, k - 1)] * Z[(k + 1, j - 1)]
            Q[(i, j)] += 2 * sum
            if PRINT:
                text = "\t2 sum_{k=%s}^{%s-4} z(%s,k-1)*z(k+1,%s-1)"
                print(2 * sum), text % (i, j, i, j)
            #Case 3: 2*EL[(i,j-1)]+2*ERprime[(i,j)]
            sum = 2 * EL[(i, j - 1, rna[j])] + 2 * ERprime[(i, j, rna[j])]
            Q[(i, j)] += sum
            if PRINT:
                text1 = "%s\t" % sum
                text2 = "2*EL[(%s,%s-1,%s)]+2*ERprime[(%s,%s,%s)]"
                text2 = text2 % (i, j, rna[j], i, j, rna[j])
                print text1, text2
                text1 = " %s\t" % 2 * EL[(i, j - 1, rna[j])]
                text2 = "2*EL[(%s,%s-1,%s)]" % (i, j, rna[j])
                print text1, text2
                text1 = " %s\t" % 2 * ERprime[(i, j, rna[j])]
                text2 = "2*ERprime[(%s,%s,%s)]" % (i, j, rna[j])
                print text1, text2
            #Case 4: fourth term is sum_{x=2}^{n-4} x*(x-1)*H(1,n,ch,x)
            sum = 0
            for x in range(2, j - i + 1 - 3):  #x in [2,j-i+1-4]
                sum += x * (x - 1) * J[(i, j, rna[j], x)]
            Q[(i, j)] += sum
            newsum = 0
            if PRINT:
                text = "\tch\tx\tx-1\tJ(%s,%s,ch,x)\tsum_ch sum_x x(x-1)J(%s,%s,ch,x)"
                print sum, "\tch\tx\tx-1\tJ(1,n,ch,x)\tsum_ch sum_x x(x-1)J(1,n,ch,x)"
                ch = rna[j]
                for x in range(2, j - i + 1 - 3):  #x in [2,j-i+1-4]
                    print "\t%s\t%s\t%s\t%s = \t%s" % (ch, x, x - 1, J[
                        (1, n, ch, x)], x * (x - 1) * J[(1, n, ch, x)])
            #Case 5: fifth term
            #sum_{k=1}^{n-\theta-1} \left( z(k-1) \cdot Q(n-k-1) \right) +
            #\left( Q(k-1) \cdot z(n-k-1) \right)
            #Case 5a: (i,j) paired
            sum = 0
            if basePair(rna[i], rna[j]):
                sum += Q[(i + 1, j - 1)]
            for k in range(i + 1, j - 3):  #k in [i+1,j-4]
                if basePair(rna[k], rna[j]):
                    sum += (Z[(i, k - 1)] * Q[(k + 1, j - 1)]) + (Q[
                        (i, k - 1)] * Z[(k + 1, j - 1)])
            Q[(i, j)] += sum
            if PRINT:
                text = "sum_k (Z[(%s,k-1)]*Q[(k+1,%s-1)])+(Q[(%s,k-1)]*Z[(k+1,%s-1)])"
                text = text % (i, j, i, j)
                print "%s\t%s" % (sum, text)
    return Q
def computeQ(rna,Z):
  FF      = computeFF(rna,Z) 
  J       = computeJ(rna,Z,FF)
  EL      = computeEleft(rna,Z)
  ER      = computeEright(rna,Z)
  ERprime = computeERprime(rna,Z,ER)
  #--------------------------------------------
  #E[(i,j) = sum_S sum_{(x,y)} I[(x,y) external in S]
  # 
  #Ebis[(i,j) = sum_S sum_{(x,y)} I[(x,y) external in S, y<n]
  #
  #Eprime[(i,j) = sum_S sum_{(x,y)} 
  #        I[(x,y) external in S, y <= j-4, j unpaired]
  #EL[(i,j) = sum_S sum_{(x,y)} 
  #        I[(x,y) external in S, x basepairs with rna[n]]
  #ER[(i,j) = sum_S sum_{(x,y)} 
  #        I[(x,y) external in S, y basepairs with rna[n]]
  #ERprime[(i,j) = sum_S sum_{(x,y)} 
  #  I[(x,y) external in S, y basepairs with rna[n], y<=j-4, n unpaired in S]
  Q = {}
  n   = len(rna)
  rna = '$'+rna
  #-------------------------------------------
  #Initialization to zero
  for d in range(n):         #d in [0,n-1]
    for i in range(1,n+1-d): #i in [1,n-d]
      j = i+d
      Q[(i,j)]=0
  #-------------------------------------------
  #Recursions
  for d in range(THETA+1,n):         #d in [4,n-1]
    for i in range(1,n+1-d):         #i in [1,n-d]
      j = i+d
      #Case 1: first term Q(i,j-1)
      Q[(i,j)] = Q[(i,j-1)]
      if PRINT:
        print "\n\n",Q[(i,j-1)], "\tQ(%d,%d)" % (i,j-1)
      #Case 2: second term 2 * sum_k z(i,k-1)*z(k+1,j-1)
      sum = 0
      if basePair(rna[i],rna[j]):
        sum += Z[(i+1,j-1)]
      for k in range(i+1,j-3): #k in [i+1,j-4]
        if basePair(rna[k],rna[j]):
          sum += Z[(i,k-1)]*Z[(k+1,j-1)]
      Q[(i,j)] += 2*sum
      if PRINT:
        text = "\t2 sum_{k=%s}^{%s-4} z(%s,k-1)*z(k+1,%s-1)" 
        print (2*sum),text % (i,j,i,j)
      #Case 3: 2*EL[(i,j-1)]+2*ERprime[(i,j)]
      sum = 2*EL[(i,j-1,rna[j])]+2*ERprime[(i,j,rna[j])]
      Q[(i,j)] += sum
      if PRINT:
        text1 = "%s\t" % sum
        text2 = "2*EL[(%s,%s-1,%s)]+2*ERprime[(%s,%s,%s)]" 
        text2 = text2 % (i,j,rna[j],i,j,rna[j])
        print text1,text2
        text1 = " %s\t" % 2*EL[(i,j-1,rna[j])]
        text2 = "2*EL[(%s,%s-1,%s)]" % (i,j,rna[j])
        print text1,text2
        text1 = " %s\t" % 2*ERprime[(i,j,rna[j])]
        text2 = "2*ERprime[(%s,%s,%s)]" % (i,j,rna[j])
        print text1,text2
      #Case 4: fourth term is sum_{x=2}^{n-4} x*(x-1)*H(1,n,ch,x)
      sum = 0
      for x in range(2,j-i+1-3): #x in [2,j-i+1-4]
        sum += x*(x-1)*J[(i,j,rna[j],x)]
      Q[(i,j)] += sum 
      newsum = 0
      if PRINT:
        text = "\tch\tx\tx-1\tJ(%s,%s,ch,x)\tsum_ch sum_x x(x-1)J(%s,%s,ch,x)"
        print sum,"\tch\tx\tx-1\tJ(1,n,ch,x)\tsum_ch sum_x x(x-1)J(1,n,ch,x)"
        ch = rna[j]
        for x in range(2,j-i+1-3): #x in [2,j-i+1-4]
          print "\t%s\t%s\t%s\t%s = \t%s"%(ch,x,x-1,J[(1,n,ch,x)],x*(x-1)*J[(1,n,ch,x)])
      #Case 5: fifth term  
      #sum_{k=1}^{n-\theta-1} \left( z(k-1) \cdot Q(n-k-1) \right) +
      #\left( Q(k-1) \cdot z(n-k-1) \right)
      #Case 5a: (i,j) paired
      sum = 0
      if basePair(rna[i],rna[j]):
        sum += Q[(i+1,j-1)] 
      for k in range(i+1,j-3): #k in [i+1,j-4]
        if basePair(rna[k],rna[j]):
          sum += (Z[(i,k-1)]*Q[(k+1,j-1)])+(Q[(i,k-1)]*Z[(k+1,j-1)])
      Q[(i,j)] += sum
      if PRINT:
        text = "sum_k (Z[(%s,k-1)]*Q[(k+1,%s-1)])+(Q[(%s,k-1)]*Z[(k+1,%s-1)])"
        text = text % (i,j,i,j)
        print "%s\t%s" % (sum,text)
  return Q