source: branches/stable/GDE/PHYLIP/kitsch.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: 25.5 KB
Line 
1
2#include "phylip.h"
3#include "dist.h"
4
5/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
6   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
7   Permission is granted to copy and use this program provided no fee is
8   charged for it and provided that this copyright notice is not removed. */
9
10#define epsilonk         0.000001   /* a very small but not too small number */
11
12#ifndef OLDC
13/* function prototypes */
14void   getoptions(void);
15void   doinit(void);
16void   inputoptions(void);
17void   getinput(void);
18void   input_data(void);
19void   add(node *, node *, node *);
20void   re_move(node **, node **);
21void   scrunchtraverse(node *, node **, double *);
22void   combine(node *, node *);
23void   scrunch(node *);
24
25void   secondtraverse(node *, node *, node *, node *, long, long,
26                long , double *);
27void   firstraverse(node *, node *, double *);
28void   sumtraverse(node *, double *);
29void   evaluate(node *);
30void   tryadd(node *, node **, node **);
31void   addpreorder(node *, node *, node *);
32void   tryrearr(node *, node **, boolean *);
33void   repreorder(node *, node **, boolean *);
34void   rearrange(node **);
35
36void   dtraverse(node *);
37void   describe(void);
38void   copynode(node *, node *);
39void   copy_(tree *, tree *);
40void   maketree(void);
41/* function prototypes */
42#endif
43
44
45
46Char infilename[FNMLNGTH], outfilename[FNMLNGTH], intreename[FNMLNGTH], outtreename[FNMLNGTH];
47long nonodes, numtrees, col, datasets, ith, njumble, jumb;
48/*   numtrees is used by usertree option part of maketree */
49long inseed;
50tree curtree, bestree;   /* pointers to all nodes in tree */
51boolean minev, jumble, usertree, lower, upper, negallowed, replicates, trout,
52        printdata, progress, treeprint, mulsets, firstset;
53longer seed;
54double power;
55long *enterorder;
56/* Local variables for maketree, propagated globally for C version: */
57  long examined;
58  double like, bestyet;
59  node *there;
60  boolean *names;
61  Char ch;
62  char *progname;
63double trweight; /* to make treeread happy */
64boolean goteof, haslengths, lengths;  /* ditto ... */
65
66
67void getoptions()
68{
69  /* interactively set options */
70  long inseed0, loopcount;
71  Char ch;
72
73  minev = false;
74  jumble = false;
75  njumble = 1;
76  lower = false;
77  negallowed = false;
78  power = 2.0;
79  replicates = false;
80  upper = false;
81  usertree = false;
82  trout = true;
83  printdata = false;
84  progress = true;
85  treeprint = true;
86  loopcount = 0;
87  for(;;) {
88    cleerhome();
89    printf("\nFitch-Margoliash method ");
90    printf("with contemporary tips, version %s\n\n",VERSION);
91    printf("Settings for this run:\n");
92    printf("  D      Method (F-M, Minimum Evolution)?  %s\n",
93           (minev ? "Minimum Evolution" : "Fitch-Margoliash"));
94    printf("  U                 Search for best tree?  %s\n",
95           usertree ? "No, use user trees in input file" : "Yes");
96    printf("  P                                Power?%9.5f\n",power);
97    printf("  -      Negative branch lengths allowed?  %s\n",
98           (negallowed ? "Yes" : "No"));
99    printf("  L         Lower-triangular data matrix?  %s\n",
100           (lower ? "Yes" : "No"));
101    printf("  R         Upper-triangular data matrix?  %s\n",
102           (upper ? "Yes" : "No"));
103    printf("  S                        Subreplicates?  %s\n",
104           (replicates ? "Yes" : "No"));
105    if (!usertree) {
106      printf("  J     Randomize input order of species?");
107      if (jumble)
108            printf("  Yes (seed =%8ld,%3ld times)\n", inseed0, njumble);
109      else
110        printf("  No. Use input order\n");
111    }
112    printf("  M           Analyze multiple data sets?");
113    if (mulsets)
114      printf("  Yes, %2ld sets\n", datasets);
115    else
116      printf("  No\n");
117    printf("  0   Terminal type (IBM PC, ANSI, none)?  %s\n",
118           (ibmpc ? "IBM PC" : ansi  ? "ANSI" : "(none)"));
119    printf("  1    Print out the data at start of run  %s\n",
120           (printdata ? "Yes" : "No"));
121    printf("  2  Print indications of progress of run  %s\n",
122           (progress ? "Yes" : "No"));
123    printf("  3                        Print out tree  %s\n",
124    (treeprint ? "Yes" : "No"));
125    printf("  4       Write out trees onto tree file?  %s\n",
126          (trout ? "Yes" : "No"));
127    printf("\n  Y to accept these or type the letter for one to change\n");
128#ifdef WIN32
129    phyFillScreenColor();
130#endif
131    scanf("%c%*[^\n]", &ch);
132    getchar();
133    if (ch == '\n')
134      ch = ' ';
135    uppercase(&ch);
136   if (ch == 'Y')
137     break;
138   if (strchr("DJUP-LRSM12340",ch) != NULL){
139     switch (ch) {
140
141     case 'D':
142       minev = !minev;
143       if (!negallowed)
144         negallowed = true;
145       break;
146
147     case '-':
148       negallowed = !negallowed;
149       break;
150
151     case 'J':
152       jumble = !jumble;
153       if (jumble)
154         initjumble(&inseed, &inseed0, seed, &njumble);
155       else njumble = 1;
156       break;
157
158     case 'L':
159       lower = !lower;
160       break;
161
162     case 'P':
163       initpower(&power);
164       break;
165
166     case 'R':
167       upper = !upper;
168       break;
169
170     case 'S':
171       replicates = !replicates;
172       break;
173
174     case 'U':
175       usertree = !usertree;
176       break;
177
178     case 'M':
179       mulsets = !mulsets;
180       if (mulsets)
181         initdatasets(&datasets);
182       break;
183
184     case '0':
185       initterminal(&ibmpc, &ansi);
186       break;
187
188     case '1':
189       printdata = !printdata;
190       break;
191
192     case '2':
193       progress = !progress;
194       break;
195
196     case '3':
197       treeprint = !treeprint;
198       break;
199
200     case '4':
201       trout = !trout;
202       break;
203     }
204   } else
205     printf("Not a possible option!\n");
206   countup(&loopcount, 100);
207 }
208 if (upper && lower) {
209   printf("ERROR: Data matrix cannot be both uppeR and Lower triangular\n");
210   exxit(-1);
211 }
212}  /* getoptions */
213
214
215void doinit()
216{
217  /* initializes variables */
218
219  inputnumbers2(&spp, &nonodes, 1);
220  getoptions();
221  alloctree(&curtree.nodep, nonodes);
222  allocd(nonodes, curtree.nodep);
223  allocw(nonodes, curtree.nodep);
224  if (!usertree && njumble > 1) {
225    alloctree(&bestree.nodep, nonodes);
226    allocd(nonodes, bestree.nodep);
227    allocw(nonodes, bestree.nodep);
228  }
229  nayme = (naym *)Malloc(spp*sizeof(naym));
230  enterorder = (long *)Malloc(spp*sizeof(long));
231}  /* doinit */
232
233
234void inputoptions()
235{
236  /* print options information */
237  if (!firstset)
238    samenumsp2(ith);
239  fprintf(outfile, "\nFitch-Margoliash method ");
240  fprintf(outfile, "with contemporary tips, version %s\n\n",VERSION);
241  if (minev)
242    fprintf(outfile, "Minimum evolution method option\n\n");
243  fprintf(outfile, "                  __ __             2\n");
244  fprintf(outfile, "                  \\  \\   (Obs - Exp)\n");
245  fprintf(outfile, "Sum of squares =  /_ /_  ------------\n");
246  fprintf(outfile, "                               ");
247  if (power == (long)power)
248    fprintf(outfile, "%2ld\n", (long)power);
249  else
250    fprintf(outfile, "%4.1f\n", power);
251  fprintf(outfile, "                   i  j      Obs\n\n");
252  fprintf(outfile, "negative branch lengths");
253  if (!negallowed)
254    fprintf(outfile, " not");
255  fprintf(outfile, " allowed\n\n");
256}  /* inputoptions */
257
258
259void getinput()
260{
261  /* reads the input data */
262  inputoptions();
263}  /* getinput */
264
265
266void input_data()
267{
268  /* read in distance matrix */
269  long i, j, k, columns, n;
270  boolean skipit, skipother;
271  double x;
272  columns = replicates ? 4 : 6;
273  if (printdata) {
274    fprintf(outfile, "\nName                       Distances");
275    if (replicates)
276      fprintf(outfile, " (replicates)");
277    fprintf(outfile, "\n----                       ---------");
278    if (replicates)
279      fprintf(outfile, "-------------");
280    fprintf(outfile, "\n\n");
281  }
282  setuptree(&curtree, nonodes);
283  if (!usertree && njumble > 1)
284    setuptree(&bestree, nonodes);
285  for (i = 0; i < (spp); i++) {
286    curtree.nodep[i]->d[i] = 0.0;
287    curtree.nodep[i]->w[i] = 0.0;
288    curtree.nodep[i]->weight = 0.0;
289    scan_eoln(infile);
290    initname(i);
291    for (j = 1; j <= (spp); j++) {
292      skipit = ((lower && j >= i + 1) || (upper && j <= i + 1));
293      skipother = ((lower && i + 1 >= j) || (upper && i + 1 <= j));
294      if (!skipit) {
295        if (eoln(infile))
296          scan_eoln(infile);
297        fscanf(infile, "%lf", &x);
298        curtree.nodep[i]->d[j - 1] = x;
299        if (replicates) {
300          if (eoln(infile)) 
301            scan_eoln(infile);
302          fscanf(infile, "%ld", &n);
303        } else
304          n = 1;
305        if (n > 0 && x < 0) {
306          printf("NEGATIVE DISTANCE BETWEEN SPECIES%5ld AND %5ld\n",
307                 i + 1, j);
308          exxit(-1);
309        }
310        curtree.nodep[i]->w[j - 1] = n;
311        if (skipother) {
312          curtree.nodep[j - 1]->d[i] = curtree.nodep[i]->d[j - 1];
313          curtree.nodep[j - 1]->w[i] = curtree.nodep[i]->w[j - 1];
314        }
315      }
316    }
317  }
318  scan_eoln(infile);
319  if (printdata) {
320    for (i = 0; i < (spp); i++) {
321      for (j = 0; j < nmlngth; j++)
322        putc(nayme[i][j], outfile);
323      putc(' ', outfile);
324      for (j = 1; j <= (spp); j++) {
325        fprintf(outfile, "%10.5f", curtree.nodep[i]->d[j - 1]);
326        if (replicates)
327          fprintf(outfile, " (%3ld)", (long)curtree.nodep[i]->w[j - 1]);
328        if (j % columns == 0 && j < spp) {
329          putc('\n', outfile);
330          for (k = 1; k <= nmlngth + 1; k++)
331            putc(' ', outfile);
332        }
333      }
334      putc('\n', outfile);
335    }
336    putc('\n', outfile);
337  }
338  for (i = 0; i < (spp); i++) {
339    for (j = 0; j < (spp); j++) {
340      if (i + 1 != j + 1) {
341        if (curtree.nodep[i]->d[j] < epsilonk)
342          curtree.nodep[i]->d[j] = epsilonk;
343        curtree.nodep[i]->w[j] /= exp(power * log(curtree.nodep[i]->d[j]));
344      }
345    }
346  }
347}  /* inputdata */
348
349
350void add(node *below, node *newtip, node *newfork)
351{
352  /* inserts the nodes newfork and its left descendant, newtip,
353     to the tree.  below becomes newfork's right descendant */
354  if (below != curtree.nodep[below->index - 1])
355    below = curtree.nodep[below->index - 1];
356  if (below->back != NULL)
357    below->back->back = newfork;
358  newfork->back = below->back;
359  below->back = newfork->next->next;
360  newfork->next->next->back = below;
361  newfork->next->back = newtip;
362  newtip->back = newfork->next;
363  if (curtree.root == below)
364    curtree.root = newfork;
365  curtree.root->back = NULL;
366}  /* add */
367
368
369void re_move(node **item, node **fork)
370{
371  /* removes nodes item and its ancestor, fork, from the tree.
372     the new descendant of fork's ancestor is made to be
373     fork's second descendant (other than item).  Also
374     returns pointers to the deleted nodes, item and fork */
375  node *p, *q;
376
377  if ((*item)->back == NULL) {
378    *fork = NULL;
379    return;
380  }
381  *fork = curtree.nodep[(*item)->back->index - 1];
382  if (curtree.root == *fork) {
383    if (*item == (*fork)->next->back)
384      curtree.root = (*fork)->next->next->back;
385    else
386      curtree.root = (*fork)->next->back;
387  }
388  p = (*item)->back->next->back;
389  q = (*item)->back->next->next->back;
390  if (p != NULL)
391    p->back = q;
392  if (q != NULL)
393    q->back = p;
394  (*fork)->back = NULL;
395  p = (*fork)->next;
396  while (p != *fork) {
397    p->back = NULL;
398    p = p->next;
399  }
400  (*item)->back = NULL;
401}  /* remove */
402
403
404void scrunchtraverse(node *u, node **closest, double *tmax)
405{
406  /* traverse to find closest node to the current one */
407  if (!u->sametime) {
408    if (u->t > *tmax) {
409      *closest = u;
410      *tmax = u->t;
411    }
412    return;
413  }
414  u->t = curtree.nodep[u->back->index - 1]->t;
415  if (!u->tip) {
416    scrunchtraverse(u->next->back, closest,tmax);
417    scrunchtraverse(u->next->next->back, closest,tmax);
418  }
419}  /* scrunchtraverse */
420
421
422void combine(node *a, node *b)
423{
424  /* put node b into the set having the same time as a */
425  if (a->weight + b->weight <= 0.0)
426    a->t = 0.0;
427  else
428    a->t = (a->t * a->weight + b->t * b->weight) / (a->weight + b->weight);
429  a->weight += b->weight;
430  b->sametime = true;
431}  /* combine */
432
433
434void scrunch(node *s)
435{
436  /* see if nodes can be combined to prevent negative lengths */
437  double tmax;
438  node *closest;
439  boolean found;
440
441  closest = NULL;
442  tmax = -1.0;
443  do {
444    if (!s->tip) {
445      scrunchtraverse(s->next->back, &closest,&tmax);
446      scrunchtraverse(s->next->next->back, &closest,&tmax);
447    }
448    found = (tmax > s->t);
449    if (found)
450      combine(s, closest);
451    tmax = -1.0;
452  } while (found);
453}  /* scrunch */
454
455
456void secondtraverse(node *a, node *q, node *u, node *v, long i, long j,
457                        long k, double *sum)
458{
459  /* recalculate distances, add to sum */
460  long l;
461  double wil, wjl, wkl, wli, wlj, wlk, TEMP;
462
463  if (!(a->processed || a->tip)) {
464    secondtraverse(a->next->back, q,u,v,i,j,k,sum);
465    secondtraverse(a->next->next->back, q,u,v,i,j,k,sum);
466    return;
467  }
468  if (!(a != q && a->processed))
469    return;
470  l = a->index;
471  wil = u->w[l - 1];
472  wjl = v->w[l - 1];
473  wkl = wil + wjl;
474  wli = a->w[i - 1];
475  wlj = a->w[j - 1];
476  wlk = wli + wlj;
477  q->w[l - 1] = wkl;
478  a->w[k - 1] = wlk;
479  if (wkl <= 0.0)
480    q->d[l - 1] = 0.0;
481  else
482    q->d[l - 1] = (wil * u->d[l - 1] + wjl * v->d[l - 1]) / wkl;
483  if (wlk <= 0.0)
484    a->d[k - 1] = 0.0;
485  else
486    a->d[k - 1] = (wli * a->d[i - 1] + wlj * a->d[j - 1]) / wlk;
487  if (minev)
488    return;
489  if (wkl > 0.0) {
490    TEMP = u->d[l - 1] - v->d[l - 1];
491    (*sum) += wil * wjl / wkl * (TEMP * TEMP);
492  }
493  if (wlk > 0.0) {
494    TEMP = a->d[i - 1] - a->d[j - 1];
495    (*sum) += wli * wlj / wlk * (TEMP * TEMP);
496  }
497}  /* secondtraverse */
498
499
500void firstraverse(node *q_, node *r, double *sum)
501{  /* firsttraverse                              */
502   /* go through tree calculating branch lengths */
503  node *q;
504  long i, j, k;
505  node *u, *v;
506
507  q = q_;
508  if (q == NULL)
509    return;
510  q->sametime = false;
511  if (!q->tip) {
512    firstraverse(q->next->back, r,sum);
513    firstraverse(q->next->next->back, r,sum);
514  }
515  q->processed = true;
516  if (q->tip)
517    return;
518  u = q->next->back;
519  v = q->next->next->back;
520  i = u->index;
521  j = v->index;
522  k = q->index;
523  if (u->w[j - 1] + v->w[i - 1] <= 0.0)
524    q->t = 0.0;
525  else
526    q->t = (u->w[j - 1] * u->d[j - 1] +  v->w[i - 1] * v->d[i - 1]) /
527             (2.0 * (u->w[j - 1] + v->w[i - 1]));
528  q->weight = u->weight + v->weight + u->w[j - 1] + v->w[i - 1];
529  if (!negallowed)
530    scrunch(q);
531  u->v = q->t - u->t;
532  v->v = q->t - v->t;
533  u->back->v = u->v;
534  v->back->v = v->v;
535  secondtraverse(r,q,u,v,i,j,k,sum);
536}  /* firstraverse */
537
538
539void sumtraverse(node *q, double *sum)
540{
541  /* traverse to finish computation of sum of squares */
542  long i, j;
543  node *u, *v;
544  double TEMP, TEMP1;
545
546  if (minev && (q != curtree.root))
547    *sum += q->v;
548  if (q->tip)
549    return;
550  sumtraverse(q->next->back, sum);
551  sumtraverse(q->next->next->back, sum);
552  if (!minev) {
553    u = q->next->back;
554    v = q->next->next->back;
555    i = u->index;
556    j = v->index;
557    TEMP = u->d[j - 1] - 2.0 * q->t;
558    TEMP1 = v->d[i - 1] - 2.0 * q->t;
559    (*sum) += u->w[j - 1] * (TEMP * TEMP) + v->w[i - 1] * (TEMP1 * TEMP1);
560  }
561}  /* sumtraverse */
562
563
564void evaluate(node *r)
565{
566  /* fill in times and evaluate sum of squares for tree */
567  double sum;
568  long i;
569  sum = 0.0;
570  for (i = 0; i < (nonodes); i++)
571    curtree.nodep[i]->processed = curtree.nodep[i]->tip;
572  firstraverse(r, r,&sum);
573  sumtraverse(r, &sum);
574  examined++;
575  if (replicates && (lower || upper))
576    sum /= 2;
577  like = -sum;
578}  /* evaluate */
579
580
581void tryadd(node *p, node **item, node **nufork)
582{
583  /* temporarily adds one fork and one tip to the tree.
584     if the location where they are added yields greater
585     "likelihood" than other locations tested up to that
586     time, then keeps that location as there */
587  add(p, *item, *nufork);
588  evaluate(curtree.root);
589  if (like > bestyet) {
590    bestyet = like;
591    there = p;
592  }
593  re_move(item, nufork);
594}  /* tryadd */
595
596
597void addpreorder(node *p, node *item, node *nufork)
598{
599  /* traverses a binary tree, calling PROCEDURE tryadd
600     at a node before calling tryadd at its descendants */
601  if (p == NULL)
602    return;
603  tryadd(p, &item,&nufork);
604  if (!p->tip) {
605    addpreorder(p->next->back, item, nufork);
606    addpreorder(p->next->next->back, item, nufork);
607  }
608}  /* addpreorder */
609
610
611void tryrearr(node *p, node **r, boolean *success)
612{
613  /* evaluates one rearrangement of the tree.
614     if the new tree has greater "likelihood" than the old
615     one sets success := TRUE and keeps the new tree.
616     otherwise, restores the old tree */
617  node *frombelow, *whereto, *forknode;
618  double oldlike;
619
620  if (p->back == NULL)
621    return;
622  forknode = curtree.nodep[p->back->index - 1];
623  if (forknode->back == NULL)
624    return;
625  oldlike = like;
626  if (p->back->next->next == forknode)
627    frombelow = forknode->next->next->back;
628  else
629    frombelow = forknode->next->back;
630  whereto = forknode->back;
631  re_move(&p, &forknode);
632  add(whereto, p, forknode);
633  if ((*r)->back != NULL)
634    *r = curtree.nodep[(*r)->back->index - 1];
635  evaluate(*r);
636  if (like > oldlike) {
637    bestyet = like;
638    *success = true;
639    return;
640  }
641  re_move(&p, &forknode);
642  add(frombelow, p, forknode);
643  if ((*r)->back != NULL)
644    *r = curtree.nodep[(*r)->back->index - 1];
645  like = oldlike;
646}  /* tryrearr */
647
648
649void repreorder(node *p, node **r, boolean *success)
650{
651  /* traverses a binary tree, calling PROCEDURE tryrearr
652     at a node before calling tryrearr at its descendants */
653  if (p == NULL)
654    return;
655  tryrearr(p,r,success);
656  if (!p->tip) {
657    repreorder(p->next->back,r,success);
658    repreorder(p->next->next->back,r,success);
659  }
660}  /* repreorder */
661
662
663void rearrange(node **r_)
664{
665  /* traverses the tree (preorder), finding any local
666     rearrangement which decreases the number of steps.
667     if traversal succeeds in increasing the tree's
668     "likelihood", PROCEDURE rearrange runs traversal again */
669  node **r;
670  boolean success;
671
672  r = r_;
673  success = true;
674  while (success) {
675    success = false;
676    repreorder(*r,r,&success);
677  }
678}  /* rearrange */
679
680
681void dtraverse(node *q)
682{
683  /* print table of lengths etc. */
684  long i;
685
686  if (!q->tip)
687    dtraverse(q->next->back);
688  if (q->back != NULL) {
689    fprintf(outfile, "%4ld   ", q->back->index - spp);
690    if (q->index <= spp) {
691      for (i = 0; i < nmlngth; i++)
692        putc(nayme[q->index - 1][i], outfile);
693    } else
694      fprintf(outfile, "%4ld      ", q->index - spp);
695    fprintf(outfile, "%13.5f", curtree.nodep[q->back->index - 1]->t - q->t);
696    fprintf(outfile, "%16.5f\n", curtree.root->t - q->t);
697  }
698  if (!q->tip)
699    dtraverse(q->next->next->back);
700}  /* dtraverse */
701
702
703void describe()
704{
705  /* prints table of lengths, times, sum of squares, etc. */
706  long i, j;
707  double totalnum;
708  double TEMP;
709
710  if (!minev)
711    fprintf(outfile, "\nSum of squares = %10.3f\n\n", -like);
712  else
713    fprintf(outfile, "Sum of branch lengths = %10.3f\n\n", -like);
714  if ((fabs(power - 2) < 0.01) && !minev) {
715    totalnum = 0.0;
716    for (i = 0; i < (spp); i++) {
717      for (j = 0; j < (spp); j++) {
718        if (i + 1 != j + 1 && curtree.nodep[i]->d[j] > 0.0) {
719          TEMP = curtree.nodep[i]->d[j];
720          totalnum += curtree.nodep[i]->w[j] * (TEMP * TEMP);
721        }
722      }
723    }
724    totalnum -= 2;
725    if (replicates && (lower || upper))
726      totalnum /= 2;
727    fprintf(outfile, "Average percent standard deviation =");
728    fprintf(outfile, "%10.5f\n\n", 100 * sqrt(-(like / totalnum)));
729  }
730  fprintf(outfile, "From     To            Length          Height\n");
731  fprintf(outfile, "----     --            ------          ------\n\n");
732  dtraverse(curtree.root);
733  putc('\n', outfile);
734  if (trout) {
735    col = 0;
736      treeoutr(curtree.root,&col,&curtree);
737/*    treeout(curtree.root); */
738  }
739}  /* describe */
740
741
742void copynode(node *c, node *d)
743{
744  /* make a copy of a node */
745
746  memcpy(d->d, c->d, nonodes*sizeof(double));
747  memcpy(d->w, c->w, nonodes*sizeof(double));
748  d->t = c->t;
749  d->sametime = c->sametime;
750  d->weight = c->weight;
751  d->processed = c->processed;
752  d->xcoord = c->xcoord;
753  d->ycoord = c->ycoord;
754  d->ymin = c->ymin;
755  d->ymax = c->ymax;
756}  /* copynode */
757
758
759void copy_(tree *a, tree *b)
760{
761  /* make a copy of a tree */
762  long i, j=0;
763  node *p, *q;
764
765  for (i = 0; i < spp; i++) {
766    copynode(a->nodep[i], b->nodep[i]);
767    if (a->nodep[i]->back) {
768      if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1])
769        b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1];
770      else if (a->nodep[i]->back
771                 == a->nodep[a->nodep[i]->back->index - 1]->next)
772        b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next;
773      else
774        b->nodep[i]->back
775          = b->nodep[a->nodep[i]->back->index - 1]->next->next;
776    }
777    else b->nodep[i]->back = NULL;
778  }
779  for (i = spp; i < nonodes; i++) {
780    p = a->nodep[i];
781    q = b->nodep[i];
782    for (j = 1; j <= 3; j++) {
783      copynode(p, q);
784      if (p->back) {
785        if (p->back == a->nodep[p->back->index - 1])
786          q->back = b->nodep[p->back->index - 1];
787        else if (p->back == a->nodep[p->back->index - 1]->next)
788          q->back = b->nodep[p->back->index - 1]->next;
789        else
790          q->back = b->nodep[p->back->index - 1]->next->next;
791      }
792      else
793        q->back = NULL;
794      p = p->next;
795      q = q->next;
796    }
797  }
798  b->root = a->root;
799}  /* copy */
800
801
802void maketree()
803{
804  /* constructs a binary tree from the pointers in curtree.nodep.
805     adds each node at location which yields highest "likelihood"
806     then rearranges the tree for greatest "likelihood" */
807  long i, j, which;
808  double bestlike, bstlike2=0, gotlike;
809  boolean lastrearr;
810  node *item, *nufork;
811
812  if (!usertree) {
813    if (jumb == 1) {
814      input_data();
815      examined = 0;
816    }
817    for (i = 1; i <= (spp); i++)
818      enterorder[i - 1] = i;
819    if (jumble)
820      randumize(seed, enterorder);
821    curtree.root = curtree.nodep[enterorder[0] - 1];
822    add(curtree.nodep[enterorder[0] - 1], curtree.nodep[enterorder[1] - 1],
823        curtree.nodep[spp]);
824    if (progress) {
825      printf("Adding species:\n");
826      writename(0, 2, enterorder);
827#ifdef WIN32
828      phyFillScreenColor();
829#endif
830    }
831    lastrearr = false;
832    for (i = 3; i <= (spp); i++) {
833      bestyet = -10000000.0;
834      item = curtree.nodep[enterorder[i - 1] - 1];
835      nufork = curtree.nodep[spp + i - 2];
836      addpreorder(curtree.root, item, nufork);
837      add(there, item, nufork);
838      like = bestyet;
839      rearrange(&curtree.root);
840      evaluate(curtree.root);
841      examined--;
842      if (progress) {
843        writename(i - 1, 1, enterorder);
844#ifdef WIN32
845        phyFillScreenColor();
846#endif
847      }
848      lastrearr = (i == spp);
849      if (lastrearr) {
850        if (progress) {
851          printf("\nDoing global rearrangements\n");
852          printf("  !");
853          for (j = 1; j <= (nonodes); j++)
854            putchar('-');
855          printf("!\n");
856#ifdef WIN32
857          phyFillScreenColor();
858#endif
859        }
860        bestlike = bestyet;
861        do {
862          gotlike = bestlike;
863          if (progress)
864            printf("   ");
865          for (j = 0; j < (nonodes); j++) {
866            there = curtree.root;
867            bestyet = -32000.0;
868            item = curtree.nodep[j];
869            if (item != curtree.root) {
870              re_move(&item, &nufork);
871              there = curtree.root;
872              addpreorder(curtree.root, item, nufork);
873              add(there, item, nufork);
874            }
875            if (progress) {
876              putchar('.');
877              fflush(stdout);
878            }
879          }
880          if (progress) {
881            putchar('\n');
882#ifdef WIN32
883            phyFillScreenColor();
884#endif
885          }
886        } while (bestlike > gotlike);
887        if (njumble > 1) {
888          if (jumb == 1 || (jumb > 1 && bestlike > bstlike2)) {
889            copy_(&curtree, &bestree);
890            bstlike2 = bestlike;
891          }
892        }
893      }
894    }
895    if (njumble == jumb) {
896      if (njumble > 1)
897        copy_(&bestree, &curtree);
898      evaluate(curtree.root);
899      printree(curtree.root, treeprint, false, true);
900      describe();
901    }
902  } else {
903    input_data();
904    openfile(&intree,INTREE,"input tree file","r",progname,intreename);
905    numtrees = countsemic(&intree);
906    if (treeprint)
907      fprintf(outfile, "\n\nUser-defined trees:\n\n");
908    names = (boolean *)Malloc(spp*sizeof(boolean));
909    which = 1;
910    while (which <= numtrees ) {
911      treeread2 (intree, &curtree.root, curtree.nodep,
912        lengths, &trweight, &goteof, &haslengths, &spp);
913      evaluate(curtree.root);
914      printree(curtree.root, treeprint, false, true);
915      describe();
916      which++;
917    }
918    FClose(intree);
919    free(names);
920  }
921  if (jumb == njumble && progress) {
922    printf("\nOutput written to file \"%s\"\n\n", outfilename);
923    if (trout)
924      printf("Tree also written onto file \"%s\"\n", outtreename);
925    putchar('\n');
926  }
927}  /* maketree */
928
929
930int main(int argc, Char *argv[])
931{  /* Fitch-Margoliash criterion with contemporary tips */
932#ifdef MAC
933  argc = 1;                /* macsetup("Kitsch","");        */
934  argv[0] = "Kitsch";
935#endif
936  init(argc,argv);
937  /* reads in spp, options, and the data, then calls maketree to
938     construct the tree */
939  progname = argv[0];
940  openfile(&infile,INFILE,"input file","r",argv[0],infilename);
941  openfile(&outfile,OUTFILE,"output file","w",argv[0],outfilename);
942
943  ibmpc = IBMCRT;
944  ansi = ANSICRT;
945  mulsets = false;
946  firstset = true;
947  datasets = 1;
948  doinit();
949  openfile(&outtree,OUTTREE,"output tree file","w",argv[0],outtreename);
950  for (ith = 1; ith <= datasets; ith++) {
951    if (datasets > 1) {
952      fprintf(outfile, "\nData set # %ld:\n",ith);
953      if (progress)
954        printf("\nData set # %ld:\n",ith);
955    }
956    getinput();
957    for (jumb = 1; jumb <= njumble; jumb++)
958      maketree();
959    firstset = false;
960    if (eoln(infile) && (ith < datasets))
961      scan_eoln(infile);
962  }
963  FClose(infile);
964  FClose(outfile);
965  FClose(outtree);
966#ifdef MAC
967  fixmacfile(outfilename);
968  fixmacfile(outtreename);
969#endif
970#ifdef WIN32
971  phyRestoreConsoleAttributes();
972#endif
973  printf("Done.\n\n");
974  return 0;
975}  /* Fitch-Margoliash criterion with contemporary tips */
Note: See TracBrowser for help on using the repository browser.