source: branches/profile/GDE/PHYLIP/dolmove.c

Last change on this file was 2175, checked in by westram, 20 years ago

upgrade to PHYLIP 3.6

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.2 KB
Line 
1#include "phylip.h"
2#include "moves.h"
3#include "disc.h"
4#include "dollo.h"
5
6/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
7   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
8   Permission is granted to copy and use this program provided no fee is
9   charged for it and provided that this copyright notice is not removed. */
10
11#define overr           4
12#define which           1
13
14typedef enum {
15  horiz, vert, up, overt, upcorner, downcorner, onne, zerro, question, polym
16} chartype;
17
18typedef enum {  rearr, flipp, reroott, none } rearrtype;
19
20typedef enum {
21  arb, use, spec
22} howtree;
23
24#ifndef OLDC
25/* function prototypes */
26void   getoptions(void);
27void   inputoptions(void);
28void   allocrest(void);
29void   doinput(void);
30void   configure(void);
31void   prefix(chartype);
32void   postfix(chartype);
33void   makechar(chartype);
34void   dolmove_correct(node *);
35void   dolmove_count(node *);
36
37void   preorder(node *);
38void   evaluate(node *);
39void   reroot(node *);
40void   dolmove_hyptrav(node *);
41void   dolmove_hypstates(void);
42void   grwrite(chartype, long, long *);
43void   dolmove_drawline(long);
44void   dolmove_printree(void);
45void   arbitree(void);
46void   yourtree(void);
47               
48void   initdolmovenode(node **, node **, node *, long, long, long *,
49        long *, initops, pointarray, pointarray, Char *, Char *, FILE *);
50void   buildtree(void);
51void   rearrange(void);
52void   tryadd(node *, node **, node **, double *);
53void   addpreorder(node *, node *, node *, double *);
54void   try(void);
55void   undo(void);
56void   treewrite(boolean);
57void   clade(void);
58void   flip(void);
59
60void   changeoutgroup(void);
61void   redisplay(void);
62void   treeconstruct(void);
63/* function prototypes */
64#endif
65
66Char infilename[FNMLNGTH],intreename[FNMLNGTH],outtreename[FNMLNGTH], ancfilename[FNMLNGTH], factfilename[FNMLNGTH], weightfilename[FNMLNGTH];
67node *root;
68long outgrno, col, screenlines, screenwidth, scrollinc,treelines,
69        leftedge,topedge,vmargin,hscroll,vscroll,farthest;
70/* outgrno indicates outgroup */
71boolean weights, thresh, ancvar, questions, dollo, factors,
72               waswritten;
73boolean *ancone, *anczero, *ancone0, *anczero0;
74Char *factor;
75pointptr treenode;   /* pointers to all nodes in tree */
76double threshold;
77double *threshwt;
78unsigned char cha[10];
79boolean reversed[10];
80boolean graphic[10];
81howtree how;
82char *progname;
83char ch;
84
85/* Variables for treeread */
86boolean usertree, goteof, firsttree, haslengths;
87pointarray nodep;
88node *grbg;
89long *zeros;
90
91/* Local variables for treeconstruct, propagated globally for c version: */
92long dispchar, dispword, dispbit, atwhat, what, fromwhere, towhere,
93  oldoutgrno, compatible;
94double like, bestyet, gotlike;
95Char *guess;
96boolean display, newtree, changed, subtree, written, oldwritten, restoring,
97  wasleft, oldleft, earlytree;
98boolean *in_tree;
99steptr numsteps;
100long fullset;
101bitptr zeroanc, oneanc;
102node *nuroot;
103rearrtype lastop;
104steptr numsone, numszero;
105boolean *names;
106
107
108void getoptions()
109{
110  /* interactively set options */
111  long loopcount;
112  Char ch;
113  boolean done, gotopt;
114  char input[100];
115
116  how = arb;
117  usertree = false;
118  goteof = false;
119  thresh = false;
120  threshold = spp;
121  weights = false;
122  ancvar = false;
123  factors = false;
124  dollo = true;
125  loopcount = 0;
126  do {
127    cleerhome();
128    printf("\nInteractive Dollo or polymorphism parsimony,");
129    printf(" version %s\n\n",VERSION);
130    printf("Settings for this run:\n");
131    printf("  P                        Parsimony method?");
132    printf("  %s\n",(dollo ? "Dollo" : "Polymorphism"));
133    printf("  A                     Use ancestral states?  %s\n",
134           ancvar ? "Yes" : "No");
135    printf("  F                  Use factors information?  %s\n",
136           factors ? "Yes" : "No");
137    printf("  W                           Sites weighted?  %s\n",
138           (weights ? "Yes" : "No"));
139    printf("  T                 Use Threshold parsimony?");
140    if (thresh)
141      printf("  Yes, count steps up to%4.1f\n", threshold);
142    else
143      printf("  No, use ordinary parsimony\n");
144    printf("  A      Use ancestral states in input file?");
145    printf("  %s\n",(ancvar ? "Yes" : "No"));
146    printf("  U Initial tree (arbitrary, user, specify)?");
147    printf("  %s\n",(how == arb) ? "Arbitrary" :
148                    (how == use) ? "User tree from tree file" :
149                                   "Tree you specify");
150    printf("  0      Graphics type (IBM PC, ANSI, none)?  %s\n",
151           ibmpc ? "IBM PC" : ansi  ? "ANSI"   : "(none)");
152    printf("  L               Number of lines on screen?%4ld\n",screenlines);
153    printf("  S                Width of terminal screen?%4ld\n",screenwidth);
154    printf(
155      "\n\nAre these settings correct? (type Y or the letter for one to change)\n");
156#ifdef WIN32
157    phyFillScreenColor();
158#endif
159    getstryng(input);
160    ch = input[0];
161    uppercase(&ch);
162    done = (ch == 'Y');
163    gotopt = (strchr("SFTPULA0W",ch) != NULL) ? true : false;
164    if (gotopt) {
165      switch (ch) {
166
167      case 'A':
168        ancvar = !ancvar;
169        break;
170
171      case 'F':
172        factors = !factors;
173        break;
174
175      case 'W':
176          weights = !weights;
177          break;
178       
179      case 'P':
180        dollo = !dollo;
181        break;
182
183      case 'T':
184        thresh = !thresh;
185        if (thresh)
186          initthreshold(&threshold);
187        break;
188
189      case 'U':
190        if (how == arb)
191          how = use;
192        else if (how == use)
193            how = spec;
194          else
195            how = arb;
196        break;
197
198      case '0':
199        initterminal(&ibmpc, &ansi);
200        break;
201
202      case 'L':
203        initnumlines(&screenlines);
204        break;
205
206      case 'S':
207        screenwidth = readlong("Width of terminal screen (in characters)?\n");
208      }
209    }
210    else 
211      printf("Not a possible option!\n");
212    countup(&loopcount, 100);
213  } while (!done);
214  if (scrollinc < screenwidth / 2.0)
215    hscroll = scrollinc;
216  else
217    hscroll = screenwidth / 2;
218  if (scrollinc < screenlines / 2.0)
219    vscroll = scrollinc;
220  else
221    vscroll = screenlines / 2;
222}  /* getoptions */
223
224
225void inputoptions()
226{
227  /* input the information on the options */
228  long i;
229
230  scan_eoln(infile);
231  for (i = 0; i < (chars); i++)
232      weight[i] = 1;
233  if (ancvar)
234      inputancestorsnew(anczero0, ancone0);
235  if (factors)
236      inputfactorsnew(chars, factor, &factors);
237  if (weights)
238      inputweights(chars, weight, &weights);
239  putchar('\n');
240  if (weights)
241    printweights(stdout, 0, chars, weight, "Characters");
242  if (factors)
243    printfactors(stdout, chars, factor, "");
244  for (i = 0; i < (chars); i++) {
245    if (!ancvar) {
246      anczero[i] = true;
247      ancone[i] = false;
248    } else {
249      anczero[i] = anczero0[i];
250      ancone[i] = ancone0[i];
251    }
252  }
253  if (ancvar)
254    printancestors(stdout, anczero, ancone);
255  if (!thresh)
256    threshold = spp;
257  questions = false;
258  for (i = 0; i < (chars); i++) {
259    questions = (questions || (ancone[i] && anczero[i]));
260    threshwt[i] = threshold * weight[i];
261  }
262}  /* inputoptions */
263
264
265void allocrest()
266{
267  nayme = (naym *)Malloc(spp*sizeof(naym));
268  in_tree = (boolean *)Malloc(nonodes*sizeof(boolean));
269  extras = (steptr)Malloc(chars*sizeof(long));
270  weight = (steptr)Malloc(chars*sizeof(long));
271  numszero = (steptr)Malloc(chars*sizeof(long));
272  numsone = (steptr)Malloc(chars*sizeof(long));
273  threshwt = (double *)Malloc(chars*sizeof(double));
274  factor = (Char *)Malloc(chars*sizeof(Char));
275  ancone = (boolean *)Malloc(chars*sizeof(boolean));
276  anczero = (boolean *)Malloc(chars*sizeof(boolean));
277  ancone0 = (boolean *)Malloc(chars*sizeof(boolean));
278  anczero0 = (boolean *)Malloc(chars*sizeof(boolean));
279  zeroanc = (bitptr)Malloc(words*sizeof(long));
280  oneanc = (bitptr)Malloc(words*sizeof(long));
281}  /* allocrest */
282
283
284void doinput()
285{
286  /* reads the input data */
287
288  inputnumbers(&spp, &chars, &nonodes, 1);
289  words = chars / bits + 1;
290  printf("%2ld species, %3ld characters\n", spp, chars);
291  printf("\nReading input file ...\n\n");
292  getoptions();
293  if (weights)
294      openfile(&weightfile,WEIGHTFILE,"weights file","r",progname,weightfilename);
295  if(ancvar)
296      openfile(&ancfile,ANCFILE,"ancestors file", "r",progname,ancfilename);
297  if(factors)
298      openfile(&factfile,FACTFILE,"factors file", "r",progname,factfilename);
299
300  alloctree(&treenode);
301  setuptree(treenode);
302  allocrest();
303  inputoptions();
304  inputdata(treenode, dollo, false, stdout);
305}  /* doinput */
306
307
308void configure()
309{
310  /* configure to machine -- set up special characters */
311  chartype a;
312
313  for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
314    reversed[(long)a] = false;
315  for (a = horiz; (long)a <= (long)polym; a = (chartype)((long)a + 1))
316    graphic[(long)a] = false;
317  if (ibmpc) {
318    cha[(long)horiz] = 205;
319    graphic[(long)horiz] = true;
320    cha[(long)vert] = 186;
321    graphic[(long)vert] = true;
322    cha[(long)up] = 186;
323    graphic[(long)up] = true;
324    cha[(long)overt] = 205;
325    graphic[(long)overt] = true;
326    cha[(long)onne] = 219;
327    reversed[(long)onne] = true;
328    cha[(long)zerro] = 176;
329    graphic[(long)zerro] = true;
330    cha[(long)question] = 178;   /* or try CHR(177) */
331    cha[(long)polym] = '\001';
332    reversed[(long)polym] = true;
333    cha[(long)upcorner] = 200;
334    graphic[(long)upcorner] = true;
335    cha[(long)downcorner] = 201;
336    graphic[(long)downcorner] = true;
337    graphic[(long)question] = true;
338    return;
339  }
340  if (ansi) {
341    cha[(long)onne] = ' ';
342    reversed[(long)onne] = true;
343    cha[(long)horiz] = cha[(long)onne];
344    reversed[(long)horiz] = true;
345    cha[(long)vert] = cha[(long)onne];
346    reversed[(long)vert] = true;
347    cha[(long)up] = 'x';
348    graphic[(long)up] = true;
349    cha[(long)overt] = 'q';
350    graphic[(long)overt] = true;
351    cha[(long)zerro] = 'a';
352    graphic[(long)zerro] = true;
353    reversed[(long)zerro] = true;
354    cha[(long)question] = '?';
355    cha[(long)question] = '?';
356    reversed[(long)question] = true;
357    cha[(long)polym] = '%';
358    reversed[(long)polym] = true;
359    cha[(long)upcorner] = 'm';
360    graphic[(long)upcorner] = true;
361    cha[(long)downcorner] = 'l';
362    graphic[(long)downcorner] = true;
363    return;
364  }
365  cha[(long)horiz] = '=';
366  cha[(long)vert] = ' ';
367  cha[(long)up] = '!';
368  cha[(long)overt] = '-';
369  cha[(long)onne] = '*';
370  cha[(long)zerro] = '=';
371  cha[(long)question] = '.';
372  cha[(long)polym] = '%';
373  cha[(long)upcorner] = '`';
374  cha[(long)downcorner] = ',';
375}  /* configure */
376
377
378void prefix(chartype a)
379{
380  /* give prefix appropriate for this character */
381  if (reversed[(long)a])
382    prereverse(ansi);
383  if (graphic[(long)a])
384    pregraph(ansi);
385}  /* prefix */
386
387
388void postfix(chartype a)
389{
390  /* give postfix appropriate for this character */
391  if (reversed[(long)a])
392    postreverse(ansi);
393  if (graphic[(long)a])
394    postgraph(ansi);
395}  /* postfix */
396
397
398void makechar(chartype a)
399{
400  /* print out a character with appropriate prefix or postfix */
401  prefix(a);
402  putchar(cha[(long)a]);
403  postfix(a);
404}  /* makechar */
405
406
407void dolmove_correct(node *p)
408{  /* get final states for intermediate nodes */
409  long i;
410  long z0, z1, s0, s1, temp;
411
412  if (p->tip)
413    return;
414  for (i = 0; i < (words); i++) {
415    if (p->back == NULL) {
416      s0 = zeroanc[i];
417      s1 = oneanc[i];
418    } else {
419      s0 = treenode[p->back->index - 1]->statezero[i];
420      s1 = treenode[p->back->index - 1]->stateone[i];
421    }
422    z0 = (s0 & p->statezero[i]) |
423         (p->next->back->statezero[i] & p->next->next->back->statezero[i]);
424    z1 = (s1 & p->stateone[i]) |
425         (p->next->back->stateone[i] & p->next->next->back->stateone[i]);
426    if (dollo) {
427      temp = z0 & (~(zeroanc[i] & z1));
428      z1 &= ~(oneanc[i] & z0);
429      z0 = temp;
430    }
431    temp = fullset & (~z0) & (~z1);
432    p->statezero[i] = z0 | (temp & s0 & (~s1));
433    p->stateone[i] = z1 | (temp & s1 & (~s0));
434  }
435}  /* dolmove_correct */
436
437
438void dolmove_count(node *p)
439{
440  /* counts the number of steps in a fork of the tree.
441    The program spends much of its time in this PROCEDURE */
442  long i, j, l;
443  bitptr steps;
444
445  steps = (bitptr)Malloc(words*sizeof(long));
446  if (dollo) {
447    for (i = 0; i < (words); i++)
448      steps[i] = (treenode[p->back->index - 1]->stateone[i] &
449                  p->statezero[i] & zeroanc[i]) |
450                 (treenode[p->back->index - 1]->statezero[i] &
451                  p->stateone[i] & oneanc[i]);
452  } else {
453    for (i = 0; i < (words); i++)
454      steps[i] = treenode[p->back->index - 1]->stateone[i] &
455                 treenode[p->back->index - 1]->statezero[i] & p->stateone[i] &
456                 p->statezero[i];
457  }
458  j = 1;
459  l = 0;
460  for (i = 0; i < (chars); i++) {
461    l++;
462    if (l > bits) {
463      l = 1;
464      j++;
465    }
466    if (((1L << l) & steps[j - 1]) != 0) {
467      if (((1L << l) & zeroanc[j - 1]) != 0)
468        numszero[i] += weight[i];
469      else
470        numsone[i] += weight[i];
471    }
472  }
473  free(steps);
474}  /* dolmove_count */
475
476
477void preorder(node *p)
478{
479  /* go back up tree setting up and counting interior node
480    states */
481
482  if (!p->tip) {
483    dolmove_correct(p);
484    preorder(p->next->back);
485    preorder(p->next->next->back);
486  }
487  if (p->back != NULL)
488    dolmove_count(p);
489}  /* preorder */
490
491
492void evaluate(node *r)
493{
494  /* Determines the number of losses or polymorphisms needed for a tree.
495     This is the minimum number needed to evolve chars on this tree */
496  long i, stepnum, smaller;
497  double sum;
498  boolean nextcompat, thiscompat, done;
499
500  sum = 0.0;
501  for (i = 0; i < (chars); i++) {
502    numszero[i] = 0;
503    numsone[i] = 0;
504  }
505  for (i = 0; i < (words); i++) {
506    zeroanc[i] = fullset;
507    oneanc[i] = 0;
508  }
509  compatible = 0;
510  nextcompat = true;
511  postorder(r);
512  preorder(r);
513  for (i = 0; i < (words); i++) {
514    zeroanc[i] = 0;
515    oneanc[i] = fullset;
516  }
517  postorder(r);
518  preorder(r);
519  for (i = 0; i < (chars); i++) {
520    smaller = spp * weight[i];
521    numsteps[i] = smaller;
522    if (anczero[i]) {
523      numsteps[i] = numszero[i];
524      smaller = numszero[i];
525    }
526    if (ancone[i] && numsone[i] < smaller)
527      numsteps[i] = numsone[i];
528    stepnum = numsteps[i] + extras[i];
529    if (stepnum <= threshwt[i])
530      sum += stepnum;
531    else
532      sum += threshwt[i];
533    thiscompat = (stepnum <= weight[i]);
534    if (factors) {
535      done = (i + 1 == chars);
536      if (!done)
537        done = (factor[i + 1] != factor[i]);
538      nextcompat = (nextcompat && thiscompat);
539      if (done) {
540        if (nextcompat)
541          compatible += weight[i];
542        nextcompat = true;
543      }
544    } else if (thiscompat)
545      compatible += weight[i];
546    guess[i] = '?';
547    if (!ancone[i] ||
548        (anczero[i] && numszero[i] < numsone[i]))
549      guess[i] = '0';
550    else if (!anczero[i] ||
551             (ancone[i] && numsone[i] < numszero[i]))
552      guess[i] = '1';
553  }
554  like = -sum;
555}  /* evaluate */
556
557
558void reroot(node *outgroup)
559{
560  /* reorients tree, putting outgroup in desired position. */
561  node *p, *q, *newbottom, *oldbottom;
562  boolean onleft;
563
564  if (outgroup->back->index == root->index)
565    return;
566  newbottom = outgroup->back;
567  p = treenode[newbottom->index - 1]->back;
568  while (p->index != root->index) {
569    oldbottom = treenode[p->index - 1];
570    treenode[p->index - 1] = p;
571    p = oldbottom->back;
572  }
573  onleft = (p == root->next);
574  if (restoring)
575    if (!onleft && wasleft){
576      p = root->next->next;
577      q = root->next;
578    } else {
579      p = root->next;
580      q = root->next->next;
581    }
582  else {
583    if (onleft)
584      oldoutgrno = root->next->next->back->index;
585    else
586      oldoutgrno = root->next->back->index;
587    wasleft = onleft;
588    p = root->next;
589    q = root->next->next;
590  }
591  p->back->back = q->back;
592  q->back->back = p->back;
593  p->back = outgroup;
594  q->back = outgroup->back;
595  if (restoring) {
596    if (!onleft && wasleft) {
597      outgroup->back->back = root->next;
598      outgroup->back = root->next->next;
599    } else {
600      outgroup->back->back = root->next->next;
601      outgroup->back = root->next;
602    }
603  } else {
604    outgroup->back->back = root->next->next;
605    outgroup->back = root->next;
606  }
607  treenode[newbottom->index - 1] = newbottom;
608}  /* reroot */
609
610
611void dolmove_hyptrav(node *r)
612{
613  /* compute states at interior nodes for one character */
614  if (!r->tip)
615    dolmove_correct(r);
616  if (((1L << dispbit) & r->stateone[dispword - 1]) != 0) {
617    if (((1L << dispbit) & r->statezero[dispword - 1]) != 0) {
618      if (dollo)
619        r->state = '?';
620      else
621        r->state = 'P';
622    } else
623      r->state = '1';
624  } else {
625    if (((1L << dispbit) & r->statezero[dispword - 1]) != 0)
626      r->state = '0';
627    else
628      r->state = '?';
629  }
630  if (!r->tip) {
631    dolmove_hyptrav(r->next->back);
632    dolmove_hyptrav(r->next->next->back);
633  }
634}  /* dolmove_hyptrav */
635
636
637void dolmove_hypstates()
638{
639  /* fill in and describe states at interior nodes */
640  long i, j, k;
641
642  for (i = 0; i < (words); i++) {
643    zeroanc[i] = 0;
644    oneanc[i] = 0;
645  }
646  for (i = 0; i < (chars); i++) {
647    j = i / bits + 1;
648    k = i % bits + 1;
649    if (guess[i] == '0')
650      zeroanc[j - 1] = ((long)zeroanc[j - 1]) | (1L << k);
651    if (guess[i] == '1')
652      oneanc[j - 1] = ((long)oneanc[j - 1]) | (1L << k);
653  }
654  filltrav(root);
655  dolmove_hyptrav(root);
656}  /* dolmove_hypstates */
657
658
659void grwrite(chartype c, long num, long *pos)
660{
661  int i;
662
663  prefix(c);
664  for (i = 1; i <= num; i++) {
665    if ((*pos) >= leftedge && (*pos) - leftedge + 1 < screenwidth)
666      putchar(cha[(long)c]);
667    (*pos)++;
668  }
669  postfix(c);
670}  /* grwrite */
671
672 
673void dolmove_drawline(long i)
674{
675  /* draws one row of the tree diagram by moving up tree */
676  node *p, *q, *r, *first =NULL, *last =NULL;
677  long n, j, pos;
678  boolean extra, done;
679  Char s, cc;
680  chartype c, d;
681
682  pos = 1;
683  p = nuroot;
684  q = nuroot;
685  extra = false;
686  if (i == (long)p->ycoord && (p == root || subtree)) {
687    c = overt;
688    if (p == root)
689      cc = guess[dispchar - 1];
690    else
691      cc = p->state;
692    if (display) {
693      switch (cc) {
694
695      case '1':
696        c = onne;
697        break;
698
699      case '0':
700        c = zerro;
701        break;
702
703      case '?':
704        c = question;
705        break;
706
707      case 'P':
708        c = polym;
709        break;
710      }
711    }
712   
713    if ((subtree))
714      stwrite("Subtree:", 8, &pos, leftedge, screenwidth);
715    if (p->index >= 100)
716      nnwrite(p->index, 3, &pos, leftedge, screenwidth);
717    else if (p->index >= 10) {
718      grwrite(c, 1, &pos);
719      nnwrite(p->index, 2, &pos, leftedge, screenwidth);
720    } else {
721      grwrite(c, 2, &pos);
722      nnwrite(p->index, 1, &pos, leftedge, screenwidth);
723    }
724    extra = true;
725  } else {
726    if (subtree)
727      stwrite("          ", 10, &pos, leftedge, screenwidth);
728    else
729      stwrite("  ", 2, &pos, leftedge, screenwidth);
730  }
731  do {
732    if (!p->tip) {
733      r = p->next;
734      done = false;
735      do {
736        if (i >= r->back->ymin && i <= r->back->ymax) {
737          q = r->back;
738          done = true;
739        }
740        r = r->next;
741      } while (!(done || r == p));
742      first = p->next->back;
743      r = p->next;
744      while (r->next != p)
745        r = r->next;
746      last = r->back;
747    }
748    done = (p == q);
749    n = (long)p->xcoord - (long)q->xcoord;
750    if (n < 3 && !q->tip)
751      n = 3;
752    if (extra) {
753      n--;
754      extra = false;
755    }
756    if ((long)q->ycoord == i && !done) {
757      if ((long)q->ycoord > (long)p->ycoord)
758        d = upcorner;
759      else
760        d = downcorner;
761      c = overt;
762      s = q->state;
763      if (s == 'P' && p->state != 'P')
764        s = p->state;
765      if (display) {
766        switch (s) {
767
768        case '1':
769          c = onne;
770          break;
771
772        case '0':
773          c = zerro;
774          break;
775
776        case '?':
777          c = question;
778          break;
779
780        case 'P':
781          c = polym;
782          break;
783        }
784        d = c;
785      }
786      if (n > 1) {
787        grwrite(d, 1, &pos);
788        grwrite(c, n - 3, &pos);
789      }
790      if (q->index >= 100)
791        nnwrite(q->index, 3, &pos, leftedge, screenwidth);
792      else if (q->index >= 10) {
793        grwrite(c, 1, &pos);
794        nnwrite(q->index, 2, &pos, leftedge, screenwidth);
795      } else {
796        grwrite(c, 2, &pos);
797        nnwrite(q->index, 1, &pos, leftedge, screenwidth);
798      }
799      extra = true;
800    } else if (!q->tip) {
801      if ((long)last->ycoord > i && (long)first->ycoord < i
802        && i != (long)p->ycoord) {
803        c = up;
804        if (i < (long)p->ycoord)
805          s = p->next->back->state;
806        else
807          s = p->next->next->back->state;
808        if (s == 'P' && p->state != 'P')
809          s = p->state;
810        if (display) {
811          switch (s) {
812
813          case '1':
814            c = onne;
815            break;
816
817          case '0':
818            c = zerro;
819            break;
820
821          case '?':
822            c = question;
823            break;
824
825          case 'P':
826            c = polym;
827            break;
828          }
829        }
830        grwrite(c, 1, &pos);
831        chwrite(' ', n - 1, &pos, leftedge, screenwidth);
832      } else
833        chwrite(' ', n, &pos, leftedge, screenwidth);
834    } else
835      chwrite(' ', n, &pos, leftedge, screenwidth);
836    if (p != q)
837      p = q;
838  } while (!done);
839  if ((long)p->ycoord == i && p->tip) {
840    n = 0;
841    for (j = 1; j <= nmlngth; j++) {
842      if (nayme[p->index - 1][j - 1] != '\0')
843        n = j;
844    }
845    chwrite(':', 1, &pos, leftedge, screenwidth);
846    for (j = 0; j < n; j++)
847      chwrite(nayme[p->index - 1][j], 1, &pos, leftedge, screenwidth);
848  }
849  putchar('\n');
850}  /* dolmove_drawline */
851
852
853void dolmove_printree()
854{
855  /* prints out diagram of the tree */
856  long tipy;
857  long i, dow;
858
859  if (!subtree)
860    nuroot = root;
861  if (changed || newtree)
862    evaluate(root);
863  if (display)
864    dolmove_hypstates();
865  if (ansi || ibmpc)
866    printf("\033[2J\033[H");
867  else
868    putchar('\n');
869  tipy = 1;
870  dow = down;
871  if (spp * dow > screenlines && !subtree)
872    dow--;
873  printf("(unrooted)");
874  if (display) {
875    printf(" ");
876    makechar(onne);
877    printf(":1 ");
878    makechar(question);
879    printf(":? ");
880    makechar(zerro);
881    printf(":0 ");
882    makechar(polym);
883    printf(":0/1");
884  } else
885    printf("                    ");
886  if (!earlytree) {
887    printf("%10.1f Steps", -like);
888  }
889  if (display)
890    printf("  SITE%4ld", dispchar);
891  else
892    printf("         ");
893  if (!earlytree) {
894    printf("  %3ld chars compatible\n", compatible);
895  }
896
897  printf("%-20s",dollo ? "Dollo" : "Polymorphism");
898 
899  if (changed && !earlytree) {
900    if (-like < bestyet) {
901      printf("     BEST YET!");
902      bestyet = -like;
903    } else if (fabs(-like - bestyet) < 0.000001)
904      printf("     (as good as best)");
905    else {
906      if (-like < gotlike)
907        printf("     better");
908      else if (-like > gotlike)
909        printf("     worse!");
910    }
911  }
912  printf("\n");
913  farthest = 0;
914  coordinates(nuroot, &tipy, 1.5, &farthest);
915  vmargin = 5;
916  treelines = tipy - dow;
917  if (topedge != 1){
918        printf("** %ld lines above screen **\n", topedge - 1);
919    vmargin++;}
920  if ((treelines - topedge + 1) > (screenlines - vmargin))
921    vmargin++;
922  for (i = 1; i <= treelines; i++) {
923    if (i >= topedge && i < topedge + screenlines - vmargin)
924      dolmove_drawline(i);
925  }
926  if ((treelines - topedge + 1) > (screenlines - vmargin)) 
927    printf("** %ld lines below screen **\n",
928           treelines - (topedge - 1 + screenlines - vmargin));
929  if (treelines - topedge + vmargin + 1 < screenlines)
930    putchar('\n');
931  gotlike = -like;
932  changed = false;
933}  /* dolmove_printree */
934
935
936void arbitree()
937{
938  long i;
939
940  root = treenode[0];
941  add2(treenode[0], treenode[1], treenode[spp], &root, restoring, wasleft,
942         treenode);
943  for (i = 3; i <= (spp); i++)
944    add2(treenode[spp + i - 3], treenode[i - 1], treenode[spp + i - 2], &root,
945      restoring, wasleft, treenode);
946  for (i = 0; i < (nonodes); i++)
947    in_tree[i] = true;
948}  /* arbitree */
949
950
951void yourtree()
952{
953  long i, j;
954  boolean ok;
955
956  root = treenode[0];
957  add2(treenode[0], treenode[1], treenode[spp], &root, restoring, wasleft,
958         treenode);
959  i = 2;
960  do {
961    i++;
962    dolmove_printree();
963    printf("Add species%3ld: ", i);
964    for (j = 0; j < nmlngth; j++)
965      putchar(nayme[i - 1][j]);
966    do {
967      printf("\nbefore node (type number): ");
968      inpnum(&j, &ok);
969      ok = (ok && ((j >= 1 && j < i) || (j > spp && j < spp + i - 1)));
970      if (!ok)
971        printf("Impossible number. Please try again:\n");
972    } while (!ok);
973    add2(treenode[j - 1], treenode[i - 1], treenode[spp + i - 2], &root,
974      restoring, wasleft, treenode);
975  } while (i != spp);
976  for (i = 0; i < (nonodes); i++)
977    in_tree[i] = true;
978}  /* yourtree */
979
980
981void initdolmovenode(node **p, node **grbg, node *q, long len, long nodei,
982                        long *ntips, long *parens, initops whichinit,
983                        pointarray treenode, pointarray nodep, Char *str, Char *ch,
984                        FILE *intree)
985{
986  /* initializes a node */
987  /* LM 7/27  I added this function and the commented lines around */
988  /* treeread() to get the program running, but all 4 move programs*/
989  /* are improperly integrated into the v4.0 support files.  As is */
990  /* this is a patchwork function                                   */
991  boolean minusread;
992  double valyew, divisor;
993
994  switch (whichinit) {
995  case bottom:
996    gnutreenode(grbg, p, nodei, chars, zeros);
997    treenode[nodei - 1] = *p;
998    break;
999  case nonbottom:
1000    gnutreenode(grbg, p, nodei, chars, zeros);
1001    break;
1002  case tip:
1003    match_names_to_data (str, treenode, p, spp);
1004    break;
1005  case length:
1006    processlength(&valyew, &divisor, ch, &minusread, intree, parens);
1007    /* process lengths and discard */
1008  default:      /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
1009    break;      /*length should never occur                      */
1010  }
1011} /* initdolmovenode */
1012
1013
1014void buildtree()
1015{
1016  long i, j, nextnode;
1017  node *p;
1018
1019  changed = false;
1020  newtree = false;
1021  switch (how) {
1022
1023  case arb:
1024    arbitree();
1025    break;
1026
1027  case use:
1028    openfile(&intree,INTREE,"input tree file", "r",progname,intreename);
1029    names = (boolean *)Malloc(spp*sizeof(boolean));
1030    firsttree = true;                       /**/
1031    nodep = NULL;                           /**/
1032    nextnode = 0;                           /**/
1033    haslengths = 0;                         /**/
1034    zeros = (long *)Malloc(chars*sizeof(long));         /**/
1035    for (i = 0; i < chars; i++)             /**/
1036      zeros[i] = 0;                         /**/
1037    treeread(intree, &root, treenode, &goteof, &firsttree,
1038                nodep, &nextnode, &haslengths,
1039                &grbg, initdolmovenode); /*debug*/
1040    for (i = spp; i < (nonodes); i++) {
1041      p = treenode[i];
1042      for (j = 1; j <= 3; j++) {
1043        p->stateone = (bitptr)Malloc(words*sizeof(long));
1044        p->statezero = (bitptr)Malloc(words*sizeof(long));
1045        p = p->next;
1046      }
1047    } /* debug: see comment at initdolmovenode() */
1048
1049    /*treeread(which, ch, &root, treenode, names);*/
1050    for (i = 0; i < (spp); i++)
1051      in_tree[i] = names[i];
1052    free(names);
1053    FClose(intree);
1054    break;
1055
1056  case spec:
1057    yourtree();
1058    break;
1059  }
1060  outgrno = root->next->back->index;
1061  if (in_tree[outgrno - 1])
1062    reroot(treenode[outgrno - 1]);
1063}  /* buildtree */
1064
1065
1066void rearrange()
1067{
1068  long i, j;
1069  boolean ok1, ok2;
1070  node *p, *q;
1071
1072  printf("Remove everything to the right of which node? ");
1073  inpnum(&i, &ok1);
1074  ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index);
1075  if (ok1) {
1076    printf("Add before which node? ");
1077    inpnum(&j, &ok2);
1078    ok2 = (ok2 && j >= 1 && j < spp * 2);
1079    if (ok2) {
1080      ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]);
1081      p = treenode[j - 1];
1082      while (p != root) {
1083        ok2 = (ok2 && p != treenode[i - 1]);
1084        p = treenode[p->back->index - 1];
1085      }
1086      if (ok1 && ok2) {
1087        what = i;
1088        q = treenode[treenode[i - 1]->back->index - 1];
1089        if (q->next->back->index == i)
1090          fromwhere = q->next->next->back->index;
1091        else
1092          fromwhere = q->next->back->index;
1093        towhere = j;
1094        re_move2(&treenode[i - 1], &q, &root, &wasleft, treenode);
1095        add2(treenode[j - 1], treenode[i - 1], q, &root, restoring, wasleft, treenode);
1096      }
1097      lastop = rearr;
1098    }
1099  }
1100  changed = (ok1 && ok2);
1101  dolmove_printree();
1102  if (!(ok1 && ok2))
1103    printf("Not a possible rearrangement.  Try again: \n");
1104  else {
1105    oldwritten = written;
1106    written = false;
1107  }
1108}  /* rearrange */
1109
1110
1111void tryadd(node *p, node **item, node **nufork, double *place)
1112{
1113  /* temporarily adds one fork and one tip to the tree.
1114    Records scores in ARRAY place */
1115  add2(p, *item, *nufork, &root, restoring, wasleft, treenode);
1116  evaluate(root);
1117  place[p->index - 1] = -like;
1118  re_move2(item, nufork, &root, &wasleft, treenode);
1119}  /* tryadd */
1120
1121
1122void addpreorder(node *p, node *item_, node *nufork_, double *place)
1123{
1124  /* traverses a binary tree, calling PROCEDURE tryadd
1125    at a node before calling tryadd at its descendants */
1126  node *item, *nufork;
1127
1128
1129  item = item_;
1130  nufork = nufork_;
1131  if (p == NULL)
1132    return;
1133  tryadd(p, &item,&nufork,place);
1134  if (!p->tip) {
1135    addpreorder(p->next->back, item,nufork,place);
1136    addpreorder(p->next->next->back,item,nufork,place);
1137  }
1138}  /* addpreorder */
1139
1140
1141void try()
1142{
1143  /* Remove node, try it in all possible places */
1144  double *place;
1145  long i, j, oldcompat;
1146  double current;
1147  node *q, *dummy, *rute;
1148  boolean tied, better, ok;
1149
1150  printf("Try other positions for which node? ");
1151  inpnum(&i, &ok);
1152  if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
1153    printf("Not a possible choice! ");
1154    return;
1155  }
1156  printf("WAIT ...\n");
1157  place = (double *)Malloc(nonodes*sizeof(double));
1158  for (j = 0; j < (nonodes); j++)
1159    place[j] = -1.0;
1160  evaluate(root);
1161  current = -like;
1162  oldcompat = compatible;
1163  what = i;
1164  q = treenode[treenode[i - 1]->back->index - 1];
1165  if (q->next->back->index == i)
1166    fromwhere = q->next->next->back->index;
1167  else
1168    fromwhere = q->next->back->index;
1169  rute = root;
1170  if (root->index == treenode[i - 1]->back->index) {
1171    if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
1172      rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
1173    else
1174      rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
1175  }
1176  re_move2(&treenode[i - 1], &dummy, &root, &wasleft, treenode);
1177  oldleft = wasleft;
1178  root = rute;
1179  addpreorder(root, treenode[i - 1], dummy, place);
1180  wasleft = oldleft;
1181  restoring = true;
1182  add2(treenode[fromwhere - 1], treenode[what - 1], dummy, &root,
1183    restoring, wasleft, treenode);
1184  like = -current;
1185  compatible = oldcompat;
1186  restoring = false;
1187  better = false;
1188  printf("       BETTER: ");
1189  for (j = 1; j <= (nonodes); j++) {
1190    if (place[j - 1] < current && place[j - 1] >= 0.0) {
1191      printf("%3ld:%6.2f", j, place[j - 1]);
1192      better = true;
1193    }
1194  }
1195  if (!better)
1196    printf(" NONE");
1197  printf("\n       TIED:    ");
1198  tied = false;
1199  for (j = 1; j <= (nonodes); j++) {
1200    if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
1201      if (j < 10)
1202        printf("%2ld", j);
1203      else
1204        printf("%3ld", j);
1205      tied = true;
1206    }
1207  }
1208  if (tied)
1209    printf(":%6.2f\n", current);
1210  else
1211    printf("NONE\n");
1212  changed = true;
1213  free(place);
1214}  /* try */
1215
1216void undo()
1217{
1218  /* restore to tree before last rearrangement */
1219  long temp;
1220  boolean btemp;
1221  node *q;
1222
1223  switch (lastop) {
1224
1225  case rearr:
1226    restoring = true;
1227    oldleft = wasleft;
1228    re_move2(&treenode[what - 1], &q, &root, &wasleft, treenode);
1229    btemp = wasleft;
1230    wasleft = oldleft;
1231    add2(treenode[fromwhere - 1], treenode[what - 1], q, &root,
1232      restoring, wasleft, treenode);
1233    wasleft = btemp;
1234    restoring = false;
1235    temp = fromwhere;
1236    fromwhere = towhere;
1237    towhere = temp;
1238    changed = true;
1239    break;
1240
1241  case flipp:
1242    q = treenode[atwhat - 1]->next->back;
1243    treenode[atwhat - 1]->next->back =
1244      treenode[atwhat - 1]->next->next->back;
1245    treenode[atwhat - 1]->next->next->back = q;
1246    treenode[atwhat - 1]->next->back->back = treenode[atwhat - 1]->next;
1247    treenode[atwhat - 1]->next->next->back->back =
1248      treenode[atwhat - 1]->next->next;
1249    break;
1250
1251  case reroott:
1252    restoring = true;
1253    temp = oldoutgrno;
1254    oldoutgrno = outgrno;
1255    outgrno = temp;
1256    reroot(treenode[outgrno - 1]);
1257    restoring = false;
1258    break;
1259
1260  case none:
1261    /* blank case */
1262    break;
1263  }
1264  dolmove_printree();
1265  if (lastop == none) {
1266    printf("No operation to undo! ");
1267    return;
1268  }
1269  btemp = oldwritten;
1270  oldwritten = written;
1271  written = btemp;
1272}  /* undo */
1273
1274
1275void treewrite(boolean done)
1276{
1277  /* write out tree to a file */
1278  Char ch;
1279
1280  treeoptions(waswritten, &ch, &outtree, outtreename, progname);
1281  if (!done)
1282    dolmove_printree();
1283  if (waswritten && ch == 'N')
1284    return;
1285  col = 0;
1286  treeout(root, 1, &col, root);
1287  printf("\nTree written to file \"%s\"\n\n", outtreename);
1288  waswritten = true;
1289  written = true;
1290  FClose(outtree);
1291#ifdef MAC
1292  fixmacfile(outtreename);
1293#endif
1294}  /* treewrite */
1295
1296
1297void clade()
1298{
1299  /* pick a subtree and show only that on screen */
1300  long i;
1301  boolean ok;
1302
1303  printf("Select subtree rooted at which node (0 for whole tree)? ");
1304  inpnum(&i, &ok);
1305  ok = (ok && ((unsigned)i) <= ((unsigned)nonodes));
1306  if (ok) {
1307    subtree = (i > 0);
1308    if (subtree)
1309      nuroot = treenode[i - 1];
1310    else
1311      nuroot = root;
1312  }
1313  dolmove_printree();
1314  if (!ok)
1315    printf("Not possible to use this node. ");
1316}  /* clade */
1317
1318
1319void flip()
1320{
1321  /* flip at a node left-right */
1322  long i;
1323  boolean ok;
1324  node *p;
1325
1326  printf("Flip branches at which node? ");
1327  inpnum(&i, &ok);
1328  ok = (ok && i > spp && i <= nonodes);
1329  if (ok) {
1330    p = treenode[i - 1]->next->back;
1331    treenode[i - 1]->next->back = treenode[i - 1]->next->next->back;
1332    treenode[i - 1]->next->next->back = p;
1333    treenode[i - 1]->next->back->back = treenode[i - 1]->next;
1334    treenode[i - 1]->next->next->back->back = treenode[i - 1]->next->next;
1335    atwhat = i;
1336    lastop = flipp;
1337  }
1338  dolmove_printree();
1339  if (ok) {
1340    oldwritten = written;
1341    written = false;
1342    return;
1343  }
1344  if (i >= 1 && i <= spp)
1345    printf("Can't flip there. ");
1346  else
1347    printf("No such node. ");
1348}  /* flip */
1349
1350
1351void changeoutgroup()
1352{
1353  long i;
1354  boolean ok;
1355
1356  oldoutgrno = outgrno;
1357  do {
1358    printf("Which node should be the new outgroup? ");
1359    inpnum(&i, &ok);
1360    ok = (ok && in_tree[i - 1] && i >= 1 && i <= nonodes &&
1361          i != root->index);
1362    if (ok)
1363      outgrno = i;
1364  } while (!ok);
1365  if (in_tree[outgrno - 1])
1366    reroot(treenode[outgrno - 1]);
1367  changed = true;
1368  lastop = reroott;
1369  dolmove_printree();
1370  oldwritten = written;
1371  written = false;
1372}  /* changeoutgroup */
1373
1374
1375void redisplay()
1376{
1377  boolean done;
1378  char input[100];
1379
1380  done = false;
1381  waswritten = false;
1382  do {
1383    printf("NEXT? (Options: R # + - S . T U W O F H J K L C ? X Q) ");
1384    printf("(? for Help) ");
1385#ifdef WIN32
1386    phyFillScreenColor();
1387#endif
1388    getstryng(input);
1389    ch = input[0];
1390    uppercase(&ch);
1391    if (strchr("RSWH#.O?+TFX-UCQHJKL",ch) != NULL){
1392      switch (ch) {
1393
1394      case 'R':
1395        rearrange();
1396        break;
1397
1398      case '#':
1399        nextinc(&dispchar, &dispword, &dispbit, chars, bits, &display,
1400                  numsteps, weight);
1401        dolmove_printree();
1402        break;
1403
1404      case '+':
1405        nextchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
1406        dolmove_printree();
1407        break;
1408
1409      case '-':
1410        prevchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
1411        dolmove_printree();
1412        break;
1413
1414      case 'S':
1415        show(&dispchar, &dispword, &dispbit, chars, bits, &display);
1416        dolmove_printree();
1417        break;
1418
1419      case '.':
1420        dolmove_printree();
1421        break;
1422
1423      case 'T':
1424        try();
1425        break;
1426
1427      case 'U':
1428        undo();
1429        break;
1430
1431      case 'W':
1432        treewrite(done);
1433        break;
1434
1435      case 'O':
1436        changeoutgroup();
1437        break;
1438
1439      case 'F':
1440        flip();
1441        break;
1442
1443      case 'H':
1444        window(left, &leftedge, &topedge, hscroll, vscroll, treelines,
1445                 screenlines, screenwidth, farthest, subtree);
1446        dolmove_printree();
1447        break;
1448
1449      case 'J':
1450        window(downn, &leftedge, &topedge, hscroll, vscroll, treelines,
1451                 screenlines, screenwidth, farthest, subtree);
1452        dolmove_printree();
1453        break;
1454
1455      case 'K':
1456        window(upp, &leftedge, &topedge, hscroll, vscroll, treelines,
1457                 screenlines, screenwidth, farthest, subtree);
1458        dolmove_printree();
1459        break;
1460
1461      case 'L':
1462        window(right, &leftedge, &topedge, hscroll, vscroll, treelines,
1463                 screenlines, screenwidth, farthest, subtree);
1464        dolmove_printree();
1465        break;
1466
1467      case 'C':
1468        clade();
1469        break;
1470
1471      case '?':
1472        help("character");
1473        dolmove_printree();
1474        break;
1475
1476      case 'X':
1477        done = true;
1478        break;
1479
1480      case 'Q':
1481        done = true;
1482        break;
1483      }
1484    }
1485  } while (!done);
1486  if (!written) {
1487    do {
1488      printf("Do you want to write out the tree to a file? (Y or N) ");
1489#ifdef WIN32
1490      phyFillScreenColor();
1491#endif
1492      getstryng(input);
1493      ch = input[0];
1494    } while (ch != 'Y' && ch != 'y' && ch != 'N' && ch != 'n');
1495  }
1496  if (ch == 'Y' || ch == 'y')
1497    treewrite(done);
1498}  /* redisplay */
1499
1500
1501void treeconstruct()
1502{
1503  /* constructs a binary tree from the pointers in treenode. */
1504
1505  restoring = false;
1506  subtree = false;
1507  display = false;
1508  dispchar = 0;
1509  fullset = (1L << (bits + 1)) - (1L << 1);
1510  guess = (Char *)Malloc(chars*sizeof(Char));
1511  numsteps = (steptr)Malloc(chars*sizeof(long));
1512  earlytree = true;
1513  buildtree();
1514  waswritten = false;
1515  printf("\nComputing steps needed for compatibility in sites ...\n\n");
1516  newtree = true;
1517  earlytree = false;
1518  dolmove_printree();
1519  bestyet = -like;
1520  gotlike = -like;
1521  lastop = none;
1522  newtree = false;
1523  written = false;
1524  lastop = none;
1525  redisplay();
1526}  /* treeconstruct */
1527
1528
1529int main(int argc, Char *argv[])
1530{ /* Interactive Dollo/polymorphism parsimony */
1531  /* reads in spp, chars, and the data. Then calls treeconstruct to
1532    construct the tree and query the user */
1533#ifdef MAC
1534  argc = 1;                /* macsetup("Dolmove","");                */
1535  argv[0] = "Dolmove";
1536#endif
1537  init(argc, argv);
1538  progname = argv[0];
1539  strcpy(infilename,INFILE);
1540  strcpy(outtreename,OUTTREE);
1541  strcpy(intreename,INTREE);
1542
1543  openfile(&infile,infilename,"input file", "r",argv[0],infilename);
1544
1545  screenlines = 24;
1546  scrollinc   = 20;
1547  screenwidth = 80;
1548  topedge     = 1;
1549  leftedge    = 1;
1550  ibmpc = IBMCRT;
1551  ansi = ANSICRT;
1552  root = NULL;
1553  bits = 8*sizeof(long) - 1;
1554  doinput();
1555  configure();
1556  treeconstruct();
1557  if (waswritten) {
1558    FClose(outtree);
1559#ifdef MAC
1560    fixmacfile(outtreename);
1561#endif
1562  }
1563  FClose(infile);
1564#ifdef WIN32
1565  phyRestoreConsoleAttributes();
1566#endif
1567  return 0;
1568}  /* Interactive Dollo/polymorphism parsimony */
1569
Note: See TracBrowser for help on using the repository browser.