2 partiton function for RNA secondary structures
9 Revision 1.29 2008/02/23 10:10:49 ivo
10 list returned from StackProb was sometimes not terminated correctly
12 Revision 1.28 2008/01/08 15:08:10 ivo
13 circular fold would fail for open chain
15 Revision 1.27 2007/12/05 13:04:04 ivo
16 add various circfold variants from Ronny
18 Revision 1.26 2007/09/19 12:41:56 ivo
19 add computation of centroid() structure for RNAfold -p
21 Revision 1.25 2007/04/30 15:12:00 ivo
22 merge RNAup into package
24 Revision 1.24 2007/03/03 17:57:44 ivo
25 make sure entries in scale[] decrease to 0
27 Revision 1.23 2006/12/01 12:40:23 ivo
28 undo Ulli's accidental commit
30 Revision 1.21 2006/08/04 15:39:06 ivo
31 new function stackProb returns probability for stacks
34 Revision 1.20 2004/08/12 12:14:46 ivo
37 Revision 1.19 2004/05/14 16:28:05 ivo
38 fix the bug in make_ptype here too (fixed in 1.27 of fold.c)
40 Revision 1.18 2004/02/17 10:46:52 ivo
41 make sure init_pf_fold is called before scale_parameters
43 Revision 1.17 2004/02/09 18:37:59 ivo
44 new mean_bp_dist() function to compute ensemble diversity
46 Revision 1.16 2003/08/04 09:14:09 ivo
47 finish up stochastic backtracking
49 Revision 1.15 2002/03/19 16:51:12 ivo
50 more on stochastic backtracking (still incomplete)
52 Revision 1.14 2002/02/08 17:37:23 ivo
53 set freed S,S1 pointers to NULL
55 Revision 1.13 2001/11/16 17:30:04 ivo
56 add stochastic backtracking (still incomplete)
63 #include <float.h> /* #defines FLT_MAX ... */
67 #include "energy_par.h"
68 #include "fold_vars.h"
71 #include "loop_energies.h"
73 #include "part_func.h"
79 #define ISOLATED 256.0
82 #################################
84 #################################
86 PUBLIC int st_back = 0;
89 #################################
91 #################################
93 PRIVATE FLT_OR_DBL *q = NULL, *qb=NULL, *qm = NULL, *qm1 = NULL, *qqm = NULL, *qqm1 = NULL, *qq = NULL, *qq1 = NULL;
94 PRIVATE FLT_OR_DBL *probs=NULL, *prml=NULL, *prm_l=NULL, *prm_l1=NULL, *q1k=NULL, *qln=NULL;
95 PRIVATE FLT_OR_DBL *scale=NULL;
96 PRIVATE FLT_OR_DBL *expMLbase=NULL;
97 PRIVATE FLT_OR_DBL qo=0., qho=0., qio=0., qmo=0., *qm2=NULL;
98 PRIVATE int *jindx=NULL;
99 PRIVATE int *my_iindx=NULL;
100 PRIVATE int init_length = -1; /* length in last call to init_pf_fold() */
101 PRIVATE int circular=0;
102 PRIVATE int do_bppm = 1; /* do backtracking per default */
103 PRIVATE int struct_constrained = 0;
104 PRIVATE char *pstruc=NULL;
105 PRIVATE char *sequence=NULL;
106 PRIVATE char *ptype=NULL; /* precomputed array of pair types */
107 PRIVATE pf_paramT *pf_params=NULL; /* the precomputed Boltzmann weights */
108 PRIVATE short *S=NULL, *S1=NULL;
109 PRIVATE int with_gquad = 0;
111 PRIVATE FLT_OR_DBL *G = NULL, *Gj = NULL, *Gj1 = NULL;
115 #pragma omp threadprivate(q, qb, qm, qm1, qqm, qqm1, qq, qq1, prml, prm_l, prm_l1, q1k, qln,\
116 probs, scale, expMLbase, qo, qho, qio, qmo, qm2, jindx, my_iindx, init_length,\
117 circular, pstruc, sequence, ptype, pf_params, S, S1, do_bppm, struct_constrained,\
118 G, Gj, Gj1, with_gquad)
123 #################################
124 # PRIVATE FUNCTION DECLARATIONS #
125 #################################
127 PRIVATE void init_partfunc(int length, pf_paramT *parameters);
128 PRIVATE void scale_pf_params(unsigned int length, pf_paramT *parameters);
129 PRIVATE void get_arrays(unsigned int length);
130 PRIVATE void make_ptypes(const short *S, const char *structure);
131 PRIVATE void pf_circ(const char *sequence, char *structure);
132 PRIVATE void pf_linear(const char *sequence, char *structure);
133 PRIVATE void pf_create_bppm(const char *sequence, char *structure);
134 PRIVATE void backtrack(int i, int j);
135 PRIVATE void backtrack_qm(int i, int j);
136 PRIVATE void backtrack_qm1(int i,int j);
137 PRIVATE void backtrack_qm2(int u, int n);
140 #################################
141 # BEGIN OF FUNCTION DEFINITIONS #
142 #################################
145 PRIVATE void init_partfunc(int length, pf_paramT *parameters){
146 if (length<1) nrerror("init_pf_fold: length must be greater 0");
149 /* Explicitly turn off dynamic threads */
151 free_pf_arrays(); /* free previous allocation */
153 if (init_length>0) free_pf_arrays(); /* free previous allocation */
157 nonstandard_arithmetic();
164 get_arrays((unsigned) length);
165 scale_pf_params((unsigned) length, parameters);
167 init_length = length;
170 PRIVATE void get_arrays(unsigned int length){
173 if((length +1) >= (unsigned int)sqrt((double)INT_MAX))
174 nrerror("get_arrays@part_func.c: sequence length exceeds addressable range");
176 size = sizeof(FLT_OR_DBL) * ((length+1)*(length+2)/2);
178 q = (FLT_OR_DBL *) space(size);
179 qb = (FLT_OR_DBL *) space(size);
180 qm = (FLT_OR_DBL *) space(size);
181 qm1 = (st_back || circular) ? (FLT_OR_DBL *) space(size) : NULL;
182 qm2 = (circular) ? (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)) : NULL;
183 probs = (do_bppm) ? (FLT_OR_DBL *) space(size) : NULL;
185 ptype = (char *) space(sizeof(char)*((length+1)*(length+2)/2));
186 q1k = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1));
187 qln = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
188 qq = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
189 qq1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
190 qqm = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
191 qqm1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
192 prm_l = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
193 prm_l1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
194 prml = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
195 expMLbase = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1));
196 scale = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1));
198 Gj = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
199 Gj1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2));
201 my_iindx = get_iindx(length);
202 iindx = get_iindx(length); /* for backward compatibility and Perl wrapper */
203 jindx = get_indx(length);
207 *** Allocate memory for all matrices and other stuff
209 PUBLIC void free_pf_arrays(void){
215 if(ptype) free(ptype);
222 if(probs) free(probs);
223 if(prm_l) free(prm_l);
224 if(prm_l1) free(prm_l1);
226 if(expMLbase) free(expMLbase);
227 if(scale) free(scale);
228 if(my_iindx) free(my_iindx);
229 if(iindx) free(iindx); /* for backward compatibility and Perl wrapper */
230 if(jindx) free(jindx);
238 q = pr = probs = qb = qm = qm1 = qm2 = qq = qq1 = qqm = qqm1 = q1k = qln = prm_l = prm_l1 = prml = expMLbase = scale = G = Gj = Gj1 = NULL;
239 my_iindx = jindx = iindx = NULL;
244 standard_arithmetic();
254 /*-----------------------------------------------------------------*/
255 PUBLIC float pf_fold(const char *sequence, char *structure){
256 return pf_fold_par(sequence, structure, NULL, do_backtrack, fold_constrained, 0);
259 PUBLIC float pf_circ_fold(const char *sequence, char *structure){
260 return pf_fold_par(sequence, structure, NULL, do_backtrack, fold_constrained, 1);
263 PUBLIC float pf_fold_par( const char *sequence,
265 pf_paramT *parameters,
272 int n = (int) strlen(sequence);
274 circular = is_circular;
275 do_bppm = calculate_bppm;
276 struct_constrained = is_constrained;
279 init_partfunc(n, parameters);
281 if(parameters) init_partfunc(n, parameters);
282 else if (n > init_length) init_partfunc(n, parameters);
283 else if (fabs(pf_params->temperature - temperature)>1e-6) update_pf_params_par(n, parameters);
286 with_gquad = pf_params->model_details.gquad;
287 S = encode_sequence(sequence, 0);
288 S1 = encode_sequence(sequence, 1);
290 make_ptypes(S, structure);
292 /* do the linear pf fold and fill all matrices */
293 pf_linear(sequence, structure);
296 pf_circ(sequence, structure); /* do post processing step for circular RNAs */
298 if (backtrack_type=='C') Q = qb[my_iindx[1]-n];
299 else if (backtrack_type=='M') Q = qm[my_iindx[1]-n];
300 else Q = (circular) ? qo : q[my_iindx[1]-n];
302 /* ensemble free energy in Kcal/mol */
303 if (Q<=FLT_MIN) fprintf(stderr, "pf_scale too large\n");
304 free_energy = (-log(Q)-n*log(pf_params->pf_scale))*pf_params->kT/1000.0;
305 /* in case we abort because of floating point errors */
306 if (n>1600) fprintf(stderr, "free energy = %8.2f\n", free_energy);
308 /* calculate base pairing probability matrix (bppm) */
310 pf_create_bppm(sequence, structure);
312 * Backward compatibility:
313 * This block may be removed if deprecated functions
314 * relying on the global variable "pr" vanish from within the package!
320 pr = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL) * ((n+1)*(n+2)/2));
321 memcpy(pr, probs, sizeof(FLT_OR_DBL) * ((n+1)*(n+2)/2));
328 PRIVATE void pf_linear(const char *sequence, char *structure){
330 int n, i,j,k,l, ij, u,u1,d,ii, type, type_2, tt, minl, maxl;
333 FLT_OR_DBL expMLstem = 0.;
335 FLT_OR_DBL temp, Qmax=0;
336 FLT_OR_DBL qbt1, *tmp;
338 FLT_OR_DBL expMLclosing = pf_params->expMLclosing;
341 max_real = (sizeof(FLT_OR_DBL) == sizeof(float)) ? FLT_MAX : DBL_MAX;
343 n = (int) strlen(sequence);
346 noGUclosure = pf_params->model_details.noGUclosure;
348 /*array initialization ; qb,qm,q
349 qb,qm,q (i,j) are stored as ((n+1-i)*(n-i) div 2 + n+1-j */
352 expMLstem = exp_E_MLstem(0, -1, -1, pf_params);
353 G = get_gquad_pf_matrix(S, scale, pf_params);
356 for (d=0; d<=TURN; d++)
357 for (i=1; i<=n-d; i++) {
360 q[ij]=1.0*scale[d+1];
365 qq[i]=qq1[i]=qqm[i]=qqm1[i]=0;
367 for (j=TURN+2;j<=n; j++) {
368 for (i=j-TURN-1; i>=1; i--) {
369 /* construction of partition function of segment i,j*/
370 /*firstly that given i binds j : qb(i,j) */
371 u = j-i-1; ij = my_iindx[i]-j;
374 /*hairpin contribution*/
375 if (((type==3)||(type==4))&&noGUclosure) qbt1 = 0;
377 qbt1 = exp_E_Hairpin(u, type, S1[i+1], S1[j-1], sequence+i-1, pf_params) * scale[u+2];
378 /* interior loops with interior pair k,l */
379 for (k=i+1; k<=MIN2(i+MAXLOOP+1,j-TURN-2); k++) {
381 for (l=MAX2(k+TURN+1,j-1-MAXLOOP+u1); l<j; l++) {
382 type_2 = ptype[my_iindx[k]-l];
384 type_2 = rtype[type_2];
385 qbt1 += qb[my_iindx[k]-l] * (scale[u1+j-l+1] *
386 exp_E_IntLoop(u1, j-l-1, type, type_2,
387 S1[i+1], S1[j-1], S1[k-1], S1[l+1], pf_params));
391 /*multiple stem loop contribution*/
392 ii = my_iindx[i+1]; /* ii-k=[i+1,k-1] */
394 for (k=i+2; k<=j-1; k++) temp += qm[ii-(k-1)]*qqm1[k];
396 qbt1 += temp * expMLclosing * exp_E_MLstem(tt, S1[j-1], S1[i+1], pf_params) * scale[2];
399 qbt1 += exp_E_GQuad_IntLoop(i, j, type, S1, G, my_iindx, pf_params) * scale[2];
404 /* end if (type!=0) */
408 /* construction of qqm matrix containing final stem
409 contributions to multiple loop partition function
411 qqm[i] = qqm1[i]*expMLbase[1];
413 qbt1 = qb[ij] * exp_E_MLstem(type, ((i>1) || circular) ? S1[i-1] : -1, ((j<n) || circular) ? S1[j+1] : -1, pf_params);
418 /*include gquads into qqm*/
419 qqm[i] += G[my_iindx[i]-j] * expMLstem;
422 if (qm1) qm1[jindx[j]+i] = qqm[i]; /* for stochastic backtracking and circfold */
424 /*construction of qm matrix containing multiple loop
425 partition function contributions from segment i,j */
427 ii = my_iindx[i]; /* ii-k=[i,k-1] */
428 for (k=j; k>i; k--) temp += (qm[ii-(k-1)] + expMLbase[k-i])*qqm[k];
429 qm[ij] = (temp + qqm[i]);
431 /*auxiliary matrix qq for cubic order q calculation below */
435 qbt1 *= exp_E_ExtLoop(type, ((i>1) || circular) ? S1[i-1] : -1, ((j<n) || circular) ? S1[j+1] : -1, pf_params);
442 qq[i] = qq1[i]*scale[1] + qbt1;
444 /*construction of partition function for segment i,j */
445 temp = 1.0*scale[1+j-i] + qq[i];
446 for (k=i; k<=j-1; k++) temp += q[ii-k]*qq[k+1];
450 if (Qmax>max_real/10.)
451 fprintf(stderr, "Q close to overflow: %d %d %g\n", i,j,temp);
453 if (temp>=max_real) {
454 PRIVATE char msg[128];
455 sprintf(msg, "overflow in pf_fold while calculating q[%d,%d]\n"
456 "use larger pf_scale", i,j);
460 tmp = qq1; qq1 =qq; qq =tmp;
461 tmp = qqm1; qqm1=qqm; qqm=tmp;
463 if(with_gquad){ /* rotate the auxilary g-quadruplex matrices */
464 tmp = Gj1; Gj1=Gj; Gj=tmp;
469 /* calculate partition function for circular case */
470 /* NOTE: this is the postprocessing step ONLY */
471 /* You have to call pf_linear first to calculate */
472 /* complete circular case!!! */
473 PRIVATE void pf_circ(const char *sequence, char *structure){
477 int n = (int) strlen(sequence);
480 FLT_OR_DBL expMLclosing = pf_params->expMLclosing;
482 noGUclosure = pf_params->model_details.noGUclosure;
483 qo = qho = qio = qmo = 0.;
485 /* construct qm2 matrix from qm1 entries */
486 for(k=1; k<n-TURN-1; k++){
488 for (u=k+TURN+1; u<n-TURN-1; u++)
489 qot += qm1[jindx[u]+k]*qm1[jindx[n]+(u+1)];
493 for(p = 1; p < n; p++){
494 for(q = p + TURN + 1; q <= n; q++){
496 /* 1. get exterior hairpin contribution */
498 if (u<TURN) continue;
499 type = ptype[my_iindx[p]-q];
501 /* cause we want to calc the exterior loops, we need the reversed pair type from now on */
506 strcpy(loopseq , sequence+q-1);
507 strncat(loopseq, sequence, p);
509 qho += (((type==3)||(type==4))&&noGUclosure) ? 0. : qb[my_iindx[p]-q] * exp_E_Hairpin(u, type, S1[q+1], S1[p-1], loopseq, pf_params) * scale[u];
511 /* 2. exterior interior loops, i "define" the (k,l) pair as "outer pair" */
512 /* so "outer type" is rtype[type[k,l]] and inner type is type[p,q] */
514 for(k=q+1; k < n; k++){
517 if(ln1+p-1>MAXLOOP) break;
518 lstart = ln1+p-1+n-MAXLOOP;
519 if(lstart<k+TURN+1) lstart = k + TURN + 1;
520 for(l=lstart;l <= n; l++){
522 ln2 = (p - 1) + (n - l);
524 if((ln1+ln2) > MAXLOOP) continue;
526 type2 = ptype[my_iindx[k]-l];
528 qio += qb[my_iindx[p]-q] * qb[my_iindx[k]-l] * exp_E_IntLoop(ln2, ln1, rtype[type2], type, S1[l+1], S1[k-1], S1[p-1], S1[q+1], pf_params) * scale[ln1+ln2];
530 } /* end of kl double loop */
532 } /* end of pq double loop */
535 for(k=TURN+2; k<n-2*TURN-3; k++)
536 qmo += qm[my_iindx[1]-k] * qm2[k+1] * expMLclosing;
538 /* add an additional pf of 1.0 to take the open chain into account too */
539 qo = qho + qio + qmo + 1.0*scale[n];
542 /* calculate base pairing probs */
543 PUBLIC void pf_create_bppm(const char *sequence, char *structure){
544 int n, i,j,k,l, ij, kl, ii, i1, ll, type, type_2, tt, u1, ov=0;
545 FLT_OR_DBL temp, Qmax=0, prm_MLb;
546 FLT_OR_DBL prmt,prmt1;
549 FLT_OR_DBL expMLclosing = pf_params->expMLclosing;
552 FLT_OR_DBL expMLstem = (with_gquad) ? exp_E_MLstem(0, -1, -1, pf_params) : 0;
554 max_real = (sizeof(FLT_OR_DBL) == sizeof(float)) ? FLT_MAX : DBL_MAX;
556 if((S != NULL) && (S1 != NULL)){
560 for (k=1; k<=n; k++) {
561 q1k[k] = q[my_iindx[1] - k];
562 qln[k] = q[my_iindx[k] -n];
567 /* pr = q; */ /* recycling */
570 /* 1. exterior pair i,j and initialization of pr array */
572 for (i=1; i<=n; i++) {
573 for (j=i; j<=MIN2(i+TURN,n); j++)
574 probs[my_iindx[i]-j] = 0;
575 for (j=i+TURN+1; j<=n; j++) {
578 if (type&&(qb[ij]>0.)) {
580 int rt = rtype[type];
582 /* 1.1. Exterior Hairpin Contribution */
583 int u = i + n - j -1;
584 /* get the loop sequence */
587 strcpy(loopseq , sequence+j-1);
588 strncat(loopseq, sequence, i);
590 tmp2 = exp_E_Hairpin(u, rt, S1[j+1], S1[i-1], loopseq, pf_params) * scale[u];
592 /* 1.2. Exterior Interior Loop Contribution */
593 /* 1.2.1. i,j delimtis the "left" part of the interior loop */
594 /* (j,i) is "outer pair" */
595 for(k=1; k < i-TURN-1; k++){
598 if(ln1>MAXLOOP) break;
599 lstart = ln1+i-1-MAXLOOP;
600 if(lstart<k+TURN+1) lstart = k + TURN + 1;
601 for(l=lstart; l < i; l++){
603 type_2 = ptype[my_iindx[k]-l];
604 if (type_2==0) continue;
606 if(ln1+ln2>MAXLOOP) continue;
607 tmp2 += qb[my_iindx[k] - l]
620 /* 1.2.2. i,j delimtis the "right" part of the interior loop */
621 for(k=j+1; k < n-TURN; k++){
624 if((ln1 + i - 1)>MAXLOOP) break;
625 lstart = ln1+i-1+n-MAXLOOP;
626 if(lstart<k+TURN+1) lstart = k + TURN + 1;
627 for(l=lstart; l <= n; l++){
629 type_2 = ptype[my_iindx[k]-l];
630 if (type_2==0) continue;
632 if(ln1+ln2>MAXLOOP) continue;
633 tmp2 += qb[my_iindx[k] - l]
646 /* 1.3 Exterior multiloop decomposition */
647 /* 1.3.1 Middle part */
648 if((i>TURN+2) && (j<n-TURN-1))
649 tmp2 += qm[my_iindx[1]-i+1]
650 * qm[my_iindx[j+1]-n]
652 * exp_E_MLstem(type, S1[i-1], S1[j+1], pf_params);
654 /* 1.3.2 Left part */
655 for(k=TURN+2; k < i-TURN-2; k++)
656 tmp2 += qm[my_iindx[1]-k]
657 * qm1[jindx[i-1]+k+1]
660 * exp_E_MLstem(type, S1[i-1], S1[j+1], pf_params);
662 /* 1.3.3 Right part */
663 for(k=j+TURN+2; k < n-TURN-1;k++)
664 tmp2 += qm[my_iindx[j+1]-k]
668 * exp_E_MLstem(type, S1[i-1], S1[j+1], pf_params);
670 /* all exterior loop decompositions for pair i,j done */
677 } /* end if(circular) */
679 for (i=1; i<=n; i++) {
680 for (j=i; j<=MIN2(i+TURN,n); j++) probs[my_iindx[i]-j] = 0;
681 for (j=i+TURN+1; j<=n; j++) {
684 if (type&&(qb[ij]>0.)) {
685 probs[ij] = q1k[i-1]*qln[j+1]/q1k[n];
686 probs[ij] *= exp_E_ExtLoop(type, (i>1) ? S1[i-1] : -1, (j<n) ? S1[j+1] : -1, pf_params);
692 } /* end if(!circular) */
694 for (l=n; l>TURN+1; l--) {
696 /* 2. bonding k,l as substem of 2:loop enclosed by i,j */
697 for (k=1; k<l-TURN; k++) {
700 if (type_2==0) continue;
701 type_2 = rtype[type_2];
702 if (qb[kl]==0.) continue;
705 for (i=MAX2(1,k-MAXLOOP-1); i<=k-1; i++)
706 for (j=l+1; j<=MIN2(l+ MAXLOOP -k+i+2,n); j++) {
707 ij = my_iindx[i] - j;
709 if (type && (probs[ij]>0.)) {
710 /* add *scale[u1+u2+2] */
713 * exp_E_IntLoop(k - i - 1,
728 /* 2.5. bonding k,l as gquad enclosed by i,j */
729 FLT_OR_DBL *expintern = &(pf_params->expinternal[0]);
732 for(k = 2; k <= l - VRNA_GQUAD_MIN_BOX_SIZE; k++){
734 if (G[kl]==0.) continue;
737 for(j = MIN2(l + MAXLOOP + 1, n); j > l + 3; j--){
738 ij = my_iindx[i] - j;
741 tmp2 += probs[ij] * expintern[j-l-1] * pf_params->expmismatchI[type][S1[i+1]][S1[j-1]] * scale[2];
743 probs[kl] += tmp2 * G[kl];
748 for(k = 4; k <= l - VRNA_GQUAD_MIN_BOX_SIZE; k++){
750 if (G[kl]==0.) continue;
753 for (i=MAX2(1,k-MAXLOOP-1); i < k - 3; i++){
754 ij = my_iindx[i] - j;
757 tmp2 += probs[ij] * expintern[k - i - 1] * pf_params->expmismatchI[type][S1[i+1]][S1[j-1]] * scale[2];
759 probs[kl] += tmp2 * G[kl];
764 for (k=3; k<=l-VRNA_GQUAD_MIN_BOX_SIZE; k++) {
766 if (G[kl]==0.) continue;
768 for (i=MAX2(1,k-MAXLOOP-1); i<=k-2; i++){
770 for (j=l+2; j<=MIN2(l + MAXLOOP - u1 + 1,n); j++) {
771 ij = my_iindx[i] - j;
774 tmp2 += probs[ij] * expintern[u1+j-l-1] * pf_params->expmismatchI[type][S1[i+1]][S1[j-1]] * scale[2];
777 probs[kl] += tmp2 * G[kl];
782 /* 3. bonding k,l as substem of multi-loop enclosed by i,j */
784 if (l<n) for (k=2; k<l-TURN; k++) {
788 ii = my_iindx[i]; /* ii-j=[i,j] */
789 ll = my_iindx[l+1]; /* ll-j=[l+1,j-1] */
790 tt = ptype[ii-(l+1)]; tt=rtype[tt];
791 /* (i, l+1) closes the ML with substem (k,l) */
793 prmt1 = probs[ii-(l+1)] * expMLclosing * exp_E_MLstem(tt, S1[l], S1[i+1], pf_params);
795 /* (i,j) with j>l+1 closes the ML with substem (k,l) */
796 for (j=l+2; j<=n; j++) {
797 tt = ptype[ii-j]; tt = rtype[tt];
799 prmt += probs[ii-j] * exp_E_MLstem(tt, S1[j-1], S1[i+1], pf_params) * qm[ll-(j-1)];
803 prmt *= expMLclosing;
805 prm_l[i] = prm_l1[i]*expMLbase[1]+prmt1;
807 prm_MLb = prm_MLb*expMLbase[1] + prml[i];
808 /* same as: prm_MLb = 0;
809 for (i=1; i<=k-1; i++) prm_MLb += prml[i]*expMLbase[k-i-1]; */
811 prml[i] = prml[ i] + prm_l[i];
814 if ((!tt) && (G[kl] == 0.)) continue;
816 if (qb[kl] == 0.) continue;
821 for (i=1;i<=k-2; i++)
822 temp += prml[i]*qm[my_iindx[i+1] - (k-1)];
826 temp *= exp_E_MLstem(tt, (k>1) ? S1[k-1] : -1, (l<n) ? S1[l+1] : -1, pf_params) * scale[2];
828 temp *= G[kl] * expMLstem * scale[2];
830 temp *= exp_E_MLstem(tt, (k>1) ? S1[k-1] : -1, (l<n) ? S1[l+1] : -1, pf_params) * scale[2];
835 if (probs[kl]>Qmax) {
837 if (Qmax>max_real/10.)
838 fprintf(stderr, "P close to overflow: %d %d %g %g\n",
839 i, j, probs[kl], qb[kl]);
841 if (probs[kl]>=max_real) {
846 } /* end for (k=..) */
847 tmp = prm_l1; prm_l1=prm_l; prm_l=tmp;
849 } /* end for (l=..) */
852 for (j=i+TURN+1; j<=n; j++) {
859 probs[ij] += q1k[i-1] * G[ij] * qln[j+1]/q1k[n];
868 bppm_to_structure(structure, probs, n);
869 if (ov>0) fprintf(stderr, "%d overflows occurred while backtracking;\n"
870 "you might try a smaller pf_scale than %g\n",
871 ov, pf_params->pf_scale);
872 } /* end if((S != NULL) && (S1 != NULL)) */
874 nrerror("bppm calculations have to be done after calling forward recursion\n");
878 PRIVATE void scale_pf_params(unsigned int length, pf_paramT *parameters){
880 double scaling_factor;
882 if(pf_params) free(pf_params);
885 pf_params = get_boltzmann_factor_copy(parameters);
888 set_model_details(&md);
889 pf_params = get_boltzmann_factors(temperature, 1.0, md, pf_scale);
892 scaling_factor = pf_params->pf_scale;
894 /* scaling factors (to avoid overflows) */
895 if (scaling_factor == -1) { /* mean energy for random sequences: 184.3*length cal */
896 scaling_factor = exp(-(-185+(pf_params->temperature-37.)*7.27)/pf_params->kT);
897 if (scaling_factor<1) scaling_factor=1;
898 pf_params->pf_scale = scaling_factor;
899 pf_scale = pf_params->pf_scale; /* compatibility with RNAup, may be removed sometime */
902 scale[1] = 1./scaling_factor;
904 expMLbase[1] = pf_params->expMLbase/scaling_factor;
905 for (i=2; i<=length; i++) {
906 scale[i] = scale[i/2]*scale[i-(i/2)];
907 expMLbase[i] = pow(pf_params->expMLbase, (double)i) * scale[i];
911 /*---------------------------------------------------------------------------*/
913 PUBLIC void update_pf_params(int length){
914 update_pf_params_par(length, NULL);
917 PUBLIC void update_pf_params_par(int length, pf_paramT *parameters){
919 make_pair_matrix(); /* is this really necessary? */
920 scale_pf_params((unsigned) length, parameters);
922 if(parameters) init_partfunc(length, parameters);
923 else if (length>init_length) init_partfunc(length, parameters); /* init not update */
926 scale_pf_params((unsigned) length, parameters);
931 /*---------------------------------------------------------------------------*/
933 PUBLIC char bppm_symbol(const float *x){
934 /* if( ((x[1]-x[2])*(x[1]-x[2]))<0.1&&x[0]<=0.677) return '|'; */
935 if( x[0] > 0.667 ) return '.';
936 if( x[1] > 0.667 ) return '(';
937 if( x[2] > 0.667 ) return ')';
938 if( (x[1]+x[2]) > x[0] ) {
939 if( (x[1]/(x[1]+x[2])) > 0.667) return '{';
940 if( (x[2]/(x[1]+x[2])) > 0.667) return '}';
943 if( x[0] > (x[1]+x[2]) ) return ',';
947 PUBLIC void bppm_to_structure(char *structure, FLT_OR_DBL *p, unsigned int length){
949 int *index = get_iindx(length);
950 float P[3]; /* P[][0] unpaired, P[][1] upstream p, P[][2] downstream p */
952 for( j=1; j<=length; j++ ) {
955 for( i=1; i<j; i++) {
956 P[2] += p[index[i]-j]; /* j is paired downstream */
957 P[0] -= p[index[i]-j]; /* j is unpaired */
959 for( i=j+1; i<=length; i++ ) {
960 P[1] += p[index[j]-i]; /* j is paired upstream */
961 P[0] -= p[index[j]-i]; /* j is unpaired */
963 structure[j-1] = bppm_symbol(P);
965 structure[length] = '\0';
970 /*---------------------------------------------------------------------------*/
971 PRIVATE void make_ptypes(const short *S, const char *structure){
974 noLP = pf_params->model_details.noLP;
977 for (k=1; k<n-TURN; k++)
978 for (l=1; l<=2; l++) {
979 int type,ntype=0,otype=0;
980 i=k; j = i+TURN+l; if (j>n) continue;
981 type = pair[S[i]][S[j]];
982 while ((i>=1)&&(j<=n)) {
983 if ((i>1)&&(j<n)) ntype = pair[S[i-1]][S[j+1]];
984 if (noLP && (!otype) && (!ntype))
985 type = 0; /* i.j can only form isolated pairs */
986 qb[my_iindx[i]-j] = 0.;
987 ptype[my_iindx[i]-j] = (char) type;
994 if (struct_constrained && (structure != NULL))
995 constrain_ptypes(structure, (unsigned int)n, ptype, NULL, TURN, 1);
999 stochastic backtracking in pf_fold arrays
1000 returns random structure S with Boltzman probabilty
1001 p(S) = exp(-E(S)/kT)/Z
1003 char *pbacktrack(char *seq){
1007 n = strlen(sequence);
1010 nrerror("can't backtrack without pf arrays.\n"
1011 "Call pf_fold() before pbacktrack()");
1012 pstruc = space((n+1)*sizeof(char));
1014 for (i=0; i<n; i++) pstruc[i] = '.';
1018 /* find i position of first pair */
1019 for (i=start; i<n; i++) {
1021 if (r > qln[i+1]*scale[1]) break; /* i is paired */
1023 if (i>=n) break; /* no more pairs */
1024 /* now find the pairing partner j */
1025 r = urn() * (qln[i] - qln[i+1]*scale[1]);
1026 for (qt=0, j=i+1; j<=n; j++) {
1028 type = ptype[my_iindx[i]-j];
1031 qkl = qb[my_iindx[i]-j];
1032 if (j<n) qkl *= qln[j+1];
1033 qkl *= exp_E_ExtLoop(type, (i>1) ? S1[i-1] : -1, (j<n) ? S1[j+1] : -1, pf_params);
1035 if (qt > r) break; /* j is paired */
1038 if (j==n+1) nrerror("backtracking failed in ext loop");
1045 char *pbacktrack_circ(char *seq){
1048 FLT_OR_DBL expMLclosing = pf_params->expMLclosing;
1051 n = strlen(sequence);
1054 nrerror("can't backtrack without pf arrays.\n"
1055 "Call pf_circ_fold() before pbacktrack_circ()");
1056 pstruc = space((n+1)*sizeof(char));
1058 /* initialize pstruct with single bases */
1059 for (i=0; i<n; i++) pstruc[i] = '.';
1065 if(qt > r) return pstruc;
1067 for(i=1; (i < n); i++){
1068 for(j=i+TURN+1;(j<=n); j++){
1071 /* 1. first check, wether we can do a hairpin loop */
1073 if (u<TURN) continue;
1075 type = ptype[my_iindx[i]-j];
1076 if (!type) continue;
1082 strcpy(loopseq , sequence+j-1);
1083 strncat(loopseq, sequence, i);
1086 qt += qb[my_iindx[i]-j] * exp_E_Hairpin(u, type, S1[j+1], S1[i-1], loopseq, pf_params) * scale[u];
1087 /* found a hairpin? so backtrack in the enclosed part and we're done */
1088 if(qt>r){ backtrack(i,j); return pstruc;}
1090 /* 2. search for (k,l) with which we can close an interior loop */
1091 for(k=j+1; (k < n); k++){
1094 if(ln1+i-1>MAXLOOP) break;
1096 lstart = ln1+i-1+n-MAXLOOP;
1097 if(lstart<k+TURN+1) lstart = k + TURN + 1;
1098 for(l=lstart; (l <= n); l++){
1100 ln2 = (i - 1) + (n - l);
1101 if((ln1+ln2) > MAXLOOP) continue;
1103 type2 = ptype[my_iindx[k]-l];
1105 type2 = rtype[type2];
1106 qt += qb[my_iindx[i]-j] * qb[my_iindx[k]-l] * exp_E_IntLoop(ln2, ln1, type2, type, S1[l+1], S1[k-1], S1[i-1], S1[j+1], pf_params) * scale[ln1 + ln2];
1107 /* found an exterior interior loop? also this time, we can go straight */
1108 /* forward and backtracking the both enclosed parts and we're done */
1109 if(qt>r){ backtrack(i,j); backtrack(k,l); return pstruc;}
1111 } /* end of kl double loop */
1113 } /* end of ij double loop */
1115 /* as we reach this part, we have to search for our barrier between qm and qm2 */
1118 for(k=TURN+2; k<n-2*TURN-3; k++){
1119 qt += qm[my_iindx[1]-k] * qm2[k+1] * expMLclosing;
1120 /* backtrack in qm and qm2 if we've found a valid barrier k */
1121 if(qt>r){ backtrack_qm(1,k); backtrack_qm2(k+1,n); return pstruc;}
1124 /* if we reach the actual end of this function, an error has occured */
1125 /* cause we HAVE TO find an exterior loop or an open chain!!! */
1126 nrerror("backtracking failed in exterior loop");
1130 PRIVATE void backtrack_qm(int i, int j){
1131 /* divide multiloop into qm and qm1 */
1135 /* now backtrack [i ... j] in qm[] */
1136 r = urn() * qm[my_iindx[i] - j];
1137 qmt = qm1[jindx[j]+i]; k=i;
1139 for(k=i+1; k<=j; k++){
1140 qmt += (qm[my_iindx[i]-(k-1)]+expMLbase[k-i])*qm1[jindx[j]+k];
1143 if(k>j) nrerror("backtrack failed in qm");
1147 if(k<i+TURN) break; /* no more pairs */
1148 r = urn() * (qm[my_iindx[i]-(k-1)] + expMLbase[k-i]);
1149 if(expMLbase[k-i] >= r) break; /* no more pairs */
1154 PRIVATE void backtrack_qm1(int i,int j){
1155 /* i is paired to l, i<l<j; backtrack in qm1 to find l */
1158 r = urn() * qm1[jindx[j]+i];
1160 for (qt=0., l=i+TURN+1; l<=j; l++) {
1163 qt += qb[ii-l] * exp_E_MLstem(type, S1[i-1], S1[l+1], pf_params) * expMLbase[j-l];
1166 if (l>j) nrerror("backtrack failed in qm1");
1170 PRIVATE void backtrack_qm2(int k, int n){
1174 /* we have to search for our barrier u between qm1 and qm1 */
1175 for (qom2t = 0.,u=k+TURN+1; u<n-TURN-1; u++){
1176 qom2t += qm1[jindx[u]+k]*qm1[jindx[n]+(u+1)];
1177 if(qom2t > r) break;
1179 if(u==n-TURN) nrerror("backtrack failed in qm2");
1181 backtrack_qm1(u+1,n);
1184 PRIVATE void backtrack(int i, int j){
1185 int noGUclosure = pf_params->model_details.noGUclosure;
1189 int k, l, type, u, u1;
1191 pstruc[i-1] = '('; pstruc[j-1] = ')';
1193 r = urn() * qb[my_iindx[i]-j];
1194 type = ptype[my_iindx[i]-j];
1196 /*hairpin contribution*/
1197 if (((type==3)||(type==4))&&noGUclosure) qbt1 = 0;
1199 qbt1 = exp_E_Hairpin(u, type, S1[i+1], S1[j-1], sequence+i-1, pf_params)*
1200 scale[u+2]; /* add scale[u+2] */
1202 if (qbt1>=r) return; /* found the hairpin we're done */
1204 for (k=i+1; k<=MIN2(i+MAXLOOP+1,j-TURN-2); k++) {
1206 for (l=MAX2(k+TURN+1,j-1-MAXLOOP+u1); l<j; l++) {
1208 type_2 = ptype[my_iindx[k]-l];
1210 type_2 = rtype[type_2];
1211 /* add *scale[u1+u2+2] */
1212 qbt1 += qb[my_iindx[k]-l] * (scale[u1+j-l+1] *
1213 exp_E_IntLoop(u1, j-l-1, type, type_2,
1214 S1[i+1], S1[j-1], S1[k-1], S1[l+1], pf_params));
1216 if (qbt1 > r) break;
1218 if (qbt1 > r) break;
1226 /* backtrack in multi-loop */
1232 /* find the first split index */
1233 ii = my_iindx[i]; /* ii-j=[i,j] */
1234 jj = jindx[j]; /* jj+i=[j,i] */
1235 for (qt=0., k=i+1; k<j; k++) qt += qm[ii-(k-1)]*qm1[jj+k];
1237 for (qt=0., k=i+1; k<j; k++) {
1238 qt += qm[ii-(k-1)]*qm1[jj+k];
1241 if (k>=j) nrerror("backtrack failed, can't find split index ");
1243 backtrack_qm1(k, j);
1250 PUBLIC void assign_plist_from_pr(plist **pl, FLT_OR_DBL *probs, int length, double cut_off){
1251 int i, j, n, count, *index;
1255 index = get_iindx(length);
1257 /* first guess of the size needed for pl */
1258 *pl = (plist *)space(n*length*sizeof(plist));
1260 for (i=1; i<length; i++) {
1261 for (j=i+1; j<=length; j++) {
1262 /* skip all entries below the cutoff */
1263 if (probs[index[i]-j] < cut_off) continue;
1264 /* do we need to allocate more memory? */
1265 if (count == n * length - 1){
1267 *pl = (plist *)xrealloc(*pl, n * length * sizeof(plist));
1271 (*pl)[count].p = probs[index[i] - j];
1272 (*pl)[count++].type = 0;
1275 /* mark the end of pl */
1278 (*pl)[count].p = 0.;
1279 (*pl)[count++].type = 0;
1280 /* shrink memory to actual size needed */
1281 *pl = (plist *)xrealloc(*pl, count * sizeof(plist));
1286 /* this doesn't work if free_pf_arrays() is called before */
1287 PUBLIC void assign_plist_gquad_from_pr( plist **pl,
1291 int i, j, k, n, count, *index;
1295 if(!probs){ *pl = NULL; return;}
1297 index = get_iindx(length);
1299 /* first guess of the size needed for pl */
1300 *pl = (plist *)space(n*length*sizeof(plist));
1302 for (i=1; i<length; i++) {
1303 for (j=i+1; j<=length; j++) {
1304 /* skip all entries below the cutoff */
1305 if (probs[index[i]-j] < cut_off) continue;
1307 /* do we need to allocate more memory? */
1308 if (count == n * length - 1){
1310 *pl = (plist *)xrealloc(*pl, n * length * sizeof(plist));
1313 /* check for presence of gquadruplex */
1314 if((S[i] == 3) && (S[j] == 3)){
1315 /* add probability of a gquadruplex at position (i,j)
1320 (*pl)[count].p = probs[index[i] - j];
1321 (*pl)[count++].type = 1;
1322 /* now add the probabilies of it's actual pairing patterns */
1324 inner = get_plist_gquad_from_pr(S, i, j, G, probs, scale, pf_params);
1325 for(ptr=inner; ptr->i != 0; ptr++){
1326 if (count == n * length - 1){
1328 *pl = (plist *)xrealloc(*pl, n * length * sizeof(plist));
1330 /* check if we've already seen this pair */
1331 for(k = 0; k < count; k++)
1332 if(((*pl)[k].i == ptr->i) && ((*pl)[k].j == ptr->j))
1334 (*pl)[k].i = ptr->i;
1335 (*pl)[k].j = ptr->j;
1338 (*pl)[k].p = ptr->p;
1341 (*pl)[k].p += ptr->p;
1346 (*pl)[count].p = probs[index[i] - j];
1347 (*pl)[count++].type = 0;
1351 /* mark the end of pl */
1354 (*pl)[count++].p = 0.;
1355 /* shrink memory to actual size needed */
1356 *pl = (plist *)xrealloc(*pl, count * sizeof(plist));
1360 /* this doesn't work if free_pf_arrays() is called before */
1361 PUBLIC char *get_centroid_struct_gquad_pr( int length,
1364 /* compute the centroid structure of the ensemble, i.e. the strutcure
1365 with the minimal average distance to all other structures
1366 <d(S)> = \sum_{(i,j) \in S} (1-p_{ij}) + \sum_{(i,j) \notin S} p_{ij}
1367 Thus, the centroid is simply the structure containing all pairs with
1372 int *my_iindx = get_iindx(length);
1375 nrerror("get_centroid_struct_pr: probs==NULL!");
1378 centroid = (char *) space((length+1)*sizeof(char));
1379 for (i=0; i<length; i++) centroid[i]='.';
1380 for (i=1; i<=length; i++)
1381 for (j=i+TURN+1; j<=length; j++) {
1382 if ((p=probs[my_iindx[i]-j])>0.5) {
1383 /* check for presence of gquadruplex */
1384 if((S[i] == 3) && (S[j] == 3)){
1386 get_gquad_pattern_pf(S, i, j, pf_params, &L, l);
1389 = centroid[i+k+L+l[0]-1]\
1390 = centroid[i+k+2*L+l[0]+l[1]-1]\
1391 = centroid[i+k+3*L+l[0]+l[1]+l[2]-1]\
1394 /* skip everything within the gquad */
1395 i = j; j = j+TURN+1;
1396 *dist += (1-p); /* right? */
1399 centroid[i-1] = '(';
1400 centroid[j-1] = ')';
1407 centroid[length] = '\0';
1411 /* this function is a threadsafe replacement for centroid() */
1412 PUBLIC char *get_centroid_struct_pl(int length, double *dist, plist *pl){
1413 /* compute the centroid structure of the ensemble, i.e. the strutcure
1414 with the minimal average distance to all other structures
1415 <d(S)> = \sum_{(i,j) \in S} (1-p_{ij}) + \sum_{(i,j) \notin S} p_{ij}
1416 Thus, the centroid is simply the structure containing all pairs with
1422 nrerror("get_centroid_struct: pl==NULL!");
1425 centroid = (char *) space((length+1)*sizeof(char));
1426 for (i=0; i<length; i++) centroid[i]='.';
1427 for (i=0; pl[i].i>0; i++){
1428 if ((pl[i].p)>0.5) {
1429 centroid[pl[i].i-1] = '(';
1430 centroid[pl[i].j-1] = ')';
1431 *dist += (1-pl[i].p);
1435 centroid[length] = '\0';
1439 /* this function is a threadsafe replacement for centroid() */
1440 PUBLIC char *get_centroid_struct_pr(int length, double *dist, FLT_OR_DBL *probs){
1441 /* compute the centroid structure of the ensemble, i.e. the strutcure
1442 with the minimal average distance to all other structures
1443 <d(S)> = \sum_{(i,j) \in S} (1-p_{ij}) + \sum_{(i,j) \notin S} p_{ij}
1444 Thus, the centroid is simply the structure containing all pairs with
1449 int *index = get_iindx(length);
1452 nrerror("get_centroid_struct_pr: probs==NULL!");
1455 centroid = (char *) space((length+1)*sizeof(char));
1456 for (i=0; i<length; i++) centroid[i]='.';
1457 for (i=1; i<=length; i++)
1458 for (j=i+TURN+1; j<=length; j++) {
1459 if ((p=probs[index[i]-j])>0.5) {
1460 centroid[i-1] = '(';
1461 centroid[j-1] = ')';
1467 centroid[length] = '\0';
1471 PUBLIC plist *stackProb(double cutoff){
1477 nrerror("probs==NULL. You need to call pf_fold() before stackProb()");
1480 int *index = get_iindx(length);
1482 pl = (plist *) space(plsize*sizeof(plist));
1484 for (i=1; i<length; i++)
1485 for (j=i+TURN+3; j<=length; j++) {
1487 if((p=probs[index[i]-j]) < cutoff) continue;
1488 if (qb[index[i+1]-(j-1)]<FLT_MIN) continue;
1489 p *= qb[index[i+1]-(j-1)]/qb[index[i]-j];
1490 p *= exp_E_IntLoop(0,0,ptype[index[i]-j],rtype[ptype[index[i+1]-(j-1)]],
1491 0,0,0,0, pf_params)*scale[2];/* add *scale[u1+u2+2] */
1498 pl = xrealloc(pl, plsize*sizeof(plist));
1507 /*-------------------------------------------------------------------------*/
1508 /* make arrays used for pf_fold available to other routines */
1509 PUBLIC int get_pf_arrays( short **S_p,
1515 FLT_OR_DBL **qln_p){
1517 if(qb == NULL) return(0); /* check if pf_fold() has been called */
1518 *S_p = S; *S1_p = S1; *ptype_p = ptype;
1519 *qb_p = qb; *qm_p = qm;
1520 *q1k_p = q1k; *qln_p = qln;
1521 return(1); /* success */
1524 /* get the free energy of a subsequence from the q[] array */
1525 PUBLIC double get_subseq_F(int i, int j){
1527 nrerror("call pf_fold() to fill q[] array before calling get_subseq_F()");
1528 return ((-log(q[my_iindx[i]-j])-(j-i+1)*log(pf_params->pf_scale))*pf_params->kT/1000.0);
1532 PUBLIC double mean_bp_distance(int length){
1533 return mean_bp_distance_pr(length, probs);
1536 PUBLIC double mean_bp_distance_pr(int length, FLT_OR_DBL *p){
1537 /* compute the mean base pair distance in the thermodynamic ensemble */
1538 /* <d> = \sum_{a,b} p_a p_b d(S_a,S_b)
1539 this can be computed from the pair probs p_ij as
1540 <d> = \sum_{ij} p_{ij}(1-p_{ij}) */
1543 int *index = get_iindx((unsigned int) length);
1546 nrerror("p==NULL. You need to supply a valid probability matrix for mean_bp_distance_pr()");
1548 for (i=1; i<=length; i++)
1549 for (j=i+TURN+1; j<=length; j++)
1550 d += p[index[i]-j] * (1-p[index[i]-j]);
1556 PUBLIC FLT_OR_DBL *export_bppm(void){
1560 /*###########################################*/
1561 /*# deprecated functions below #*/
1562 /*###########################################*/
1564 /* this function is deprecated since it is not threadsafe */
1565 PUBLIC char *centroid(int length, double *dist) {
1566 /* compute the centroid structure of the ensemble, i.e. the strutcure
1567 with the minimal average distance to all other structures
1568 <d(S)> = \sum_{(i,j) \in S} (1-p_{ij}) + \sum_{(i,j) \notin S} p_{ij}
1569 Thus, the centroid is simply the structure containing all pairs with
1576 nrerror("pr==NULL. You need to call pf_fold() before centroid()");
1579 centroid = (char *) space((length+1)*sizeof(char));
1580 for (i=0; i<length; i++) centroid[i]='.';
1581 for (i=1; i<=length; i++)
1582 for (j=i+TURN+1; j<=length; j++) {
1583 if ((p=pr[my_iindx[i]-j])>0.5) {
1584 centroid[i-1] = '(';
1585 centroid[j-1] = ')';
1594 /* This function is deprecated since it uses the global array pr for calculations */
1595 PUBLIC double mean_bp_dist(int length) {
1596 /* compute the mean base pair distance in the thermodynamic ensemble */
1597 /* <d> = \sum_{a,b} p_a p_b d(S_a,S_b)
1598 this can be computed from the pair probs p_ij as
1599 <d> = \sum_{ij} p_{ij}(1-p_{ij}) */
1604 nrerror("pr==NULL. You need to call pf_fold() before mean_bp_dist()");
1606 for (i=1; i<=length; i++)
1607 for (j=i+TURN+1; j<=length; j++)
1608 d += pr[my_iindx[i]-j] * (1-pr[my_iindx[i]-j]);
1612 /*----------------------------------------------------------------------*/
1613 PUBLIC double expHairpinEnergy(int u, int type, short si1, short sj1,
1614 const char *string) {
1615 /* compute Boltzmann weight of a hairpin loop, multiply by scale[u+2] */
1617 kT = pf_params->kT; /* kT in cal/mol */
1619 q = pf_params->exphairpin[u];
1621 q = pf_params->exphairpin[30] * exp( -(pf_params->lxc*log( u/30.))*10./kT);
1622 if ((tetra_loop)&&(u==4)) {
1623 char tl[7]={0}, *ts;
1624 strncpy(tl, string, 6);
1625 if ((ts=strstr(pf_params->Tetraloops, tl)))
1626 return (pf_params->exptetra[(ts-pf_params->Tetraloops)/7]);
1628 if ((tetra_loop)&&(u==6)) {
1629 char tl[9]={0}, *ts;
1630 strncpy(tl, string, 6);
1631 if ((ts=strstr(pf_params->Hexaloops, tl)))
1632 return (pf_params->exphex[(ts-pf_params->Hexaloops)/9]);
1635 char tl[6]={0}, *ts;
1636 strncpy(tl, string, 5);
1637 if ((ts=strstr(pf_params->Triloops, tl)))
1638 return (pf_params->exptri[(ts-pf_params->Triloops)/6]);
1640 q *= pf_params->expTermAU;
1642 else /* no mismatches for tri-loops */
1643 q *= pf_params->expmismatchH[type][si1][sj1];
1647 PUBLIC double expLoopEnergy(int u1, int u2, int type, int type2,
1648 short si1, short sj1, short sp1, short sq1) {
1649 /* compute Boltzmann weight of interior loop,
1650 multiply by scale[u1+u2+2] for scaling */
1654 if ((no_closingGU) && ((type2==3)||(type2==4)||(type==2)||(type==4)))
1657 if ((u1==0) && (u2==0)) /* stack */
1658 z = pf_params->expstack[type][type2];
1659 else if (no_close==0) {
1660 if ((u1==0)||(u2==0)) { /* bulge */
1663 z = pf_params->expbulge[u];
1664 if (u2+u1==1) z *= pf_params->expstack[type][type2];
1666 if (type>2) z *= pf_params->expTermAU;
1667 if (type2>2) z *= pf_params->expTermAU;
1670 else { /* interior loop */
1671 if (u1+u2==2) /* size 2 is special */
1672 z = pf_params->expint11[type][type2][si1][sj1];
1673 else if ((u1==1) && (u2==2))
1674 z = pf_params->expint21[type][type2][si1][sq1][sj1];
1675 else if ((u1==2) && (u2==1))
1676 z = pf_params->expint21[type2][type][sq1][si1][sp1];
1677 else if ((u1==2) && (u2==2))
1678 z = pf_params->expint22[type][type2][si1][sp1][sq1][sj1];
1679 else if (((u1==2)&&(u2==3))||((u1==3)&&(u2==2))){ /*2-3 is special*/
1680 z = pf_params->expinternal[5]*
1681 pf_params->expmismatch23I[type][si1][sj1]*
1682 pf_params->expmismatch23I[type2][sq1][sp1];
1683 z *= pf_params->expninio[2][1];
1685 else if ((u1==1)||(u2==1)) { /*1-n is special*/
1686 z = pf_params->expinternal[u1+u2]*
1687 pf_params->expmismatch1nI[type][si1][sj1]*
1688 pf_params->expmismatch1nI[type2][sq1][sp1];
1689 z *= pf_params->expninio[2][abs(u1-u2)];
1692 z = pf_params->expinternal[u1+u2]*
1693 pf_params->expmismatchI[type][si1][sj1]*
1694 pf_params->expmismatchI[type2][sq1][sp1];
1695 z *= pf_params->expninio[2][abs(u1-u2)];
1702 PUBLIC void init_pf_circ_fold(int length){
1706 PUBLIC void init_pf_fold(int length){