source: tags/initial/GDE/PHYLIP/contrast.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: 17.2 KB
Line 
1#include "phylip.h"
2
3/* version 3.52c. (c) Copyright 1993 by Joseph Felsenstein.
4   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
5   Permission is granted to copy and use this program provided no fee is
6   charged for it and provided that this copyright notice is not removed. */
7
8#define namelength      10   /* maximum number of characters in species name */
9
10#define ibmpc0          false
11#define ansi0           true
12#define vt520           false
13
14#define point           "."
15
16typedef double *phenotype;
17typedef Char naym[namelength];
18typedef struct node {
19  struct node *next, *back;
20  boolean tip;
21  long number;
22  phenotype view;
23  naym nayme;
24  double v, deltav;
25} node;
26
27typedef struct tree {
28  node **nodep;
29  node *start;
30} tree;
31
32Static FILE *infile, *outfile, *treefile;
33Static long numsp, numsp1, numsp2, chars, numtrees, j;
34Static phenotype *x, *cntrast;
35Static naym *nayms;
36Static boolean printdata, progress, reg, mulsets, ibmpc, vt52, ansi,
37       bifurcating;
38Static Char ch;
39
40/* Local variables for maketree, propagated globally for c version: */
41tree curtree;
42long contno;
43
44
45openfile(fp,filename,mode,application,perm)
46FILE **fp;
47char *filename;
48char *mode;
49char *application;
50char *perm;
51{
52  FILE *of;
53  char file[100];
54  strcpy(file,filename);
55  while (1){
56    of = fopen(file,mode);
57    if (of)
58      break;
59    else {
60      switch (*mode){
61      case 'r':
62        printf("%s:  can't read %s\n",application,file);
63        printf("Please enter a new filename>");
64        gets(file);
65        break;
66      case 'w':
67        printf("%s: can't write %s\n",application,file);
68        printf("Please enter a new filename>");
69        gets(file);
70        break;
71      }
72    }
73  }
74  *fp=of;
75  if (perm != NULL)
76    strcpy(perm,file);
77}
78
79
80
81void uppercase(ch)
82Char *ch;
83{
84  /* convert a character to upper case -- either ASCII or EBCDIC */
85    *ch = isupper(*ch) ? (*ch) :toupper(*ch);
86}  /* uppercase */
87
88
89void getnums()
90{
91  /* read species numbers and number of characters */
92  fscanf(infile, "%ld%ld", &numsp, &chars);
93  numsp1 = numsp + 1;
94  numsp2 = numsp * 2 - 1;
95}  /* getnums */
96
97void getoptions()
98{
99  /* interactively set options */
100  Char ch;
101  boolean done, done1;
102
103  printdata = false;
104  progress = true;
105  do {
106    printf(ansi ? "\033[2J\033[H" :
107           vt52 ? "\033E\033H"    : "\n");
108    printf("\nContinuous character Contrasts, version %s\n\n",VERSION);
109    printf("Settings for this run:\n");
110    printf("  R     Print out correlations and regressions?  %s\n",
111           (reg ? "Yes" : "No"));
112    printf("  M                     Analyze multiple trees?");
113    if (mulsets)
114      printf("  Yes, %2ld trees\n", numtrees);
115    else
116      printf("  No\n");
117    printf("  0         Terminal type (IBM PC, VT52, ANSI)?  %s\n",
118           ibmpc ? "IBM PC"  :
119           ansi  ? "ANSI"    :
120           vt52  ? "VT52"    : "(none)");
121
122    printf("  1          Print out the data at start of run  %s\n",
123           (printdata ? "Yes" : "No"));
124    printf("  2        Print indications of progress of run  %s\n",
125           (progress ? "Yes" : "No"));
126
127    printf("\nAre these settings correct? (type Y or the letter for one to change)\n");
128    scanf("%c%*[^\n]", &ch);
129    getchar();
130    if (ch == '\n')
131      ch = ' ';
132    uppercase(&ch);
133    done = (ch == 'Y');
134    if (!done) {
135      if (ch == 'R' || ch == 'M' || ch == '1' || ch == '2' || ch == '0') {
136        switch (ch) {
137
138        case 'R':
139          reg = !reg;
140          break;
141
142        case 'M':
143          mulsets = !mulsets;
144          if (mulsets) {
145            done1 = false;
146            do {
147              printf("How many trees?\n");
148              scanf("%ld%*[^\n]", &numtrees);
149              getchar();
150              done1 = (numtrees >= 1);
151              if (!done1)
152                printf("BAD TREES NUMBER:  it must be greater than 1\n");
153            } while (done1 != true);
154          }
155          break;
156
157        case '0':
158          if (ibmpc) {
159            ibmpc = false;
160            vt52 = true;
161          } else {
162            if (vt52) {
163              vt52 = false;
164              ansi = true;
165            } else if (ansi)
166              ansi = false;
167            else
168              ibmpc = true;
169          }
170          break;
171
172        case '1':
173          printdata = !printdata;
174          break;
175
176        case '2':
177          progress = !progress;
178          break;
179        }
180      } else
181        printf("Not a possible option!\n");
182    }
183  } while (!done);
184}  /* getoptions */
185
186void getdata()
187{
188  /* read species data */
189  long i, j, l;
190
191  if (printdata) {
192    fprintf(outfile, "\nContinuous character Contrasts, version %s\n\n",VERSION);
193    fprintf(outfile, "%4ld Populations, %4ld Characters\n\n", numsp, chars);
194    fprintf(outfile, "Name");
195    fprintf(outfile, "                       Phenotypes\n");
196    fprintf(outfile, "----");
197    fprintf(outfile, "                       ----------\n\n");
198  }
199  for (i = 0; i < numsp; i++) {
200    fscanf(infile, "%*[^\n]");
201    getc(infile);
202    for (j = 0; j < namelength; j++) {
203      nayms[i][j] = getc(infile);
204      if (nayms[i][j] == '\n')
205        nayms[i][j] = ' ';
206      if ( eof(infile) | eoln(infile)){
207        printf("ERROR: END-OF-LINE OR END-OF-FILE");
208        printf(" IN THE MIDDLE OF A SPECIES NAME\n");
209        exit(-1);}
210      else if (printdata)
211        putc(nayms[i][j], outfile);
212    }
213    for (j = 1; j <= chars; j++) {
214      if (eoln(infile)) {
215        fscanf(infile, "%*[^\n]");
216        getc(infile);
217      }
218      fscanf(infile, "%lf", &x[i][j - 1]);
219      if (printdata) {
220        fprintf(outfile, "%10.5lf", x[i][j - 1]);
221        if (j % 6 == 0) {
222          putc('\n', outfile);
223          for (l = 1; l <= namelength; l++)
224            putc(' ', outfile);
225        }
226      }
227    }
228    if (printdata)
229      putc('\n', outfile);
230  }
231  fscanf(infile, "%*[^\n]");
232  getc(infile);
233  if (printdata)
234    putc('\n', outfile);
235}  /* getdata */
236
237
238void doinit()
239{
240  /* initializes variables */
241  getnums();
242  getoptions();
243}  /* doinit */
244
245
246void setuptree(a)
247tree *a;
248{
249  /* initialize a tree */
250  long i, j;
251  node *p, *q;
252
253  a->nodep = (node **)Malloc((long)numsp2*sizeof(node *));
254  for (i = 1; i <= numsp; i++) {
255    a->nodep[i - 1] = (node *)Malloc((long)sizeof(node));
256    a->nodep[i - 1]->view = (phenotype)Malloc((long)chars*sizeof(double));
257    a->nodep[i - 1]->tip = true;
258    a->nodep[i - 1]->number = i;
259    a->nodep[i - 1]->back = NULL;
260  }
261  for (i = numsp1; i <= numsp2; i++) {
262    q = NULL;
263    for (j = 1; j <= 3; j++) {
264      p = (node *)Malloc((long)sizeof(node));
265      p->view = (phenotype)Malloc((long)chars*sizeof(double));
266      p->tip = false;
267      p->number = i;
268      p->next = q;
269      p->back = NULL;
270      q = p;
271    }
272    p->next->next->next = p;
273    a->nodep[i - 1] = p;
274  }
275}  /* setuptree */
276
277void hookup(p, q)
278node *p, *q;
279{
280  /* hook together two nodes */
281  p->back = q;
282  q->back = p;
283}  /* hookup */
284
285void setuptip(m, t)
286long m;
287tree *t;
288{
289  /* initialize branch lengths and views in a tip */
290  node *with;
291
292  with = t->nodep[m - 1];
293  memcpy(with->view, x[m - 1], chars*sizeof(double));
294  memcpy(with->nayme, nayms[m - 1], sizeof(naym));
295  with->deltav = 0.0;
296  with->v = 0.0;
297}  /* setuptip */
298
299
300void getch(c)
301Char *c;
302{
303  /* get next nonblank character */
304  do {
305    if (eoln(treefile)) {
306      fscanf(treefile, "%*[^\n]");
307      getc(treefile);
308    }
309    *c = getc(treefile);
310    if (*c == '\n')
311      *c = ' ';
312  } while (*c == ' ');
313}  /* getch */
314
315void findch(c, lparens,rparens)
316Char c;
317long *lparens,*rparens;
318{
319  /* skip forward in user tree until find character c */
320  boolean done;
321
322  done = false;
323  while (!done) {
324    if (c == ',') {
325      if (ch == '(' || ch == ')' || ch == ':' || ch == ';') {
326        printf("\nERROR IN USER TREE: UNMATCHED PARENTHESIS OR MISSING");
327        printf(" COMMA\n OR NOT TRIFURCATED BASE\n");
328        exit(-1);
329      } else if (ch == ',')
330        done = true;
331    } else if (c == ')') {
332      if (ch == '(' || ch == ',' || ch == ':' || ch == ';') {
333        printf("\nERROR IN USER TREE:");
334        printf(" UNMATCHED PARENTHESIS OR NOT BIFURCATED NODE\n");
335        exit(-1);
336      } else if (ch == ')') {
337        (*rparens)++;
338        if ((*lparens) > 0 && (*lparens) == (*rparens)) {
339          if ((*lparens) < numsp - 2) {
340            printf("\nERROR: UNMATCHED PARENTHESIS OR TOO FEW SPECIES\n");
341            exit(-1);
342          } else if ((*lparens) == numsp - 1) {
343            getch(&ch);
344            if (ch != ';') {
345              printf("\nERROR IN USER TREE: ");
346              printf("UNMATCHED PARENTHESIS OR MISSING SEMICOLON\n");
347              exit(-1);
348            }
349          }
350        }
351        done = true;
352      }
353    }
354    if ((done && ch == ')') || (!done))
355      getch(&ch);
356  }
357}  /* findch */
358
359void findeither(lparens,rparens,rtparen)
360long *lparens,*rparens;
361boolean *rtparen;
362{
363  /* find either a rt paren or a comma */
364  boolean done;
365
366  done = false;
367  while (!(done)) {
368    if (ch == '(' || ch == ':' || ch == ';') {
369      printf("\nERROR IN USER TREE: UNMATCHED PARENTHESIS OR MISSING COMMA\n");
370      printf(" OR NOT TRIFURCATED BASE\n");
371      exit(-1);
372    } else if (ch == ',' || ch == ')')
373      done = true;
374    else
375      getch(&ch);
376  }
377  if (ch == ')') {
378    (*rparens)++;
379    if ((*lparens) > 0 && (*lparens) == (*rparens)) {
380      if ((*lparens) < numsp - 2) {
381        printf("\nERROR: UNMATCHED PARENTHESIS OR TOO FEW SPECIES\n");
382        exit(-1);
383      } else if ((*lparens) == numsp - 2) {
384        getch(&ch);
385        if (ch != ';') {
386          printf("\nERROR IN USER TREE:");
387          printf(" UNMATCHED PARENTHESIS OR MISSING SEMICOLON\n");
388          exit(-1);
389        }
390      }
391    }
392  }
393  (*rtparen) = (ch == ')');
394  if ((done && ch == ')') || !(done))
395    getch(&ch);
396}  /* findeither */
397
398
399void processlength(p)
400node *p;
401{
402  long digit, ordzero;
403  double valyew, divisor;
404  boolean pointread;
405  Char STR1[256], STR2[256];
406
407  ordzero = '0';
408  pointread = false;
409  valyew = 0.0;
410  divisor = 1.0;
411  getch(&ch);
412  digit = ch - ordzero;
413  while (((unsigned long)digit <= 9) |
414         (strcmp((sprintf(STR1, "%c", ch), STR1), point) == 0)) {
415    sprintf(STR2, "%c", ch);
416    if (!strcmp(STR2, point))
417      pointread = true;
418    else {
419      valyew = valyew * 10.0 + digit;
420      if (pointread)
421        divisor *= 10.0;
422    }
423    getch(&ch);
424    digit = ch - ordzero;
425  }
426  p->v = valyew / divisor;
427  p->back->v = p->v;
428}  /* processlength */
429
430
431void addelement(p, nextnode,lparens,rparens,names)
432node *p;
433long *nextnode,*lparens,*rparens;
434boolean *names;
435{
436  /* add one node to the user tree */
437  node *q;
438  long i, n;
439  boolean found;
440  Char str[namelength];
441
442  getch(&ch);
443  if (ch == '(') {
444    (*lparens)++;
445    if ((*lparens) >= numsp) {
446      printf("\nERROR IN USER TREE: TOO MANY LEFT PARENTHESES\n");
447      exit(-1);
448    } else {
449      (*nextnode)++;
450      q = curtree.nodep[(*nextnode) - 1];
451      hookup(p, q);
452      addelement(q->next, nextnode,lparens,rparens,names);
453      findch(',', lparens,rparens);
454      addelement(q->next->next, nextnode,lparens,rparens,names);
455      findch(')',lparens,rparens);
456    }
457  } else {
458    for (i = 0; i < namelength; i++)
459      str[i] = ' ';
460    n = 1;
461    do {
462      if (ch == '_')
463        ch = ' ';
464      str[n - 1] = ch;
465      if (eoln(treefile)) {
466        fscanf(treefile, "%*[^\n]");
467        getc(treefile);
468      }
469      ch = getc(treefile);
470      if (ch == '\n')
471        ch = ' ';
472      n++;
473    } while (ch != ':' && ch != ',' && ch != ')' && n <= namelength);
474    n = 1;
475    do {
476      found = true;
477      for (i = 0; i < namelength; i++)
478        found = (found && str[i] == nayms[n - 1][i]);
479      if (found) {
480        if (names[n - 1] == false)
481          names[n - 1] = true;
482        else {
483          printf("\nERROR IN USER TREE: DUPLICATE NAME FOUND -- ");
484          for (i = 0; i < namelength; i++)
485            putchar(curtree.nodep[n - 1]->nayme[i]);
486          putchar('\n');
487          exit(-1);
488        }
489      } else
490        n++;
491    } while (!(n > numsp || found));
492    if (n > numsp) {
493      printf("Cannot find species: ");
494      for (i = 0; i < namelength; i++)
495        putchar(str[i]);
496      putchar('\n');
497      exit(-1);
498    }
499    hookup(curtree.nodep[n - 1], p);
500  }
501  if (ch == ':')
502    processlength(p);
503}  /* addelement */
504
505void treeread()
506{
507  /* read in a user tree */
508  /* Local variables for treeread: */
509  boolean rtparen;
510  long nextnode, lparens, rparens;
511  boolean *names;
512  node *p;
513  long i;
514
515  getch(&ch);
516  if (ch != '(')
517    return;
518  names = (boolean *)Malloc((long)numsp*sizeof(boolean));
519  for (i = 0; i < numsp; i++)
520    names[i] = false;
521  lparens = 1;
522  rparens = 0;
523  nextnode = numsp + 1;
524  p = curtree.nodep[nextnode - 1];
525  p->back = NULL;
526  curtree.start = p;
527  p = p->next;
528  i = 1;
529  rtparen = false;
530  while (i <= 3 && !rtparen) {
531    addelement(p, &nextnode,&lparens,&rparens,names);
532    p = p->next;
533    findeither(&lparens,&rparens,&rtparen);
534    i++;
535  }
536  bifurcating = (i == 3);
537  free(names);
538}  /* treeread */
539
540void initcontrasts()
541{
542  /* compute the contrasts */
543  long i, j;
544  for (i = 0; i <= numsp - 2 ; i++) {
545    for (j = 0; j < chars; j++)
546      cntrast[i][j] = 0.0;
547  }
548  contno = 1;
549}  /* initcontrasts */
550
551void contbetween(p, q)
552node *p, *q;
553{
554  /* compute one contrast */
555  long i;
556  double sqbl;
557
558  if (p->back != q)
559    sqbl = sqrt(p->v + q->v + p->deltav + q->deltav);
560  else
561    sqbl = sqrt(p->v + p->deltav + q->deltav);
562  for (i = 0; i < chars; i++)
563    cntrast[contno - 1][i] = (p->view[i] - q->view[i]) / sqbl;
564  contno++;
565}  /* contbetween */
566
567void nuview(p)
568node *p;
569{
570  /* renew information about subtrees */
571  long j;
572  node *q, *r;
573  double v1, v2, vtot, f1, f2;
574
575  q = p->next->back;
576  r = p->next->next->back;
577  v1 = q->v + q->deltav;
578  v2 = r->v + r->deltav;
579  vtot = v1 + v2;
580  if (vtot > 0.0)
581    f1 = v2 / vtot;
582  else
583    f1 = 0.5;
584  f2 = 1.0 - f1;
585  for (j = 0; j < chars; j++)
586    p->view[j] = f1 * q->view[j] + f2 * r->view[j];
587  p->deltav = v1 * f1;
588}  /* nuview */
589
590void makecontrasts(p)
591node *p;
592{
593  /* compute the contrasts, recursively */
594  if (p->tip)
595    return;
596  makecontrasts(p->next->back);
597  makecontrasts(p->next->next->back);
598  nuview(p);
599  contbetween(p->next->back, p->next->next->back);
600}  /* makecontrasts */
601
602void writecontrasts()
603{
604  /* write out the contrasts */
605  long i, j;
606
607  if (printdata || reg) {
608    fprintf(outfile, "\nContrasts (columns are different characters)\n");
609    fprintf(outfile, "--------- -------- --- --------- -----------\n\n");
610  }
611  for (i = 0; i <= contno - 2; i++) {
612    for (j = 0; j < chars; j++)
613      fprintf(outfile, "%10.5lf", cntrast[i][j]);
614    putc('\n', outfile);
615  }
616}  /* writecontrasts */
617
618void regressions()
619{
620  /* compute regressions and correlations among contrasts */
621  long i, j, k;
622  double **sumprod;
623
624  sumprod = (double **)Malloc((long)chars*sizeof(double *));
625  for (i = 0; i < chars; i++) {
626    sumprod[i] = (double *)Malloc((long)chars*sizeof(double));
627    for (j = 0; j < chars; j++)
628      sumprod[i][j] = 0.0;
629  }
630    for (i = 0; i <= contno - 2; i++) {
631    for (j = 0; j < chars; j++) {
632      for (k = 0; k < chars; k++)
633        sumprod[j][k] += cntrast[i][j] * cntrast[i][k];
634    }
635  }
636  fprintf(outfile, "\nCovariance matrix\n");
637  fprintf(outfile, "---------- ------\n\n");
638  for (i = 0; i < chars; i++) {
639    for (j = 0; j < chars; j++)
640      sumprod[i][j] /= contno - 1;
641  }
642  for (i = 0; i < chars; i++) {
643    for (j = 0; j < chars; j++)
644      fprintf(outfile, "%10.4lf", sumprod[i][j]);
645    putc('\n', outfile);
646  }
647  fprintf(outfile, "\nRegressions (columns on rows)\n");
648  fprintf(outfile, "----------- -------- -- -----\n\n");
649  for (i = 0; i < chars; i++) {
650    for (j = 0; j < chars; j++)
651      fprintf(outfile, "%10.4lf", sumprod[i][j] / sumprod[i][i]);
652    putc('\n', outfile);
653  }
654  fprintf(outfile, "\nCorrelations\n");
655  fprintf(outfile, "------------\n\n");
656  for (i = 0; i < chars; i++) {
657    for (j = 0; j < chars; j++)
658      fprintf(outfile, "%10.4lf",
659              sumprod[i][j] / sqrt(sumprod[i][i] * sumprod[j][j]));
660    putc('\n', outfile);
661  }
662  for (i = 0; i < chars; i++)
663    free(sumprod[i]);
664  free(sumprod);
665
666}  /* regressions */
667
668
669void maketree()
670{
671  /* set up the tree and use it */
672  long which;
673
674  setuptree(&curtree);
675  for (which = 1; which <= numsp; which++)
676    setuptip(which, &curtree);
677  which = 1;
678  while (which <= numtrees) {
679    if ((printdata || reg) && numtrees > 1) {
680      fprintf(outfile, "Tree number%4ld\n", which);
681      fprintf(outfile, "==== ====== ====\n\n");
682    }
683    bifurcating = false;
684    treeread();
685    initcontrasts();
686    makecontrasts(curtree.start);
687    if (!bifurcating)
688      contbetween(curtree.start, curtree.start->back);
689    writecontrasts();
690    if (reg)
691      regressions();
692    putc('\n', outfile);
693    which++;
694  }
695  if (progress)
696    printf("\nOutput written on output file\n\n");
697}  /* maketree */
698
699
700main(argc, argv)
701int argc;
702Char *argv[];
703{  /* main program */
704char infilename[100],outfilename[100],trfilename[100];
705#ifdef MAC
706  macsetup("Contrast","Contrast");
707#endif
708  openfile(&infile,INFILE,"r",argv[0],infilename);
709  openfile(&treefile,TREEFILE,"r",argv[0],trfilename);
710  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
711  ibmpc = ibmpc0;
712  ansi = ansi0;
713  vt52 = vt520;
714  mulsets = false;
715  reg = true;
716  numtrees = 1;
717  doinit();
718  x = (phenotype *)Malloc((long)numsp*sizeof(phenotype));
719  for (j = 0; j < numsp; j++)
720    x[j] = (phenotype)Malloc((long)chars*sizeof(double));
721  cntrast = (phenotype *)Malloc((long)numsp*sizeof(phenotype));
722  for (j = 0; j < numsp; j++)
723    cntrast[j] = (phenotype)Malloc((long)chars*sizeof(double));
724  nayms = (naym *)Malloc((long)numsp*sizeof(naym));
725  getdata();
726  maketree();
727  FClose(infile);
728  FClose(outfile);
729  FClose(treefile);
730  exit(0);
731}
732
733int eof(f)
734FILE *f;
735{
736    register int ch;
737
738    if (feof(f))
739        return 1;
740    if (f == stdin)
741        return 0;
742    ch = getc(f);
743    if (ch == EOF)
744        return 1;
745    ungetc(ch, f);
746    return 0;
747}
748
749
750int eoln(f)
751FILE *f;
752{
753    register int ch;
754
755    ch = getc(f);
756    if (ch == EOF)
757        return 1;
758    ungetc(ch, f);
759    return (ch == '\n');
760}
761
762void memerror()
763{
764printf("Error allocating memory\n");
765exit(-1);
766}
767
768MALLOCRETURN *mymalloc(x)
769long x;
770{
771MALLOCRETURN *mem;
772mem = (MALLOCRETURN *)calloc(1,(size_t)x);
773if (!mem)
774  memerror();
775else
776  return (MALLOCRETURN *)mem;
777
778}
Note: See TracBrowser for help on using the repository browser.