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

Last change on this file was 19480, checked in by westram, 2 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.4 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 global_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 **local_grbg, node *UNUSED_q, long UNUSED_len, long nodei,
982                        long *UNUSED_ntips, long *parens, initops whichinit,
983                        pointarray local_treenode, pointarray UNUSED_nodep, Char *str, Char *ch,
984                        FILE *fp_intree)
985{
986    (void)UNUSED_q;
987    (void)UNUSED_len;
988    (void)UNUSED_ntips;
989    (void)UNUSED_nodep;
990
991  /* initializes a node */
992  /* LM 7/27  I added this function and the commented lines around */
993  /* treeread() to get the program running, but all 4 move programs*/
994  /* are improperly integrated into the v4.0 support files.  As is */
995  /* this is a patchwork function                                   */
996  boolean minusread;
997  double valyew, divisor;
998
999  switch (whichinit) {
1000  case bottom:
1001    gnutreenode(local_grbg, p, nodei, chars, zeros);
1002    local_treenode[nodei - 1] = *p;
1003    break;
1004  case nonbottom:
1005    gnutreenode(local_grbg, p, nodei, chars, zeros);
1006    break;
1007  case tip:
1008    match_names_to_data (str, local_treenode, p, spp);
1009    break;
1010  case length:
1011    processlength(&valyew, &divisor, ch, &minusread, fp_intree, parens);
1012    /* process lengths and discard */
1013  default:      /*cases hslength,hsnolength,treewt,unittrwt,iter,*/
1014    break;      /*length should never occur                      */
1015  }
1016} /* initdolmovenode */
1017
1018
1019void buildtree()
1020{
1021  long i, j, nextnode;
1022  node *p;
1023
1024  changed = false;
1025  newtree = false;
1026  switch (how) {
1027
1028  case arb:
1029    arbitree();
1030    break;
1031
1032  case use:
1033    openfile(&intree,INTREE,"input tree file", "r",progname,intreename);
1034    names = (boolean *)Malloc(spp*sizeof(boolean));
1035    firsttree = true;                       /**/
1036    nodep = NULL;                           /**/
1037    nextnode = 0;                           /**/
1038    haslengths = 0;                         /**/
1039    zeros = (long *)Malloc(chars*sizeof(long));         /**/
1040    for (i = 0; i < chars; i++)             /**/
1041      zeros[i] = 0;                         /**/
1042    treeread(intree, &root, treenode, &goteof, &firsttree,
1043                nodep, &nextnode, &haslengths,
1044                &grbg, initdolmovenode); /*debug*/
1045    for (i = spp; i < (nonodes); i++) {
1046      p = treenode[i];
1047      for (j = 1; j <= 3; j++) {
1048        p->stateone = (bitptr)Malloc(words*sizeof(long));
1049        p->statezero = (bitptr)Malloc(words*sizeof(long));
1050        p = p->next;
1051      }
1052    } /* debug: see comment at initdolmovenode() */
1053
1054    /*treeread(which, ch, &root, treenode, names);*/
1055    for (i = 0; i < (spp); i++)
1056      in_tree[i] = names[i];
1057    free(names);
1058    FClose(intree);
1059    break;
1060
1061  case spec:
1062    yourtree();
1063    break;
1064  }
1065  outgrno = root->next->back->index;
1066  if (in_tree[outgrno - 1])
1067    reroot(treenode[outgrno - 1]);
1068}  /* buildtree */
1069
1070
1071void rearrange()
1072{
1073  long i, j;
1074  boolean ok1, ok2;
1075  node *p, *q;
1076
1077  printf("Remove everything to the right of which node? ");
1078  inpnum(&i, &ok1);
1079  ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index);
1080  if (ok1) {
1081    printf("Add before which node? ");
1082    inpnum(&j, &ok2);
1083    ok2 = (ok2 && j >= 1 && j < spp * 2);
1084    if (ok2) {
1085      ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]);
1086      p = treenode[j - 1];
1087      while (p != root) {
1088        ok2 = (ok2 && p != treenode[i - 1]);
1089        p = treenode[p->back->index - 1];
1090      }
1091      if (ok1 && ok2) {
1092        what = i;
1093        q = treenode[treenode[i - 1]->back->index - 1];
1094        if (q->next->back->index == i)
1095          fromwhere = q->next->next->back->index;
1096        else
1097          fromwhere = q->next->back->index;
1098        towhere = j;
1099        re_move2(&treenode[i - 1], &q, &root, &wasleft, treenode);
1100        add2(treenode[j - 1], treenode[i - 1], q, &root, restoring, wasleft, treenode);
1101      }
1102      lastop = rearr;
1103    }
1104  }
1105  changed = (ok1 && ok2);
1106  dolmove_printree();
1107  if (!(ok1 && ok2))
1108    printf("Not a possible rearrangement.  Try again: \n");
1109  else {
1110    oldwritten = written;
1111    written = false;
1112  }
1113}  /* rearrange */
1114
1115
1116void tryadd(node *p, node **item, node **nufork, double *place)
1117{
1118  /* temporarily adds one fork and one tip to the tree.
1119    Records scores in ARRAY place */
1120  add2(p, *item, *nufork, &root, restoring, wasleft, treenode);
1121  evaluate(root);
1122  place[p->index - 1] = -like;
1123  re_move2(item, nufork, &root, &wasleft, treenode);
1124}  /* tryadd */
1125
1126
1127void addpreorder(node *p, node *item_, node *nufork_, double *place)
1128{
1129  /* traverses a binary tree, calling PROCEDURE tryadd
1130    at a node before calling tryadd at its descendants */
1131  node *item, *nufork;
1132
1133
1134  item = item_;
1135  nufork = nufork_;
1136  if (p == NULL)
1137    return;
1138  tryadd(p, &item,&nufork,place);
1139  if (!p->tip) {
1140    addpreorder(p->next->back, item,nufork,place);
1141    addpreorder(p->next->next->back,item,nufork,place);
1142  }
1143}  /* addpreorder */
1144
1145
1146void try()
1147{
1148  /* Remove node, try it in all possible places */
1149  double *place;
1150  long i, j, oldcompat;
1151  double current;
1152  node *q, *dummy, *rute;
1153  boolean tied, better, ok;
1154
1155  printf("Try other positions for which node? ");
1156  inpnum(&i, &ok);
1157  if (!(ok && i >= 1 && i <= nonodes && i != root->index)) {
1158    printf("Not a possible choice! ");
1159    return;
1160  }
1161  printf("WAIT ...\n");
1162  place = (double *)Malloc(nonodes*sizeof(double));
1163  for (j = 0; j < (nonodes); j++)
1164    place[j] = -1.0;
1165  evaluate(root);
1166  current = -like;
1167  oldcompat = compatible;
1168  what = i;
1169  q = treenode[treenode[i - 1]->back->index - 1];
1170  if (q->next->back->index == i)
1171    fromwhere = q->next->next->back->index;
1172  else
1173    fromwhere = q->next->back->index;
1174  rute = root;
1175  if (root->index == treenode[i - 1]->back->index) {
1176    if (treenode[treenode[i - 1]->back->index - 1]->next->back == treenode[i - 1])
1177      rute = treenode[treenode[i - 1]->back->index - 1]->next->next->back;
1178    else
1179      rute = treenode[treenode[i - 1]->back->index - 1]->next->back;
1180  }
1181  re_move2(&treenode[i - 1], &dummy, &root, &wasleft, treenode);
1182  oldleft = wasleft;
1183  root = rute;
1184  addpreorder(root, treenode[i - 1], dummy, place);
1185  wasleft = oldleft;
1186  restoring = true;
1187  add2(treenode[fromwhere - 1], treenode[what - 1], dummy, &root,
1188    restoring, wasleft, treenode);
1189  like = -current;
1190  compatible = oldcompat;
1191  restoring = false;
1192  better = false;
1193  printf("       BETTER: ");
1194  for (j = 1; j <= (nonodes); j++) {
1195    if (place[j - 1] < current && place[j - 1] >= 0.0) {
1196      printf("%3ld:%6.2f", j, place[j - 1]);
1197      better = true;
1198    }
1199  }
1200  if (!better)
1201    printf(" NONE");
1202  printf("\n       TIED:    ");
1203  tied = false;
1204  for (j = 1; j <= (nonodes); j++) {
1205    if (fabs(place[j - 1] - current) < 1.0e-6 && j != fromwhere) {
1206      if (j < 10)
1207        printf("%2ld", j);
1208      else
1209        printf("%3ld", j);
1210      tied = true;
1211    }
1212  }
1213  if (tied)
1214    printf(":%6.2f\n", current);
1215  else
1216    printf("NONE\n");
1217  changed = true;
1218  free(place);
1219}  /* try */
1220
1221void undo()
1222{
1223  /* restore to tree before last rearrangement */
1224  long temp;
1225  boolean btemp;
1226  node *q;
1227
1228  switch (lastop) {
1229
1230  case rearr:
1231    restoring = true;
1232    oldleft = wasleft;
1233    re_move2(&treenode[what - 1], &q, &root, &wasleft, treenode);
1234    btemp = wasleft;
1235    wasleft = oldleft;
1236    add2(treenode[fromwhere - 1], treenode[what - 1], q, &root,
1237      restoring, wasleft, treenode);
1238    wasleft = btemp;
1239    restoring = false;
1240    temp = fromwhere;
1241    fromwhere = towhere;
1242    towhere = temp;
1243    changed = true;
1244    break;
1245
1246  case flipp:
1247    q = treenode[atwhat - 1]->next->back;
1248    treenode[atwhat - 1]->next->back =
1249      treenode[atwhat - 1]->next->next->back;
1250    treenode[atwhat - 1]->next->next->back = q;
1251    treenode[atwhat - 1]->next->back->back = treenode[atwhat - 1]->next;
1252    treenode[atwhat - 1]->next->next->back->back =
1253      treenode[atwhat - 1]->next->next;
1254    break;
1255
1256  case reroott:
1257    restoring = true;
1258    temp = oldoutgrno;
1259    oldoutgrno = outgrno;
1260    outgrno = temp;
1261    reroot(treenode[outgrno - 1]);
1262    restoring = false;
1263    break;
1264
1265  case none:
1266    /* blank case */
1267    break;
1268  }
1269  dolmove_printree();
1270  if (lastop == none) {
1271    printf("No operation to undo! ");
1272    return;
1273  }
1274  btemp = oldwritten;
1275  oldwritten = written;
1276  written = btemp;
1277}  /* undo */
1278
1279
1280void treewrite(boolean done)
1281{
1282  /* write out tree to a file */
1283  Char ch;
1284
1285  treeoptions(waswritten, &ch, &outtree, outtreename, progname);
1286  if (!done)
1287    dolmove_printree();
1288  if (waswritten && ch == 'N')
1289    return;
1290  col = 0;
1291  treeout(root, 1, &col, root);
1292  printf("\nTree written to file \"%s\"\n\n", outtreename);
1293  waswritten = true;
1294  written = true;
1295  FClose(outtree);
1296#ifdef MAC
1297  fixmacfile(outtreename);
1298#endif
1299}  /* treewrite */
1300
1301
1302void clade()
1303{
1304  /* pick a subtree and show only that on screen */
1305  long i;
1306  boolean ok;
1307
1308  printf("Select subtree rooted at which node (0 for whole tree)? ");
1309  inpnum(&i, &ok);
1310  ok = (ok && ((unsigned)i) <= ((unsigned)nonodes));
1311  if (ok) {
1312    subtree = (i > 0);
1313    if (subtree)
1314      nuroot = treenode[i - 1];
1315    else
1316      nuroot = root;
1317  }
1318  dolmove_printree();
1319  if (!ok)
1320    printf("Not possible to use this node. ");
1321}  /* clade */
1322
1323
1324void flip()
1325{
1326  /* flip at a node left-right */
1327  long i;
1328  boolean ok;
1329  node *p;
1330
1331  printf("Flip branches at which node? ");
1332  inpnum(&i, &ok);
1333  ok = (ok && i > spp && i <= nonodes);
1334  if (ok) {
1335    p = treenode[i - 1]->next->back;
1336    treenode[i - 1]->next->back = treenode[i - 1]->next->next->back;
1337    treenode[i - 1]->next->next->back = p;
1338    treenode[i - 1]->next->back->back = treenode[i - 1]->next;
1339    treenode[i - 1]->next->next->back->back = treenode[i - 1]->next->next;
1340    atwhat = i;
1341    lastop = flipp;
1342  }
1343  dolmove_printree();
1344  if (ok) {
1345    oldwritten = written;
1346    written = false;
1347    return;
1348  }
1349  if (i >= 1 && i <= spp)
1350    printf("Can't flip there. ");
1351  else
1352    printf("No such node. ");
1353}  /* flip */
1354
1355
1356void changeoutgroup()
1357{
1358  long i;
1359  boolean ok;
1360
1361  oldoutgrno = outgrno;
1362  do {
1363    printf("Which node should be the new outgroup? ");
1364    inpnum(&i, &ok);
1365    ok = (ok && in_tree[i - 1] && i >= 1 && i <= nonodes &&
1366          i != root->index);
1367    if (ok)
1368      outgrno = i;
1369  } while (!ok);
1370  if (in_tree[outgrno - 1])
1371    reroot(treenode[outgrno - 1]);
1372  changed = true;
1373  lastop = reroott;
1374  dolmove_printree();
1375  oldwritten = written;
1376  written = false;
1377}  /* changeoutgroup */
1378
1379
1380void redisplay()
1381{
1382  boolean done;
1383  char input[100];
1384
1385  done = false;
1386  waswritten = false;
1387  do {
1388    printf("NEXT? (Options: R # + - S . T U W O F H J K L C ? X Q) ");
1389    printf("(? for Help) ");
1390#ifdef WIN32
1391    phyFillScreenColor();
1392#endif
1393    getstryng(input);
1394    global_ch = input[0];
1395    uppercase(&global_ch);
1396    if (strchr("RSWH#.O?+TFX-UCQHJKL",global_ch) != NULL){
1397      switch (global_ch) {
1398
1399      case 'R':
1400        rearrange();
1401        break;
1402
1403      case '#':
1404        nextinc(&dispchar, &dispword, &dispbit, chars, bits, &display,
1405                  numsteps, weight);
1406        dolmove_printree();
1407        break;
1408
1409      case '+':
1410        nextchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
1411        dolmove_printree();
1412        break;
1413
1414      case '-':
1415        prevchar(&dispchar, &dispword, &dispbit, chars, bits, &display);
1416        dolmove_printree();
1417        break;
1418
1419      case 'S':
1420        show(&dispchar, &dispword, &dispbit, chars, bits, &display);
1421        dolmove_printree();
1422        break;
1423
1424      case '.':
1425        dolmove_printree();
1426        break;
1427
1428      case 'T':
1429        try();
1430        break;
1431
1432      case 'U':
1433        undo();
1434        break;
1435
1436      case 'W':
1437        treewrite(done);
1438        break;
1439
1440      case 'O':
1441        changeoutgroup();
1442        break;
1443
1444      case 'F':
1445        flip();
1446        break;
1447
1448      case 'H':
1449        window(left, &leftedge, &topedge, hscroll, vscroll, treelines,
1450                 screenlines, screenwidth, farthest, subtree);
1451        dolmove_printree();
1452        break;
1453
1454      case 'J':
1455        window(downn, &leftedge, &topedge, hscroll, vscroll, treelines,
1456                 screenlines, screenwidth, farthest, subtree);
1457        dolmove_printree();
1458        break;
1459
1460      case 'K':
1461        window(upp, &leftedge, &topedge, hscroll, vscroll, treelines,
1462                 screenlines, screenwidth, farthest, subtree);
1463        dolmove_printree();
1464        break;
1465
1466      case 'L':
1467        window(right, &leftedge, &topedge, hscroll, vscroll, treelines,
1468                 screenlines, screenwidth, farthest, subtree);
1469        dolmove_printree();
1470        break;
1471
1472      case 'C':
1473        clade();
1474        break;
1475
1476      case '?':
1477        help("character");
1478        dolmove_printree();
1479        break;
1480
1481      case 'X':
1482        done = true;
1483        break;
1484
1485      case 'Q':
1486        done = true;
1487        break;
1488      }
1489    }
1490  } while (!done);
1491  if (!written) {
1492    do {
1493      printf("Do you want to write out the tree to a file? (Y or N) ");
1494#ifdef WIN32
1495      phyFillScreenColor();
1496#endif
1497      getstryng(input);
1498      global_ch = input[0];
1499    } while (global_ch != 'Y' && global_ch != 'y' && global_ch != 'N' && global_ch != 'n');
1500  }
1501  if (global_ch == 'Y' || global_ch == 'y')
1502    treewrite(done);
1503}  /* redisplay */
1504
1505
1506void treeconstruct()
1507{
1508  /* constructs a binary tree from the pointers in treenode. */
1509
1510  restoring = false;
1511  subtree = false;
1512  display = false;
1513  dispchar = 0;
1514  fullset = (1L << (bits + 1)) - (1L << 1);
1515  guess = (Char *)Malloc(chars*sizeof(Char));
1516  numsteps = (steptr)Malloc(chars*sizeof(long));
1517  earlytree = true;
1518  buildtree();
1519  waswritten = false;
1520  printf("\nComputing steps needed for compatibility in sites ...\n\n");
1521  newtree = true;
1522  earlytree = false;
1523  dolmove_printree();
1524  bestyet = -like;
1525  gotlike = -like;
1526  lastop = none;
1527  newtree = false;
1528  written = false;
1529  lastop = none;
1530  redisplay();
1531}  /* treeconstruct */
1532
1533
1534int main(int argc, Char *argv[])
1535{ /* Interactive Dollo/polymorphism parsimony */
1536  /* reads in spp, chars, and the data. Then calls treeconstruct to
1537    construct the tree and query the user */
1538#ifdef MAC
1539  argc = 1;                /* macsetup("Dolmove","");                */
1540  argv[0] = "Dolmove";
1541#endif
1542  init(argc, argv);
1543  progname = argv[0];
1544  strcpy(infilename,INFILE);
1545  strcpy(outtreename,OUTTREE);
1546  strcpy(intreename,INTREE);
1547
1548  openfile(&infile,infilename,"input file", "r",argv[0],infilename);
1549
1550  screenlines = 24;
1551  scrollinc   = 20;
1552  screenwidth = 80;
1553  topedge     = 1;
1554  leftedge    = 1;
1555  ibmpc = IBMCRT;
1556  ansi = ANSICRT;
1557  root = NULL;
1558  bits = 8*sizeof(long) - 1;
1559  doinput();
1560  configure();
1561  treeconstruct();
1562  if (waswritten) {
1563    FClose(outtree);
1564#ifdef MAC
1565    fixmacfile(outtreename);
1566#endif
1567  }
1568  FClose(infile);
1569#ifdef WIN32
1570  phyRestoreConsoleAttributes();
1571#endif
1572  return 0;
1573}  /* Interactive Dollo/polymorphism parsimony */
1574
Note: See TracBrowser for help on using the repository browser.