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