📄 phylip.c
字号:
/* countcomma rewritten so it passes back both lparen+comma to allocate nodep and a pointer to the comma variable. This allows the tree to know how many species exist, and the tips to be placed in the front of the nodep array */long countsemic(FILE **treefile){ /* Used to determine the number of user trees. Return either a: the number of semicolons in the file outside comments or b: the first integer in the file */ Char c; long return_val, semic = 0; long bracket = 0; /* Eat all whitespace */ c = gettc(*treefile); while ((c == ' ') || (c == '\t') || (c == '\n')) { c = gettc(*treefile); } /* Then figure out if the first non-white character is a digit; if so, return it */ if (isdigit (c)) { return_val = atoi(&c); } else { /* Loop past all characters, count the number of semicolons outside of comments */ for (;;){ c = fgetc(*treefile); if (feof(*treefile)) break; if (c == ';') semic++; if (c == '[') { bracket++; commentskipper(&treefile, &bracket); } } return_val = semic; } rewind (*treefile); return return_val;} /* countsemic */void hookup(node *p, node *q){ /* hook together two nodes */ p->back = q; q->back = p;} /* hookup */void link_trees(long local_nextnum, long nodenum, long local_nodenum, pointarray nodep){ if(local_nextnum == 0) hookup(nodep[nodenum],nodep[local_nodenum]); else if(local_nextnum == 1) hookup(nodep[nodenum], nodep[local_nodenum]->next); else if(local_nextnum == 2) hookup(nodep[nodenum],nodep[local_nodenum]->next->next); else printf("Error in Link_Trees()");} /* link_trees() */void allocate_nodep(pointarray *nodep, FILE **treefile, long *precalc_tips) { /* pre-compute space and allocate memory for nodep */ long numnodes; /* returns number commas & ( */ long numcom = 0; /* returns number commas */ numnodes = countcomma(treefile, &numcom) + 1; *nodep = (pointarray)Malloc(2*numnodes*sizeof(node *)); (*precalc_tips) = numcom + 1; /* this will be used in placing the tip nodes in the front region of nodep. Used for species check? */} /* allocate_nodep -plc */void malloc_pheno (node *p, long endsite, long rcategs){ /* Allocate the phenotype arrays; used by dnaml */ long i; p->x = (phenotype)Malloc(endsite*sizeof(ratelike)); for (i = 0; i < endsite; i++) p->x[i] = (ratelike)Malloc(rcategs*sizeof(sitelike));} /* malloc_pheno */void malloc_ppheno (node *p,long endsite, long rcategs){ /* Allocate the phenotype arrays; used by proml */ long i; p->protx = (pphenotype)Malloc(endsite*sizeof(pratelike)); for (i = 0; i < endsite; i++) p->protx[i] = (pratelike)Malloc(rcategs*sizeof(psitelike));} /* malloc_ppheno */long take_name_from_tree (Char *ch, Char *str, FILE *treefile){ /* This loop takes in the name from the tree. Return the length of the name string. */ long name_length = 0; do { if ((*ch) == '_') (*ch) = ' '; str[name_length++] = (*ch); if (eoln(treefile)) scan_eoln(treefile); (*ch) = gettc(treefile); if (*ch == '\n') *ch = ' '; } while ((*ch) != ':' && (*ch) != ',' && (*ch) != ')' && (*ch) != '[' && (*ch) != ';' && name_length <= MAXNCH); return name_length;} /* take_name_from_tree */void match_names_to_data (Char *str, pointarray treenode, node **p, long spp){ /* This loop matches names taken from treefile to indexed names in the data file */ boolean found; long i, n; n = 1; do { found = true; for (i = 0; i < nmlngth; i++) { found = (found && ((str[i] == nayme[n - 1][i]) || (((nayme[n - 1][i] == '_') && (str[i] == ' ')) || ((nayme[n - 1][i] == ' ') && (str[i] == '\0'))))); } if (found) *p = treenode[n - 1]; else n++; } while (!(n > spp || found)); if (n > spp) { printf("\n\nERROR: Cannot find species: "); for (i = 0; (str[i] != '\0') && (i < MAXNCH); i++) putchar(str[i]); printf(" in data file\n\n"); exxit(-1); }} /* match_names_to_data */void addelement(node **p, node *q, Char *ch, long *parens, FILE *treefile, pointarray treenode, boolean *goteof, boolean *first, pointarray nodep, long *nextnode, long *ntips, boolean *haslengths, node **grbg, initptr initnode){ /* Recursive procedure adds nodes to user-defined tree This is the main (new) tree-reading procedure */ node *pfirst; long i, len = 0, nodei = 0; boolean notlast; Char str[MAXNCH]; node *r; if ((*ch) == '(') { (*nextnode)++; /* get ready to use new interior node */ nodei = *nextnode; /* do what needs to be done at bottom */ (*initnode)(p, grbg, q, len, nodei, ntips, parens, bottom, treenode, nodep, str, ch, treefile); pfirst = (*p); notlast = true; while (notlast) { /* loop through immediate descendants */ (*initnode)(&(*p)->next, grbg, q, len, nodei, ntips, parens, nonbottom, treenode, nodep, str, ch, treefile); /* ... doing what is done before each */ r = (*p)->next; getch(ch, parens, treefile); /* look for next character */ addelement(&(*p)->next->back, (*p)->next, ch, parens, treefile, treenode, goteof, first, nodep, nextnode, ntips, haslengths, grbg, initnode); /* call self recursively */ (*initnode)(&r, grbg, q, len, nodei, ntips, parens, hslength, treenode, nodep, str, ch, treefile); /* do what is done after each about length */ pfirst->numdesc++; /* increment number of descendants */ *p = r; /* make r point back to p */ if ((*ch) == ')') { notlast = false; do { getch(ch, parens, treefile); } while ((*ch) != ',' && (*ch) != ')' && (*ch) != '[' && (*ch) != ';' && (*ch) != ':'); } } (*p)->next = pfirst; (*p) = pfirst; } else if ((*ch) != ')') { /* if it's a species name */ for (i = 0; i < MAXNCH; i++) /* fill string with nulls */ str[i] = '\0'; len = take_name_from_tree (ch, str, treefile); /* get the name */ if ((*ch) == ')') (*parens)--; /* decrement count of open parentheses */ (*initnode)(p, grbg, q, len, nodei, ntips, parens, tip, treenode, nodep, str, ch, treefile); /* do what needs to be done at a tip */ } else getch(ch, parens, treefile); if (q != NULL) hookup(q, (*p)); /* now hook up */ (*initnode)(p, grbg, q, len, nodei, ntips, parens, iter, treenode, nodep, str, ch, treefile); if ((*ch) == ':') (*initnode)(p, grbg, q, len, nodei, ntips, parens, length, treenode, nodep, str, ch, treefile); /* do what needs to be done with length */ else if ((*ch) != ';' && (*ch) != '[') (*initnode)(p, grbg, q, len, nodei, ntips, parens, hsnolength, treenode, nodep, str, ch, treefile); /* ... or what needs to be done when no length */ if ((*ch) == '[') (*initnode)(p, grbg, q, len, nodei, ntips, parens, treewt, treenode, nodep, str, ch, treefile); /* ... for processing a tree weight */ else if ((*ch) == ';') /* ... and at end of tree */ (*initnode)(p, grbg, q, len, nodei, ntips, parens, unittrwt, treenode, nodep, str, ch, treefile);} /* addelement */void treeread (FILE *treefile, node **root, pointarray treenode, boolean *goteof, boolean *first, pointarray nodep, long *nextnode, boolean *haslengths, node **grbg, initptr initnode){ /* read in user-defined tree and set it up */ char ch; long parens = 0; long ntips = 0; (*goteof) = false; (*nextnode) = spp; /* eat blank lines */ while (eoln(treefile) && !eoff(treefile)) scan_eoln(treefile); if (eoff(treefile)) { (*goteof) = true; return; } getch(&ch, &parens, treefile); while (ch != '(') { /* Eat everything in the file (i.e. digits, tabs) until you encounter an open-paren */ getch(&ch, &parens, treefile); } (*haslengths) = true; addelement(root, NULL, &ch, &parens, treefile, treenode, goteof, first, nodep, nextnode, &ntips, haslengths, grbg, initnode); /* Eat blank lines and end of current line*/ do { scan_eoln(treefile); } while (eoln(treefile) && !eoff(treefile)); (*first) = false; if (parens != 0) { printf("\n\nERROR in tree file: unmatched parentheses\n\n"); exxit(-1); }} /* treeread */void addelement2(node *q, Char *ch, long *parens, FILE *treefile, pointarray treenode, boolean lngths, double *trweight, boolean *goteof, long *nextnode, long *ntips, long no_species, boolean *haslengths){ /* recursive procedure adds nodes to user-defined tree -- old-style bifurcating-only version */ node *pfirst = NULL, *p; long i, len, current_loop_index; boolean notlast, minusread; Char str[MAXNCH]; double valyew, divisor; if ((*ch) == '(') { current_loop_index = (*nextnode) + spp; (*nextnode)++; /* This is an assignment of an interior node */ p = treenode[current_loop_index]; pfirst = p; notlast = true; while (notlast) { /* This while loop goes through a circle (triad for bifurcations) of nodes */ p = p->next; /* added to ensure that non base nodes in loops have indices */ p->index = current_loop_index + 1; getch(ch, parens, treefile); addelement2(p, ch, parens, treefile, treenode, lngths, trweight, goteof, nextnode, ntips, no_species, haslengths); if ((*ch) == ')') { notlast = false; do { getch(ch, parens, treefile); } while ((*ch) != ',' && (*ch) != ')' && (*ch) != '[' && (*ch) != ';' && (*ch) != ':'); } } } else if ((*ch) != ')') { for (i = 0; i < MAXNCH; i++) str[i] = '\0'; len = take_name_from_tree (ch, str, treefile); match_names_to_data (str, treenode, &p, spp); pfirst = p; if ((*ch) == ')') (*parens)--; (*ntips)++; strncpy (p->nayme, str, len); } else getch(ch, parens, treefile); if ((*ch) == '[') { /* getting tree weight from last comment field */ if (!eoln(treefile)) { fscanf(treefile, "%lf", trweight); getch(ch, parens, treefile); if (*ch != ']') { printf("\n\nERROR: Missing right square bracket\n\n"); exxit(-1); } else { getch(ch, parens, treefile); if (*ch != ';') { printf("\n\nERROR: Missing semicolon after square brackets\n\n"); exxit(-1); } } } } else if ((*ch) == ';') { (*trweight) = 1.0 ; if (!eoln(treefile)) printf("WARNING: tree weight set to 1.0\n"); } else (*haslengths) = ((*haslengths) && q == NULL); if (q != NULL) hookup(q, pfirst); if (q != NULL) { if (q->branchnum < pfirst->branchnum) pfirst->branchnum = q->branchnum; else q->branchnum = pfirst->branchnum; } if ((*ch) == ':') { processlength(&valyew, &divisor, ch, &minusread, treefile, parens); if (q != NULL) { if (!minusread) q->oldlen = valyew / divisor; else q->oldlen = 0.0; if (lngths) { q->v = valyew / divisor; q->back->v = q->v; q->iter = false; q->back->iter = false; q->back->iter = false; } } } } /* addelement2 */void treeread2 (FILE *treefile, node **root, pointarray treenode, boolean lngths, double *trweight, boolean *goteof, boolean *haslengths, long *no_species){ /* read in user-defined tree and set it up -- old-style bifurcating-only version */ char ch; long parens = 0; long ntips = 0; long nextnode; (*goteof) = false; nextnode = 0; /* Eats all blank lines at start of file */ while (eoln(treefile) && !eoff(treefile)) scan_eoln(treefile); if (eoff(treefile)) { (*goteof) = true; return; } getch(&ch, &parens, treefile); while (ch != '(') { /* Eat everything in the file (i.e. digits, tabs) until you encounter an open-paren */ getch(&ch, &parens, treefile); } addelement2(NULL, &ch, &parens, treefile, treenode, lngths, trweight, goteof, &nextnode, &ntips, (*no_species), haslengths); (*root) = treenode[*no_species]; /*eat blank lines */ while (eoln(treefile) && !eoff(treefile)) scan_eoln(treefile); (*root)->oldlen = 0.0; if (parens != 0) { printf("\n\nERROR in tree file: unmatched parentheses\n\n"); exxit(-1); }} /* treeread2 */void exxit(int exitcode){#ifdef WIN32 if (exitcode == 0)#endif exit (exitcode);#ifdef WIN32 else { puts ("Hit Enter or Return to close program."); puts(" You may have to hit Enter or Return twice."); getchar (); getchar (); phyRestoreConsoleAttributes(); exit (exitcode); }#endif} /* exxit */char gettc(FILE* file) { /* catch eof's so that other functions not expecting an eof * won't have to worry about it */ int ch; ch=getc(file); if (ch == EOF ) { puts("Unexpected End of File"); exxit(-1); } return ch;} /* gettc */#ifdef WIN32void phySaveConsoleAttributes(){ GetConsoleScreenBufferInfo( hConsoleOutput, &savecsbi );} /* PhySaveConsoleAttributes */void phySetConsoleAttributes(){ hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); phySaveConsoleAttributes(); SetConsoleTextAttribute(hConsoleOutput, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);} /* phySetConsoleAttributes */void phyRestoreConsoleAttributes(){ COORD c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -