source: trunk/GDE/PHYLIP/neighbor.c

Last change on this file was 19480, checked in by westram, 15 months ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 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 Mary Kuhner, Jon Yamato, Joseph Felsenstein, Akiko Fuseki,
7   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
12#ifndef OLDC
13/* function prototypes */
14void getoptions(void);
15void allocrest(void);
16void doinit(void);
17void inputoptions(void);
18void getinput(void);
19void describe(node *, double);
20void summarize(void);
21void nodelabel(boolean);
22void jointree(void);
23void maketree(void);
24/* function prototypes */
25#endif
26
27
28Char infilename[FNMLNGTH], outfilename[FNMLNGTH], outtreename[FNMLNGTH];
29long nonodes2, outgrno, col, datasets, ith;
30long inseed;
31vector *x;
32intvector *reps;
33boolean jumble, lower, upper, outgropt, replicates, trout,
34               printdata, progress, treeprint, mulsets, njoin;
35tree curtree;
36longer seed;
37long *enterorder;
38Char progname[20];
39
40/* variables for maketree, propagated globally for C version: */
41node **cluster;
42
43
44void getoptions()
45{
46  /* interactively set options */
47  long inseed0 = 0, loopcount;
48  Char ch;
49
50  fprintf(outfile, "\nNeighbor-Joining/UPGMA method version %s\n\n",VERSION);
51  putchar('\n');
52  jumble = false;
53  lower = false;
54  outgrno = 1;
55  outgropt = false;
56  replicates = false;
57  trout = true;
58  upper = false;
59  printdata = false;
60  progress = true;
61  treeprint = true;
62  njoin = true;
63  loopcount = 0;
64  for(;;) {
65    cleerhome();
66    printf("\nNeighbor-Joining/UPGMA method version %s\n\n",VERSION);
67    printf("Settings for this run:\n");
68    printf("  N       Neighbor-joining or UPGMA tree?  %s\n",
69           (njoin ? "Neighbor-joining" : "UPGMA"));
70    if (njoin) {
71      printf("  O                        Outgroup root?");
72      if (outgropt)
73        printf("  Yes, at species number%3ld\n", outgrno);
74      else
75        printf("  No, use as outgroup species%3ld\n", outgrno);
76    }
77    printf("  L         Lower-triangular data matrix?  %s\n",
78           (lower ? "Yes" : "No"));
79    printf("  R         Upper-triangular data matrix?  %s\n",
80           (upper ? "Yes" : "No"));
81    printf("  S                        Subreplicates?  %s\n",
82           (replicates ? "Yes" : "No"));
83    printf("  J     Randomize input order of species?");
84    if (jumble)
85      printf("  Yes (random number seed =%8ld)\n", inseed0);
86    else
87      printf("  No. Use input order\n");
88    printf("  M           Analyze multiple data sets?");
89    if (mulsets)
90      printf("  Yes, %2ld sets\n", datasets);
91    else
92      printf("  No\n");
93    printf("  0   Terminal type (IBM PC, ANSI, none)?  %s\n",
94           (ibmpc ? "IBM PC" : ansi ? "ANSI" : "(none)"));
95    printf("  1    Print out the data at start of run  %s\n",
96           (printdata ? "Yes" : "No"));
97    printf("  2  Print indications of progress of run  %s\n",
98           (progress ? "Yes" : "No"));
99    printf("  3                        Print out tree  %s\n",
100           (treeprint ? "Yes" : "No"));
101    printf("  4       Write out trees onto tree file?  %s\n",
102           (trout ? "Yes" : "No"));
103    printf("\n\n  Y to accept these or type the letter for one to change\n");
104#ifdef WIN32
105    phyFillScreenColor();
106#endif
107    scanf("%c%*[^\n]", &ch);
108    getchar();
109    if (ch == '\n')
110      ch = ' ';
111    uppercase(&ch);
112    if  (ch == 'Y')
113      break;
114    if (strchr("NJOULRSM01234",ch) != NULL){
115      switch (ch) {
116       
117      case 'J':
118        jumble = !jumble;
119         if (jumble)
120          initseed(&inseed, &inseed0, seed);
121        break;
122       
123      case 'L':
124        lower = !lower;
125        break;
126       
127      case 'O':
128        outgropt = !outgropt;
129        if (outgropt)
130          initoutgroup(&outgrno, spp);
131        else
132          outgrno = 1;
133        break;
134       
135      case 'R':
136        upper = !upper;
137        break;
138       
139      case 'S':
140        replicates = !replicates;
141        break;
142       
143      case 'N':
144        njoin = !njoin;
145        break;
146       
147      case 'M':
148        mulsets = !mulsets;
149        if (mulsets)
150          initdatasets(&datasets);
151        jumble = true;
152         if (jumble)
153          initseed(&inseed, &inseed0, seed);
154        break;
155       
156      case '0':
157        initterminal(&ibmpc, &ansi);
158        break;
159       
160      case '1':
161        printdata = !printdata;
162        break;
163       
164      case '2':
165        progress = !progress;
166        break;
167       
168      case '3':
169        treeprint = !treeprint;
170        break;
171       
172      case '4':
173        trout = !trout;
174        break;
175      }
176    } else
177      printf("Not a possible option!\n");
178    countup(&loopcount, 100);
179  }
180}  /* getoptions */
181
182
183void allocrest()
184{
185  long i;
186
187  x = (vector *)Malloc(spp*sizeof(vector));
188  for (i = 0; i < spp; i++)
189    x[i] = (vector)Malloc(spp*sizeof(double));
190  reps = (intvector *)Malloc(spp*sizeof(intvector));
191  for (i = 0; i < spp; i++)
192    reps[i] = (intvector)Malloc(spp*sizeof(long));
193  nayme = (naym *)Malloc(spp*sizeof(naym));
194  enterorder = (long *)Malloc(spp*sizeof(long));
195  cluster = (node **)Malloc(spp*sizeof(node *));
196}  /* allocrest */
197
198
199void doinit()
200{
201  /* initializes variables */
202  node *p;
203
204  inputnumbers2(&spp, &nonodes2, 2);
205  nonodes2 += (njoin ? 0 : 1);
206  getoptions();
207  alloctree(&curtree.nodep, nonodes2+1);
208  p = curtree.nodep[nonodes2]->next->next;
209  curtree.nodep[nonodes2]->next = curtree.nodep[nonodes2];
210  free(p);
211  allocrest();
212}  /* doinit */
213
214
215void inputoptions()
216{
217  /* read options information */
218
219  if (ith != 1)
220    samenumsp2(ith);
221  putc('\n', outfile);
222  if (njoin)
223    fprintf(outfile, " Neighbor-joining method\n");
224  else
225    fprintf(outfile, " UPGMA method\n");
226  fprintf(outfile, "\n Negative branch lengths allowed\n\n");
227}  /* inputoptions */
228
229
230void describe(node *p, double height)
231{
232  /* print out information for one branch */
233  long i;
234  node *q;
235
236  q = p->back;
237  if (njoin)
238    fprintf(outfile, "%4ld          ", q->index - spp);
239  else
240    fprintf(outfile, "%4ld     ", q->index - spp);
241  if (p->tip) {
242    for (i = 0; i < nmlngth; i++)
243      putc(nayme[p->index - 1][i], outfile);
244    putc(' ', outfile);
245  } else {
246    if (njoin)
247      fprintf(outfile, "%4ld       ", p->index - spp);
248    else {
249      fprintf(outfile, "%4ld       ", p->index - spp);
250    }
251  }
252  if (njoin)
253    fprintf(outfile, "%12.5f\n", q->v);
254  else
255    fprintf(outfile, "%10.5f      %10.5f\n", q->v, q->v+height);
256  if (!p->tip) {
257    describe(p->next->back, height+q->v);
258    describe(p->next->next->back, height+q->v);
259  }
260}  /* describe */
261
262
263void summarize()
264{
265  /* print out branch lengths etc. */
266  putc('\n', outfile);
267  if (njoin) {
268    fprintf(outfile, "remember:");
269    if (outgropt)
270      fprintf(outfile, " (although rooted by outgroup)");
271    fprintf(outfile, " this is an unrooted tree!\n");
272  }
273  if (njoin) {
274    fprintf(outfile, "\nBetween        And            Length\n");
275    fprintf(outfile, "-------        ---            ------\n");
276  } else {
277    fprintf(outfile, "From     To            Length          Height\n");
278    fprintf(outfile, "----     --            ------          ------\n");
279  }
280  describe(curtree.start->next->back, 0.0);
281  describe(curtree.start->next->next->back, 0.0);
282  if (njoin)
283    describe(curtree.start->back, 0.0);
284  fprintf(outfile, "\n\n");
285}  /* summarize */
286
287
288void nodelabel(boolean isnode)
289{
290  if (isnode)
291    printf("node");
292  else
293    printf("species");
294}  /* nodelabel */
295
296
297void jointree()
298{
299  /* calculate the tree */
300  long nc, nextnode, mini=0, minj=0, i, j, ia, ja, ii, jj, nude, local_iter;
301  double fotu2, total, tmin, dio, djo, bi, bj, bk, dmin=0, da;
302  long el[3];
303  vector av;
304  intvector oc;
305
306  double *R;   /* added in revisions by Y. Ina */
307  R = (double *)Malloc(spp * sizeof(double));
308
309  for (i = 0; i <= spp - 2; i++) {
310    for (j = i + 1; j < spp; j++) {
311      da = (x[i][j] + x[j][i]) / 2.0;
312      x[i][j] = da;
313      x[j][i] = da;
314    }
315  }
316  /* First initialization */
317  fotu2 = spp - 2.0;
318  nextnode = spp + 1;
319  av = (vector)Malloc(spp*sizeof(double));
320  oc = (intvector)Malloc(spp*sizeof(long));
321  for (i = 0; i < spp; i++) {
322    av[i] = 0.0;
323    oc[i] = 1;
324  }
325  /* Enter the main cycle */
326  if (njoin)
327    local_iter = spp - 3;
328  else
329    local_iter = spp - 1;
330  for (nc = 1; nc <= local_iter; nc++) {
331    for (j = 2; j <= spp; j++) {
332      for (i = 0; i <= j - 2; i++)
333        x[j - 1][i] = x[i][j - 1];
334    }
335    tmin = 99999.0;
336    /* Compute sij and minimize */
337    if (njoin) {     /* many revisions by Y. Ina from here ... */
338      for (i = 0; i < spp; i++)
339        R[i] = 0.0;
340      for (ja = 2; ja <= spp; ja++) {
341        jj = enterorder[ja - 1];
342        if (cluster[jj - 1] != NULL) {
343          for (ia = 0; ia <= ja - 2; ia++) {
344            ii = enterorder[ia];
345            if (cluster[ii - 1] != NULL) {
346              R[ii - 1] += x[ii - 1][jj - 1];
347              R[jj - 1] += x[ii - 1][jj - 1];
348            }
349          }
350        }
351      }
352    } /* ... to here */
353    for (ja = 2; ja <= spp; ja++) {
354      jj = enterorder[ja - 1];
355      if (cluster[jj - 1] != NULL) {
356        for (ia = 0; ia <= ja - 2; ia++) {
357          ii = enterorder[ia];
358          if (cluster[ii - 1] != NULL) {
359            if (njoin) {
360              total = fotu2 * x[ii - 1][jj - 1] - R[ii - 1] - R[jj - 1];
361               /* this statement part of revisions by Y. Ina */
362            } else
363              total = x[ii - 1][jj - 1];
364            if (total < tmin) {
365              tmin = total;
366              mini = ii;
367              minj = jj;
368            }
369          }
370        }
371      }
372    }
373    /* compute lengths and print */
374    if (njoin) {
375      dio = 0.0;
376      djo = 0.0;
377      for (i = 0; i < spp; i++) {
378        dio += x[i][mini - 1];
379        djo += x[i][minj - 1];
380      }
381      dmin = x[mini - 1][minj - 1];
382      dio = (dio - dmin) / fotu2;
383      djo = (djo - dmin) / fotu2;
384      bi = (dmin + dio - djo) * 0.5;
385      bj = dmin - bi;
386      bi -= av[mini - 1];
387      bj -= av[minj - 1];
388    } else {
389      bi = x[mini - 1][minj - 1] / 2.0 - av[mini - 1];
390      bj = x[mini - 1][minj - 1] / 2.0 - av[minj - 1];
391      av[mini - 1] += bi;
392    }
393    if (progress) {
394      printf("Cycle %3ld: ", local_iter - nc + 1);
395      if (njoin)
396        nodelabel((boolean)(av[mini - 1] > 0.0));
397      else
398        nodelabel((boolean)(oc[mini - 1] > 1.0));
399      printf(" %ld (%10.5f) joins ", mini, bi);
400      if (njoin)
401        nodelabel((boolean)(av[minj - 1] > 0.0));
402      else
403        nodelabel((boolean)(oc[minj - 1] > 1.0));
404      printf(" %ld (%10.5f)\n", minj, bj);
405#ifdef WIN32
406      phyFillScreenColor();
407#endif
408    }
409    hookup(curtree.nodep[nextnode - 1]->next, cluster[mini - 1]);
410    hookup(curtree.nodep[nextnode - 1]->next->next, cluster[minj - 1]);
411    cluster[mini - 1]->v = bi;
412    cluster[minj - 1]->v = bj;
413    cluster[mini - 1]->back->v = bi;
414    cluster[minj - 1]->back->v = bj;
415    cluster[mini - 1] = curtree.nodep[nextnode - 1];
416    cluster[minj - 1] = NULL;
417    nextnode++;
418    if (njoin)
419      av[mini - 1] = dmin * 0.5;
420    /* re-initialization */
421    fotu2 -= 1.0;
422    for (j = 0; j < spp; j++) {
423      if (cluster[j] != NULL) {
424        if (njoin) {
425          da = (x[mini - 1][j] + x[minj - 1][j]) * 0.5;
426          if (mini - j - 1 < 0)
427            x[mini - 1][j] = da;
428          if (mini - j - 1 > 0)
429            x[j][mini - 1] = da;
430        } else {
431          da = x[mini - 1][j] * oc[mini - 1] + x[minj - 1][j] * oc[minj - 1];
432          da /= oc[mini - 1] + oc[minj - 1];
433          x[mini - 1][j] = da;
434          x[j][mini - 1] = da;
435        }
436      }
437    }
438    for (j = 0; j < spp; j++) {
439      x[minj - 1][j] = 0.0;
440      x[j][minj - 1] = 0.0;
441    }
442    oc[mini - 1] += oc[minj - 1];
443  }
444  /* the last cycle */
445  nude = 1;
446  for (i = 1; i <= spp; i++) {
447    if (cluster[i - 1] != NULL) {
448      el[nude - 1] = i;
449      nude++;
450    }
451  }
452  if (!njoin) {
453    curtree.start = cluster[el[0] - 1];
454    curtree.start->back = NULL;
455    free(av);
456    free(oc);
457    return;
458  }
459  bi = (x[el[0] - 1][el[1] - 1] + x[el[0] - 1][el[2] - 1] - x[el[1] - 1]
460        [el[2] - 1]) * 0.5;
461  bj = x[el[0] - 1][el[1] - 1] - bi;
462  bk = x[el[0] - 1][el[2] - 1] - bi;
463  bi -= av[el[0] - 1];
464  bj -= av[el[1] - 1];
465  bk -= av[el[2] - 1];
466  if (progress) {
467    printf("last cycle:\n");
468    putchar(' ');
469    nodelabel((boolean)(av[el[0] - 1] > 0.0));
470    printf(" %ld  (%10.5f) joins ", el[0], bi);
471    nodelabel((boolean)(av[el[1] - 1] > 0.0));
472    printf(" %ld  (%10.5f) joins ", el[1], bj);
473    nodelabel((boolean)(av[el[2] - 1] > 0.0));
474    printf(" %ld  (%10.5f)\n", el[2], bk);
475#ifdef WIN32
476    phyFillScreenColor();
477#endif
478  }
479  hookup(curtree.nodep[nextnode - 1], cluster[el[0] - 1]);
480  hookup(curtree.nodep[nextnode - 1]->next, cluster[el[1] - 1]);
481  hookup(curtree.nodep[nextnode - 1]->next->next, cluster[el[2] - 1]);
482  cluster[el[0] - 1]->v = bi;
483  cluster[el[1] - 1]->v = bj;
484  cluster[el[2] - 1]->v = bk;
485  cluster[el[0] - 1]->back->v = bi;
486  cluster[el[1] - 1]->back->v = bj;
487  cluster[el[2] - 1]->back->v = bk;
488  curtree.start = cluster[el[0] - 1]->back;
489  free(av);
490  free(oc);
491}  /* jointree */
492
493
494void maketree()
495{
496  /* construct the tree */
497  long i ;
498
499  inputdata(replicates, printdata, lower, upper, x, reps);
500  if (njoin && (spp < 3)) {
501    printf("\nERROR: Neighbor-Joining runs must have at least 3 species\n\n");
502    exxit(-1);
503  }
504  if (progress)
505    putchar('\n');
506  if (ith == 1)
507    setuptree(&curtree, nonodes2 + 1);
508  for (i = 1; i <= spp; i++)
509    enterorder[i - 1] = i;
510  if (jumble)
511    randumize(seed, enterorder);
512  for (i = 0; i < spp; i++)
513    cluster[i] = curtree.nodep[i];
514  jointree();
515  if (njoin)
516    curtree.start = curtree.nodep[outgrno - 1]->back;
517  printree(curtree.start, treeprint, njoin, (boolean)(!njoin));
518  if (treeprint)
519    summarize();
520  if (trout) {
521    col = 0;
522    if (njoin)
523      treeout(curtree.start, &col, 0.43429448222, njoin, curtree.start);
524    else
525      curtree.root = curtree.start,
526      treeoutr(curtree.start,&col,&curtree);
527  }
528  if (progress) {
529    printf("\nOutput written on file \"%s\"\n\n", outfilename);
530    if (trout)
531      printf("Tree written on file \"%s\"\n\n", outtreename);
532  }
533}  /* maketree */
534
535
536int main(int argc, Char *argv[])
537{  /* main program */
538#ifdef MAC
539  argc = 1;                /* macsetup("Neighbor","");                */
540  argv[0] = "Neighbor";
541#endif
542  init(argc, argv);
543  openfile(&infile,INFILE,"input file", "r",argv[0],infilename);
544  openfile(&outfile,OUTFILE,"output file", "w",argv[0],outfilename);
545  ibmpc = IBMCRT;
546  ansi = ANSICRT;
547  mulsets = false;
548  datasets = 1;
549  doinit();
550  if (trout)
551    openfile(&outtree,OUTTREE,"output tree file", "w",argv[0],outtreename);
552  ith = 1;
553  while (ith <= datasets) {
554    if (datasets > 1) {
555      fprintf(outfile, "Data set # %ld:\n",ith);
556      if (progress)
557        printf("Data set # %ld:\n",ith);
558    }
559    inputoptions();
560    maketree();
561    if (eoln(infile) && (ith < datasets)) 
562      scan_eoln(infile);
563    ith++;
564  }
565  FClose(infile);
566  FClose(outfile);
567  FClose(outtree);
568#ifdef MAC
569  fixmacfile(outfilename);
570  fixmacfile(outtreename);
571#endif
572  printf("Done.\n\n");
573#ifdef WIN32
574  phyRestoreConsoleAttributes();
575#endif
576  return 0;
577}
578
579
580
581
582
Note: See TracBrowser for help on using the repository browser.