2 /* this file contains code for alifolding circular RNAs */
3 /* it's #include'd into alifold.c */
5 float circalifold(const char **strings, char *structure) {
6 /* variant of alifold() for circular RNAs */
8 fM2 = multiloop region with exactly two stems, extending to 3' end
9 for stupid dangles=1 case we also need:
10 fM_d3 = multiloop region with >= 2 stems, starting at pos 2
11 (a pair (k,n) will form 3' dangle with pos 1)
12 fM_d5 = multiloop region with >= 2 stems, extending to pos n-1
13 (a pair (1,k) will form a 5' dangle with pos n)
15 int *fM2, Fc, FcH, FcI, FcM, Hi, Hj, Ii, Ij, Ip, Iq, Mi;
17 int i,j, p,q,length, energy;
22 /* if (!uniq_ML) {uniq_ML=1; init_length=-1;} */
23 length = (int) strlen(strings[0]);
26 /* always init everything since all global static variables are uninitialized when entering a thread */
29 if (length > init_length) init_alifold(length);
31 if (fabs(P->temperature - temperature)>1e-6) update_alifold_params();
33 oldAliEn=1; /* TODO allow new gap treatment in alicircfold() */
34 for (s=0; strings[s]!=NULL; s++);
36 type = (int *) space(n_seq*sizeof(int));
38 alloc_sequence_arrays(strings, &S, &S5, &S3, &a2s, &Ss, circular);
39 make_pscores((const short **) S, strings, n_seq, structure);
41 /* compute all arrays used by fold() for linear RNA */
42 energy = fill_arrays((const char **) strings);
44 /* extra arrays for circfold() */
45 fM2 = (int *) space(sizeof(int)*(length+2));
46 FcH = FcI= FcM = FcMd3= FcMd5= Fc = INF;
47 for (i=1; i<length; i++)
48 for (j=i+TURN+1; j <= length; j++) {
55 psc = pscore[indx[j]+i];
57 if (psc<MINPSCORE) continue;
60 for (s=0; s<n_seq; s++) {
64 type[s] = pair[S[s][i]][S[s][j]];
65 if (type[s]==0) type[s]=7;
69 strcpy(loopseq , strings[s]+j-1);
70 strncat(loopseq, strings[s], i);
72 si1 = (i==1)?S[s][length] : S[s][i-1];
73 sj1 = (j==length)?S[s][1] : S[s][j+1];
74 new_c += E_Hairpin(u, rt, sj1, si1, loopseq, P);
78 FcH = new_c; Hi=i; Hj=j;
81 for (p = j+1; p < length ; p++) {
84 if (u1+i-1>MAXLOOP) break;
85 qmin = u1+i-1+length-MAXLOOP;
86 if (qmin<p+TURN+1) qmin = p+TURN+1;
87 for (q = qmin; q <=length; q++) {
88 int u2, si1, sq1, type_2;
90 if (pscore[indx[q]+p]<MINPSCORE) continue;
93 if (u1+u2>MAXLOOP) continue;
94 for (energy = s=0; s<n_seq; s++) {
97 type_2 = pair[S[s][q]][S[s][p]]; /* q,p not p,q! */
98 if (type_2 ==0) type_2=7;
99 si1 = (i==1)? S[s][length] : S[s][i-1];
100 sq1 = (q==length)? S[s][1] : S[s][q+1];
101 energy += E_IntLoop(u1, u2, rt, type_2,
102 S[s][j+1], si1, S[s][p-1], sq1, P);
104 new_c = c[ij] + c[indx[q]+p] + energy;
106 FcI = new_c; Ii=i; Ij=j; Ip=p; Iq=q;
113 /* compute the fM2 array (multi loops with exactly 2 helices) */
114 /* to get a unique ML decomposition, just use fM1 instead of fML
115 below. However, that will not work with dangles==1 */
116 for (i=1; i<length-TURN; i++) {
119 for (u=i+TURN; u<length-TURN; u++)
120 fM2[i] = MIN2(fM2[i], fML[indx[u]+i] + fML[indx[length]+u+1]);
123 for (i=TURN+1; i<length-2*TURN; i++) {
125 fm = fML[indx[i]+1]+fM2[i+1]+n_seq*P->MLclosing;
145 else if (FcM==Fc) { /* grumpf we found a Multiloop */
147 /* backtrack in fM2 */
149 for (u=Mi+TURN+1; u<length-TURN; u++)
150 if (fm == fML[indx[u]+Mi+1] + fML[indx[length]+u+1]) {
163 backtrack(strings, s);
166 parenthesis_structure(structure, base_pair2, length);
168 letter_structure(structure, base_pair2, length);
172 * Backward compatibility:
173 * This block may be removed if deprecated functions
174 * relying on the global variable "base_pair" vanishs from within the package!
176 base_pair = base_pair2;
179 if(base_pair) free(base_pair);
180 base_pair = (bondT *)space(sizeof(bondT) * (1+length/2));
181 memcpy(base_pair, base_pair2, sizeof(bondT) * (1+length/2));
186 free_sequence_arrays(n_seq, &S, &S5, &S3, &a2s, &Ss);
188 return (float) Fc/(n_seq*100.);