WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / Progs / RNAcofold.c
diff --git a/binaries/src/ViennaRNA/Progs/RNAcofold.c b/binaries/src/ViennaRNA/Progs/RNAcofold.c
new file mode 100644 (file)
index 0000000..5d92d71
--- /dev/null
@@ -0,0 +1,683 @@
+/* Last changed Time-stamp: <2006-04-05 12:58:49 ivo> */
+/*
+                  c Ivo L Hofacker, Vienna RNA package
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+#include "PS_dot.h"
+#include "cofold.h"
+#include "fold.h"
+#include "part_func_co.h"
+#include "part_func.h"
+#include "fold_vars.h"
+#include "utils.h"
+#include "read_epars.h"
+#include "params.h"
+#include "RNAcofold_cmdl.h"
+
+/*@unused@*/
+PRIVATE char rcsid[] = "$Id: RNAcofold.c,v 1.7 2006/05/10 15:14:27 ivo Exp $";
+
+PRIVATE char *costring(char *string);
+PRIVATE char *tokenize(char *line);
+PRIVATE cofoldF do_partfunc(char *string, int length, int Switch, struct plist **tpr, struct plist **mf, pf_paramT *parameters);
+PRIVATE double *read_concentrations(FILE *fp);
+PRIVATE void do_concentrations(double FEAB, double FEAA, double FEBB, double FEA, double FEB, double *startconces);
+
+PRIVATE double bppmThreshold;
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  struct        RNAcofold_args_info args_info;
+  unsigned int  input_type;
+  char          *string, *input_string;
+  char    *structure, *cstruc, *rec_sequence, *orig_sequence, *rec_id, **rec_rest;
+  char    fname[FILENAME_MAX_LENGTH], ffname[FILENAME_MAX_LENGTH];
+  char    *ParamFile;
+  char    *ns_bases, *c;
+  char    *Concfile;
+  int     i, length, l, sym, r, cl;
+  double  min_en;
+  double  kT, sfact, betaScale;
+  int     pf, istty;
+  int     noconv, noPS;
+  int     doT;    /*compute dimere free energies etc.*/
+  int     doC;    /*toggle to compute concentrations*/
+  int     doQ;    /*toggle to compute prob of base being paired*/
+  int     cofi;   /*toggle concentrations stdin / file*/
+  plist   *prAB;
+  plist   *prAA;   /*pair probabilities of AA dimer*/
+  plist   *prBB;
+  plist   *prA;
+  plist   *prB;
+  plist   *mfAB;
+  plist   *mfAA;   /*pair mfobabilities of AA dimer*/
+  plist   *mfBB;
+  plist   *mfA;
+  plist   *mfB;
+  double  *ConcAandB;
+  unsigned int    rec_type, read_opt;
+  pf_paramT       *pf_parameters;
+  model_detailsT  md;
+
+
+  /*
+  #############################################
+  # init variables and parameter options
+  #############################################
+  */
+  dangles       = 2;
+  sfact         = 1.07;
+  bppmThreshold = 1e-5;
+  noconv        = 0;
+  noPS          = 0;
+  do_backtrack  = 1;
+  pf            = 0;
+  doT           = 0;
+  doC           = 0;
+  doQ           = 0;
+  cofi          = 0;
+  betaScale     = 1.;
+  gquad         = 0;
+  ParamFile     = NULL;
+  pf_parameters = NULL;
+  string        = NULL;
+  Concfile      = NULL;
+  structure     = NULL;
+  cstruc        = NULL;
+  ns_bases      = NULL;
+  rec_type      = read_opt = 0;
+  rec_id        = rec_sequence = orig_sequence = NULL;
+  rec_rest      = NULL;
+
+  set_model_details(&md);
+  /*
+  #############################################
+  # check the command line prameters
+  #############################################
+  */
+  if(RNAcofold_cmdline_parser (argc, argv, &args_info) != 0) exit(1);
+  /* temperature */
+  if(args_info.temp_given)            temperature = args_info.temp_arg;
+  /* structure constraint */
+  if(args_info.constraint_given)      fold_constrained=1;
+  /* do not take special tetra loop energies into account */
+  if(args_info.noTetra_given)         md.special_hp = tetra_loop=0;
+  /* set dangle model */
+  if(args_info.dangles_given){
+    if((args_info.dangles_arg < 0) || (args_info.dangles_arg > 3))
+      warn_user("required dangle model not implemented, falling back to default dangles=2");
+    else
+     md.dangles = dangles = args_info.dangles_arg;
+  }
+  /* do not allow weak pairs */
+  if(args_info.noLP_given)            md.noLP = noLonelyPairs = 1;
+  /* do not allow wobble pairs (GU) */
+  if(args_info.noGU_given)            md.noGU = noGU = 1;
+  /* do not allow weak closing pairs (AU,GU) */
+  if(args_info.noClosingGU_given)     md.noGUclosure = no_closingGU = 1;
+  /* gquadruplex support */
+  if(args_info.gquad_given)           md.gquad = gquad = 1;
+  /* do not convert DNA nucleotide "T" to appropriate RNA "U" */
+  if(args_info.noconv_given)          noconv = 1;
+  /* set energy model */
+  if(args_info.energyModel_given)     energy_set = args_info.energyModel_arg;
+  /*  */
+  if(args_info.noPS_given)            noPS = 1;
+  /* take another energy parameter set */
+  if(args_info.paramFile_given)       ParamFile = strdup(args_info.paramFile_arg);
+  /* Allow other pairs in addition to the usual AU,GC,and GU pairs */
+  if(args_info.nsp_given)             ns_bases = strdup(args_info.nsp_arg);
+  /* set pf scaling factor */
+  if(args_info.pfScale_given)         sfact = args_info.pfScale_arg;
+
+  if(args_info.all_pf_given)          doT = pf = 1;
+  /* concentrations from stdin */
+  if(args_info.concentrations_given)  doC = doT = pf = 1;
+  /* set the bppm threshold for the dotplot */
+  if(args_info.bppmThreshold_given)
+    bppmThreshold = MIN2(1., MAX2(0.,args_info.bppmThreshold_arg));
+  /* concentrations in file */
+  if(args_info.betaScale_given)       betaScale = args_info.betaScale_arg;
+  if(args_info.concfile_given){
+    Concfile = strdup(args_info.concfile_arg);
+    doC = cofi = doT = pf = 1;
+  }
+  /* partition function settings */
+  if(args_info.partfunc_given){
+    pf = 1;
+    if(args_info.partfunc_arg != -1)
+      do_backtrack = args_info.partfunc_arg;
+  }
+  /* free allocated memory of command line data structure */
+  RNAcofold_cmdline_parser_free (&args_info);
+
+
+  /*
+  #############################################
+  # begin initializing
+  #############################################
+  */
+  if(pf && gquad){
+    nrerror("G-Quadruplex support is currently not available for partition function computations");
+  }
+
+  if (ParamFile != NULL)
+    read_parameter_file(ParamFile);
+
+  if (ns_bases != NULL) {
+    nonstandards = space(33);
+    c=ns_bases;
+    i=sym=0;
+    if (*c=='-') {
+      sym=1; c++;
+    }
+    while (*c!='\0') {
+      if (*c!=',') {
+        nonstandards[i++]=*c++;
+        nonstandards[i++]=*c;
+        if ((sym)&&(*c!=*(c-1))) {
+          nonstandards[i++]=*c;
+          nonstandards[i++]=*(c-1);
+        }
+      }
+      c++;
+    }
+  }
+  istty = isatty(fileno(stdout))&&isatty(fileno(stdin));
+
+  /* print user help if we get input from tty */
+  if(istty){
+    printf("Use '&' to connect 2 sequences that shall form a complex.\n");
+    if(fold_constrained){
+      print_tty_constraint(VRNA_CONSTRAINT_DOT | VRNA_CONSTRAINT_X | VRNA_CONSTRAINT_ANG_BRACK | VRNA_CONSTRAINT_RND_BRACK);
+      print_tty_input_seq_str("Input sequence (upper or lower case) followed by structure constraint\n");
+    }
+    else print_tty_input_seq();
+  }
+
+  /* set options we wanna pass to read_record */
+  if(istty)             read_opt |= VRNA_INPUT_NOSKIP_BLANK_LINES;
+  if(!fold_constrained) read_opt |= VRNA_INPUT_NO_REST;
+
+  /*
+  #############################################
+  # main loop: continue until end of file
+  #############################################
+  */
+  while(
+    !((rec_type = read_record(&rec_id, &rec_sequence, &rec_rest, read_opt))
+        & (VRNA_INPUT_ERROR | VRNA_INPUT_QUIT))){
+
+    /*
+    ########################################################
+    # init everything according to the data we've read
+    ########################################################
+    */
+    if(rec_id){
+      if(!istty) printf("%s\n", rec_id);
+      (void) sscanf(rec_id, ">%" XSTR(FILENAME_ID_LENGTH) "s", fname);
+    }
+    else fname[0] = '\0';
+
+    cut_point = -1;
+
+    rec_sequence  = tokenize(rec_sequence); /* frees input_string and sets cut_point */
+    length    = (int) strlen(rec_sequence);
+    structure = (char *) space((unsigned) length+1);
+
+    /* parse the rest of the current dataset to obtain a structure constraint */
+    if(fold_constrained){
+      cstruc = NULL;
+      int cp = cut_point;
+      unsigned int coptions = (rec_id) ? VRNA_CONSTRAINT_MULTILINE : 0;
+      coptions |= VRNA_CONSTRAINT_DOT | VRNA_CONSTRAINT_X | VRNA_CONSTRAINT_ANG_BRACK | VRNA_CONSTRAINT_RND_BRACK;
+      getConstraint(&cstruc, (const char **)rec_rest, coptions);
+      cstruc = tokenize(cstruc);
+      if(cut_point != cp) nrerror("cut point in sequence and structure constraint differs");
+      cl = (cstruc) ? (int)strlen(cstruc) : 0;
+
+      if(cl == 0)           warn_user("structure constraint is missing");
+      else if(cl < length)  warn_user("structure constraint is shorter than sequence");
+      else if(cl > length)  nrerror("structure constraint is too long");
+
+      if(cstruc) strncpy(structure, cstruc, sizeof(char)*(cl+1));
+    }
+
+    /* convert DNA alphabet to RNA if not explicitely switched off */
+    if(!noconv) str_DNA2RNA(rec_sequence);
+    /* store case-unmodified sequence */
+    orig_sequence = strdup(rec_sequence);
+    /* convert sequence to uppercase letters only */
+    str_uppercase(rec_sequence);
+
+    if(istty){
+      if (cut_point == -1)
+        printf("length = %d\n", length);
+      else
+        printf("length1 = %d\nlength2 = %d\n", cut_point-1, length-cut_point+1);
+    }
+
+    /*
+    ########################################################
+    # begin actual computations
+    ########################################################
+    */
+
+    if (doC) {
+      FILE *fp;
+      if (cofi) { /* read from file */
+        fp = fopen(Concfile, "r");
+        if (fp==NULL) {
+          fprintf(stderr, "could not open concentration file %s", Concfile);
+          nrerror("\n");
+        }
+        ConcAandB = read_concentrations(fp);
+        fclose(fp);
+      } else {
+        printf("Please enter concentrations [mol/l]\n format: ConcA ConcB\n return to end\n");
+        ConcAandB = read_concentrations(stdin);
+      }
+    }
+    /*compute mfe of AB dimer*/
+    min_en = cofold(rec_sequence, structure);
+    assign_plist_from_db(&mfAB, structure, 0.95);
+
+    {
+      char *pstring, *pstruct;
+      if (cut_point == -1) {
+        pstring = strdup(orig_sequence);
+        pstruct = strdup(structure);
+      } else {
+        pstring = costring(orig_sequence);
+        pstruct = costring(structure);
+      }
+      printf("%s\n%s", pstring, pstruct);
+      if (istty)
+        printf("\n minimum free energy = %6.2f kcal/mol\n", min_en);
+      else
+        printf(" (%6.2f)\n", min_en);
+
+      (void) fflush(stdout);
+
+      if (!noPS) {
+        char annot[512] = "";
+        if (fname[0]!='\0') {
+          strcpy(ffname, fname);
+          strcat(ffname, "_ss.ps");
+        } else {
+          strcpy(ffname, "rna.ps");
+        }
+        if (cut_point >= 0)
+          sprintf(annot,
+                  "1 %d 9  0 0.9 0.2 omark\n%d %d 9  1 0.1 0.2 omark\n",
+                  cut_point-1, cut_point+1, length+1);
+        if(gquad){
+          if (!noPS) (void) PS_rna_plot_a_gquad(pstring, pstruct, ffname, annot, NULL);
+        } else {
+          if (!noPS) (void) PS_rna_plot_a(pstring, pstruct, ffname, annot, NULL);
+        }
+      }
+      free(pstring);
+      free(pstruct);
+    }
+
+    if (length>2000)  free_co_arrays();
+
+    /*compute partition function*/
+    if (pf) {
+      cofoldF AB, AA, BB;
+      FLT_OR_DBL *probs;
+      if (dangles==1) {
+        dangles=2;   /* recompute with dangles as in pf_fold() */
+        min_en = energy_of_structure(rec_sequence, structure, 0);
+        dangles=1;
+      }
+
+      kT = (betaScale*((temperature+K0)*GASCONST))/1000.; /* in Kcal */
+      pf_scale = exp(-(sfact*min_en)/kT/length);
+      if (length>2000) fprintf(stderr, "scaling factor %f\n", pf_scale);
+
+      pf_parameters = get_boltzmann_factors(temperature, betaScale, md, pf_scale);
+
+      if (cstruc!=NULL)
+        strncpy(structure, cstruc, length+1);
+      AB = co_pf_fold_par(rec_sequence, structure, pf_parameters, do_backtrack, fold_constrained);
+
+      if (do_backtrack) {
+        char *costruc;
+        costruc = (char *) space(sizeof(char)*(strlen(structure)+2));
+        if (cut_point<0) printf("%s", structure);
+        else {
+          strncpy(costruc, structure, cut_point-1);
+          strcat(costruc, "&");
+          strcat(costruc, structure+cut_point-1);
+          printf("%s", costruc);
+        }
+        if (!istty) printf(" [%6.2f]\n", AB.FAB);
+        else printf("\n");/*8.6.04*/
+      }
+      if ((istty)||(!do_backtrack))
+        printf(" free energy of ensemble = %6.2f kcal/mol\n", AB.FAB);
+      printf(" frequency of mfe structure in ensemble %g",
+             exp((AB.FAB-min_en)/kT));
+
+      printf(" , delta G binding=%6.2f\n", AB.FcAB - AB.FA - AB.FB);
+
+      probs = export_co_bppm();
+      assign_plist_from_pr(&prAB, probs, length, bppmThreshold);
+
+      /* if (doQ) make_probsum(length,fname); */ /*compute prob of base paired*/
+      /* free_co_arrays(); */
+      if (doT) { /* cofold of all dimers, monomers */
+        int Blength, Alength;
+        char  *Astring, *Bstring, *orig_Astring, *orig_Bstring;
+        char *Newstring;
+        char Newname[30];
+        char comment[80];
+        if (cut_point<0) {
+          printf("Sorry, i cannot do that with only one molecule, please give me two or leave it\n");
+          free(mfAB);
+          free(prAB);
+          continue;
+        }
+        if (dangles==1) dangles=2;
+        Alength=cut_point-1;        /*length of first molecule*/
+        Blength=length-cut_point+1; /*length of 2nd molecule*/
+
+        Astring=(char *)space(sizeof(char)*(Alength+1));/*Sequence of first molecule*/
+        Bstring=(char *)space(sizeof(char)*(Blength+1));/*Sequence of second molecule*/
+        strncat(Astring,rec_sequence,Alength);
+        strncat(Bstring,rec_sequence+Alength,Blength);
+
+        orig_Astring=(char *)space(sizeof(char)*(Alength+1));/*Sequence of first molecule*/
+        orig_Bstring=(char *)space(sizeof(char)*(Blength+1));/*Sequence of second molecule*/
+        strncat(orig_Astring,orig_sequence,Alength);
+        strncat(orig_Bstring,orig_sequence+Alength,Blength);
+
+        /* compute AA dimer */
+        AA=do_partfunc(Astring, Alength, 2, &prAA, &mfAA, pf_parameters);
+        /* compute BB dimer */
+        BB=do_partfunc(Bstring, Blength, 2, &prBB, &mfBB, pf_parameters);
+        /*free_co_pf_arrays();*/
+
+        /* compute A monomer */
+        do_partfunc(Astring, Alength, 1, &prA, &mfA, pf_parameters);
+
+        /* compute B monomer */
+        do_partfunc(Bstring, Blength, 1, &prB, &mfB, pf_parameters);
+
+        compute_probabilities(AB.F0AB, AB.FA, AB.FB, prAB, prA, prB, Alength);
+        compute_probabilities(AA.F0AB, AA.FA, AA.FA, prAA, prA, prA, Alength);
+        compute_probabilities(BB.F0AB, BB.FA, BB.FA, prBB, prA, prB, Blength);
+        printf("Free Energies:\nAB\t\tAA\t\tBB\t\tA\t\tB\n%.6f\t%6f\t%6f\t%6f\t%6f\n",
+               AB.FcAB, AA.FcAB, BB.FcAB, AB.FA, AB.FB);
+
+        if (doC) {
+          do_concentrations(AB.FcAB, AA.FcAB, BB.FcAB, AB.FA, AB.FB, ConcAandB);
+          free(ConcAandB);/*freeen*/
+        }
+
+        if (fname[0]!='\0') {
+          strcpy(ffname, fname);
+          strcat(ffname, "_dp5.ps");
+        } else strcpy(ffname, "dot5.ps");
+        /*output of the 5 dot plots*/
+
+        /*AB dot_plot*/
+        /*write Free Energy into comment*/
+        sprintf(comment,"\n%%Heterodimer AB FreeEnergy= %.9f\n", AB.FcAB);
+        /*reset cut_point*/
+        cut_point=Alength+1;
+        /*write New name*/
+        strcpy(Newname,"AB");
+        strcat(Newname,ffname);
+        (void)PS_dot_plot_list(orig_sequence, Newname, prAB, mfAB, comment);
+
+        /*AA dot_plot*/
+        sprintf(comment,"\n%%Homodimer AA FreeEnergy= %.9f\n",AA.FcAB);
+        /*write New name*/
+        strcpy(Newname,"AA");
+        strcat(Newname,ffname);
+        /*write AA sequence*/
+        Newstring=(char*)space((2*Alength+1)*sizeof(char));
+        strcpy(Newstring,orig_Astring);
+        strcat(Newstring,orig_Astring);
+        (void)PS_dot_plot_list(Newstring, Newname, prAA, mfAA, comment);
+        free(Newstring);
+
+        /*BB dot_plot*/
+        sprintf(comment,"\n%%Homodimer BB FreeEnergy= %.9f\n",BB.FcAB);
+        /*write New name*/
+        strcpy(Newname,"BB");
+        strcat(Newname,ffname);
+        /*write BB sequence*/
+        Newstring=(char*)space((2*Blength+1)*sizeof(char));
+        strcpy(Newstring,orig_Bstring);
+        strcat(Newstring,orig_Bstring);
+        /*reset cut_point*/
+        cut_point=Blength+1;
+        (void)PS_dot_plot_list(Newstring, Newname, prBB, mfBB, comment);
+        free(Newstring);
+
+        /*A dot plot*/
+        /*reset cut_point*/
+        cut_point=-1;
+        sprintf(comment,"\n%%Monomer A FreeEnergy= %.9f\n",AB.FA);
+        /*write New name*/
+        strcpy(Newname,"A");
+        strcat(Newname,ffname);
+        /*write BB sequence*/
+        (void)PS_dot_plot_list(orig_Astring, Newname, prA, mfA, comment);
+
+        /*B monomer dot plot*/
+        sprintf(comment,"\n%%Monomer B FreeEnergy= %.9f\n",AB.FB);
+        /*write New name*/
+        strcpy(Newname,"B");
+        strcat(Newname,ffname);
+        /*write BB sequence*/
+        (void)PS_dot_plot_list(orig_Bstring, Newname, prB, mfB, comment);
+        free(Astring); free(Bstring); free(orig_Astring); free(orig_Bstring);
+        free(prAB); free(prAA); free(prBB); free(prA); free(prB);
+        free(mfAB); free(mfAA); free(mfBB); free(mfA); free(mfB);
+
+      } /*end if(doT)*/
+
+      free(pf_parameters);
+    }/*end if(pf)*/
+
+
+    if (do_backtrack) {
+      if (fname[0]!='\0') {
+        strcpy(ffname, fname);
+        strcat(ffname, "_dp.ps");
+      } else strcpy(ffname, "dot.ps");
+
+      if (!doT) {
+        if (pf) {          (void) PS_dot_plot_list(rec_sequence, ffname, prAB, mfAB, "doof");
+        free(prAB);}
+        free(mfAB);
+      }
+    }
+    if (!doT) free_co_pf_arrays();
+
+    (void) fflush(stdout);
+    
+    /* clean up */
+    if(cstruc) free(cstruc);
+    if(rec_id) free(rec_id);
+    free(rec_sequence);
+    free(orig_sequence);
+    free(structure);
+    /* free the rest of current dataset */
+    if(rec_rest){
+      for(i=0;rec_rest[i];i++) free(rec_rest[i]);
+      free(rec_rest);
+    }
+    rec_id = rec_sequence = orig_sequence = structure = cstruc = NULL;
+    rec_rest = NULL;
+
+    /* print user help for the next round if we get input from tty */
+    if(istty){
+      printf("Use '&' to connect 2 sequences that shall form a complex.\n");
+      if(fold_constrained){
+        print_tty_constraint(VRNA_CONSTRAINT_DOT | VRNA_CONSTRAINT_X | VRNA_CONSTRAINT_ANG_BRACK | VRNA_CONSTRAINT_RND_BRACK);
+        print_tty_input_seq_str("Input sequence (upper or lower case) followed by structure constraint\n");
+      }
+      else print_tty_input_seq();
+    }
+  }
+  return EXIT_SUCCESS;
+}
+
+PRIVATE char *tokenize(char *line)
+{
+  char *pos, *copy;
+  int cut = -1;
+
+  copy = (char *) space(strlen(line)+1);
+  (void) sscanf(line, "%s", copy);
+  pos = strchr(copy, '&');
+  if (pos) {
+    cut = (int) (pos-copy)+1;
+    if (cut >= strlen(copy)) cut = -1;
+    if (strchr(pos+1, '&')) nrerror("more than one cut-point in input");
+    for (;*pos;pos++) *pos = *(pos+1); /* splice out the & */
+  }
+  if (cut > -1) {
+    if (cut_point==-1) cut_point = cut;
+    else if (cut_point != cut) {
+      fprintf(stderr,"cut_point = %d cut = %d\n", cut_point, cut);
+      nrerror("Sequence and Structure have different cut points.");
+    }
+  }
+  free(line);
+  return copy;
+}
+
+PRIVATE char *costring(char *string)
+{
+  char *ctmp;
+  int len;
+
+  len = strlen(string);
+  ctmp = (char *)space((len+2) * sizeof(char));
+  /* first sequence */
+  (void) strncpy(ctmp, string, cut_point-1);
+  /* spacer */
+  ctmp[cut_point-1] = '&';
+  /* second sequence */
+  (void) strcat(ctmp, string+cut_point-1);
+
+  return ctmp;
+}
+
+PRIVATE cofoldF do_partfunc(char *string, int length, int Switch, struct plist **tpr, struct plist **mfpl, pf_paramT *parameters){
+  /*compute mfe and partition function of dimere or  monomer*/
+  char *Newstring;
+  char *tempstruc;
+  double min_en;
+  double sfact=1.07;
+  double kT;
+  pf_paramT *par;
+  FLT_OR_DBL *probs;
+  cofoldF X;
+  kT = parameters->kT/1000.;
+  switch (Switch)
+    {
+    case 1: /*monomer*/
+      cut_point=-1;
+      tempstruc = (char *) space((unsigned)length+1);
+      min_en = fold(string, tempstruc);
+      assign_plist_from_db(mfpl, tempstruc, 0.95);
+      free_arrays();
+      /*En=pf_fold(string, tempstruc);*/
+      /* init_co_pf_fold(length); <- obsolete */
+      par = get_boltzmann_factor_copy(parameters);
+      par->pf_scale = exp(-(sfact*min_en)/kT/(length));
+      X=co_pf_fold_par(string, tempstruc, par, 1, fold_constrained);
+      probs = export_co_bppm();
+      assign_plist_from_pr(tpr, probs, length, bppmThreshold);
+      free_co_pf_arrays();
+      free(tempstruc);
+      free(par);
+      break;
+
+    case 2: /*dimer*/
+      Newstring=(char *)space(sizeof(char)*(length*2+1));
+      strcat(Newstring,string);
+      strcat(Newstring,string);
+      cut_point=length+1;
+      tempstruc = (char *) space((unsigned)length*2+1);
+      min_en = cofold(Newstring, tempstruc);
+      assign_plist_from_db(mfpl, tempstruc, 0.95);
+      free_co_arrays();
+      /* init_co_pf_fold(2*length); <- obsolete */
+      par = get_boltzmann_factor_copy(parameters);
+      par->pf_scale =exp(-(sfact*min_en)/kT/(2*length));
+      X=co_pf_fold_par(Newstring, tempstruc, par, 1, fold_constrained);
+      probs = export_co_bppm();
+      assign_plist_from_pr(tpr, probs, 2*length, bppmThreshold);
+      free_co_pf_arrays();
+      free(Newstring);
+      free(tempstruc);
+      free(par);
+      break;
+
+    default:
+      printf("Error in get_partfunc\n, computing neither mono- nor dimere!\n");
+      exit (42);
+
+    }
+  return X;
+}
+
+
+PRIVATE void do_concentrations(double FEAB, double FEAA, double FEBB, double FEA, double FEB, double *startconc) {
+  /* compute and print concentrations out of free energies, calls get_concentrations */
+  struct ConcEnt *result;
+  int i, n;
+
+  result=get_concentrations(FEAB, FEAA, FEBB, FEA, FEB, startconc);
+
+  printf("Initial concentrations\t\trelative Equilibrium concentrations\n");
+  printf("A\t\t B\t\t AB\t\t AA\t\t BB\t\t A\t\t B\n");
+  for (n=0; (startconc[2*n]>0) || (startconc[2*n+1]>0); n++); /* count */
+  for (i=0; i<n ;i++) {
+    double tot = result[i].A0+result[i].B0;
+    printf("%-10g\t%-10g\t%.5f \t%.5f \t%.5f \t%.5f \t%.5f\n", result[i].A0, result[i].B0,
+           result[i].ABc/tot, result[i].AAc/tot, result[i].BBc/tot ,result[i].Ac/tot, result[i].Bc/tot);
+  }
+  free(result);
+}
+
+
+PRIVATE double *read_concentrations(FILE *fp) {
+  /* reads concentrations, returns list of double, -1. marks end */
+  char *line;
+  double *startc;
+  int i=0, n=2;
+
+  startc = (double *) space((2*n+1)*sizeof(double));
+
+  while ((line=get_line(fp))!=NULL) {
+    int c;
+    if (i+4>=2*n) {
+      n*=2;
+      startc=(double *)xrealloc(startc,(2*n+1)*sizeof(double));
+    }
+    c = sscanf(line,"%lf %lf", &startc[i], &startc[i+1]);
+    free(line);
+    if (c<2) break;
+    i+=2;
+  }
+  startc[i]=startc[i+1]=0;
+  return startc;
+}