source: tags/initial/GDE/PHYLIP/dnapars.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.0 KB
Line 
1#include "phylip.h"
2
3/* version 3.56c. (c) Copyright 1993 by Joseph Felsenstein.
4   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
5   Permission is granted to copy and use this program provided no fee is
6   charged for it and provided that this copyright notice is not removed. */
7
8#define nmlngth         10   /* number of characters in species name    */
9#define maxtrees        100   /* maximum number of tied trees stored     */
10#define maxuser         8   /* maximum number of user-defined trees */
11#define ibmpc0          false
12#define ansi0           true
13#define vt520           false
14#define down            2
15
16static char basechar[32]="ACMGRSVTWYHKDBNO???????????????";
17typedef short *steptr;
18typedef short *stepshortptr;
19typedef enum {
20  A, C, G, U, O
21} bases;
22typedef short *baseptr;
23/* nodes will form a binary tree */
24
25typedef struct node {           /* describes a tip species or an ancestor */
26  struct node *next, *back;     /* pointers to nodes                      */
27  short index;                   /* number of the node                     */
28  boolean tip, bottom;          /* present species are tips of tree       */
29  baseptr base;                 /* the sequence                           */
30  stepshortptr numsteps;        /* bookkeeps steps                        */
31  short xcoord, ycoord, ymin;    /* used by printree                       */
32  short ymax;
33} node;
34
35typedef node **pointptr;
36typedef short longer[6];
37typedef char **sequence;
38
39
40
41typedef struct gbases {
42  baseptr base;
43  struct gbases *next;
44} gbases;
45
46
47Static node *root, *p;
48Static FILE *infile, *outfile, *treefile;
49Static short spp, nonodes, chars, endsite, outgrno, col, datasets, ith,
50            i, j, l, jumb, njumble, inseed;
51/* spp = number of species
52   nonodes = number of nodes in tree
53   chars = number of sites in actual sequences
54   outgrno indicates outgroup */
55Static boolean jumble, usertree, weights, thresh, trout, outgropt,
56               printdata, progress, treeprint, stepbox, ancseq, mulsets,
57               interleaved, ibmpc, vt52, ansi, firstset;
58Static steptr weight, oldweight, alias, ally, location;
59Static pointptr treenode;            /* pointers to all nodes in tree */
60Static Char **nayme;                 /* names of species              */
61Static sequence y;
62Static gbases *garbage;
63Static double threshold;
64Static longer seed;
65Static short *enterorder;
66
67/* local variables for Pascal maketree, propagated globally for C  version: */
68
69short nextree, which, minwhich;
70double like, minsteps, bestyet, bestlike, bstlike2;
71boolean lastrearr, recompute;
72double nsteps[maxuser];
73short **fsteps;
74node *there;
75short *place;
76short **bestrees;
77long *threshwt;
78baseptr nothing;
79node *temp, *temp1;
80Char ch;
81boolean *names;
82
83
84openfile(fp,filename,mode,application,perm)
85FILE **fp;
86char *filename;
87char *mode;
88char *application;
89char *perm;
90{
91  FILE *of;
92  char file[100];
93  strcpy(file,filename);
94  while (1){
95    of = fopen(file,mode);
96    if (of)
97      break;
98    else {
99      switch (*mode){
100      case 'r':
101        printf("%s:  can't read %s\n",application,file);
102        file[0] = '\0';
103        while (file[0] =='\0'){
104          printf("Please enter a new filename>");
105          gets(file);}
106        break;
107      case 'w':
108      case 'a':
109        printf("%s: can't write %s\n",application,file);
110        file[0] = '\0';
111        while (file[0] =='\0'){
112          printf("Please enter a new filename>");
113          gets(file);}
114        break;
115      }
116    }
117  }
118  *fp=of;
119  if (perm != NULL)
120    strcpy(perm,file);
121}
122
123
124Static Void gnu(p)
125gbases **p;
126{
127  /* this and the following are do-it-yourself garbage collectors.
128     Make a new node or pull one off the garbage list */
129  if (garbage != NULL) {
130    *p = garbage;
131    garbage = garbage->next;
132  } else {
133    *p = (gbases *)Malloc(sizeof(gbases));
134    (*p)->base = (baseptr)Malloc(endsite*sizeof(short));
135  }
136  (*p)->next = NULL;
137}  /* gnu */
138
139
140void chuck(p)
141gbases *p;
142{
143  /* collect garbage on p -- put it on front of garbage list */
144  p->next = garbage;
145  garbage = p;
146}  /* chuck */
147
148
149double randum(seed)
150short *seed;
151{
152  /* random number generator -- slow but machine independent */
153  short i, j, k, sum;
154  longer mult, newseed;
155  double x;
156
157  mult[0] = 13;
158  mult[1] = 24;
159  mult[2] = 22;
160  mult[3] = 6;
161  for (i = 0; i <= 5; i++)
162    newseed[i] = 0;
163  for (i = 0; i <= 5; i++) {
164    sum = newseed[i];
165    k = i;
166    if (i > 3)
167      k = 3;
168    for (j = 0; j <= k; j++)
169      sum += mult[j] * seed[i - j];
170    newseed[i] = sum;
171    for (j = i; j <= 4; j++) {
172      newseed[j + 1] += newseed[j] / 64;
173      newseed[j] &= 63;
174    }
175  }
176  memcpy(seed, newseed, sizeof(longer));
177  seed[5] &= 3;
178  x = 0.0;
179  for (i = 0; i <= 5; i++)
180    x = x / 64.0 + seed[i];
181  x /= 4.0;
182  return x;
183}  /* randum */
184
185
186
187Static Void uppercase(ch)
188Char *ch;
189{
190  /* convert ch to upper case -- either ASCII or EBCDIC */
191  *ch = (islower (*ch) ? toupper(*ch) : (*ch));
192}  /* uppercase */
193
194
195Local Void getoptions()
196{
197  /* interactively set options */
198  short i, inseed0;
199  Char ch;
200  boolean done1;
201
202  fprintf(outfile, "\nDNA parsimony algorithm, version %s\n\n",VERSION);
203  jumble = false;
204  njumble = 1;
205  outgrno = 1;
206  outgropt = false;
207  thresh = false;
208  trout = true;
209  usertree = false;
210  weights = false;
211  printdata = false;
212  progress = true;
213  treeprint = true;
214  stepbox = false;
215  ancseq = false;
216  interleaved = true;
217  for (;;) {
218    printf(ansi ? "\033[2J\033[H" :
219           vt52 ? "\033E\033H"    : "\n");
220    printf("\nDNA parsimony algorithm, version %s\n\n",VERSION);
221    printf("Setting for this run:\n");
222    printf("  U                 Search for best tree?  %s\n",
223           (usertree ? "No, use user trees in input file" : "Yes"));
224    if (!usertree) {
225      printf("  J   Randomize input order of sequences?");
226      if (jumble)
227        printf("  Yes (seed =%8hd,%3hd times)\n", inseed0, njumble);
228      else
229        printf("  No. Use input order\n");
230    }
231    printf("  O                        Outgroup root?");
232    if (outgropt)
233      printf("  Yes, at sequence number%3hd\n", outgrno);
234    else
235      printf("  No, use as outgroup species%3hd\n", outgrno);
236    printf("  T              Use Threshold parsimony?");
237    if (thresh)
238      printf("  Yes, count steps up to%4.1f per site\n", threshold);
239    else
240      printf("  No, use ordinary parsimony\n");
241    printf("  M           Analyze multiple data sets?");
242    if (mulsets)
243      printf("  Yes, %2hd sets\n", datasets);
244    else
245      printf("  No\n");
246    printf("  I          Input sequences interleaved?  %s\n",
247           (interleaved ? "Yes" : "No, sequential"));
248    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
249           ibmpc ? "IBM PC" :
250           ansi  ? "ANSI"   :
251           vt52  ? "VT52"    : "(none)");
252    printf("  1    Print out the data at start of run  %s\n",
253           (printdata ? "Yes" : "No"));
254    printf("  2  Print indications of progress of run  %s\n",
255           progress ? "Yes" : "No");
256    printf("  3                        Print out tree  %s\n",
257           treeprint ? "Yes" : "No");
258    printf("  4          Print out steps in each site  %s\n",
259           stepbox ? "Yes" : "No");
260    printf("  5  Print sequences at all nodes of tree  %s\n",
261           ancseq ? "Yes" : "No");
262    printf("  6       Write out trees onto tree file?  %s\n",
263           trout ? "Yes" : "No");
264    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
265    scanf("%c%*[^\n]", &ch);
266    getchar();
267    if (ch == '\n')
268      ch = ' ';
269    uppercase(&ch);
270    if (ch == 'Y')
271      break;
272    if (strchr("JOTUMI1234560",ch) != NULL){
273      switch (ch) {
274       
275      case 'J':
276        jumble = !jumble;
277        if (jumble) {
278          printf("Random number seed (must be odd)?\n");
279          scanf("%hd%*[^\n]", &inseed);
280          getchar();
281          inseed0 = inseed;
282          for (i = 0; i <= 5; i++)
283            seed[i] = 0;
284          i = 0;
285          do {
286            seed[i] = inseed & 63;
287            inseed /= 64;
288            i++;
289          } while (inseed != 0);
290          printf("Number of times to jumble?\n");
291          scanf("%hd%*[^\n]", &njumble);
292          getchar();
293        }
294        else njumble = 1;
295        break;
296       
297      case 'O':
298        outgropt = !outgropt;
299        if (outgropt) {
300          done1 = true;
301          do {
302            printf("Type number of the outgroup:\n");
303            scanf("%hd%*[^\n]", &outgrno);
304              getchar();
305            done1 = (outgrno >= 1 && outgrno <= spp);
306            if (!done1) {
307              printf("BAD OUTGROUP NUMBER: %4hd\n", outgrno);
308              printf("  Must be in range 1 -%2hd\n", spp);
309            }
310          } while (done1 != true);
311        }
312        break;
313       
314      case 'T':
315        thresh = !thresh;
316        if (thresh) {
317          done1 = false;
318          do {
319            printf("What will be the threshold value?\n");
320            scanf("%lf%*[^\n]", &threshold);
321              getchar();
322            done1 = (threshold >= 1.0);
323            if (!done1)
324              printf("BAD THRESHOLD VALUE:  it must be greater than 1\n");
325            else
326              threshold = (short)(threshold * 10.0 + 0.5) / 10.0;
327          } while (done1 != true);
328        }
329        break;
330       
331      case 'M':
332        mulsets = !mulsets;
333        if (mulsets) {
334          done1 = false;
335          do {
336            printf("How many data sets?\n");
337            scanf("%hd%*[^\n]", &datasets);
338            getchar();
339            done1 = (datasets >= 1);
340            if (!done1)
341              printf("BAD DATA SETS NUMBER:  it must be greater than 1\n");
342          } while (done1 != true);
343        }
344        break;
345       
346      case 'U':
347        usertree = !usertree;
348        break;
349       
350      case 'I':
351        interleaved = !interleaved;
352        break;
353       
354      case '0':
355        if (ibmpc) {
356          ibmpc = false;
357          vt52 = true;
358        } else {
359          if (vt52) {
360            vt52 = false;
361            ansi = true;
362            } else if (ansi)
363              ansi = false;
364            else
365              ibmpc = true;
366        }
367        break;
368       
369      case '1':
370        printdata = !printdata;
371        break;
372       
373      case '2':
374        progress = !progress;
375        break;
376       
377      case '3':
378        treeprint = !treeprint;
379        break;
380       
381      case '4':
382        stepbox = !stepbox;
383        break;
384       
385      case '5':
386        ancseq = !ancseq;
387        break;
388       
389      case '6':
390        trout = !trout;
391        break;
392      }
393    } else
394      printf("Not a possible option!\n");
395  }
396}  /* getoptions */
397
398Local Void inputnumbers()
399{
400  /* input the numbers of species and of characters */
401  fscanf(infile, "%hd%hd", &spp, &chars);
402  if (printdata)
403    fprintf(outfile, "%2hd species, %3hd  sites\n", spp, chars);
404  if (printdata)
405    putc('\n', outfile);
406  nonodes = spp * 2 - 1;
407}  /* inputnumbers */
408
409Static Void doinit()
410{
411  /* initializes variables */
412  short i;
413  node *p, *q;
414
415  inputnumbers();
416  getoptions();
417  y = (Char **)Malloc(spp*sizeof(Char *));
418  for (i = 0; i < spp; i++)
419    y[i] = (Char *)Malloc(chars*sizeof(Char));
420  treenode = (pointptr)Malloc(nonodes*sizeof(node *));
421  for (i = 0; i < nonodes; i++)
422    treenode[i] = (node *)Malloc(sizeof(node));
423  for (i = spp; i < nonodes; i++) {
424    q = NULL;
425    for (j = 1; j <= 3; j++) {
426      p = (node *)Malloc(sizeof(node));
427      p->next = q;
428      q = p;
429    }
430    p->next->next->next = p;
431    treenode[i] = p;
432  }
433}  /* doinit*/
434
435Local Void inputweights()
436{
437  /* input the character weights, 0-9 and A-Z for weights 0 - 35 */
438  Char ch;
439  short i;
440
441  for (i = 1; i < nmlngth; i++) {
442    ch = getc(infile);
443    if (ch == '\n')
444      ch = ' ';
445  }
446  for (i = 0; i < chars; i++) {
447    do {
448      if (eoln(infile)) {
449        fscanf(infile, "%*[^\n]");
450        getc(infile);
451      }
452      ch = getc(infile);
453      if (ch == '\n')
454        ch = ' ';
455    } while (ch == ' ');
456    weight[i] = 1;
457    if (isdigit(ch))
458      weight[i] = ch - '0';
459    else if (isalpha(ch)) {
460      uppercase(&ch);
461      if (ch >= 'A' && ch <= 'I')
462        weight[i] = ch - 55;
463      else if (ch >= 'J' && ch <= 'R')
464        weight[i] = ch - 55;
465      else
466        weight[i] = ch - 55;
467    } else {
468      printf("BAD WEIGHT CHARACTER: %c\n", ch);
469      exit(-1);
470    }
471  }
472  fscanf(infile, "%*[^\n]");
473  getc(infile);
474  weights = true;
475}  /* inputweights */
476
477Local Void printweights()
478{
479  /* print out the weights of sites */
480  short i, j, k;
481
482  fprintf(outfile, "    Sites are weighted as follows:\n");
483  fprintf(outfile, "        ");
484  for (i = 0; i <= 9; i++)
485    fprintf(outfile, "%3hd", i);
486  fprintf(outfile, "\n     *---------------------------------\n");
487  for (j = 0; j <= (chars / 10); j++) {
488    fprintf(outfile, "%5hd!  ", j * 10);
489    for (i = 0; i <= 9; i++) {
490      k = j * 10 + i;
491      if (k > 0 && k <= chars)
492        fprintf(outfile, "%3hd", weight[k - 1]);
493      else
494        fprintf(outfile, "   ");
495    }
496    putc('\n', outfile);
497  }
498  putc('\n', outfile);
499}  /* printweights */
500
501Local Void inputoptions()
502{
503  /* input the information on the options */
504  Char ch;
505  short extranum, i, cursp, curchs;
506
507  if (!firstset) {
508    if (eoln(infile)) {
509      fscanf(infile, "%*[^\n]");
510      getc(infile);
511    }
512    fscanf(infile, "%hd%hd", &cursp, &curchs);
513    if (cursp != spp) {
514      printf("\nERROR: INCONSISTENT NUMBER OF SPECIES IN DATA SET %4hd\n",
515             ith);
516      exit(-1);
517    }
518    chars = curchs;
519  }
520  extranum = 0;
521  while (!(eoln(infile))) {
522    ch = getc(infile);
523    if (ch == '\n')
524      ch = ' ';
525    uppercase(&ch);
526    if (ch == 'W')
527      extranum++;
528    else if (ch != ' ') {
529      printf("BAD OPTION CHARACTER: %c\n", ch);
530      exit(-1);
531    }
532  }
533  fscanf(infile, "%*[^\n]");
534  getc(infile);
535  for (i = 0; i < chars; i++)
536    weight[i] = 1;
537  for (i = 1; i <= extranum; i++) {
538    ch = getc(infile);
539    if (ch == '\n')
540      ch = ' ';
541      uppercase(&ch);
542    if (ch == 'W')
543      inputweights();
544    else {
545      printf("ERROR: INCORRECT AUXILIARY OPTIONS LINE WHICH STARTS WITH %c\n",
546             ch);
547      exit(-1);}
548  }
549  if (weights)
550    printweights();
551}  /* inputoptions */
552
553Local Void inputdata()
554{
555  /* input the names and sequences for each species */
556  short i, j, k, l, basesread, basesnew;
557  Char charstate;
558  boolean allread, done;
559
560  if (progress)
561    putchar('\n');
562  j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5;
563  if (j < nmlngth - 1)
564    j = nmlngth - 1;
565  if (j > 37)
566    j = 37;
567  if (printdata) {
568    fprintf(outfile, "Name");
569    for (i = 1; i <= j; i++)
570      putc(' ', outfile);
571    fprintf(outfile, "Sequences\n");
572    fprintf(outfile, "----");
573    for (i = 1; i <= j; i++)
574      putc(' ', outfile);
575    fprintf(outfile, "---------\n\n");
576  }
577  basesread = 0;
578  allread = false;
579  while (!(allread)) {
580    allread = true;
581    if (eoln(infile)) {
582      fscanf(infile, "%*[^\n]");
583      getc(infile);
584    }
585    i = 1;
586    while (i <= spp) {
587      if ((interleaved && basesread == 0) || !interleaved) {
588        for (j = 0; j < nmlngth; j++) {
589          nayme[i - 1][j] = getc(infile);
590          if ( eof(infile) | eoln(infile)){
591            printf("ERROR: END-OF-LINE OR END-OF-FILE");
592            printf(" IN THE MIDDLE OF A SPECIES NAME\n");
593            exit(-1);}
594        }
595      }
596      if (interleaved)
597        j = basesread;
598      else
599        j = 0;
600      done = false;
601      while (((!done) & (!eof(infile)))) {
602        if (interleaved)
603          done = true;
604        while (((j < chars) & (!(eoln(infile) | eof(infile))))) {
605          charstate = getc(infile);
606          if (charstate == '\n')
607            charstate = ' ';
608          if (charstate == ' ' || (charstate >= '0' && charstate <= '9'))
609            continue;
610          uppercase(&charstate);
611          if ((strchr("ABCDGHKMNRSTUVWXY?O-.",charstate)) == NULL){
612            printf("ERROR: BAD BASE:%c AT POSITION%5hd OF SPECIES %3hd\n",
613                   charstate, j, i);
614            exit(-1);
615          }
616          j++;
617          if (charstate == '.')
618            charstate = y[0][j - 1];
619          y[i - 1][j - 1] = charstate;
620        }
621        if (interleaved)
622          continue;
623        if (j < chars) {
624          fscanf(infile, "%*[^\n]");
625          getc(infile);
626        } else if (j == chars)
627          done = true;
628      }
629      if (interleaved && i == 1)
630        basesnew = j;
631      fscanf(infile, "%*[^\n]");
632      getc(infile);
633      if ((interleaved && j != basesnew) || ((!interleaved) && j != chars)){
634        printf("ERROR: SEQUENCES OUT OF ALIGNMENT\n");
635        exit(-1);}
636      i++;
637    }
638    if (interleaved) {
639      basesread = basesnew;
640      allread = (basesread == chars);
641    } else
642      allread = (i > spp);
643  }
644  if (!printdata)
645    return;
646  for (i = 1; i <= ((chars - 1) / 60 + 1); i++) {
647    for (j = 1; j <= spp; j++) {
648      for (k = 0; k < nmlngth; k++)
649        putc(nayme[j - 1][k], outfile);
650      fprintf(outfile, "   ");
651      l = i * 60;
652      if (l > chars)
653        l = chars;
654      for (k = (i - 1) * 60 + 1; k <= l; k++) {
655        if (j > 1 && y[j - 1][k - 1] == y[0][k - 1])
656          charstate = '.';
657        else
658          charstate = y[j - 1][k - 1];
659        putc(charstate, outfile);
660        if (k % 10 == 0 && k % 60 != 0)
661          putc(' ', outfile);
662      }
663      putc('\n', outfile);
664    }
665    putc('\n', outfile);
666  }
667  putc('\n', outfile);
668}  /* inputdata */
669
670Local Void sitesort()
671{
672  /* Shell sort keeping sites, weights in same order */
673  short gap, i, j, jj, jg, k, itemp;
674  boolean flip, tied;
675
676  gap = chars / 2;
677  while (gap > 0) {
678    for (i = gap + 1; i <= chars; i++) {
679      j = i - gap;
680      flip = true;
681      while (j > 0 && flip) {
682        jj = alias[j - 1];
683        jg = alias[j + gap - 1];
684        tied = true;
685        k = 1;
686        while (k <= spp && tied) {
687          flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]);
688          tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]);
689          k++;
690        }
691        if (!flip)
692          break;
693        itemp = alias[j - 1];
694        alias[j - 1] = alias[j + gap - 1];
695        alias[j + gap - 1] = itemp;
696        itemp = weight[j - 1];
697        weight[j - 1] = weight[j + gap - 1];
698        weight[j + gap - 1] = itemp;
699        j -= gap;
700      }
701    }
702    gap /= 2;
703  }
704}  /* sitesort */
705
706Local Void sitecombine()
707{
708  /* combine sites that have identical patterns */
709  short i, j, k;
710  boolean tied;
711
712  i = 1;
713  while (i < chars) {
714    j = i + 1;
715    tied = true;
716    while (j <= chars && tied) {
717      k = 1;
718      while (k <= spp && tied) {
719        tied = (tied &&
720            y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]);
721        k++;
722      }
723      if (tied) {
724        weight[i - 1] += weight[j - 1];
725        weight[j - 1] = 0;
726        ally[alias[j - 1] - 1] = alias[i - 1];
727      }
728      j++;
729    }
730    i = j - 1;
731  }
732}  /* sitecombine */
733
734Local Void sitescrunch()
735{
736  /* move so one representative of each pattern of
737     sites comes first */
738  short i, j, itemp;
739  boolean done, found;
740
741  done = false;
742  i = 1;
743  j = 2;
744  while (!done) {
745    if (ally[alias[i - 1] - 1] != alias[i - 1]) {
746      if (j <= i)
747        j = i + 1;
748      if (j <= chars) {
749        found = false;
750        do {
751          found = (ally[alias[j - 1] - 1] == alias[j - 1]);
752          j++;
753        } while (!(found || j > chars));
754        if (found) {
755          j--;
756          itemp = alias[i - 1];
757          alias[i - 1] = alias[j - 1];
758          alias[j - 1] = itemp;
759          itemp = weight[i - 1];
760          weight[i - 1] = weight[j - 1];
761          weight[j - 1] = itemp;
762        } else
763          done = true;
764      } else
765        done = true;
766    }
767    i++;
768    done = (done || i >= chars);
769  }
770}  /* sitescrunch */
771
772Local Void makeweights()
773{
774  /* make up weights vector to avoid duplicate computations */
775  short i;
776
777  for (i = 1; i <= chars; i++) {
778    alias[i - 1] = i;
779    oldweight[i - 1] = weight[i - 1];
780    ally[i - 1] = i;
781  }
782  sitesort();
783  sitecombine();
784  sitescrunch();
785  endsite = 0;
786  for (i = 1; i <= chars; i++) {
787    if (ally[i - 1] == i)
788      endsite++;
789  }
790  for (i = 1; i <= endsite; i++)
791    location[alias[i - 1] - 1] = i;
792  if (!thresh)
793    threshold = spp;
794  threshwt = (long *)Malloc(endsite*sizeof(long));
795  for (i = 0; i < endsite; i++) {
796    weight[i] *= 10;
797    threshwt[i] = (long)(threshold * weight[i] + 0.5);
798  }
799}  /* makeweights */
800
801Local Void makevalues()
802{
803  /* set up fractional likelihoods at tips */
804  short i, j;
805  short ns;
806  node *p;
807
808  for (i = 1; i <= nonodes; i++) {
809    treenode[i-1]->back = NULL;
810    treenode[i-1]->tip = (i <= spp);
811    treenode[i-1]->index = i;
812    if (i > spp) {
813      p = treenode[i-1]->next;
814      while (p != treenode[i-1]) {
815        p->back = NULL;
816        p->tip = false;
817        p->index = i;
818        p = p->next;
819      }
820    }
821  }
822  for (i = 0; i < nonodes; i++) {
823    treenode[i]->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
824    treenode[i]->base = (baseptr)Malloc(endsite*sizeof(short));
825  }
826  for (i = spp; i < nonodes; i++) {
827    p = treenode[i];
828    for (j = 1; j <= 3; j++) {
829      p->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
830      p->base = (baseptr)Malloc(endsite*sizeof(short));
831      p = p->next;
832    }
833  }
834  for (j = 0; j < endsite; j++) {
835    for (i = 0; i < spp; i++) {
836      switch (y[i][alias[j] - 1]) {
837
838      case 'A':
839        ns = (short)(1 << A);
840        break;
841
842      case 'C':
843        ns = (short)(1 << C);
844        break;
845
846      case 'G':
847        ns = (short)(1 << G);
848        break;
849
850      case 'U':
851        ns = (short)(1 << U);
852        break;
853
854      case 'T':
855        ns = (short)(1 << U);
856        break;
857
858      case 'M':
859        ns = ((short)(1 << A)) | ((short)(1 << C));
860        break;
861
862      case 'R':
863        ns = ((short)(1 << A)) | ((short)(1 << G));
864        break;
865
866      case 'W':
867        ns = ((short)(1 << A)) | ((short)(1 << U));
868        break;
869
870      case 'S':
871        ns = ((short)(1 << C)) | ((short)(1 << G));
872        break;
873
874      case 'Y':
875        ns = ((short)(1 << C)) | ((short)(1 << U));
876        break;
877
878      case 'K':
879        ns = ((short)(1 << G)) | ((short)(1 << U));
880        break;
881
882      case 'B':
883        ns = ((short)(1 << C)) | ((short)(1 << G)) | ((short)(1 << U));
884        break;
885
886      case 'D':
887        ns = ((short)(1 << A)) | ((short)(1 << G)) | ((short)(1 << U));
888        break;
889
890      case 'H':
891        ns = ((short)(1 << A)) | ((short)(1 << C)) | ((short)(1 << U));
892        break;
893
894      case 'V':
895        ns = ((short)(1 << A)) | ((short)(1 << C)) | ((short)(1 << G));
896        break;
897
898      case 'N':
899        ns = ((short)(1 << A)) | ((short)(1 << C)) | ((short)(1 << G)) |
900             ((short)(1 << U));
901        break;
902
903      case 'X':
904        ns = ((short)(1 << A)) | ((short)(1 << C)) | ((short)(1 << G)) |
905             ((short)(1 << U));
906        break;
907
908      case '?':
909        ns = ((short)(1 << A)) | ((short)(1 << C)) | ((short)(1 << G)) |
910             ((short)(1 << U)) | (short)(1 << O);
911        break;
912
913      case 'O':
914        ns = (short)(1 << O);
915        break;
916
917      case '-':
918        ns = (short)(1 << O);
919        break;
920      }
921      treenode[i]->base[j] = ns;
922      treenode[i]->numsteps[j] = 0;
923    }
924  }
925}  /* makevalues */
926
927
928Static Void doinput()
929{
930  /* reads the input data */
931  inputoptions();
932  inputdata();
933  makeweights();
934  makevalues();
935}  /* doinput */
936
937
938Local Void fillin(p, left, rt)
939node *p, *left, *rt;
940{
941  /* sets up for each node in the tree the base sequence
942     at that point and counts the changes.  The program
943     spends much of its time in this PROCEDURE */
944  int i;
945  int ns, rs, ls;
946  if (!left){
947      for (i = endsite-1;i>=0;i--){
948          p->numsteps[i] = rt->numsteps[i];
949          p->base[i] = rt->base[i];
950      }
951      return;
952  }
953  if (!rt){
954      for (i = endsite-1;i>=0;i--){
955          p->numsteps[i] = left->numsteps[i];
956          p->base[i] = left->base[i];
957      }
958      return;
959  }
960  {
961      short *b_l, *b_r;
962      short *nsl,*nsr;
963      b_l = left->base;
964      b_r = rt->base;
965      nsl = left->numsteps;
966      nsr = rt->numsteps;
967      for (i = 0; i <endsite;i++) {
968          ls = *(b_l++);
969          rs = *(b_r++);
970          ns = ls & rs;
971         
972          if (ns == 0) {
973              p->base[i] = ls | rs;
974              p->numsteps[i] = *(nsl++) + *(nsr++) + weight[i];
975          }else{
976              p->base[i] = ns;
977              p->numsteps[i] = *(nsl++) + *(nsr++);
978          }
979      }
980  }
981}
982  /* fillin */
983
984Local Void preorder(p)
985node *p;
986{
987  /* recompute number of steps in preorder taking both ancestoral and
988     descendent steps into account */
989
990  if (p && !p->tip) {
991    fillin (p->next, p->next->next->back, p->back);
992    fillin (p->next->next, p->back, p->next->back);
993    preorder (p->next->back);
994    preorder (p->next->next->back);
995  }
996} /* preorder */
997
998Local Void add(below, newtip, newfork)
999node *below, *newtip, *newfork;
1000{
1001  /* inserts the nodes newfork and its left descendant, newtip,
1002     to the tree.  below becomes newfork's right descendant */
1003
1004  if (below != treenode[below->index - 1])
1005    below = treenode[below->index - 1];
1006  if (below->back != NULL)
1007    below->back->back = newfork;
1008  newfork->back = below->back;
1009  below->back = newfork->next->next;
1010  newfork->next->next->back = below;
1011  newfork->next->back = newtip;
1012  newtip->back = newfork->next;
1013  if (root == below)
1014    root = newfork;
1015  root->back = NULL;
1016  if (!recompute)
1017    return;
1018  fillin(newfork, newfork->next->back, newfork->next->next->back);
1019  preorder(newfork);
1020  if (newfork != root)
1021    preorder(newfork->back);
1022}  /* add */
1023
1024Local Void re_move(item, fork)
1025node **item, **fork;
1026{
1027  /* removes nodes item and its ancestor, fork, from the tree.
1028     the new descendant of fork's ancestor is made to be
1029     fork's second descendant (other than item).  Also
1030     returns pointers to the deleted nodes, item and fork */
1031  node *p, *q, *other;
1032
1033  if ((*item)->back == NULL) {
1034    *fork = NULL;
1035    return;
1036  }
1037  *fork = treenode[(*item)->back->index - 1];
1038  if (*item == (*fork)->next->back)
1039    other = (*fork)->next->next->back;
1040  else
1041    other = (*fork)->next->back;
1042  if (root == *fork)
1043    root = other;
1044  p = (*item)->back->next->back;
1045  q = (*item)->back->next->next->back;
1046  if (p != NULL)
1047    p->back = q;
1048  if (q != NULL)
1049    q->back = p;
1050  (*fork)->back = NULL;
1051  p = (*fork)->next;
1052  while (p != *fork) {
1053    p->back = NULL;
1054    p = p->next;
1055    (*item)->back = NULL;
1056  }
1057  if (!recompute)
1058    return;
1059  preorder(other);
1060  if (other != root)
1061    preorder(other->back);
1062}  /* remove */
1063
1064Local Void evaluate(r)
1065node *r;
1066{
1067  /* determines the number of steps needed for a tree. this is
1068     the minimum number of steps needed to evolve sequences on
1069     this tree */
1070  short i, steps;
1071  long term;
1072  double sum;
1073
1074  sum = 0.0;
1075  for (i = 0; i < endsite; i++) {
1076    steps = r->numsteps[i];
1077    if ((long)steps <= threshwt[i])
1078      term = steps;
1079    else
1080      term = threshwt[i];
1081    sum += term;
1082    if (usertree && which <= maxuser)
1083      fsteps[which - 1][i] = term;
1084  }
1085  if (usertree && which <= maxuser) {
1086    nsteps[which - 1] = sum;
1087    if (which == 1) {
1088      minwhich = 1;
1089      minsteps = sum;
1090    } else if (sum < minsteps) {
1091      minwhich = which;
1092      minsteps = sum;
1093    }
1094  }
1095  like = -sum;
1096}  /* evaluate */
1097
1098Local Void postorder(p)
1099node *p;
1100{
1101  /* traverses a binary tree, calling PROCEDURE fillin at a
1102     node's descendants before calling fillin at the node */
1103  if (p->tip)
1104    return;
1105  postorder(p->next->back);
1106  postorder(p->next->next->back);
1107  fillin(p, p->next->back, p->next->next->back);
1108}  /* postorder */
1109
1110Local Void reroot(outgroup)
1111node *outgroup;
1112{
1113  /* reorients tree, putting outgroup in desired position. */
1114  node *p, *q;
1115
1116  if (outgroup->back->index == root->index)
1117    return;
1118  p = root->next;
1119  q = root->next->next;
1120  p->back->back = q->back;
1121  q->back->back = p->back;
1122  p->back = outgroup;
1123  q->back = outgroup->back;
1124  outgroup->back->back = root->next->next;
1125  outgroup->back = root->next;
1126}  /* reroot */
1127
1128Local Void savetraverse(p)
1129node *p;
1130{
1131  /* sets BOOLEANs that indicate which way is down */
1132  p->bottom = true;
1133  if (p->tip)
1134    return;
1135  p->next->bottom = false;
1136  savetraverse(p->next->back);
1137  p->next->next->bottom = false;
1138  savetraverse(p->next->next->back);
1139}  /* savetraverse */
1140
1141Local Void savetree()
1142{
1143  /* record in place where each species has to be
1144     added to reconstruct this tree */
1145  short i, j;
1146  node *p;
1147  boolean done;
1148
1149  reroot(treenode[outgrno - 1]);
1150  savetraverse(root);
1151  for (i = 0; i < nonodes; i++)
1152    place[i] = 0;
1153  place[root->index - 1] = 1;
1154  for (i = 1; i <= spp; i++) {
1155    p = treenode[i - 1];
1156    while (place[p->index - 1] == 0) {
1157      place[p->index - 1] = i;
1158      while (!p->bottom)
1159        p = p->next;
1160      p = p->back;
1161    }
1162    if (i > 1) {
1163      place[i - 1] = place[p->index - 1];
1164      j = place[p->index - 1];
1165      done = false;
1166      while (!done) {
1167        place[p->index - 1] = spp + i - 1;
1168        while (!p->bottom)
1169          p = p->next;
1170        p = p->back;
1171        done = (p == NULL);
1172        if (!done)
1173          done = (place[p->index - 1] != j);
1174      }
1175    }
1176  }
1177}  /* savetree */
1178
1179Local Void findtree(found,pos)
1180boolean *found;
1181short *pos;
1182{
1183  /* finds tree given by ARRAY place in ARRAY
1184     bestrees by binary search */
1185  short i, lower, upper;
1186  boolean below, done;
1187
1188  below = false;
1189  lower = 1;
1190  upper = nextree - 1;
1191  (*found) = false;
1192  while (!(*found) && lower <= upper) {
1193    (*pos) = (lower + upper) / 2;
1194    i = 3;
1195    done = false;
1196    while (!done) {
1197      done = (i > spp);
1198      if (!done)
1199        done = (place[i - 1] != bestrees[(*pos) - 1][i - 1]);
1200      if (!done)
1201        i++;
1202    }
1203    (*found) = (i > spp);
1204    below = (place[i - 1] <  bestrees[(*pos )- 1][i - 1]);
1205    if (*found)
1206      break;
1207    if (below)
1208      upper = (*pos) - 1;
1209    else
1210      lower = (*pos) + 1;
1211  }
1212  if (!(*found) && !below)
1213    (*pos)++;
1214}  /* findtree */
1215
1216Local Void addtree(pos)
1217short pos;
1218{
1219  /* puts tree from ARRAY place in its proper position
1220     in ARRAY bestrees */
1221  short i;
1222
1223  for (i = nextree - 1; i >= pos; i--)
1224    memcpy(bestrees[i], bestrees[i - 1], nonodes * sizeof(short));
1225  for (i = 0; i < spp; i++)
1226    bestrees[pos - 1][i] = place[i];
1227  nextree++;
1228}  /* addtree */
1229
1230Local Void tryadd(p, item,nufork)
1231node *p,**item,**nufork;
1232{
1233  /* temporarily adds one fork and one tip to the tree.
1234     if the location where they are added yields greater
1235     "likelihood" than other locations tested up to that
1236     time, then keeps that location as there */
1237  short pos;
1238  boolean found;
1239  node *rute, *q;
1240
1241  if (p == root)
1242    fillin(temp, *item, p);
1243  else {
1244    fillin(temp1, *item, p);
1245    fillin(temp, temp1, p->back);
1246  }
1247  evaluate(temp);
1248  if (lastrearr) {
1249    if (like < bestlike) {
1250      if ((*item) == (*nufork)->next->next->back) {
1251        q = (*nufork)->next;
1252        (*nufork)->next = (*nufork)->next->next;
1253        (*nufork)->next->next = q;
1254        q->next = (*nufork);
1255      }
1256    } else if (like >= bstlike2) {
1257      recompute = false;
1258      add(p, *item,*nufork);
1259      rute = root->next->back;
1260      savetree();
1261      reroot(rute);
1262      if (like > bstlike2) {
1263        bestlike = bstlike2 = like;
1264        pos = 1;
1265        nextree = 1;
1266        addtree(pos);
1267      } else {
1268        pos = 0;
1269        findtree(&found,&pos);
1270        if (!found) {
1271          if (nextree <= maxtrees)
1272            addtree(pos);
1273        }
1274      }
1275      re_move(item, nufork);
1276      recompute = true;
1277    }
1278  }
1279  if (like > bestyet) {
1280    bestyet = like;
1281    there = p;
1282  }
1283}  /* tryadd */
1284
1285Local Void addpreorder(p, item, nufork)
1286node *p, *item, *nufork;
1287{
1288  /* traverses a binary tree, calling PROCEDURE tryadd
1289     at a node before calling tryadd at its descendants */
1290
1291  if (p == NULL)
1292    return;
1293  tryadd(p, &item,&nufork);
1294  if (!p->tip) {
1295    addpreorder(p->next->back, item, nufork);
1296    addpreorder(p->next->next->back, item, nufork);
1297  }
1298}  /* addpreorder */
1299
1300
1301
1302Local Void tryrearr(p, success)
1303node *p;
1304boolean *success;
1305
1306{
1307  /* evaluates one rearrangement of the tree.
1308     if the new tree has greater "likelihood" than the old
1309     one sets success = TRUE and keeps the new tree.
1310     otherwise, restores the old tree */
1311  node *frombelow, *whereto, *forknode, *q;
1312  double oldlike;
1313
1314  if (p->back == NULL)
1315    return;
1316  forknode = treenode[p->back->index - 1];
1317  if (forknode->back == NULL)
1318    return;
1319  oldlike = bestyet;
1320  if (p->back->next->next == forknode)
1321    frombelow = forknode->next->next->back;
1322  else
1323    frombelow = forknode->next->back;
1324  whereto = treenode[forknode->back->index - 1];
1325  if (whereto->next->back == forknode)
1326    q = whereto->next->next->back;
1327  else
1328    q = whereto->next->back;
1329  fillin(temp1, frombelow, q);
1330  fillin(temp, temp1, p);
1331  fillin(temp1, temp, whereto->back);
1332  evaluate(temp1);
1333  if (like <= oldlike) {
1334    if (p != forknode->next->next->back)
1335      return;
1336    q = forknode->next;
1337    forknode->next = forknode->next->next;
1338    forknode->next->next = q;
1339    q->next = forknode;
1340    return;
1341  }
1342  recompute = false;
1343  re_move(&p, &forknode);
1344  fillin(whereto, whereto->next->back, whereto->next->next->back);
1345  recompute = true;
1346  add(whereto, p, forknode);
1347  (*success) = true;
1348  bestyet = like;
1349}  /* tryrearr */
1350
1351Local Void repreorder(p, success)
1352node *p;
1353boolean *success;
1354{
1355  /* traverses a binary tree, calling PROCEDURE tryrearr
1356     at a node before calling tryrearr at its descendants */
1357  if (p == NULL)
1358    return;
1359  tryrearr(p, success);
1360  if (!p->tip) {
1361    repreorder(p->next->back,success);
1362    repreorder(p->next->next->back,success);
1363  }
1364}  /* repreorder */
1365
1366Local Void rearrange(r)
1367node **r;
1368{
1369  /* traverses the tree (preorder), finding any local
1370     rearrangement which decreases the number of steps.
1371     if traversal succeeds in increasing the tree's
1372     "likelihood", PROCEDURE rearrange runs traversal again */
1373  boolean success=true;
1374
1375  while (success) {
1376    success = false;
1377    repreorder(*r, &success);
1378  }
1379}  /* rearrange */
1380
1381
1382Local Void findch(c)
1383Char c;
1384{
1385  /* scan forward until find character c */
1386  boolean done;
1387
1388  done = false;
1389  while (!(done)) {
1390    if (c == ',') {
1391      if (ch == '(' || ch == ')' || ch == ';') {
1392        printf("\nERROR IN USER TREE%3hd: UNMATCHED PARENTHESIS OR MISSING COMMA\n",  which);
1393        exit(-1);
1394      } else if (ch == ',')
1395        done = true;
1396    } else if (c == ')') {
1397      if (ch == '(' || ch == ',' || ch == ';') {
1398        printf("\nERROR IN USER TREE%3hd: ",which);
1399        printf("UNMATCHED PARENTHESIS OR NON-BIFURCATED NODE\n");
1400        exit(-1);
1401      } else {
1402        if (ch == ')')
1403          done = true;
1404      }
1405    } else if (c == ';') {
1406      if (ch != ';') {
1407        printf("\nERROR IN USER TREE%3hd: ",which);
1408        printf("UNMATCHED PARENTHESIS OR MISSING SEMICOLON\n");
1409        exit(-1);
1410      } else
1411        done = true;
1412    }
1413    if (ch != ')' && done)
1414      continue;
1415    if (eoln(infile)) {
1416      fscanf(infile, "%*[^\n]");
1417      getc(infile);
1418    }
1419    ch = getc(infile);
1420    if (ch == '\n')
1421      ch = ' ';
1422  }
1423}  /* findch */
1424
1425Local Void addelement(p,nextnode,lparens,names)
1426node **p;
1427short *nextnode,*lparens;
1428boolean *names;
1429
1430{
1431  /* recursive procedure adds nodes to user-defined tree */
1432  node *q;
1433  short i, n;
1434  boolean found;
1435  Char str[nmlngth];
1436
1437  do {
1438    if (eoln(infile)) {
1439      fscanf(infile, "%*[^\n]");
1440      getc(infile);
1441    }
1442    ch = getc(infile);
1443    if (ch == '\n')
1444      ch = ' ';
1445  } while (ch == ' ');
1446  if (ch == '(' ) {
1447    if ((*lparens) >= spp - 1) {
1448      printf("\nERROR IN USER TREE: TOO MANY LEFT PARENTHESES\n");
1449      exit(-1);
1450    }
1451    (*nextnode)++;
1452    (*lparens)++;
1453    q = treenode[(*nextnode) - 1];
1454    addelement(&q->next->back, nextnode,lparens,names);
1455    q->next->back->back = q->next;
1456    findch(',');
1457    addelement(&q->next->next->back,nextnode,lparens,names);
1458    q->next->next->back->back = q->next->next;
1459    findch(')');
1460    *p = q;
1461    return;
1462  }
1463  for (i = 0; i < nmlngth; i++)
1464    str[i] = ' ';
1465  n = 1;
1466  do {
1467    if (ch == '_')
1468      ch = ' ';
1469    str[n - 1] = ch;
1470    if (eoln(infile)) {
1471      fscanf(infile, "%*[^\n]");
1472      getc(infile);
1473    }
1474    ch = getc(infile);
1475    if (ch == '\n')
1476     ch = ' ';
1477    n++;
1478  } while (ch != ',' && ch != ')' && ch != ':' && n <= nmlngth);
1479  n = 1;
1480  do {
1481    found = true;
1482    for (i = 0; i < nmlngth; i++)
1483      found = (found && str[i] == nayme[n - 1][i]);
1484    if (found) {
1485      if (names[n - 1] == false) {
1486        *p = treenode[n - 1];
1487        names[n - 1] = true;
1488      } else {
1489        printf("\nERROR IN USER TREE: DUPLICATE NAME FOUND -- ");
1490        for (i = 0; i < nmlngth; i++)
1491          putchar(nayme[n - 1][i]);
1492        putchar('\n');
1493        exit(-1);
1494      }
1495    } else
1496      n++;
1497  } while (!(n > spp || found));
1498  if (n <= spp)
1499    return;
1500  printf("\nCannot find species: ");
1501  for (i = 0; i < nmlngth; i++)
1502    putchar(str[i]);
1503  putchar('\n');
1504}  /* addelement */
1505
1506Local Void treeread()
1507{
1508  /* read in user-defined tree and set it up */
1509  short i, nextnode,lparens;
1510
1511  root = treenode[spp];
1512  nextnode = spp;
1513  root->back = NULL;
1514  for (i = 0; i < spp; i++)
1515    names[i] = false;
1516  lparens = 0;
1517  addelement(&root, &nextnode,&lparens,names);
1518  findch(';');
1519  if (treeprint)
1520    fprintf(outfile, "\n\n");
1521  fscanf(infile, "%*[^\n]");
1522  getc(infile);
1523}  /* treeread */
1524
1525
1526Local Void coordinates(p,tipy)
1527node *p;
1528short *tipy;
1529{
1530  /* establishes coordinates of nodes */
1531  if (p->tip) {
1532    p->xcoord = 0;
1533    p->ycoord = (*tipy);
1534    p->ymin = (*tipy);
1535    p->ymax = (*tipy);
1536    (*tipy) += down;
1537    return;
1538  }
1539  coordinates(p->next->back, tipy);
1540  coordinates(p->next->next->back, tipy);
1541  p->xcoord = p->next->next->back->ymax - p->next->back->ymin;
1542  p->ycoord = (p->next->back->ycoord + p->next->next->back->ycoord) / 2;
1543  p->ymin = p->next->back->ymin;
1544  p->ymax = p->next->next->back->ymax;
1545}  /* coordinates */
1546
1547Local Void drawline(i, scale)
1548short i;
1549double scale;
1550{
1551  /* draws one row of the tree diagram by moving up tree */
1552  node *p, *q;
1553  short n, j;
1554  boolean extra, done;
1555
1556  p = root;
1557  q = root;
1558  extra = false;
1559  if (i == p->ycoord && p == root) {
1560    if (p->index - spp >= 10)
1561      fprintf(outfile, "-%2hd", p->index - spp);
1562    else
1563      fprintf(outfile, "--%hd", p->index - spp);
1564    extra = true;
1565  } else
1566    fprintf(outfile, "  ");
1567  do {
1568    if (!p->tip) {
1569      if (i >= p->next->back->ymin && i <= p->next->back->ymax)
1570        q = p->next->back;
1571      if (i >= p->next->next->back->ymin && i <= p->next->next->back->ymax)
1572        q = p->next->next->back;
1573    }
1574    done = (p == q);
1575    n = (short)(scale * (p->xcoord - q->xcoord) + 0.5);
1576    if (n < 3 && !q->tip)
1577      n = 3;
1578    if (extra) {
1579      n--;
1580      extra = false;
1581    }
1582    if (q->ycoord == i && !done) {
1583      putc('+', outfile);
1584      if (!q->tip) {
1585        for (j = 1; j <= n - 2; j++)
1586          putc('-', outfile);
1587        if (q->index - spp >= 10)
1588          fprintf(outfile, "%2hd", q->index - spp);
1589        else
1590          fprintf(outfile, "-%hd", q->index - spp);
1591        extra = true;
1592      } else {
1593        for (j = 1; j < n; j++)
1594          putc('-', outfile);
1595      }
1596    } else if (!p->tip) {
1597      if (p->next->next->back->ycoord > i && p->next->back->ycoord < i
1598            && i != p->ycoord) {
1599        putc('!', outfile);
1600        for (j = 1; j < n; j++)
1601          putc(' ', outfile);
1602      } else {
1603        for (j = 1; j <= n; j++)
1604          putc(' ', outfile);
1605      }
1606    } else {
1607      for (j = 1; j <= n; j++)
1608        putc(' ', outfile);
1609    }
1610    if (p != q)
1611      p = q;
1612  } while (!done);
1613  if (p->ycoord == i && p->tip) {
1614    for (j = 0; j < nmlngth; j++)
1615      putc(nayme[p->index - 1][j], outfile);
1616  }
1617  putc('\n', outfile);
1618}  /* drawline */
1619
1620Local Void printree()
1621{
1622  /* prints out diagram of the tree */
1623  short tipy;
1624  double scale;
1625  short i;
1626
1627  putc('\n', outfile);
1628  if (!treeprint)
1629    return;
1630  putc('\n', outfile);
1631  tipy = 1;
1632  coordinates(root, &tipy);
1633  scale = 1.5;
1634  putc('\n', outfile);
1635  for (i = 1; i <= (tipy - down); i++)
1636    drawline(i, scale);
1637  fprintf(outfile, "\n  remember:");
1638  if (outgropt)
1639    fprintf(outfile, " (although rooted by outgroup)");
1640  fprintf(outfile, " this is an unrooted tree!\n\n");
1641}  /* printree */
1642
1643
1644
1645/* Local variables for hypstates: */
1646struct LOC_hypstates {
1647  boolean bottom;
1648} ;
1649
1650Local Void ancestset(a, b, c)
1651short *a, *b, *c;
1652{
1653  /* make the set of ancestral states below nodes
1654     whose base sets are a and b */
1655  *c = (*a) & (*b);
1656  if (*c == 0)
1657    *c = (*a) | (*b);
1658}  /* ancestset */
1659
1660/* Local variables for hyptrav: */
1661struct LOC_hyptrav {
1662  node *r;
1663  short *hypset;
1664  boolean maybe, nonzero;
1665  short tempset, anc;
1666} ;
1667
1668Local Void hyprint(b1, b2, htrav,hyps)
1669short b1, b2;
1670struct LOC_hyptrav   *htrav; /* variables from hyptrav */
1671struct LOC_hypstates *hyps;  /* variables from hypstates */
1672{
1673  /* print out states in sites b1 through b2 at node */
1674  short i, j, k, n;
1675  boolean dot;
1676  bases b;
1677
1678  if (hyps->bottom) {
1679    if (!outgropt)
1680      fprintf(outfile, "       ");
1681    else
1682      fprintf(outfile, "root   ");
1683  } else
1684    fprintf(outfile, "%4hd   ", htrav->r->back->index - spp);
1685  if (htrav->r->tip) {
1686    for (i = 0; i < nmlngth; i++)
1687      putc(nayme[htrav->r->index - 1][i], outfile);
1688  } else
1689    fprintf(outfile, "%4hd      ", htrav->r->index - spp);
1690  if (hyps->bottom)
1691    fprintf(outfile, "          ");
1692  else if (htrav->nonzero)
1693    fprintf(outfile, "   yes    ");
1694  else if (htrav->maybe)
1695    fprintf(outfile, "  maybe   ");
1696  else
1697    fprintf(outfile, "   no     ");
1698  for (i = b1; i <= b2; i++) {
1699    j = location[ally[i - 1] - 1];
1700    htrav->tempset = htrav->r->base[j - 1];
1701    htrav->anc = htrav->hypset[j - 1];
1702    if (!hyps->bottom)
1703      htrav->anc = treenode[htrav->r->back->index - 1]->base[j - 1];
1704    dot = (htrav->tempset == htrav->anc && !hyps->bottom);
1705    if (dot)
1706      putc('.', outfile);
1707    else if (htrav->tempset == (short)(1 << A))
1708      putc('A', outfile);
1709    else if (htrav->tempset == (short)(1 << C))
1710      putc('C', outfile);
1711    else if (htrav->tempset == (short)(1 << G))
1712      putc('G', outfile);
1713    else if (htrav->tempset == (short)(1 << U))
1714      putc('T', outfile);
1715    else if (htrav->tempset == (short)(1 << O))
1716      putc('-', outfile);
1717    else {
1718      k = 1;
1719      n = 0;
1720      for (b = A; (short)b <= (short)O; b = (bases)((short)b + 1)) {
1721        if ((((short)(1 << b)) & htrav->tempset) != 0)
1722          n += k;
1723        k += k;
1724      }
1725      putc(basechar[n - 1], outfile);
1726    }
1727    if (i % 10 == 0)
1728      putc(' ', outfile);
1729  }
1730  putc('\n', outfile);
1731}  /* hyprint */
1732
1733
1734Local Void hyptrav(r_, hypset_, b1, b2, hyps)
1735node *r_;
1736short *hypset_;
1737short b1, b2;
1738struct LOC_hypstates *hyps;
1739{
1740  /*  compute, print out states at one interior node */
1741  struct LOC_hyptrav HyptravV;
1742  short i, j;
1743  short left, rt;
1744  gbases *temparray, *ancset;
1745
1746  HyptravV.r = r_;
1747  HyptravV.hypset = hypset_;
1748  gnu(&ancset);
1749  gnu(&temparray);
1750  HyptravV.maybe = false;
1751  HyptravV.nonzero = false;
1752  for (i = b1 - 1; i < b2; i++) {
1753    j = location[ally[i] - 1];
1754    HyptravV.anc = HyptravV.hypset[j - 1];
1755    if (!HyptravV.r->tip) {
1756      left = HyptravV.r->next->back->base[j - 1];
1757      rt = HyptravV.r->next->next->back->base[j - 1];
1758      HyptravV.tempset = left & rt & HyptravV.anc;
1759      if (HyptravV.tempset == 0) {
1760        HyptravV.tempset = (left & rt) | (left & HyptravV.anc) | (rt & HyptravV.anc);
1761        if (HyptravV.tempset == 0)
1762          HyptravV.tempset = left | rt | HyptravV.anc;
1763      }
1764      HyptravV.r->base[j - 1] = HyptravV.tempset;
1765    }
1766    if (!hyps->bottom)
1767      HyptravV.anc = treenode[HyptravV.r->back->index - 1]->base[j - 1];
1768    HyptravV.nonzero = (HyptravV.nonzero ||
1769                          (HyptravV.r->base[j - 1] & HyptravV.anc) == 0);
1770    HyptravV.maybe = (HyptravV.maybe || HyptravV.r->base[j - 1] != HyptravV.anc);
1771  }
1772  hyprint(b1, b2, &HyptravV,hyps);
1773  hyps->bottom = false;
1774  if (!HyptravV.r->tip) {
1775    memcpy(temparray->base, HyptravV.r->next->back->base, endsite*sizeof(short));
1776    for (i = b1 - 1; i < b2; i++) {
1777      j = location[ally[i] - 1];
1778      ancestset(&HyptravV.hypset[j-1],
1779                  &HyptravV.r->next->next->back->base[j-1],&ancset->base[j-1]);
1780    }
1781    hyptrav(HyptravV.r->next->back, ancset->base, b1, b2, hyps);
1782    for (i = b1 - 1; i < b2; i++) {
1783      j = location[ally[i] - 1];
1784      ancestset(&HyptravV.hypset[j-1], &temparray->base[j-1],&ancset->base[j-1]);
1785    }
1786    hyptrav(HyptravV.r->next->next->back, ancset->base, b1, b2, hyps);
1787  }
1788  chuck(temparray);
1789  chuck(ancset);
1790}  /* HyptravV */
1791
1792Local Void hypstates()
1793{
1794  /* fill in and describe states at interior nodes */
1795  struct LOC_hypstates Vars;
1796  short i, n;
1797
1798  fprintf(outfile, "\nFrom    To     Any Steps?    State at upper node\n");
1799  fprintf(outfile, "                            ");
1800  fprintf(outfile, " ( . means same as in the node below it on tree)\n\n");
1801  nothing = (baseptr)Malloc(endsite*sizeof(short));
1802  for (i = 0; i < endsite; i++)
1803    nothing[i] = 0;
1804  for (i = 1; i <= ((chars -1) / 40 + 1); i++) {
1805    putc('\n', outfile);
1806    Vars.bottom = true;
1807    n = i * 40;
1808    if (n > chars)
1809      n = chars;
1810    hyptrav(root, nothing, i * 40 - 39, n, &Vars);
1811  }
1812  free(nothing);
1813}  /* hypstates */
1814
1815Local Void treeout(p)
1816node *p;
1817{
1818  /* write out file with representation of final tree */
1819  short i, n;
1820  Char c;
1821
1822  if (p->tip) {
1823    n = 0;
1824    for (i = 1; i <= nmlngth; i++) {
1825      if (nayme[p->index - 1][i - 1] != ' ')
1826        n = i;
1827    }
1828    for (i = 0; i < n; i++) {
1829      c = nayme[p->index - 1][i];
1830      if (c == ' ')
1831        c = '_';
1832      putc(c, treefile);
1833    }
1834    col += n;
1835  } else {
1836    putc('(', treefile);
1837    col++;
1838    treeout(p->next->back);
1839    putc(',', treefile);
1840    col++;
1841    if (col > 65) {
1842      putc('\n', treefile);
1843      col = 0;
1844    }
1845    treeout(p->next->next->back);
1846    putc(')', treefile);
1847    col++;
1848  }
1849  if (p != root)
1850    return;
1851  if (nextree > 2)
1852    fprintf(treefile, "[%6.4f];\n", 1.0 / (nextree - 1));
1853  else
1854    fprintf(treefile, ";\n");
1855}  /* treeout */
1856
1857Local Void describe()
1858{
1859  /* prints ancestors, steps and table of numbers of steps in
1860     each site */
1861  short i, j, k, l;
1862
1863  if (treeprint)
1864    fprintf(outfile, "\nrequires a total of %10.3f\n", like / -10.0);
1865  if (stepbox) {
1866    putc('\n', outfile);
1867    if (weights)
1868      fprintf(outfile, " weighted");
1869    fprintf(outfile, " steps in each site:\n");
1870    fprintf(outfile, "      ");
1871    for (i = 0; i <= 9; i++)
1872      fprintf(outfile, "%4hd", i);
1873    fprintf(outfile, "\n     *------------------------------------");
1874    fprintf(outfile, "-----\n");
1875    for (i = 0; i <= (chars / 10); i++) {
1876      fprintf(outfile, "%5hd", i * 10);
1877      putc('!', outfile);
1878      for (j = 0; j <= 9; j++) {
1879        k = i * 10 + j;
1880        if (k == 0 || k > chars)
1881          fprintf(outfile, "    ");
1882        else {
1883          l = location[ally[k - 1] - 1];
1884          if (oldweight[k - 1] > 0)
1885            fprintf(outfile, "%4hd",
1886              oldweight[k - 1] * (root->numsteps[l - 1] / weight[l - 1]));
1887          else
1888            fprintf(outfile, "   0");
1889        }
1890      }
1891      putc('\n', outfile);
1892    }
1893  }
1894  if (ancseq) {
1895    hypstates();
1896    putc('\n', outfile);
1897  }
1898  putc('\n', outfile);
1899  if (trout) {
1900    col = 0;
1901    treeout(root);
1902  }
1903}  /* describe */
1904
1905
1906Static Void maketree()
1907{
1908  /* constructs a binary tree from the pointers in treenode.
1909     adds each node at location which yields highest "likelihood"
1910     then rearranges the tree for greatest "likelihood" */
1911  short i, j, k, numtrees, num;
1912  double gotlike, wt, sumw, sum, sum2, sd;
1913  node *item, *nufork, *dummy;
1914  double TEMP;
1915
1916  temp = (node *)Malloc(sizeof(node));
1917  temp->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
1918  temp->base = (baseptr)Malloc(endsite*sizeof(short));
1919  temp1 = (node *)Malloc(sizeof(node));
1920  temp1->numsteps = (stepshortptr)Malloc(endsite*sizeof(short));
1921  temp1->base = (baseptr)Malloc(endsite*sizeof(short));
1922  if (!usertree) {
1923    recompute = true;
1924    for (i = 1; i <= spp; i++)
1925      enterorder[i - 1] = i;
1926    if (jumble) {
1927      for (i = 0; i < spp; i++) {
1928        j = (short)(randum(seed) * spp) + 1;
1929        k = enterorder[j - 1];
1930        enterorder[j - 1] = enterorder[i];
1931        enterorder[i] = k;
1932      }
1933    }
1934    root = treenode[enterorder[0] - 1];
1935    add(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1],
1936        treenode[spp]);
1937    if (progress) {
1938      printf("Adding species:\n");
1939      printf("   ");
1940      for (i = 0; i < nmlngth; i++)
1941        putchar(nayme[enterorder[0] - 1][i]);
1942      printf("\n   ");
1943      for (i = 0; i < nmlngth; i++)
1944        putchar(nayme[enterorder[1] - 1][i]);
1945      putchar('\n');
1946    }
1947    lastrearr = false;
1948    for (i = 3; i <= spp; i++) {
1949      bestyet = -10.0 * spp * chars;
1950      item = treenode[enterorder[i - 1] - 1];
1951      nufork = treenode[spp + i - 2];
1952      there = root;
1953      addpreorder(root, item, nufork);
1954      add(there, item, nufork);
1955      like = bestyet;
1956      rearrange(&root);
1957      if (progress) {
1958        printf("   ");
1959        for (j = 0; j < nmlngth; j++)
1960          putchar(nayme[enterorder[i - 1] - 1][j]);
1961        putchar('\n');
1962      }
1963      lastrearr = (i == spp);
1964      if (lastrearr) {
1965        if (progress) {
1966          printf("\nDoing global rearrangements\n");
1967          printf("  !");
1968          for (j = 1; j <= nonodes; j++)
1969            putchar('-');
1970          printf("!\n");
1971        }
1972        bestlike = bestyet;
1973        if (jumb == 1) {
1974          bstlike2 = bestlike;
1975          nextree = 1;
1976        }
1977        do {
1978          if (progress)
1979            printf("   ");
1980          gotlike = bestlike;
1981          for (j = 0; j < nonodes; j++) {
1982            there = root;
1983            bestyet = -10.0 * spp * chars;
1984            item = treenode[j];
1985            if (item != root) {
1986              re_move(&item, &nufork);
1987              there = root;
1988              addpreorder(root, item, nufork);
1989              add(there, item, nufork);
1990            }
1991            if (progress)
1992              putchar('.');
1993          }
1994          if (progress)
1995            putchar('\n');
1996        } while (bestlike > gotlike);
1997      }
1998    }
1999    if (progress)
2000      putchar('\n');
2001    for (i = spp - 1; i >= 1; i--)
2002      re_move(&treenode[i], &dummy);
2003    if (jumb == njumble) {
2004      if (treeprint) {
2005        putc('\n', outfile);
2006        if (nextree == 2)
2007          fprintf(outfile, "One most parsimonious tree found:\n");
2008        else
2009          fprintf(outfile, "%6hd trees in all found\n", nextree - 1);
2010      }
2011      if (nextree > maxtrees + 1) {
2012        if (treeprint)
2013          fprintf(outfile, "here are the first%4hd of them\n", (short)maxtrees);
2014        nextree = maxtrees + 1;
2015      }
2016      if (treeprint)
2017        putc('\n', outfile);
2018      recompute = false;
2019      for (i = 0; i <= (nextree - 2); i++) {
2020        root = treenode[0];
2021        add(treenode[0], treenode[1], treenode[spp]);
2022        for (j = 3; j <= spp; j++)
2023          add(treenode[bestrees[i][j - 1] - 1], treenode[j - 1],
2024            treenode[spp + j - 2]);
2025        reroot(treenode[outgrno - 1]);
2026        postorder(root);
2027        evaluate(root);
2028        printree();
2029        describe();
2030        for (j = 1; j < spp; j++)
2031          re_move(&treenode[j], &dummy);
2032      }
2033    }
2034  } else {
2035    fscanf(infile, "%hd%*[^\n]", &numtrees);
2036    getc(infile);
2037    if (treeprint) {
2038      fprintf(outfile, "User-defined tree");
2039      if (numtrees > 1)
2040        putc('s', outfile);
2041      fprintf(outfile, ":\n\n\n\n");
2042    }
2043    fsteps = (short **)Malloc(maxuser*sizeof(short *));
2044    for (j = 1; j <= maxuser; j++)
2045      fsteps[j - 1] = (short *)Malloc(endsite*sizeof(short));
2046    which = 1;
2047    while (which <= numtrees) {
2048      treeread();
2049      if (outgropt)
2050        reroot(treenode[outgrno - 1]);
2051      postorder(root);
2052      evaluate(root);
2053      printree();
2054      describe();
2055      which++;
2056    }
2057    putc('\n', outfile);
2058    if (numtrees > 1 && chars > 1) {
2059      fprintf(outfile, "Tree    Steps   Diff Steps   Its S.D.");
2060      fprintf(outfile, "   Significantly worse?\n\n");
2061      if (numtrees > maxuser)
2062        num = maxuser;
2063      else
2064        num = numtrees;
2065      for (which = 1; which <= num; which++) {
2066        fprintf(outfile, "%3hd%10.1f", which, nsteps[which - 1] / 10);
2067        if (minwhich == which)
2068          fprintf(outfile, "  <------ best\n");
2069        else {
2070          sumw = 0.0;
2071          sum = 0.0;
2072          sum2 = 0.0;
2073          for (j = 0; j < endsite; j++) {
2074            if (weight[j] > 0) {
2075              wt = weight[j] / 10.0;
2076              sumw += wt;
2077              sum += (fsteps[which - 1][j] -
2078                      fsteps[minwhich - 1][j]) / 10.0;
2079              TEMP = (fsteps[which - 1][j] -
2080                      fsteps[minwhich - 1][j]) / 10.0;
2081              sum2 += TEMP * TEMP / wt;
2082            }
2083          }
2084          TEMP = sum / sumw;
2085          sd = sqrt(sumw / (sumw - 1.0) * (sum2 - TEMP * TEMP));
2086          fprintf(outfile, "%10.1f%13.4f",
2087                  (nsteps[which - 1] - minsteps) / 10, sd);
2088          if (sum > 1.95996 * sd)
2089            fprintf(outfile, "          Yes\n");
2090          else
2091            fprintf(outfile, "           No\n");
2092        }
2093      }
2094      fprintf(outfile, "\n\n");
2095    }
2096    for (j = 1; j <= maxuser; j++)
2097      free(fsteps[j - 1]);
2098    free(fsteps);
2099  }
2100  if (jumb == njumble) {
2101    if (progress) {
2102      printf("Output written to output file\n\n");
2103      if (trout)
2104        printf("Trees also written onto treefile\n\n");
2105    }
2106    free(temp->numsteps);
2107    free(temp->base);
2108    free(temp);
2109    free(temp1->numsteps);
2110    free(temp1->base);
2111    free(temp1);
2112  }
2113}  /* maketree */
2114
2115
2116main(argc, argv)
2117int argc;
2118Char *argv[];
2119{  /* DNA parsimony by uphill search */
2120
2121  /* reads in spp, chars, and the data. Then calls maketree to
2122     construct the tree */
2123char infilename[100],outfilename[100],trfilename[100];
2124#ifdef MAC
2125   macsetup("Dnapars","");
2126#endif
2127  openfile(&infile,INFILE,"r",argv[0],infilename);
2128  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
2129
2130  ibmpc = ibmpc0;
2131  ansi = ansi0;
2132  vt52 = vt520;
2133  mulsets = false;
2134  datasets = 1;
2135  firstset = true;
2136  garbage = NULL;
2137  doinit();
2138  bestrees = (short **)Malloc(maxtrees*sizeof(short *));
2139  for (j = 1; j <= maxtrees; j++)
2140    bestrees[j - 1] = (short *)Malloc(nonodes*sizeof(short));
2141  nayme = (Char **)Malloc(spp*sizeof(Char *));
2142  for (j = 1; j <= spp; j++)
2143    nayme[j - 1] = (Char *)Malloc(nmlngth*sizeof(Char));
2144  enterorder = (short *)Malloc(spp*sizeof(short));
2145  names = (boolean *)Malloc(spp*sizeof(boolean));
2146  place = (short *)Malloc(nonodes*sizeof(short));
2147  weight = (short *)Malloc(chars*sizeof(short));
2148  oldweight = (short *)Malloc(chars*sizeof(short));
2149  alias = (short *)Malloc(chars*sizeof(short));
2150  ally = (short *)Malloc(chars*sizeof(short));
2151  location = (short *)Malloc(chars*sizeof(short));
2152  if (trout)
2153    openfile(&treefile,TREEFILE,"w",argv[0],trfilename);
2154  for (ith = 1; ith <= datasets; ith++) {
2155    doinput();
2156    if (ith == 1)
2157      firstset = false;
2158    if (datasets > 1) {
2159      fprintf(outfile, "Data set # %hd:\n\n",ith);
2160      if (progress)
2161        printf("Data set # %hd:\n\n",ith);
2162    }
2163    for (jumb = 1; jumb <= njumble; jumb++)
2164      maketree();
2165    for (i = 0; i < spp; i++) {
2166      free(treenode[i]->numsteps);
2167      free(treenode[i]->base);
2168    }
2169    for (i = spp; i < nonodes; i++) {
2170      p = treenode[i];
2171      for (j = 1; j <= 3; j++) {
2172        free(p->numsteps);
2173        free(p->base);
2174        p = p->next;
2175      }
2176    }
2177    free(threshwt);
2178  }
2179  FClose(infile);
2180  FClose(outfile);
2181  FClose(treefile);
2182#ifdef MAC
2183  fixmacfile(outfilename);
2184  fixmacfile(trfilename);
2185#endif
2186  exit(0);
2187}  /* DNA parsimony by uphill search */
2188
2189int eof(f)
2190FILE *f;
2191{
2192    register int ch;
2193
2194    if (feof(f))
2195        return 1;
2196    if (f == stdin)
2197        return 0;
2198    ch = getc(f);
2199    if (ch == EOF)
2200        return 1;
2201    ungetc(ch, f);
2202    return 0;
2203}
2204
2205
2206int eoln(f)
2207FILE *f;
2208{
2209    register int ch;
2210
2211    ch = getc(f);
2212    if (ch == EOF)
2213        return 1;
2214    ungetc(ch, f);
2215    return (ch == '\n');
2216}
2217
2218void memerror()
2219{
2220printf("Error allocating memory\n");
2221exit(-1);
2222}
2223
2224MALLOCRETURN *mymalloc(x)
2225long x;
2226{
2227MALLOCRETURN *mem;
2228mem = (MALLOCRETURN *)malloc(x);
2229if (!mem)
2230  memerror();
2231else
2232  return (MALLOCRETURN *)mem;
2233}
2234
Note: See TracBrowser for help on using the repository browser.