source: tags/initial/GDE/PHYLIP/coallike.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1#include "phylip.h"
2
3/* version 3.52c.  (c) Copyright 1993 by Joseph Felsenstein.  Permission is
4   granted to copy and use this program provided that no fee is charged for
5   it and provided that this copyright notice is not removed */
6
7#define epsilon         0.000001  /* a small number                          */
8
9#define ansi0           true
10#define ibmpc0          false
11#define vt520           false
12
13typedef struct node {             /* describes a tip species or an ancestor */
14  struct node *ancestor, *leftdesc, *rtdesc;   /* pointers to nodes         */
15  long index;                           /* number of the node               */
16  boolean tip;                          /* present species are tips of tree */
17  double v, tyme;
18} node;
19
20typedef node **pointarray;
21typedef double *timearray;
22
23
24FILE       *treefile, *outfile;
25long        i, j, n, rep, spp, nonodes,maxsp;
26double      b, b1, bnum, bdenom, mintheta, maxtheta, lnlike, summ, summax;
27boolean     ansi, ibmpc, vt52, progress;
28node       *root;
29pointarray  treenode;   /* pointers to all nodes in tree */
30timearray   thyme;
31double      *sum;
32double      *a;
33char        ch;
34
35openfile(fp,filename,mode,application,perm)
36FILE **fp;
37char *filename;
38char *mode;
39char *application;
40char *perm;
41{
42  FILE *of;
43  char file[100];
44  strcpy(file,filename);
45  while (1){
46    of = fopen(file,mode);
47    if (of)
48      break;
49    else {
50      switch (*mode){
51      case 'r':
52        printf("%s:  can't read %s\n",application,file);
53        file[0]='\0';
54        while (file[0] =='\0'){
55          printf("Please enter a new filename>");
56          gets(file);}
57        break;
58      case 'w':
59        printf("%s: can't write %s\n",application,file);
60        file[0] = '\0';
61        while (file[0] =='\0'){
62          printf("Please enter a new filename>");
63          gets(file);}
64        break;
65      }
66    }
67  }
68  *fp=of;
69  if (perm != NULL)
70    strcpy(perm,file);
71}
72void preread(file,filename,species,trees)
73     FILE **file;
74     char *filename;
75     long *species;
76     long *trees;
77{
78 long colons,semicolons;
79  char c;
80  FILE *fp;
81  colons     = 0;
82  semicolons = 0;
83  fp         = (*file);
84  while (!feof(fp)){
85    c = fgetc(fp);
86    if (c == ':')
87      colons++;
88    else if (c == ';')
89      semicolons++;
90  }
91(*species) = (colons/semicolons/2)+1;
92(*trees)   = semicolons;
93fclose(*file);
94(*file)    = fopen(filename,"r");
95}
96
97void uppercase(ch)
98Char *ch;
99{
100  /* convert ch to upper case -- either ASCII or EBCDIC */
101  (*ch) = isupper(*ch) ? (*ch) : toupper(*ch);
102}  /* uppercase */
103
104
105void getoptions()
106{
107  /* interactively set options */
108  Char ch;
109  char in[100];
110  boolean done, badoption;
111
112  done = false;
113  ch = ' ';
114  mintheta = 0.0001;
115  maxtheta = 100.0;
116  ansi = ansi0;
117  ibmpc = ibmpc0;
118  vt52 = vt520;
119  progress = false;
120  badoption = false;
121  do {
122    printf(ansi ? "\033[2J\033[H" :
123           vt52 ? "\033E\033H"    : "\n");
124    if (badoption)
125      printf("\nNot a possible option!\n");
126    if (!done && ch == 'Y') {
127      putchar('\n');
128      if (mintheta > maxtheta)
129        printf("Minimum and maximum theta values are out of order\n");
130    }
131    printf("\nCoalescent likelihoods from sampled trees, version %s\n\n",
132           VERSION);
133    printf("Settings for this run:\n");
134    printf("  N   Minimum value of theta            %12.7f\n", mintheta);
135    printf("  X   Maximum value of theta            %12.5f\n", maxtheta);
136    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
137           ibmpc ? "IBM PC" :
138           ansi  ? "ANSI"   :
139           vt52  ? "VT52"   : "(none)");
140
141    printf("  1  Print indications of progress of run  %s\n",
142           (progress ? "Yes" : "No"));
143    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
144    in[0]=0;
145    gets(in);
146    ch = in[0];
147    if (ch == '\n')
148      ch = ' ';
149    uppercase(&ch);
150    done = (ch == 'Y' && mintheta < maxtheta);
151    if (!done) {
152      if (ch == 'N' || ch == 'X' || ch == '1' || ch == '0') {
153        badoption = false;
154        switch (ch) {
155
156        case 'N':
157          do {
158            printf("Minimum value of theta?\n");
159            scanf("%lg%*[^\n]", &mintheta);
160            getchar();
161            if (mintheta <= 0.0)
162              printf("Must be positive\n");
163          } while (mintheta <= 0.0);
164          break;
165
166        case 'X':
167          do {
168            printf("Maximum value of theta?\n");
169            scanf("%lg%*[^\n]", &maxtheta);
170            getchar();
171            if (maxtheta <= 0.0)
172              printf("Must be positive\n");
173          } while (mintheta <= 0.0);
174          break;
175
176        case '0':
177          if (ibmpc) {
178            ibmpc = false;
179            vt52 = true;
180          } else {
181            if (vt52) {
182              vt52 = false;
183              ansi = true;
184            } else if (ansi)
185              ansi = false;
186            else
187              ibmpc = true;
188          }
189          break;
190
191        case '1':
192          progress = !progress;
193          break;
194        }
195      } else
196        badoption = true;
197    }
198  } while (!done);
199}  /* getoptions */
200
201
202void setup(p)
203node **p;
204{
205  /* create an empty tree node */
206  if (rep == 1)
207    *p = (node *)Malloc(sizeof(node));
208  (*p)->leftdesc = NULL;
209  (*p)->rtdesc = NULL;
210  (*p)->ancestor = NULL;
211}  /* setup */
212
213
214
215void getch(ch)
216Char *ch;
217{
218  /* get next nonblank character */
219  do {
220    if (eoln(treefile)) {
221      fscanf(treefile, "%*[^\n]");
222      getc(treefile);
223    }
224    *ch = getc(treefile);
225    if (*ch == '\n')
226      *ch = ' ';
227  } while (*ch == ' ');
228}  /* getch */
229
230void processlength(p)
231node *p;
232{
233  long digit, ordzero;
234  double valyew, divisor;
235  boolean pointread;
236
237  ordzero = '0';
238  pointread = false;
239  valyew = 0.0;
240  divisor = 1.0;
241  getch(&ch);
242  digit = ch - ordzero;
243  while ((unsigned long)digit <= 9 || ch == '.') {
244    if (ch == '.')
245      pointread = true;
246    else {
247      valyew = valyew * 10.0 + digit;
248      if (pointread)
249        divisor *= 10.0;
250    }
251    getch(&ch);
252    digit = ch - ordzero;
253  }
254  p->v = valyew / divisor;
255}  /* processlength */
256
257void findch(c)
258Char c;
259{
260  /* scan forward until find character c */
261  if (ch == c)
262    return;
263  do {
264    if (eoln(treefile)) {
265      fscanf(treefile, "%*[^\n]");
266      getc(treefile);
267    }
268    ch = getc(treefile);
269    if (ch == '\n')
270      ch = ' ';
271  } while (ch != c);
272}  /* findch */
273
274void findeither(c1, c2)
275Char c1, c2;
276{  /* findch */
277  /* scan forward until find either character c1 or c2 */
278  if (ch == c2 || ch == c2)
279    return;
280  do {
281    if (eoln(treefile)) {
282      fscanf(treefile, "%*[^\n]");
283      getc(treefile);
284    }
285    ch = getc(treefile);
286    if (ch == '\n')
287      ch = ' ';
288  } while (ch != c1 && ch != c2);
289}  /* findch */
290
291void addelement(p, nextnode,nexttip)
292node **p;
293long *nextnode,*nexttip;
294{
295  /* recursive procedure adds nodes to user-defined tree */
296  node *q;
297  long n;
298
299  getch(&ch);
300  if (ch == '(') {
301    (*nextnode)++;
302    setup(&treenode[(*nextnode) - 1]);
303    q = treenode[(*nextnode) - 1];
304    addelement(&q->leftdesc, nextnode,nexttip);
305    q->leftdesc->ancestor = q;
306    findch(',');
307    addelement(&q->rtdesc, nextnode,nexttip);
308    q->rtdesc->ancestor = q;
309    findeither(':', ';');
310    *p = q;
311  } else {
312    n = 1;
313    do {
314      if (eoln(treefile)) {
315        fscanf(treefile, "%*[^\n]");
316        getc(treefile);
317      }
318      ch = getc(treefile);
319      if (ch == '\n')
320        ch = ' ';
321      n++;
322    } while (ch != ':' && ch != ',' && ch != ')' && ch != ';');
323    (*nexttip)++;
324    setup(&treenode[(*nexttip) - 1]);
325    *p = treenode[(*nexttip) - 1];
326  }
327  if (ch == ':')
328    processlength(*p);
329}  /* addelement */
330
331
332void treeread()
333{
334  /* read in user-defined tree and set it up */
335/* Local variables for treeread */
336  long i;
337  long nextnode, nexttip;
338
339  nexttip = 0;
340  if (rep == 1)
341    nextnode = maxsp;
342  else
343    nextnode = spp;
344  addelement(&treenode[nextnode], &nextnode,&nexttip);
345  if (rep == 1) {
346    spp = nexttip;
347    nonodes = spp + nextnode - maxsp;
348    for (i = maxsp; i < nextnode; i++) {
349      treenode[spp + i - maxsp] = treenode[i];
350      treenode[i] = NULL;
351    }
352    for (i = 1; i <= nonodes; i++)
353      treenode[i - 1]->tip = (i <= spp);
354  }
355  root = treenode[spp];
356  root->ancestor = NULL;
357}  /* treeread */
358
359
360void gettymes(p)
361node *p;
362{
363  if (p->tip) {
364    p->tyme = 0.0;
365    return;
366  }
367  gettymes(p->leftdesc);
368  gettymes(p->rtdesc);
369  p->tyme = p->leftdesc->tyme - p->leftdesc->v;
370}  /* gettymes */
371
372
373void shellsort(a, n)
374double *a;
375long n;
376{
377  /* Shell sort */
378  long gap, i, j;
379  double rtemp;
380
381  gap = n / 2;
382  while (gap > 0) {
383    for (i = gap + 1; i <= n; i++) {
384      j = i - gap;
385      while (j > 0) {
386        if (a[j - 1] < a[j + gap - 1]) {
387          rtemp = a[j - 1];
388          a[j - 1] = a[j + gap - 1];
389          a[j + gap - 1] = rtemp;
390        }
391        j -= gap;
392      }
393    }
394    gap /= 2;
395  }
396}  /* shellsort */
397
398
399void estimate()
400{
401  long i;
402  double n, tt;
403
404  sum[rep - 1] = 0.0;
405  n = spp;
406  for (i = 1; i < spp; i++) {
407    if (i == 1)
408      tt = -thyme[0];
409    else
410      tt = thyme[i - 2] - thyme[i - 1];
411    sum[rep - 1] += (n - i) * (n - i + 1) * tt;
412  }
413}  /* estimate */
414
415
416
417main(argc, argv)
418int argc;
419Char *argv[];
420{  /* Coalescent log-likelihood curve */
421  char outfilename[100],trfilename[100];
422  long species,trees;
423#ifdef MAC
424  macsetup("Coallike","");
425#endif
426  openfile(&treefile,TREEFILE,"r",argv[0],trfilename);
427  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
428  preread(&treefile,trfilename,&species,&trees);
429  thyme     =(double *)Malloc((2*species - 1) * sizeof(double));
430  treenode =(node **)Malloc((2*species - 1) * sizeof(node *));
431  sum      =(double *)Malloc(trees*sizeof(double));
432    maxsp = species+1;
433  spp      = species;
434  getoptions();
435  a = (double *)Malloc((1+(long)(log10(maxtheta/mintheta))*3)*sizeof(double));
436  b = mintheta;
437  b1 = exp(log(10.0) * (long)floor(log(b) / log(10.0) + 0.5));
438  bdenom = (long)floor(1 / b1 + 0.5);
439  bnum = (long)floor(b / b1 + 0.5);
440  i = 0;
441  do {
442    i++;
443    a[i - 1] = bnum / bdenom;
444    if (fabs(bnum - 2.0) < epsilon)
445      bnum = (long)floor(2.5 * bnum + 0.5);
446    else
447      bnum *= 2.0;
448    if (fabs(bnum - 10.0) < epsilon) {
449      bnum = 1.0;
450      bdenom /= 10.0;
451    }
452  } while (bnum / bdenom <= maxtheta * (1.0 + epsilon));
453  n = i;
454  if (progress)
455    putchar('\n');
456  for (rep=1;rep<=trees;++i){
457    treeread();
458    if (progress && rep % 100 == 0)
459      printf("Read tree number %6ld\n", rep);
460
461    if (eoln(treefile) & (!eof(treefile))) {
462      fscanf(treefile, "%*[^\n]");
463      getc(treefile);
464    }
465    gettymes(root);
466    for (i = spp + 1; i <= nonodes; i++)
467      thyme[i - spp - 1] = treenode[i - 1]->tyme;
468    shellsort(thyme, spp - 1);
469    estimate();
470    rep++;
471  }
472  fprintf(outfile, "\n    Read %5ld trees of %4ld  tips each\n\n",
473          rep - 1, spp);
474  fprintf(outfile, "      theta        Ln(Likelihood)\n");
475  fprintf(outfile, "      -----        --------------\n");
476  for (i = 1; i <= n; i++) {
477    summax = sum[0];
478    for (j = 2; j < rep; j++) {
479      if (sum[j - 1] < summax)
480        summax = sum[j - 1];
481    }
482    summ = 0.0;
483    for (j = 1; j < rep; j++) {
484      if ((summax - sum[j - 1]) / a[i - 1] > -20.0)
485        summ += exp((summax - sum[j - 1]) / a[i - 1]);
486    }
487    lnlike = (1 - spp) * log(a[i - 1]) - summax / a[i - 1] - log(rep - 1.0) +
488             log(summ);
489    fprintf(outfile, "%12.5f%20.5f\n", a[i - 1], lnlike);
490  }
491  putc('\n', outfile);
492  printf("\nResults written on output file\n\n");
493  FClose(treefile);
494  FClose(outfile);
495#ifdef MAC
496  fixmacfile(outfilename);
497#endif
498  exit(0);
499}  /* coalescent likelihoods */
500
501
502int eof(f)
503FILE *f;
504{
505    register int ch;
506
507    if (feof(f))
508        return 1;
509    if (f == stdin)
510        return 0;
511    ch = getc(f);
512    if (ch == EOF)
513        return 1;
514    ungetc(ch, f);
515    return 0;
516  }
517
518
519int eoln(f)
520FILE *f;
521{
522    register int ch;
523
524    ch = getc(f);
525    if (ch == EOF)
526        return 1;
527    ungetc(ch, f);
528    return (ch == '\n');
529  }
530
531void memerror()
532{
533printf("Error allocating memory\n");
534exit(-1);
535}
536
537MALLOCRETURN *mymalloc(x)
538long x;
539{
540MALLOCRETURN *mem;
541mem = (MALLOCRETURN *)malloc(x);
542if (!mem)
543  memerror();
544else
545  return (MALLOCRETURN *)mem;
546}
547
548
Note: See TracBrowser for help on using the repository browser.