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 | |
---|
16 | typedef double *phenotype; |
---|
17 | typedef Char naym[namelength]; |
---|
18 | typedef 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 | |
---|
27 | typedef struct tree { |
---|
28 | node **nodep; |
---|
29 | node *start; |
---|
30 | } tree; |
---|
31 | |
---|
32 | Static FILE *infile, *outfile, *treefile; |
---|
33 | Static long numsp, numsp1, numsp2, chars, numtrees, j; |
---|
34 | Static phenotype *x, *cntrast; |
---|
35 | Static naym *nayms; |
---|
36 | Static boolean printdata, progress, reg, mulsets, ibmpc, vt52, ansi, |
---|
37 | bifurcating; |
---|
38 | Static Char ch; |
---|
39 | |
---|
40 | /* Local variables for maketree, propagated globally for c version: */ |
---|
41 | tree curtree; |
---|
42 | long contno; |
---|
43 | |
---|
44 | |
---|
45 | openfile(fp,filename,mode,application,perm) |
---|
46 | FILE **fp; |
---|
47 | char *filename; |
---|
48 | char *mode; |
---|
49 | char *application; |
---|
50 | char *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 | |
---|
81 | void uppercase(ch) |
---|
82 | Char *ch; |
---|
83 | { |
---|
84 | /* convert a character to upper case -- either ASCII or EBCDIC */ |
---|
85 | *ch = isupper(*ch) ? (*ch) :toupper(*ch); |
---|
86 | } /* uppercase */ |
---|
87 | |
---|
88 | |
---|
89 | void 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 | |
---|
97 | void 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 | |
---|
186 | void 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 | |
---|
238 | void doinit() |
---|
239 | { |
---|
240 | /* initializes variables */ |
---|
241 | getnums(); |
---|
242 | getoptions(); |
---|
243 | } /* doinit */ |
---|
244 | |
---|
245 | |
---|
246 | void setuptree(a) |
---|
247 | tree *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 | |
---|
277 | void hookup(p, q) |
---|
278 | node *p, *q; |
---|
279 | { |
---|
280 | /* hook together two nodes */ |
---|
281 | p->back = q; |
---|
282 | q->back = p; |
---|
283 | } /* hookup */ |
---|
284 | |
---|
285 | void setuptip(m, t) |
---|
286 | long m; |
---|
287 | tree *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 | |
---|
300 | void getch(c) |
---|
301 | Char *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 | |
---|
315 | void findch(c, lparens,rparens) |
---|
316 | Char c; |
---|
317 | long *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 | |
---|
359 | void findeither(lparens,rparens,rtparen) |
---|
360 | long *lparens,*rparens; |
---|
361 | boolean *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 | |
---|
399 | void processlength(p) |
---|
400 | node *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 | |
---|
431 | void addelement(p, nextnode,lparens,rparens,names) |
---|
432 | node *p; |
---|
433 | long *nextnode,*lparens,*rparens; |
---|
434 | boolean *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 | |
---|
505 | void 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 | |
---|
540 | void 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 | |
---|
551 | void contbetween(p, q) |
---|
552 | node *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 | |
---|
567 | void nuview(p) |
---|
568 | node *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 | |
---|
590 | void makecontrasts(p) |
---|
591 | node *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 | |
---|
602 | void 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 | |
---|
618 | void 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 | |
---|
669 | void 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 | |
---|
700 | main(argc, argv) |
---|
701 | int argc; |
---|
702 | Char *argv[]; |
---|
703 | { /* main program */ |
---|
704 | char 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 | |
---|
733 | int eof(f) |
---|
734 | FILE *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 | |
---|
750 | int eoln(f) |
---|
751 | FILE *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 | |
---|
762 | void memerror() |
---|
763 | { |
---|
764 | printf("Error allocating memory\n"); |
---|
765 | exit(-1); |
---|
766 | } |
---|
767 | |
---|
768 | MALLOCRETURN *mymalloc(x) |
---|
769 | long x; |
---|
770 | { |
---|
771 | MALLOCRETURN *mem; |
---|
772 | mem = (MALLOCRETURN *)calloc(1,(size_t)x); |
---|
773 | if (!mem) |
---|
774 | memerror(); |
---|
775 | else |
---|
776 | return (MALLOCRETURN *)mem; |
---|
777 | |
---|
778 | } |
---|