Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

RNA folding

In the examples below, the secondary structure of the RNA strand is plotted with the draw_rna lib, which can be installed with pip install draw_rna.

First of all, we define some useful utility functions

  • to check whether two bases are complementary; here I also include wobble base pairs among the “compatible” nucleotides;

  • to obtain a dot-paren notation out of a sequence and a list of pairs;

  • to draw an RNA secondary structure by using draw_rna; note that the function fails if the secondary structure is “too unphysical”, which happens very often with Nussinov’s algorithm;

  • to print (in an orderly manner) a matrix; this function can be used to debug the codes or have a look at the energy and traceback matrices to better understand how the algorithms work.

1Nussinov’s algorithm

This is an implementation of the algorithm presented in the lectures. The contribution of each base pair is -1, and the traceback phase is carried out by using recursion.

Optimal folding energy: -35.0
Base pairs: [(0, 1), (2, 74), (3, 73), (4, 5), (6, 72), (7, 8), (9, 10), (11, 63), (12, 17), (13, 16), (14, 15), (18, 62), (19, 60), (21, 27), (23, 24), (25, 26), (28, 32), (29, 31), (33, 55), (34, 54), (35, 40), (36, 39), (37, 38), (41, 49), (42, 48), (44, 47), (45, 46), (50, 51), (52, 53), (56, 59), (57, 58), (64, 69), (65, 68), (66, 67), (70, 71)]
Dot-parens: ()((()(()()(((()))((.(.()())((.))((((()))((.(())))()()))(())).))((()))()))).
Error occured while drawing RNA 1 0
Cannot draw this structure: it probably has a non-physical secondary structure

2Zuker’s algorithm

In the simplified approach below, I make many approximations for the sake of readability and conciseness.

First of all, every stack composed by two compatible base pairs gives an energy of -2. Then, I use simple expressions for the hairpin, bulge and interior loop penalties, FH(L)F_H(L), FI(L)F_I(L), FB(L)F_B(L) as a function of the length LL, which I obtained by (very crudely) fitting the values reported here:

FH(L)=4.8+0.19L−0.0031L2FB(L)=3.5+0.16L−0.0026L2FI(L)=1.3+0.14L−0.0019L2\begin{align} F_H(L) &= 4.8 + 0.19 L - 0.0031 L^2\\ F_B(L) &= 3.5 + 0.16 L - 0.0026 L^2\\ F_I(L) & = 1.3 + 0.14 L - 0.0019 L^2\\ \end{align}

Moreover, there is no asymmetry correction for the internal loops, and mismatches are treated as bulges or internal loops. Finally, as in the original Zuker model, there is no energy penalty associated to kk-multiloops.

Those are all rather crude approximations, so don’t be surprised if the final structure does not look as the one given by “real” codes. However, in many cases it will still look not too different (at least in terms of number of base pairs and energy).

About the algorithm itself: the fill-in phase should be rather straightforward, as we simply apply the recursion relations derived in class. The traceback is a bit more complicated, as it requires two traceback matrices T^W\hat T^W and T^V\hat T^V: we use Ti,jVT^V_{i,j} if i,ji,j and bonded, Ti,jWT^W_{i,j} otherwise.

The traceback function below doesn’t use recursion as in the Nussinov’s algorithm, but another technique that makes use of a list of subsequences to check, called to_check. This list contains the extrema of the subsequence, and the matrix that should be used to traceback. Then, for each element of the list we check whether the next subsequence connected to it is paired or not, and we add the subsequence to to_check, together with the information about the traceback matrix to be used.

Minimum Free Energy (MFE): -36.4276
Base pairs: [(0, 71), (1, 70), (2, 69), (3, 68), (4, 67), (5, 66), (6, 65), (7, 64), (49, 63), (50, 62), (51, 61), (52, 60), (36, 47), (37, 46), (38, 45), (39, 44), (11, 34), (12, 33), (13, 32), (14, 31), (15, 30), (16, 29), (18, 27), (19, 26)]
Dot-parens: ((((((((...((((((.((......)).)))))).((((....)))).((((.......))))))))))))....
<Figure size 726.236x726.236 with 1 Axes>

For reference, I report below the MFE as computed by ViennaRNA (with dangling ends off, energy 19.90 kcal/mol). If you look closely you can see that there is some agreement, especially close to the termini of the strands. The appearance of a multibranched loop (which is not present in the ViennaRNA prediction) is most likely due to simplified way that these motifs are taken into account here.

ViennaRNA's MFE

3McCaskill’s algorithm

The algorithm implemented here is exactly that presented in class. The implementation is rather straightforward, with two exceptions: when computing Q^\hat Q and p^\hat p, care has to be taken in handling the finiteness of the chain: indeed, some of the recursive relations have to be corrected when dealing with the first and last nucleotides.

<Figure size 432x288 with 1 Axes>