WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / lib / read_epars.c
diff --git a/binaries/src/ViennaRNA/lib/read_epars.c b/binaries/src/ViennaRNA/lib/read_epars.c
new file mode 100644 (file)
index 0000000..2da7872
--- /dev/null
@@ -0,0 +1,1075 @@
+/*
+                  read energy parameters from a file
+
+                      Stephan Kopp, Ivo Hofacker
+                          Vienna RNA Package
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include <stdarg.h>
+#include "utils.h"
+#include "energy_const.h"
+#include "energy_par.h"
+#include "read_epars.h"
+
+#define PUBLIC
+#define PRIVATE   static
+#define PARSET 20
+
+#define DEF -50
+#define NST 0
+
+PRIVATE FILE *fp;
+
+PRIVATE void  display_array(int *p, int size, int line, FILE *fp);
+PRIVATE char  *get_array1(int *arr, int size);
+PRIVATE void  ignore_comment(char *line);
+PRIVATE void  check_symmetry(void);
+PRIVATE void  update_nst(int array[NBPAIRS+1][NBPAIRS+1][5][5][5][5]);
+
+/**
+*** read a 1dimensional array from file
+*** \param array  a pointer to the first element in the array
+*** \param dim    the size of the array
+*** \param shift  the first position the new values will be written in
+**/
+PRIVATE void  rd_1dim(int *array, int dim, int shift);
+PRIVATE void  rd_1dim_slice(int *array, int dim, int shift, int post);
+PRIVATE void  rd_2dim(int *array,
+                      int dim1, int dim2,
+                      int shift1, int shift2);
+PRIVATE void  rd_2dim_slice(int *array,
+                      int dim1, int dim2,
+                      int shift1, int shift2,
+                      int post1, int post2);
+PRIVATE void  rd_3dim(int *array,
+                      int dim1, int dim2, int dim3,
+                      int shift1, int shift2, int shift3);
+PRIVATE void  rd_3dim_slice(int *array,
+                      int dim1, int dim2, int dim3,
+                      int shift1, int shift2, int shift3,
+                      int post1, int post2, int post3);
+PRIVATE void  rd_4dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4,
+                      int shift1, int shift2, int shift3, int shift4);
+PRIVATE void  rd_4dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4,
+                      int shift1, int shift2, int shift3, int shift4,
+                      int post1, int post2, int post3, int post4);
+PRIVATE void  rd_5dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5,
+                      int shift1, int shift2, int shift3, int shift4, int shift5);
+PRIVATE void  rd_5dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5,
+                      int shift1, int shift2, int shift3, int shift4, int shift5,
+                      int post1, int post2, int post3, int post4, int post5);
+PRIVATE void  rd_6dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5, int dim6,
+                      int shift1, int shift2, int shift3, int shift4, int shift5, int shift6);
+PRIVATE void  rd_6dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5, int dim6,
+                      int shift1, int shift2, int shift3, int shift4, int shift5, int shift6,
+                      int post1, int post2, int post3, int post4, int post5, int post6);
+PRIVATE void  rd_Tetraloop37(void);
+PRIVATE void  rd_Triloop37(void);
+PRIVATE void  rd_Hexaloop37(void);
+
+/*------------------------------------------------------------*/
+PUBLIC void read_parameter_file(const char fname[]){
+  char        *line, ident[256];
+  enum parset type;
+  int         r;
+
+  if (!(fp=fopen(fname,"r"))) {
+    fprintf(stderr,
+            "\nread_parameter_file:\n"
+            "\t\tcan't open file %s\n"
+            "\t\tusing default parameters instead.\n", fname);
+    return;
+  }
+
+  if (!(line = get_line(fp))) {
+    fprintf(stderr," File %s is inproper.\n", fname);
+    fclose(fp);
+    return;
+  }
+
+  if (strncmp(line,"## RNAfold parameter file v2.0",30)!=0) {
+    fprintf(stderr,
+            "Missing header line in file.\n"
+            "May be this file has not v2.0 format.\n"
+            "Use INTERRUPT-key to stop.\n");
+  }
+  free(line);
+
+  while((line=get_line(fp))) {
+
+    r = sscanf(line, "# %255s", ident);
+    if (r==1) {
+      type = gettype(ident);
+      switch (type){
+        case QUIT:    break;
+        case S:       rd_2dim(&(stack37[0][0]), NBPAIRS+1, NBPAIRS+1, 1, 1);
+                      break;
+        case S_H:     rd_2dim(&(stackdH[0][0]), NBPAIRS+1, NBPAIRS+1, 1, 1);
+                      break;
+        case HP:      rd_1dim(&(hairpin37[0]), 31, 0);
+                      break;
+        case HP_H:    rd_1dim(&(hairpindH[0]), 31, 0);
+                      break;
+        case B:       rd_1dim(&(bulge37[0]), 31, 0);
+                      break;
+        case B_H:     rd_1dim(&(bulgedH[0]), 31, 0);
+                      break;
+        case IL:      rd_1dim(&(internal_loop37[0]), 31, 0);
+                      break;
+        case IL_H:    rd_1dim(&(internal_loopdH[0]), 31, 0);
+                      break;
+        case MME:     rd_3dim(&(mismatchExt37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MME_H:   rd_3dim(&(mismatchExtdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMH:     rd_3dim(&(mismatchH37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMH_H:   rd_3dim(&(mismatchHdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI:     rd_3dim(&(mismatchI37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI_H:   rd_3dim(&(mismatchIdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI1N:   rd_3dim(&(mismatch1nI37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI1N_H: rd_3dim(&(mismatch1nIdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI23:   rd_3dim(&(mismatch23I37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMI23_H: rd_3dim(&(mismatch23IdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMM:     rd_3dim(&(mismatchM37[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case MMM_H:   rd_3dim(&(mismatchMdH[0][0][0]),
+                          NBPAIRS+1, 5, 5,
+                          1, 0, 0);
+                      break;
+        case INT11:   rd_4dim(&(int11_37[0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5,
+                          1, 1, 0, 0);
+                      break;
+        case INT11_H: rd_4dim(&(int11_dH[0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5,
+                          1, 1, 0, 0);
+                      break;
+        case INT21:   rd_5dim(&(int21_37[0][0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5, 5,
+                          1, 1, 0, 0, 0);
+                      break;
+        case INT21_H: rd_5dim(&(int21_dH[0][0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5, 5,
+                          1, 1, 0, 0, 0);
+                      break;
+        case INT22:   rd_6dim_slice(&(int22_37[0][0][0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5, 5, 5,
+                          1, 1, 1, 1, 1, 1,
+                          1, 1, 0, 0, 0, 0);
+                      update_nst(int22_37);
+                      break;
+        case INT22_H: rd_6dim_slice(&(int22_dH[0][0][0][0][0][0]),
+                          NBPAIRS+1, NBPAIRS+1, 5, 5, 5, 5,
+                          1, 1, 1, 1, 1, 1,
+                          1, 1, 0, 0, 0, 0);
+                      update_nst(int22_dH);
+                      break;
+        case D5:      rd_2dim(&(dangle5_37[0][0]), NBPAIRS+1, 5, 1, 0);
+                      break;
+        case D5_H:    rd_2dim(&(dangle5_dH[0][0]), NBPAIRS+1, 5, 1, 0);
+                      break;
+        case D3:      rd_2dim(&(dangle3_37[0][0]), NBPAIRS+1, 5, 1, 0);
+                      break;
+        case D3_H:    rd_2dim(&(dangle3_dH[0][0]), NBPAIRS+1, 5, 1, 0);
+                      break;
+        case ML:      {
+                        int values[6];
+                        rd_1dim(&values[0], 6, 0);
+                        ML_BASE37     = values[0];
+                        ML_BASEdH     = values[1];
+                        ML_closing37  = values[2];
+                        ML_closingdH  = values[3];
+                        ML_intern37   = values[4];
+                        ML_interndH   = values[5];
+                      }
+                      break;
+        case NIN:     {
+                        int values[3];
+                        rd_1dim(&values[0], 3, 0);
+                        ninio37 = values[0];
+                        niniodH = values[1];
+                        MAX_NINIO  = values[2];
+                      }
+                      break;
+        case MISC:    {
+                        int values[4];
+                        rd_1dim(&values[0], 4, 0);
+                        DuplexInit37 = values[0];
+                        DuplexInitdH = values[1];
+                        TerminalAU37 = values[2];
+                        TerminalAUdH = values[3];
+                      }
+                      break;
+        case TL:      rd_Tetraloop37();
+                      break;
+        case TRI:     rd_Triloop37();
+                      break;
+        case HEX:     rd_Hexaloop37();
+                      break;
+        default:      /* do nothing but complain */
+                      fprintf(stderr,"read_epars: Unknown field identifier in `%s'\n", line);
+      }
+    } /* else ignore line */
+    free(line);
+  }
+  fclose(fp);
+
+  check_symmetry();
+  return;
+}
+
+/*------------------------------------------------------------*/
+
+PRIVATE void display_array(int *p, int size, int nl, FILE *fp)
+{
+  int i;
+
+  for (i=1; i<=size; i++, p++) {
+    switch(*p)
+      {
+      case  INF: fprintf(fp,"   INF"); break;
+      case -INF: fprintf(fp,"  -INf"); break;
+      case  DEF: fprintf(fp,"   DEF"); break;
+      default:   fprintf(fp,"%6d",  *p); break;
+      }
+    if ((i%nl)==0) fprintf(fp,"\n");
+  }
+  if (size%nl) fprintf(fp,"\n");
+  return;
+}
+
+/*------------------------------------------------------------*/
+
+PRIVATE char *get_array1(int *arr, int size)
+{
+  int    i, p, pos, pp, r, last;
+  char  *line, buf[16];
+
+
+  i = last = 0;
+  while( i<size ) {
+    line = get_line(fp);
+    if (!line) nrerror("unexpected end of file in get_array1");
+    ignore_comment(line);
+    pos=0;
+    while ((i<size)&&(sscanf(line+pos,"%15s%n", buf, &pp)==1)) {
+      pos += pp;
+      if (buf[0]=='*') {i++; continue;}
+      else if (buf[0]=='x') { /* should only be used for loop parameters */
+        if (i==0) nrerror("can't extrapolate first value");
+        p = arr[last] + (int) (0.5+ lxc37*log(((double) i)/(double)(last)));
+      }
+      else if (strcmp(buf,"DEF") == 0) p = DEF;
+      else if (strcmp(buf,"INF") == 0) p = INF;
+      else if (strcmp(buf,"NST") == 0) p = NST;
+      else {
+        r=sscanf(buf,"%d", &p);
+        if (r!=1) {
+          return line+pos;
+          fprintf(stderr, "can't interpret `%s' in get_array1\n", buf);
+          exit(1);
+        }
+        last = i;
+      }
+      arr[i++]=p;
+    }
+    free(line);
+  }
+
+  return NULL;
+}
+
+PRIVATE void rd_1dim(int *array, int dim, int shift){
+  rd_1dim_slice(array, dim, shift, 0);
+}
+
+PRIVATE void rd_1dim_slice(int *array, int dim, int shift, int post){
+  char *cp;
+  cp   = get_array1(array+shift, dim-shift-post);
+
+  if (cp) {
+    fprintf(stderr,"\nrd_1dim: %s\n", cp);
+    exit(1);
+  }
+  return;
+}
+
+PRIVATE void  rd_2dim(int *array, int dim1, int dim2, int shift1, int shift2){
+  rd_2dim_slice(array, dim1, dim2, shift1, shift2, 0, 0);
+}
+
+PRIVATE void  rd_2dim_slice(int *array,
+                      int dim1, int dim2,
+                      int shift1, int shift2,
+                      int post1, int post2){
+  int i;
+  int delta_pre   = shift1 + shift2;
+  int delta_post  = post1 + post2;
+
+  if(delta_pre + delta_post == 0){
+    rd_1dim(array, dim1 * dim2, 0);
+    return;
+  }
+  for (i=shift1; i<dim1 - post1; i++)
+    rd_1dim_slice(array + (i*dim2), dim2, shift2, post2);
+  return;
+}
+
+PRIVATE void  rd_3dim(int *array, int dim1, int dim2, int dim3, int shift1, int shift2, int shift3){
+  rd_3dim_slice(array,
+                dim1, dim2, dim3,
+                shift1, shift2, shift3,
+                0, 0, 0);
+}
+
+PRIVATE void  rd_3dim_slice(int *array,
+                            int dim1, int dim2, int dim3,
+                            int shift1, int shift2, int shift3,
+                            int post1, int post2, int post3){
+  int    i;
+  int delta_pre   = shift1 + shift2 + shift3;
+  int delta_post  = post1 + post2 + post3;
+
+  if(delta_pre + delta_post == 0){
+    rd_1dim(array, dim1 * dim2 * dim3, 0);
+    return;
+  }
+  for (i=shift1; i<dim1 - post1; i++){
+    rd_2dim_slice(array + (i * dim2 * dim3),
+            dim2, dim3,
+            shift2, shift3,
+            post2, post3);
+  }
+  return;
+}
+
+PRIVATE void  rd_4dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4,
+                      int shift1, int shift2, int shift3, int shift4){
+  rd_4dim_slice(array,
+                dim1, dim2, dim3, dim4,
+                shift1, shift2, shift3, shift4,
+                0, 0, 0, 0);
+}
+
+PRIVATE void  rd_4dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4,
+                      int shift1, int shift2, int shift3, int shift4,
+                      int post1, int post2, int post3, int post4){
+  int i;
+  int delta_pre   = shift1 + shift2 + shift3 + shift4;
+  int delta_post  = post1 + post2 + post3 + post4;
+
+  if(delta_pre + delta_post == 0){
+    rd_1dim(array, dim1 * dim2 * dim3 * dim4, 0);
+    return;
+  }
+  for(i=shift1; i<dim1 - post1; i++){
+    rd_3dim_slice(array + (i * dim2 * dim3 * dim4),
+            dim2, dim3, dim4,
+            shift2, shift3, shift4,
+            post2, post3, post4);
+  }
+  return;
+}
+
+PRIVATE void  rd_5dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5,
+                      int shift1, int shift2, int shift3, int shift4, int shift5){
+  rd_5dim_slice(array,
+                dim1, dim2, dim3, dim4, dim5,
+                shift1, shift2, shift3, shift4, shift5,
+                0, 0, 0, 0, 0);
+}
+
+PRIVATE void  rd_5dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5,
+                      int shift1, int shift2, int shift3, int shift4, int shift5,
+                      int post1, int post2, int post3, int post4, int post5){
+  int i;
+  int delta_pre   = shift1 + shift2 + shift3 + shift4 + shift5;
+  int delta_post  = post1 + post2 + post3 + post4 + post5;
+
+  if(delta_pre + delta_post == 0){
+    rd_1dim(array, dim1 * dim2 * dim3 * dim4 * dim5, 0);
+    return;
+  }
+  for(i=shift1; i<dim1 - post1; i++)
+    rd_4dim_slice(array + (i * dim2 * dim3 * dim4 * dim5),
+            dim2, dim3, dim4, dim5,
+            shift2, shift3, shift4, shift5,
+            post2, post3, post4, post5);
+  return;
+}
+
+/**
+*** \param dim1   The size of the first dimension
+*** \param shift1 The pre shift for the first dimension
+**/
+PRIVATE void  rd_6dim(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5, int dim6,
+                      int shift1, int shift2, int shift3, int shift4, int shift5, int shift6){
+  rd_6dim_slice(array,
+                dim1, dim2, dim3, dim4, dim5, dim6,
+                shift1, shift2, shift3, shift4, shift5, shift6,
+                0, 0, 0, 0, 0, 0);
+}
+
+PRIVATE void  rd_6dim_slice(int *array,
+                      int dim1, int dim2, int dim3, int dim4, int dim5, int dim6,
+                      int shift1, int shift2, int shift3, int shift4, int shift5, int shift6,
+                      int post1, int post2, int post3, int post4, int post5, int post6){
+  int i;
+  int delta_pre   = shift1 + shift2 + shift3 + shift4 + shift5 + shift6;
+  int delta_post  = post1 + post2 + post3 + post4 + post5 + post6;
+
+  if(delta_pre + delta_post == 0){
+    rd_1dim(array, dim1 * dim2 * dim3 * dim4 * dim5 * dim6, 0);
+    return;
+  }
+  for(i=shift1; i<dim1 - post1; i++)
+    rd_5dim_slice(array + (i * dim2 * dim3 * dim4 * dim5 * dim6),
+            dim2, dim3, dim4, dim5, dim6,
+            shift2, shift3, shift4, shift5, shift6,
+            post2, post3, post4, post5, post6);
+  return;
+}
+
+
+/*------------------------------------------------------------*/
+PRIVATE void  rd_Tetraloop37(void)
+{
+  int    i, r;
+  char   *buf;
+
+  i=0;
+  /* erase old tetraloop entries */
+  memset(&Tetraloops, 0, 281);
+  memset(&Tetraloop37, 0, sizeof(int)*40);
+  memset(&TetraloopdH, 0, sizeof(int)*40);
+  do {
+    buf = get_line(fp);
+    if (buf==NULL) break;
+    r = sscanf(buf,"%6s %d %d", &Tetraloops[7*i], &Tetraloop37[i], &TetraloopdH[i]);
+    strcat(Tetraloops, " ");
+    free(buf);
+    i++;
+  } while((r==3)&&(i<40));
+  return;
+}
+
+/*------------------------------------------------------------*/
+PRIVATE void  rd_Hexaloop37(void)
+{
+  int    i, r;
+  char   *buf;
+
+  i=0;
+  /* erase old hexaloop entries */
+  memset(&Hexaloops, 0, 361);
+  memset(&Hexaloop37, 0, sizeof(int)*40);
+  memset(&HexaloopdH, 0, sizeof(int)*40);
+  do {
+    buf = get_line(fp);
+    if (buf==NULL) break;
+    r = sscanf(buf,"%8s %d %d", &Hexaloops[9*i], &Hexaloop37[i], &HexaloopdH[i]);
+    strcat(Hexaloops, " ");
+    free(buf);
+    i++;
+  } while((r==3)&&(i<40));
+  return;
+}
+
+/*------------------------------------------------------------*/
+PRIVATE void  rd_Triloop37(void)
+{
+  int    i, r;
+  char   *buf;
+
+  i=0;
+  /* erase old hexaloop entries */
+  memset(&Triloops,   0, 241);
+  memset(&Triloop37,  0, sizeof(int)*40);
+  memset(&TriloopdH,  0, sizeof(int)*40);
+  do {
+    buf = get_line(fp);
+    if (buf==NULL) break;
+    r = sscanf(buf,"%5s %d %d", &Triloops[6*i], &Triloop37[i], &TriloopdH[i]);
+    strcat(Triloops, " ");
+    free(buf);
+    i++;
+  } while((r==3)&&(i<40));
+  return;
+}
+
+/*------------------------------------------------------------*/
+
+
+PRIVATE void ignore_comment(char * line)
+{
+  /* excise C style comments */
+  /* only one comment per line, no multiline comments */
+  char *cp1, *cp2;
+
+  if ((cp1=strstr(line, "/*"))) {
+    cp2 = strstr(cp1, "*/");
+    if (cp2==NULL)
+      nrerror("unclosed comment in parameter file");
+    /* can't use strcpy for overlapping strings */
+    for (cp2+=2; *cp2!='\0'; cp2++, cp1++)
+      *cp1 = *cp2;
+    *cp1 = '\0';
+  }
+
+  return;
+}
+/*------------------------------------------------------------*/
+
+PUBLIC char *settype(enum parset s){
+  switch(s){
+    case        S:  return "stack";
+    case      S_H:  return "stack_enthalpies";
+    case       HP:  return "hairpin";
+    case     HP_H:  return "hairpin_enthalpies";
+    case        B:  return "bulge";
+    case      B_H:  return "bulge_enthalpies";
+    case       IL:  return "interior";
+    case     IL_H:  return "interior_enthalpies";
+    case      MME:  return "mismatch_exterior";
+    case    MME_H:  return "mismatch_exterior_enthalpies";
+    case      MMH:  return "mismatch_hairpin";
+    case    MMH_H:  return "mismatch_hairpin_enthalpies";
+    case      MMI:  return "mismatch_interior";
+    case    MMI_H:  return "mismatch_interior_enthalpies";
+    case    MMI1N:  return "mismatch_interior_1n";
+    case  MMI1N_H:  return "mismatch_interior_1n_enthalpies";
+    case    MMI23:  return "mismatch_interior_23";
+    case  MMI23_H:  return "mismatch_interior_23_enthalpies";
+    case      MMM:  return "mismatch_multi";
+    case    MMM_H:  return "mismatch_multi_enthalpies";
+    case       D5:  return "dangle5";
+    case     D5_H:  return "dangle5_enthalpies";
+    case       D3:  return "dangle3";
+    case     D3_H:  return "dangle3_enthalpies";
+    case    INT11:  return "int11";
+    case  INT11_H:  return "int11_enthalpies";
+    case    INT21:  return "int21";
+    case  INT21_H:  return "int21_enthalpies";
+    case    INT22:  return "int22";
+    case  INT22_H:  return "int22_enthalpies";
+    case       ML:  return "ML_params";
+    case      NIN:  return "NINIO";
+    case      TRI:  return "Triloops";
+    case       TL:  return "Tetraloops";
+    case      HEX:  return "Hexaloops";
+    case     QUIT:  return "END";
+    case     MISC:  return "Misc";
+    default: nrerror("\nThe answer is: 42\n");
+  }
+  return "";
+}
+/*------------------------------------------------------------*/
+
+PUBLIC enum parset gettype(const char *ident){
+  if      (strcmp(ident,"stack") == 0)                            return S;
+  else if (strcmp(ident,"stack_enthalpies") == 0)                 return S_H;
+  else if (strcmp(ident,"hairpin") == 0)                          return HP;
+  else if (strcmp(ident,"hairpin_enthalpies") == 0)               return HP_H;
+  else if (strcmp(ident,"bulge") == 0)                            return B;
+  else if (strcmp(ident,"bulge_enthalpies") == 0)                 return B_H;
+  else if (strcmp(ident,"interior") == 0)                         return IL;
+  else if (strcmp(ident,"interior_enthalpies") == 0)              return IL_H;
+  else if (strcmp(ident,"mismatch_exterior") == 0)                return MME;
+  else if (strcmp(ident,"mismatch_exterior_enthalpies") == 0)     return MME_H;
+  else if (strcmp(ident,"mismatch_hairpin") == 0)                 return MMH;
+  else if (strcmp(ident,"mismatch_hairpin_enthalpies") == 0)      return MMH_H;
+  else if (strcmp(ident,"mismatch_interior") == 0)                return MMI;
+  else if (strcmp(ident,"mismatch_interior_enthalpies") == 0)     return MMI_H;
+  else if (strcmp(ident,"mismatch_interior_1n") == 0)             return MMI1N;
+  else if (strcmp(ident,"mismatch_interior_1n_enthalpies") == 0)  return MMI1N_H;
+  else if (strcmp(ident,"mismatch_interior_23") == 0)             return MMI23;
+  else if (strcmp(ident,"mismatch_interior_23_enthalpies") == 0)  return MMI23_H;
+  else if (strcmp(ident,"mismatch_multi") == 0)                   return MMM;
+  else if (strcmp(ident,"mismatch_multi_enthalpies") == 0)        return MMM_H;
+  else if (strcmp(ident,"int11") == 0)                            return INT11;
+  else if (strcmp(ident,"int11_enthalpies") == 0)                 return INT11_H;
+  else if (strcmp(ident,"int21") == 0)                            return INT21;
+  else if (strcmp(ident,"int21_enthalpies") == 0)                 return INT21_H;
+  else if (strcmp(ident,"int22") == 0)                            return INT22;
+  else if (strcmp(ident,"int22_enthalpies") == 0)                 return INT22_H;
+  else if (strcmp(ident,"dangle5")== 0)                           return D5;
+  else if (strcmp(ident,"dangle5_enthalpies")== 0)                return D5_H;
+  else if (strcmp(ident,"dangle3")== 0)                           return D3;
+  else if (strcmp(ident,"dangle3_enthalpies")== 0)                return D3_H;
+  else if (strcmp(ident,"ML_params")== 0)                         return ML;
+  else if (strcmp(ident,"NINIO") == 0)                            return NIN;
+  else if (strcmp(ident,"Triloops") == 0)                         return TRI;
+  else if (strcmp(ident,"Tetraloops") == 0)                       return TL;
+  else if (strcmp(ident,"Hexaloops") == 0)                        return HEX;
+  else if (strcmp(ident,"Misc") == 0)                             return MISC;
+  else if (strcmp(ident,"END") == 0)                              return QUIT;
+  else return UNKNOWN;
+}
+
+/*---------------------------------------------------------------*/
+
+PUBLIC void write_parameter_file(const char fname[]){
+  FILE *outfp;
+  int c;
+  char *pnames[] = {"NP", "CG", "GC", "GU", "UG", "AU", "UA", " @"};
+  char bnames[] = "@ACGU";
+  outfp = fopen(fname, "w");
+  if (!outfp) {
+    fprintf(stderr, "can't open file %s\n", fname);
+    exit(1);
+  }
+  fprintf(outfp,"## RNAfold parameter file v2.0\n");
+
+  fprintf(outfp,"\n# %s\n", settype(S));
+  fprintf(outfp,"/*  CG    GC    GU    UG    AU    UA    @  */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(stack37[c]+1,NBPAIRS,NBPAIRS, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(S_H));
+  fprintf(outfp,"/*  CG    GC    GU    UG    AU    UA    @  */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(stackdH[c]+1,NBPAIRS,NBPAIRS, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(MMH));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchH37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMH_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchHdH[k][i],5,5, outfp);
+
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchI37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchIdH[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI1N));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatch1nI37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI1N_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatch1nIdH[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI23));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatch23I37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMI23_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatch23IdH[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMM));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchM37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MMM_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchMdH[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MME));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchExt37[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(MME_H));
+  { int i,k;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (i=0; i<5; i++)
+      display_array(mismatchExtdH[k][i],5,5, outfp);
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(D5));
+  fprintf(outfp,"/*  @     A     C     G     U   */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(dangle5_37[c], 5, 5, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(D5_H));
+  fprintf(outfp,"/*  @     A     C     G     U   */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(dangle5_dH[c], 5, 5, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(D3));
+  fprintf(outfp,"/*  @     A     C     G     U   */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(dangle3_37[c], 5, 5, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(D3_H));
+  fprintf(outfp,"/*  @     A     C     G     U   */\n");
+  for (c=1; c<NBPAIRS+1; c++)
+    display_array(dangle3_dH[c], 5, 5, outfp);
+
+
+  /* dont print "no pair" entries for interior loop arrays */
+  fprintf(outfp,"\n# %s\n", settype(INT11));
+  { int i,k,l;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (l=1; l<NBPAIRS+1; l++) {
+      fprintf(outfp, "/* %2s..%2s */\n", pnames[k], pnames[l]);
+      for (i=0; i<5; i++)
+        display_array(int11_37[k][l][i], 5, 5, outfp);
+    }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(INT11_H));
+  { int i,k,l;
+  for (k=1; k<NBPAIRS+1; k++)
+    for (l=1; l<NBPAIRS+1; l++) {
+      fprintf(outfp, "/* %2s..%2s */\n", pnames[k], pnames[l]);
+      for (i=0; i<5; i++)
+        display_array(int11_dH[k][l][i],5,5, outfp);
+    }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(INT21));
+  { int p1, p2, i, j;
+  for (p1=1; p1<NBPAIRS+1; p1++)
+    for (p2=1; p2<NBPAIRS+1; p2++)
+      for (i=0; i<5; i++) {
+        fprintf(outfp, "/* %2s.%c..%2s */\n",
+                pnames[p1], bnames[i], pnames[p2]);
+        for (j=0; j<5; j++)
+          display_array(int21_37[p1][p2][i][j],5,5, outfp);
+      }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(INT21_H));
+  { int p1, p2, i, j;
+  for (p1=1; p1<NBPAIRS+1; p1++)
+    for (p2=1; p2<NBPAIRS+1; p2++)
+      for (i=0; i<5; i++) {
+        fprintf(outfp, "/* %2s.%c..%2s */\n",
+                pnames[p1], bnames[i], pnames[p2]);
+        for (j=0; j<5; j++)
+          display_array(int21_dH[p1][p2][i][j],5,5, outfp);
+      }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(INT22));
+  { int p1, p2, i, j, k;
+  for (p1=1; p1<NBPAIRS; p1++)
+    for (p2=1; p2<NBPAIRS; p2++)
+      for (i=1; i<5; i++)
+        for (j=1; j<5; j++) {
+          fprintf(outfp, "/* %2s.%c%c..%2s */\n",
+                  pnames[p1], bnames[i], bnames[j], pnames[p2]);
+          for (k=1; k<5; k++)
+            display_array(int22_37[p1][p2][i][j][k]+1,4,5, outfp);
+        }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(INT22_H));
+  { int p1, p2, i, j, k;
+  for (p1=1; p1<NBPAIRS; p1++)
+    for (p2=1; p2<NBPAIRS; p2++)
+      for (i=1; i<5; i++)
+        for (j=1; j<5; j++) {
+          fprintf(outfp, "/* %2s.%c%c..%2s */\n",
+                  pnames[p1], bnames[i], bnames[j], pnames[p2]);
+          for (k=1; k<5; k++)
+            display_array(int22_dH[p1][p2][i][j][k]+1,4,5, outfp);
+        }
+  }
+
+  fprintf(outfp,"\n# %s\n", settype(HP));
+  display_array(hairpin37, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(HP_H));
+  display_array(hairpindH, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(B));
+  display_array(bulge37, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(B_H));
+  display_array(bulgedH, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(IL));
+  display_array(internal_loop37, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(IL_H));
+  display_array(internal_loopdH, 31, 10, outfp);
+
+  fprintf(outfp,"\n# %s\n", settype(ML));
+  fprintf(outfp,"/* F = cu*n_unpaired + cc + ci*loop_degree (+TermAU) */\n");
+  fprintf(outfp,"/*\t    cu\t cu_dH\t    cc\t cc_dH\t    ci\t ci_dH  */\n");
+  fprintf(outfp,"\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\n", ML_BASE37, ML_BASEdH, ML_closing37, ML_closingdH, ML_intern37, ML_interndH);
+
+  fprintf(outfp,"\n# %s\n", settype(NIN));
+  fprintf(outfp,"/* Ninio = MIN(max, m*|n1-n2| */\n"
+              "/*\t    m\t  m_dH     max  */\n"
+              "\t%6d\t%6d\t%6d\n", ninio37, niniodH, MAX_NINIO);
+
+  fprintf(outfp,"\n# %s\n", settype(MISC));
+  fprintf(outfp,"/* all parameters are pairs of 'energy enthalpy' */\n");
+  fprintf(outfp,"/*    DuplexInit     TerminalAU      LXC */\n");
+  fprintf(outfp,"   %6d %6d %6d  %6d %3.6f %6d\n", DuplexInit37, DuplexInitdH, TerminalAU37, TerminalAUdH, lxc37, 0);
+
+  fprintf(outfp,"\n# %s\n", settype(HEX));
+  for (c=0; c< strlen(Hexaloops)/9; c++)
+    fprintf(outfp,"\t%.8s %6d %6d\n", Hexaloops+c*9, Hexaloop37[c], HexaloopdH[c]);
+
+  fprintf(outfp,"\n# %s\n", settype(TL));
+  for (c=0; c< strlen(Tetraloops)/7; c++)
+    fprintf(outfp,"\t%.6s %6d %6d\n", Tetraloops+c*7, Tetraloop37[c], TetraloopdH[c]);
+
+  fprintf(outfp,"\n# %s\n", settype(TRI));
+  for (c=0; c< strlen(Triloops)/6; c++)
+    fprintf(outfp,"\t%.5s %6d %6d\n", Triloops+c*6, Triloop37[c], TriloopdH[c]);
+
+  fprintf(outfp,"\n# %s\n", settype(QUIT));
+  fclose(outfp);
+}
+
+PRIVATE void check_symmetry(void) {
+  int i,j,k,l;
+
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      if (stack37[i][j] != stack37[j][i])
+        fprintf(stderr, "WARNING: stacking energies not symmetric\n");
+
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      if (stackdH[i][j] != stackdH[j][i])
+        fprintf(stderr, "WARNING: stacking enthalpies not symmetric\n");
+
+
+  /* interior 1x1 loops */
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      for (k=0; k<5; k++)
+        for (l=0; l<5; l++)
+          if (int11_37[i][j][k][l] != int11_37[j][i][l][k])
+            fprintf(stderr, "WARNING: int11 energies not symmetric (%d,%d,%d,%d) (%d vs. %d)\n", i, j, k, l, int11_37[i][j][k][l], int11_37[j][i][l][k]);
+
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      for (k=0; k<5; k++)
+        for (l=0; l<5; l++)
+          if (int11_dH[i][j][k][l] != int11_dH[j][i][l][k])
+            fprintf(stderr, "WARNING: int11 enthalpies not symmetric\n");
+
+  /* interior 2x2 loops */
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      for (k=0; k<5; k++)
+        for (l=0; l<5; l++) {
+          int m,n;
+          for (m=0; m<5; m++)
+            for (n=0; n<5; n++)
+              if (int22_37[i][j][k][l][m][n] != int22_37[j][i][m][n][k][l])
+                fprintf(stderr, "WARNING: int22 energies not symmetric\n");
+        }
+
+  for (i=0; i<=NBPAIRS; i++)
+    for (j=0; j<=NBPAIRS; j++)
+      for (k=0; k<5; k++)
+        for (l=0; l<5; l++) {
+          int m,n;
+          for (m=0; m<5; m++)
+            for (n=0; n<5; n++)
+              if (int22_dH[i][j][k][l][m][n] != int22_dH[j][i][m][n][k][l])
+                fprintf(stderr, "WARNING: int22 enthalpies not symmetric: %d %d %d %d %d %d\n", i,j,k,l,m,n);
+        }
+}
+
+/* update nonstandard nucleotide/basepair involved contributions for int22 */
+PRIVATE void update_nst(int array[NBPAIRS+1][NBPAIRS+1][5][5][5][5]){
+  int    i, j, k, l, m, n;
+  int max, max2, max3, max4, max5, max6;
+
+  /* get maxima for one nonstandard nucleotide */
+  for (i=1; i<NBPAIRS; i++){
+    for (j=1; j<NBPAIRS; j++){
+      for (k=1; k<5; k++){
+        for (l=1; l<5; l++){
+          for (m=1; m<5; m++){
+            max = max2 = max3 = max4 = -INF; /* max of {CGAU} */
+            for(n=1;n<5;n++){
+              max   = MAX2(max,   array[i][j][k][l][m][n]);
+              max2  = MAX2(max2,  array[i][j][k][l][n][m]);
+              max3  = MAX2(max3,  array[i][j][k][n][l][m]);
+              max4  = MAX2(max4,  array[i][j][n][k][l][m]);
+            }
+            array[i][j][k][l][m][0] = max;
+            array[i][j][k][l][0][m] = max2;
+            array[i][j][k][0][l][m] = max3;
+            array[i][j][0][k][l][m] = max4;
+          }
+        }
+      }
+    }
+  }
+  /* get maxima for two nonstandard nucleotides */
+  for (i=1; i<NBPAIRS; i++){
+    for (j=1; j<NBPAIRS; j++){
+      for (k=1; k<5; k++){
+        for (l=1; l<5; l++){
+          max = max2 = max3 = max4 = max5 = max6 = -INF; /* max of {CGAU} */
+          for (m=1; m<5; m++){
+            max   = MAX2(max,   array[i][j][k][l][m][0]);
+            max2  = MAX2(max2,  array[i][j][k][m][0][l]);
+            max3  = MAX2(max3,  array[i][j][m][0][k][l]);
+            max4  = MAX2(max4,  array[i][j][0][k][l][m]);
+            max5  = MAX2(max5,  array[i][j][0][k][m][l]);
+            max6  = MAX2(max6,  array[i][j][k][0][l][m]);
+          }
+          array[i][j][k][l][0][0] = max;
+          array[i][j][k][0][0][l] = max2;
+          array[i][j][0][0][k][l] = max3;
+          array[i][j][k][0][l][0] = max6;
+          array[i][j][0][k][0][l] = max5;
+          array[i][j][0][k][l][0] = max4;
+        }
+      }
+    }
+  }
+  /* get maxima for three nonstandard nucleotides */
+  for (i=1; i<NBPAIRS; i++){
+    for (j=1; j<NBPAIRS; j++){
+      for (k=1; k<5; k++){
+        max = max2 = max3 = max4 = -INF; /* max of {CGAU} */
+        for (l=1; l<5; l++){
+          /* should be arbitrary where index l resides in last 3 possible locations */
+          max   = MAX2(max,   array[i][j][k][l][0][0]);
+          max2  = MAX2(max2,  array[i][j][0][k][l][0]);
+          max3  = MAX2(max3,  array[i][j][0][0][k][l]);
+          max4  = MAX2(max4,  array[i][j][0][0][l][k]);
+        }
+        array[i][j][k][0][0][0] = max;
+        array[i][j][0][k][0][0] = max2;
+        array[i][j][0][0][k][0] = max3;
+        array[i][j][0][0][0][k] = max4;
+      }
+    }
+  }
+  /* get maxima for 4 nonstandard nucleotides */
+  for (i=1; i<NBPAIRS; i++){
+    for (j=1; j<NBPAIRS; j++){
+      max = -INF; /* max of {CGAU} */
+      for (k=1; k<5; k++){
+        max   = MAX2(max,   array[i][j][k][0][0][0]);
+      }
+      array[i][j][0][0][0][0] = max;
+    }
+  }
+
+  /* now compute contributions for nonstandard base pairs ... */
+  /* first, 1 nonstandard bp */
+  for (i=1; i<NBPAIRS; i++){
+    for (k=0; k<5; k++){
+      for (l=0; l<5; l++){
+        for (m=0; m<5; m++){
+          for(n=0;n<5;n++){
+            max = max2 = -INF;
+            for(j=1;j<NBPAIRS;j++){
+              max   = MAX2(max, array[i][j][k][l][m][n]);
+              max2  = MAX2(max2, array[j][i][k][l][m][n]);
+            }
+            array[i][NBPAIRS][k][l][m][n] = max;
+            array[NBPAIRS][i][k][l][m][n] = max2;
+          }
+        }
+      }
+    }
+  }
+
+  /* now 2 nst base pairs */
+  for (k=0; k<5; k++){
+    for (l=0; l<5; l++){
+      for (m=0; m<5; m++){
+        for(n=0;n<5;n++){
+          max = -INF;
+          for(j=1;j<NBPAIRS;j++){
+            max   = MAX2(max, array[NBPAIRS][j][k][l][m][n]);
+          }
+          array[NBPAIRS][NBPAIRS][k][l][m][n] = max;
+        }
+      }
+    }
+  }
+
+}