source: tags/initial/GDE/PHYLIP/dolmove.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: 51.4 KB
Line 
1#include "phylip.h"
2
3/* version 3.52c. (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
10#define ibmpc0          false
11#define ansi0           true
12#define vt520           false
13#define downn           2
14#define overr           4
15
16typedef short *steptr;
17
18typedef Char naym[nmlngth];
19
20typedef enum {
21  horiz, vert, up, over, upcorner, downcorner, one, zero, quest, polym
22} chartype;
23typedef long *bitptr;
24/* nodes will form a binary tree */
25
26typedef struct node {         /* describes a tip species or an ancestor */
27  struct node *next, *back;   /* pointers to nodes                      */
28  short index;                /* number of the node                     */
29  boolean tip;                /* present species are tips of tree       */
30  bitptr stateone, statezero;/* see in PROCEDURE fillin               */
31  short xcoord, ycoord, ymin, ymax;/* used by printree                  */
32  /* stores state for printing */
33  Char state;
34} node;
35typedef enum {  rearr, flipp, reroott, none } rearrtype;
36
37typedef node **pointptr;
38typedef enum {
39  arb, use, spec
40} howtree;
41
42char infilename[100],trfilename[100];
43Static node *root;
44Static FILE *infile, *treefile;
45Static short spp, nonodes, chars, words, outgrno, screenlines, col;
46/* spp = number of species
47  nonodes = number of nodes in tree
48  chars = number of binary characters
49  words = number of words needed to represent characters of one organism
50  outgrno indicates outgroup */
51Static boolean weights, thresh, ancvar, questions, dollo, factors,
52               waswritten, ibmpc, vt52, ansi;
53Static steptr extras, weight;
54Static boolean *ancone, *anczero, *ancone0, *anczero0;
55Static Char *factor;
56Static pointptr treenode;   /* pointers to all nodes in tree */
57Static naym *nayme;         /* names of species              */
58Static double threshold;
59Static double *threshwt;
60Static Char cha[10];
61Static boolean reversed[10];
62Static boolean graphic[10];
63Static howtree how;
64char progname[25];
65char ch;
66Static short bits = 8*sizeof(long) - 1;
67
68/* Local variables for treeconstruct, propagated globally for c version: */
69short dispchar, dispword, dispbit, atwhat, what, fromwhere, towhere,
70  oldoutgrno, compatible;
71double like, bestyet, gotlike;
72Char *guess;
73boolean display, newtree, changed, subtree, written, oldwritten, restoring,
74  wasleft, oldleft, earlytree;
75boolean *intree;
76steptr numsteps;
77long fullset;
78bitptr zeroanc, oneanc;
79node *nuroot;
80rearrtype lastop;
81steptr numsone, numszero;
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
120  if (perm != NULL)
121    strcpy(perm,file);
122}
123
124boolean digit(ch)
125Char ch;
126{
127  /* tests whether ch is a digit */
128  return isdigit(ch);
129}  /* digit */
130
131
132void uppercase(ch)
133Char *ch;
134{
135  *ch = (islower (*ch) ? toupper(*ch) : (*ch));
136}  /* uppercase */
137
138void newline(i, j, k)
139short i, j, k;
140{
141  /* go to new line if i is a multiple of j, indent k spaces */
142  short m;
143
144  if ((i - 1) % j != 0 || i <= 1)
145    return;
146  putchar('\n');
147  for (m = 1; m <= k; m++)
148    putchar(' ');
149}  /* newline */
150
151void inpnum(n, success)
152short *n;
153boolean *success;
154{
155  int fields;
156  char line[100];
157  gets(line);
158  *n = atof(line);
159  fields = sscanf(line,"%hd",n);
160  *success = (fields == 1);
161
162}  /* inpnum */
163
164
165
166void inputnumbers()
167{
168  /* input the numbers of species and of characters */
169  fscanf(infile, "%hd%hd", &spp, &chars);
170  printf("%3hd Species, %3hd Characters\n\n", spp, chars);
171  words = chars / bits + 1;
172  nonodes = spp * 2 - 1;
173}  /* inputnumbers */
174
175void getoptions()
176{
177  /* interactively set options */
178  Char ch;
179  boolean done, done1, gotopt;
180
181  how = arb;
182  thresh = false;
183  threshold = spp;
184  weights = false;
185  ancvar = false;
186  factors = false;
187  dollo = true;
188  do {
189    printf((ansi || ibmpc) ? "\033[2J\033[H" :
190           vt52 ? "\033E\033H"    : "\n");
191    printf("\nInteractive Dollo or polymorphism parsimony,");
192    printf(" version %s\n\n",VERSION);
193    printf("Settings for this run:\n");
194    printf("  P                        Parsimony method?");
195    printf("  %s\n",(dollo ? "Dollo" : "Polymorphism"));
196    printf("  T                 Use Threshold parsimony?");
197    if (thresh)
198      printf("  Yes, count steps up to%4.1f\n", threshold);
199    else
200      printf("  No, use ordinary parsimony\n");
201    printf("  A      Use ancestral states in input file?");
202    printf("  %s\n",(ancvar ? "Yes" : "No"));
203    printf("  U Initial tree (arbitrary, user, specify)?");
204    printf("  %s\n",(how == arb) ? "Arbitrary" :
205                    (how == use) ? "User tree from tree file" :
206                                   "Tree you specify");
207    printf("  0      Graphics type (IBM PC, VT52, ANSI)?  %s\n",
208           ibmpc ? "IBM PC" :
209           ansi  ? "ANSI"   :
210           vt52  ? "VT52"   :
211                  "(none)");
212    printf("  L               Number of lines on screen?%4hd",screenlines);
213    do {
214      printf(
215        "\n\nAre these settings correct? (type Y or the letter for one to change)\n");
216      scanf("%c%*[^\n]", &ch);
217      getchar();
218      uppercase(&ch);
219      done = (ch == 'Y');
220      gotopt = (strchr("TPULA0",ch) != NULL) ? true : false;
221      if (gotopt) {
222        switch (ch) {
223
224        case 'A':
225          ancvar = !ancvar;
226          break;
227
228        case 'P':
229          dollo = !dollo;
230          break;
231
232        case 'T':
233          thresh = !thresh;
234          if (thresh) {
235            done1 = false;
236            do {
237              printf("What will be the threshold value?\n");
238              scanf("%lf%*[^\n]", &threshold);
239              getchar();
240              done1 = (threshold >= 1.0);
241              if (!done1)
242                printf("BAD THRESHOLD VALUE:  it must be greater than 1\n");
243              else
244                threshold = (long)(threshold * 10.0 + 0.5) / 10.0;
245            } while (done1 != true);
246          }
247          break;
248
249        case 'U':
250          if (how == arb)
251            how = use;
252          else if (how == use)
253            how = spec;
254          else
255            how = arb;
256          break;
257
258        case '0':
259          if (ibmpc) {
260            ibmpc = false;
261            vt52 = true;
262          } else {
263            if (vt52) {
264              vt52 = false;
265              ansi = true;
266            } else if (ansi)
267              ansi = false;
268            else
269              ibmpc = true;
270          }
271          break;
272
273        case 'L':
274          do {
275            printf("Number of lines on screen?\n");
276            scanf("%hd", &screenlines);
277          } while (screenlines <= 12);
278          break;
279        }
280      }
281      if (!(gotopt || done))
282        printf("Not a possible option!\n");
283    } while (!(gotopt || done));
284  } while (!done);
285}  /* getoptions */
286
287void inputfactors()
288{
289  /* reads the factor symbols */
290  short i;
291  Char ch;
292
293  for (i = 1; i < nmlngth; i++)
294    ch = getc(infile);
295  for (i = 0; i < (chars); i++) {
296    if (eoln(infile)) {
297      fscanf(infile, "%*[^\n]");
298      getc(infile);
299    }
300    factor[i] = getc(infile);
301  }
302  fscanf(infile, "%*[^\n]");
303  getc(infile);
304  factors = true;
305}  /* inputfactors */
306
307
308void printfactors()
309{
310  /* print out list of factor symbols */
311  short i;
312  printf("Factors:");
313  for (i = 1; i <= nmlngth - 5; i++)
314    putchar(' ');
315  for (i = 1; i <= (chars); i++) {
316    newline(i, 55, (int)(nmlngth + 3));
317    putchar(factor[i - 1]);
318    if (i % 5 == 0)
319      putchar(' ');
320  }
321  printf("\n\n");
322}  /* printfactors */
323
324void inputweights()
325{
326  /* input the character weights, 0-9 and A-Z for weights 0 - 35 */
327  Char ch;
328  short i;
329
330  for (i = 1; i < nmlngth; i++)
331    ch = getc(infile);
332  for (i = 0; i < (chars); i++) {
333    do {
334      if (eoln(infile)) {
335        fscanf(infile, "%*[^\n]");
336        getc(infile);
337      }
338      ch = getc(infile);
339    } while (ch == ' ');
340    weight[i] = 1;
341    if (digit(ch))
342      weight[i] = ch - '0';
343    else if (isalpha(ch)) {
344      uppercase(&ch);
345      if (ch >= 'A' && ch <= 'I')
346        weight[i] = ch - 55;
347      else if (ch >= 'J' && ch <= 'R')
348        weight[i] = ch - 55;
349      else
350        weight[i] = ch - 55;
351    } else {
352      printf("BAD WEIGHT CHARACTER: %c\n", ch);
353      exit(-1);
354    }
355  }
356  fscanf(infile, "%*[^\n]");
357  getc(infile);
358  weights = true;
359}  /* inputweights */
360
361void printweights()
362{
363  /* print out the weights of characters */
364  short i, j, k;
365
366  printf("   Characters are weighted as follows:\n");
367  printf("        ");
368  for (i = 0; i <= 9; i++)
369    printf("%3hd", i);
370  printf("\n     *---------------------------------\n");
371  for (j = 0; j <= (chars / 10); j++) {
372    printf("%5hd!  ", j * 10);
373    for (i = 0; i <= 9; i++) {
374      k = j * 10 + i;
375      if (k > 0 && k <= chars)
376        printf("%3hd", weight[k - 1]);
377      else
378        printf("   ");
379    }
380    putchar('\n');
381  }
382  putchar('\n');
383}  /* printweights */
384
385void inputancestors()
386{
387  /* reads the ancestral states for each character */
388  short i;
389  Char ch;
390
391  for (i = 1; i < nmlngth; i++)
392    ch = getc(infile);
393  for (i = 0; i < (chars); i++) {
394    anczero0[i] = true;
395    ancone0[i] = true;
396    do {
397      if (eoln(infile)) {
398        fscanf(infile, "%*[^\n]");
399        getc(infile);
400      }
401      ch = getc(infile);
402    } while (ch == ' ');
403    if (ch == 'p')
404      ch = 'P';
405    if (ch == 'b')
406      ch = 'B';
407    if (strchr("10PB?",ch)){
408      anczero0[i] = (ch == '1') ? false : anczero0[i];
409      ancone0[i] = (ch == '0') ? false : ancone0[i];
410    } else {
411      printf("BAD ANCESTOR STATE: %cAT CHARACTER %4hd\n", ch, i + 1);
412      exit(-1);
413    }
414  }
415  fscanf(infile, "%*[^\n]");
416  getc(infile);
417}  /* inputancestors */
418
419void printancestors()
420{
421  /* print out list of ancestral states */
422  short i;
423
424  printf("Ancestral states:\n");
425  for (i = 1; i <= nmlngth + 3; i++)
426    putchar(' ');
427  for (i = 1; i <= (chars); i++) {
428    newline(i, 55, (int)(nmlngth + 3));
429    if (ancone[i - 1] && anczero[i - 1])
430      putchar('?');
431    else if (ancone[i - 1])
432      putchar('1');
433    else
434      putchar('0');
435    if (i % 5 == 0)
436      putchar(' ');
437  }
438  printf("\n\n");
439}  /* printancestor */
440
441void inputoptions()
442{
443  /* input the information on the options */
444  Char ch;
445  short extranum, i;
446  boolean avar;
447
448  extranum = 0;
449  avar = false;
450  while (!eoln(infile)) {
451    ch = getc(infile);
452    uppercase(&ch);
453    if (ch == 'A' || ch == 'F' || ch == 'W')
454      extranum++;
455    else if (ch != ' ') {
456      printf("BAD OPTION CHARACTER: %c\n\n", ch);
457      exit(-1);
458    }
459  }
460  fscanf(infile, "%*[^\n]");
461  getc(infile);
462  for (i = 0; i < (chars); i++)
463    weight[i] = 1;
464  for (i = 1; i <= extranum; i++) {
465    ch = getc(infile);
466    uppercase(&ch);
467    if (ch != 'A' && ch != 'F' && ch != 'W'){
468      printf("ERROR: INCORRECT AUXILIARY OPTIONS LINE WHICH STARTS WITH %c\n",
469             ch);
470      exit(-1);}
471    if (ch == 'A') {
472      avar = true;
473      if (!ancvar) {
474        printf("ERROR: ANCESTOR OPTION NOT CHOSEN IN MENU WITH OPTION %c IN INPUT\n",
475               ch);
476        exit(-1);
477      } else
478        inputancestors();
479    }
480    if (ch == 'F')
481      inputfactors();
482    if (ch == 'W')
483      inputweights();
484  }
485  if (ancvar && !avar) {
486    puts("ERROR: ANCESTOR OPTION CHOSEN IN MENU WITH NO OPTION A IN INPUT");
487    exit(-1);
488  }
489  putchar('\n');
490  if (weights)
491    printweights();
492  if (factors)
493    printfactors();
494  for (i = 0; i < (chars); i++) {
495    if (!ancvar) {
496      anczero[i] = true;
497      ancone[i] = false;
498    } else {
499      anczero[i] = anczero0[i];
500      ancone[i] = ancone0[i];
501    }
502  }
503  if (ancvar && avar)
504    printancestors();
505  if (!thresh)
506    threshold = spp;
507  questions = false;
508  for (i = 0; i < (chars); i++) {
509    questions = (questions || (ancone[i] && anczero[i]));
510    threshwt[i] = threshold * weight[i];
511  }
512}  /* inputoptions */
513
514void inputdata()
515{
516  /* input the names and character state data for species */
517  short i, j, l;
518  char k;
519  Char charstate;
520  /* possible states are
521                 '0', '1', 'P', 'B', and '?' */
522  node *p, *q;
523
524  for (i = 0; i < (chars); i++)
525    extras[i] = 0;
526  treenode = (pointptr)Malloc(nonodes*sizeof(node *));
527  for (i = 0; i < (spp); i++) {
528    treenode[i] = (node *)Malloc(sizeof(node));
529    treenode[i]->stateone = (bitptr)Malloc(words*sizeof(long));
530    treenode[i]->statezero = (bitptr)Malloc(words*sizeof(long));
531  }
532  for (i = spp; i < (nonodes); i++) {
533    q = NULL;
534    for (j = 1; j <= 3; j++) {
535      p = (node *)Malloc(sizeof(node));
536      p->stateone = (bitptr)Malloc(words*sizeof(long));
537      p->statezero = (bitptr)Malloc(words*sizeof(long));
538      p->next = q;
539      q = p;
540    }
541    p->next->next->next = p;
542    treenode[i] = p;
543  }
544  for (i = 1; i <= (nonodes); i++) {
545    treenode[i - 1]->back = NULL;
546    treenode[i - 1]->tip = (i <= spp);
547    treenode[i - 1]->index = i;
548    if (i > spp) {
549      p = treenode[i - 1]->next;
550      while (p != treenode[i - 1]) {
551        p->back = NULL;
552        p->tip = false;
553        p->index = i;
554        p = p->next;
555      }
556    } else {
557      for (j = 0; j < nmlngth; j++) {
558        nayme[i - 1][j] = getc(infile);
559        if (eof(infile) || eoln(infile)){
560          printf("ERROR: END-OF-LINE OR END-OF-FILE");
561          printf(" IN THE MIDDLE OF A SPECIES NAME\n");
562          exit(-1);}
563      }
564      for (j = 0; j < (words); j++) {
565        treenode[i - 1]->stateone[j] = 0;
566        treenode[i - 1]->statezero[j] = 0;
567      }
568      for (j = 0; j < (chars); j++) {
569        k = j % bits + 1;
570        l = j / bits + 1;
571        do {
572          if (eoln(infile)) {
573            fscanf(infile, "%*[^\n]");
574            getc(infile);
575          }
576          charstate = getc(infile);
577        } while (charstate == ' ');
578        if (charstate == 'b')
579          charstate = 'B';
580        if (charstate == 'p')
581          charstate = 'P';
582        if (charstate != '0' && charstate != '1' && charstate != '?' &&
583            charstate != 'P' && charstate != 'B') {
584          printf("INPUT ERROR -- BAD CHARACTER STATE: %c ",charstate);
585          printf("AT CHARACTER %5hd OF SPECIES %3hd\n",j+1,i);
586          exit(-1);
587        }
588        if (charstate == '1')
589          treenode[i - 1]->stateone[l - 1] =
590            ((long)treenode[i - 1]->stateone[l - 1]) | (1L << k);
591        if (charstate == '0')
592          treenode[i - 1]->statezero[l - 1] =
593            ((long)treenode[i - 1]->statezero[l - 1]) | (1L << k);
594        if (charstate == 'P' || charstate == 'B') {
595          if (dollo)
596            extras[j] += weight[j];
597          else {
598            treenode[i - 1]->stateone[l - 1] =
599              ((long)treenode[i - 1]->stateone[l - 1]) | (1L << k);
600            treenode[i - 1]->statezero[l - 1] =
601              ((long)treenode[i - 1]->statezero[l - 1]) | (1L << k);
602          }
603        }
604      }
605      fscanf(infile, "%*[^\n]");
606      getc(infile);
607    }
608  }
609  root = NULL;
610  printf("\n\n");
611}  /* inputdata */
612
613
614void doinput()
615{
616  /* reads the input data */
617  inputnumbers();
618  printf("\nReading input file ...\n\n");
619  getoptions();
620  nayme = (naym *)Malloc(spp*sizeof(naym));
621  intree = (boolean *)Malloc(nonodes*sizeof(boolean));
622  extras = (steptr)Malloc(chars*sizeof(short));
623  weight = (steptr)Malloc(chars*sizeof(short));
624  numszero = (steptr)Malloc(chars*sizeof(short));
625  numsone = (steptr)Malloc(chars*sizeof(short));
626  threshwt = (double *)Malloc(chars*sizeof(double));
627  factor = (Char *)Malloc(chars*sizeof(Char));
628  ancone = (boolean *)Malloc(chars*sizeof(boolean));
629  anczero = (boolean *)Malloc(chars*sizeof(boolean));
630  ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
631  anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
632  zeroanc = (bitptr)Malloc(words*sizeof(long));
633  oneanc = (bitptr)Malloc(words*sizeof(long));
634  inputoptions();
635  inputdata();
636}  /* doinput */
637
638
639void configure()
640{
641  /* configure to machine -- set up special characters */
642  chartype a;
643
644  for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
645    reversed[(long)a] = false;
646  for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
647    graphic[(long)a] = false;
648  if (ibmpc) {
649    cha[(long)horiz] = 205;
650    graphic[(long)horiz] = true;
651    cha[(long)vert] = 186;
652    graphic[(long)vert] = true;
653    cha[(long)up] = 186;
654    graphic[(long)up] = true;
655    cha[(long)over] = 205;
656    graphic[(long)over] = true;
657    cha[(long)one] = 219;
658    reversed[(long)one] = true;
659    cha[(long)zero] = 176;
660    graphic[(long)zero] = true;
661    cha[(long)quest] = 178;   /* or try CHR(177) */
662    cha[(long)polym] = '\001';
663    reversed[(long)polym] = true;
664    cha[(long)upcorner] = 200;
665    graphic[(long)upcorner] = true;
666    cha[(long)downcorner] = 201;
667    graphic[(long)downcorner] = true;
668    graphic[(long)quest] = true;
669    return;
670  }
671  if (vt52) {
672    cha[(long)one] = ' ';
673    reversed[(long)one] = true;
674    cha[(long)horiz] = cha[(long)one];
675    reversed[(long)horiz] = true;
676    cha[(long)vert] = cha[(long)one];
677    reversed[(long)vert] = true;
678    cha[(long)up] = '`';
679    graphic[(long)up] = true;
680    cha[(long)over] = 'a';
681    graphic[(long)over] = true;
682    cha[(long)zero] = 'i';
683    graphic[(long)zero] = true;
684    cha[(long)quest] = '?';
685    reversed[(long)quest] = true;
686    cha[(long)polym] = '%';
687    reversed[(long)polym] = true;
688    cha[(long)upcorner] = 'e';
689    graphic[(long)upcorner] = true;
690    cha[(long)downcorner] = 'f';
691    graphic[(long)downcorner] = true;
692    return;
693  }
694  if (ansi) {
695    cha[(long)one] = ' ';
696    reversed[(long)one] = true;
697    cha[(long)horiz] = cha[(long)one];
698    reversed[(long)horiz] = true;
699    cha[(long)vert] = cha[(long)one];
700    reversed[(long)vert] = true;
701    cha[(long)up] = 'x';
702    graphic[(long)up] = true;
703    cha[(long)over] = 'q';
704    graphic[(long)over] = true;
705    cha[(long)zero] = 'a';
706    graphic[(long)zero] = true;
707    reversed[(long)zero] = true;
708    cha[(long)quest] = '?';
709    cha[(long)quest] = '?';
710    reversed[(long)quest] = true;
711    cha[(long)polym] = '%';
712    reversed[(long)polym] = true;
713    cha[(long)upcorner] = 'm';
714    graphic[(long)upcorner] = true;
715    cha[(long)downcorner] = 'l';
716    graphic[(long)downcorner] = true;
717    return;
718  }
719  cha[(long)horiz] = '=';
720  cha[(long)vert] = ' ';
721  cha[(long)up] = '!';
722  cha[(long)over] = '-';
723  cha[(long)one] = '*';
724  cha[(long)zero] = '=';
725  cha[(long)quest] = '.';
726  cha[(long)polym] = '%';
727  cha[(long)upcorner] = '`';
728  cha[(long)downcorner] = ',';
729}  /* configure */
730
731
732void pregraph()
733{
734  /* turn on graphic characters */
735  if (vt52)
736    printf("\033F");
737  if (ansi)
738    printf("\033(0");
739}  /* pregraph */
740
741void prereverse()
742{
743  /* turn on reverse video */
744  if (vt52)
745    printf("\033p");
746  if (ansi)
747    printf("\033[7m");
748}  /* prereverse */
749
750
751void prefix(a)
752chartype a;
753{
754  /* give prefix appropriate for this character */
755  if (reversed[(long)a])
756    prereverse();
757  if (graphic[(long)a])
758    pregraph();
759}  /* prefix */
760
761
762void postgraph()
763{
764  /* turn off graphic characters */
765  if (vt52)
766    printf("\033G");
767  if (ansi)
768    printf("\033(B");
769}  /* postgraph */
770
771void postreverse()
772{
773  /* turn off reverse video */
774  if (vt52)
775    printf("\033q");
776  if (ansi)
777    printf("\033[0m");
778}  /* postreverse */
779
780
781void postfix(a)
782chartype a;
783{
784  /* give postfix appropriate for this character */
785  if (reversed[(long)a])
786    postreverse();
787  if (graphic[(long)a])
788    postgraph();
789}  /* postfix */
790
791
792void makechar(a)
793chartype a;
794{
795  /* print out a character with appropriate prefix or postfix */
796  prefix(a);
797  putchar(cha[(long)a]);
798  postfix(a);
799}  /* makechar */
800
801
802
803void add(below, newtip, newfork)
804node *below, *newtip, *newfork;
805{
806  /* inserts the nodes newfork and its left descendant, newtip,
807    to the tree.  below becomes newfork's right descendant */
808  boolean putleft;
809  node *leftdesc, *rtdesc;
810
811  if (below != treenode[below->index - 1])
812    below = treenode[below->index - 1];
813  if (below->back != NULL)
814    below->back->back = newfork;
815  newfork->back = below->back;
816  putleft = true;
817  if (restoring)
818    putleft =wasleft;
819  if (putleft) {
820    leftdesc = newtip;
821    rtdesc = below;
822  } else {
823    leftdesc = below;
824    rtdesc = newtip;
825  }
826  rtdesc->back = newfork->next->next;
827  newfork->next->next->back = rtdesc;
828  newfork->next->back = leftdesc;
829  leftdesc->back = newfork->next;
830  if (root == below)
831    root = newfork;
832  root->back = NULL;
833}  /* add */
834
835void re_move(item, fork)
836node **item, **fork;
837{
838  /* removes nodes item and its ancestor, fork, from the tree.
839    the new descendant of fork's ancestor is made to be
840    fork's second descendant (other than item).  Also
841    returns pointers to the deleted nodes, item and fork */
842  node *p, *q;
843
844  if ((*item)->back == NULL) {
845    *fork = NULL;
846    return;
847  }
848  *fork = treenode[(*item)->back->index - 1];
849  if (*item == (*fork)->next->back) {
850    if (root == *fork)
851      root = (*fork)->next->next->back;
852    wasleft = true;
853  } else {
854    if (root == *fork)
855      root = (*fork)->next->back;
856    wasleft = false;
857  }
858  p = (*item)->back->next->back;
859  q = (*item)->back->next->next->back;
860  if (p != NULL)
861    p->back = q;
862  if (q != NULL)
863    q->back = p;
864  (*fork)->back = NULL;
865  p = (*fork)->next;
866  while (p != *fork) {
867    p->back = NULL;
868    p = p->next;
869  }
870  (*item)->back = NULL;
871}  /* remove */
872
873
874void fillin(p)
875node *p;
876
877{
878  /* Sets up for each node in the tree two statesets.
879    stateone and statezero are the sets of character
880    states that must be 1 or must be 0, respectively,
881    in a most parnsimonious reconstruction, based on the
882    information at or above this node.  Note that this
883    state assignment may change based on information further
884    down the tree.  If a character is in both sets it is in
885    state "P".  If in neither, it is "?". */
886  short i;
887
888  for (i = 0; i < (words); i++) {
889    p->stateone[i] = p->next->back->stateone[i] | p->next->next->back->stateone[i];
890    p->statezero[i] = p->next->back->statezero[i] |
891                      p->next->next->back->statezero[i];
892  }
893}  /* fillin */
894
895void correct(p)
896node *p;
897{  /* get final states for intermediate nodes */
898  short i;
899  long z0, z1, s0, s1, temp;
900
901  if (p->tip)
902    return;
903  for (i = 0; i < (words); i++) {
904    if (p->back == NULL) {
905      s0 = zeroanc[i];
906      s1 = oneanc[i];
907    } else {
908      s0 = treenode[p->back->index - 1]->statezero[i];
909      s1 = treenode[p->back->index - 1]->stateone[i];
910    }
911    z0 = (s0 & p->statezero[i]) |
912         (p->next->back->statezero[i] & p->next->next->back->statezero[i]);
913    z1 = (s1 & p->stateone[i]) |
914         (p->next->back->stateone[i] & p->next->next->back->stateone[i]);
915    if (dollo) {
916      temp = z0 & (~(zeroanc[i] & z1));
917      z1 &= ~(oneanc[i] & z0);
918      z0 = temp;
919    }
920    temp = fullset & (~z0) & (~z1);
921    p->statezero[i] = z0 | (temp & s0 & (~s1));
922    p->stateone[i] = z1 | (temp & s1 & (~s0));
923  }
924}  /* correct */
925
926/* Local variables for evaluate: */
927
928
929void postorder(p)
930node *p;
931{
932  /* traverses a binary tree, calling PROCEDURE fillin at a
933    node's descendants before calling fillin at the node */
934  if (p->tip)
935    return;
936  postorder(p->next->back);
937  postorder(p->next->next->back);
938  fillin(p);
939}  /* postorder */
940
941
942void count(p)
943node *p;
944{
945  /* counts the number of steps in a fork of the tree.
946    The program spends much of its time in this PROCEDURE */
947  short i, j, l;
948  bitptr steps;
949
950  steps = (bitptr)Malloc(words*sizeof(long));
951  if (dollo) {
952    for (i = 0; i < (words); i++)
953      steps[i] = (treenode[p->back->index - 1]->stateone[i] &
954                  p->statezero[i] & zeroanc[i]) |
955                 (treenode[p->back->index - 1]->statezero[i] &
956                  p->stateone[i] & oneanc[i]);
957  } else {
958    for (i = 0; i < (words); i++)
959      steps[i] = treenode[p->back->index - 1]->stateone[i] &
960                 treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
961                 p->statezero[i];
962  }
963  j = 1;
964  l = 0;
965  for (i = 0; i < (chars); i++) {
966    l++;
967    if (l > bits) {
968      l = 1;
969      j++;
970    }
971    if ((unsigned)l < 32 && ((1L << l) & steps[j - 1]) != 0) {
972      if ((unsigned)l < 32 && ((1L << l) & zeroanc[j - 1]) != 0)
973        numszero[i] += weight[i];
974      else
975        numsone[i] += weight[i];
976    }
977  }
978  free(steps);
979}  /* count */
980
981void preorder(p)
982node *p;
983{
984  /* go back up tree setting up and counting interior node
985    states */
986
987  if (!p->tip) {
988    correct(p);
989    preorder(p->next->back);
990    preorder(p->next->next->back);
991  }
992  if (p->back != NULL)
993    count(p);
994}  /* preorder */
995
996void evaluate(r)
997node *r;
998{
999  /* Determines the number of losses or polymorphisms needed for a tree.
1000     This is the minimum number needed to evolve chars on this tree */
1001  short i, stepnum, smaller;
1002  double sum;
1003  boolean nextcompat, thiscompat, done;
1004
1005  sum = 0.0;
1006  for (i = 0; i < (chars); i++) {
1007    numszero[i] = 0;
1008    numsone[i] = 0;
1009  }
1010  for (i = 0; i < (words); i++) {
1011    zeroanc[i] = fullset;
1012    oneanc[i] = 0;
1013  }
1014  compatible = 0;
1015  nextcompat = true;
1016  postorder(r);
1017  preorder(r);
1018  for (i = 0; i < (words); i++) {
1019    zeroanc[i] = 0;
1020    oneanc[i] = fullset;
1021  }
1022  postorder(r);
1023  preorder(r);
1024  for (i = 0; i < (chars); i++) {
1025    smaller = spp * weight[i];
1026    numsteps[i] = smaller;
1027    if (anczero[i]) {
1028      numsteps[i] = numszero[i];
1029      smaller = numszero[i];
1030    }
1031    if (ancone[i] && numsone[i] < smaller)
1032      numsteps[i] = numsone[i];
1033    stepnum = numsteps[i] + extras[i];
1034    if (stepnum <= threshwt[i])
1035      sum += stepnum;
1036    else
1037      sum += threshwt[i];
1038    thiscompat = (stepnum <= weight[i]);
1039    if (factors) {
1040      done = (i + 1 == chars);
1041      if (!done)
1042        done = (factor[i + 1] != factor[i]);
1043      nextcompat = (nextcompat && thiscompat);
1044      if (done) {
1045        if (nextcompat)
1046          compatible += weight[i];
1047        nextcompat = true;
1048      }
1049    } else if (thiscompat)
1050      compatible += weight[i];
1051    guess[i] = '?';
1052    if (!ancone[i] ||
1053        (anczero[i] && numszero[i] < numsone[i]))
1054      guess[i] = '0';
1055    else if (!anczero[i] ||
1056             (ancone[i] && numsone[i] < numszero[i]))
1057      guess[i] = '1';
1058  }
1059  like = -sum;
1060}  /* evaluate */
1061
1062void reroot(outgroup)
1063node *outgroup;
1064{
1065  /* reorients tree, putting outgroup in desired position. */
1066  node *p, *q, *newbottom, *oldbottom;
1067  boolean onleft;
1068
1069  if (outgroup->back->index == root->index)
1070    return;
1071  newbottom = outgroup->back;
1072  p = treenode[newbottom->index - 1]->back;
1073  while (p->index != root->index) {
1074    oldbottom = treenode[p->index - 1];
1075    treenode[p->index - 1] = p;
1076    p = oldbottom->back;
1077  }
1078  onleft = (p == root->next);
1079  if (restoring)
1080    if (!onleft && wasleft){
1081      p = root->next->next;
1082      q = root->next;
1083    } else {
1084      p = root->next;
1085      q = root->next->next;
1086    }
1087  else {
1088    if (onleft)
1089      oldoutgrno = root->next->next->back->index;
1090    else
1091      oldoutgrno = root->next->back->index;
1092    wasleft = onleft;
1093    p = root->next;
1094    q = root->next->next;
1095  }
1096  p->back->back = q->back;
1097  q->back->back = p->back;
1098  p->back = outgroup;
1099  q->back = outgroup->back;
1100  if (restoring) {
1101    if (!onleft && wasleft) {
1102      outgroup->back->back = root->next;
1103      outgroup->back = root->next->next;
1104    } else {
1105      outgroup->back->back = root->next->next;
1106      outgroup->back = root->next;
1107    }
1108  } else {
1109    outgroup->back->back = root->next->next;
1110    outgroup->back = root->next;
1111  }
1112  treenode[newbottom->index - 1] = newbottom;
1113}  /* reroot */
1114
1115void filltrav(r)
1116node *r;
1117{
1118  /* traverse to fill in interior node states */
1119  if (r->tip)
1120    return;
1121  filltrav(r->next->back);
1122  filltrav(r->next->next->back);
1123  fillin(r);
1124}  /* filltrav */
1125
1126void hyptrav(r)
1127node *r;
1128{
1129  /* compute states at interior nodes for one character */
1130  if (!r->tip)
1131    correct(r);
1132  if ((unsigned)dispbit < 32 &&
1133      ((1L << dispbit) & r->stateone[dispword - 1]) != 0) {
1134    if ((unsigned)dispbit < 32 &&
1135        ((1L << dispbit) & r->statezero[dispword - 1]) != 0) {
1136      if (dollo)
1137        r->state = '?';
1138      else
1139        r->state = 'P';
1140    } else
1141      r->state = '1';
1142  } else {
1143    if ((unsigned)dispbit < 32 &&
1144        ((1L << dispbit) & r->statezero[dispword - 1]) != 0)
1145      r->state = '0';
1146    else
1147      r->state = '?';
1148  }
1149  if (!r->tip) {
1150    hyptrav(r->next->back);
1151    hyptrav(r->next->next->back);
1152  }
1153}  /* hyptrav */
1154
1155void hypstates()
1156{
1157  /* fill in and describe states at interior nodes */
1158  short i, j, k;
1159
1160  for (i = 0; i < (words); i++) {
1161    zeroanc[i] = 0;
1162    oneanc[i] = 0;
1163  }
1164  for (i = 0; i < (chars); i++) {
1165    j = i / bits + 1;
1166    k = i % bits + 1;
1167    if (guess[i] == '0')
1168      zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
1169    if (guess[i] == '1')
1170      oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
1171  }
1172  filltrav(root);
1173  hyptrav(root);
1174}  /* hypstates */
1175
1176/* Local variables for printree: */
1177
1178
1179void coordinates(p, tipy)
1180node *p;
1181short *tipy;
1182{
1183  /* establishes coordinates of nodes */
1184  node *q, *first, *last;
1185
1186  if (p->tip) {
1187    p->xcoord = 0;
1188    p->ycoord = *tipy;
1189    p->ymin = *tipy;
1190    p->ymax = *tipy;
1191    (*tipy) += downn;
1192    return;
1193  }
1194  q = p->next;
1195  do {
1196    coordinates(q->back, tipy);
1197    q = q->next;
1198  } while (p != q);
1199  first = p->next->back;
1200  q = p->next;
1201  while (q->next != p)
1202    q = q->next;
1203  last = q->back;
1204  p->xcoord = (last->ymax - first->ymin) * 3 / 2;
1205  p->ycoord = (first->ycoord + last->ycoord) / 2;
1206  p->ymin = first->ymin;
1207  p->ymax = last->ymax;
1208}  /* coordinates */
1209
1210void drawline(i, lastline)
1211short i, lastline;
1212{
1213  /* draws one row of the tree diagram by moving up tree */
1214  node *p, *q, *r, *first, *last;
1215  short n, j;
1216  boolean extra, done;
1217  Char s, cc;
1218  chartype c, d;
1219
1220  p = nuroot;
1221  q = nuroot;
1222  extra = false;
1223  if (i == p->ycoord && (p == root || subtree)) {
1224    c = over;
1225    if (p == root)
1226      cc = guess[dispchar - 1];
1227    else
1228      cc = p->state;
1229    if (display) {
1230      switch (cc) {
1231
1232      case '1':
1233        c = one;
1234        break;
1235
1236      case '0':
1237        c = zero;
1238        break;
1239
1240      case '?':
1241        c = quest;
1242        break;
1243
1244      case 'P':
1245        c = polym;
1246        break;
1247      }
1248    }
1249    if (p->index >= 10) {
1250      makechar(c);
1251      printf("%2hd", p->index);
1252    } else {
1253      makechar(c);
1254      makechar(c);
1255      printf("%hd", p->index);
1256    }
1257    extra = true;
1258  } else
1259    printf("  ");
1260  do {
1261    if (!p->tip) {
1262      r = p->next;
1263      done = false;
1264      do {
1265        if (i >= r->back->ymin && i <= r->back->ymax) {
1266          q = r->back;
1267          done = true;
1268        }
1269        r = r->next;
1270      } while (!(done || r == p));
1271      first = p->next->back;
1272      r = p->next;
1273      while (r->next != p)
1274        r = r->next;
1275      last = r->back;
1276    }
1277    done = (p == q);
1278    n = p->xcoord - q->xcoord;
1279    if (n < 3 && !q->tip)
1280      n = 3;
1281    if (extra) {
1282      n--;
1283      extra = false;
1284    }
1285    if (q->ycoord == i && !done) {
1286      if (q->ycoord > p->ycoord)
1287        d = upcorner;
1288      else
1289        d = downcorner;
1290      c = over;
1291      s = q->state;
1292      if (s == 'P' && p->state != 'P')
1293        s = p->state;
1294      if (display) {
1295        switch (s) {
1296
1297        case '1':
1298          c = one;
1299          break;
1300
1301        case '0':
1302          c = zero;
1303          break;
1304
1305        case '?':
1306          c = quest;
1307          break;
1308
1309        case 'P':
1310          c = polym;
1311          break;
1312        }
1313        d = c;
1314      }
1315      if (n > 1) {
1316        makechar(d);
1317        prefix(c);
1318        for (j = 1; j <= n - 2; j++)
1319          putchar(cha[(long)c]);
1320        postfix(c);
1321      }
1322      if (q->index >= 10)
1323        printf("%2hd", q->index);
1324      else {
1325        makechar(c);
1326        printf("%hd", q->index);
1327      }
1328      extra = true;
1329    } else if (!q->tip) {
1330      if (last->ycoord > i && first->ycoord < i && i != p->ycoord) {
1331        c = up;
1332        if (i < p->ycoord)
1333          s = p->next->back->state;
1334        else
1335          s = p->next->next->back->state;
1336        if (s == 'P' && p->state != 'P')
1337          s = p->state;
1338        if (display) {
1339          switch (s) {
1340
1341          case '1':
1342            c = one;
1343            break;
1344
1345          case '0':
1346            c = zero;
1347            break;
1348
1349          case '?':
1350            c = quest;
1351            break;
1352
1353          case 'P':
1354            c = polym;
1355            break;
1356          }
1357        }
1358        makechar(c);
1359        for (j = 1; j < n; j++)
1360          putchar(' ');
1361      } else {
1362        for (j = 1; j <= n; j++)
1363          putchar(' ');
1364      }
1365    } else {
1366      for (j = 1; j <= n; j++)
1367        putchar(' ');
1368    }
1369    if (p != q)
1370      p = q;
1371  } while (!done);
1372  if (p->ycoord == i && p->tip) {
1373    putchar(':');
1374    for (j = 0; j < nmlngth; j++)
1375      putchar(nayme[p->index - 1][j]);
1376  }
1377  if (i == 1) {
1378    if (display)
1379      printf("   CHARACTER%4hd", dispchar);
1380    else
1381      printf("            ");
1382    if (subtree)
1383      printf(" Subtree ");
1384    else
1385      printf("         ");
1386    if (dollo)
1387      printf("Dollo");
1388    else
1389      printf("Polymorphism ");
1390  }
1391  if (i == 3 && display) {
1392    printf("   ");
1393    makechar(one);
1394    printf(":1 ");
1395    makechar(quest);
1396    printf(":? ");
1397    makechar(zero);
1398    printf(":0 ");
1399    if (!dollo) {
1400      putchar(' ');
1401      makechar(polym);
1402      printf(":0/1");
1403    }
1404  }
1405  if ((i == 5 || (lastline < 5 && i == lastline)) && !earlytree) {
1406    if (lastline < 5)
1407      printf("\n                   ");
1408    printf("   Total:%10.5f", -like);
1409    gotlike = -like;
1410  }
1411  if ((i == 7 || (lastline < 7 && i == lastline)) && changed && !earlytree) {
1412    if (lastline < 7)
1413      printf("\n                     ");
1414    if (-like < bestyet) {
1415      printf("     BEST YET!");
1416      bestyet = -like;
1417    } else if (fabs(-like - bestyet) < 0.000001)
1418      printf("     (as good as best)");
1419    else {
1420      if (-like < gotlike)
1421        printf("     better");
1422      else if (-like > gotlike)
1423        printf("     worse!");
1424    }
1425  }
1426  if ((i == 9 || (lastline < 9 && i == lastline)) && !earlytree) {
1427    if (lastline < 9)
1428      printf("\n                       ");
1429    printf("     %3hd characters compatible", compatible);
1430  }
1431  putchar('\n');
1432}  /* drawline */
1433
1434void printree()
1435{
1436  /* prints out diagram of the tree */
1437  short tipy;
1438  short i, rover, dow;
1439
1440  if (!subtree)
1441    nuroot = root;
1442  if (changed || newtree)
1443    evaluate(root);
1444  if (display)
1445    hypstates();
1446  if (ansi || ibmpc)
1447    printf("\033[2J\033[H");
1448  else if (vt52)
1449    printf("\033E\033H");
1450  else
1451    putchar('\n');
1452  tipy = 1;
1453  rover = 100 / spp;
1454  if (rover > overr)
1455    rover = overr;
1456  dow = downn;
1457  if (spp * dow > screenlines && !subtree) {
1458    dow--;
1459    rover--;
1460  }
1461  coordinates(nuroot, &tipy);
1462  for (i = 1; i <= (tipy - dow); i++)
1463    drawline(i, tipy - dow);
1464  if (spp <= screenlines / 2 ||subtree)
1465    putchar('\n');
1466  changed = false;
1467}  /* printree */
1468
1469
1470
1471void arbitree()
1472{
1473  short i;
1474
1475  root = treenode[0];
1476  add(treenode[0], treenode[1], treenode[spp]);
1477  for (i = 3; i <= (spp); i++)
1478    add(treenode[spp + i - 3], treenode[i - 1], treenode[spp + i - 2]);
1479  for (i = 0; i < (nonodes); i++)
1480    intree[i] = true;
1481}  /* arbitree */
1482
1483void yourtree()
1484{
1485  short i, j;
1486  boolean ok;
1487
1488  root = treenode[0];
1489  add(treenode[0], treenode[1], treenode[spp]);
1490  i = 2;
1491  do {
1492    i++;
1493    printree();
1494    printf("Add species%3hd: ", i);
1495    for (j = 0; j < nmlngth; j++)
1496      putchar(nayme[i - 1][j]);
1497    do {
1498      printf("\nbefore node (type number): ");
1499      inpnum(&j, &ok);
1500      ok = (ok && ((j >= 1 && j < i) || (j > spp && j < spp + i - 1)));
1501      if (!ok)
1502        printf("Impossible number. Please try again:\n");
1503    } while (!ok);
1504    add(treenode[j - 1], treenode[i - 1], treenode[spp + i - 2]);
1505  } while (i != spp);
1506  for (i = 0; i < (nonodes); i++)
1507    intree[i] = true;
1508}  /* yourtree */
1509
1510
1511void findch(c)
1512Char c;
1513{
1514  /* scan forward until find character c */
1515  boolean done;
1516
1517  done = false;
1518  while (!(done)) {
1519    if (c == ',') {
1520      if (ch == '(' || ch == ')' || ch == ';') {
1521        printf("\nERROR IN USER TREE: UNMATCHED PARENTHESIS OR MISSING COMMA\n");
1522        exit(-1);
1523      } else if (ch == ',')
1524        done = true;
1525    } else if (c == ')') {
1526      if (ch == '(' || ch == ',' || ch == ';') {
1527        printf("\nERROR IN USER TREE: ");
1528        printf("UNMATCHED PARENTHESIS OR NOT BIFURCATED NODE\n");
1529        exit(-1);
1530      } else {
1531        if (ch == ')')
1532          done = true;
1533      }
1534    } else if (c == ';') {
1535      if (ch != ';') {
1536        printf("\nERROR IN USER TREE: UNMATCHED PARENTHESIS");
1537        printf(" OR MISSING SEMICOLON\n");
1538        exit(-1);
1539      } else
1540        done = true;
1541    }
1542    if ((done && ch == ')') || !(done)) {
1543      if (eoln(treefile)) {
1544        fscanf(treefile, "%*[^\n]");
1545        getc(treefile);
1546      }
1547      ch = getc(treefile);
1548    }
1549  }
1550}  /* findch */
1551
1552void addelement(p, nextnode,lparens,names)
1553node **p;
1554short *nextnode,*lparens;
1555boolean *names;
1556{
1557  /* recursive procedure adds nodes to user-defined tree */
1558  node *q;
1559  short i, n;
1560  boolean found;
1561  Char str[nmlngth];
1562
1563  do {
1564    if (eoln(treefile)) {
1565      fscanf(treefile, "%*[^\n]");
1566      getc(treefile);
1567    }
1568    ch = getc(treefile);
1569  } while (!(ch != ' '));
1570  if (ch == '(' ) {
1571    if ((*lparens) >= spp - 1) {
1572      printf("\nERROR IN USER TREE: TOO MANY LEFT PARENTHESES\n");
1573      exit(-1);
1574    }
1575    (*nextnode)++;
1576    (*lparens)++;
1577    q = treenode[*nextnode - 1];
1578    addelement(&q->next->back, nextnode,lparens,names);
1579    q->next->back->back = q->next;
1580    findch(',');
1581    addelement(&q->next->next->back, nextnode,lparens,names);
1582    q->next->next->back->back = q->next->next;
1583    findch(')');
1584    *p = q;
1585    intree[*nextnode - 1] = true;
1586    return;
1587  }
1588  for (i = 0; i < nmlngth; i++)
1589    str[i] = ' ';
1590  n = 1;
1591  do {
1592    if (ch == '_')
1593      ch = ' ';
1594    str[n - 1] = ch;
1595    if (eoln(treefile)) {
1596      fscanf(treefile, "%*[^\n]");
1597      getc(treefile);
1598    }
1599    ch = getc(treefile);
1600    n++;
1601  } while (ch != ',' && ch != ')' && ch != ':' && n <= nmlngth);
1602  n = 1;
1603  do {
1604    found = true;
1605    for (i = 0; i < nmlngth; i++)
1606      found = (found && str[i] == nayme[n - 1][i]);
1607    if (found) {
1608      if (names[n - 1] == false) {
1609        *p = treenode[n - 1];
1610        intree[n - 1] = true;
1611        names[n - 1] = true;
1612      } else {
1613        printf("\nERROR IN USER TREE: DUPLICATE NAME FOUND -- ");
1614        for (i = 0; i < nmlngth; i++)
1615          putchar(nayme[n - 1][i]);
1616        putchar('\n');
1617        exit(-1);
1618      }
1619    } else
1620      n++;
1621  } while (!(n > spp || found));
1622  if (n <= spp)
1623    return;
1624  printf("CANNOT FIND SPECIES: ");
1625  for (i = 0; i < nmlngth; i++)
1626    putchar(str[i]);
1627  putchar('\n');
1628}  /* addelement */
1629
1630void treeread()
1631{
1632  /* read in user-defined tree and set it up */
1633  /* Local variables for treeread:           */
1634  short nextnode, lparens;
1635  boolean *names;
1636  short i;
1637
1638  openfile(&treefile,TREEFILE,"r",progname,trfilename);
1639
1640  root = treenode[spp];
1641  nextnode = spp;
1642  root->back = NULL;
1643  for (i = 0; i < nonodes; i++)
1644    intree[i] = false;
1645  names = (boolean *)Malloc(spp*sizeof(boolean));
1646  for (i = 0; i < spp; i++)
1647    names[i] = false;
1648  lparens = 0;
1649  addelement(&root, &nextnode,&lparens,names);
1650  findch(';');
1651  FClose(treefile);
1652#ifdef MAC
1653   fixmacfile(trfilename);
1654#endif
1655  free(names);
1656}  /* treeread */
1657
1658void buildtree()
1659{
1660
1661  changed = false;
1662  newtree = false;
1663  switch (how) {
1664
1665  case arb:
1666    arbitree();
1667    break;
1668
1669  case use:
1670    treeread();
1671    break;
1672
1673  case spec:
1674    yourtree();
1675    break;
1676  }
1677  outgrno = root->next->back->index;
1678  if (intree[outgrno - 1])
1679    reroot(treenode[outgrno - 1]);
1680}  /* buildtree */
1681
1682
1683void help()
1684{
1685  /* display help information */
1686  printf("\n\nR Rearrange a tree by moving a node or group\n");
1687  printf("# Show the states of the next char. that doesn't fit tree\n");
1688  printf("+ Show the states of the next character\n");
1689  printf("-         ...     of the previous character\n");
1690  printf("S Show the states of a given character\n");
1691  printf(". redisplay the same tree again\n");
1692  printf("T Try all possible positions of a node or group\n");
1693  printf("U Undo the most recent rearrangement\n");
1694  printf("W Write tree to a file\n");
1695  printf("O select an Outgroup for the tree\n");
1696  printf("F Flip (rotate) branches at a node\n");
1697  printf("C show only one Clade (subtree) (useful if tree is too big)\n");
1698  printf("H Help (this screen)\n");
1699  printf("?  \"     \"      \"   \n");
1700  printf("Q (Quit) Exit from program\n");
1701  printf("X Exit from program\n\n\n");
1702  printf("TO CONTINUE, PRESS ON THE Return OR Enter KEY");
1703  scanf("%c%*[^\n]", &ch);
1704  getchar();
1705  printree();
1706}  /* help */
1707
1708void rearrange()
1709{
1710  short i, j;
1711  boolean ok1, ok2;
1712  node *p, *q;
1713
1714  printf("Remove everything to the right of which node? ");
1715  inpnum(&i, &ok1);
1716  ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index);
1717  if (ok1) {
1718    printf("Add before which node? ");
1719    inpnum(&j, &ok2);
1720    ok2 = (ok2 && j >= 1 && j < spp * 2);
1721    if (ok2) {
1722      ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]);
1723      p = treenode[j - 1];
1724      while (p != root) {
1725        ok2 = (ok2 && p != treenode[i - 1]);
1726        p = treenode[p->back->index - 1];
1727      }
1728      if (ok1 && ok2) {
1729        what = i;
1730        q = treenode[treenode[i - 1]->back->index - 1];
1731        if (q->next->back->index == i)
1732          fromwhere = q->next->next->back->index;
1733        else
1734          fromwhere = q->next->back->index;
1735        towhere = j;
1736        re_move(&treenode[i - 1], &q);
1737        add(treenode[j - 1], treenode[i - 1], q);
1738      }
1739      lastop = rearr;
1740    }
1741  }
1742  changed = (ok1 && ok2);
1743  printree();
1744  if (!(ok1 && ok2))
1745    printf("Not a possible rearrangement.  Try again: \n");
1746  else {
1747    oldwritten = written;
1748    written = false;
1749  }
1750}  /* rearrange */
1751
1752void nextinc()
1753{
1754  /* show next incompatible character */
1755  short disp0;
1756  boolean done;
1757
1758  display = true;
1759  disp0 = dispchar;
1760  done = false;
1761  do {
1762    dispchar++;
1763    if (dispchar > chars) {
1764      dispchar = 1;
1765      done = (disp0 == 0);
1766    }
1767  } while (!(numsteps[dispchar - 1] >
1768             weight[dispchar - 1] ||
1769             dispchar == disp0 || done));
1770  dispword = (dispchar - 1) / bits + 1;
1771  dispbit = (dispchar - 1) % bits + 1;
1772  printree();
1773}  /* nextinc */
1774
1775void nextchar()
1776{
1777  /* show next character */
1778  display = true;
1779  dispchar++;
1780  if (dispchar > chars)
1781    dispchar = 1;
1782  dispword = (dispchar - 1) / bits + 1;
1783  dispbit = (dispchar - 1) % bits + 1;
1784  printree();
1785}  /* nextchar */
1786
1787void prevchar()
1788{
1789  /* show previous character */
1790  display = true;
1791  dispchar--;
1792  if (dispchar < 1)
1793    dispchar = chars;
1794  dispword = (dispchar - 1) / bits + 1;
1795  dispbit = (dispchar - 1) % bits + 1;
1796  printree();
1797}  /* prevchar */
1798
1799void show()
1800{
1801  short i;
1802  boolean ok;
1803
1804  do {
1805    printf("SHOW: (Character number or 0 to see none)? ");
1806    inpnum(&i, &ok);
1807    ok = (ok && (i == 0 || (i >= 1 && i <= chars)));
1808    if (ok && i != 0) {
1809      display = true;
1810      dispchar = i;
1811      dispword = (i - 1) / bits + 1;
1812      dispbit = (i - 1) % bits + 1;
1813    }
1814    if (ok && i == 0)
1815      display = false;
1816  } while (!ok);
1817  printree();
1818}  /* show */
1819
1820void tryadd(p, item,nufork,place)
1821node *p,**item,**nufork;
1822double *place;
1823{
1824  /* temporarily adds one fork and one tip to the tree.
1825    Records scores in ARRAY place */
1826  add(p, *item, *nufork);
1827  evaluate(root);
1828  place[p->index - 1] = -like;
1829  re_move(item, nufork);
1830}  /* tryadd */
1831
1832void addpreorder(p, item_, nufork_, place)
1833node *p, *item_, *nufork_;
1834double *place;
1835{
1836  /* traverses a binary tree, calling PROCEDURE tryadd
1837    at a node before calling tryadd at its descendants */
1838  node *item, *nufork;
1839
1840
1841  item = item_;
1842  nufork = nufork_;
1843  if (p == NULL)
1844    return;
1845  tryadd(p, &item,&nufork,place);
1846  if (!p->tip) {
1847    addpreorder(p->next->back, item,nufork,place);
1848    addpreorder(p->next->next->back,item,nufork,place);
1849  }
1850}  /* addpreorder */
1851
1852void try()
1853{
1854  /* Remove node, try it in all possible places */
1855/* Local variables for try: */
1856  double *place;
1857  short i, j, oldcompat;
1858  double current;
1859  node *q, *dummy, *rute;
1860  boolean tied, better, ok;
1861
1862  printf("Try other positions for which node? ");
1863  inpnum(&i, &ok);
1864  if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
1865    printf("Not a possible choice! ");
1866    return;
1867  }
1868  printf("WAIT ...\n");
1869  place = (double *)Malloc(nonodes*sizeof(double));
1870  for (j = 0; j < (nonodes); j++)
1871    place[j] = -1.0;
1872  evaluate(root);
1873  current = -like;
1874  oldcompat = compatible;
1875  what = i;
1876  q = treenode[treenode[i - 1]->back->index - 1];
1877  if (q->next->back->index == i)
1878    fromwhere = q->next->next->back->index;
1879  else
1880    fromwhere = q->next->back->index;
1881  rute = root;
1882  if (root->index == treenode[i - 1]->back->index) {
1883    if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
1884      rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
1885    else
1886      rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
1887  }
1888  re_move(&treenode[i - 1], &dummy);
1889  oldleft = wasleft;
1890  root = rute;
1891  addpreorder(root, treenode[i - 1], dummy, place);
1892  wasleft = oldleft;
1893  restoring = true;
1894  add(treenode[fromwhere - 1], treenode[what - 1],
1895      dummy);
1896  like = -current;
1897  compatible = oldcompat;
1898  restoring = false;
1899  better = false;
1900  printf("       BETTER: ");
1901  for (j = 1; j <= (nonodes); j++) {
1902    if (place[j - 1] < current && place[j - 1] >= 0.0) {
1903      printf("%3hd:%6.2f", j, place[j - 1]);
1904      better = true;
1905    }
1906  }
1907  if (!better)
1908    printf(" NONE");
1909  printf("\n       TIED:    ");
1910  tied = false;
1911  for (j = 1; j <= (nonodes); j++) {
1912    if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
1913      if (j < 10)
1914        printf("%2hd", j);
1915      else
1916        printf("%3hd", j);
1917      tied = true;
1918    }
1919  }
1920  if (tied)
1921    printf(":%6.2f\n", current);
1922  else
1923    printf("NONE\n");
1924  changed = true;
1925  free(place);
1926}  /* try */
1927
1928void undo()
1929{
1930  /* restore to tree before last rearrangement */
1931  short temp;
1932  boolean btemp;
1933  node *q;
1934
1935  switch (lastop) {
1936
1937  case rearr:
1938    restoring = true;
1939    oldleft = wasleft;
1940    re_move(&treenode[what - 1], &q);
1941    btemp = wasleft;
1942    wasleft = oldleft;
1943    add(treenode[fromwhere - 1], treenode[what - 1],q);
1944    wasleft = btemp;
1945    restoring = false;
1946    temp = fromwhere;
1947    fromwhere = towhere;
1948    towhere = temp;
1949    changed = true;
1950    break;
1951
1952  case flipp:
1953    q = treenode[atwhat - 1]->next->back;
1954    treenode[atwhat - 1]->next->back =
1955      treenode[atwhat - 1]->next->next->back;
1956    treenode[atwhat - 1]->next->next->back = q;
1957    treenode[atwhat - 1]->next->back->back = treenode[atwhat - 1]->next;
1958    treenode[atwhat - 1]->next->next->back->back =
1959      treenode[atwhat - 1]->next->next;
1960    break;
1961
1962  case reroott:
1963    restoring = true;
1964    temp = oldoutgrno;
1965    oldoutgrno = outgrno;
1966    outgrno = temp;
1967    reroot(treenode[outgrno - 1]);
1968    restoring = false;
1969    break;
1970
1971  case none:
1972    /* blank case */
1973    break;
1974  }
1975  printree();
1976  if (lastop == none) {
1977    printf("No operation to undo! ");
1978    return;
1979  }
1980  btemp = oldwritten;
1981  oldwritten = written;
1982  written = btemp;
1983}  /* undo */
1984
1985void treeout(p)
1986node *p;
1987{
1988  /* write out file with representation of final tree */
1989  short i, n;
1990  Char c;
1991
1992  if (p->tip) {
1993    n = 0;
1994    for (i = 1; i <= nmlngth; i++) {
1995      if (nayme[p->index - 1][i - 1] != ' ')
1996        n = i;
1997    }
1998    for (i = 0; i < n; i++) {
1999      c = nayme[p->index - 1][i];
2000      if (c == ' ')
2001        c = '_';
2002      putc(c, treefile);
2003    }
2004    col += n;
2005  } else {
2006    putc('(', treefile);
2007    col++;
2008    treeout(p->next->back);
2009    putc(',', treefile);
2010    col++;
2011    if (col > 65) {
2012      putc('\n', treefile);
2013      col = 0;
2014    }
2015    treeout(p->next->next->back);
2016    putc(')', treefile);
2017    col++;
2018  }
2019  if (p == root)
2020    fprintf(treefile, ";\n");
2021}  /* treeout */
2022
2023void treewrite(done)
2024boolean done;
2025{
2026  /* write out tree to a file */
2027  Char ch;
2028
2029  if (waswritten) {   /*MIPS*/
2030    printf("Tree file already was open.\n");
2031    printf("   A   Add to this tree to tree file\n");
2032    printf("   R   Replace tree file contents by this tree\n");
2033    printf("   F   Write out tree to a different tree file\n");
2034    printf("   N   Do Not write out this tree\n");
2035    do {
2036      printf("Which should we do? ");
2037      scanf("%c%*[^\n]", &ch);
2038      getchar();
2039      uppercase(&ch);
2040    } while (ch != 'A' && ch != 'R' && ch != 'N' && ch != 'F');
2041  }
2042  if (ch == 'F'){
2043    trfilename[0] = '\0';
2044    while (trfilename[0] =='\0'){
2045      printf("Please enter a tree file name>");
2046      gets(trfilename);}
2047  }
2048  if (ch == 'R' || ch == 'A' || ch == 'F' || !waswritten){
2049    openfile(&treefile,trfilename,(ch == 'A' && waswritten) ? "a" : "w",
2050             progname,trfilename);
2051  }
2052
2053  if (!done)
2054    printree();
2055  if (waswritten && ch == 'N')
2056    return;
2057  col = 0;
2058  treeout(root);
2059  printf("\nTree written to file\n\n");
2060  waswritten = true;
2061  written = true;
2062  FClose(treefile);
2063#ifdef MAC
2064  fixmacfile(trfilename);
2065#endif
2066}  /* treewrite */
2067
2068void clade()
2069{
2070  /* pick a subtree and show only that on screen */
2071  short i;
2072  boolean ok;
2073
2074  printf("Select subtree rooted at which node (0 for whole tree)? ");
2075  inpnum(&i, &ok);
2076  ok = (ok && (unsigned)i <= nonodes);
2077  if (ok) {
2078    subtree = (i > 0);
2079    if (subtree)
2080      nuroot = treenode[i - 1];
2081    else
2082      nuroot = root;
2083  }
2084  printree();
2085  if (!ok)
2086    printf("Not possible to use this node. ");
2087}  /* clade */
2088
2089void flip()
2090{
2091  /* flip at a node left-right */
2092  short i;
2093  boolean ok;
2094  node *p;
2095
2096  printf("Flip branches at which node? ");
2097  inpnum(&i, &ok);
2098  ok = (ok && i > spp && i <= nonodes);
2099  if (ok) {
2100    p = treenode[i - 1]->next->back;
2101    treenode[i - 1]->next->back = treenode[i - 1]->next->next->back;
2102    treenode[i - 1]->next->next->back = p;
2103    treenode[i - 1]->next->back->back = treenode[i - 1]->next;
2104    treenode[i - 1]->next->next->back->back = treenode[i - 1]->next->next;
2105    atwhat = i;
2106    lastop = flipp;
2107  }
2108  printree();
2109  if (ok) {
2110    oldwritten = written;
2111    written = false;
2112    return;
2113  }
2114  if (i >= 1 && i <= spp)
2115    printf("Can't flip there. ");
2116  else
2117    printf("No such node. ");
2118}  /* flip */
2119
2120void changeoutgroup()
2121{
2122  short i;
2123  boolean ok;
2124
2125  oldoutgrno = outgrno;
2126  do {
2127    printf("Which node should be the new outgroup? ");
2128    inpnum(&i, &ok);
2129    ok = (ok && intree[i - 1] && i >= 1 && i <= nonodes &&
2130          i != root->index);
2131    if (ok)
2132      outgrno = i;
2133  } while (!ok);
2134  if (intree[outgrno - 1])
2135    reroot(treenode[outgrno - 1]);
2136  changed = true;
2137  lastop = reroott;
2138  printree();
2139  oldwritten = written;
2140  written = false;
2141}  /* changeoutgroup */
2142
2143void redisplay()
2144{
2145/* Local variables for redisplay: */
2146  boolean done;
2147
2148  done = false;
2149  waswritten = false;
2150  do {
2151    printf("NEXT? (Options: R # + - S . T U W O F C H ? X Q) ");
2152    printf("(H or ? for Help) ");
2153    scanf("%c%*[^\n]", &ch);
2154    getchar();
2155    uppercase(&ch);
2156    if (strchr("RSWH#.O?+TFX-UCQ",ch)){
2157      switch (ch) {
2158
2159      case 'R':
2160        rearrange();
2161        break;
2162
2163      case '#':
2164        nextinc();
2165        break;
2166
2167      case '+':
2168        nextchar();
2169        break;
2170
2171      case '-':
2172        prevchar();
2173        break;
2174
2175      case 'S':
2176        show();
2177        break;
2178
2179      case '.':
2180        printree();
2181        break;
2182
2183      case 'T':
2184        try();
2185        break;
2186
2187      case 'U':
2188        undo();
2189        break;
2190
2191      case 'W':
2192        treewrite(done);
2193        break;
2194
2195      case 'O':
2196        changeoutgroup();
2197        break;
2198
2199      case 'F':
2200        flip();
2201        break;
2202
2203      case 'C':
2204        clade();
2205        break;
2206
2207      case 'H':
2208        help();
2209        break;
2210
2211      case '?':
2212        help();
2213        break;
2214
2215      case 'X':
2216        done = true;
2217        break;
2218
2219      case 'Q':
2220        done = true;
2221        break;
2222      }
2223    }
2224  } while (!done);
2225  if (!written) {
2226    do {
2227      printf("Do you want to write out the tree to a file? (Y or N) ");
2228      scanf("%c%*[^\n]", &ch);
2229      getchar();
2230    } while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n');
2231  }
2232  if (ch == 'Y' || ch == 'y')
2233    treewrite(done);
2234}  /* redisplay */
2235
2236
2237void treeconstruct()
2238{
2239  /* constructs a binary tree from the pointers in treenode. */
2240
2241  restoring = false;
2242  subtree = false;
2243  display = false;
2244  dispchar = 0;
2245  fullset = (1L << (bits + 1)) - (1L << 1);
2246  guess = (Char *)Malloc(chars*sizeof(Char));
2247  numsteps = (steptr)Malloc(chars*sizeof(short));
2248  earlytree = true;
2249  buildtree();
2250  waswritten = false;
2251  printf("\nComputing steps needed for compatibility in sites ...\n\n");
2252  newtree = true;
2253  earlytree = false;
2254  printree();
2255  bestyet = -like;
2256  gotlike = -like;
2257  lastop = none;
2258  newtree = false;
2259  written = false;
2260  lastop = none;
2261  redisplay();
2262}  /* treeconstruct */
2263
2264
2265main(argc, argv)
2266int argc;
2267Char *argv[];
2268{  /* Interactive Dollo/polymorphism parsimony */
2269  /* reads in spp, chars, and the data. Then calls treeconstruct to
2270    construct the tree and query the user */
2271#ifdef MAC
2272  macsetup("Dolmove","");
2273#endif
2274  strcpy(progname,argv[0]);
2275  strcpy(infilename,INFILE);
2276  strcpy(trfilename,TREEFILE);
2277
2278  openfile(&infile,infilename,"r",argv[0],infilename);
2279
2280  screenlines = 24;
2281  ibmpc = ibmpc0;
2282  ansi = ansi0;
2283  vt52 = vt520;
2284  doinput();
2285  configure();
2286  treeconstruct();
2287  if (waswritten) {
2288    FClose(treefile);
2289#ifdef MAC
2290    fixmacfile(trfilename);
2291#endif
2292  }
2293  FClose(infile);
2294  exit(0);
2295}  /* Interactive Dollo/polymorphism parsimony */
2296
2297
2298
2299int eof(f)
2300FILE *f;
2301{
2302    register int ch;
2303
2304    if (feof(f))
2305        return 1;
2306    if (f == stdin)
2307        return 0;
2308    ch = getc(f);
2309    if (ch == EOF)
2310        return 1;
2311    ungetc(ch, f);
2312    return 0;
2313}
2314
2315
2316int eoln(f)
2317FILE *f;
2318{
2319    register int ch;
2320
2321    ch = getc(f);
2322    if (ch == EOF)
2323        return 1;
2324    ungetc(ch, f);
2325    return (ch == '\n');
2326}
2327
2328void memerror()
2329{
2330printf("Error allocating memory\n");
2331exit(-1);
2332}
2333
2334MALLOCRETURN *mymalloc(x)
2335long x;
2336{
2337MALLOCRETURN *mem;
2338mem = (MALLOCRETURN *)malloc(x);
2339if (!mem)
2340  memerror();
2341else
2342  return (MALLOCRETURN *)mem;
2343}
2344
Note: See TracBrowser for help on using the repository browser.