source: tags/initial/GDE/PHYLIP/dnadist.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: 33.8 KB
Line 
1#include "phylip.h"
2
3/* version 3.56c. (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 maxcategs       9    /* maximum number of site types */
9#define iterations      100  /* number of iterates of EM for each distance */
10#define nmlngth         10   /* number of characters max. in species name */
11
12#define epsilon         0.00001   /* used in makedist */
13
14#define ibmpc0          false
15#define ansi0           true
16#define vt520           false
17
18
19typedef enum {
20  A, C, G, T
21} base;
22typedef double sitelike[(long)T - (long)A + 1];
23typedef sitelike *phenotype;
24typedef Char naym[nmlngth];
25
26typedef Char** sequence;
27typedef struct node {
28  phenotype x;
29  naym nayme;
30} node;
31
32typedef struct valrec {
33  double rat, ratxv, z1, y1, z1zz, z1yy, z1xv;
34} valrec;
35
36
37Static FILE *infile, *outfile;
38Static short j, numsp, sites, endsite, categs, weightsum, datasets, ith;
39Static boolean freqsfrom, jukes, jinnei, kimura, lower, ml, weights,
40               printdata, progress, ctgry, mulsets, firstset, interleaved,
41               ibmpc, vt52, ansi;
42Static node **nodep;
43Static double xi, xv, ttratio, ttratio0, freqa, freqc, freqg, freqt, freqr,
44              freqy, freqar, freqcy, freqgr, freqty, fracchange, sumrates, cvi;
45Static short *category, *oldweight, *weight, *alias, *ally, *location;
46Static double rate[maxcategs];
47Static double **d;
48Static sequence y;
49double sumweightrat;                  /* these values were propogated  */
50double *weightrat;                    /* to global values from the     */
51valrec tbl[maxcategs];                /* procedure makedists.          */
52
53
54openfile(fp,filename,mode,application,perm)
55FILE **fp;
56char *filename;
57char *mode;
58char *application;
59char *perm;
60{
61  FILE *of;
62  char file[100];
63  strcpy(file,filename);
64  while (1){
65    of = fopen(file,mode);
66    if (of)
67      break;
68    else {
69      switch (*mode){
70      case 'r':
71        printf("%s:  can't read %s\n",application,file);
72        file[0] = '\0';
73        while (file[0] =='\0'){
74          printf("Please enter a new filename>");
75          gets(file);}
76        break;
77      case 'w':
78        printf("%s: can't write %s\n",application,file);
79        file[0] = '\0';
80        while (file[0] =='\0'){
81          printf("Please enter a new filename>");
82          gets(file);}
83        break;
84      }
85    }
86  }
87  *fp=of;
88  if (perm != NULL)
89    strcpy(perm,file);
90}
91
92
93void uppercase(ch)
94Char *ch;
95{  /* convert ch to upper case -- either ASCII or EBCDIC */
96   *ch = (islower(*ch) ?  toupper(*ch) : (*ch));
97}  /* uppercase */
98
99
100void getnums()
101{
102  /* input number of species, number of sites */
103  fscanf(infile, "%hd%hd", &numsp, &sites);
104}  /* getnums */
105
106void getoptions()
107{
108  /* interactively set options */
109  short j,i;
110  Char ch;
111  boolean  done1, ttr;
112  char line[256];
113  char rest[256];
114  int   scanned;
115
116  ctgry = false;
117  categs = 1;
118  rate[0] = 1.0;
119  freqsfrom = false;
120  jinnei = false;
121  jukes = false;
122  kimura = true;
123  ml = false;
124  lower = false;
125  ttratio = 2.0;
126  ttr = false;
127  weights = false;
128  printdata = false;
129  progress = true;
130  interleaved = true;
131  for (;;) {
132    printf(ansi ? "\033[2J\033[H" :
133           vt52 ? "\033E\033H"    : "\n");
134    printf("\nNucleic acid sequence Distance Matrix program,");
135    printf(" version %s\n\n",VERSION);
136    printf("Settings for this run:\n");
137    printf("  D  Distance (Kimura, Jin/Nei, ML, J-C)?  %s\n",
138           kimura ? "Kimura 2-parameter" :
139           jinnei ? "Jin and Nei"        :
140           jukes  ? "Jukes-Cantor"       : "Maximum Likelihood");
141    if (kimura || jinnei || ml) {
142      printf("  T        Transition/transversion ratio?");
143      if (!ttr)
144        printf("  2.0\n");
145      else
146        printf("  %8.4f\n", ttratio);
147    }
148    printf("  C   One category of substitution rates?");
149    if (!ctgry || categs == 1)
150      printf("  Yes\n");
151    else
152      printf("  %hd categories\n", categs);
153    if (ml) {
154      printf("  F       Use empirical base frequencies?  %s\n",
155             (freqsfrom ? "Yes" : "No"));
156    }
157    printf("  L              Form of distance matrix?  %s\n",
158           (lower ? "Lower-triangular" : "Square"));
159    printf("  M           Analyze multiple data sets?");
160    if (mulsets)
161      printf("  Yes, %2hd sets\n", datasets);
162    else
163      printf("  No\n");
164    printf("  I          Input sequences interleaved?  %s\n",
165           (interleaved ? "Yes" : "No, sequential"));
166    printf("  0   Terminal type (IBM PC, VT52, ANSI)?  %s\n",
167           ibmpc ? "IBM PC" :
168           ansi  ? "ANSI"   :
169           vt52  ? "VT52"   : "(none)");
170    printf("  1    Print out the data at start of run  %s\n",
171           (printdata ? "Yes" : "No"));
172    printf("  2  Print indications of progress of run  %s\n",
173           (progress ? "Yes" : "No"));
174    printf("\nAre these settings correct? (type Y or letter for one to change)\n");
175    scanf("%c%*[^\n]", &ch);
176    getchar();
177    uppercase(&ch);
178    if  (ch == 'Y')
179           break;
180   if (ch == 'C' || ch == 'F' || ch == 'L' || ch == 'I' || ch == 'D' ||
181       ch == 'T' || ch == 'M' || ch == '0' || ch == '1' || ch == '2') {
182     switch (ch) {
183
184     case 'D':
185       if (kimura) {
186         kimura = false;
187         jinnei = true;
188         freqsfrom = false;
189       } else if (jinnei) {
190         jinnei = false;
191         ml = true;
192         freqsfrom = true;
193       } else if (ml) {
194         ml = false;
195         jukes = true;
196         freqsfrom = false;
197       } else {
198         jukes = false;
199         kimura = true;
200         freqsfrom = false;
201       }
202       break;
203
204     case 'C':
205       ctgry = !ctgry;
206       if (ctgry) {
207         do {
208           printf("Number of categories?\n");
209           gets(line);
210           categs = (short)atoi(line);
211         } while (categs < 1 || categs > maxcategs);
212         for (;;){
213           printf("Rate for each category? (use a space to separate)\n");
214           gets(line);
215           done1 = true;
216           for (i = 0; i < categs; i++){
217             scanned = sscanf(line,"%lf %[^\n]", &rate[i],rest);
218             if ((scanned != 2 && i < (categs - 1)) ||
219                 (scanned != 1 && i == (categs - 1))){
220               printf("Please enter exactly %hd values.\n",categs);
221               done1 = false;
222               break;
223             }
224             strcpy(line,rest);
225           }
226           if (done1)
227             break;
228         }
229       }
230       break;
231
232     case 'F':
233       freqsfrom = !freqsfrom;
234       if (!freqsfrom) {
235         printf(
236                "Base frequencies for A, C, G, T/U (use blanks to separate)?\n");
237         scanf("%lf%lf%lf%lf%*[^\n]", &freqa, &freqc, &freqg, &freqt);
238         getchar();
239       }
240       break;
241
242     case 'L':
243       lower = !lower;
244       break;
245
246     case 'T':
247       if (jukes) {
248         printf("WARNING: CANNOT SET TRANSITION/");
249         printf("TRANSVERSION RATIO FOR");
250         printf(" JUKES-CANTOR DISTANCE\n");
251       } else {
252         ttr = !ttr;
253         if (ttr) {
254           do {
255             printf("Transition/transversion ratio?\n");
256             scanf("%lf%*[^\n]", &ttratio);
257             getchar();
258           } while (ttratio < 0.0);
259         }
260       }
261       break;
262
263     case 'M':
264       mulsets = !mulsets;
265       if (mulsets) {
266         done1 = false;
267         do {
268           printf("How many data sets?\n");
269           scanf("%hd%*[^\n]", &datasets);
270           getchar();
271           done1 = (datasets >= 1);
272           if (!done1)
273             printf("BAD DATA SETS NUMBER:  it must be greater than 1\n");
274         } while (done1 != true);
275       }
276       break;
277
278     case 'I':
279       interleaved = !interleaved;
280       break;
281
282     case '0':
283       if (ibmpc) {
284         ibmpc = false;
285         vt52 = true;
286       } else {
287         if (vt52) {
288           vt52 = false;
289           ansi = true;
290         } else if (ansi)
291           ansi = false;
292         else
293           ibmpc = true;
294       }
295       break;
296
297     case '1':
298       printdata = !printdata;
299          break;
300
301     case '2':
302       progress = !progress;
303       break;
304     }
305   } else
306      printf("Not a possible option!\n");
307  }
308  if (jinnei) {
309    do {
310      printf(
311        "\nCoefficient of variation of substitution rate among sites (must be positive)\n");
312      scanf("%lf%*[^\n]", &cvi);
313      getchar();
314    } while (cvi <= 0.0);
315    cvi = 1.0 / (cvi * cvi);
316  }
317    if (!printdata)
318    return;
319    fprintf(outfile, "\nNucleic acid sequence Distance Matrix program,");
320    fprintf(outfile, " version %s\n\n",VERSION);
321    fprintf(outfile, "%3hd species, %4hd sites\n", numsp, sites);
322}  /* getoptions */
323
324
325void doinit()
326{
327  /* initializes variables */
328  short i;
329
330  getnums();
331  getoptions();
332  y = (Char **)Malloc(numsp*sizeof(Char *));
333  nodep = (node **)Malloc(numsp*sizeof(node *));
334  for (i = 0; i < numsp; i++) {
335    y[i] = (Char *)Malloc(sites*sizeof(Char));
336    nodep[i] = (node *)Malloc(sizeof(node));
337  }
338}  /* doinit */
339
340void inputcategories()
341{
342  /* reads the categories for each site */
343  short i;
344  Char ch;
345
346  for (i = 1; i < nmlngth; i++)
347    ch = getc(infile);
348  for (i = 0; i < sites; i++) {
349    do {
350      if (eoln(infile)) {
351        fscanf(infile, "%*[^\n]");
352        getc(infile);
353      }
354      ch = getc(infile);
355    } while (ch == ' ');
356    category[i] = ch - '0';
357  }
358  fscanf(infile, "%*[^\n]");
359  getc(infile);
360}  /* inputcategories */
361
362void printcategories()
363{
364  /* print out list of categories of sites */
365  short i, j;
366
367  fprintf(outfile, "Rate categories\n\n");
368  for (i = 1; i <= nmlngth + 3; i++)
369    putc(' ', outfile);
370  for (i = 1; i <= sites; i++) {
371    fprintf(outfile, "%hd", category[i - 1]);
372    if (i % 60 == 0) {
373      putc('\n', outfile);
374      for (j = 1; j <= nmlngth + 3; j++)
375        putc(' ', outfile);
376    } else if (i % 10 == 0)
377      putc(' ', outfile);
378  }
379  fprintf(outfile, "\n\n");
380
381}  /* printcategories */
382
383void inputweights()
384{
385  /* input the character weights, 0 or 1 */
386  Char ch;
387  short i;
388
389  for (i = 1; i < nmlngth; i++)
390    ch = getc(infile);
391  weightsum = 0;
392  for (i = 0; i < sites; i++) {
393    do {
394      if (eoln(infile)) {
395        fscanf(infile, "%*[^\n]");
396        getc(infile);
397      }
398      ch = getc(infile);
399    } while (ch == ' ');
400    oldweight[i] = 1;
401    if (ch == '0' || ch == '1')
402      oldweight[i] = ch - '0';
403    else {
404      printf("BAD WEIGHT CHARACTER: %c -- ");
405      printf("WEIGHTS IN DNADIST MUST BE 0 OR 1\n",ch);
406      exit(-1);
407    }
408    weightsum += oldweight[i];
409  }
410  weights = true;
411  fscanf(infile, "%*[^\n]");
412  getc(infile);
413}  /* inputweights */
414
415void printweights()
416{
417  /* print out the weights of sites */
418  short i, j;
419
420  fprintf(outfile, "\nSites are weighted as follows:\n");
421  for (i = 1; i <= sites; i++) {
422    if ((i - 1) % 60 == 0) {
423      putc('\n', outfile);
424      for (j = 1; j <= nmlngth + 3; j++)
425        putc(' ', outfile);
426    }
427    fprintf(outfile, "%hd", oldweight[i - 1]);
428    if (i % 10 == 0 && i % 60 != 0)
429      putc(' ', outfile);
430  }
431  fprintf(outfile, "\n\n");
432}  /* printweights */
433
434void inputoptions()
435{
436  /* read options information */
437  Char ch;
438  boolean ctg;
439  short i, extranum, cursp, cursts;
440
441  if (!firstset) {
442    if (eoln(infile)) {
443      fscanf(infile, "%*[^\n]");
444      getc(infile);
445    }
446    fscanf(infile, "%hd%hd", &cursp, &cursts);
447    if (cursp != numsp) {
448      printf("\nERROR: INCONSISTENT NUMBER OF SPECIES IN DATA SET %4hd\n", ith);
449      exit(-1);
450    }
451    sites = cursts;
452  }
453  for (i = 0; i < sites; i++){
454    category[i] = 1;
455    oldweight[i]= 1;
456  }
457  weightsum = sites;
458  ctg = false;
459  extranum = 0;
460  while (!(eoln(infile))) {
461    ch = getc(infile);
462    uppercase(&ch);
463    if (ch == 'C' || ch == 'W')
464      extranum++;
465    else if (ch != ' ') {
466      putc('\n', outfile);
467      printf("MAKE SURE YOU WANTED OPTION CHARACTER: %c\n", ch);
468      printf("(It was passed along to output file)\n");
469    }
470  }
471  fscanf(infile, "%*[^\n]");
472  getc(infile);
473  if (printdata)
474    putc('\n', outfile);
475  if (jukes && printdata)
476    fprintf(outfile, "  Jukes-Cantor Distance\n");
477  if (kimura && printdata)
478    fprintf(outfile, "  Kimura 2-parameter Distance\n");
479  if (jinnei && printdata)
480    fprintf(outfile, "  Jin and Nei Distance\n");
481  if (ml && printdata)
482    fprintf(outfile, "  Maximum Likelihood Distance\n");
483  for (i = 1; i <= extranum; i++) {
484    ch = getc(infile);
485    uppercase(&ch);
486    if (ch != 'C' && ch != 'W') {
487      printf("ERROR: INCORRECT AUXILIARY OPTIONS");
488      printf(" LINE WHICH STARTS WITH %c\n", ch);
489    }
490    if (ch == 'C') {
491      ctg = true;
492      if (!ctgry || categs <= 1) {
493        printf("ERROR: CATEGORY OPTION NOT CHOSEN IN MENU");
494        printf(" WITH OPTION %c IN INPUT\n",ch);
495        exit(-1);
496      } else
497        inputcategories();
498    }
499    if (ch == 'W')
500      inputweights();
501  }
502  if ((categs > 1 || ctgry) && !ctg) {
503    printf("ERROR: CATEGORY OPTION CHOSEN IN MENU");
504    printf(" WITH NO OPTION C IN INPUT\n");
505    exit(-1);
506  } else if (printdata && (categs > 1)) {
507    fprintf(outfile, "\nSite category   Rate of change\n\n");
508    for (i = 1; i <= categs; i++)
509      fprintf(outfile, "%12hd%13.3f\n", i, rate[i - 1]);
510    putc('\n', outfile);
511    printcategories();
512  }
513  if ((jukes || kimura || jinnei) && freqsfrom) {
514    printf("WARNING: CANNOT USE EMPIRICAL BASE FREQUENCIES");
515    printf(" WITH JUKES-CANTOR, KIMURA OR JIN/NEI DISTANCES\n");
516    exit(-1);
517  }
518  if (jukes)
519    ttratio = 0.5;
520  if (weights && printdata)
521    printweights();
522}  /* inputoptions */
523
524void getbasefreqs()
525{
526  /* compute or read in base frequencies */
527  double aa, bb;
528
529  if (printdata) {
530    putc('\n', outfile);
531    if (freqsfrom)
532      fprintf(outfile, "Empirical");
533    fprintf(outfile, " Base Frequencies:\n");
534  }
535  if (progress)
536    putchar('\n');
537  if (!freqsfrom) {
538    if (kimura || jukes || jinnei) {
539      freqa = 0.25;
540      freqc = 0.25;
541      freqg = 0.25;
542      freqt = 0.25;
543    }
544  }
545  if (printdata) {
546    fprintf(outfile, "    A    %10.5f\n", freqa);
547    fprintf(outfile, "    C    %10.5f\n", freqc);
548    fprintf(outfile, "    G    %10.5f\n", freqg);
549    fprintf(outfile, "   T(U)  %10.5f\n", freqt);
550  }
551  freqr = freqa + freqg;
552  freqy = freqc + freqt;
553  freqar = freqa / freqr;
554  freqcy = freqc / freqy;
555  freqgr = freqg / freqr;
556  freqty = freqt / freqy;
557  if (printdata)
558    fprintf(outfile, "\nTransition/transversion ratio = %10.6f\n\n", ttratio);
559  aa = ttratio * freqr * freqy - freqa * freqg - freqc * freqt;
560  bb = freqa * freqgr + freqc * freqty;
561  xi = aa / (aa + bb);
562  xv = 1.0 - xi;
563  ttratio = xi / xv;
564  if (xi <= 0.0 && xi >= -epsilon)
565    xi = 0.0;
566  if (xi < 0.0) {
567    printf("WARNING: This transition/transversion ratio\n");
568    printf("is impossible with these base frequencies!\n");
569    xi = 3.0 / 5;
570    xv = 2.0 / 5;
571    printf(" Transition/transversion parameter reset\n\n");
572  }
573  if (printdata)
574    fprintf(outfile, "(Transition/transversion parameter = %10.6f)\n\n",
575            xi / xv);
576  fracchange = xi * (2 * freqa * freqgr + 2 * freqc * freqty) +
577      xv * (1.0 - freqa * freqa - freqc * freqc - freqg * freqg - freqt * freqt);
578}  /* getbasefreqs */
579
580void inputdata()
581{
582  /* Input the names and sequences for each species */
583  short i, j, k, l, basesread, basesnew;
584  Char charstate;
585  boolean allread, done;
586
587  if (printdata)
588    putc('\n', outfile);
589  j = nmlngth + (sites + (sites - 1) / 10) / 2 - 5;
590  if (j < nmlngth - 1)
591    j = nmlngth - 1;
592  if (j > 37)
593    j = 37;
594  if (printdata) {
595    fprintf(outfile, "Name");
596    for (i = 1; i <= j; i++)
597      putc(' ', outfile);
598    fprintf(outfile, "Sequences\n");
599    fprintf(outfile, "----");
600    for (i = 1; i <= j; i++)
601      putc(' ', outfile);
602    fprintf(outfile, "---------\n\n");
603  }
604  basesread = 0;
605  allread = false;
606  while (!(allread)) {
607    allread = true;
608    if (eoln(infile)) {
609      fscanf(infile, "%*[^\n]");
610      getc(infile);
611    }
612    i = 1;
613    while (i <= numsp) {
614      if ((interleaved && basesread == 0 )|| !interleaved) {
615        for (j = 0; j < nmlngth; j++) {
616          if (eof(infile) || eoln(infile)){
617            printf("ERROR: END-OF-LINE OR END-OF-FILE IN");
618            printf(" THE MIDDLE OF A SPECIES NAME\n");
619            exit(-1);}
620          nodep[i - 1]->nayme[j] = getc(infile);
621        }
622      }
623      j = (interleaved) ? basesread : 0;
624      done = false;
625      while (!done && !eof(infile)) {
626        if (interleaved)
627          done = true;
628        while (j < sites && !(eoln(infile) || eof(infile))) {
629          charstate = getc(infile);
630          if (charstate == ' ' || (charstate >= '0' && charstate <= '9'))
631            continue;
632          uppercase(&charstate);
633          if (strchr("ABCDGHKMNRSTUVWXY?O-.",charstate) == NULL){
634            printf("ERROR: BAD BASE:%c AT POSITION%5hd OF SPECIES %3hd\n",
635                   charstate, j, i);
636            exit(-1);
637          }
638          j++;
639          if (charstate == '.')
640            charstate = y[0][j - 1];
641          y[i - 1][j - 1] = charstate;
642        }
643        if (interleaved)
644          continue;
645        if (j < sites) {
646          fscanf(infile, "%*[^\n]");
647          getc(infile);
648        } else if (j == sites)
649          done = true;
650      }
651      if (interleaved && i == 1)
652        basesnew = j;
653      fscanf(infile, "%*[^\n]");
654      getc(infile);
655      if ((interleaved && j != basesnew) || ((!interleaved) && j != sites)){
656        printf("ERROR: SEQUENCES OUT OF ALIGNMENT\n");
657        exit(-1);}
658      i++;
659    }
660    if (interleaved) {
661      basesread = basesnew;
662      allread = (basesread == sites);
663    } else
664      allread = (i > numsp);
665  }
666  if (!printdata)
667    return;
668  for (i = 1; i <= ((sites -1) / 60 + 1); i++) {
669    for (j = 1; j <= numsp; j++) {
670      for (k = 0; k < nmlngth; k++)
671        putc(nodep[j - 1]->nayme[k], outfile);
672      fprintf(outfile, "   ");
673      l = i * 60;
674      if (l > sites)
675        l = sites;
676      for (k = (i - 1) * 60 + 1; k <= l; k++) {
677        if (j > 1 && y[j - 1][k - 1] == y[0][k - 1])
678          charstate = '.';
679        else
680          charstate = y[j - 1][k - 1];
681        putc(charstate, outfile);
682        if (k % 10 == 0 && k % 60 != 0)
683          putc(' ', outfile);
684      }
685      putc('\n', outfile);
686    }
687    putc('\n', outfile);
688  }
689  putc('\n', outfile);
690}  /* inputdata */
691
692void sitesort()
693{
694  /* Shell sort of sites lexicographically */
695  short gap, i, j, jj, jg, k, itemp;
696  boolean flip, tied;
697
698  gap = sites / 2;
699  while (gap > 0) {
700    for (i = gap + 1; i <= sites; i++) {
701      j = i - gap;
702      flip = true;
703      while (j > 0 && flip) {
704        jj = alias[j - 1];
705        jg = alias[j + gap - 1];
706        tied = (oldweight[jj - 1] == oldweight[jg - 1]);
707        flip = (oldweight[jj - 1] < oldweight[jg - 1] ||
708                (tied && category[jj - 1] > category[jg - 1]));
709        tied = (tied && category[jj - 1] == category[jg - 1]);
710        k = 1;
711        while (k <= numsp && tied) {
712          flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]);
713          tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]);
714          k++;
715        }
716        if (!flip)
717          break;
718        itemp = alias[j - 1];
719        alias[j - 1] = alias[j + gap - 1];
720        alias[j + gap - 1] = itemp;
721        j -= gap;
722      }
723    }
724    gap /= 2;
725  }
726}  /* sitesort */
727
728void sitecombine()
729{
730  /* combine sites that have identical patterns */
731  short i, j, k;
732  boolean tied;
733
734  i = 1;
735  while (i < sites) {
736    j = i + 1;
737    tied = true;
738    while (j <= sites && tied) {
739      tied = (oldweight[alias[i - 1] - 1] == oldweight[alias[j - 1] - 1] &&
740              category[alias[i - 1] - 1] == category[alias[j - 1] - 1]);
741      k = 1;
742      while (k <= numsp && tied) {
743        tied = (tied &&
744            y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]);
745        k++;
746      }
747      if (!tied)
748        break;
749      ally[alias[j - 1] - 1] = alias[i - 1];
750      j++;
751    }
752    i = j;
753  }
754}  /* sitecombine */
755
756void sitescrunch()
757{
758  /* move so one representative of each pattern of
759     sites comes first */
760  short i, j, itemp;
761  boolean done, found, completed;
762
763  done = false;
764  i = 1;
765  j = 2;
766  while (!done) {
767    if (ally[alias[i - 1] - 1] != alias[i - 1]) {
768      if (j <= i)
769        j = i + 1;
770      if (j <= sites) {
771        found = false;
772        do {
773          found = (ally[alias[j - 1] - 1] == alias[j - 1]);
774          j++;
775          completed = (j > sites);
776          if (j <= sites)
777            completed = (oldweight[alias[j - 1] - 1] == 0);
778        } while (!(found || completed));
779        if (found) {
780          j--;
781          itemp = alias[i - 1];
782          alias[i - 1] = alias[j - 1];
783          alias[j - 1] = itemp;
784        } else
785          done = true;
786      } else
787        done = true;
788    }
789    i++;
790    done = (done || i >= sites);
791  }
792}  /* sitescrunch */
793
794void makeweights()
795{
796  /* make up weights vector to avoid duplicate computations */
797  short i;
798
799  for (i = 1; i <= sites; i++) {
800    alias[i - 1] = i;
801    ally[i - 1] = i;
802    weight[i - 1] = 0;
803  }
804  sitesort();
805  sitecombine();
806  sitescrunch();
807  endsite = 0;
808  for (i = 1; i <= sites; i++) {
809    if (ally[i - 1] == i && oldweight[i - 1] > 0)
810      endsite++;
811  }
812  for (i = 1; i <= endsite; i++)
813    location[alias[i - 1] - 1] = i;
814  sumrates = 0.0;
815  for (i = 0; i < sites; i++)
816    sumrates += oldweight[i] * rate[category[i] - 1];
817  for (i = 0; i < categs; i++)
818    rate[i] *= weightsum / sumrates;
819  sumrates = weightsum;
820  for (i = 0; i < sites; i++)
821    weight[location[ally[i] - 1] - 1] += oldweight[i];
822}  /* makeweights */
823
824void makevalues()
825{
826  /* set up fractional likelihoods at tips */
827  short i, j, k;
828  base b;
829
830  for (i = 0; i < numsp; i++)
831    nodep[i]->x = (phenotype)Malloc(endsite*sizeof(sitelike));
832  for (k = 0; k < endsite; k++) {
833    j = alias[k];
834    for (i = 0; i < numsp; i++) {
835      for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
836        nodep[i]->x[k][(long)b - (long)A] = 0.0;
837      switch (y[i][j - 1]) {
838
839      case 'A':
840        nodep[i]->x[k][0] = 1.0;
841        break;
842
843      case 'C':
844        nodep[i]->x[k][(long)C - (long)A] = 1.0;
845        break;
846
847      case 'G':
848        nodep[i]->x[k][(long)G - (long)A] = 1.0;
849        break;
850
851      case 'T':
852        nodep[i]->x[k][(long)T - (long)A] = 1.0;
853        break;
854
855      case 'U':
856        nodep[i]->x[k][(long)T - (long)A] = 1.0;
857        break;
858
859      case 'M':
860        nodep[i]->x[k][0] = 1.0;
861        nodep[i]->x[k][(long)C - (long)A] = 1.0;
862        break;
863
864      case 'R':
865        nodep[i]->x[k][0] = 1.0;
866        nodep[i]->x[k][(long)G - (long)A] = 1.0;
867        break;
868
869      case 'W':
870        nodep[i]->x[k][0] = 1.0;
871        nodep[i]->x[k][(long)T - (long)A] = 1.0;
872        break;
873
874      case 'S':
875        nodep[i]->x[k][(long)C - (long)A] = 1.0;
876        nodep[i]->x[k][(long)G - (long)A] = 1.0;
877        break;
878
879      case 'Y':
880        nodep[i]->x[k][(long)C - (long)A] = 1.0;
881        nodep[i]->x[k][(long)T - (long)A] = 1.0;
882        break;
883
884      case 'K':
885        nodep[i]->x[k][(long)G - (long)A] = 1.0;
886        nodep[i]->x[k][(long)T - (long)A] = 1.0;
887        break;
888
889      case 'B':
890        nodep[i]->x[k][(long)C - (long)A] = 1.0;
891        nodep[i]->x[k][(long)G - (long)A] = 1.0;
892        nodep[i]->x[k][(long)T - (long)A] = 1.0;
893        break;
894
895      case 'D':
896        nodep[i]->x[k][0] = 1.0;
897        nodep[i]->x[k][(long)G - (long)A] = 1.0;
898        nodep[i]->x[k][(long)T - (long)A] = 1.0;
899        break;
900
901      case 'H':
902        nodep[i]->x[k][0] = 1.0;
903        nodep[i]->x[k][(long)C - (long)A] = 1.0;
904        nodep[i]->x[k][(long)T - (long)A] = 1.0;
905        break;
906
907      case 'V':
908        nodep[i]->x[k][0] = 1.0;
909        nodep[i]->x[k][(long)C - (long)A] = 1.0;
910        nodep[i]->x[k][(long)G - (long)A] = 1.0;
911        break;
912
913      case 'N':
914        for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
915          nodep[i]->x[k][(long)b - (long)A] = 1.0;
916        break;
917
918      case 'X':
919        for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
920          nodep[i]->x[k][(long)b - (long)A] = 1.0;
921        break;
922
923      case '?':
924        for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
925          nodep[i]->x[k][(long)b - (long)A] = 1.0;
926        break;
927
928      case 'O':
929        for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
930          nodep[i]->x[k][(long)b - (long)A] = 1.0;
931        break;
932
933      case '-':
934        for (b = A; (long)b <= (long)T; b = (base)((long)b + 1))
935          nodep[i]->x[k][(long)b - (long)A] = 1.0;
936        break;
937      }
938    }
939  }
940}  /* makevalues */
941
942void empiricalfreqs()
943{
944  /* Get empirical base frequencies from the data */
945  short i, j, k;
946  double sum, suma, sumc, sumg, sumt, w;
947
948  freqa = 0.25;
949  freqc = 0.25;
950  freqg = 0.25;
951  freqt = 0.25;
952  for (k = 1; k <= 8; k++) {
953    suma = 0.0;
954    sumc = 0.0;
955    sumg = 0.0;
956    sumt = 0.0;
957    for (i = 0; i < numsp; i++) {
958      for (j = 0; j < endsite; j++) {
959        w = weight[j];
960        sum = freqa * nodep[i]->x[j][0];
961        sum += freqc * nodep[i]->x[j][(long)C - (long)A];
962        sum += freqg * nodep[i]->x[j][(long)G - (long)A];
963        sum += freqt * nodep[i]->x[j][(long)T - (long)A];
964        suma += w * freqa * nodep[i]->x[j][0] / sum;
965        sumc += w * freqc * nodep[i]->x[j][(long)C - (long)A] / sum;
966        sumg += w * freqg * nodep[i]->x[j][(long)G - (long)A] / sum;
967        sumt += w * freqt * nodep[i]->x[j][(long)T - (long)A] / sum;
968      }
969    }
970    sum = suma + sumc + sumg + sumt;
971    freqa = suma / sum;
972    freqc = sumc / sum;
973    freqg = sumg / sum;
974    freqt = sumt / sum;
975  }
976}  /* empiricalfreqs */
977
978
979void getinput()
980{
981  /* reads the input data */
982  inputoptions();
983  if (!freqsfrom )
984    getbasefreqs();
985  inputdata();
986  makeweights();
987  makevalues();
988  if (freqsfrom) {
989    empiricalfreqs();
990    getbasefreqs();
991  }
992}  /* getinput */
993
994
995
996void inittable()
997{
998  /* Define a lookup table. Precompute values and store in a table */
999  short i;
1000
1001  for (i = 0; i < categs; i++) {
1002    tbl[i].rat = rate[i];
1003    tbl[i].ratxv = rate[i] * xv;
1004  }
1005}  /* inittable */
1006
1007
1008void makev(m, n, v)
1009short m, n;
1010double *v;
1011{
1012  /* compute one distance */
1013  short i, it, numerator, denominator, num1, num2, idx;
1014  double sum, sum1, sum2, sumyr, lz, aa, bb, cc, vv, p1, p2, p3, q1, q2, q3,
1015         tt, delta, slope, xx1freqa, xx1freqc, xx1freqg, xx1freqt;
1016  double *prod, *prod2, *prod3;
1017  boolean quick, jukesquick, kimquick, jinneiquick;
1018  base b;
1019  node *p, *q;
1020  sitelike xx1, xx2;
1021
1022  p = nodep[m - 1];
1023  q = nodep[n - 1];
1024  quick = (!ctgry || categs == 1);
1025  if (jukes || kimura || jinnei) {
1026    numerator = 0;
1027    denominator = 0;
1028    for (i = 0; i < endsite; i++) {
1029      memcpy(xx1, p->x[i], sizeof(sitelike));
1030      memcpy(xx2, q->x[i], sizeof(sitelike));
1031      sum = 0.0;
1032      sum1 = 0.0;
1033      sum2 = 0.0;
1034      for (b = A; (long)b <= (long)T; b = (base)((long)b + 1)) {
1035        sum1 += xx1[(long)b - (long)A];
1036        sum2 += xx2[(long)b - (long)A];
1037        sum += xx1[(long)b - (long)A] * xx2[(long)b - (long)A];
1038      }
1039      quick = (quick && (sum1 == 1.0 || sum1 == 4.0) &&
1040               (sum2 == 1.0 || sum2 == 4.0));
1041      if (sum1 == 1.0 && sum2 == 1.0) {
1042        numerator += (long)(weight[i] * sum);
1043        denominator += weight[i];
1044      }
1045    }
1046  }
1047  jukesquick = (jukes && quick);
1048  kimquick = (kimura && quick);
1049  jinneiquick = (jinnei && quick);
1050  if (jinnei && !jinneiquick) {
1051    printf("WARNING: CANNOT CALCULATE JIN/NEI DISTANCE\n");
1052    printf(" WITH PRESENT PROGRAM IF PARTIALLY AMBIGUOUS NUCLEOTIDES\n");
1053    exit(-1);
1054  }
1055  if (jukesquick && numerator * 4 <= denominator) {
1056    printf(" WARNING: INFINITE DISTANCE BETWEEN ");
1057    printf(" SPECIES %3hd AND %3hd\n", m, n);
1058    exit(-1);
1059  }
1060  if (jukesquick)
1061    vv = -0.75 * log((4.0 * ((double)numerator / denominator) - 1.0) / 3.0);
1062  if (kimquick || jinneiquick) {
1063    num1 = 0;
1064    num2 = 0;
1065    denominator = 0;
1066    for (i = 0; i < endsite; i++) {
1067      memcpy(xx1, p->x[i], sizeof(sitelike));
1068      memcpy(xx2, q->x[i], sizeof(sitelike));
1069      sum = 0.0;
1070      sum1 = 0.0;
1071      sum2 = 0.0;
1072      for (b = A; (long)b <= (long)T; b = (base)((long)b + 1)) {
1073        sum1 += xx1[(long)b - (long)A];
1074        sum2 += xx2[(long)b - (long)A];
1075        sum += xx1[(long)b - (long)A] * xx2[(long)b - (long)A];
1076      }
1077      sumyr = (xx1[0] + xx1[(long)G - (long)A])
1078            * (xx2[0] + xx2[(long)G - (long)A]) +
1079              (xx1[(long)C - (long)A] + xx1[(long)T - (long)A]) *
1080              (xx2[(long)C - (long)A] + xx2[(long)T - (long)A]);
1081      if (sum1 == 1.0 && sum2 == 1.0) {
1082        num1 += (long)(weight[i] * sum);
1083        num2 += (long)(weight[i] * (sumyr - sum));
1084        denominator += weight[i];
1085      }
1086    }
1087    tt = 1.0 - (double)num1 / denominator;
1088    if (tt > 0.0) {
1089      delta = 0.1;
1090      tt = delta;
1091      it = 0;
1092      while (fabs(delta) > 0.00002 && it < iterations) {
1093        it++;
1094        if (kimura) {
1095          p1 = exp(-tt);
1096          p2 = exp(-xv * tt) - exp(-tt);
1097          p3 = 1.0 - exp(-xv * tt);
1098        } else {
1099          p1 = exp(-cvi * log(1 + tt / cvi));
1100          p2 = exp(-cvi * log(1 + xv * tt / cvi))
1101              - exp(-cvi * log(1 + tt / cvi));
1102          p3 = 1.0 - exp(-cvi * log(1 + xv * tt / cvi));
1103        }
1104        q1 = p1 + p2 / 2.0 + p3 / 4.0;
1105        q2 = p2 / 2.0 + p3 / 4.0;
1106        q3 = p3 / 2.0;
1107        if (kimura)
1108          slope = 0.5 * exp(-tt) * (num2 / q2 - num1 / q1) +
1109                  0.25 * xv * exp(-xv * tt) *
1110                 ((denominator - num1 - num2) * 2 / q3 - num2 / q2 - num1 / q1);
1111        else
1112          slope = 0.5 * (1 / (1 + tt / cvi)) * exp(-cvi * log(1 + tt / cvi)) *
1113                  (num2 / q2 - num1 / q1) + 0.25 * (xv / (1 + xv * tt / cvi)) *
1114                    exp(-cvi * log(1 + xv * tt / cvi)) *
1115                 ((denominator - num1 - num2) * 2 / q3 - num2 / q2 - num1 / q1);
1116        if (slope < 0.0)
1117          delta = fabs(delta) / -2.0;
1118        else
1119          delta = fabs(delta);
1120        tt += delta;
1121      }
1122    }
1123    vv = fracchange * tt;
1124  }
1125  if (!(jukesquick || kimquick || jinneiquick)) {
1126    prod = (double *)Malloc(sites*sizeof(double));
1127    prod2 = (double *)Malloc(sites*sizeof(double));
1128    prod3 = (double *)Malloc(sites*sizeof(double));
1129    for (i = 0; i < endsite; i++) {
1130      memcpy(xx1, p->x[i], sizeof(sitelike));
1131      memcpy(xx2, q->x[i], sizeof(sitelike));
1132      xx1freqa = xx1[0] * freqa;
1133      xx1freqc = xx1[(long)C - (long)A] * freqc;
1134      xx1freqg = xx1[(long)G - (long)A] * freqg;
1135      xx1freqt = xx1[(long)T - (long)A] * freqt;
1136      sum1 = xx1freqa + xx1freqc + xx1freqg + xx1freqt;
1137      sum2 = freqa * xx2[0] + freqc * xx2[(long)C - (long)A] +
1138             freqg * xx2[(long)G - (long)A] + freqt * xx2[(long)T - (long)A];
1139      prod[i] = sum1 * sum2;
1140      prod2[i] = (xx1freqa + xx1freqg) *
1141                 (xx2[0] * freqar + xx2[(long)G - (long)A] * freqgr) +
1142          (xx1freqc + xx1freqt) *
1143          (xx2[(long)C - (long)A] * freqcy + xx2[(long)T - (long)A] * freqty);
1144      prod3[i] = xx1freqa * xx2[0] + xx1freqc * xx2[(long)C - (long)A] +
1145         xx1freqg * xx2[(long)G - (long)A] + xx1freqt * xx2[(long)T - (long)A];
1146    }
1147    tt = 0.1;
1148    delta = 0.1;
1149    it = 1;
1150    while (it < iterations && fabs(delta) > 0.00002) {
1151      slope = 0.0;
1152      if (tt > 0.0) {
1153        lz = -tt;
1154        for (i = 0; i < categs; i++) {
1155          tbl[i].z1 = exp(tbl[i].ratxv * lz);
1156          tbl[i].y1 = 1.0 - tbl[i].z1;
1157          tbl[i].z1zz = exp(tbl[i].rat * lz);
1158          tbl[i].z1yy = tbl[i].z1 - tbl[i].z1zz;
1159          tbl[i].z1xv = tbl[i].z1 * xv;
1160        }
1161        for (i = 0; i < endsite; i++) {
1162          idx = category[alias[i] - 1];
1163          cc = prod[i];
1164          bb = prod2[i];
1165          aa = prod3[i];
1166          slope += weightrat[i] * (tbl[idx - 1].z1zz * (bb - aa) +
1167                tbl[idx - 1].z1xv * (cc - bb)) /
1168              (aa * tbl[idx - 1].z1zz + bb * tbl[idx - 1].z1yy +
1169               cc * tbl[idx - 1].y1);
1170        }
1171      }
1172      if (slope < 0.0)
1173        delta = fabs(delta) / -2.0;
1174      else
1175        delta = fabs(delta);
1176      tt += delta;
1177      it++;
1178    }
1179    vv = tt * fracchange;
1180    free(prod);
1181    free(prod2);
1182    free(prod3);
1183  }
1184  *v = vv;
1185}  /* makev */
1186
1187
1188void makedists()
1189{
1190  /* compute distance matrix */
1191  short i, j;
1192  double v;
1193
1194  inittable();
1195  for (i = 0; i < endsite; i++)
1196    weightrat[i] = weight[i] * rate[category[alias[i] - 1] - 1];
1197  if (progress)
1198    printf("Distances calculated for species\n");
1199  for (i = 0; i < numsp; i++)
1200    d[i][i] = 0.0;
1201  for (i = 1; i < numsp; i++) {
1202    if (progress) {
1203      printf("    ");
1204      for (j = 0; j < nmlngth; j++)
1205        putchar(nodep[i - 1]->nayme[j]);
1206      printf("   ");
1207    }
1208    for (j = i + 1; j <= numsp; j++) {
1209      makev(i, j, &v);
1210      d[i - 1][j - 1] = v;
1211      d[j - 1][i - 1] = v;
1212      if (progress)
1213        putchar('.');
1214    }
1215    if (progress)
1216      putchar('\n');
1217  }
1218  if (progress) {
1219    printf("    ");
1220    for (j = 0; j < nmlngth; j++)
1221      putchar(nodep[numsp - 1]->nayme[j]);
1222    putchar('\n');
1223  }
1224  for (i = 0; i < numsp; i++)
1225    free(nodep[i]->x);
1226}  /* makedists */
1227
1228void writedists()
1229{
1230  /* write out distances */
1231  short i, j, k;
1232
1233  fprintf(outfile, "%5hd\n", numsp);
1234  for (i = 0; i < numsp; i++) {
1235    for (j = 0; j < nmlngth; j++)
1236      putc(nodep[i]->nayme[j], outfile);
1237    if (lower)
1238      k = i;
1239    else
1240      k = numsp;
1241    for (j = 1; j <= k; j++) {
1242      fprintf(outfile, "%8.4f", d[i][j - 1]);
1243      if ((j + 1) % 9 == 0 && j < k)
1244        putc('\n', outfile);
1245    }
1246    putc('\n', outfile);
1247  }
1248  if (progress)
1249    printf("\nDistances written to file\n\n");
1250}  /* writedists */
1251
1252
1253main(argc, argv)
1254int argc;
1255Char *argv[];
1256{  /* DNA Distances by Maximum Likelihood */
1257char infilename[100],outfilename[100];
1258#ifdef MAC
1259  macsetup("Dnadist","");
1260#endif
1261  openfile(&infile,INFILE,"r",argv[0],infilename);
1262  openfile(&outfile,OUTFILE,"w",argv[0],outfilename);
1263
1264  ibmpc = ibmpc0;
1265  ansi = ansi0;
1266  vt52 = vt520;
1267  mulsets = false;
1268  datasets = 1;
1269  firstset = true;
1270  doinit();
1271  d = (double **)Malloc(numsp*sizeof(double *));
1272  for (j = 0; j < numsp; j++)
1273    d[j] = (double*)Malloc(numsp*sizeof(double));
1274  category = (short *)Malloc(sites*sizeof(short));
1275  oldweight = (short *)Malloc(sites*sizeof(short));
1276  weight = (short *)Malloc(sites*sizeof(short));
1277  alias = (short *)Malloc(sites*sizeof(short));
1278  ally = (short *)Malloc(sites*sizeof(short));
1279  location = (short *)Malloc(sites*sizeof(short));
1280  weightrat = (double *)Malloc(sites*sizeof(double));
1281  ttratio0 = ttratio;
1282  for (ith = 1; ith <= datasets; ith++) {
1283    ttratio = ttratio0;
1284    getinput();
1285    if (ith == 1)
1286      firstset = false;
1287    if (datasets > 1 && progress)
1288      printf("Data set # %hd:\n\n",ith);
1289    makedists();
1290    writedists();
1291  }
1292  FClose(infile);
1293  FClose(outfile);
1294#ifdef MAC
1295  fixmacfile(outfilename);
1296#endif
1297  exit(0);
1298}  /* DNA Distances by Maximum Likelihood */
1299
1300int eof(f)
1301FILE *f;
1302{
1303    register int ch;
1304
1305    if (feof(f))
1306        return 1;
1307    if (f == stdin)
1308        return 0;
1309    ch = getc(f);
1310    if (ch == EOF)
1311        return 1;
1312    ungetc(ch, f);
1313    return 0;
1314}
1315
1316
1317int eoln(f)
1318FILE *f;
1319{
1320    register int ch;
1321
1322    ch = getc(f);
1323    if (ch == EOF)
1324        return 1;
1325    ungetc(ch, f);
1326    return (ch == '\n');
1327}
1328
1329void memerror()
1330{
1331printf("Error allocating memory\n");
1332exit(-1);
1333}
1334
1335MALLOCRETURN *mymalloc(x)
1336long x;
1337{
1338MALLOCRETURN *mem;
1339mem = (MALLOCRETURN *)malloc(x);
1340if (!mem)
1341  memerror();
1342else
1343  return (MALLOCRETURN *)mem;
1344}
1345
Note: See TracBrowser for help on using the repository browser.