seaview/000755 000765 000000 00000000000 12614160742 013022 5ustar00mgouywheel000000 000000 seaview/addbootstrap.cxx000644 000765 000024 00000100335 12404325714 016242 0ustar00mgouystaff000000 000000 #include "treedraw.h" #include #include #include #include #include #include #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif #define lmot (8*sizeof(int)) /* structures */ typedef struct branche { /* une branche definie par ses deux extremites */ struct noeud *bouta; struct noeud *boutb; char *br_label; int *bits; float count; struct branche *next_h; } branche; #define s_noeud sizeof(struct noeud) /* included functions */ int init_add_bootstrap(char *full_tree); int process_one_replicate(char *one_tree, float w); char *finish_add_bootstrap(int replicates); static void free_arbre(struct noeud *racine, struct noeud *); static void free_branches(branche *branch_tab); static char *preptree(char *, int *, struct noeud **pracine, struct noeud ***ptabtax, branche **); static int loadphylip(char *arbre, int *prooted, struct noeud **, branche *); struct noeud *unrootedset(char *deb, char *fin, branche **p_int_br, struct noeud **tabtax, branche *); static char *recur_write_tree(struct noeud *centre, struct noeud *pere, char *arbre, char *finarbre, branche *); static int get_br_from_bouts(struct noeud *a, struct noeud *b, branche *); static int for_all_branches(struct noeud *centre, struct noeud *origine, branche *branches); static int process_branch(struct noeud *cote1, struct noeud *cote2, branche *); char *get_br_label(struct noeud *a, struct noeud *b, branche *); inline int is_leave(struct noeud *n); void set_leaves(struct noeud *centre, struct noeud *pere, int *bits); static int hashvalue(int *bits, int modulo, int totbits); void parcourir_branches_each(struct noeud *centre, struct noeud *origine, float w); void process_branch_each(struct noeud *cote1, struct noeud *cote2, float w); branche *find_branch(int *bits); void add_hash(branche *br); int recodeleaves(struct noeud *node, struct noeud *parent, struct noeud **tabtax); static void use_count(branche *branches, int count); void bit0(int *plist, int num); void bit1(int *plist, int num); int testbit(int *plist, int num); void non(int *listnon, int *list, int len); char *compute_consensus_tree(char **seqnames, int **rows, int branch_count); void init_consensus_calculation(int); static int recodeleaves_consensus(struct noeud *node, struct noeud *parent, char **seqnames); static branche *find_branch_consensus(int *bits); static void process_branch_consensus(struct noeud *cote1, struct noeud *cote2); static void parcourir_branches_consensus(struct noeud *centre, struct noeud *origine); int process_one_consensus_item(char *one_tree, char **seqnames); int after_consensus_items(float threshold, int item_count, int ***prows); /* extern functions */ extern char *nextpar(char *pospar); extern double place_midpoint_root(struct noeud *from, struct noeud *racine, int notu, int fixed_outgroup); extern const char *make_binary_or_unrooted(char *arbre); /* globals */ static int w_bits, modulo; static int has_br_length = 0, notu /* counted from 1 */, totbranches /* counted from 1 */, num_noeud, nextotu; static branche **hashtable; static struct noeud **maintabtax; static branche *mainbranches; static struct noeud *racine; static int taille; static int *candidate_bits; int init_add_bootstrap(char *full_tree) // returns != 0 iff error { char *message; int err; message = preptree(full_tree, &taille, &racine, &maintabtax, &mainbranches); if(message != NULL || racine == NULL) return 1; taille = (int)(1.5 * taille + 100); w_bits = (notu-1) / lmot + 1; modulo = 997; hashtable = (branche **)calloc(modulo, sizeof(branche *)); candidate_bits = (int *)calloc(w_bits, sizeof(int)); //to have same tree display as without bootstrap, must root it at midpoint and go over branches //from there struct noeud *newroot = (struct noeud *)malloc(sizeof(struct noeud));//deallocated later by free_arbre place_midpoint_root(racine, newroot, notu, FALSE); // root at midpoint newroot->nom = NULL; struct noeud *v1 = newroot->v1; struct noeud *v2 = newroot->v2; //remove root if(v1->v1 == newroot) v1->v1 = v2; else if(v1->v2 == newroot) v1->v2 = v2; else v1->v3 = v2; if(v2->v1 == newroot) v2->v1 = v1; else if(v2->v2 == newroot) v2->v2 = v1; else v2->v3 = v1; /* parcourir branches internes de l'arbre et les coder */ err = for_all_branches(v1, v2, mainbranches); if(err) return 1; err = for_all_branches(v2, v1, mainbranches); if(err) return 1; if(has_br_length || (newroot->l1 + newroot->l2 != 0) )err = process_branch(v1, v2, mainbranches); if(err) return 1; //put back root if(v1->v1 == v2) v1->v1 = newroot; else if(v1->v2 == v2) v1->v2 = newroot; else v1->v3 = newroot; if(v2->v1 == v1) v2->v1 = newroot; else if(v2->v2 == v1) v2->v2 = newroot; else v2->v3 = newroot; racine = newroot; return 0; } int process_one_replicate(char *one_tree, float w) // returns 1 iff one_tree was a correct tree { struct noeud *eachroot; char *message; struct noeud **eachtabtax; branche *eachbranches; message = preptree(one_tree, NULL, &eachroot, &eachtabtax, &eachbranches); if(message != NULL) return 0; if( recodeleaves(eachroot, NULL, maintabtax) ) return 0; parcourir_branches_each(eachroot, NULL, w); free_arbre(eachroot, NULL); free(eachtabtax); free_branches(eachbranches); return 1; } char *finish_add_bootstrap(int replicates) //returns NULL iff error { char *arbre1, *arbre2, *arbre3, *arbre, *f1, *f2, *f3, *bootstrap = NULL; struct noeud *r1, *r2, *r3, *r, *r1p, *r2p, *r3p; double l1, l2, l3; use_count(mainbranches, replicates); /* calcul de son format phylip unrooted */ r = racine->v1; if(r->nom != NULL) {//racine->v1 is a leaf r1 = r; r = racine->v2; if(r->v1 == racine) { r2 = r->v2; r3 = r->v3; l2 = r->l2; l3 = r->l3; } else if(r->v2 == racine) { r2 = r->v1; r3 = r->v3; l2 = r->l1; l3 = r->l3; } else { r2 = r->v1; r3 = r->v2; l2 = r->l1; l3 = r->l2; } r1p = racine; r2p = r3p = racine->v2; l1 = racine->l1 + racine->l2; } else {//racine->v1 is not a leaf r3 = racine->v2; if(r->v1 == racine) { r1 = r->v2; r2 = r->v3; l1 = r->l2; l2 = r->l3; } else if(r->v2 == racine) { r1 = r->v1; r2 = r->v3; l1 = r->l1; l2 = r->l3; } else { r1 = r->v1; r2 = r->v2; l1 = r->l1; l2 = r->l2; } r1p = r2p = racine->v1; r3p = racine; l3 = racine->l1 + racine->l2; if(has_br_length || (l3 != 0) ) bootstrap = get_br_label(racine->v1, racine->v2, mainbranches); } arbre1 = (char *)malloc( taille); arbre2 = (char *)malloc( taille); arbre3 = (char *)malloc( taille); f1 = recur_write_tree(r1, r1p, arbre1, arbre1 + taille, mainbranches); if(f1 == NULL) return NULL; *(f1 + 1) = 0; f2 = recur_write_tree(r2, r2p, arbre2, arbre2 + taille, mainbranches); if(f2 == NULL) return NULL; *(f2 + 1) = 0; f3 = recur_write_tree(r3, r3p, arbre3, arbre3 + taille, mainbranches); if(f3 == NULL) return NULL; *(f3 + 1) = 0; arbre = (char *)malloc( f1 - arbre1 + f2 - arbre2 + f3 - arbre3 + 100); if(has_br_length) sprintf(arbre, "(%s:%.5f,%s:%.5f,%s%s:%.5f);", arbre1, l1, arbre2, l2, arbre3, bootstrap != NULL ? bootstrap : "", l3); else sprintf(arbre, "(%s,%s,%s%s);", arbre1, arbre2, arbre3, bootstrap != NULL ? bootstrap : ""); free(arbre1); free(arbre2); free(arbre3); free_arbre(racine, NULL); free(maintabtax); free_branches(mainbranches); free(hashtable); free(candidate_bits); return arbre; } static void free_arbre(struct noeud *racine, struct noeud *pere) { if(racine == NULL) return; if(racine->v1 != pere) free_arbre(racine->v1, racine); if(racine->v2 != pere) free_arbre(racine->v2, racine); if(racine->v3 != pere) free_arbre(racine->v3, racine); if(racine->nom != NULL) free(racine->nom); free(racine); } static void free_branches(branche *branch_tab) { for(int i = 0; i < notu - 3; i++) { if(branch_tab[i].br_label != NULL) free(branch_tab[i].br_label); if(branch_tab[i].bits != NULL) free(branch_tab[i].bits); } if(notu > 3) free(branch_tab); } static char *preptree(char *tree, int *ptaille, struct noeud **pracine, struct noeud ***ptabtax, branche **pbranches) { int i, c, rooted, v, error; char *arbre, *p; double root_br_l; struct noeud *racine, *fils, **tabtax; branche *branches = NULL; arbre = strdup(tree); /* lecture de l'arbre */ p = arbre; while(isspace(*p)) p++; if(*p == '[') { do p++; while(*p != ']'); p++; while(isspace(*p)) p++; } if(*p != '(') goto erreur; if(p > arbre) memmove(arbre, p, strlen(p) + 1); p = arbre + 1; notu=2; i=3; v = 0; while( (c=*(p++)) != 0 && c != ';') { if(c == ')') notu++; if(c == '(') i++; if(c == ',') v++; } if(i != notu)goto erreur; totbranches = 0; arbre = (char *)realloc(arbre, strlen(arbre) + 4 * v + 5 ); /* worst case add 4 chars for each , */ p = (char *)make_binary_or_unrooted(arbre); if(p != NULL) return p; notu = v + 1 ; /* after this notu = number of OTUs */ /* allocate all memory */ tabtax = (struct noeud **)calloc(2*notu-1, sizeof(struct noeud *)); for (i = 0; i < 2*notu - 1; i++) { tabtax[i] = (struct noeud *)calloc(1, s_noeud); tabtax[i]->rank = i; } if(notu > 3) branches = (branche *)calloc(notu-3, sizeof(branche)); if(ptaille != NULL) *ptaille = strlen(arbre); error = loadphylip(arbre, &rooted, tabtax, branches); free(arbre); if(error) goto erreur; if(! rooted) { racine = *tabtax; if(num_noeud >= 2*notu - 1) goto erreur; } else { racine = *(tabtax+num_noeud); root_br_l= racine->l1 + racine->l2; /* y a-t-il un bootstrap sur l'une des branches racine ? */ i = get_br_from_bouts(racine, racine->v1, branches); if(i == -1) i = get_br_from_bouts(racine, racine->v2, branches); if(i != -1) { branches[i].bouta = racine->v1; branches[i].boutb = racine->v2; } /* remove the root */ fils = racine->v1; if(fils->v1 == racine) { fils->v1 = racine->v2; fils->l1 = root_br_l; } else if(fils->v2 == racine) { fils->v2 = racine->v2; fils->l2 = root_br_l; } else { fils->v3 = racine->v2; fils->l3 = root_br_l; } fils = racine->v2; if(fils->v1 == racine) { fils->v1 = racine->v1; fils->l1 = root_br_l; } else if(fils->v2 == racine) { fils->v2 = racine->v1; fils->l2 = root_br_l; } else { fils->v3 = racine->v1; fils->l3 = root_br_l; } free(racine); racine = *tabtax; rooted = 0; } if(notu < 2) return (char *)"Tree should contain at least 2 elements."; if(totbranches != notu - 3) return (char *)"Trouble totbranches"; *pracine = racine; *ptabtax = tabtax; *pbranches = branches; return NULL; erreur: return (char *)"File does not contain correct tree data."; } /* end of preptree */ static int loadphylip(char *arbre, int *prooted, struct noeud **tabtax, branche *branches) // returns != 0 iff error { char *deba,*debb,*debc, *finarbre; struct noeud *p1, *p2, *p3, *p; branche *int_br_g, *int_br_d; has_br_length = 2; /* ignore all stuff after last closing parenthesis (needed for fastDNAml output) */ finarbre= nextpar(arbre); *prooted = 0; deba=arbre+1; debb=deba; while(*debb != ',') { if(*debb == 0) return 1; if(*debb == '(')debb=nextpar(debb); debb++; } debb++; debc=debb; while(*debc != ',' && debc it has 3 subtrees at its bottommost level */ debc++; } else { /* the tree is rooted */ debc=finarbre+1; *prooted = 1; } num_noeud = notu-1; nextotu = -1; p1 = unrootedset(deba, debb-2 ,&int_br_g, tabtax, branches); if(p1 == NULL) return 1; p2 = unrootedset(debb, debc-2, &int_br_d, tabtax, branches); if(p2 == NULL) return 1; p = *(tabtax+(++num_noeud)); if(num_noeud >= 2*notu - 1) return 1; if(!has_br_length) { p1->l3 = 0.5*p1->l3; p2->l3 = 0.5*p2->l3; } p->v1=p1; p1->v3=p; p->l1=p1->l3; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p1; } p->v2=p2; p2->v3=p; p->l2=p2->l3; if(int_br_d!=NULL) { int_br_d->bouta=p; int_br_d->boutb=p2; } if(! *prooted) { p3 = unrootedset(debc, finarbre-1, &int_br_g, tabtax, branches); if(p3 == NULL) return 1; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p3; } p->v3=p3; p3->v3=p; p->l3=p3->l3; } else { p->v3=NULL; /* recherche d'un dernier label interne */ if(totbranches < notu - 3) { branches[totbranches].bouta = p1; branches[totbranches].boutb = p2; totbranches++; } } return 0; } struct noeud *unrootedset(char *deb, char *fin, branche **p_int_br, struct noeud **tabtax, branche *branches) //returns NULL iff error { struct noeud *p, *pp; char *virg, *ferme; branche *int_br; static int l; static double brlength; *p_int_br=NULL; while(*deb==' ')deb++; while(*fin==' ')fin--; if(*deb != '(') { /* une feuille */ virg = strchr(deb, ':'); if(virg != NULL && virg < fin) { // if(has_br_length == 0) return NULL; sscanf(virg+1, "%le", &brlength); has_br_length=1; } else { // if(has_br_length == 1) return NULL; brlength = 1; has_br_length=0; virg = fin + 1; } virg--; while(*deb==' ' || *deb=='\'')deb++; if( virg-1 >= deb && *virg == '\'' ) virg--; l = virg-deb+1; p = *(tabtax + ++nextotu); p->nom = (char *)calloc(l + 1, 1); memcpy(p->nom, deb, l); p->nom[l] = 0; p->l3 = brlength; p->v1 = p->v2 = p->v3 = NULL; return p; } /* un noeud */ num_noeud++; if(num_noeud >= 2*notu - 1) return NULL; p = *(tabtax + num_noeud); ferme = nextpar(deb); virg=deb + 1; while(*virg != ',' && virg < fin) { if(*virg == '(') virg=nextpar(virg); virg++; } if(virg>=ferme) return NULL; pp = unrootedset(deb + 1, virg - 1, &int_br, tabtax, branches); if(pp == NULL) return NULL; p->v1 = pp; pp->v3 = p; p->l1 = pp->l3; if(int_br != NULL) { int_br->bouta = p; int_br->boutb = pp; } pp = unrootedset(virg + 1, ferme - 1, &int_br, tabtax, branches); if(pp == NULL) return NULL; p->v2 = pp; pp->v3 = p; p->l2 = pp->l3; if(int_br != NULL) { int_br->bouta = p; int_br->boutb = pp; } virg = strchr(ferme, ':'); if(virg != NULL && virg < fin) { /* traitement longueur */ sscanf(virg+1, "%le", &brlength); has_br_length=1; } else { brlength = 1; has_br_length=0; //virg = fin + 1; } /* recherche bootstrap (internal label) */ if(totbranches < notu-3) { *p_int_br= &branches[totbranches]; totbranches++; } p->l3 = brlength; return p; } /* calcul d'un arbre racine au format phylip */ static char *recur_write_tree(struct noeud *centre, struct noeud *pere, char *arbre, char *finarbre, branche *branches) //returns pter to last used byte of tree or NULL iff error //caution: no null byte after last used byte ! { int l; char *p, *q; struct noeud *gauche, *droit; double lg, ld, lup; if(is_leave(centre)) { l=strlen(centre->nom); if(arbre+l>=finarbre) return NULL; memcpy(arbre,centre->nom,l); arbre += l-1; } else { if(centre->v1 == pere) { gauche = centre->v2; droit = centre->v3; lg = centre->l2; ld = centre->l3; lup = centre->l1; } else if(centre->v2 == pere) { gauche = centre->v1; droit = centre->v3; lg = centre->l1; ld = centre->l3; lup = centre->l2; } else { gauche = centre->v1; droit = centre->v2; lg = centre->l1; ld = centre->l2; lup = centre->l3; } *arbre='('; p = arbre; arbre=recur_write_tree(gauche, centre, arbre+1, finarbre, branches); if(arbre==NULL) return NULL; if(has_br_length) { if(arbre+10>=finarbre) return NULL; sprintf(++arbre,":%.5f",lg); while(*arbre!=0) arbre++; } else arbre++; *arbre=','; arbre = recur_write_tree(droit, centre, arbre+1, finarbre, branches); if(arbre==NULL) return NULL; if(has_br_length) { if(arbre+10>=finarbre) return NULL; sprintf(++arbre,":%.5f",ld); while(*arbre!=0) arbre++; } else arbre++; *arbre=')'; /* ecriture des labels internes */ if( (q = get_br_label(centre, pere, branches)) != NULL && (has_br_length || (lup != 0) ) ) { l=strlen(q); if(arbre+l>=finarbre) return NULL; memcpy(arbre+1,q,l); arbre+=l; } else if( pere != NULL && (!has_br_length) && lup == 0 ) {//multibranches processed here memmove(p, p + 1, arbre - p); arbre -= 2; } } return arbre; } static int get_br_from_bouts(struct noeud *a, struct noeud *b, branche *branches) { int i; for(i=0; i < totbranches; i++) { if(branches[i].bouta==a && branches[i].boutb==b) return i; if(branches[i].boutb==a && branches[i].bouta==b) return i; } return -1; } static int for_all_branches(struct noeud *centre, struct noeud *origine, branche *branches) /* parcourir recursivement toutes les branches de l'arbre sans racine a partir de centre et dans la direction opposee a son voisin origine returns 1 iff error */ { if(centre==NULL) return 0; if(centre->v1!=origine) { if( process_branch(centre, centre->v1, branches) ) return 1; if( for_all_branches(centre->v1, centre, branches) ) return 1; } if(centre->v2!=origine) { if( process_branch(centre, centre->v2, branches) ) return 1; if( for_all_branches(centre->v2, centre, branches) ) return 1; } if(centre->v3!=origine) { if( process_branch(centre, centre->v3, branches) ) return 1; if( for_all_branches(centre->v3, centre, branches) ) return 1; } return 0; } static int process_branch(struct noeud *cote1, struct noeud *cote2, branche *branches) //returns 1 iff error { int num; branche *br; /* eliminer branches terminales */ if(is_leave(cote1) || is_leave(cote2) ) return 0; if(!has_br_length) {//if no branch length ignore multifurcations if(cote1->v1 == cote2 && cote1->l1 == 0) return 0; if(cote1->v2 == cote2 && cote1->l2 == 0) return 0; if(cote1->v3 == cote2 && cote1->l3 == 0) return 0; } num = get_br_from_bouts(cote1, cote2, branches); if(num == -1) return 1; br = &branches[num]; br->bits = (int *)calloc(w_bits, sizeof(int)); br->count = 0; br->next_h = NULL; set_leaves(cote1, cote2, br->bits); if(! testbit(br->bits, 1) ) { int width, word = 1; non(br->bits, br->bits, w_bits); /* eliminer bits a 1 terminaux */ width = notu % lmot; if(width > 1) word = (1 << width) - 1; if(width > 0) br->bits[w_bits - 1] &= word; } add_hash(br); return 0; } void set_leaves(struct noeud *centre, struct noeud *pere, int *bits) { if(is_leave(centre)) { bit1(bits, centre->rank + 1); return; } if(centre->v1 != pere)set_leaves(centre->v1, centre, bits); if(centre->v2 != pere)set_leaves(centre->v2, centre, bits); if(centre->v3 != pere)set_leaves(centre->v3, centre, bits); } void parcourir_branches_each(struct noeud *centre, struct noeud *origine, float w) /* parcourir recursivement toutes les branches de l'arbre sans racine a partir de centre et dans la direction opposee a son voisin origine */ { if(centre==NULL) return; if(centre->v1!=origine) { if (centre->l1) process_branch_each(centre, centre->v1, w); parcourir_branches_each(centre->v1, centre, w); } if(centre->v2!=origine) { if (centre->l2) process_branch_each(centre, centre->v2, w); parcourir_branches_each(centre->v2, centre, w); } if(centre->v3!=origine) { if (centre->l3) process_branch_each(centre, centre->v3, w); parcourir_branches_each(centre->v3, centre, w); } } void process_branch_each(struct noeud *cote1, struct noeud *cote2, float w) { branche *br; /* eliminer branches terminales */ if(is_leave(cote1) || is_leave(cote2) ) return; memset(candidate_bits, 0, w_bits * sizeof(int)); set_leaves(cote1, cote2, candidate_bits); if(! testbit(candidate_bits, 1) ) { int width, word = 1; non(candidate_bits, candidate_bits, w_bits); /* eliminer bits a 1 terminaux */ width = notu % lmot; if(width > 1) word = (1 << width) - 1; if(width > 0) candidate_bits[w_bits - 1] &= word; } br = find_branch(candidate_bits); if(br != NULL) br->count += w; } branche *find_branch(int *bits) { int h; branche *br; h = hashvalue(bits, modulo, notu); br = hashtable[h]; while(br != NULL) { if(memcmp(br->bits, bits, w_bits * sizeof(int) ) == 0) return br; br = br->next_h; } return NULL; } void add_hash(branche *br) { int h; branche *old; h = hashvalue(br->bits, modulo, notu); old = hashtable[h]; hashtable[h] = br; br->next_h = old; } inline int is_leave(struct noeud *n) { return n->nom != NULL; } char *get_br_label(struct noeud *a, struct noeud *b, branche *branches) { int i; i = get_br_from_bouts(a, b, branches); return (i == -1 ? NULL : branches[i].br_label); } static int hashvalue(int *bits, int modulo, int totbits) { /* inspire de celui de java */ const unsigned maxi = (UINT_MAX - 256) / 37; unsigned c, h = 0; unsigned char *debut, *fin; debut = (unsigned char *)bits; fin = debut + (totbits-1)/8; debut--; while(++debut <= fin ) { c = *debut; h = h * 37 + c; if(h >= maxi) h %= modulo; } return h % modulo; } int recodeleaves(struct noeud *node, struct noeud *parent, struct noeud **tabtax) //returns != 0 iff error { int i; if(node == NULL) return 0; if(is_leave(node)) { for(i=0; i < notu; i++) { if(strcmp(node->nom, tabtax[i]->nom)==0) { node->rank = i; break; } } if(i>= notu) return 1; } if(node->v1 != parent) recodeleaves(node->v1, node, tabtax); if(node->v2 != parent) recodeleaves(node->v2, node, tabtax); if(node->v3 != parent) recodeleaves(node->v3, node, tabtax); return 0; } static void use_count(branche *branches, int count) { int num; char text[20], *p; branche *br; char nan[] = "NaN"; if (count) p = text; else p = nan; for(num = 0; num < totbranches; num++) { br = branches + num; if(br->br_label != NULL) free(br->br_label); if (count) sprintf(text, "%d", (int)(br->count * 100. / count + 0.5) ); br->br_label = strdup(p); } } void bit0(int *plist, int num) { num--; plist+=(num/lmot); *plist &= ~(1<<(num%lmot)); } void bit1(int *plist, int num) { num--; plist+=(num/lmot); *plist |= (1<<(num%lmot)); } int testbit(int *plist, int num) { num--; plist += (num/lmot); return (*plist) & (1<<(num%lmot)); } void non(int *listnon, int *list, int len) { int i; for(i=0; i< len; i++) listnon[i]= ~list[i]; } void et(int *listet, int *list1, int *list2, int len) { int i; for (i = 0; i < len; i++) listet[i] = list1[i] & list2[i]; } int irbit(int *pdeblist, int deb, int fin) /* finds next set bit strictly after bit of rank deb and before that of rank fin returns rank of that bit or 0 if none present */ { unsigned int mot; int *plist, *debw, *finw, retval, d; if(deb >= fin) return 0; finw = pdeblist+(fin-1)/lmot; debw = pdeblist+deb/lmot; plist = debw; mot = *plist; if( (d = deb%lmot) != 0) mot = ( mot>>d ) << d; if(mot == 0 && plist < finw) { do { if ( *(++plist) != 0) break; } while ( plist < finw ); mot = *plist; } if( plist == finw && (d = fin%lmot) != 0 ) { d = lmot-d; mot <<= d; mot >>= d; } if(mot == 0)return 0; retval = (plist-pdeblist)*lmot + 1; while( (mot&1) == 0 ) { mot >>= 1; retval++; } return retval; /* the instruction mot = mot ^ (~(-mot)); replaces x...x10...0 by 0...011...1 so that the bit count operation can be used to find first set bit */ } /* Returns the Newick string of the consensus tree expressed as a list of internal branches, each branch i is represented by a bitlist rows[i] (one bit for each leave, 1s on one side, 0s on the other; rows are standardized with their first bit at 1). The resulting tree is multibranched, unrooted, without length nor branch support. This function could be expanded to output also branch support. Initialization: Build the array of columns: bitlists obtained by reading perpendicular to the rows, one column for each leave. Prepare a string pter for each leave initialized to its name. Prepare row-mask a bitlist with 1 for each column. Prepare column-mask a bitlist with 1 for each row (=branch). Definition: a multibranched cherry is a tree node with only terminal branches on one side; a multibranched cherry is detectable relatively to an internal branch: all columns indexed by the leaves at one or the other side of the branch are identical. Algorithm: For each row (=branch) k, check whether all columns for unmasked leaves i1,i2,... at its 1-side are identical (mask with column-mask when comparing columns); if not, check whether all columns for unmasked leaves i1,i2,... at its 0-side are identical; if not, continue with next branch; if yes, build the Newick form of this cherry: "(i1,i2,...)" and attach it to i1's pter and put 0 to other leave pters. Remove i2,... from row-mask. Remove k from column-mask. Continue until all rows (=branches) have been removed. Finally, 3 or more leaves remain, and the full Newick string concatenates the strings attached to them. */ char *compute_consensus_tree(char **seqnames, int **rows, int branch_count) { // each row represents a tree branch as the bitlist of leaves on one side of the branch int i, j, k, l, w, word, restbranches, j1; char *newtree, *p; char **treeparts = (char**)malloc(notu*sizeof(char*)); // treepart[i] will be the growing string of subtree containing leave i, or NULL for (i = 0; i < notu; i++) treeparts[i] = strdup(seqnames[i]); int height = (branch_count-1)/lmot + 1; // length of column bitlists int width = (notu-1)/lmot + 1; // length of row bitlists int *column_tmp = (int*)malloc(height*sizeof(int)); int *column_mask = (int*)malloc(height*sizeof(int)); // bitlist of remaining rows (= branches) memset(column_mask, -1, height*sizeof(int)); int *row_tmp = (int*)malloc(width*sizeof(int)); int *row_mask = (int*)malloc(width*sizeof(int)); // bitlist of remaining columns memset(row_mask, -1, width*sizeof(int)); /* clear bits after end of bitlist */ word = 1; w = notu % lmot; if (w > 1) word = (1 << w) - 1; if (w > 0) row_mask[width - 1] &= word; // build the column table: one column for each tree leave, perpendicular to bit array of rows int **columns = (int**)malloc(notu*sizeof(int*)); for (i = 0; i < notu; i++) { columns[i] = (int*)calloc(height, sizeof(int)); } for (i = 0; i < branch_count; i++) { for (j = 0; j < notu; j++) { if (testbit(rows[i], j+1)) bit1(columns[j], i+1); } } restbranches = branch_count; // number of remaining branches to process while (restbranches > 0) { for (i = 0; i < branch_count; i++) { // loop for all rows i if (!testbit(column_mask, i+1)) continue; // skip removed rows(=branches) et(row_tmp, rows[i], row_mask, width); // mask out removed leaves j1 = irbit(row_tmp, 0, notu); // find first leave on 1-side of branch i j = j1-1; et(column_tmp, columns[j], column_mask, height); // mask out removed rows while ( (j1 = irbit(row_tmp, j1, notu)) != 0) { // for all other leaves on 1-side of branch i for (k = 0; k < height; k++) { // check that column k is identical-with-mask to column j1-1 if (column_tmp[k] != (columns[j1-1][k] & column_mask[k])) break; } if (k < height) break; } if (k < height) { // columns were not all identical, try columns on 0-side of branch i non(row_tmp, rows[i], width); // list of leaves on 0-side of branch et(row_tmp, row_tmp, row_mask, width); // mask out removed leaves j1 = irbit(row_tmp, 0, notu); // find first leave on 0-side of branch i j = j1-1; et(column_tmp, columns[j], column_mask, height); // mask out removed rows while ( (j1 = irbit(row_tmp, j1, notu)) != 0) {// for all other leaves on 0-side of branch i for (k = 0; k < height; k++) { // check that column k is identical-with-mask to column j1-1 if (column_tmp[k] != (columns[j1-1][k] & column_mask[k])) break; } if (k < height) break; } } if (k < height) continue; // not all colummns on one side of the branch were identical-with-mask // we have found a cherry corresponding to row i j = irbit(row_tmp, 0, notu) - 1; // first of the cherry leaves bit0(column_mask, i+1); // remove row (=tree internal branch) i from list of remaining rows restbranches--; // one branch less to process // build growing tree string containing leave j newtree = (char*)malloc(strlen(treeparts[j]) + 2); sprintf(newtree, "(%s", treeparts[j]); j1 = j+1; while ( (j1 = irbit(row_tmp, j1, notu)) != 0) { // add names of all found leaves k = j1-1; l = strlen(newtree) + strlen(treeparts[k]) + 2; newtree = (char*)realloc(newtree, l+1); strcat(newtree, ","); strcat(newtree, treeparts[k]); free(treeparts[k]); treeparts[k] = NULL; } strcat(newtree, ")"); free(treeparts[j]); treeparts[j] = newtree; for (k = 0; k < width; k++) { // remove found leaves from row_mask row_mask[k] &= (~row_tmp[k]); } bit1(row_mask, j+1); // except leave j } } // end of loop while branches remain l = 0; // build complete Newick string of tree after all branches have been processed for (i = 0; i < notu; i++) { // 3 or more non-NULL treeparts[i] remain if (treeparts[i]) l += strlen(treeparts[i]) + 1; } newtree = (char*)malloc(l + 3); p = newtree; for (i = 0; i < notu; i++) { if (!treeparts[i]) continue; sprintf(p, ",%s", treeparts[i]); p += strlen(p); free(treeparts[i]); treeparts[i] = NULL; } *newtree = '('; strcpy(p, ");"); // final Newick string is complete free(column_mask); // free memory free(column_tmp); free(row_mask); free(row_tmp); for (i = 0; i < notu; i++) free(columns[i]); free(columns); free(treeparts); return newtree; } void init_consensus_calculation(int n) { notu = n; w_bits = (notu-1) / lmot + 1; modulo = 997; hashtable = (branche **)calloc(modulo, sizeof(branche *)); candidate_bits = (int *)calloc(w_bits, sizeof(int)); } static int recodeleaves_consensus(struct noeud *node, struct noeud *parent, char **seqnames) //returns != 0 iff error { int i; if (node == NULL) return 0; if (is_leave(node)) { for (i=0; i < notu; i++) { if (strcmp(node->nom, seqnames[i])==0) { node->rank = i; break; } } if (i>= notu) return 1; } if (node->v1 != parent) recodeleaves_consensus(node->v1, node, seqnames); if (node->v2 != parent) recodeleaves_consensus(node->v2, node, seqnames); if (node->v3 != parent) recodeleaves_consensus(node->v3, node, seqnames); return 0; } branche *find_branch_consensus(int *bits) { int h; branche *br; h = hashvalue(bits, modulo, notu); br = hashtable[h]; while (br != NULL) { if(memcmp(br->bits, bits, w_bits * sizeof(int) ) == 0) return br; br = br->next_h; } br = (branche*)calloc(1, sizeof(branche));; br->bits = (int*)malloc(w_bits*sizeof(int)); memcpy(br->bits, bits, w_bits*sizeof(int)); br->count = 0; br->next_h = NULL; add_hash(br); return br; } static void process_branch_consensus(struct noeud *cote1, struct noeud *cote2) { branche *br; /* eliminer branches terminales */ if (is_leave(cote1) || is_leave(cote2) ) return; memset(candidate_bits, 0, w_bits * sizeof(int)); set_leaves(cote1, cote2, candidate_bits); if (! testbit(candidate_bits, 1) ) { int width, word = 1; non(candidate_bits, candidate_bits, w_bits); /* eliminer bits a 1 terminaux */ width = notu % lmot; if (width > 1) word = (1 << width) - 1; if (width > 0) candidate_bits[w_bits - 1] &= word; } br = find_branch_consensus(candidate_bits); br->count += 1; } static void parcourir_branches_consensus(struct noeud *centre, struct noeud *origine) /* parcourir recursivement toutes les branches de l'arbre sans racine a partir de centre et dans la direction opposee a son voisin origine */ { if(centre==NULL) return; if(centre->v1!=origine) { if (centre->l1) process_branch_consensus(centre, centre->v1); parcourir_branches_consensus(centre->v1, centre); } if(centre->v2!=origine) { if (centre->l2) process_branch_consensus(centre, centre->v2); parcourir_branches_consensus(centre->v2, centre); } if(centre->v3!=origine) { if (centre->l3) process_branch_consensus(centre, centre->v3); parcourir_branches_consensus(centre->v3, centre); } } int process_one_consensus_item(char *one_tree, char **seqnames) { struct noeud *eachroot; char *message; struct noeud **eachtabtax; branche *eachbranches; message = preptree(one_tree, NULL, &eachroot, &eachtabtax, &eachbranches); if (message != NULL) return 0; if( recodeleaves_consensus(eachroot, NULL, seqnames) ) return 0; parcourir_branches_consensus(eachroot, NULL); free_arbre(eachroot, NULL); free(eachtabtax); free_branches(eachbranches); return 1; } int after_consensus_items(float threshold, int item_count, int ***prows) { branche *br, *br2; int i, j = 0, br_count = 0; if (threshold > 0.999) threshold = 0.999; else if (threshold < 0.501) threshold = 0.501; for (i = 0; i < modulo; i++) { br = hashtable[i]; while (br) { if (br->count/item_count >= threshold) br_count++; else free(br->bits); br = br->next_h; } } int **rows = (int**)malloc(br_count * sizeof(int*)); for (i = 0; i < modulo; i++) { br = hashtable[i]; while (br) { if (br->count/item_count >= threshold) rows[j++] = br->bits; br2 = br->next_h; free(br); br = br2; } } *prows = rows; free(hashtable); free(candidate_bits); return br_count; } seaview/align.cxx000644 000765 000024 00000146530 12404325714 014655 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include #include #include #ifdef unix #include #endif #ifdef WIN32 #define tempnam _tempnam #endif #define MAX_MSA_ALGOS 10 //max # of alignment methods allowed in Props menu /* local prototypes */ int save_part_as_pir(int debut, int fin, char **sequence, char **seqname, int *sel_seqs, int tot_seqs, char *fname, int *withU, int *num_longest, int protein); int replace_align_part(SEA_VIEW *view, int debut, int fin, char *fname, int withU, int num_longest, int *tmpselseqs, align_choice mychoice, const char **err_message); int calc_gap_sites(char *old_seq, char *new_seq, int lold, int lnew, gap_site *gap_sites, int maxsites); int insert_gaps_new_align(char **seq, int site, int number, int numseqs, int lseqs); int reset_stars(SEA_VIEW *view, int debut, int lpart, char **seq, int lfrag, int *tmpselseqs); int confirm_refer_seq(int num_longest, SEA_VIEW *view, int *tmpselseqs); char *calc_msa_command(SEA_VIEW *view, char *base_fname, void (*alert)(const char *,...) ); void cre_align_menu(SEA_VIEW *view); void align_opt_callback(Fl_Widget *ob, long unused); char *get_algo_opts(int algonum /* from 0 */, char **presname); char *get_opt_resname(int algonum); void set_algo_option_item(char *opts, Fl_Menu_Item *menu, int itemrank, int checkit); void add_align_callback(Fl_Widget *ob, void *data); void delete_align_callback(Fl_Widget *ob, void *data); void add_align_w_callback(Fl_Widget *ob, void *data); void edit_align_callback(Fl_Widget *ob, void *data); void init_msa_algos(void); void profile_align(SEA_VIEW *view); void replace_stars(char *fname); void back_to_stars(char *aligned, char *ori); int save_fasta_file_no_gaponly(char *fname, char **sequence, int tot_seqs, int *each_length, int *sel_seqs); void unalign(SEA_VIEW *view); int reorder_seqs(int tot, char **seq, char **name); int check_alignment_characters(SEA_VIEW *view, int *sel_seqs); int command_line_align(int argc, char **argv); /* extern proto */ extern const char *progname; extern int run_external_prog_in_pseudoterm(char *cmd, const char *dialogfname, const char *label); extern int insert_gaps_at(SEA_VIEW *view, int seq, int site, int total); extern int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view); extern void del_gap_only_sites(SEA_VIEW *view); extern char *get_res_value(const char *name, const char *def_value); extern int int_res_value(const char *name, int def_value); extern int set_res_value(const char *name, const char *value); extern void delete_res_value(const char *name); extern void save_resources(void); extern char *create_tmp_filename(void); extern void delete_tmp_filename(const char *base_fname); extern void direct_help_callback(Fl_Widget *wgt, void *data); extern int compute_size_params(SEA_VIEW *view, int force_recompute); extern char **prepcolranks_by_codon(char **seq, int totseqs, int maxlen, int *eachlength, char **comments); extern int is_view_valid(SEA_VIEW *view); extern int calc_max_seq_length(int seq_length, int tot_seqs); extern void allonge_seqs(char **seq, int totseqs, int maxlen, int *eachlength, int tot_comment_lines, char **comment_line, char **pregion_line); extern SEA_VIEW *cmdline_read_input_alignment(int argc, char **argv); extern bool isarg(int argc, char *argv[], const char *arg); extern float argval(int argc, char *argv[], const char *arg, float defval); extern char *argname(int argc, char *argv[], const char *arg); extern int get_ncbi_gc_from_comment(char *comment); extern char *translate_with_gaps(char *seq, int gc); extern char *back_translate_with_gaps(char *prot, char *dna); extern char *process_output_options(int argc, char **argv, known_format& out_format, bool& std_output); extern void load_resources(const char *progname); extern "C" { int get_acnuc_gc_number(int ncbi_gc); } /* extern variables */ extern gap_site gap_sites[]; int save_part_as_pir(int debut, int fin, char **sequence, char **seqname, int *sel_seqs, int tot_seqs, char *fname, int *withU, int *num_longest, int protein) /* returns TRUE iff error */ { FILE *out; int num, pos, l_line, retval, maxlen, seqlen, current, empty_seq; char line[90], lname[25]; out = fopen(fname,"w"); if( out == NULL ) return TRUE; retval = TRUE; *withU = FALSE; maxlen = 0; current = 0; for(num = 0; num < tot_seqs; num++) { if(! sel_seqs[num] ) continue; empty_seq = TRUE; l_line = 0; seqlen = 0; for ( pos = debut - 1 ; pos < fin; pos++) { if( sequence[num][pos] == 0 ) break; if( sequence[num][pos] == '-' || sequence[num][pos] == '!') continue; if(empty_seq) { sprintf(lname, "%d_%.10s", ++current, seqname[num]); fprintf(out, ">%.10s\n", lname); if(ferror(out)) goto fin; empty_seq = FALSE; } if(l_line >= 70) { line[l_line] = 0; if(!*withU) *withU = (strchr(line, 'U') != NULL); fprintf(out, "%s\n", line); if(ferror(out)) goto fin; seqlen += l_line; l_line = 0; } line[l_line++] = sequence[num][pos]; if(sequence[num][pos] == '*') line[l_line - 1] = 'X'; if(sequence[num][pos] == '?') line[l_line - 1] = 'X'; } line[l_line] = 0; seqlen += l_line; if(seqlen > maxlen) { maxlen = seqlen; *num_longest = num; } if(!*withU) *withU = (strchr(line, 'U') != NULL); fprintf(out, "%s\n", line); if(ferror(out)) goto fin; if(empty_seq) sel_seqs[num] = FALSE; } retval = FALSE; fin: if( fclose(out) != 0) return TRUE; return retval; } #if ! ( defined(WIN32) || defined(__APPLE__) ) void align_listener(int fd, void *data) { char line[100]; int l = read(fd, line, sizeof(line)); if(l == 0) *(int *)data = TRUE; } #endif void align_selected_parts(SEA_VIEW *view, align_choice my_align_choice, bool no_gui) { int debut, fin, status, withU, *tmpselseqs, num_longest, l; char *p; char base_fname[PATH_MAX], fname[PATH_MAX]; char *commande; FILE *in; void (*alert)(const char *,...) = no_gui ? Fl::fatal : fl_alert; if( my_align_choice == ALIGN_SITES && (view->active_region == NULL || view->active_region->list == NULL || view->active_region->list->next != NULL || view->tot_sel_seqs <= 1) ) { alert("Need to have exactly one block of selected sites\n" "and some selected sequences"); return; } if(my_align_choice == ALIGN_SELECTED_SEQS) { if(view->tot_sel_seqs == 0) return; if ( !no_gui && ! fl_choice("Confirm alignment of %d selected sequences ?\n" "(Any previous alignment between selected and other sequences will disappear)", "Cancel", "Align", NULL, view->tot_sel_seqs) ) return; } if(my_align_choice == ALIGN_ALL || my_align_choice == ALIGN_SELECTED_SEQS) { debut = 1; fin = view->seq_length; } else { debut = view->active_region->list->debut; fin = view->active_region->list->fin; } p = create_tmp_filename(); if(p == NULL) return; strcpy(base_fname, p); sprintf(fname, "%s.pir", base_fname); /* allonger les seqs plus courtes que la region traitee sans compter comme modif alignment*/ int old_modif_but_not_saved = view->modif_but_not_saved; for(l = 0; l < view->tot_seqs; l++) { if(my_align_choice != ALIGN_ALL && !view->sel_seqs[l]) continue; if(fin > view->each_length[l]) insert_gaps_at(view, l + 1, view->each_length[l] + 1, fin - view->each_length[l]); } if (!no_gui) set_seaview_modified(view, old_modif_but_not_saved); /* prepare list of empty seqs */ tmpselseqs = (int *)malloc(view->tot_seqs * sizeof(int)); if(my_align_choice == ALIGN_ALL) memset(tmpselseqs, 1, view->tot_seqs * sizeof(int)); else memcpy(tmpselseqs, view->sel_seqs, view->tot_seqs * sizeof(int)); if ( check_alignment_characters(view, tmpselseqs) ) return; status = save_part_as_pir(debut, fin, view->sequence, view->seqname, tmpselseqs, view->tot_seqs, fname, &withU, &num_longest, view->protein); //if(view->protein) //clustalw2 now accepts U and muscle also withU = FALSE; if(status) { alert("Cannot write sequences to filename\n%s", fname); free(tmpselseqs); delete_tmp_filename(base_fname); return; } if( !no_gui && my_align_choice == ALIGN_SITES ) num_longest = confirm_refer_seq(num_longest, view, tmpselseqs); if(num_longest == -1 ) { free(tmpselseqs); delete_tmp_filename(base_fname); return; } commande = calc_msa_command(view, base_fname, alert); status = (commande == NULL); if(status) { free(tmpselseqs); delete_tmp_filename(base_fname); return; } if (no_gui) { #ifdef WIN32 #define system(a) mysystem(a) extern int mysystem(const char *command); #endif status = system(commande); } else status = run_external_prog_in_pseudoterm(commande, NULL, "alignment"); free(commande); sprintf(fname, "%s.out", base_fname); if( status == 0 ) { in = fopen(fname, "r"); if(in != NULL) { fseek(in, 0, SEEK_END); status = (ftell(in) < 10); fclose(in); } else status = 1; } if (no_gui || is_view_valid(view)) { if( status != 0 ) alert("%s: alignment operation ignored", extract_filename(view->masename)); else { const char *err_message; status = replace_align_part(view, debut, fin, fname, withU, num_longest, tmpselseqs, my_align_choice, &err_message ); if (status) alert("%s", err_message); else if(my_align_choice == ALIGN_ALL) del_gap_only_sites(view); } } free(tmpselseqs); delete_tmp_filename(base_fname); } int calc_gap_sites(char *old_seq, char *new_seq, int lold, int lnew, gap_site *gap_sites, int maxsites) { char *fin_old, *fin_new; int tot_sites = 0, posalign = 0; fin_old = old_seq + lold - 1; fin_new = new_seq + lnew - 1; while( old_seq <= fin_old || new_seq <= fin_new ) { if(old_seq <= fin_old && new_seq <= fin_new && ( ( *old_seq != '-' && *new_seq != '-') || ( *old_seq == '-' && *new_seq == '-') ) ){ old_seq++; new_seq++; posalign++; continue; } if(tot_sites >= maxsites) return -1; gap_sites[tot_sites].l[1] = 0; gap_sites[tot_sites].l[0] = 0; if(old_seq <= fin_old && *old_seq == '-') { gap_sites[tot_sites].pos = posalign; do { old_seq++; ++(gap_sites[tot_sites].l[1]); } while( *old_seq == '-' && old_seq < fin_old); posalign += gap_sites[tot_sites].l[1]; } else { gap_sites[tot_sites].pos = posalign; do { new_seq++; ++(gap_sites[tot_sites].l[0]); } while( *new_seq == '-' && new_seq < fin_new); posalign += gap_sites[tot_sites].l[0]; } tot_sites++; } return tot_sites; } int replace_align_part(SEA_VIEW *view, int debut, int fin, char *fname, int withU, int num_longest, int *tmpselseqs, align_choice mychoice, const char **err_message) /* returns TRUE if error, FALSE if ok */ { int num, lfrag, lpart, i, rang, retval, newlength, lfrag2, total; char **seq, **comments, **seqname, *pheader; int (*calc_color_function)(int); int totgapsites, num1, site, l_copy, res; char *tmp; total = 0; for(num = 0; num < view->tot_seqs; num++) if(tmpselseqs[num]) total++; view->cursor_in_comment = FALSE; view->cursor_seq = view->first_seq; /* lecture de l'alignement multiple produit par clustalw */ num = read_fasta_align(fname, &seq, &seqname, &comments, &pheader, (char **)err_message, FALSE); if(num == total && reorder_seqs(num, seq, seqname) ) { *err_message = "Error: not enough memory."; return TRUE; } for(i = 0; i < num; i++) free(seqname[i]); if(num > 0) { free(seqname); free(comments); } if( num != total) { if(num > 0) free(seq); static char *message = NULL; if (message) free(message); message = (char*)malloc(strlen(fname) + 100); sprintf(message, "Error in file of aligned sequences:\n%s", fname); *err_message = message; return TRUE; } retval = TRUE; if(withU) { /* si seq avec U au depart, les remettre car ont ete changes en T par clustalw */ char *p, *q; for(num = 0; num < total; num++) { p = seq[num]; while( (q = strchr(p, 'T')) != NULL) { *q = 'U'; p = q; } } } lfrag = strlen(seq[0]); /* long alignement de clustalw */ lpart = fin - debut + 1; /*long region traitee de l'ancien alignement multiple*/ if( (num = reset_stars(view, debut, lpart, seq, lfrag, tmpselseqs)) ) { *err_message = "Error: mismatch between alignment input and output."; return TRUE; } if(view->numb_gc > 1) { calc_color_function = ( view->protein ? get_color_for_aa : get_color_for_base ); } if(mychoice == ALIGN_SITES) { /* num1 = rang dans align clustalw de num_longest dans align multiple */ num1 = -1; for(i = 0; i < view->tot_seqs; i++) { if( ! tmpselseqs[i] ) continue; num1++; if( i == num_longest) break; } /* calcul des pos et longs de gaps a inserer: gap_sites[x].pos = position a droite du gap a inserer (from 0) gap_sites[x].l[0] = longueur a inserer dans alignement multiple gap_sites[x].l[1] = longueur a inserer dans alignement produit par clustalw */ totgapsites = calc_gap_sites(view->sequence[num_longest] + debut - 1, seq[num1], FL_min(lpart, view->each_length[num_longest] - debut + 1), lfrag, gap_sites, MAX_GAP_SITES); if(totgapsites == -1) { *err_message = "Error: reduce length of aligned sequences or increase parameter MAX_GAP_SITES."; goto fin; } /* calcul long region traitee apres ajout des gaps */ for(site=0; siteseq_length + lpart - (fin - debut + 1) > view->max_seq_length ) { *err_message = "Error: reduce length of aligned sequences."; goto fin; } /* calcul long alignement de clustalw apres ajout des gaps */ lfrag2 = lfrag; for(site = 0; site < totgapsites; site++) lfrag2 += gap_sites[site].l[1]; /* allongement memoire pour seqs de l'alignement de clustalw */ for(num=0; numseq_length; /* allongement des seqs de l'alignement multiple */ for(site = 0; site < totgapsites; site++) { if(gap_sites[site].l[0] == 0) continue; for(num = 0; num < view->tot_seqs; num++) { insert_gaps_at(view, num + 1, debut + gap_sites[site].pos, gap_sites[site].l[0]); } newlength += gap_sites[site].l[0]; insert_region_part(view, debut + gap_sites[site].pos, gap_sites[site].l[0]); if(view->tot_comment_lines > 0) insert_gap_all_comments( gap_sites[site].l[0], debut + gap_sites[site].pos, view); } /* copie des sequences de clustalw vers alignement multiple */ rang = -1; for(num = 0; num < view->tot_seqs; num++) { if( ! tmpselseqs[num] ) continue; rang++; /* on met les nouvelles seqs */ l_copy = FL_min(lpart, lfrag); memcpy( view->sequence[num] + debut - 1, seq[rang], l_copy); if(debut + l_copy - 1 > view->each_length[num]) view->each_length[num] = debut + l_copy - 1; newlength = FL_max(newlength, view->each_length[num]); if(view->each_length[num] == debut + l_copy - 1) view->sequence[num][debut + l_copy - 1] = 0; if(view->numb_gc == 1) continue; for(i = debut - 1; i < debut + l_copy - 1; i++) { res = view->sequence[num][i]; if (view->col_rank) view->col_rank[num][i] = (char)calc_color_function( res ); } } } else { if (lfrag > view->max_seq_length) { view->max_seq_length = calc_max_seq_length(lfrag, view->tot_seqs); for (num = 0; view->col_rank && num < view->tot_seqs; num++) { free(view->col_rank[num]); } if (view->col_rank) free(view->col_rank); allonge_seqs(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, &view->region_line); if (view->col_rank) view->col_rank = prepcolranks(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); } newlength = view->seq_length; rang = -1; for(num = 0; num < view->tot_seqs; num++) { if( ! tmpselseqs[num] ) continue; rang++; /* on met les nouvelles seqs */ l_copy = strlen(seq[rang]); strcpy(view->sequence[num], seq[rang]); view->each_length[num] = l_copy; newlength = FL_max(newlength, l_copy); if(view->numb_gc > 1) { for (i = 0; view->col_rank && i < view->each_length[num]; i++) { res = view->sequence[num][i]; view->col_rank[num][i] = (char)calc_color_function( res ); } } } } if (view->col_rank) { /* mettre a jour horsli */ if(mychoice == ALIGN_ALL) { view->seq_length = 0; for(num = 0; num < view->tot_seqs; num++) view->seq_length = FL_max(view->seq_length, view->each_length[num]); compute_size_params(view, TRUE); view->horsli->redraw(); } else update_current_seq_length(newlength, view); set_seaview_modified(view, TRUE); } retval = FALSE; fin: for(num = 0; num < total; num++) free(seq[num]); free(seq); return retval; } int insert_gaps_new_align(char **seq, int site, int number, int numseqs, int lseqs) { int num; char *pos; for(num=0; num < numseqs; num++) { pos = seq[num] + site; memmove(pos + number, pos, lseqs - site + 1); memset(pos, '-', number); } return lseqs + number; } int reset_stars(SEA_VIEW *view, int debut, int lpart, char **seq, int lfrag, int *tmpselseqs) /* returns 0 iff OK, or mismatch between alignment input and output */ { int oldseq, newseq; char *p, *q; newseq = -1; for(oldseq = 0; oldseq < view->tot_seqs; oldseq++) { if(! tmpselseqs[oldseq] ) continue; newseq++; p = view->sequence[oldseq] + debut - 2; q = seq[newseq] - 1; while(TRUE) { p++; q++; while (*p == '-' || *p == '!') p++; while (*q == '-' || *q == '!') q++; if(*p == 0 || *q == 0) break; if( *p == '*' && *q == 'X') *q = '*'; if( *p == '?' && *q == 'X') *q = '?'; if( toupper(*p) != toupper(*q) ) return 1; if( islower(*p) ) *q = *p; } } return 0; } int confirm_refer_seq(int num_longest, SEA_VIEW *view, int *tmpselseqs) { static Fl_Window *form; static int first = TRUE; static Fl_Browser *browser_noms; static Fl_Button *ok_button, *cancel_button; int lnum, i; if(first) { first = FALSE; form = new Fl_Window( 300, 400); form->label("Reference Sequence"); form->box(FL_FLAT_BOX); fl_font(FL_HELVETICA, FL_NORMAL_SIZE); browser_noms = new Fl_Browser(5, 5 + fl_height(), form->w() - 10, form->h() - 35 - fl_height(), "Choose one seq."); browser_noms->type(FL_HOLD_BROWSER); browser_noms->textsize(FL_NORMAL_SIZE); browser_noms->has_scrollbar(Fl_Browser_::VERTICAL); browser_noms->align(FL_ALIGN_TOP); browser_noms->color(FL_LIGHT1, browser_noms->selection_color()); ok_button = new Fl_Return_Button(5, form->h() - 25, browser_noms->w() / 2, 20, "OK"); cancel_button = new Fl_Button(ok_button->x() + ok_button->w(), ok_button->y(), ok_button->w(), ok_button->h(), "Cancel"); form->resizable(browser_noms); form->end(); form->set_modal(); } browser_noms->clear(); lnum = 0; for(i = 0; i < view->tot_seqs; i++) { if(!tmpselseqs[i]) continue; lnum++; browser_noms->add(view->seqname[i]); if(i == num_longest) browser_noms->value(lnum); } form->show(); for (;;) { Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); else if (o == cancel_button || o == form) { num_longest = -1; break; } else if(o == ok_button && browser_noms->value() != 0) break; } form->hide(); if(num_longest == -1) return -1; Fl::flush(); lnum = browser_noms->value(); for(i = 0; i < view->tot_seqs; i++) { if(!tmpselseqs[i]) continue; if(strcmp(view->seqname[i], browser_noms->text(lnum)) == 0) { num_longest = i; break; } } return num_longest; } char *calc_msa_command(SEA_VIEW *view, char *base_fname, void (*alert)(const char *,...) ) { char *command; char *algo_name; char local[400], tmp[400], *p, *optargs; int status; sprintf(tmp, "msa_name_%d", view->alignment_algorithm + 1); algo_name = strdup( get_res_value(tmp, NULL) ); /* check if program present */ #if defined(WIN32) char w32path[400]; strcpy(tmp, algo_name); if(strchr(algo_name, '\\') == NULL && strchr(algo_name, '.') == NULL) strcat(tmp, ".exe"); p = get_full_path(tmp); if(p != NULL) strcpy(w32path, p); status = (p == NULL); #else status = (get_full_path(algo_name) == NULL); #endif if(status) { alert("Alignment is impossible because program '%s' is not found\n" "in PATH or seaview's directory", algo_name); free(algo_name); return NULL; } sprintf(tmp, "msa_args_%d", view->alignment_algorithm + 1); strcpy(local, get_res_value(tmp, NULL)); /* add user-entered options to command */ int clustalopt = ALIGN_OPTIONS + 1; optargs = get_algo_opts(view->alignment_algorithm, NULL); status = view->menu_align[clustalopt + MAX_MSA_ALGOS ].flags; if(optargs != NULL && (status & FL_MENU_VALUE) ) { if (strchr(local, '>') != NULL) { sprintf(tmp, "%s %s", optargs, local); } else { sprintf(tmp, "%s %s", local, optargs); } strcpy(local, tmp); } if(view->alignment_algorithm == 1 && (p = strstr(local, " -stable")) != NULL) { //make sure -stable is not in muscle arguments because it's buggy memmove(p, p+8, strlen(p+8)+1); } /* replace all %f by file names */ while((p = strstr(local, "%f")) != NULL) { char *q, *r, s; *p = 0; q = p; do q--; while (q > local && *q != ' '); q++; r = p; do r++; while (*r != ' ' && *r != 0); s = *q; *q = 0; strcpy(tmp, local); *q = s; s = *r; *r = 0; sprintf(tmp + strlen(tmp), "\"%s%s%s\"", q, base_fname, p+2); *r = s; if (*r) strcat(tmp, r); strcpy(local, tmp); } /* build complete command string */ #if defined(WIN32) command = (char *)malloc(strlen(w32path) + strlen(local) + 30); sprintf(command, "\"%s\" %s ", w32path, local); #else command = (char *)malloc(strlen(get_full_path(algo_name)) + strlen(local) + 10); sprintf(command, "\"%s\" %s ", get_full_path(algo_name), local); #endif free(algo_name); return command; } //extern void fix_paste_timeout(void *u); void align_menu_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW *) ob->user_data(); int reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_align; //Fl::remove_timeout(fix_paste_timeout); if(reponse <= ALIGN_SITES) { align_selected_parts(view, (align_choice)reponse ); if(is_view_valid(view)) { view->DNA_obj->redraw(); view->horsli->redraw(); fl_reset_cursor(view->dnawin); } } else if(reponse == PROFILE) { if(view->tot_sel_seqs == 0) return; profile_align(view); if(is_view_valid(view)) { view->DNA_obj->redraw(); view->horsli->redraw(); fl_reset_cursor(view->dnawin); } } else if(reponse == UNALIGN) { if(view->tot_sel_seqs == 0) return; unalign(view); view->DNA_obj->redraw(); view->horsli->redraw(); } //Fl::add_timeout(0.5, fix_paste_timeout); } void cre_align_menu(SEA_VIEW *view) { char msa_name[60], *name; int elt, attr; const int clustalopt = ALIGN_OPTIONS + 1;//keep to rank in menu of first alignment option static const Fl_Menu_Item alignitems_static[] = { {"Align all", 0, align_menu_callback, 0, 0}, {"Align selected sequences", 0, align_menu_callback, 0, 0}, {"Align selected sites", 0, align_menu_callback, 0, 0}, {"Profile alignment", 0, align_menu_callback, 0, FL_MENU_DIVIDER}, {"De-align selection", 0, align_menu_callback, 0, FL_MENU_DIVIDER}, {"Alignment options", 0, align_menu_callback, 0, FL_SUBMENU}, {"", 0, NULL, 0, FL_MENU_TOGGLE | FL_MENU_INACTIVE}, {"Edit options", 0, edit_align_callback, 0, FL_MENU_DIVIDER}, {"Add external method", 0, add_align_w_callback, 0, 0}, {"Delete method", 0, delete_align_callback, 0, 0}, {0}, {0} }; view->alignment_algorithm = int_res_value("alignment", 0); view->count_msa_algos = int_res_value("msa_algo_count", 0); Fl_Menu_Item* alignitems = new Fl_Menu_Item[sizeof(alignitems_static)/sizeof(Fl_Menu_Item) + MAX_MSA_ALGOS]; memcpy(alignitems, alignitems_static, 6 * sizeof(Fl_Menu_Item)); memset(alignitems + 6, 0, MAX_MSA_ALGOS * sizeof(Fl_Menu_Item)); memcpy(alignitems + 6 + MAX_MSA_ALGOS, alignitems_static + 6, 6 * sizeof(Fl_Menu_Item)); for(elt = 1; elt <= MAX_MSA_ALGOS; elt++) { attr = FL_MENU_RADIO; alignitems[clustalopt + elt - 1].callback(align_opt_callback, elt - 1); if (elt <= view->count_msa_algos) { sprintf(msa_name, "msa_name_%d", elt); name = get_res_value(msa_name, NULL); alignitems[clustalopt + elt - 1].label(strdup(name)); if (elt == view->count_msa_algos) attr |= FL_MENU_DIVIDER; #ifndef WIN32 if (get_full_path(name) == NULL) { attr |= FL_MENU_INACTIVE; } #endif alignitems[clustalopt + elt - 1].flags = attr; } else { alignitems[clustalopt + elt - 1].label(""); alignitems[clustalopt + elt - 1].flags = FL_MENU_INVISIBLE; } } (alignitems + clustalopt + view->alignment_algorithm)->set(); name = get_algo_opts(view->alignment_algorithm, NULL); char *options = new char[100 + (name ? strlen(name) : 0) ]; sprintf(options, "%s", name == NULL ? "" : name); attr = FL_MENU_TOGGLE; if(name == NULL) attr |= FL_MENU_INACTIVE; alignitems[clustalopt + MAX_MSA_ALGOS].label(strdup(options)); alignitems[clustalopt + MAX_MSA_ALGOS].flags = attr; if (view->alignment_algorithm < 2) alignitems[clustalopt + MAX_MSA_ALGOS + 3].flags = FL_MENU_INACTIVE; delete options; view->menu_align = alignitems; view->menubar->add("Align", 0, NULL, (void*)view->menu_align, FL_SUBMENU_POINTER); if (view->count_msa_algos >= MAX_MSA_ALGOS) (alignitems + clustalopt + MAX_MSA_ALGOS + 2)->deactivate(); } void add_align_callback(Fl_Widget *ob, void *data) { if(strcmp(ob->label(), "OK") != 0) { ob->window()->hide(); return; } char tmp[200]; int doit = TRUE, x; int clustalopt = ALIGN_OPTIONS + 1; SEA_VIEW *view = (SEA_VIEW *)ob->window()->user_data(); Fl_Menu_Item *menu_align = (Fl_Menu_Item *)view->menu_align; Fl_Window *w = ob->window(); const char *name = ((Fl_Input *)w->child(0))->value(); const char *args = ((Fl_Input *)w->child(1))->value(); for(x = 0; x < view->count_msa_algos; x++) { if(strcmp(name, (menu_align + clustalopt + x)->label() ) == 0) doit = FALSE; } if(doit) doit = (name != NULL && args != NULL && strlen(name) >= 2 && strlen(args) >= 2); #ifdef WIN32 strcpy(tmp, name); if(strchr(tmp, '\\') == NULL && strchr(tmp, '.') == NULL) strcat(tmp, ".exe"); if(get_full_path(tmp) == NULL) #else if(get_full_path(name) == NULL) #endif { fl_alert("Program '%s' not found.\nMethod won't be added.", name); doit = FALSE; } if(doit) { menu_align[clustalopt + view->count_msa_algos].label(strdup(name)); int stat = menu_align[clustalopt + view->count_msa_algos - 1 ].flags; menu_align[clustalopt + view->count_msa_algos - 1 ].flags = stat & ~FL_MENU_DIVIDER; menu_align[clustalopt + view->count_msa_algos ].flags = FL_MENU_RADIO | FL_MENU_DIVIDER; view->alignment_algorithm = view->count_msa_algos; (menu_align + clustalopt + view->alignment_algorithm)->setonly(); set_algo_option_item(NULL, menu_align, clustalopt + MAX_MSA_ALGOS, FALSE); (menu_align + clustalopt + MAX_MSA_ALGOS + 3)->activate(); ++(view->count_msa_algos); sprintf(tmp, "%d", view->count_msa_algos); set_res_value("msa_algo_count", tmp); sprintf(tmp, "msa_name_%d", view->count_msa_algos); set_res_value(tmp, name); sprintf(tmp, "msa_args_%d", view->count_msa_algos); set_res_value(tmp, args); save_resources(); if (view->count_msa_algos == MAX_MSA_ALGOS) (menu_align + clustalopt + MAX_MSA_ALGOS + 2)->deactivate(); } w->hide(); } void delete_align_callback(Fl_Widget *ob, void *data) { int clustalopt = ALIGN_OPTIONS + 1; SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); Fl_Menu_Item *menu_align = (Fl_Menu_Item*)view->menu_align; char msa_name[20], *name; int num, status; sprintf(msa_name, "msa_name_%d", view->alignment_algorithm + 1); name = get_res_value(msa_name, NULL); if(name == NULL) return; int rep = fl_choice("Delete alignment method '%s' ?", "Keep", "Delete", NULL, name); if(rep == 0) return; free((void*) (menu_align + clustalopt + view->alignment_algorithm)->label() ); for(num = view->alignment_algorithm + 1; num <= view->count_msa_algos - 1; num++) { name = (char *)(menu_align + clustalopt + num)->label(); (menu_align + clustalopt + num - 1)->label(name); sprintf(msa_name, "msa_name_%d", num + 1); name = get_res_value(msa_name, NULL); sprintf(msa_name, "msa_name_%d", num); set_res_value(msa_name, name); sprintf(msa_name, "msa_args_%d", num + 1); name = get_res_value(msa_name, NULL); sprintf(msa_name, "msa_args_%d", num); set_res_value(msa_name, name); name = get_opt_resname(num); name = get_res_value(name, NULL); if(name != NULL) { char *tmp = strdup(name); name = get_opt_resname(num - 1); set_res_value(name, tmp); free(tmp); } else delete_res_value(get_opt_resname(num - 1)); } menu_align[clustalopt + view->count_msa_algos - 1].flags = FL_MENU_INVISIBLE; menu_align[clustalopt + view->count_msa_algos - 1].label(""); sprintf(msa_name, "msa_name_%d", view->count_msa_algos); delete_res_value(msa_name); sprintf(msa_name, "msa_args_%d", view->count_msa_algos); delete_res_value(msa_name); name = get_opt_resname(view->count_msa_algos - 1); delete_res_value(name); --(view->count_msa_algos); sprintf(msa_name, "%d", view->count_msa_algos); set_res_value("msa_algo_count", msa_name); status = menu_align[ clustalopt + view->count_msa_algos - 1 ].flags; menu_align[ clustalopt + view->count_msa_algos - 1 ].flags = status | FL_MENU_DIVIDER ; num = int_res_value("alignment", 0); view->alignment_algorithm = (num < view->count_msa_algos ? num : 0); sprintf(msa_name, "%d", view->alignment_algorithm); set_res_value("alignment", msa_name); (menu_align + clustalopt + view->alignment_algorithm)->setonly(); name = get_algo_opts(view->alignment_algorithm, NULL); set_algo_option_item(name, menu_align, clustalopt + MAX_MSA_ALGOS, FALSE); Fl_Menu_Item* item = (Fl_Menu_Item*)view->menubar->mvalue(); if (view->alignment_algorithm >= 2) item->activate(); else item->deactivate(); save_resources(); } void choose_align_callback(Fl_Widget *ob, void *data) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file chooser->title("Select external alignment program"); #if defined(WIN32) chooser->filter("*.exe"); #endif char *filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; ((Fl_Input*)data)->value(filename); ((Fl_Input*)data)->position(strlen(filename)); } void add_align_w_callback(Fl_Widget *ob, void *data) { static Fl_Window *w = NULL; static Fl_Input *name, *args; Fl_Button *chooser; SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); if(view->count_msa_algos >= MAX_MSA_ALGOS) return; if(w == NULL) { w = new Fl_Window(530, 100, "alignment method creation"); name = new Fl_Input(85, 10, 250, 20, "Name"); name->tooltip("Enter name of program from PATH" #ifdef WIN32 " or seaview's directory" #endif " or select program using button at right"); args = new Fl_Input(85, 40, 430, 20, "Arguments"); args->tooltip( "probcons example: %f.pir > %f.out\n" "t_coffee example: %f.pir -outfile=%f.out -output=fasta_aln\n" "mafft example: --auto %f.pir > %f.out" ); chooser = new Fl_Button(345, 10, 160, 20, "Select external program"); chooser->callback(choose_align_callback, (void *)name); Fl_Return_Button *b = new Fl_Return_Button(480, 70, 40, 20, "OK"); b->callback(add_align_callback, data); Fl_Button *b2 = new Fl_Button(10, 70, 50, 20, "Cancel"); b2->callback(add_align_callback, NULL); } name->value(NULL); args->value(NULL); name->take_focus(); w->user_data(view); w->show(); #ifndef MICRO w->hotspot(w); #endif } void edit_align_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); Fl_Menu_Item *menu_align = (Fl_Menu_Item *)view->menu_align; char *opts, *optresname; char resname[20], *name; int clustalopt = ALIGN_OPTIONS + 1; sprintf(resname, "msa_name_%d", view->alignment_algorithm + 1); name = get_res_value(resname, NULL); opts = get_algo_opts(view->alignment_algorithm, &optresname); opts = (char *)fl_input("Optional arguments for method '%s'\n" "(Clustal ex: --threads=4 | Muscle ex: -maxiters 2 -diags)", opts, name); if(opts == NULL) return; if(strlen(opts) == 0) opts = NULL; set_algo_option_item(opts, menu_align, clustalopt + MAX_MSA_ALGOS, TRUE); if(opts != NULL) set_res_value(optresname, opts); else delete_res_value(optresname); save_resources(); } void align_opt_callback(Fl_Widget *ob, long unused) { SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); char *opts; int clustalopt = ALIGN_OPTIONS + 1; int reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_align - clustalopt; if(reponse >= 0 && reponse < view->count_msa_algos) { view->alignment_algorithm = reponse; opts = get_algo_opts(view->alignment_algorithm, NULL); set_algo_option_item(opts, (Fl_Menu_Item*)view->menu_align, clustalopt + MAX_MSA_ALGOS, FALSE); if(view->alignment_algorithm >= 2) ((Fl_Menu_Item *)view->menu_align + clustalopt + MAX_MSA_ALGOS + 3)->activate(); else ((Fl_Menu_Item *)view->menu_align + clustalopt + MAX_MSA_ALGOS + 3)->deactivate(); } } char *get_algo_opts(int algonum /* from 0 */, char **presname) { char *resname = get_opt_resname(algonum); if(presname != NULL) *presname = resname; return get_res_value(resname, NULL); } char *get_opt_resname(int algonum) { static char resname[20]; sprintf(resname, "msa_opt_args_%d", algonum + 1); return resname; } void set_algo_option_item(char *opts, Fl_Menu_Item *menu, int itemrank, int checkit) { int status; if(opts != NULL && strlen(opts) == 0) opts = NULL; menu[itemrank].label(opts == NULL ? "" : strdup(opts)); status = FL_MENU_TOGGLE; if(opts == NULL) status |= FL_MENU_INACTIVE; else if(checkit) status |= FL_MENU_VALUE; menu[itemrank].flags = status; } void init_msa_algos(void) { int count = int_res_value("msa_algo_count", 0); set_res_value("msa_name_1", "clustalo"); set_res_value("msa_args_1", "-v -i %f.pir -o %f.out --outfmt=fasta"); set_res_value("msa_name_2", "muscle"); set_res_value("msa_args_2", "-in %f.pir -out %f.out"); if (count < 2) { set_res_value("msa_algo_count", "2"); set_res_value("alignment", "0"); /* clustal-omega is default starting msa method */ } } enum {profile_clustalo, profile_muscle}; static int num_sp_set, profile_to_profile = FALSE, profile_algo = profile_clustalo, do_propagate; int profile_dialog(SEA_VIEW *view) // returns TRUE iff cancel { int retval, i, y; Fl_Window *w = new Fl_Window(270, 185); w->label("Profile alignment dialog"); y = 5; Fl_Choice *choice = new Fl_Choice(155, y, 100, 20, "Profile sequences:"); for(i = 0; i < view->numb_species_sets; i++) { retval = choice->add("TeMpOrArY"); choice->replace(retval, view->name_species_sets[i]); } choice->value(0); y += 25; Fl_Choice *choice_algo = new Fl_Choice(155, y, 100, 20, "Alignment algorithm:"); choice_algo->add("clustalo"); choice_algo->add("muscle"); choice_algo->value(profile_algo); y = 75; Fl_Group *group = new Fl_Group(20, y, w->w() - 40, 55, "Align selected sequences to profile as:"); group->box(FL_ROUNDED_BOX); group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; Fl_Round_Button *sequence = new Fl_Round_Button(25, y, 200, 20, "each sequence to profile"); sequence->type(FL_RADIO_BUTTON); y += 25; Fl_Round_Button *profile = new Fl_Round_Button(25, y, 200, 20, "profile to profile"); profile->type(FL_RADIO_BUTTON); group->end(); if(profile_algo == profile_muscle) { profile->setonly(); profile_to_profile = TRUE; sequence->deactivate(); } else if(profile_to_profile) profile->setonly(); else sequence->setonly(); y = group->y() + group->h() + 5; Fl_Check_Button *propagate = new Fl_Check_Button(5, y, 170, 20, "Propagate gaps to sites"); propagate->type(FL_TOGGLE_BUTTON); if(view->regions == NULL && view->tot_comment_lines == 0) propagate->deactivate(); else propagate->value(1); y += 25; Fl_Button *cancel_button = new Fl_Button(5, y, 60, 20, "Cancel"); cancel_button->shortcut(FL_COMMAND | 'w'); Fl_Button *help_button = new Fl_Button(97, y, 60, 20, "Help"); Fl_Button *ok_button = new Fl_Return_Button(190, y, 60, 20, "OK"); w->end(); w->set_non_modal(); w->show(); while (TRUE) { Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); else if(o == cancel_button || o == w ) { retval = 1; break; } else if(o == ok_button ){ retval = 0; break; } else if(o == help_button ) { direct_help_callback(o, (void *)"Align Menu"); } else if(o == choice_algo) { profile_algo = choice_algo->value(); if(profile_algo == profile_muscle) { profile->setonly(); sequence->deactivate(); } else { sequence->activate(); sequence->setonly(); } } } num_sp_set = choice->value(); do_propagate = propagate->value(); profile_to_profile = profile->value(); delete w; return retval; } void profile_align(SEA_VIEW *view) { char *p, base_fname[200], fname1[200], fname2[200], *command, tmp[200]; char **seq, **comments, **seqname, *pheader, *err_message, res; int withU, num_longest, status, num, total, *table, i, rang, newlength, l_copy; int (*calc_color_function)(int); if(view->numb_species_sets == 0) { fl_alert("Profile alignment requires previous definition of a species group"); return; } if( profile_dialog(view) ) return; p = create_tmp_filename(); if(p == NULL) return; strcpy(base_fname, p); sprintf(fname1, "%s_1.fasta", base_fname); total = 0; for(num = 0; num < view->tot_seqs; num++) { if(view->sel_seqs[num]) total++; if(view->list_species_sets[num_sp_set][num] == 0) continue; total++; if(view->sel_seqs[num]) { fl_alert("Selected sequences should not belong to profile sequences"); delete_tmp_filename(base_fname); return; } } if ( check_alignment_characters(view, view->list_species_sets[num_sp_set]) ) return; status = save_fasta_file_no_gaponly(fname1, view->sequence, view->tot_seqs, view->each_length, view->list_species_sets[num_sp_set]); if(status) { fl_alert("Cannot write sequences to filename\n%s", fname1); delete_tmp_filename(base_fname); return; } replace_stars(fname1); sprintf(fname2, "%s_2.fasta", base_fname); if ( check_alignment_characters(view, view->sel_seqs) ) return; if(profile_to_profile) { status = save_fasta_file_no_gaponly(fname2, view->sequence, view->tot_seqs, view->each_length, view->sel_seqs); } else status = save_part_as_pir(1, view->seq_length, view->sequence, view->seqname, view->sel_seqs, view->tot_seqs, fname2, &withU, &num_longest, view->protein); replace_stars(fname2); if(status) { fl_alert("Cannot write sequences to filename\n%s", fname2); delete_tmp_filename(base_fname); return; } p = get_res_value( profile_algo == profile_clustalo ? "msa_name_1" : "msa_name_2", NULL); strcpy(tmp, p); #ifdef WIN32 strcat(tmp, ".exe"); #endif p = get_full_path(tmp); if(p == NULL) { fl_alert("Alignment program %s not found.", tmp); status = 1; } else { command = new char[1000]; if(profile_algo == profile_clustalo) { sprintf(command, "\"%s\" -v \"--profile1=%s\" %s%s\" --outfmt=fasta -o \"%s.aligned\" -t %s", p, fname1, profile_to_profile ? "\"--profile2=" : "-i \"", fname2, base_fname, view->protein ? "protein" : "dna" ); } else { // muscle sprintf(command, "\"%s\" -profile -in1 \"%s\" -in2 \"%s\" -out \"%s.aligned\" ", p, fname1, fname2, base_fname ); } status = run_external_prog_in_pseudoterm(command, NULL, "profile alignment"); delete[] command; } sprintf(fname1, "%s.aligned", base_fname); /* lecture de l'alignement multiple */ if( status == 0 ) { num = read_fasta_align(fname1, &seq, &seqname, &comments, &pheader, &err_message, FALSE); if (num == total && !profile_to_profile) { // clustalo for "each seq to profile" outputs selected seqs first and profile second. We reverse this. for (i = 0; i < total; i++) { if (strncmp(seqname[i], "S_", 2) == 0) break; } if (i > 0) { char **seq2 = (char**)malloc(total * sizeof(char*)); memcpy(seq2, seq+i, (total - i)*sizeof(char*)); memcpy(seq2+(total-i), seq, i*sizeof(char*)); memcpy(seq, seq2, total*sizeof(char*)); free(seq2); } } if(num > 0) { for(i = 0; i < num; i++) free(seqname[i]); free(seqname); free(comments); } if(num != total) { for(i = 0; i < num; i++) free(seq[i]); if(num > 0) free(seq); } } delete_tmp_filename(base_fname); if ( !is_view_valid(view) ) return; if( status != 0 || num != total) { fl_message("%s: alignment operation ignored", extract_filename(view->masename)); return; } // compute table[rank in file xx.aligned] = rank in seaview alignment table = (int *)calloc(total, sizeof(int)); rang = -1; for(num = 0; num < view->tot_seqs; num++) { // seqs from the reference profile if( ! view->list_species_sets[num_sp_set][num] ) continue; rang++; table[rang] = num; back_to_stars(seq[rang], view->sequence[num]); } for(num = 0; num < view->tot_seqs; num++) { // currently selected seqs if( ! view->sel_seqs[num] ) continue; rang++; table[rang] = num; back_to_stars(seq[rang], view->sequence[num]); } if(do_propagate && (view->regions != NULL || view->tot_comment_lines > 0) ) { //propagate gaps created in profile seqs to regions and comment lines int l = 0, num_align = table[0]; char *p, *q; p = view->sequence[num_align]; // one profile seq q = seq[0]; // this seq after profile alignment while(*p != 0) { while(*p != 0 && toupper(*p) == toupper(*q)) { p++; q++; } if(*p == 0 && *q == 0) break; if(*p == '-') { int from = q - seq[0]; l = 1; p++; while(toupper(*p) != toupper(*q)) { p++; l++; } for(num = 0; num < total; num++) { seq[num] = (char*)realloc(seq[num], strlen(seq[num]) + l + 1); memmove(seq[num] + from + l, seq[num] + from, strlen(seq[num] + from) + 1); memset(seq[num] + from, '-', l); } q = seq[0] + from + l; l = 0; } else if(*q == '-') { l = 1; q++; while(toupper(*p) != toupper(*q)) { q++; l++; } } if(l > 0) { //insert gap of length l in regions insert_region_part(view, p - view->sequence[num_align], l); if(view->tot_comment_lines > 0) insert_gap_all_comments(l, p - view->sequence[num_align], view); l = 0; } } } //replace seaview seqs by those from the file if(view->numb_gc > 1) { calc_color_function = ( view->protein ? get_color_for_aa : get_color_for_base ); } newlength = view->seq_length; for(num = 0; num < total; num++) { l_copy = strlen(seq[num]); if(l_copy > view->max_seq_length) { l_copy = view->max_seq_length; seq[num][l_copy] = 0; } strcpy(view->sequence[table[num]], seq[num]); free(seq[num]); view->each_length[table[num]] = l_copy; newlength = FL_max(newlength, l_copy); if(view->numb_gc > 1) { for(i = 0; i < view->each_length[table[num]]; i++) { res = view->sequence[table[num]][i]; view->col_rank[table[num]][i] = (char)calc_color_function( res ); } } } free(seq); free(table); /* mettre a jour horsli */ update_current_seq_length(newlength, view); set_seaview_modified(view, TRUE); } void replace_stars(char *fname) // replace all * and ? in file by X { FILE *in = fopen(fname, "rb+"); if(in == NULL) return; fseek(in, 0, SEEK_END); long l = ftell(in); char *all = (char *)malloc(l + 1); fseek(in, 0, SEEK_SET); fread(all, 1, l, in); all[l] = 0; char *p = all; while((p = strchr(p, '*')) != NULL) *p = 'X'; p = all; while((p = strchr(p, '?')) != NULL) *p = 'X'; fseek(in, 0, SEEK_SET); fwrite(all, 1, l, in); fclose(in); } void back_to_stars(char *aligned, char *ori) // replaces X in aligned by * when * at same place in ori // replaces X in aligned by ? when ? at same place in ori { while (TRUE) { while(*aligned == '-') aligned++; while(*ori == '-') ori++; if(*ori == 0 || *aligned == 0) break; if(*aligned == 'X' && *ori == '*') *aligned = '*'; if(*aligned == 'X' && *ori == '?') *aligned = '?'; aligned++; ori++; } } int save_fasta_file_no_gaponly(char *fname, char **sequence, int tot_seqs, int *each_length, int *sel_seqs) { list_segments *segment, *next; region maregion; int num, l = 0, pos, insegment, status; char **seqname; segment = NULL; insegment = FALSE; seqname = (char **)malloc(tot_seqs * sizeof(char *)); if(seqname == NULL) return 1; for(num = 0; num < tot_seqs; num++) { if(sel_seqs[num]) l = FL_max(l, each_length[num]); seqname[num] = (char *)malloc(10); if(seqname[num] == NULL) return 1; sprintf(seqname[num], "S_%d", num); } for(pos = 0; pos < l; pos++) { for(num = 0; num < tot_seqs; num++) { if(!sel_seqs[num]) continue; if(pos < each_length[num] && sequence[num][pos] != '-') break; } if(num < tot_seqs && ! insegment) { next = (list_segments *)malloc(sizeof(list_segments)); if(segment != NULL) segment->next = next; else maregion.list = next; segment = next; segment->debut = pos + 1; insegment = TRUE; } else if(num >= tot_seqs && insegment) { segment->fin = pos; insegment = FALSE; } } if(insegment) segment->fin = l; segment->next = NULL; status = save_fasta_file(fname, sequence, NULL, seqname, tot_seqs, each_length, &maregion, sel_seqs, 1,0); segment = maregion.list; do { next = segment->next; free(segment); segment = next; } while(segment != NULL); for(num = 0; num < tot_seqs; num++) { free(seqname[num]); } free(seqname); return status; } void unalign(SEA_VIEW *view) { int num, i, newlength; char *tmpseq, *p, *q, res; int (*calc_color_function)(int); if( fl_choice("This will remove all gaps from selected sequences.", "Cancel", "Remove gaps", NULL) == 0) return; if(view->numb_gc > 1) calc_color_function = ( view->protein ? get_color_for_aa : get_color_for_base ); for(num = 0; num < view->tot_seqs; num++) { if(!view->sel_seqs[num]) continue; tmpseq = (char *)malloc(view->max_seq_length + 1); p = tmpseq; q = view->sequence[num]; while(*q != 0) { if(*q != '-') *(p++) = *q; q++; } *p = 0; free(view->sequence[num]); view->sequence[num] = tmpseq; view->each_length[num] = strlen(tmpseq); if(view->numb_gc > 1) { if( view->curr_colors == view->codoncolors) { char **tmp = prepcolranks_by_codon(&view->sequence[num], 1, view->max_seq_length, &view->each_length[num], &view->comments[num]); free(view->col_rank[num]); view->col_rank[num] = tmp[0]; free(tmp); } else { for(i = 0; i < view->each_length[num]; i++) { res = view->sequence[num][i]; view->col_rank[num][i] = (char)calc_color_function( res ); } } } } newlength = 0; for(num = 0; num < view->tot_seqs; num++) newlength = FL_max(newlength, view->each_length[num]); view->seq_length = newlength; compute_size_params(view, TRUE); view->horsli->redraw(); set_seaview_modified(view, TRUE); } int reorder_seqs(int tot, char **seq, char **name) //reorders sequences in seq in their original order using their names //that start with 1_, 2_, 3_, etc... //returns TRUE iff memory error { int num, rank; char **newseq = (char **)malloc(tot * sizeof(char *)); if(newseq == NULL) return TRUE; for( num = 0; num < tot; num++) { sscanf(name[num], "%d", &rank); newseq[rank - 1] = seq[num]; } memcpy(seq, newseq, tot * sizeof(char *)); free(newseq); return FALSE; } int check_alignment_characters(SEA_VIEW *view, int *sel_seqs) //returns TRUE iff unexpected characters are present and alignment shd be cancelled //otherwise, replaces unexpected characters by X or N and returns FALSE { int i, choice; char *p, X; const char dna_accepted[] = "ABCDGHKMNRSTUVWXY-*?!"; const char prot_accepted[] = "ABCDEFGHIKLMNPQRSTVWXYZ-*?!"; const char *accepted; char unexpected[50] = "", single[2] = ""; X = view->protein ? 'X' : 'N'; accepted = view->protein ? prot_accepted : dna_accepted; for(i = 0; i < view->tot_seqs; i++) { if(!sel_seqs[i]) continue; p = view->sequence[i] - 1; while(*++p) { if(strchr(accepted, toupper(*p)) == NULL) { if(strlen(unexpected) + 1 < sizeof(unexpected) && strchr(unexpected, *p) == NULL) { *single = *p; strcat(unexpected, single); } } } } if(*unexpected == 0) return FALSE; choice = fl_choice("Unexpected characters are present in sequence data '%s'.\n" "You can replace them by '%c' and continue aligning, or cancel alignment:", "Replace && align", "Cancel", NULL, unexpected, view->protein ? 'X' : 'N'); if(choice) return TRUE; for(i = 0; i < view->tot_seqs; i++) { if(!sel_seqs[i]) continue; p = view->sequence[i] - 1; while(*++p) { if(strchr(accepted, toupper(*p)) == NULL) *p = X; } } set_seaview_modified(view, TRUE); return FALSE; } int command_line_align(int argc, char **argv) { char *p; int i; bool std_output = false; bool need_back_translate = false; char *old_opt_args = NULL; char opt_name[20]; SEA_VIEW *DNAview; SEA_VIEW *view = cmdline_read_input_alignment(argc, argv); known_format out_format = view->format_for_save; load_resources(progname); init_msa_algos(); view->alignment_algorithm = (int)argval(argc, argv, "-align_algo", int_res_value("alignment", 0)); view->menu_align = new Fl_Menu_Item[ALIGN_OPTIONS + MAX_MSA_ALGOS + 2]; Fl_Menu_Item *item = (Fl_Menu_Item *)&view->menu_align[ALIGN_OPTIONS + MAX_MSA_ALGOS + 1]; item->clear() ; if ( (p = argname(argc, argv, "-align_extra_args")) != NULL) { item->set(); sprintf(opt_name, "msa_opt_args_%d", view->alignment_algorithm + 1); old_opt_args = strdup(get_res_value(opt_name, "")); set_res_value(opt_name, p); } if ( !view->protein && isarg(argc, argv, "-align_at_protein_level")) { need_back_translate = true; DNAview = view; view = new SEA_VIEW; memcpy(view, DNAview, sizeof(SEA_VIEW)); view->seq_length = 0; view->sequence = (char **)malloc(view->tot_seqs * sizeof(char*)); for (i = 0; i < view->tot_seqs; i++) { int gc = (view->comments != NULL ? get_ncbi_gc_from_comment(DNAview->comments[i]) : 1); p = translate_with_gaps(DNAview->sequence[i], get_acnuc_gc_number(gc)); view->sequence[i] = p; view->each_length[i] = strlen(p); if (view->each_length[i] > view->seq_length) view->seq_length = view->each_length[i]; view->regions = NULL; } view->protein = true; view->max_seq_length = calc_max_seq_length(view->seq_length, view->tot_seqs); allonge_seqs(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, &view->region_line); } align_selected_parts(view, ALIGN_ALL, true); if (old_opt_args) set_res_value(opt_name, old_opt_args); if (need_back_translate) { DNAview->seq_length = 0; for (i = 0; i < DNAview->tot_seqs; i++) { p = back_translate_with_gaps(view->sequence[i], DNAview->sequence[i]); free(DNAview->sequence[i]); DNAview->sequence[i] = p; int l = strlen(p); DNAview->each_length[i] = l; if (l > DNAview->seq_length) DNAview->seq_length = l; } view = DNAview; } char *outfile = process_output_options(argc, argv, out_format, std_output); char *err_message = save_alignment_or_region(outfile, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, view->regions, NULL, out_format, view->numb_species_sets, view->list_species_sets, view->name_species_sets, NULL, 0, view->protein, view->tot_comment_lines, view->comment_name, view->comment_line, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); if (err_message) { fprintf(stderr, "%s\n", err_message); if (std_output) delete_tmp_filename(outfile); exit(1); } if (std_output) { char line[200]; FILE *in = fopen(outfile, "r"); while (fgets(line, sizeof(line), in) != NULL) { fputs(line, stdout); } fclose(in); fflush(stdout); delete_tmp_filename(outfile); } return 0; } seaview/comlines.cxx000644 000765 000024 00000024031 12404325714 015363 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include void draw_comment_lines(Fl_Widget *ob, SEA_VIEW *view); int parse_comment_lines_from_header(char *header, char ***plines, char ***pnames, int **plengths, int *pmax_seq_length); int insert_char_in_comment(int key, int num, SEA_VIEW *view); int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view); int delete_char_in_comment(SEA_VIEW *view, int count, int comnum, int depart, int protect); int delete_in_all_comments(int numdels, int pos, SEA_VIEW *view); void update_menu_footers(SEA_VIEW *view); void footers_menu_callback(Fl_Widget *ob, void* data); /* used prototypes */ void set_and_show_new_cursor_site(SEA_VIEW *view, int new_pos, int center, int force_redraw); int compute_size_params(SEA_VIEW *view, int force_recompute); void draw_comment_lines(Fl_Widget *ob, SEA_VIEW *view) { int offset, x, y, l_line, nline; int couleur, background; if( !view->show_comment_lines ) return; x = view->x_seq; y = view->y_seq + (view->pos_first_comment_line - 1) * view->line_height; /* write lines */ x = view->x_seq; offset= view->first_site - 1; for(nline = 0; nline < view->tot_comment_lines ; nline++, y += view->line_height ) { if(view->mod_comment_line == 0 || view->mod_comment_line == nline+1 ) { if(view->active_comment_line == nline + 1) { couleur = FL_WHITE; background = FL_BLACK; } else { couleur = FL_BLACK; background = ob->selection_color(); } fl_font(FL_COURIER_ITALIC, ob->labelsize() ); fl_color(background); fl_rectf( view->x_name, y - view->line_height + fl_descent(), (view->wid_names+1) * view->char_width, view->line_height); fl_color(couleur); fl_draw(view->comment_name[nline], FL_min((unsigned)view->wid_names, strlen(view->comment_name[nline]) ), view->x_name, y); l_line = ( offset + view->tot_sites < view->comment_length[nline] ? view->tot_sites : view->comment_length[nline] - offset); if(l_line <= 0) continue; fl_font(ob->labelfont(), ob->labelsize() ); fl_color(ob->color()); fl_rectf(x, y - view->line_height + fl_descent(), (view->tot_sites + 1) * view->char_width, view->line_height); fl_color(FL_BLACK); fl_draw(view->comment_line[nline] + offset, l_line, x, y); } } } int parse_comment_lines_from_header(char *header, char ***plines, char ***pnames, int **plengths, int *pmax_seq_length) { char *new_header, *fin_new_header, *old_header, *j, *p, *q; int l_header, num, total, max_seq_length; char **lines, **names; int *lengths; if(header == NULL) return 0; old_header = header; l_header = strlen(header); total = 0; while (*header!= 0) { if(strncmp(header,";;|",3) == 0) { total++; do header = strchr(header,'\n') + 1; while(strncmp(header, ";;||", 4) != 0); } header = strchr(header,'\n') + 1; } if(total == 0) return 0; names = (char **)malloc(total * sizeof(char *)); lines = (char **)malloc(total * sizeof(char *)); lengths = (int *)malloc(total * sizeof(int)); if( names == NULL || lines == NULL || lengths == NULL) out_of_memory(); header = old_header; if( (new_header = (char *)malloc(l_header+1)) == NULL) out_of_memory(); fin_new_header = new_header; *new_header = 0; num = -1; max_seq_length = *pmax_seq_length; while (*header!= 0) { if(strncmp(header,";;|",3) == 0) { num++; p = header + 3; while(*p == ' ') p++; q = strchr(p, '\n'); names[num] = (char *)malloc(q - p + 1); if( names[num] == NULL ) out_of_memory(); memcpy( names[num], p, q - p ); names[num][q - p] = 0; header = q + 1; p = header; do p = strchr(p,'\n') + 1; while(strncmp(p, ";;||", 4) != 0); if(p - header > max_seq_length) max_seq_length = p - header; lines[num] = (char *)malloc(p - header + 1); if( lines[num] == NULL ) out_of_memory(); q = lines[num]; do { p = strchr(header,'\n') + 1; memcpy(q, header + 2, p - header - 3); q += p - header - 3; header = p; } while(strncmp(p, ";;||", 4) != 0); *q = 0; lengths[num] = strlen(lines[num]); } else { j=(char *)memccpy(fin_new_header, header, '\n', l_header); fin_new_header += (j - fin_new_header); } header = strchr(header,'\n') + 1; } *fin_new_header = 0; strcpy(old_header, new_header); free(new_header); *pnames = names; *plines = lines; *plengths = lengths; *pmax_seq_length = max_seq_length; return num + 1; } int insert_char_in_comment(int key, int num, SEA_VIEW *view) { char *pos; int l; if(num + view->comment_length[view->active_comment_line - 1] > view->max_seq_length) num = view->max_seq_length - view->comment_length[view->active_comment_line - 1]; pos = view->comment_line[view->active_comment_line - 1] + view->cursor_site - 1; l = view->comment_length[view->active_comment_line - 1] - view->cursor_site + 1; memmove(pos + num, pos, l + 1); memset(pos, key, num); view->mod_comment_line = view->cursor_seq; view->comment_length[view->active_comment_line - 1] += num; set_and_show_new_cursor_site(view, view->cursor_site + num, FALSE, TRUE); set_seaview_modified(view, TRUE); return num; } int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view) { int num, l, total = 0; char *debut; for(num = 0; num < view->tot_comment_lines; num++) { if(pos > view->comment_length[num] + 1) continue; /* beyond end */ total = numgaps; if(total + view->comment_length[num] > view->max_seq_length) { total = view->max_seq_length - view->comment_length[num]; fl_beep(FL_BEEP_DEFAULT); } debut = view->comment_line[num] + pos - 1; l = view->comment_length[num] - pos + 1; memmove(debut + total, debut, l + 1); memset(debut, '-', total); view->comment_length[num] += total; } return total; } int delete_char_in_comment(SEA_VIEW *view, int count, int comnum, int depart, int protect) { char *pos; int l, total; if(count >= depart) count = depart - 1; pos = view->comment_line[comnum - 1] + depart - 1; l = view->comment_length[comnum - 1] - depart + 1; if(protect) { for(total = 1; total <= count ; total++) if( *(pos - total) != '-' ) break; count = total - 1; if(count == 0) return 0; } memmove(pos - count, pos, l + 1); view->mod_comment_line = comnum; view->comment_length[comnum - 1] -= count; set_and_show_new_cursor_site(view, depart - count, FALSE, TRUE); set_seaview_modified(view, TRUE); return count; } int delete_in_all_comments(int numdels, int pos, SEA_VIEW *view) { int num, l; char *debut; numdels = FL_min(numdels, pos); for(num = 0; num < view->tot_comment_lines; num++) { if(pos > view->comment_length[num] + 1) continue; /* beyond end */ debut = view->comment_line[num] + pos - 1; l = view->comment_length[num] - pos + 1; memmove(debut - numdels, debut, l + 1); view->comment_length[num] -= numdels; } return numdels; } void update_menu_footers(SEA_VIEW *view) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_footers; if(view->tot_comment_lines > 0) items[SHOW_HIDE_FOOTERS].activate(); else items[SHOW_HIDE_FOOTERS].deactivate(); items[SHOW_HIDE_FOOTERS].label( view->show_comment_lines ? "Hide footers" : "Show footers" ); if(view->show_comment_lines && view->active_comment_line > 0) items[DELETE_FOOTER].activate(); else items[DELETE_FOOTER].deactivate(); if(view->tot_seqs > 0 ) items[CREATE_FOOTER].activate(); else items[CREATE_FOOTER].deactivate(); } void footers_menu_callback(Fl_Widget *ob, void* data) { SEA_VIEW *view = (SEA_VIEW *) ob->user_data(); int num, reponse = view->menubar->mvalue() - view->menu_footers; if(reponse == SHOW_HIDE_FOOTERS && view->tot_comment_lines > 0) { view->show_comment_lines = !view->show_comment_lines; view->active_comment_line = 0; view->cursor_in_comment = FALSE; compute_size_params(view, TRUE); view->DNA_obj->redraw(); } else if(reponse == CREATE_FOOTER) { char **pline, **pname, *texte, *name; const char *c_name; int *plength; c_name = fl_input("Name of new footer line?", "Comments" ); if(c_name == NULL || strlen(c_name) == 0) return; num = view->tot_comment_lines; pline = (char **)malloc((view->tot_comment_lines + 1) *sizeof(char *)); if(pline == NULL) return; pname = (char **)malloc((view->tot_comment_lines + 1) *sizeof(char *)); if(pname == NULL) return; plength = (int *)malloc((view->tot_comment_lines + 1) *sizeof(int )); if(plength == NULL) return; texte = (char *)malloc((view->max_seq_length + 1) *sizeof(char)); if(texte == NULL) return; name = (char *)malloc(strlen(c_name) + 1); if(name == NULL) return; memset(texte, '-', view->seq_length); texte[view->seq_length] = 0; strcpy(name, c_name); if(view->tot_comment_lines > 0) { memcpy(pline, view->comment_line, view->tot_comment_lines * sizeof(char *)); free(view->comment_line); } pline[view->tot_comment_lines] = texte; view->comment_line = pline; if(view->tot_comment_lines > 0) { memcpy(pname, view->comment_name, view->tot_comment_lines * sizeof(char *)); free(view->comment_name); } pname[view->tot_comment_lines] = name; view->comment_name = pname; if(view->tot_comment_lines > 0) { memcpy(plength, view->comment_length, view->tot_comment_lines * sizeof(int)); free(view->comment_length); } plength[view->tot_comment_lines] = view->seq_length; view->comment_length = plength; ++(view->tot_comment_lines); view->show_comment_lines = TRUE; view->active_comment_line = 0; view->cursor_in_comment = FALSE; set_seaview_modified(view, TRUE); compute_size_params(view, TRUE); view->DNA_obj->redraw(); } else if(reponse == DELETE_FOOTER) { if(view->tot_comment_lines == 0 || view->active_comment_line == 0) return; if(! fl_choice("Confirm deletion?", "Cancel", "Delete", NULL) ) return; free(view->comment_line[view->active_comment_line - 1]); free(view->comment_name[view->active_comment_line - 1]); for(num = view->active_comment_line; num < view->tot_comment_lines; num++) { view->comment_line[num - 1] = view->comment_line[num]; view->comment_name[num - 1] = view->comment_name[num]; view->comment_length[num - 1] = view->comment_length[num]; } (view->tot_comment_lines)--; if(view->tot_comment_lines == 0) view->show_comment_lines = FALSE; view->active_comment_line = 0; view->cursor_in_comment = FALSE; set_seaview_modified(view, TRUE); compute_size_params(view, TRUE); view->DNA_obj->redraw(); } update_menu_footers(view); } seaview/concatenate.cxx000644 000765 000024 00000016723 12424723305 016047 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include #include #include void concatenate_dialog(SEA_VIEW *view); static void cancel_callback(Fl_Widget *, void *); void rank_name_callback( Fl_Widget *o, void *data); void do_concatenate_callback( Fl_Widget *ob, void *data); extern char *f_format_names[]; extern char *f_format_exts[]; extern int nbr_formats; extern SEA_VIEW *cmdline_read_input_alignment(int argc, char **argv); extern known_format what_format(const char *filename); extern char *argname(int argc, char *argv[], const char *arg); extern int isarg(int argc, char *argv[], const char *arg); extern char *create_tmp_filename(void); extern void delete_tmp_filename(const char *base_fname); extern char *process_output_options(int argc, char **argv, known_format& out_format, bool& std_output); static Fl_Round_Button *by_name; static Fl_Choice *choice; static int interrupted; static Fl_Check_Button *addgaps; void concatenate_dialog(SEA_VIEW *view) { Fl_Window *w; w = new Fl_Window(305, 160); choice = new Fl_Choice(130,10,170, 20, "Source alignment"); choice->align(FL_ALIGN_LEFT); Fl_Window *w2 = Fl::first_window(); int count = 0; while(w2 != NULL) { const char *wclass = w2->xclass(); if(w2 != view->dnawin && wclass != NULL && strcmp(wclass, SEAVIEW_WINDOW) == 0) { choice->add(w2->label()); Fl_Menu_Item *menu = (Fl_Menu_Item *)choice->menu(); (menu + count)->user_data(w2->user_data()); count++; } w2 = Fl::next_window(w2); } if(choice->size() <= 1) { w->end(); delete w; fl_alert("Concatenation requires more than one alignment window"); return; } choice->value(0); static char title[100]; sprintf(title, "Target alignment: %s", view->dnawin->label()); Fl_Box *target = new Fl_Box(10, 40, w->w() - 20, 20, title); target->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); Fl_Group *g = new Fl_Group(0, 70, w->w(), 40); by_name = new Fl_Round_Button(10, 75, 80, 20, "by name"); by_name->value(1); by_name->type(FL_RADIO_BUTTON); by_name->callback(rank_name_callback, NULL); Fl_Round_Button *rank = new Fl_Round_Button(100, 75, 80, 20, "by rank"); rank->type(FL_RADIO_BUTTON); rank->callback(rank_name_callback, NULL); g->end(); addgaps = new Fl_Check_Button(10, 100, 100, 20, "add gaps"); Fl_Button *cancel = new Fl_Button(10, 125, 50, 20, "Cancel"); cancel->callback(cancel_callback, NULL); Fl_Return_Button *ok = new Fl_Return_Button(w->w() - 60, 125, 50, 20, "OK"); ok->callback(do_concatenate_callback, view); w->end(); w->callback(cancel_callback, NULL); w->show(); #ifndef MICRO w->hotspot(w); #endif interrupted = FALSE; while(!interrupted) Fl::wait(); w->hide(); Fl::delete_widget(w); } static void cancel_callback( Fl_Widget *ob, void *data) { interrupted = TRUE; } void rank_name_callback( Fl_Widget *o, void *data) { if(o == by_name) addgaps->activate(); else { addgaps->value(0); addgaps->deactivate(); } } //concatenate target = target + source static void concatenate(SEA_VIEW *target, SEA_VIEW *source, bool want_addgaps, bool is_by_name, bool no_gui) { int i, j, l, *found, target_length = target->seq_length; char *gaps; if (is_by_name) {//concatenation by name if (want_addgaps) { l = FL_max(target_length, source->seq_length); gaps = (char *)malloc(l + 1); memset(gaps, '-', l); found = (int *)calloc(target->tot_seqs + source->tot_seqs, sizeof(int)); } for (i = 0; i < source->tot_seqs; i++) { for (j = 0; j < target->tot_seqs; j++) if(strcmp(source->seqname[i], target->seqname[j]) == 0) break; if (j >= target->tot_seqs) {//seq in source absent from target if ( !want_addgaps ) continue; //add a gap-only sequence to target add_seq_to_align(target, source->seqname[i], gaps, target_length, no_gui); j = target->tot_seqs - 1; if (source->comments[i] != NULL) target->comments[j] = strdup(source->comments[i]); } l = target->each_length[j] + source->each_length[i]; target->sequence[j] = (char *)realloc(target->sequence[j], l + 1); memcpy(target->sequence[j] + target->each_length[j], source->sequence[i], source->each_length[i]); target->each_length[j] = l; if (l > target->seq_length) target->seq_length = l; target->sequence[j][l] = 0; if (want_addgaps) found[j] = TRUE; } if (want_addgaps) { for (j = 0; j < target->tot_seqs; j++) { if (found[j]) continue; //seqs from target only are concatenated with a gap-only sequence l = target->each_length[j] + source->seq_length; target->sequence[j] = (char *)realloc(target->sequence[j], l + 1); memset(target->sequence[j] + target->each_length[j], '-', source->seq_length); target->sequence[j][l] = 0; target->each_length[j] = l; } free(gaps); free(found); } } else {//concatenation by rank for (i = 0; i < source->tot_seqs; i++) { if (i >= target->tot_seqs) break; l = strlen(target->sequence[i]) + strlen(source->sequence[i]); target->sequence[i] = (char *)realloc(target->sequence[i], l + 1); strcat(target->sequence[i], source->sequence[i]); target->each_length[i] = l; if (l > target->seq_length) target->seq_length = l; } } } void do_concatenate_callback( Fl_Widget *ob, void *data) { int i; SEA_VIEW *target = (SEA_VIEW *)data; interrupted = TRUE; i = choice->value(); Fl_Menu_Item *item = (Fl_Menu_Item *)choice->menu() + i; SEA_VIEW *source = (SEA_VIEW *)item->user_data(); char *oldname = strdup(target->masename); concatenate(target, source, addgaps->value(), by_name->value(), false); free(target->masename); free(target->each_length); for (i = 0; i < target->tot_seqs; i++) free(target->col_rank[i]); free(target->col_rank); init_dna_scroller(target, target->tot_seqs, oldname, target->protein, target->header); free(oldname); set_seaview_modified(target, TRUE); } void concatenate_no_gui(int argc, char *argv[]) { char *err_message; bool std_output = false; SEA_VIEW *target = cmdline_read_input_alignment(argc, argv); char *all_sources = argname(argc, argv, "-concatenate"); known_format out_format = target->format_for_save; char *source_name; source_name = strtok(all_sources, ","); bool is_by_rank = isarg(argc, argv, "-by_rank"); while (source_name) { SEA_VIEW *source = cmdline_read_input_alignment(1, &source_name); concatenate(target, source, !is_by_rank, !is_by_rank, true); source_name = strtok(NULL, ","); } char *outfile = process_output_options(argc, argv, out_format, std_output); err_message = save_alignment_or_region(outfile, target->sequence, target->comments, target->header, target->seqname, target->tot_seqs, target->each_length, target->regions, NULL, out_format, target->numb_species_sets, target->list_species_sets, target->name_species_sets, NULL, 0, target->protein, target->tot_comment_lines, target->comment_name, target->comment_line, target->phylipwidnames, target->tot_trees, target->trees, target->menu_trees->vitem(0), target->spaces_in_fasta_names); if (err_message) { fprintf(stderr, "%s\n", err_message); if (std_output) delete_tmp_filename(outfile); exit(1); } if (std_output) { char line[200]; FILE *in = fopen(outfile, "r"); while (fgets(line, sizeof(line), in) != NULL) { fputs(line, stdout); } fclose(in); fflush(stdout); delete_tmp_filename(outfile); } exit(0); } seaview/csrc/000755 000765 000000 00000000000 12614160742 013754 5ustar00mgouywheel000000 000000 seaview/custom.cxx000644 000765 000024 00000062043 12404325714 015071 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include #include #include #include #include #include void custom_callback(Fl_Widget *obj, void *data); void my_colorchooser(Fl_Widget *obj, void *data); void my_colorchooser_callback(Fl_Widget *obj, void *data); void slider_cb(Fl_Widget *obj, void *data); void ignore_cb(Fl_Widget *obj, void *data); void accept_cb(Fl_Widget *obj, void *data); void permanent_cb(void *data); void reset_color_callback(Fl_Widget *obj, void *data); void accept_color_callback(Fl_Widget *obj, void *data); void reset_callback(Fl_Widget *obj, void *data); void codon_color_chooser_cb(Fl_Widget *obj, void *data); int is_view_valid(SEA_VIEW *view); /* private global variables */ static Fl_Button *A, *C, *G, *T; static Fl_Slider *bgrnd, *s_bgrnd; static Fl_Input *protgroups, *s_protgroups, *movekeys; static Fl_Button **protcol; static Fl_Check_Button *lowercase, *inverted, *fastaspaces; static Fl_Int_Input *maxnamewidth; static Fl_Choice *pdfformat, *saveformat, *alignment_algo, *fontsize; static Fl_Value_Input *pdffontsize; static Fl_Value_Input *phylipwidnames; /* extern variables & functions */ extern int *def_protcolors, max_protcolors; extern char def_stdcolorgroups[]; extern int numb_stdprotcolors, numb_altprotcolors; extern color_choice curr_color_choice; extern char *f_format_names[]; extern int nbr_formats; extern Fl_Paged_Device::Page_Format printout_pageformat; extern int printout_fontsize; extern void mod_multipl(SEA_VIEW *view, int newval); extern void set_aa_color_mode(color_choice choice); extern color_choice prep_aa_color_code(char *list_std, char *list_alt, int maxprotcolors, int *numb_stdprotcolors, int *numb_altprotcolors); extern int set_res_value(const char *name, const char *value); extern int save_resources(void); extern void minuscules(char *); extern char *get_res_value(const char *name, const char *def_value); extern int int_res_value(const char *name, int def_value); extern char aminoacids[]; // from misc_acnuc.c class coloraas : public Fl_Widget { void draw(void); public: int codoncolors[22]; coloraas(int x,int y,int w,int h, int *in_codoncolors) : Fl_Widget(x,y,w,h) { memcpy(codoncolors, in_codoncolors, sizeof(codoncolors)); } }; void custom_callback(Fl_Widget *obj, void *data) { static Fl_Window *win = NULL; static Fl_Button *permanent, *accept, *ignore; static coloraas *mycoloraas; int x, y, w, h, c; SEA_VIEW *view = (SEA_VIEW *)obj->user_data(); Fl_Button *reset; const Fl_Menu_Item *item; if(win == NULL) { win = new Fl_Window(310, 640, "Customization"); x = 9; y = 20; w = 160; h = 20; bgrnd = new Fl_Slider(x,y,w,h, "background grey"); bgrnd->type(FL_HOR_NICE_SLIDER); bgrnd->bounds(32., 55.); bgrnd->color2( FL_BLACK ); bgrnd->precision(0); bgrnd->align(FL_ALIGN_TOP); bgrnd->callback(slider_cb); y += bgrnd->h() + 25; s_bgrnd = new Fl_Slider(x,y,w,h, "sites background grey"); s_bgrnd->type(FL_HOR_NICE_SLIDER); s_bgrnd->bounds(32., 55.); s_bgrnd->color2( FL_BLACK ); s_bgrnd->precision(0); s_bgrnd->align(FL_ALIGN_TOP); s_bgrnd->callback(slider_cb); reset = new Fl_Button(bgrnd->x() + bgrnd->w() + 40, s_bgrnd->y() - 20, 50, 20, "reset"); reset->color(FL_LIGHT2); reset->callback(reset_callback, bgrnd); new Fl_Box(FL_DOWN_FRAME, 5, 3, win->w() - 8, 90 , ""); y += s_bgrnd->h() + 20; w=40; h=w; A = new Fl_Button(x, y, w, h, "A"); A->callback(my_colorchooser ); x += A->w() + 10; C = new Fl_Button(x, y, w, h, "C"); C->callback(my_colorchooser ); x += A->w() + 10; G = new Fl_Button(x, y, w, h, "G"); G->callback(my_colorchooser ); x += A->w() + 10; T = new Fl_Button(x, y, w, h, "T/U"); T->callback(my_colorchooser ); x += A->w() + 30; reset = new Fl_Button(x, y + 10, 50, 20, "reset"); reset->color(FL_LIGHT2); reset->callback(reset_callback, A); new Fl_Box(FL_DOWN_FRAME, 5, A->y() - 5, win->w() - 8, A->h() + 10 , ""); x = A->x(); y += A->h() + 35; int topbox = y - 25; protgroups = new Fl_Input(x,y,280, 20, "aa coloring scheme"); protgroups->align(FL_ALIGN_TOP); y += protgroups->h() + 20; s_protgroups = new Fl_Input(x,y,280, 20, "alternate aa coloring scheme"); s_protgroups->align(FL_ALIGN_TOP); y += s_protgroups->h() + 10; new Fl_Box(x, y, win->w(), 20, "catalog of amino acid colors"); y += 20; w = h = 25; protcol = (Fl_Button **)malloc(max_protcolors * sizeof(Fl_Button *)); for(c=1; c < max_protcolors; c++) { protcol[c] = new Fl_Button(x, y, w, h, ""); protcol[c]->callback(my_colorchooser); x += w + 5; } y += h + 10; reset = new Fl_Button(win->w() / 2 - 25, y, 50, 20, "reset"); reset->color(FL_LIGHT2); reset->callback(reset_callback, protgroups); new Fl_Box(FL_DOWN_FRAME, 5, topbox, win->w() - 8, y + reset->h() + 5 - topbox, ""); topbox = reset->y() + reset->h() + 10; Fl_Box *frame = new Fl_Box(FL_DOWN_FRAME, 5, topbox, win->w() - 8, 50, ""); Fl_Box *box = new Fl_Box(FL_NO_BOX, 0, topbox, win->w(), 20, "Synonymous codon colors"); box->align(FL_ALIGN_CENTER); mycoloraas = new coloraas(10, topbox + 20, win->w() - 10, 20, view->codoncolors); mycoloraas->labelfont(FL_COURIER); mycoloraas->labelsize(18); Fl_Button *codons = new Fl_Button(win->w() - 65, topbox + 20, 60, 20, "Change"); codons->callback(codon_color_chooser_cb, mycoloraas); codons->clear_visible_focus(); x = A->x(); y = frame->y() + frame->h() + 25; movekeys = new Fl_Input(x,y, 50, 20, "right-left move keys"); movekeys->align(FL_ALIGN_TOP | FL_ALIGN_LEFT); reset = new Fl_Button(x + movekeys->w() + 5, y, 50, 20, "reset"); reset->color(FL_LIGHT2); reset->callback(reset_callback, movekeys); w = 130; x = win->w() - w - 5; saveformat = new Fl_Choice(x,y,w,h, "default save format"); saveformat->align(FL_ALIGN_TOP); for(c=0; c < nbr_formats; c++) saveformat->add(f_format_names[c]); saveformat->selection_color(saveformat->color()); x = A->x(); y += movekeys->h() + 10; lowercase = new Fl_Check_Button(x,y,140,20, "display lowercase"); y += lowercase->h(); inverted = new Fl_Check_Button(x,y,140,20, "inverted"); y += inverted->h(); fastaspaces = new Fl_Check_Button(x,y,170,20, "spaces in FASTA names"); fastaspaces->labelsize(13); x = win->w() - w - 5; y = movekeys->y() + movekeys->h() + 20; pdfformat = new Fl_Choice(x,y,w/2,h, PDF_OR_PS_EXT" page"); pdfformat->align(FL_ALIGN_TOP_LEFT); pdfformat->add("A4|LETTER"); pdfformat->selection_color(pdfformat->color()); pdfformat->labelsize(10); pdfformat->textsize(10); pdffontsize = new Fl_Value_Input(x+w/2,y,w/2,h, PDF_OR_PS_EXT" fontsize"); pdffontsize->align(FL_ALIGN_TOP_RIGHT); pdffontsize->labelsize(10); y += pdffontsize->h() + 15; maxnamewidth = new Fl_Int_Input(x, y, w, 20, "max name width"); maxnamewidth->labelsize(13); maxnamewidth->align(FL_ALIGN_TOP); x = A->x(); y = fastaspaces->y() + fastaspaces->h() + 25; alignment_algo = new Fl_Choice(x,y,w,h, "alignment algorithm"); alignment_algo->align(FL_ALIGN_TOP); y = alignment_algo->y(); x = pdfformat->x(); phylipwidnames = new Fl_Value_Input(x,y,w,h, "phylip names width"); phylipwidnames->align(FL_ALIGN_TOP); phylipwidnames->labelsize(13); x = phylipwidnames->x(); y = phylipwidnames->y() + phylipwidnames->h() + 15; fontsize = new Fl_Choice(x,y,w,h, "sequence font size"); fontsize->align(FL_ALIGN_TOP_LEFT); item = view->menu_props; while ((++item)->label()) { fontsize->add(item->label()); } x = A->x(); y += fontsize->h() + 10; h = 40; w = 95; accept = new Fl_Button(x,y,w,h, "Apply"); accept->tooltip("changes apply only to current seaview run"); accept->color(FL_LIGHT2); x += w + 5; permanent = new Fl_Button(x,y,w,h, "Set changes\npermanent"); permanent->tooltip("changes apply to current & future seaview runs"); permanent->color(FL_LIGHT2); w = 45; y += 10; ignore = new Fl_Button(win->w() - w - 5,y,w,20, "Close"); ignore->shortcut(FL_COMMAND | 'w'); ignore->color(FL_LIGHT2); win->end(); win->resizable(NULL); } mycoloraas->user_data(view); accept->callback(accept_cb, mycoloraas); bgrnd->value( view->DNA_obj->color() ); bgrnd->color( view->DNA_obj->color() ); s_bgrnd->value( view->DNA_obj->color2() ); s_bgrnd->color( view->DNA_obj->color2() ); A->color(view->dnacolors[1], view->dnacolors[1]); C->color(view->dnacolors[2], view->dnacolors[2]); G->color(view->dnacolors[3], view->dnacolors[3]); T->color(view->dnacolors[4], view->dnacolors[4]); char *p, aagroups[30]; p = aagroups; set_aa_color_mode(USING_STANDARD_COLORS); for(c=1; c < view->numb_stdprotcolors; c++) { for(char aa='A'; aa<='Z';aa++) { if(get_color_for_aa(aa) == c) *(p++) = aa; } if(c+1< view->numb_stdprotcolors) strcpy(p++, ","); } *p = 0; protgroups->value(aagroups); if(view->numb_altprotcolors <= 1) s_protgroups->value(""); else { p = aagroups; set_aa_color_mode(USING_ALT_COLORS); for(c=1; c < view->numb_altprotcolors; c++) { for(char aa='A'; aa<='Z';aa++) { if(get_color_for_aa(aa) == c) *(p++) = aa; } if(c+1< view->numb_altprotcolors) strcpy(p++, ","); } *p = 0; s_protgroups->value(aagroups); } if(view->curr_colors == view->stdprotcolors) set_aa_color_mode(USING_STANDARD_COLORS); else set_aa_color_mode(USING_ALT_COLORS); for(c=1; c < max_protcolors; c++) { protcol[c]->color(view->stdprotcolors[c], view->stdprotcolors[c]); } movekeys->value( view->movekeys ); lowercase->value(view->allow_lower); inverted->value(view->inverted_colors); fastaspaces->value(view->spaces_in_fasta_names); maxnamewidth->value(get_res_value("maxnamewidth", "20")); pdfformat->value(printout_pageformat == Fl_Paged_Device::A4 ? 0 : 1); pdffontsize->value(printout_fontsize); phylipwidnames->value(view->phylipwidnames); saveformat->value(view->format_for_save); Fl_Menu_Item *menu_align = (Fl_Menu_Item *)view->menu_align; int clustalopt = ALIGN_OPTIONS + 1; alignment_algo->clear(); for(x = 0; x < view->count_msa_algos; x++) { item = (menu_align + clustalopt + x); alignment_algo->add( item->label() ); } alignment_algo->value(view->alignment_algorithm); fontsize->value(3); item = view->menu_props; while((++item)->label()) { int fsize; sscanf(item->label(), "%d", &fsize); if (fsize == view->DNA_obj->labelsize()) { fontsize->value(item - view->menu_props - 1); break; } } win->show(); #ifndef MICRO win->hotspot(win); #endif while (TRUE) { Fl_Widget* obj = Fl::readqueue(); if (!obj) Fl::wait(); else if (obj == ignore || obj == permanent || obj == win) { if (obj == permanent) permanent_cb(mycoloraas); win->hide(); break; } } } void ignore_cb(Fl_Widget *obj, void *data) { obj->window()->hide(); } void accept_cb(Fl_Widget *obj, void *data) { coloraas *mycoloraas = (coloraas *)data; SEA_VIEW *view = (SEA_VIEW *)mycoloraas->user_data(); if(!is_view_valid(view)) return; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); char *p; Fl_Menu_Item *item; my_watch_cursor(view->dnawin); memcpy(view->codoncolors, mycoloraas->codoncolors, sizeof(mycoloraas->codoncolors)); view->DNA_obj->color((int)(bgrnd->value() + 0.5)); view->DNA_obj->color2((int)(s_bgrnd->value() + 0.5)); view->DNA_obj->parent()->color( view->DNA_obj->color() ); view->dnacolors[1] = A->color(); view->dnacolors[2] = C->color(); view->dnacolors[3] = G->color(); view->dnacolors[4] = T->color(); for(int c=1; c < max_protcolors; c++) view->stdprotcolors[c] = protcol[c]->color(); p = strdup(protgroups->value()); majuscules(p); protgroups->value(p); free(p); p = strdup(s_protgroups->value()); majuscules(p); s_protgroups->value(p); free(p); curr_color_choice = prep_aa_color_code((char *)protgroups->value(), (char *)s_protgroups->value(), max_protcolors, &numb_stdprotcolors, &numb_altprotcolors); view->numb_stdprotcolors = numb_stdprotcolors; view->numb_altprotcolors = numb_altprotcolors; if (view->numb_altprotcolors > 1) (menu_props + props_parts->colors + 2)->activate(); else (menu_props + props_parts->colors + 2)->deactivate(); if(view->protein) { view->alt_colors = (color_choice)-1; /* to force redraw of sequences */ item = menu_props + props_parts->colors + 1; item->setonly(); view->menubar->value(item); item->callback()(view->menubar, props_parts); if(view->numb_altprotcolors > 1) view->alt_colors = USING_STANDARD_COLORS; else view->alt_colors = NO_ALT_COLORS; } if(strlen(movekeys->value()) != 4) movekeys->value(view->movekeys); else { strcpy(view->movekeys, movekeys->value() ); mod_multipl(view, view->multipl->argument() ); view->multipl->redraw(); } item = menu_props + props_parts->allow_lower; view->allow_lower = lowercase->value(); if(view->allow_lower) item->set(); else item->clear(); item = menu_props + props_parts->inverted; view->inverted_colors =! inverted->value(); /* because callback toggles it */ view->menubar->value(item); Fl_Callback1* cb = (Fl_Callback1*)item->callback(); cb(view->menubar, props_parts->inverted); if(view->inverted_colors) item->set(); else item->clear(); view->spaces_in_fasta_names = fastaspaces->value(); set_res_value("maxnamewidth", ((Fl_Input*)maxnamewidth)->value()); printout_pageformat = pdfformat->value() == 0 ? Fl_Paged_Device::A4 : Fl_Paged_Device::LETTER; printout_fontsize = (int)pdffontsize->value(); view->phylipwidnames = (int)phylipwidnames->value(); if(view->phylipwidnames < 10) { view->phylipwidnames = 10; phylipwidnames->value(10); } view->format_for_save = (known_format)saveformat->value(); view->alignment_algorithm = alignment_algo->value(); Fl_Menu_Item *menu_align = (Fl_Menu_Item *)view->menu_align; int clustalopt = ALIGN_OPTIONS + 1; item = menu_align + clustalopt; (item + view->alignment_algorithm)->setonly(); item = (Fl_Menu_Item*)view->menu_props + fontsize->value() + 1; item->setonly(); view->menubar->value(item); item->callback()(view->menubar, NULL); if(!view->protein) view->DNA_obj->redraw(); fl_reset_cursor(view->dnawin); } void permanent_cb(void *data) { char txt[150], *p; int v, i; uchar r, g, b; coloraas *mycoloraas = (coloraas *)data; accept_cb(NULL, data); v = (int)(bgrnd->value() + 0.5); sprintf(txt, "%d", v ); set_res_value("background", txt ); v = (int)(s_bgrnd->value() + 0.5); sprintf(txt, "%d", v ); set_res_value("sites_background", txt ); Fl::get_color( A->color(), r, g, b); sprintf(txt, "%d %d %d,", r, g, b); Fl::get_color( C->color(), r, g, b); sprintf(txt + strlen(txt), "%d %d %d,", r, g, b); Fl::get_color( G->color(), r, g, b); sprintf(txt + strlen(txt), "%d %d %d,", r, g, b); Fl::get_color( T->color(), r, g, b); sprintf(txt + strlen(txt), "%d %d %d", r, g, b); set_res_value("dnacolors", txt); set_res_value("stdcolorgroups", (char *)protgroups->value()); set_res_value("altcolorgroups", (char *)s_protgroups->value()); txt[0] = 0; for(int c=1; c < max_protcolors; c++) { Fl::get_color( protcol[c]->color(), r, g, b); sprintf(txt + strlen(txt), "%d %d %d,", r, g, b); } txt[strlen(txt) - 1] = 0; set_res_value("protcolors", txt); set_res_value("movekeys", movekeys->value() ); set_res_value("lowercase", lowercase->value() ? "true" : "false"); set_res_value("inverted", inverted->value() ? "true" : "false"); set_res_value("spacesinfastanames", fastaspaces->value() ? "true" : "false"); set_res_value("printoutpageformat", printout_pageformat == Fl_Paged_Device::A4 ? "A4" : "LETTER" ); sprintf(txt, "%d", (int)pdffontsize->value() ); set_res_value("printoutfontsize", txt); sprintf(txt, "%d", (int)phylipwidnames->value() ); set_res_value("phylipwidnames", txt); strcpy(txt, f_format_names[saveformat->value()] ); minuscules(txt); set_res_value("save", txt ); v = alignment_algo->value(); sprintf(txt, "%d", v ); set_res_value("alignment", txt); p = txt; for(i = 0; i < 21; i++) { sprintf(p, "%c:%d,", aminoacids[i], mycoloraas->codoncolors[i+1]); p += strlen(p); } *(p-1) = 0; set_res_value("codoncolors", txt); set_res_value("sequencefontsize", fontsize->text()); save_resources(); } void reset_callback(Fl_Widget *obj, void *data) { if(data == A) { A->color(FL_RED, FL_RED); C->color(FL_GREEN, FL_GREEN); G->color(FL_YELLOW, FL_YELLOW); T->color(FL_BLUE, FL_BLUE); } else if(data == bgrnd) { int back_color, region_back_color; #ifdef WIN32 back_color = FL_DARK1; region_back_color = 43; #else back_color = FL_GRAY; region_back_color = FL_DARK2; #endif bgrnd->value( back_color ); bgrnd->color( back_color ); s_bgrnd->value( region_back_color ); s_bgrnd->color( region_back_color ); } else if(data == movekeys) { movekeys->value(MOVEKEYS_DEFAULT); } else if(data == protgroups) { protgroups->value(def_stdcolorgroups); s_protgroups->value(""); for(int c=1; c < max_protcolors; c++) { protcol[c]->color(def_protcolors[c], def_protcolors[c]); } } obj->window()->redraw(); } void my_colorchooser(Fl_Widget *obj, void *data) { static Fl_Window *win = NULL; static Fl_Color_Chooser *ch; uchar r, g, b; static Fl_Color initial; if(win == NULL) { win = new Fl_Window(205, 125, "Color chooser"); ch = new Fl_Color_Chooser(1, 1, 200, 95); ch->callback(my_colorchooser_callback); Fl_Button *reset = new Fl_Button(5, 100, 40, 20, "reset"); reset->callback(reset_color_callback, ch); Fl_Button *ok = new Fl_Button(160, 100, 40, 20, "OK"); ok->callback(accept_color_callback, ch); win->end(); win->resizable(NULL); win->set_modal(); win->callback(reset_color_callback, ch); } if(win->shown()) return; Fl::get_color( obj->color(), r, g, b); ch->rgb(r/255., g/255., b/255.); ch->user_data(obj); obj->user_data(&initial); initial = obj->color(); win->show(); return; } void my_colorchooser_callback(Fl_Widget *obj, void *data) { int r, g, b; Fl_Button *but = (Fl_Button *)data; Fl_Color_Chooser *ch = (Fl_Color_Chooser *)obj; r = (int)(ch->r() * 255 + 0.5); g = (int)(ch->g() * 255 + 0.5); b = (int)(ch->b() * 255 + 0.5); Fl_Color c = fl_rgb_color(r, g, b); but->color(c, c); but->redraw(); } void reset_color_callback(Fl_Widget *obj, void *data) { Fl_Color_Chooser *ch = (Fl_Color_Chooser *)data; Fl_Widget *from = (Fl_Widget *)(ch->user_data()); Fl_Color c = *(Fl_Color *)(from->user_data()); uchar r, g, b; from->color(c, c); from->redraw(); if(obj->window() == NULL) ((Fl_Window *)obj)->hide(); else { Fl::get_color( c, r, g, b); ch->rgb(r/255., g/255., b/255.); } } void accept_color_callback(Fl_Widget *obj, void *data) { obj->window()->hide(); } void slider_cb(Fl_Widget *obj, void *data) { Fl_Valuator *v = (Fl_Valuator *)obj; v->color( (int)(v->value() + 0.5) ); } class colorcell : public Fl_Widget { FL_EXPORT void draw(void); FL_EXPORT int handle(int); public: FL_EXPORT colorcell(int x,int y,int w,int h) : Fl_Widget(x,y,w,h,NULL) { this->copy_label(" "); } }; class codon_color_chooser : public Fl_Window { public: Fl_Group *g; colorcell *selected; coloraas *mycoloraas; codon_color_chooser(coloraas *mycoloraas); private: static void cancel_cb(Fl_Widget *ob, void *data); static void new_colors_cb(Fl_Widget *w, void *data); static void reset_cb(Fl_Widget *w, void *data); static void defaults_cb(Fl_Widget *w, void *data); }; int colorcell::handle(int event) { char *aa, *p; int key, before, i; Fl_Group *g; colorcell *cell; codon_color_chooser *mychooser = (codon_color_chooser *)this->window(); switch (event) { case FL_RELEASE: if(mychooser->selected) { mychooser->selected->redraw(); } mychooser->selected = this; this->redraw(); Fl::focus(this); break; case FL_KEYBOARD: if( Fl::event_state(FL_COMMAND) ) return 0; // can be shortcut of other widgets if(Fl::event_length() == 0) break; key = Fl::event_text()[0]; key = toupper(key); if((aa = strchr(aminoacids, key)) == NULL) break; if(*aa == 'X') break; p = (char *)this->label(); before = *p; *p = *aa; this->redraw(); g = parent(); for(i=0; i < 256; i++) { cell = (colorcell *)g->child(i); p = (char *)cell->label(); if(*p == key && cell != this) { *p = before; cell->redraw(); break; } } break; case FL_FOCUS: break; default: return 0; } return 1; } void colorcell::draw(void) { codon_color_chooser *mychooser = (codon_color_chooser *)this->window(); fl_color(color()); fl_rectf(x(), y(), w(), h()); fl_color(FL_BLACK); if(*label() != ' ') { fl_font(labelfont(), labelsize()); fl_draw(label(), 1, x() + w()/2 - (int)fl_width(label())/2, y() + h()/2 + fl_size()/3 ); } if(mychooser->selected == this) { fl_line_style(0, 3); fl_rect(x() + 2, y() + 2, w()-4, h()-4); fl_line_style(0, 0); } } void decode_codon_colors(int *colors) // puts desired colorindex in colors[1..21] in the order of aminoacids table { const char *q; char *p, *codestring; int i, val, retval = 0; codestring = get_res_value("codoncolors", NULL); if(codestring != NULL) { //codestring contains R:10,W:155,*:5,.... p = codestring; for(i = 1; i <= 21; i++) { q = strchr(aminoacids, *p); if(q == NULL || *q == 'X') { p = strchr(p, ','); if(p == NULL) break; p++; continue; } p += 2; sscanf(p, "%d", &val); colors[q - aminoacids + 1] = val; retval++; p = strchr(p, ','); if(p == NULL) break; p++; } } if(retval != 21) {//absence or incomplete codoncolors preference for(i = 1; i <= 21; i++) colors[i] = i + 72; return; } } void codon_color_chooser::defaults_cb(Fl_Widget *w, void *data) { int aa, colrank, i; char *p; codon_color_chooser *mychooser = (codon_color_chooser *)w->window(); colorcell *cell; for(i=0; i < 256; i++) { cell = (colorcell *)mychooser->g->child(i); p = (char *)cell->label(); *p = ' '; } for(aa=1; aa <= 21; aa++) { colrank = aa + 72; cell = (colorcell *)mychooser->g->child(colrank); p = (char *)cell->label(); *p = aminoacids[aa-1]; } mychooser->selected = NULL; mychooser->g->redraw(); } void codon_color_chooser::cancel_cb(Fl_Widget *ob, void *data) { codon_color_chooser *mychooser = (codon_color_chooser *)(ob->window() ? ob->window() : ob); mychooser->hide(); Fl::delete_widget(mychooser); } void codon_color_chooser::new_colors_cb(Fl_Widget *w, void *data) { codon_color_chooser *mychooser = (codon_color_chooser *)w->window(); char *aa; int rank, i; colorcell *cell; for(i=0; i < 256; i++) { cell = (colorcell *)mychooser->g->child(i); aa = (char *)cell->label(); if(*aa == ' ') continue; rank = strchr(aminoacids, *aa) - aminoacids; mychooser->mycoloraas->codoncolors[rank+1] = i; } mychooser->mycoloraas->redraw(); mychooser->do_callback(); } void codon_color_chooser::reset_cb(Fl_Widget *w, void *data) { codon_color_chooser *mychooser = (codon_color_chooser *)w->window(); char *p; int aa, colrank, colors[22]; colorcell *cell; for(colrank=0; colrank < 256; colrank++) { cell = (colorcell *)mychooser->g->child(colrank); p = (char *)cell->label(); *p = ' '; } decode_codon_colors(colors); //we have now a complete list of colors for(aa = 1; aa <= 21; aa++) { cell = (colorcell *)mychooser->g->child(colors[aa]); p = (char *)cell->label(); *p = aminoacids[aa-1]; } mychooser->selected = NULL; mychooser->g->redraw(); } void codon_color_chooser_cb(Fl_Widget *obj, void *data) { codon_color_chooser *mychooser = new codon_color_chooser( (coloraas *)data ); mychooser->show(); } codon_color_chooser::codon_color_chooser(coloraas *in_coloraas) : Fl_Window(330, 414) { int i, j; colorcell *box; mycoloraas = in_coloraas; label("Synonymous codon color chooser"); set_modal(); Fl_Box *b = new Fl_Box(FL_NO_BOX, 0, 0, this->w(), 60, "Click on color cell, and type desired\none-letter amino acid (or * for stop codons)."); b->align(FL_ALIGN_CENTER); g = new Fl_Group(5, 65, 320, 320); for(i=0; i < 16; i++) { for(j=0; j < 16; j++) { box = new colorcell( 5 + j*20, 65 + i * 20, 20, 20); box->box(FL_FLAT_BOX); box->color(16*i + j); box->align(FL_ALIGN_CENTER); box->labelfont(FL_COURIER_BOLD); box->labelsize(14); } } g->end(); //fill cells with adequate aas for(i = 1; i <= 21; i++) { colorcell *cell = (colorcell *)g->child(mycoloraas->codoncolors[i]); char *p = (char *)cell->label(); *p = aminoacids[i-1]; } Fl_Button *cancel = new Fl_Button(5, 390, 60, 20, "Cancel"); cancel->callback(cancel_cb, NULL); cancel->tooltip("don't change anything"); cancel->shortcut(FL_COMMAND | 'w'); Fl_Button *reset = new Fl_Button(100, 390, 60, 20, "Reset"); reset->callback(reset_cb, NULL); reset->tooltip("back to previous color set"); Fl_Button *defaults = new Fl_Button(170, 390, 70, 20, "Defaults"); defaults->callback(defaults_cb, NULL); defaults->tooltip("use seaview's default color set"); Fl_Button *ok = new Fl_Button(275, 390, 50, 20, "OK"); ok->callback(new_colors_cb, NULL); ok->tooltip("accept new color set"); end(); callback(cancel_cb, NULL); selected = NULL; } void coloraas::draw(void) { int i, wl; fl_font(this->labelfont(), this->labelsize()); wl = (int)(fl_width("A") + 0.5); for(i=0; i < 21; i++) { fl_color(this->codoncolors[i + 1]); fl_rectf(x() + i * wl, y(), wl, h()); } fl_color(FL_BLACK); fl_draw(aminoacids, 21, x() , y() + h()/2 + fl_size()/3 ); } int is_view_valid(SEA_VIEW *view) { Fl_Window *w = Fl::first_window(); while(w != NULL) { const char *wclass = w->xclass(); if(wclass != NULL && strcmp(wclass, SEAVIEW_WINDOW) == 0 && w->user_data() == view) return TRUE; w = Fl::next_window(w); } return FALSE; } seaview/example.nxs000644 000765 000024 00000076245 11157462710 015233 0ustar00mgouystaff000000 000000 #NEXUS [saved by seaview on Mon Mar 16 15:43:12 2009] BEGIN DATA; DIMENSIONS NTAX=54 NCHAR=456; FORMAT DATATYPE=DNA GAP=- ; MATRIX [1] D82069.PE1 ---------atgaagcctgaggaaatttcaagaggaaaagcttttggactgctgaaagcc caacaggaagagaggttggatgggatcaacaagcacttcctcgatgatcccaagtacagc agtgatgaggatctgcagtccaaactggaggccttcaagacgaagtacatggagtttgat ctgaatggcaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccatctagagctgaagaaattaattagagaggtgtccagtggctccgag ---gagacgttcagttactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacaccag---aagccaactggt cccccagccaagaaagctatttctgagttgccctaa [2] 'AB019540.AIF-1' ------------atggacagcacagctcaaggaggtaaagcatttggtcttctcaagtct caccaggaagaaaaattgaactctatcaatgaggcttttctctcagatccccaatatgca gaagaggaagacctcagctcaaagcttgaagcatttaaaaagaaatacatggagtttgat cttaacgacaaaggagaaatagatattatgggtttgaaacggatgctggaaaaactcgga ttggccaagactcacttggagctgaaaaagatgatgtcagaggtctgtggaggaacatcg aaagaaactttcggctaccacgacttcctgaatatgatgctgggaaaaagaaatgcaatt ctaaaactgatcttgatgtttgaaggcatgggaaaggagcacgagtccaaagatgcggca ccacctcctcgcaaaaccttttcagacctgccctga [3] AB000818.PE1 ------atgagccagagcaaggatttgcagggaggaaaagcttttggactgctgaaagcc cagcaggaagagaggttggatgggatcaacaagcacttcctcgatgatcccaagtacagc agtgatgaggatctgcagtccaaactggaggccttcaagacgaagtacatggagtttgat ctgaatggcaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccatctagagctgaagaaattaattagagaggtgtccagtggctccgag ---gagacgttcagttactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacaccag---aagccaactggt cccccagccaagaaagctatttctgagttgccctaa [4] AB012309.PE1 ------atgccttccaaccagaatttacaaggcgggaaagccttcgggttactcaaagca cagcagagggagaagctggatgaaatcaataaggagtttatggaagatcagaagtaccgg gatgaagaggatttgcaagagaagctagattcttttaaaaataaatatgctgagtttgac ctgaacgatcagggggatatcgacatgatgggcttgaagcgaatgatggagaagttgggt gtgccaaagactcacctggagatgaagaaaatgatctcagaggtgacaggaggttgcagc ---gacaccatcaactacagggactttgtgaaaatgatgcttggcaagcgatcagctgtt ctcaaactggttatgatgtttgaagacaaagctaatgaggccagcggtaaacccgatgga cccccacccaagcgtgacatcaccacccttccataa [5] 'AB013745.AIF-1' ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [6] AB035322 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaatatgatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [7] AB036423.IBA1 ---------atgaagcctgaggagatttcaagaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [8] AB036423.PE2 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [9] AB094629.IBA2 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaatatgatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [10] AB128049.AIF1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaatttctagatgatcccaaatacagc agtgatgaggatctgctctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaacggcgatattgatatcatgtccctgaagcgaatgctggagaaacttggg gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatt ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatttctgagttgccctga [11] AF074959.PE1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [12] AF109719.PE7 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [13] AF129756.PE18 ------atgagccaaaccagggatttacagggaggaaaagctttcagactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [14] AF348450.PE1 ------atgagcgaaactagggatttacagggaggaaaagcctttgggctgcggaaagcc cagcaggaagagagaatcaatgaaatcaaccagcaattcctggatgatcccaaatacagc agtgatgaggacctgccctccaaactggaagccttcaagaagaaatacatggagtttgac ctgaatgaagatggaggtatcgatatcatgtccctgaagcgaatgatggagaaacttggg gttcccaagacccacctggagctaaagaaattaatcatggaggtatccagtggccctggg ---gagactttcagctactctgactttctcaagatgatgttgggcaagagatctgccatt ctaaaaatgatcctgatgtatgaagagaaagcaagagaacaggag---aagccaacaggt ctcccagccaagaaagctatctctgagttgccctga [15] AJ506968.AIF1 ------------atggagaaaaatgttcaaggaggcaaagcgtatggacttctcaaaagt caccaggaagagaaactgaactcgatcaatgaggcttttcagtcagatcctcaatatgcc gaagaggaggaccttggctccaaacttgaaatgtttaaaaataaatacatggagtttgat ctcaatgatcaaggagacatagacataatggggttaaaacggatgcttgaaaaacttgga gtggccaagactcacctagaactgaaaaagatgatgtcagaggtgattggtggggcctcg aaagacacaatcagctaccacgacttcctaaatatgatgctggggaaaagaaatgcaatt ctcaaactgatcctgatgtttgaaggaatggggaaggagcaggagtcaaaagtcgttggt ccacctggtcgcaaaaccttttcagacctgccctga [16] AK006184.PE1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [17] AK006562.PE1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [18] AK022845.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagcttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [19] AK028955.PE1 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaataagatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [20] AK045539.PE1 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaatatgatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [21] AK091912.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagttt--- ---------------------gacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [22] AL136566.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [23] AL157938.PE2 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [24] AL157938.PE3 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagttt--- ---------------------gacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [25] AL662801.PE45 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [26] AL662847.AIF1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [27] AL805934.AIF1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [28] AL833896.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [29] AL928893.PE3 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaatatgatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [30] AY359067.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagtttctgtgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctgatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacactatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagttagtcatgatgtttgaaggaaaagccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [31] BA000025.AIF1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [32] BC009474.AIF1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [33] BC021539.PE1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaaatacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [34] BC024599.PE1 atgtcggtcgcactcagcaacaggttccaaggagggaaggcgttcggtttgctcaaagcc cggcaggagaagaggctcgaggagatcaatcgggagttcctctgtgaccagaagtacagt gatgaagagaacctgccggaaaagctcgcagccttcaaagagaaatacatggagtttgac ctgaataatgaaggcgagattgatctgatgtctttaaagaggatgatggagaagctgggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacagggggtgtcagt ---gacaccatctcctaccgagactttgtgaatatgatgctgggcaagcggtcggctgtc ctcaagctggtcatgatgtttgaaggaaaagccaacgagagcagcccgaagccagctggc ccacctccagagcgagacatcgccagcctgccttga [35] BC073304.MGC8069 ------atgtcttctaataacattaaacaaggtggcaaagctttcgtgatccaaaaggca cagcaggagcacagactagaggaggtgaacaaggagttccttaaagatgaaaaatacaag gatgatgaggacttggataaaaaactgatgtcctttaaaaaaaagtacatggaatttgac cttaaccaacaaggagagctggatatgatgggcctcaagaaaatgttggagaatctggga gccgctaagacccatttagaagttaagaaattgatatatgaagtgacaggaggcaaaagt ---gaggcaatcagctatcaggattttgtaaccatgatgcttggaaaacgttcagccata atgaaatttatcatgatgtttgagggaaaaaatgaagtcacaagtcccaagcccatgggt ccaccaccaaagagagacatcagcagcctaccctga [36] BC074259.MGC8401 ------atgtcttccaataacattaaacaaggtggcaaagctttcgtgatccaaaaggcg cagcaggagcacagactggaggaggtgaacaaggagttccttaaagatgaaaaatacaag gatgacgaggacttggataaaaaactgatgtcctttaaaaaaaagtacatggaatttgac cttaaccaccaaggagagctggatatgatgggcctgaagaaaatgatggagaacctggga gctgctaaaacccatttagaagttaagaaactgatatatgaagtgacgggaggcaaaagt ---gaggcaatcagctaccgggattttgtaaccatgatgctgggaaaacgttctgccgtg atgaaatttatcatgatgtttgagggaaaaaatgaagtcacatgtcccaagccaaagggt ccaccacccaagagagacatcagcagccttccctga [37] BC084814.MGC8401 ------atgtcttccaataacattaaacaaggtggcaaagctttcgtgatccaaaaggcg cagcaggagcacagactggaggaggtgaacaaggagttccttaaagatgaaaaatacaag gatgacgaggacttggataaaaaactgatgtcctttaaaaaaaagtacatggaatttgac cttaaccaccaaggagagctggatatgatgggcctgaagaaaatgatggagaacctggga gctgctaaaacccatttagaagttaagaaactgatatatgaagtgacgggaggcaaaagt ---gaggcaatcagctaccgggattttgtaaccatgatgctgggaaaacgttctgccgtg atgaaatttatcatgatgtttgagggaaaaaatgaagtcacatgtcccaagccaaagggt ccaccacccaagagagacatcagcagccttccctga [38] BC102890.AIF1 ------atgagcgaaactagggatttacagggaggaaaagcctttgggctgcggaaagcc cagcaggaagagagaatcaatgaaatcaaccagcaattcctggatgatcccaaatacagc agtgatgaggacctgccctccaaactggaagccttcaagaagaaatacatggagtttgac ctgaatgaagatggaggtatcgatatcatgtccctgaagcgaatgatggagaaacttggg gttcccaagacccacctggagctaaagaaattaatcatggaggtatccagtggccctggg ---gagactttcagctactctgactttctcaagatgatgttgggcaagagatctgccatt ctaaaaatgatcctgatgtatgaagagaaagcaagagaacaggag---aagccaacaggt ctcccagccaagaaagctatctctgagttgccctga [39] BC126840.C9ORF58 atgtcggtcgcgttcagcaacaggttccaaggagggaaagccttcggtttgctcaaagcc cggcaggagaggaggctggccgagatcaaccgggagttcctctgcgaccaaaagtacagt gatgaagagaacctgccggaaaagctcacagcctttaaagagaagtacatggagtttgac ctgaacaatgagggagagattgatctgatgtctttgaagaggatgatggagaagcttggg gtccccaagacccacctggagatgaagaagatgatctcggaggtgacaggtggggtcagc ---gacaccatctcctaccgagacttcgtgaacatgatgctggggaagcggtcggcggtc cttaagctagtcatgatgtttgaaggaaaagccaacgaaggcagctccaagccagtcggg ccccctccagagagagacatcgccagcctgccctga [40] BX248305.PE3 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [41] BX571730.PE3 ------atgccttccaacatggacttacaaggcggaaaagccttcgggttgctcaaagct cagcagagggacaagctggaggaaatcaataaggagttcatggaagatcagaagtacaga gacgaagaggacttgcctgaaaagctggattcttttaaaaataaatatgcagagtttgac ctgaacgatcaaggggaaatcgacatgatgggcttgaagcgaatgatggagaagttgggt gtgccaaaaactcatctgcagatgaagaaaatgatctctgaggtgacaggaggctgcagt ---gacaccatcaactacagggattttgtgaaaatgatgctcggcaagcgatcagctgtt ctcaaactggttatgatgtttgaagacaaagctaatgggtccagctgtaagcctgatggg cctccacccaaacgtgacatcaccagcctaccatag [42] BX883046.AIF1 ------atgagccagagcaaggatttgcagggaggaaaagcttttggactgctgaaagcc caacaggaagagaggttggatgggatcaacaagcacttcctcgatgatcccaagtacagc agtgatgaggatctgcagtccaaactggaggccttcaagacgaagtacatggagtttgat ctgaatggcaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccatctagagctgaagaaattaattagagaggtgtccagtggctccgag ---gagacgttcagttactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacaccag---aagccaactggt cccccagccaagaaagctatttctgagttgccctaa [43] CR762385.PE3 ------atgccttccaacatggacttacaaggcggaaaagccttcgggttgctcaaagct cagcagagggacaagctggaggaaatcaataaggagttcatggaagatcagaagtacaga gacgaagaggacttgcctgaaaagctggattcttttaaaaataaatatgcagagtttgac ctgaacgatcaaggggaaatcgacatgatgggcttgaagcgaatgatggagaagttgggt gtgccaaaaactcatctgcagatgaagaaaatgatctctgaggtgacaggaggctgcagt ---gacaccatcaactacagggattttgtgaaaatgatgctcggcaagcgatcagctgtt ctcaaactggttatgatgtttgaagacaaagctaatgggtccagctgtaagcctgatggg cctccacccaaacgtgacatcaccagcctaccatag [44] CR857925.PE1 atgtcgggcgagctcagcaacaggttccaaggagggaaggcgttcggcttgctcaaagcc cggcaggagaggaggctggccgagatcgaccgggagtttctctgtgaccagaagtacagt gatgaagagaaccttccagaaaagctcacagccttcaaagagaagtacatggagtttgac ctgaacaatgaaggcgagattgacctaatgtctttaaagaggatgatggagaagcttggt gtccccaagacccacctggagatgaagaagatgatctcagaggtgacaggaggggtcagt ---gacaccatatcctaccgagactttgtgaacatgatgctggggaaacggtcggctgtc ctcaagctagtcatgatgtttgaaggaaaggccaacgagagcagccccaagccagttggc ccccctccagagagagacattgctagcctgccctga [45] CT010265 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctag [46] CT010385 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaaatacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctag [47] D86382.IBA1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [48] D86438.IBA1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [49] EF070983.PE1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [50] U17919.PE1 ------atgagccagagcaaggatttgcagggaggaaaagcttttggactgctgaaagcc cagcaggaagagaggttggatgggatcaacaagcacttcctcgatgatcccaagtacagc agtgatgaggatctgcagtccaaactggaggccttcaagacgaagtacatggagtttgat ctgaatggcaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccatctagagctgaagaaattaattagagaggtgtccagtggctccgag ---gagacgttcagttactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacaccag---aagccaactggt cccccagccaagaaagctatttctgagttgccctaa [51] U19713.PE1 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga [52] 'U49392.AIF-1' ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctacacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccttgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaagg------aaaaccaacacg ccccccagccaagaaagccctatctga--------- [53] U82792.PE1 ------atgagccaaagcagggatttgcagggaggaaaagcttttggactgctgaaggcc cagcaggaagagaggctggaggggatcaacaagcaattcctcgatgatcccaaatacagc aatgatgaggatctgccgtccaaacttgaagccttcaaggtgaagtacatggagtttgat ctgaatggaaatggagatatcgatattatgtccttgaagcgaatgctggagaaacttggg gttcccaagacccacctagagctgaagagattaattagagaggtgtccagtggctccgag ---gagacgttcagctactctgactttctcagaatgatgctgggcaagagatctgccatc ttgagaatgattctgatgtatgaggagaaaaacaaagaacacaag---aggccaactggt cccccagccaagaaagctatctccgagctgccctga [54] Y14768.PE3 ------atgagccaaaccagggatttacagggaggaaaagctttcggactgctgaaggcc cagcaggaagagaggctggatgagatcaacaagcaattcctagacgatcccaaatatagc agtgatgaggatctgccctccaaactggaaggcttcaaagagaaatacatggagtttgac cttaatggaaatggcgatattgatatcatgtccctgaaacgaatgctggagaaacttgga gtccccaagactcacctagagctaaagaaattaattggagaggtgtccagtggctccggg ---gagacgttcagctaccctgactttctcaggatgatgctgggcaagagatctgccatc ctaaaaatgatcctgatgtatgaggaaaaagcgagagaaaaggaa---aagccaacaggc cccccagccaagaaagctatctctgagttgccctga ; END; BEGIN NOTES; TEXT TAXON=1 TEXT='D82069.PE1 CDS /codon_start=1 /product="iba1, ionized calcium binding adapter mo '; TEXT TAXON=2 TEXT='AB019540.AIF-1 CDS /codon_start=1 /transl_table=1 /gene="AIF-1" /product="allogr '; TEXT TAXON=3 TEXT='AB000818.PE1 CDS /codon_start=1 /transl_table=1 /product="MRF-1" /db_xref="GOA:P '; TEXT TAXON=4 TEXT='AB012309.PE1 CDS /codon_start=1 /transl_table=1 /product="allograft inflammatory '; TEXT TAXON=5 TEXT='AB013745.AIF-1 CDS /codon_start=1 /transl_table=1 /gene="AIF-1" /product="allogr '; TEXT TAXON=6 TEXT='AB035322 Mus musculus mRNA for ionized calcium binding adapter molecule 2 (Iba2) '; TEXT TAXON=7 TEXT='AB036423.IBA1 CDS /codon_start=1 /transl_table=1 /gene="iba1" /product="ionized '; TEXT TAXON=8 TEXT='AB036423.PE2 CDS /codon_start=1 /transl_table=1 /gene="iba1" /product="ionized c '; TEXT TAXON=9 TEXT='AB094629.IBA2 CDS /codon_start=1 /transl_table=1 /gene="iba2" /product="ionized '; TEXT TAXON=10 TEXT='AB128049.AIF1 CDS /codon_start=1 /transl_table=1 /gene="AIF1" /product="allograf '; TEXT TAXON=11 TEXT='AF074959.PE1 CDS /codon_start=1 /product="allograft inflammatory factor-1" /note '; TEXT TAXON=12 TEXT='AF109719.PE7 CDS /codon_start=1 /product="AIF-1" /note="allograft inflammatory f '; TEXT TAXON=13 TEXT='AF129756.PE18 CDS /codon_start=1 /product="AIF-1" /note="anti-inflammatory facto '; TEXT TAXON=14 TEXT='AF348450.PE1 CDS /codon_start=1 /product="allograft inflammatory factor-1" /note '; TEXT TAXON=15 TEXT='AJ506968.AIF1 CDS /gene="aif1" /product="allograft inflammatory factor 1" /db_xr '; TEXT TAXON=16 TEXT='AK006184.PE1 CDS /codon_start=1 /transl_table=1 /note="ALLOGRAFT INFLAMMATORY FA '; TEXT TAXON=17 TEXT='AK006562.PE1 CDS /codon_start=1 /transl_table=1 /note="ALLOGRAFT INFLAMMATORY FA '; TEXT TAXON=18 TEXT='AK022845.PE1 CDS /codon_start=1 /db_xref="GOA:Q9BQI0" /db_xref="HGNC:28904" /db_ '; TEXT TAXON=19 TEXT='AK028955.PE1 CDS /codon_start=1 /transl_table=1 /note="IONIZED CALCIUM BINDING A '; TEXT TAXON=20 TEXT='AK045539.PE1 CDS /codon_start=1 /transl_table=1 /note="IONIZED CALCIUM BINDING A '; TEXT TAXON=21 TEXT='AK091912.PE1 CDS /codon_start=1 /db_xref="GOA:Q9BQI0" /db_xref="HGNC:28904" /db_ '; TEXT TAXON=22 TEXT='AL136566.PE1 CDS /codon_start=1 /gene="DKFZp761J191" /product="hypothetical prot '; TEXT TAXON=23 TEXT='AL157938.PE2 CDS /gene="C9orf58" /locus_tag="RP11-544A12.2-001" /standard_name=" '; TEXT TAXON=24 TEXT='AL157938.PE3 CDS /gene="C9orf58" /locus_tag="RP11-544A12.2-003" /standard_name=" '; TEXT TAXON=25 TEXT='AL662801.PE45 CDS /gene="AIF1" /locus_tag="XXbac-BPG296P20.11-001" /standard_nam '; TEXT TAXON=26 TEXT='AL662847.AIF1 CDS /gene="AIF1" /locus_tag="XXbac-BCX270M2.5-001" /standard_name= '; TEXT TAXON=27 TEXT='AL805934.AIF1 CDS /gene="AIF1" /locus_tag="DAQB-195H10.2-001" /standard_name="OT '; TEXT TAXON=28 TEXT='AL833896.PE1 CDS /codon_start=1 /gene="DKFZp761N011" /product="hypothetical prot '; TEXT TAXON=29 TEXT='AL928893.PE3 CDS /locus_tag="RP23-55I14.2-001" /standard_name="OTTMUSP0000001316 '; TEXT TAXON=30 TEXT='AY359067.PE1 CDS /codon_start=1 /locus_tag="UNQ672" /product="SGEL672" /note="PR '; TEXT TAXON=31 TEXT='BA000025.AIF1 CDS /codon_start=1 /transl_table=1 /gene="AIF1" /product="Allograf '; TEXT TAXON=32 TEXT='BC009474.AIF1 CDS /codon_start=1 /gene="AIF1" /product="allograft inflammatory f '; TEXT TAXON=33 TEXT='BC021539.PE1 CDS /codon_start=1 /product="Aif1 protein" /db_xref="GOA:O70200" '; TEXT TAXON=34 TEXT='BC024599.PE1 CDS /codon_start=1 /gene="2810003C17Rik" /product="RIKEN cDNA 28100 '; TEXT TAXON=35 TEXT='BC073304.MGC8069 CDS /codon_start=1 /gene="MGC80699" /product="MGC80699 protein" '; TEXT TAXON=36 TEXT='BC074259.MGC8401 CDS /codon_start=1 /gene="MGC84014" /product="MGC84014 protein" '; TEXT TAXON=37 TEXT='BC084814.MGC8401 CDS /codon_start=1 /gene="MGC84014" /product="MGC84014 protein" '; TEXT TAXON=38 TEXT='BC102890.AIF1 CDS /codon_start=1 /gene="AIF1" /product="allograft inflammatory f '; TEXT TAXON=39 TEXT='BC126840.C9ORF58 CDS /codon_start=1 /gene="C9orf58" /product="ionized calcium bi '; TEXT TAXON=40 TEXT='BX248305.PE3 CDS /gene="AIF1" /locus_tag="DASS-82G15.2-001" /standard_name="OTTH '; TEXT TAXON=41 TEXT='BX571730.PE3 CDS /gene="DKEY-35I22.4" /locus_tag="DKEY-35I22.4-001" /standard_na '; TEXT TAXON=42 TEXT='BX883046.AIF1 CDS /codon_start=1 /gene="Aif1" /product="allograft inflammatory f '; TEXT TAXON=43 TEXT='CR762385.PE3 CDS /gene="DKEY-35I22.4" /locus_tag="DKEY-35I22.4-001" /standard_na '; TEXT TAXON=44 TEXT='CR857925.PE1 CDS /codon_start=1 /gene="DKFZp469A1629" /product="hypothetical pro '; TEXT TAXON=45 TEXT='CT010265 Mus musculus full open reading frame cDNA clone RZPDo836F0551D for gene '; TEXT TAXON=46 TEXT='CT010385 Mus musculus full open reading frame cDNA clone RZPDo836E0453D for gene '; TEXT TAXON=47 TEXT='D86382.IBA1 CDS /transl_table=1 /gene="iba1" /product="Iba1 (ionized calcium bin '; TEXT TAXON=48 TEXT='D86438.IBA1 CDS /codon_start=1 /transl_table=1 /gene="iba1" /product="Iba1 (ioni '; TEXT TAXON=49 TEXT='EF070983.PE1 CDS /codon_start=1 /product="allograft inflammatory factor 1 isofor '; TEXT TAXON=50 TEXT='U17919.PE1 CDS /codon_start=1 /product="allograft inflammatory factor-1" /note=" '; TEXT TAXON=51 TEXT='U19713.PE1 CDS /codon_start=1 /product="allograft-inflammatory factor-1" /db_xre '; TEXT TAXON=52 TEXT='U49392.AIF-1 CDS /codon_start=1 /gene="AIF-1" /product="allograft inflammatory f '; TEXT TAXON=53 TEXT='U82792.PE1 CDS /codon_start=1 /product="allograft inflammatory factor-1" /note=" '; TEXT TAXON=54 TEXT='Y14768.PE3 CDS /gene="AIF1" /product="allograft inflamatory factor-1" /note="U19 '; END; seaview/FL/000755 000765 000000 00000000000 12614160742 013323 5ustar00mgouywheel000000 000000 seaview/least_squares_brl.cxx000644 000765 000024 00000042537 12404325714 017277 0ustar00mgouystaff000000 000000 #include #include #include #include typedef struct noeud2{ struct noeud2 *v1, *v2, *v3; /* neighbors */ double l1, l2, l3; /* actual branch lengths */ double b1, b2, b3; /* bootstrap values */ char* nom; /* name */ } *noeud; typedef struct sbranche{ noeud bout1; noeud bout2; double length; double bootstrap; } *branche; char *least_squares_brl(const char *input_tree, int notu, double **dist, char **names); double* lslgbr(int** btree, int n, double** dist, double* sce, double* totallength); int tree_ctob(char *carbre, char *nom[], int notu, int *barbre[]); int tree_btos(int** arbre_b, int notu, double* lgbi, double* lgbp, double* bootval, char** nom, noeud* arbre_s); noeud create_node(noeud v1, noeud v2, noeud v3, double l1, double l2, double l3, double b1, double b2, double b3, char* nom); int invmat(double** mat, int n, double** invmat); int matmat(double** m1, int nbl1, int nbc1, double** m2, int nbl2, int nbc2, double** prod); int matvect(double** m1, int nbl1, int nbc1, double* v2, int nbl2, double* vprod); double* vectmat(double* v1, int nbc1, double** m2, int nbl2, int nbc2); int retder(int *liste); void aj(int *liste, int nb); noeud bottomnode(noeud nd); void lubksb(double **a, int n, int *indx, double b[]); int rooted(char* carbre); int unroot_c(char* carbre); char *write_unrooted(noeud centre, char *tree); char *write_rooted(noeud centre, noeud from, char *tree); extern int testbit(int *plist, int num); extern void bit1(int *plist, int num); extern void bit0(int *plist, int num); extern int ludcmp(double **a, int n, int *indx, double *d); #define lmot (8*sizeof(int)) char *least_squares_brl(const char *input_tree, int notu, double **dist, char **names) //returns a tree or NULL if error { int **barbre, i, lliste, err; double sce, tot, *newbl, *lgbp, *lgbi; noeud *sarbre; char *tree; tree = strdup(input_tree); lliste=(notu+lmot-1)/lmot; barbre=(int**)calloc(notu, sizeof(int*)); for(i=0;i0.) *sce+=(pdist[i]-cdist[i])*(pdist[i]-cdist[i]); else *sce+=cdist[i]*cdist[i]; } if(totallength){ *totallength=0.; for(i=0;i0.) *totallength+=lgbr[i]; } free(cdist); free(ind1); free(ind2); for(i=0;il3, p2->l3, arg6, p1->b3, p2->b3, arg9, NULL); p1->v3 = arbre_s[notu + cpt1]; p2->v3 = arbre_s[notu + cpt1]; kill_tax[tax1] = kill_bi[j] = 1; notuv--; } /* last node */ for (i = 0; i < 2 * notu - 3; i++) if (arbre_s[i]->v3 == NULL) { n1 = i; break; } for (i = n1 + 1; i < 2 * notu - 3; i++) if (arbre_s[i]->v3 == NULL) { n2 = i; break; } for (i = n2 + 1; i < 2 * notu - 3; i++) if (arbre_s[i]->v3 == NULL) { n3 = i; break; } arbre_s[2 * notu - 3] = create_node(arbre_s[n1], arbre_s[n2], arbre_s[n3], arbre_s[n1]->l3, arbre_s[n2]->l3, arbre_s[n3]->l3, arbre_s[n1]->b3, arbre_s[n2]->b3, arbre_s[n3]->b3, NULL); arbre_s[n1]->v3 = arbre_s[2 * notu - 3]; arbre_s[n2]->v3 = arbre_s[2 * notu - 3]; arbre_s[n3]->v3 = arbre_s[2 * notu - 3]; free(kill_tax); free(kill_bi); return 0; } /* create_node */ /* Return a node (part of a s_tree) whose "parent", "childs" and values are */ /* v1, v2, v3, l1, l2, l3, nom, order. */ noeud create_node(noeud v1, noeud v2, noeud v3, double l1, double l2, double l3, double b1, double b2, double b3, char* nom) { noeud nd; nd = (struct noeud2*) calloc(1, sizeof(struct noeud2)); if (nd==NULL) { printf("Not enough memory.\n"); return NULL; } nd->v1 = v1; nd->v2 = v2; nd->v3 = v3; nd->l1 = l1; nd->l2 = l2; nd->l3 = l3; nd->b1 = b1; nd->b2 = b2; nd->b3 = b3; if (nom!=NULL) nd->nom = strdup(nom); return nd; } /* invmat */ /* Invert square matrix mat(n,n). Result in invmat.*/ /* If mat is singular, 0 is returned (1 otherwise) */ int invmat(double** mat, int n, double** invmat) { int i, j, *indx; double **lu, d, *col; for(i=0;iv3 == NULL) return nd; return (bottomnode(nd->v3)); } /* lubksb */ /* from Numerical Recipes in C */ void lubksb(double **a, int n, int *indx, double b[]) { int i,ii=0,ip,j; double sum; for (i=1;i<=n;i++) { ip=indx[i]; sum=b[ip]; b[ip]=b[i]; if (ii) for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j]; else if (sum) ii=i; b[i]=sum; } for (i=n;i>=1;i--) { sum=b[i]; for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j]; b[i]=sum/a[i][i]; } } /* Return 1 if c_tree carbre is rooted, 0 if unrooted, -1 if problem */ int rooted(char* carbre) { int i=0, cpt=0, cptv=0; while((carbre[i]==' ' || carbre[i]=='\n' || carbre[i]=='\t') && carbre[i]) i++; if(carbre[i]!='[' && carbre[i]!='(') { printf("Tree first char must be ( or [\n"); return -1; } if(carbre[i]=='[') while(carbre[i]!=']' && carbre[i]) i++; if(!carbre[i]){ printf("Unmatched '[' ']'\n"); return -1; } while(carbre[i]!='(' && carbre[i]) i++; if(!carbre[i]) {printf("No initial parenthesis\n"); return -1; } while(carbre[i]!=';' && carbre[i]){ if (carbre[i]=='(') cpt++; if (carbre[i]==')') cpt--; if (carbre[i]==',' && cpt==1) cptv++; i++; } if (cptv==2) return 0; if (cptv==1) return 1; return -1; } /* unroot_c */ /* Remove root from rooted c_tree carbre. */ int unroot_c(char* carbre) { int i=0, diff; while((carbre[i]==' ' || carbre[i]=='\n' || carbre[i]=='\t') && carbre[i]) i++; if(carbre[i]!='[' && carbre[i]!='(') { printf("Tree first char must be ( or [\n"); return -1; } if(carbre[i]=='[') while(carbre[i]!=']' && carbre[i]) i++; if(!carbre[i]){ printf("Unmatched '[' ']'\n"); return -1; } while(carbre[i]!='(' && carbre[i]) i++; if(!carbre[i]) {printf("No initial parenthesis\n"); return -1; } i++; while(carbre[i]!='(' && carbre[i] && carbre[i]!=';') i++; if(!carbre[i] || carbre[i]==';') return 0; carbre[i]=' '; diff=0; while(diff!=-1 && carbre[i] && carbre[i]!=';'){ if(carbre[i]=='(') diff++; if(carbre[i]==')') diff--; i++; } if(!carbre[i] || carbre[i]==';') return 0; carbre[i-1]=' '; while(carbre[i]!=',' && carbre[i]!=')') { carbre[i]=' '; i++; } return 1; } char *write_unrooted(noeud centre, char *tree_start) { char *tree; tree = tree_start; *tree++ = '('; if(centre->v1 == NULL && centre->v2 == NULL) centre = centre->v3; else if(centre->v1 == NULL && centre->v3 == NULL) centre = centre->v2; else if(centre->v2 == NULL && centre->v3 == NULL) centre = centre->v1; tree = write_rooted(centre->v1, centre, tree); sprintf(tree, ":%.5f,", centre->l1); tree += strlen(tree); tree = write_rooted(centre->v2, centre, tree); sprintf(tree, ":%.5f,", centre->l2); tree += strlen(tree); tree = write_rooted(centre->v3, centre, tree); sprintf(tree, ":%.5f);", centre->l3); return tree_start; } char *write_rooted(noeud centre, noeud from, char *tree) { noeud g, d; double lg, ld; if(centre->v1 == from) {g = centre->v2; d = centre->v3; lg = centre->l2; ld = centre->l3; } else if(centre->v2 == from) {g = centre->v1; d = centre->v3; lg = centre->l1; ld = centre->l3; } else {g = centre->v1; d = centre->v2; lg = centre->l1; ld = centre->l2; } if(g == NULL) { strcpy(tree, centre->nom); } else { *tree++ = '('; tree = write_rooted(d, centre, tree); sprintf(tree, ":%.5f,", ld); tree += strlen(tree); tree = write_rooted(g, centre, tree); sprintf(tree, ":%.5f)", lg); } tree += strlen(tree); return tree; } seaview/load_seq.cxx000644 000765 000024 00000060103 12424724501 015340 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include #define ISSEQCHAR(c) (isalpha(c) || c=='-' || c=='*' ) typedef struct { SEA_VIEW *view; Fl_Input *seq_name_field; Fl_Input *seq_field; } view_name_struct; /* included prototypes */ void clear_callback(Fl_Widget *ob, void *data); void refresh_callback(Fl_Widget *ob, void *data); void remove_gaps_callback(Fl_Widget *ob, void *data); void remove_numbers_callback(Fl_Widget *ob, void *data); void to_upcase_callback(Fl_Widget *ob, void *data); void load_seq_callback(void *data); void load_seq_dialog(SEA_VIEW *view); char complement_base(char old); void edit_comments_dialog(SEA_VIEW *view); void edit_sequence_dialog(SEA_VIEW *view); int load_sequence_for_edit(struct editseq *editdata); char *renumber_seq(char *seq); void renumber_callback(Fl_Widget *ob, void *data); void edit_sequence_callback(struct editseq *editdata); void update_comments_callback(void *data); int load_comments(SEA_VIEW *view, Fl_Input *input, Fl_Widget *name); char *cre_consensus(SEA_VIEW *view, char *newname); Fl_Widget *cre_adjusted_button(int x, int y, int *w, int h, const char *label); /* external prototypes */ extern void hide_window_callback(Fl_Widget *ob, void *data); extern void allonge_seqs(char **seq, int totseqs, int maxlen, int *eachlength, int tot_comment_lines, char **comment_line, char **pregion_line); extern int compute_wid_names(SEA_VIEW *view, int totseqs); extern int compute_size_params(SEA_VIEW *view, int force_recompute); extern int calc_max_seq_length(int seq_length, int tot_seqs); void clear_callback(Fl_Widget *ob, void *data) { Fl_Input *seq_input, *seq_name_input; seq_name_input = ((view_name_struct *)data)->seq_name_field; seq_input = ((view_name_struct *)data)->seq_field; seq_input->value(""); if(seq_name_input != NULL) seq_name_input->value(""); } void refresh_callback(Fl_Widget *ob, void *data) { Fl_Input *seq_input; seq_input = ((view_name_struct *)data)->seq_field; seq_input->redraw(); } void remove_gaps_callback(Fl_Widget *ob, void *data) { Fl_Input *seq_input; char *old_seq, *new_seq, *p, *q; size_t lseq; seq_input = (Fl_Input *)data; old_seq = (char *)seq_input->value(); lseq = strlen(old_seq); new_seq = (char *)malloc(lseq+1); if(new_seq == NULL) return; p = old_seq; q = new_seq; while(*p != 0) { if(*p != '-' ) *(q++) = *p; p++; } *q = 0; seq_input->value(new_seq); } void remove_numbers_callback(Fl_Widget *ob, void *data) { Fl_Input *seq_input; char *old_seq, *new_seq, *p, *q; size_t lseq; seq_input = (Fl_Input *)data; old_seq = (char *)seq_input->value(); lseq = strlen(old_seq); new_seq = (char *)malloc(lseq+1); if(new_seq == NULL) return; p = old_seq; q = new_seq; while(*p != 0) { if( ! isdigit(*p) ) *(q++) = *p; p++; } *q = 0; seq_input->value(new_seq); } void to_upcase_callback(Fl_Widget *ob, void *data) { Fl_Input *seq_input = (Fl_Input *)data; char *old_seq = (char *)seq_input->value(); int lseq = strlen(old_seq); char *new_seq = (char *)malloc(lseq+1); if(new_seq == NULL) return; char *p = old_seq; char *q = new_seq - 1; do *(++q) = toupper(*(p++)); while(*q != 0); seq_input->value(new_seq); } void load_seq_callback(void *data) { Fl_Input *seq_name_input, *seq_input; SEA_VIEW *view; char *name, *newseq, *tmp, *p, *q; int lenseq; seq_name_input = ((view_name_struct *)data)->seq_name_field; view = ((view_name_struct *)data)->view; seq_input = ((view_name_struct *)data)->seq_field; name = (char *)seq_name_input->value(); if(strlen(name) == 0) { fl_alert( "`Seq. name' field is empty\nPlease enter a sequence name"); return; } tmp = (char *)seq_input->value(); lenseq = (int)strlen(tmp); newseq = (char *)malloc(lenseq+1); if(newseq == NULL) { fl_alert("Not enough memory"); return; } p = tmp; q = newseq; lenseq = 0; while(*p != 0) { if(*p != ' ' && *p != '\n' && *p != '\t') { if(view->allow_lower) *(q++) = (*p); else *(q++) = toupper(*p); lenseq++; } p++; } *q = 0; add_seq_to_align(view, name, newseq, lenseq); free(newseq); } Fl_Widget *cre_adjusted_button(int x, int y, int *w, int h, const char *label) { Fl_Button *obj; const int lsize = FL_NORMAL_SIZE; fl_font(FL_HELVETICA, lsize); // *w = (int) ( fl_width(label) + 2 * fl_width("R") + 0.5 ); *w = (int) ( fl_width(label) + 10 + 0.5 ); obj = new Fl_Button(x, y, *w, h, label); obj->labelsize(lsize); obj->labelfont(FL_HELVETICA); return (Fl_Widget *)obj; } void load_seq_dialog(SEA_VIEW *view) { Fl_Window *load_form; Fl_Input *seq_input, *seq_name_input; view_name_struct view_name; Fl_Widget *cancel, *add, *obj; int fin, width; load_form = new Fl_Window(490,530); load_form->box(FL_FLAT_BOX); load_form->label("Sequence Loading"); int curr_y = 5; fin = 5; Fl_Group *top = new Fl_Group(fin,curr_y,load_form->w() - 2 * fin, 25); static char label[] = "Seq. name:"; fl_font(FL_HELVETICA, FL_NORMAL_SIZE); width = (int)fl_width(label) + 4 * 2; Fl_Box *name_box = new Fl_Box(FL_UP_BOX, fin, top->y(), width, top->h(), label); name_box->labelsize(FL_NORMAL_SIZE); name_box->box(FL_NO_BOX); fin += width + 5; seq_name_input = new Fl_Input(fin,top->y(),100,top->h(),""); seq_name_input->type(FL_NORMAL_INPUT); fin += seq_name_input->w() + 5; add = cre_adjusted_button(fin,top->y(),&width,top->h(), "Add to alignment"); fin += width + 5; cancel = cre_adjusted_button(fin,top->y(),&width,top->h(), "Cancel"); ((Fl_Button *)cancel)->shortcut(FL_COMMAND | 'w'); fin += width; top->resizable(NULL); top->size(fin - top->x(), top->h()); top->end(); curr_y += top->h() + 15; seq_input = new Fl_Input(top->x(), curr_y, load_form->w() - 2 * top->x(), 450, #if defined(__APPLE__) "" #elif defined(WIN32) "Type sequence or paste it with CRTL-V in panel below" #else "Type or paste sequence with middle mouse button in panel below" #endif ); seq_input->type(FL_MULTILINE_INPUT); seq_input->align(FL_ALIGN_TOP); seq_input->textfont(FL_COURIER); seq_input->textsize(12); fin = top->x(); curr_y += seq_input->h() + 5; Fl_Group *bottom = new Fl_Group(fin, curr_y, top->w(), top->h() ); obj = cre_adjusted_button(fin, curr_y, &width, bottom->h(), "Refresh"); obj->callback(refresh_callback, &view_name); fin += width + 5; obj = cre_adjusted_button(fin, curr_y, &width, bottom->h(), "Clear"); obj->callback(clear_callback, &view_name); fin += width + 5; obj = cre_adjusted_button(fin, curr_y, &width, bottom->h(), "Remove gaps"); obj->callback(remove_gaps_callback, seq_input); fin += width + 5; obj = cre_adjusted_button(fin,curr_y,&width,bottom->h(), "Remove numbers"); obj->callback(remove_numbers_callback, seq_input); fin += width + 5; obj = cre_adjusted_button(fin, curr_y, &width, bottom->h(), "to UPPER"); obj->callback(to_upcase_callback, seq_input); fin += width; bottom->resizable(NULL); bottom->size(fin - bottom->x(), bottom->h()); bottom->end(); load_form->resizable(seq_input); view_name.seq_name_field = seq_name_input; view_name.seq_field = seq_input; load_form->end(); load_form->position((Fl::w() - load_form->w())/2, (Fl::h() - load_form->h())/2); seq_name_input->value(""); seq_input->value(""); view_name.view = view; #if defined(__APPLE__) seq_input->value("\n\n\n\n\n\nType sequence or paste it with cmd-V\n\n\n"); seq_input->position(seq_input->size(), 0); #endif seq_input->take_focus(); load_form->show(); #ifndef MICRO load_form->hotspot(load_form); #endif while (TRUE) { obj = Fl::readqueue(); if (!obj) Fl::wait(); else if(obj == add || obj == cancel || obj == load_form) { if (obj == add) { load_seq_callback(&view_name); } delete load_form; break; } } } int add_seq_to_align(SEA_VIEW *view, char *newname, char *newseq, int lenseq, bool no_gui) /* returns 0 if failed or the rank of newly added sequence */ { int num, *newsel, numset; char **newcol; static char defname[]="newfile"; char **new_s, **new_n, **new_c; if(view->tot_seqs == 0) { view->max_seq_length = lenseq;//the true value is set later in init_dna_scroller } num = view->tot_seqs + 1; if(view->sequence != NULL) new_s = (char **)realloc(view->sequence, num * sizeof(char *)); else new_s = (char **)malloc(num * sizeof(char *)); if(new_s != NULL) view->sequence = new_s; if(view->comments != NULL) { new_c = (char **)realloc(view->comments, num * sizeof(char *)); if(new_c != NULL) view->comments = new_c; else goto nomem; } else view->comments = (char **)calloc(num, sizeof(char *)); if(view->seqname != NULL) new_n = (char **)realloc(view->seqname, num * sizeof(char *)); else new_n = (char **)malloc(num * sizeof(char *)); if(new_n != NULL) view->seqname = new_n; if(new_s == NULL || new_n == NULL) goto nomem; if(lenseq > view->max_seq_length) { view->max_seq_length = calc_max_seq_length(lenseq, view->tot_seqs); allonge_seqs(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, &view->region_line); if (!no_gui) { for (int i = 0; i < view->tot_seqs; i++) free(view->col_rank[i]); free(view->col_rank); view->col_rank = prepcolranks(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); } } if( (view->seqname[num-1] = (char *)malloc(strlen(newname)+1)) == NULL) goto nomem; strcpy(view->seqname[num-1], newname); if(view->comments != NULL) { view->comments[num-1] = NULL; } if( (view->sequence[num-1] = (char *)malloc(view->max_seq_length + 1)) == NULL) goto nomem; memcpy(view->sequence[num-1], newseq, lenseq+1); if(view->masename == NULL && !no_gui) { newname = (char *) fl_input("Name of the new alignment?", ""); if(newname == NULL) newname = defname; } else newname = view->masename; if (view->tot_seqs == 0 && !no_gui) { init_dna_scroller(view, 1, newname, is_a_protein_seq(newseq), NULL); set_seaview_modified(view, TRUE); view->DNA_obj->redraw(); ((Fl_Menu_Item*)view->menu_file + SAVE_AS)->activate(); return 1; } if( (newsel = (int *)malloc(num*sizeof(int))) == NULL) goto nomem; memcpy(newsel, view->each_length, (num-1)*sizeof(int) ); free(view->each_length); view->each_length = newsel; view->each_length[num-1] = lenseq; if (lenseq > view->seq_length && !no_gui) { double x; int l; view->seq_length = lenseq; x = ( (double) view->tot_sites ) / ( view->seq_length + 3 ); if(x>1) x=1; ((Fl_Slider*)view->horsli)->slider_size(x); l = view->seq_length - view->tot_sites+3; if(l<1) l=1; ((Fl_Slider*)view->horsli)->bounds(1,l); } if(view->numb_dnacolors > 1 && !no_gui) { if( (newcol = (char **)malloc(num*sizeof(char *))) == NULL) goto nomem; memcpy(newcol, view->col_rank, (num-1)*sizeof(char *) ); char **tmpcol = prepcolranks(view->sequence+num-1, 1, view->max_seq_length, view->each_length+num-1, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); if(tmpcol == NULL) out_of_memory(); newcol[num-1] = tmpcol[0]; free(tmpcol); free(view->col_rank); view->col_rank = newcol; } if( (newsel = (int *)malloc(num*sizeof(int))) == NULL) goto nomem; if (!no_gui) { memcpy(newsel, view->sel_seqs, (num-1)*sizeof(int) ); free(view->sel_seqs); view->sel_seqs = newsel; view->sel_seqs[num-1] = FALSE; } for(numset = 0; numset < view->numb_species_sets; numset++) { if( (newsel = (int *)malloc(num*sizeof(int))) == NULL) goto nomem; memcpy(newsel, view->list_species_sets[numset], (num-1)*sizeof(int) ); free(view->list_species_sets[numset]); view->list_species_sets[numset] = newsel; view->list_species_sets[numset][num-1] = FALSE; } view->tot_seqs = num; view->cursor_seq = num; view->cursor_site = 1; view->first_site = 1; if (no_gui) return num; if(strlen(view->seqname[num - 1]) > (unsigned)view->wid_names) { view->wid_names = compute_wid_names(view, num); compute_size_params(view, TRUE); } set_seaview_modified(view, TRUE); ((Fl_Slider*)view->horsli)->value(1); set_tot_lines(view, view->tot_lines); view->first_seq = FL_max(num - view->tot_lines + 1, 1); ((Fl_Slider*)view->vertsli)->value(view->first_seq); view->DNA_obj->redraw(); view->vertsli->redraw(); view->horsli->redraw(); return num; nomem: void (*alert)(const char *,...) = no_gui ? Fl::fatal : fl_alert; alert("Not enough memory\nto create the new sequence %s", newname); return 0; } char complement_base(char old) { static char bases[] = "ACGTURYMWSKVHDBacgturymwskvhdb"; static char complement[] = "TGCAAYRKWSMBDHVtgcaayrkwsmbdhv"; char *p; if( (p = strchr(bases, old)) != NULL ) return complement[ p - bases ]; else return old; } void edit_comments_dialog(SEA_VIEW *view) { Fl_Window *comments_form; Fl_Input *comments_input; Fl_Widget *comments_name; view_name_struct comments_data; Fl_Widget *o, *cancel, *apply; Fl_Widget *obj; int fin, width; comments_form = new Fl_Window(490,530); comments_form->label("Comments Editing"); comments_form->box(FL_FLAT_BOX); Fl_Group *top_group = new Fl_Group(5,5,comments_form->w() - 10, 25); fin = 5; apply = cre_adjusted_button(fin,5,&width,25, "Apply"); fin += width + 5; cancel = cre_adjusted_button(fin,5,&width,25,"Cancel"); ((Fl_Button *)cancel)->shortcut(FL_COMMAND | 'w'); fin += width + 5; obj = cre_adjusted_button(fin,5,&width,25,"Refresh"); obj->callback(refresh_callback, &comments_data); fin += width + 5; comments_name = new Fl_Box(FL_DOWN_BOX, fin, 5, top_group->x() +top_group->w() - fin, 25, ""); comments_name->align(FL_ALIGN_LEFT | FL_ALIGN_CLIP | FL_ALIGN_INSIDE); comments_name->labelfont(FL_COURIER); comments_name->labelsize(FL_NORMAL_SIZE); top_group->resizable(comments_name); top_group->end(); comments_input = new Fl_Input(5,35,top_group->w(), comments_form->h() - 5 - 35, ""); comments_input->type(FL_MULTILINE_INPUT); comments_input->textfont(FL_COURIER); comments_input->textsize(12); comments_data.seq_field = comments_input; comments_form->resizable(comments_input); comments_form->end(); comments_form->position( (Fl::w() - comments_form->w())/2, (Fl::h() - comments_form->h())/2 ); comments_data.view = view; if(load_comments(view, comments_input, comments_name)) { delete comments_form; fl_alert("Not enough memory"); return; } comments_input->take_focus(); comments_form->show(); #ifndef MICRO comments_form->hotspot(comments_form); #endif while (TRUE) { o = Fl::readqueue(); if (!o) Fl::wait(); else if (o == apply || o == cancel || o == comments_form) { if (o == apply) { update_comments_callback(&comments_data); } delete comments_form; break; } } } struct editseq { Fl_Multiline_Input *input; Fl_Widget *name; SEA_VIEW *view; int seqnum; }; void edit_sequence_dialog(SEA_VIEW *view) { struct editseq *editdata; int fin, width, num; Fl_Window *form; Fl_Widget *obj, *apply, *cancel; for(num = 0; num tot_seqs; num++) { if(view->sel_seqs[num]) break; } if(num >= view->tot_seqs) return; editdata = (struct editseq *)malloc(sizeof(struct editseq)); if(editdata == NULL) return; editdata->seqnum = num; editdata->view = view; form = new Fl_Window(770,530); form->label("Sequence Editing"); form->box(FL_FLAT_BOX); form->user_data(editdata); Fl_Group *top_group = new Fl_Group(5,5,form->w() - 10, 25); fin = 5; apply = cre_adjusted_button(fin,5,&width,25, "Apply"); fin += width + 5; obj = cre_adjusted_button(fin,5,&width,25,"Renumber"); obj->callback(renumber_callback, 0); fin += width + 5; cancel = cre_adjusted_button(fin,5,&width,25,"Cancel"); ((Fl_Button *)cancel)->shortcut(FL_COMMAND | 'w'); fin += width + 5; editdata->name = new Fl_Box(FL_DOWN_BOX, fin, 5, top_group->x() +top_group->w() - fin, 25, ""); editdata->name->align(FL_ALIGN_LEFT | FL_ALIGN_CLIP | FL_ALIGN_INSIDE); editdata->name->labelfont(FL_COURIER); editdata->name->labelsize(FL_NORMAL_SIZE); top_group->resizable(editdata->name); top_group->end(); editdata->input = new Fl_Multiline_Input(5,35,top_group->w(), form->h() - 5 - 35, ""); editdata->input->type(FL_MULTILINE_INPUT); editdata->input->textfont(FL_COURIER); editdata->input->textsize(12); form->resizable(editdata->input); form->end(); form->position( (Fl::w() - form->w())/2, (Fl::h() - form->h())/2 ); if(load_sequence_for_edit(editdata)) { free(editdata); delete form; fl_alert("Not enough memory"); return; } form->show(); #ifndef MICRO form->hotspot(form); #endif editdata->input->take_focus(); while (TRUE) { obj = Fl::readqueue(); if (!obj) Fl::wait(); else if(obj == apply || obj == cancel || obj == form) { if (obj == apply) { edit_sequence_callback(editdata); } free(editdata); delete form; break; } } } int load_sequence_for_edit(struct editseq *editdata) { char *temp; editdata->name->label(editdata->view->seqname[editdata->seqnum]); editdata->name->redraw(); temp = renumber_seq(editdata->view->sequence[editdata->seqnum]); if(temp == NULL) return TRUE; editdata->input->value(temp); free(temp); editdata->input->position(0); return FALSE; } char *renumber_seq(char *seq) { int l, nl, pos; char *p, *q, *temp; const int w = 100; p = seq - 1; l = 0; while(*(++p) != 0) { if(ISSEQCHAR(*p)) l++; } nl = l / w + 2; temp = (char *)malloc(l + 7 * nl + 100); if(temp == NULL) return NULL; p = seq - 1; q = temp; pos = 0; while(*(++p) != 0) { if( ! ISSEQCHAR(*p)) continue; *q++ = *p; pos++; if(pos % w == 0) { sprintf(q, "%6d\n", pos); q += strlen(q); } } strcpy(q, "\n"); return temp; } void renumber_callback(Fl_Widget *ob, void *data) { char *temp; struct editseq *editdata = (struct editseq *)ob->window()->user_data(); temp = renumber_seq((char *)editdata->input->value()); if(temp == NULL) return; editdata->input->value(temp); free(temp); } void edit_sequence_callback(struct editseq *editdata) { char *p, *newseq, *q, **newcolseq; SEA_VIEW *view; int num, l; view = editdata->view; num = editdata->seqnum; l = strlen( editdata->input->value() ); newseq = (char *)malloc(l + 1); if(newseq == NULL) return; q = newseq; p = (char *)editdata->input->value() - 1; while(*(++p) != 0) { if( ! ISSEQCHAR(*p) ) continue; *(q++) = *p; } *q = 0; l = strlen(newseq); if (l > view->max_seq_length) { view->max_seq_length = calc_max_seq_length(l, view->tot_seqs); allonge_seqs(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, &view->region_line); for (int i = 0; i < view->tot_seqs; i++) free(view->col_rank[i]); free(view->col_rank); view->col_rank = prepcolranks(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); } if(view->numb_gc > 1) { newcolseq = prepcolranks(&newseq, 1, view->max_seq_length, &l, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); if(newcolseq == NULL) return; free(view->col_rank[num]); view->col_rank[num] = newcolseq[0]; free(newcolseq); } strcpy(view->sequence[num], newseq); free(newseq); view->each_length[num] = l; set_seaview_modified(view, TRUE); if(l > view->seq_length) { double x; view->seq_length = l; x = ( (double) view->tot_sites ) / ( view->seq_length + 3 ); if(x>1) x=1; ((Fl_Slider*)view->horsli)->slider_size(x); l = view->seq_length - view->tot_sites+3; if(l<1) l=1; ((Fl_Slider*)view->horsli)->bounds(1,l); } else view->mod_seq = num; view->DNA_obj->redraw(); } void update_comments_callback(void *data) { Fl_Input *comments_input; SEA_VIEW *view; int num, l, num_l; char *temp, *p, *q, *r; view = ((view_name_struct *)data)->view; if(view->comments == NULL) { view->comments = (char **)calloc(view->tot_seqs , sizeof(char *)); if(view->comments == NULL) return; } comments_input = ((view_name_struct *)data)->seq_field; num = comments_input->argument(); num_l = 0; p = (char *)comments_input->value(); l =strlen(p); q = p; while( (q = strchr(q, '\n')) != NULL) { q++; num_l++; } if(p[l - 1] != '\n') num_l++; temp = (char *)malloc(l + num_l + 1); if(temp == NULL) { fl_alert("Not enough memory"); return; } r = temp; do { q = strchr(p, '\n'); if(q == NULL) q = strchr(p, 0) - 1; *(r++) = ';'; memcpy(r, p, q - p + 1); r += q - p + 1; p = q + 1; } while( *p != 0); if( *(r - 1) != '\n') *(r++) = '\n'; *r = 0; if(view->comments[num] != NULL) free(view->comments[num]); view->comments[num] = temp; set_seaview_modified(view, TRUE); } int load_comments(SEA_VIEW *view, Fl_Input *input, Fl_Widget *name) { int num; char *temp, *p, *q, *r; for(num = 0; num tot_seqs; num++) if(view->sel_seqs[num]) break; input->argument( num); name->label(view->seqname[num]); name->redraw(); if( view->comments == NULL || view->comments[num] == NULL) { input->value(""); return FALSE; } temp = (char *)malloc(strlen(view->comments[num]) + 1); if( temp == NULL) return TRUE; r = temp; p = view->comments[num]; do { q = strchr(p, '\n'); memcpy(r, p + 1, q - p); r += q - p; p = q + 1; } while( *p != 0); *r = 0; input->value(temp); free(temp); input->position(0); return FALSE; } char calc_site_consensus(int *freqs, int dernier, int threshold, char *residues, char unknown, int total, int protein, int allowgaps, int iupac) { char retval; int maxi = 0, num, kind, last; maxi = freqs[1]; kind = 1; if(protein) last = dernier; else last = 5; for(num = 2; num < last; num++) { if(freqs[num] > maxi) { maxi = freqs[num]; kind = num; } } if(allowgaps && !protein) { num = dernier - 1;//check if '-' has the highest freq if(freqs[num] > maxi) { maxi = freqs[num]; kind = num; } } if(!protein) { total -= freqs[16];//DNA: don't count uninformative N's for frequency calculation if(total == 0) return 'N'; } float minval = total * (threshold / 100.); if(iupac && !protein ) { // for DNA/RNA with IUPAC codes if( maxi >= minval ) retval = residues[kind - 1]; else if(freqs[1] + freqs[2] + freqs[6] >= minval) retval = 'M';//AC else if(freqs[1] + freqs[3] + freqs[7] >= minval) retval = 'R';//AG else if(freqs[1] + freqs[4] + freqs[5] + freqs[8] >= minval) retval = 'W';//AT(U) else if(freqs[2] + freqs[3] + freqs[9] >= minval) retval = 'S';//CG else if(freqs[2] + freqs[4] + freqs[5] + freqs[10] >= minval) retval = 'Y';//CT(U) else if(freqs[3] + freqs[4] + freqs[5] + freqs[11] >= minval) retval = 'K';//GT(U) else if(freqs[1] + freqs[2] + freqs[3] + freqs[6] + freqs[9] + freqs[7] + freqs[12] >= minval) retval = 'V';//ACG else if(freqs[1] + freqs[2] + freqs[4] + freqs[5] + freqs[6] + freqs[8] + freqs[10] + freqs[13] >= minval) retval = 'H';//ACT(U) else if(freqs[1] + freqs[3] + freqs[4] + freqs[5] + freqs[7] + freqs[8] + freqs[11] + freqs[14] >= minval) retval = 'D';//AGT(U) else if(freqs[2] + freqs[3] + freqs[4] + freqs[5] + freqs[9] + freqs[10] + freqs[11] + freqs[15] >= minval) retval = 'B';//CGT(U) else retval = 'N'; } else { if( maxi >= minval ) retval = residues[kind - 1]; else retval = unknown; } return retval; } char *cre_consensus(SEA_VIEW *view, char *newname) { char *newseq, *p, *residues, unknown; int pos, num, total, kind, dernier, vu; static char dna_residues[]="ACGTUMRWSYKVHDBN-"; static const char prot_residues[] = "EDQNHRKILMVAPSGTFYWC-"; static int freqs[30]; newseq = (char *)malloc(view->seq_length + 1); if(newseq == NULL) return NULL; if(view->protein) { residues = (char *)prot_residues; unknown = 'X'; } else { residues = (char *)dna_residues; unknown = 'N'; } dernier = strlen(residues) + 1; for (pos = 0; pos < view->seq_length; pos++) { vu = total = 0; memset(freqs, 0, dernier * sizeof(int)); for(num = 0; num < view->tot_seqs; num++) { if( !view->sel_seqs[num] ) continue; if(pos >= view->each_length[num]) continue; vu++; if(view->sequence[num][pos] == '-' && ! view->consensus_allowgaps) continue; total++; p = strchr(residues, toupper(view->sequence[num][pos])); if(p == NULL) kind = 0; else kind = p - residues + 1; ++(freqs[kind]); } if(vu == 0) break; if(total == 0) newseq[pos] = '-'; else { newseq[pos] = calc_site_consensus(freqs, dernier, view->consensus_threshold, residues, unknown, total, view->protein, view->consensus_allowgaps, view->consensus_allowiupac); } newseq[pos + 1] = 0; } sprintf(newname, "Consensus%d", view->consensus_threshold); return newseq; } seaview/macos_extras.mm000644 000765 000024 00000052404 12533560062 016056 0ustar00mgouystaff000000 000000 #ifdef __APPLE__ #import #include "seaview.h" #include "pdf_or_ps.h" #include #include #include #include #include #include #include // included functions char *mac_fname_to_roman(const char *in); const char *MG_GetBundleResourcesDir(void); static void file_receive_cb(const char *fname); static void show_apropos(Fl_Widget *, void *unused); void MG_apple_inits(void); void set_seaview_modified(SEA_VIEW *view, int ismodified); void windowmenuitem_callback(Fl_Widget *o, void *data); int find_windowmenuitem(Fl_Window *w); int add_windowmenuitem(const char *name, Fl_Window *w); void rename_windowmenuitem(const char *name, int rank); void delete_windowmenuitem(int rank); char *mac_GetOutputFName_Plus(const char *dfault, const char *message, int, const char *directory); /* extern functions */ extern void hide_window_callback(Fl_Widget *ob, void *data); extern char *get_res_value(const char *name, const char *def_value); extern int printout_block, printout_fontsize; extern int printout_vary, printout_black; extern Fl_Paged_Device::Page_Format printout_pageformat; extern Fl_Paged_Device::Page_Layout printout_layout; extern Fl_Window *use_initial_file(SEA_VIEW *view, char *masename, int doing_dnd); /* globals */ char *mac_fname_to_roman(const char *in) /* passage codage pathname vers codage MacRoman qui est necessaire pour PDFlib/PostScript */ { static char out[250]; CFStringRef mycfs; Boolean ok; /* les pathnames sont codes en UTF8 */ mycfs = CFStringCreateWithCString(NULL, in, kCFStringEncodingUTF8); /* conversion vers MacRoman */ ok = CFStringGetCString(mycfs, out, sizeof(out), kCFStringEncodingMacRoman); CFRelease(mycfs); return (ok ? out : (char *)in); } const char *MG_GetBundleResourcesDir(void) { static char *path = NULL; if (!path) { path = strdup([[[NSBundle mainBundle] resourcePath] UTF8String]); } return path; } static void label(int x, int y, int w, int h, const char *text, NSView *view) { NSRect rect = {{x, y}, {w, h}}; NSTextField *label = [[[NSTextField alloc] initWithFrame:rect] autorelease]; [label setStringValue:[[[NSString alloc] initWithUTF8String:text] autorelease]]; [label setEditable:NO]; [label setSelectable:NO]; [label setBordered:NO]; [label setDrawsBackground:NO]; [view addSubview:label]; } char *mac_GetOutputFName_Plus(const char *dfault, const char *message, int use_only_button, const char *directory) { static char pathname[FL_PATH_MAX]; NSSavePanel *_panel = [NSSavePanel savePanel]; CFStringRef cfs_title; cfs_title = CFStringCreateWithCString(NULL,message,kCFStringEncodingUTF8); [_panel setTitle:(NSString*)cfs_title]; CFRelease(cfs_title); [_panel setNameFieldLabel:@"Output To:"]; NSString *dir = [[NSString alloc] initWithUTF8String:directory]; NSString *preset = [[NSString alloc] initWithUTF8String:dfault]; NSString *fname = [preset lastPathComponent]; NSRect rectview = {{0, 0}, {500, 65} }; NSView *view = [[[NSView alloc] initWithFrame:rectview] autorelease]; //blocksize label(12, 15, 45, 30, "block\nsize:", view); NSRect rectblock = {{50, 20}, {35, 20} }; NSTextField *blockview = [[[NSTextField alloc] initWithFrame:rectblock] autorelease]; [view addSubview:blockview]; [blockview setIntValue:printout_block]; //fontsize label(102, 15, 45, 30, "font\nsize:", view); NSRect rectfont = {{140, 20}, {35, 20} }; NSTextField *fontview = [[[NSTextField alloc] initWithFrame:rectfont] autorelease]; [view addSubview:fontview]; [fontview setIntValue:printout_fontsize]; //color NSRect pdfrect = {{190, -10}, {80, 70} }; NSMatrix *pdfmatrix = [[[NSMatrix alloc] initWithFrame:pdfrect mode:NSRadioModeMatrix cellClass:[NSButtonCell class] numberOfRows:3 numberOfColumns:1] autorelease]; [pdfmatrix setAllowsEmptySelection:NO]; NSSize spacing= {0, 2}; [pdfmatrix setIntercellSpacing:spacing]; NSSize cellsize= {80, 16}; [pdfmatrix setCellSize:cellsize]; NSButton *color = [[[NSButton alloc] init] autorelease]; [color setButtonType:NSRadioButton]; [color setTitle:@"PDF color"]; [pdfmatrix putCell:[color cell] atRow:0 column:0]; NSButton *bw = [[[NSButton alloc] init] autorelease]; [bw setButtonType:NSRadioButton]; [bw setTitle:@"PDF B&W"]; [pdfmatrix putCell:[bw cell] atRow:1 column:0]; NSButton *textfile = [[[NSButton alloc] init] autorelease]; [textfile setButtonType:NSRadioButton]; [textfile setTitle:@"Text File"]; [pdfmatrix putCell:[textfile cell] atRow:2 column:0]; [pdfmatrix selectCell:[bw cell]]; if([pdfmatrix selectedRow] != printout_black) [pdfmatrix selectCellAtRow:printout_black column:0]; [view addSubview:pdfmatrix]; //paper format NSRect paperrect = {{280, -10}, {80, 70} }; NSMatrix *papermatrix = [[[NSMatrix alloc] initWithFrame:paperrect mode:NSRadioModeMatrix cellClass:[NSButtonCell class] numberOfRows:2 numberOfColumns:1] autorelease]; [papermatrix setAllowsEmptySelection:NO]; [papermatrix setIntercellSpacing:spacing]; [papermatrix setCellSize:cellsize]; NSButton *A4 = [[[NSButton alloc] init] autorelease]; [A4 setButtonType:NSRadioButton]; [A4 setTitle:@"A4"]; [papermatrix putCell:[A4 cell] atRow:0 column:0]; NSButton *LETTER = [[[NSButton alloc] init] autorelease]; [LETTER setButtonType:NSRadioButton]; [LETTER setTitle:@"LETTER"]; [papermatrix putCell:[LETTER cell] atRow:1 column:0]; [papermatrix selectCell:[LETTER cell]]; int desired_paper_cell = (printout_pageformat == Fl_Paged_Device::A4 ? 0 : 1); if ([papermatrix selectedRow] != desired_paper_cell) [papermatrix selectCellAtRow:desired_paper_cell column:0]; [view addSubview:papermatrix]; // landscape button NSRect landscaperect = {{280, 6}, {80, 20} }; NSButton *landscape = [[[NSButton alloc] initWithFrame:landscaperect] autorelease]; [landscape setButtonType:NSSwitchButton]; [landscape setTitle:@"landscape"]; [landscape sizeToFit]; [landscape setIntValue:(printout_layout == Fl_Paged_Device::LANDSCAPE)]; [landscape setEnabled:YES]; [view addSubview:landscape]; //variable site button NSRect variablerect = {{360, 30}, {80, 20} }; NSButton *variable = [[[NSButton alloc] initWithFrame:variablerect] autorelease]; [variable setButtonType:NSSwitchButton]; [variable setTitle:@"variable sites only"]; [variable sizeToFit]; [variable setIntValue:printout_vary]; [variable setEnabled:use_only_button]; [view addSubview:variable]; //add accessory view to panel [_panel setAccessoryView:view]; //run panel NSWindow *key = [NSApp keyWindow]; int retval; if (fl_mac_os_version >= 100600) { if (dir) [_panel performSelector:@selector(setDirectoryURL:) withObject:[NSURL fileURLWithPath:dir]]; if (fname) [_panel performSelector:@selector(setNameFieldStringValue:) withObject:fname]; retval = [_panel runModal]; } else { retval = [(id)_panel runModalForDirectory:dir file:fname]; } [key makeKeyWindow]; [preset release]; [dir release]; if ( retval == NSOKButton ) {//read accessory view state printout_block = [blockview intValue]; printout_fontsize = [fontview intValue]; printout_black = [pdfmatrix selectedRow]; printout_pageformat = ([papermatrix selectedRow] == 0 ? Fl_Paged_Device::A4 : Fl_Paged_Device::LETTER); printout_vary = [variable intValue]; printout_layout = [landscape intValue] ? Fl_Paged_Device::LANDSCAPE : Fl_Paged_Device::PORTRAIT; strcpy(pathname, [[[_panel URL] path] UTF8String]); } [_panel setAccessoryView:nil]; if ( retval == NSCancelButton ) return NULL; return pathname; } void windowmenuitem_callback(Fl_Widget *o, void *data) { ((Fl_Window *)data)->show(); const char *c = ((Fl_Window *)data)->xclass(); if(c == NULL) return; if(strcmp(c, SEAVIEW_WINDOW) == 0) { SEA_VIEW *view = (SEA_VIEW *)((Fl_Window *)data)->user_data(); view->DNA_obj->take_focus(); } } int find_windowmenuitem(Fl_Window *w) { const Fl_Menu_Item *items = fl_sys_menu_bar->Fl_Menu_::menu(); int count = fl_sys_menu_bar->Fl_Menu_::size(); for(int i = 1; i < count; i++) { if(items[i].user_data() == w) return i; } return -1; } int add_windowmenuitem(const char *name, Fl_Window *w) //returns rank of new menu item or -1 if error { if(fl_sys_menu_bar == NULL) new Fl_Sys_Menu_Bar(0,0,0,0,NULL); char line[200]; sprintf(line, "Window/%s", name ? name : ""); int val = fl_sys_menu_bar->add(line, 0, windowmenuitem_callback, w); return val; } void rename_windowmenuitem(const char *name, int rank) { fl_sys_menu_bar->replace(rank, name); } void delete_windowmenuitem(int rank) { fl_sys_menu_bar->remove(rank); } static void file_receive_cb(const char *fname) { SEA_VIEW *view; Fl_Window *w = Fl::first_window(); #if 100*FL_MAJOR_VERSION + 10*FL_MINOR_VERSION + FL_PATCH_VERSION <= 131 // without this show() call, the opening of the alignment window is delayed by several seconds. // not needed with FLTK 1.3.2 or above if (fl_mac_os_version >= 100800 && w) w->show(); #endif while(w != NULL) { const char *c = w->xclass(); if(c != NULL && strcmp(c, SEAVIEW_WINDOW) == 0) break; w = Fl::next_window(w); } view = (w != NULL ? (SEA_VIEW *)w->user_data() : NULL); use_initial_file(view, (char *)fname, false); } static void show_apropos(Fl_Widget *w, void *unused) { static Fl_Window *about = NULL; char line[100], *p; FILE *data; static char text[5000]; if(about == NULL) { about = new Fl_Window(600, 450, "About seaview"); Fl_Help_View *br = new Fl_Help_View(1, 1, about->w() - 2, about->h() - 2); Fl_Button *b = new Fl_Button(1, 1, 1, 1, NULL);//only to allow the shortcut b->callback(hide_window_callback, NULL); b->shortcut(FL_COMMAND | 'w'); about->end(); p = get_full_path(get_res_value("helpfile", "seaview.html")); if(p == NULL) return; data = fopen(p, "r"); if(data == NULL) return; p = text; int doit = 0; while(TRUE) { fgets(line, sizeof(line), data); if(strncmp(line, "", 4) == 0) break; if(doit) { strcpy(p, line); p += strlen(p); } } fclose(data); br->value(text); about->resizable(br); } about->show(); } void MG_apple_inits(void) { fl_open_callback(file_receive_cb); fl_mac_set_about(show_apropos, NULL, 0); Fl::set_font(FL_COURIER,"Courier"); Fl::set_font(FL_COURIER_BOLD, (fl_mac_os_version >= 100500 ? "Courier-Bold" : "Courier Bold") ); if (fl_mac_os_version >= 100500) { // it seems that Courier Oblique is not present on older OS Fl::set_font(FL_COURIER_ITALIC,"Courier-Oblique"); Fl::set_font(FL_COURIER_BOLD_ITALIC,"Courier-BoldOblique"); } } void set_seaview_modified(SEA_VIEW *view, int ismodified) { view->modif_but_not_saved = ismodified; [(NSWindow*)(fl_xid(view->dnawin)) setDocumentEdited:ismodified]; } #ifdef USE_PICT class Fl_PICT_Graphics_Driver : public Fl_Graphics_Driver { protected: void rect(int x, int y, int w, int h); void rectf(int x, int y, int w, int h); void line_style(int style, int width, char *dashes=0); void line(int x1, int y1, int x2, int y2); void font(int f, int s); void draw(const char *str, int n, int x, int y); void draw(const char*, int, float, float) ; void draw(int, const char*, int, int, int) ; void rtl_draw(const char*, int, int, int) ; void color(uchar r, uchar g, uchar b); void color(Fl_Color c); void draw_image(const uchar*, int, int, int, int, int, int) ; void draw_image_mono(const uchar*, int, int, int, int, int, int) ; void draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw(Fl_RGB_Image*, int, int, int, int, int, int) ; void draw(Fl_Pixmap*, int, int, int, int, int, int) ; void draw(Fl_Bitmap*, int, int, int, int, int, int) ; double width(const char*, int) ; int height() ; int descent() ; }; void Fl_PICT_Graphics_Driver::draw(const char *txt, int n, int x, int y) { if(txt == NULL || n == 0) return; MoveTo(x, y); unsigned char copy[n + 1]; memcpy(copy+1, txt, n); *copy = n; DrawString(copy); } void Fl_PICT_Graphics_Driver::line(int x, int y, int x1, int y1) { MoveTo(x, y); LineTo(x1, y1); } void Fl_PICT_Graphics_Driver::rect(int x, int y, int w, int h) { MoveTo(x, y); LineTo(x, y+h-1); LineTo(x+w-1, y+h-1); LineTo(x+w-1, y); LineTo(x, y); } void Fl_PICT_Graphics_Driver::rectf(int x, int y, int w, int h) { Rect r; r.top = (short)y; r.left = (short)x; r.bottom = (short)(y+h); r.right = (short)(x+w); PaintRect(&r); } void Fl_PICT_Graphics_Driver::font(int fontrank, int size) { Style mystyle = normal; int macfont, fontstyle; if(fontrank < FL_SYMBOL) { fontstyle = fontrank % 4; fontrank -= fontstyle; } if(fontrank == FL_COURIER) macfont=kFontIDCourier/*22*/; else if(fontrank == FL_HELVETICA) macfont=kFontIDHelvetica/*21*/; else if(fontrank == FL_TIMES) macfont=kFontIDTimes/*20*/; else if(fontrank == FL_SYMBOL) macfont=kFontIDSymbol/*23*/; else macfont=21; if(fontrank < FL_SYMBOL) { if(fontstyle == 0) mystyle = normal; else if(fontstyle == 1) mystyle = bold; else if(fontstyle == 2) mystyle = italic; else if(fontstyle == 3) mystyle = bold+italic; } TextFont(macfont); TextSize(size); TextFace(mystyle); Fl_Display_Device::display_device()->driver()->font(fontrank, size); } void Fl_PICT_Graphics_Driver::color(Fl_Color color) { unsigned char r, g, b; Fl::get_color(color, r, g, b); RGBColor maccolor; maccolor.red = r << 8; maccolor.green = g << 8; maccolor.blue = b << 8; RGBForeColor(&maccolor); } double Fl_PICT_Graphics_Driver::width(const char *txt, int l) { return (double)TextWidth( txt, 0, l ); } void Fl_PICT_Graphics_Driver::draw_image(const uchar*, int, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw_image_mono(const uchar*, int, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw(Fl_RGB_Image*, int, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw(Fl_Pixmap*, int, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::draw(Fl_Bitmap*, int, int, int, int, int, int) {} void Fl_PICT_Graphics_Driver::line_style(int style, int width, char *dashes) {} void Fl_PICT_Graphics_Driver::color(uchar r, uchar g, uchar b) {} void Fl_PICT_Graphics_Driver::rtl_draw(const char*, int, int, int) {} void Fl_PICT_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) {} int Fl_PICT_Graphics_Driver::height() { return Fl_Display_Device::display_device()->driver()->height(); } int Fl_PICT_Graphics_Driver::descent() { return Fl_Display_Device::display_device()->driver()->descent(); } void Fl_PICT_Graphics_Driver::draw(const char* str, int n, float fx, float fy) { draw(str, n, (int)fx, (int)fy); } #endif // USE_PICT Fl_Copy_Surface::Fl_Copy_Surface(bool pict, int w, int h) : Fl_Surface_Device(NULL) { #ifdef USE_PICT use_pict = pict; #else use_pict = false; #endif if (use_pict) { #ifdef USE_PICT Rect myrect; myrect.top=0; myrect.left=0; myrect.right=w; myrect.bottom=h; mypicture = OpenPicture(&myrect); ClipRect(&myrect); PenNormal(); driver(new Fl_PICT_Graphics_Driver()); #endif } else { prepare_copy_pdf_and_pict(w, h); driver(new Fl_Quartz_Graphics_Driver()); oldgc = fl_gc; fl_gc = gc; } } Fl_Copy_Surface::~Fl_Copy_Surface() { if (use_pict) { #ifdef USE_PICT ClosePicture(); MyCopyPictToClipboard(); KillPicture(mypicture); #endif } else { complete_copy_pdf_and_pict(); fl_gc = oldgc; } delete driver(); } size_t Fl_Copy_Surface::MyPutBytes (void* info, const void* buffer, size_t count) { CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count); return count; } #ifdef USE_PICT QDPictRef Fl_Copy_Surface::MyPictToQDPict() { CFIndex pictlen; CGDataProviderRef provider; /* conversion picture to QDPict */ pictlen = GetHandleSize( (Handle) mypicture); HLock( (Handle) mypicture); provider = CGDataProviderCreateWithData (NULL, *mypicture, pictlen, NULL); HUnlock( (Handle) mypicture); if (provider != NULL) { QDPictRef myqdpict = QDPictCreateWithProvider (provider); CFRelease(provider); return myqdpict; } else return NULL; return NULL; } void Fl_Copy_Surface::MyCopyPictToClipboard() { CFDataRef data = NULL; PasteboardRef clipboard = NULL; CFIndex pictlen; QDPictRef myqdpict; pictlen = GetHandleSize( (Handle) mypicture); PasteboardCreate (kPasteboardClipboard, &clipboard); PasteboardClear(clipboard); HLock( (Handle) mypicture); data = CFDataCreate( kCFAllocatorDefault, (UInt8*)*mypicture, pictlen ); HUnlock( (Handle) mypicture); PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, /* kUTTypePICT */ CFSTR("com.apple.pict"), data, kPasteboardFlavorNoFlags ); CFRelease (data); if (fl_mac_os_version < 100400) return; // useful under 10.3 for unclear reason myqdpict = MyPictToQDPict(); CGRect bounds = QDPictGetBounds (myqdpict); init_PDF_context(bounds.size.width, bounds.size.height); if (gc) { /* convert PICT to PDF */ CGContextBeginPage (gc, &bounds); (void) QDPictDrawToCGContext (gc, bounds, myqdpict); CGContextEndPage (gc); CGContextRelease (gc); /* copy PDF to clipboard */ (void) PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, /* kUTTypePDF */ CFSTR("com.adobe.pdf"), pdfdata, kPasteboardFlavorNoFlags); } CFRelease (pdfdata); CFRelease (clipboard); if(myqdpict != NULL) QDPictRelease(myqdpict); } #endif // USE_PICT void Fl_Copy_Surface::init_PDF_context(int w, int h) { CGRect bounds = CGRectMake(0, 0, w, h ); pdfdata = CFDataCreateMutable(NULL, 0); CGDataConsumerRef myconsumer; if (CGDataConsumerCreateWithCFData != NULL) { // true from 10.4 myconsumer = CGDataConsumerCreateWithCFData (pdfdata); } else { static CGDataConsumerCallbacks callbacks = { MyPutBytes, NULL }; myconsumer = CGDataConsumerCreate ((void*) pdfdata, &callbacks); } gc = CGPDFContextCreate (myconsumer, &bounds, NULL); CGDataConsumerRelease (myconsumer); } //next 2 functions copy quartz data to clipboard both as pdf and as tiff bitmap void Fl_Copy_Surface::prepare_copy_pdf_and_pict(int w, int h) { init_PDF_context(w, h); if (gc == NULL) return; CGRect bounds = CGRectMake(0, 0, w, h ); CGContextBeginPage (gc, &bounds); CGContextTranslateCTM(gc, 0, h); CGContextScaleCTM(gc, 1.0f, -1.0f); } void Fl_Copy_Surface::complete_copy_pdf_and_pict() { int w, h; CGContextEndPage (gc); CGContextRelease (gc); PasteboardRef clipboard = NULL; PasteboardCreate (kPasteboardClipboard, &clipboard); PasteboardClear(clipboard); // copy PDF to clipboard PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, CFSTR("com.adobe.pdf"), // kUTTypePDF pdfdata, kPasteboardFlavorNoFlags); //second, transform this PDF to a bitmap image and put it as tiff in clipboard CGDataProviderRef prov; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 if(fl_mac_os_version >= 100400) prov = CGDataProviderCreateWithCFData(pdfdata); // 10.4 else #endif prov = CGDataProviderCreateWithData(NULL, CFDataGetBytePtr(pdfdata), CFDataGetLength(pdfdata), NULL); CGPDFDocumentRef pdfdoc = CGPDFDocumentCreateWithProvider(prov); CGPDFPageRef pdfpage = CGPDFDocumentGetPage(pdfdoc, 1); CGRect clip = CGPDFPageGetBoxRect(pdfpage, kCGPDFCropBox); w = (int)(clip.size.width + 0.5); h = (int)(clip.size.height + 0.5); CGDataProviderRelease(prov); CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); const int scale = 2; w *= scale; h *= scale; void *mem = ( fl_mac_os_version >= 100600 ? NULL : malloc(w * h * 4) ); gc = CGBitmapContextCreate(mem, w, h, 8, w * 4, space, kCGImageAlphaNoneSkipLast ); CFRelease(space); if (gc == NULL) { if (mem) free(mem); CGPDFDocumentRelease(pdfdoc); return; } CGRect rect = CGRectMake(0, 0, w, h); CGContextSetRGBFillColor(gc, 1,1,1,1);//need to clear background CGContextFillRect(gc, rect); CGContextConcatCTM(gc, CGAffineTransformMakeScale(scale, scale)); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 CGContextDrawPDFPage(gc, pdfpage); // 10.3 #endif CGPDFDocumentRelease(pdfdoc); CFRelease(pdfdata); unsigned char *plane = (unsigned char *)CGBitmapContextGetData(gc); NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&plane pixelsWide:w pixelsHigh:h bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:w*4 bitsPerPixel:32]; CFDataRef data = (CFDataRef)[rep TIFFRepresentation]; [rep release]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, CFSTR("public.tiff"), data, kPasteboardFlavorNoFlags ); #endif CFRelease (clipboard); CGContextRelease(gc); if (mem) free(mem); } void mac_tmp_dir_name(char *buffer, int l) { CFStringGetCString((CFStringRef)NSTemporaryDirectory(), buffer, l, kCFStringEncodingUTF8); } #endif //__APPLE__ seaview/Makefile000644 000765 000024 00000003515 12567614277 014511 0ustar00mgouystaff000000 000000 #For Debian compilation, uncomment the 2 lines below #HELPFILE= -DDEFAULT_HELPFILE=\"/usr/share/doc/seaview/seaview.html\" #PHYMLNAME= -DPHYMLNAME=\"phyml\" #to compile with PDF (through PDFlib Lite) rather than PostScript output, # uncomment next 4 lines and adapt next 2 to your local file system #PDF_INC = $(HOME)/PDFlib-Lite-6.0.1/libs #customize by setting to place of pdflib.h #PDF_LIB = $(HOME)/PDFlib-Lite-6.0.1/libs #customize by setting to place of libpdf.* #PDF_PS_FLAGS = -I$(PDF_INC) #LPDF = -L$(PDF_LIB) -lpdf #to use your own, uninstalled FLTK library, #uncomment the next 3 lines and adapt the 1st to your local file system #FLTK = $(HOME)/fltk-1.3 #IFLTK = -I$(FLTK) #CONFIG = $(FLTK)/fltk-config CONFIG ?= fltk-config PDF_PS_FLAGS ?= -DNO_PDF EXTRALIBS = `$(CONFIG) --use-images --ldflags` -ldl -lpthread -lz CC = gcc CXX = g++ CSRC = csrc #DEBUG = -g #OPT = -O0 OPT ?= -O3 SVFLAGS = $(CPPFLAGS) $(CFLAGS) -Dunix $(OPT) -I. $(IFLTK) -I$(CSRC) $(DEBUG) $(HELPFILE) $(PHYMLNAME) $(PDF_PS_FLAGS) OBJECTS = seaview.o custom.o use_mase_files.o regions.o load_seq.o align.o xfmatpt.o \ comlines.o resource.o nexus.o \ viewasprots.o racnuc_fetch.o concatenate.o statistics.o \ trees.o treedraw.o addbootstrap.o least_squares_brl.o \ pseudoterminal.o unrooted.o pdf_or_ps.o svg.o threads.o Fl_Native_File_Chooser_FLTK.o COBJECTS = raa_acnuc.o parser.o md5.o zsockr.o misc_acnuc.o dnapars.o protpars.o seq.o phylip.o lwl.o bionj.o phyml_util.o seaview : $(OBJECTS) $(COBJECTS) $(CXX) -o $@ $(DEBUG) $(LDFLAGS) $(OBJECTS) $(COBJECTS) $(LPDF) $(EXTRALIBS) $(COBJECTS) : $(CSRC)/$< $(CC) -c $(DEBUG) $(OPT) $(CFLAGS) -Dunix -I$(CSRC) $(CSRC)/$*.c Fl_Native_File_Chooser_FLTK.o : FL/Fl_Native_File_Chooser_FLTK.cxx $(CXX) -c -I. $(SVFLAGS) FL/Fl_Native_File_Chooser_FLTK.cxx .SUFFIXES: .c .cxx .h .o .cxx.o : $(CXX) -c $(SVFLAGS) $< seaview/matpt.h000644 000765 000024 00000001660 12404325714 014327 0ustar00mgouystaff000000 000000 #ifndef FD_matpt_h_ #define FD_matpt_h_ #include "seaview.h" typedef struct { Fl_Window *form; Fl_Widget *mat_panel, *ident_type_box, *win_size_type_box, *compute_butt, *x_slider, *y_slider, *region_box, *region_slider, *align_button, *choice_ref_seq, *interrupt_butt; int phys_width; int view_x, view_y; int view_size; int longmax; int seqlong1, seqlong2; int maxseqlength; char *seq1, *seq2; char *seqname1, *seqname2; char *plotname; int margin; int hitx, hity; int region_size; int fenetre, identites; char regionboxtext[300]; char *title; int totsegments; int need_compute; int modif_but_not_saved; double factor, kx, ky; int interrupted; int rect_only; gap_site *gap_sites; int tot_gap_sites; void *seaview_data; int kk, dmin, dmax, flip, *it, centre, *addgaps1, *addgaps2; int seqlong1_nogaps, seqlong2_nogaps; } FD_matpt; typedef struct { int x, y, w, h; } rectangle; #endif /* FD_matpt_h_ */ seaview/nexus.cxx000644 000765 000024 00000112512 12502312116 014705 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include typedef struct _linked_strings { void *data; char *name; struct _linked_strings *next; } linked_strings; /* prototypes of local functions */ int read_nexus_align(char *fname, char ***pseqs, char ***pseqnames, char ***pcomments, char **pheader, char **err_message, list_regions **charsets, int *pnum_species_sets, int ***list_species_sets, char ***name_species_sets, int *ptot_comment_lines, char ***comment_name, char ***comment_line, int **comment_length, int *protein, SEA_VIEW *view); int read_nexus_file(FILE *in, char ***pseqs, int *nchars, int *protein, char ***taxnames, char ***notes, char **header, int *pnum_species_sets, int ***list_species_sets, char ***name_species_sets, list_regions **charsets, int *tot_comment_lines, char ***comment_name, char ***comment_line, int *p_ntrees, char ***p_trees, char ***p_tree_names); int save_nexus_file(const char *fname, int ntaxa, int protein, char **seqs, char **taxnames, char **notes, char *header, int num_species_sets, int **list_species_sets, char **name_species_sets, list_regions *charsets, int tot_comment_lines, char **comment_name, char **comment_line, region *region_used, int *sel_seqs, int tot_sel_seqs, int *eachlength, int tot_trees, char **trees, const Fl_Menu_Item *items); int nextbracket(FILE *in); char *next_token(FILE *in); FILE *is_nexus_file(char *nom); char *next_block_name(FILE *in); int process_block_taxa(FILE *in, char ***taxnames); int is_block_end(char *p); void skip_block(FILE *in); void skip_command(FILE *in); int process_taxa_dim(FILE *in); int process_chars_dim(FILE *in, int *pntaxa); int process_chars_format(FILE *in, int *protein, int *interleave, int *matchchar, int *missing); char **process_taxa_taxlabels(FILE *in, int ntax); char **process_block_characters(FILE *in, int *pntaxa, char ***taxnames, int *nchars, int *protein); char **process_chars_m_interleave(FILE *in, int nsites, int gap, int ntaxa, char **taxnames, int define_taxlabels, int matchchar, int missing, int protein); char **process_chars_matrix(FILE *in, int nsites, int gap, int ntaxa, char **taxnames, int define_taxlabels, int matchchar, int missing, int protein); char **process_block_data(FILE *in, int *pntaxa, char ***ptaxnames, int *nsites, int *protein); char **process_block_notes(FILE *in, int ntaxa, char **taxnames); int find_by_name_num(char *token, int nelt, char **elts); char *build_list(FILE *in, int nelt, char **elts); list_segments *build_list_pairs(FILE *in, int maxi); void process_notes_text(FILE *in, int ntaxa, char **taxnames, char **notes); char *process_sets_taxset(FILE *in, int ntaxa, char **taxnames, char **setname); list_segments *process_sets_charset(FILE *in, char **setname, int max_chars); void process_block_sets(FILE *in, int ntaxa, char **taxnames, int nchars, linked_strings **taxsets, list_regions **charsets); linked_strings *process_block_seaview(FILE *in, char **header); char *process_seaview_text(FILE *in, char **name); char **process_block_unaligned(FILE *in, int *ntaxa, char ***taxnames, int *nchars, int *protein); int process_unal_dim(FILE *in); int process_unal_format(FILE *in); char **process_unal_matrix(FILE *in, int ntaxa, char **taxnames); char *out_with_apostrophe(char *p); char *out_with_optional_protection(char *p); int linked_to_series(linked_strings *linked, char ***names, char ***lines); void out_table_by_series(FILE *out, int *table, int dim); /* used functions */ int output_next_res_from_region(char *seq, int lenseq, list_segments **segment, int *current, FILE *out, int total, int use_dots); int nextbracket(FILE *in) { int pos; pos = fgetc(in); while(pos != ']') { if(pos == EOF) return EOF; if(pos == '[') pos = nextbracket(in); pos = fgetc(in); } return pos; } #define PUNCTUATION "(){}/\\,;:=*\"+-<>" #define APOSTROPHE '\'' char *next_token(FILE *in) { static char *big_token = NULL, *fin_token; int c, punct; char *p, *q; const int slice = 500; static int l_token; if(big_token == NULL) { l_token = slice; big_token = (char *)malloc(l_token); if(big_token == NULL) return NULL; fin_token = big_token + l_token; } do { c = fgetc(in); if(c == '[' ) { c = nextbracket(in); c = fgetc(in);; } if(c == EOF) return NULL; } while(isspace(c)); if(strchr(PUNCTUATION, c) != NULL) { big_token[0] = c; big_token[1] = 0; return big_token; } p = big_token; if(c == APOSTROPHE) { while (1) { c = fgetc(in); if(c == '\r') { punct = fgetc(in); if(punct != '\n') ungetc(punct, in); c = '\n'; } if(c == EOF) break; if(c == APOSTROPHE) { punct = fgetc(in); if(punct != APOSTROPHE) { ungetc(punct, in); break; } } *p = c; p++; if(p >= fin_token) { l_token += slice; q = (char *)realloc(big_token, l_token); if(q == NULL) return NULL; p = q + (p - big_token); big_token = q; fin_token = big_token + l_token; } } *p = 0; return big_token; } do { if(c == '[' ) { c = nextbracket(in); } else { *p = c; p++; if(p >= fin_token) { l_token += slice; q = (char *)realloc(big_token, l_token); if(q == NULL) return NULL; p = q + (p - big_token); big_token = q; fin_token = big_token + l_token; } } c = fgetc(in); punct = FALSE; if(c == EOF) break; punct = (strchr(PUNCTUATION, c) != NULL); } while( ! (isspace(c) || punct) ); *p = 0; if(punct) ungetc(c, in); return big_token; } FILE *is_nexus_file(char *fname) /* return !0 iff seems a NEXUS file */ { FILE *in; char *p; in = fopen(fname, "r"); if(in == NULL) return NULL; p = next_token(in); if(p != NULL) majuscules(p); if(p == NULL || strcmp(p, "#NEXUS") != 0 ) { fclose(in); return NULL; } else return in; } char *next_block_name(FILE *in) { char *p; static char name[81]; do { p = next_token(in); if(p == NULL) return NULL; majuscules(p); } while(strcmp(p, "BEGIN") != 0); p = next_token(in); if(p == NULL) return NULL; majuscules(p); strcpy(name, p); next_token(in); /* skip the ; */ return name; } int is_block_end(char *p) { if(p!=NULL)majuscules(p); return p == NULL || strcmp(p, "END") == 0 || strcmp(p, "ENDBLOCK") == 0; } void skip_command(FILE *in) { char *p; do p = next_token(in); while(p != NULL && *p != ';'); } void skip_block(FILE *in) { char *p; do p = next_token(in); while (!is_block_end(p)); } int process_taxa_dim(FILE *in) { char *p; int ntax = 0; p = next_token(in); if(p == NULL) return 0; majuscules(p); if(strcmp(p, "NTAX") == 0) { next_token(in); p = next_token(in); if(p == NULL) return 0; sscanf(p, "%d", &ntax); } skip_command(in); return ntax; } int process_chars_dim(FILE *in, int *pntaxa) { char *p; int sites = 0; do { p = next_token(in); if(p == NULL) break; majuscules(p); if(strcmp(p, "NCHAR") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; sscanf(p, "%d", &sites); } else if(strcmp(p, "NEWTAXA") == 0) ; else if(strcmp(p, "NTAX") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; sscanf(p, "%d", pntaxa); } } while(*p != ';'); return sites; } int process_chars_format(FILE *in, int *protein, int *interleave, int *matchchar, int *missing) { char *p; int gap=0; *interleave = FALSE; do { p = next_token(in); if(p == NULL) break; majuscules(p); if(strcmp(p, "DATATYPE") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; majuscules(p); *protein = strcmp(p, "PROTEIN") == 0; } else if(strcmp(p, "GAP") == 0) { next_token(in); /* skip = */ do gap = fgetc(in); while(isspace(gap)); if(gap == EOF) break; } else if(strcmp(p, "MATCHCHAR") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; *matchchar = *p; } else if(strcmp(p, "MISSING") == 0) { next_token(in); /* skip = */ do *missing = fgetc(in); while(isspace(*missing)); if(*missing == EOF) break; } else if(strcmp(p, "INTERLEAVE") == 0) { *interleave = TRUE; } } while(*p != ';'); return gap; } char **process_taxa_taxlabels(FILE *in, int ntax) { char *p, **names; int i; names = (char **)malloc(ntax * sizeof(char *)); if(names == NULL) ntax = 0; for(i = 0; i < ntax; i++) names[i] = NULL; for(i = 0; i < ntax; i++) { p = next_token(in); if(p == NULL) break; if(*p == ';') break; names[i] = (char *)malloc(strlen(p)+1); if(names[i] == NULL) break; strcpy(names[i], p); } if(p != NULL && *p != ';') skip_command(in); return names; } int process_block_taxa(FILE *in, char ***taxnames) { char *p; int ntax = 0; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "DIMENSIONS") == 0) ntax = process_taxa_dim(in); else if(strcmp(p, "TAXLABELS") == 0) *taxnames = process_taxa_taxlabels(in, ntax); else skip_command(in); } return ntax; } int find_by_name_num(char *token, int nelt, char **elts) { int num; for(num = 0; num < nelt; num++) { if(strcmp(token, elts[num]) == 0) return num; } if(num >= nelt) {num = -1; sscanf(token, "%d", &num); num--; } if(num < 0 || num >= nelt) num = -1; return num; } char *build_list(FILE *in, int nelt, char **elts) { char *p, *list; int num, previous = -1, need_range = FALSE, i; list = (char *)malloc(nelt + 1); if(list == NULL) { skip_command(in); return NULL; } memset(list, '0', nelt); list[nelt] = 0; while(TRUE) { p = next_token(in); if(p == NULL || *p == ';') break; if(strcmp(p, "-") == 0) { if(previous >= 0) need_range = TRUE; continue; } if(strcmp(p, ".") == 0) num = nelt - 1; else num = find_by_name_num(p, nelt, elts); if(num == -1) continue; list[num] = '1'; if(need_range) { for(i = previous + 1; i < num; i++) list[i] = '1'; need_range = FALSE; } previous = num; } return list; } list_segments *build_list_pairs(FILE *in, int maxi) { char *p; list_segments *list = NULL, *next, *elt; int num, previous = -1, need_range = FALSE, debut, fin; while(TRUE) { p = next_token(in); if(p == NULL || *p == ';') break; if(strcmp(p, "-") == 0) { if(previous >= 0) need_range = TRUE; continue; } if(strcmp(p, ".") == 0) num = maxi; else if(strcmp(p, "\\") == 0) { /* process syntax: from-to\step */ p = next_token(in); if(p == NULL) return NULL; num = -1; sscanf(p, "%d", &num); /* num has the step value */ if(num == -1 || list == NULL) { skip_command(in); return NULL; } debut = next->debut; fin = next->fin; next->fin = debut; debut += num; while(debut <= fin) { elt = (list_segments *)malloc(sizeof(list_segments)); if(elt == NULL) { skip_command(in); return NULL; } elt->debut = elt->fin = debut; elt->next = NULL; next->next = elt; next = elt; debut += num; } continue; } else {num = -1; sscanf(p, "%d", &num); } if(num == -1) { skip_command(in); return NULL; } if(need_range) { next->fin = num; need_range = FALSE; } else { elt = (list_segments *)malloc(sizeof(list_segments)); if(elt == NULL) { skip_command(in); return NULL; } elt->debut = elt->fin = num; elt->next = NULL; if(list == NULL) list = elt; else next->next = elt; next = elt; } previous = num; } return list; } char **process_chars_m_interleave(FILE *in, int nsites, int gap, int ntaxa, char **taxnames, int define_taxlabels, int matchchar, int missing, int protein) { int num, c, newtaxa = 0; char *p, **seq; seq = (char **)malloc(ntaxa * sizeof(char *)); if(seq == NULL) { skip_command(in); return NULL;} for(num = 0; num < ntaxa; num++) seq[num] = NULL; while(TRUE) { p = next_token(in); if(p == NULL || *p == ';') break; if(define_taxlabels) { if(newtaxa >= ntaxa) { num = find_by_name_num(p, ntaxa, taxnames); } else { taxnames[newtaxa] = (char *)malloc(strlen(p) + 1); if(taxnames[newtaxa] == NULL) num = -1; else { strcpy(taxnames[newtaxa], p); num = newtaxa++; } } } else num = find_by_name_num(p, ntaxa, taxnames); if(num == -1) { /* bad format */ skip_command(in); free(seq); return NULL; } if(seq[num] == NULL) { seq[num] = (char *)malloc(nsites + 1); if(seq[num] == NULL) { skip_command(in); free(seq); return NULL; } seq[num][0] = 0; } p = seq[num]; p += strlen(p); while(TRUE) { c = fgetc(in); if(c == ';' || c == '\n' || c == '\r' || c == EOF) break; if(isspace(c)) continue; if(c == gap) c = '-'; if(p - seq[num] < nsites) *(p++) = c; } *p = 0; } if(matchchar != 0) { for(num = 1; num < ntaxa; num++) { p = seq[num] - 1; while(*(++p) != 0) if(*p == matchchar) *p = seq[0][p - seq[num]]; } } /* if(missing != 0) { char miss_char = (protein ? 'X' : 'N'); for(num = 0; num < ntaxa; num++) { p = seq[num] - 1; while(*(++p) != 0) if(*p == missing) *p = miss_char; } } */ return seq; } char **process_chars_matrix(FILE *in, int nsites, int gap, int ntaxa, char **taxnames, int define_taxlabels, int matchchar, int missing, int protein) { int num, c, newtaxa = 0, offset; char *p, **seq; seq = (char **)calloc(ntaxa , sizeof(char *)); if(seq == NULL) { skip_command(in); return NULL;} for(num = 0; num < ntaxa; num++) seq[num] = NULL; while(TRUE) { p = next_token(in); if(p == NULL || *p == ';') break; if(define_taxlabels) { if(newtaxa >= ntaxa) num = -1; else { taxnames[newtaxa] = (char *)malloc(strlen(p) + 1); if(taxnames[newtaxa] == NULL) num = -1; else { strcpy(taxnames[newtaxa], p); num = newtaxa++; } } } else { offset = 0; do {/* handle repetitions of names */ num = find_by_name_num(p, ntaxa - offset, taxnames + offset); if(num != -1) num += offset; offset = num + 1; } while(num != -1 && seq[num] != NULL); } if(num == -1) { /* bad format */ skip_command(in); free(seq); return NULL; } seq[num] = (char *)malloc(nsites + 1); if(seq[num] == NULL) { skip_command(in); free(seq); return NULL;} p = seq[num]; do { c = fgetc(in); if(c == ';' || c == EOF) break; if(c == '[') { c = nextbracket(in); if(c == EOF) break; continue; } if(isspace(c)) continue; if(c == gap) c = '-'; *(p++) = c; } while(p < seq[num] + nsites); *p = 0; if(c == ';' || c == EOF) break; } for(num = 0; num < ntaxa; num++) { if(seq[num] == NULL) { seq[num] = (char *)malloc(1); if(seq[num] == NULL) { free(seq); return NULL;} seq[num][0] = 0; } } if(matchchar != 0) { for(num = 1; num < ntaxa; num++) { p = seq[num] - 1; while(*(++p) != 0) if(*p == matchchar) *p = seq[0][p - seq[num]]; } } /* if(missing != 0) { char miss_char = (protein ? 'X' : 'N'); for(num = 0; num < ntaxa; num++) { p = seq[num] - 1; while(*(++p) != 0) if(*p == missing) *p = miss_char; } } */ return seq; } char **process_block_data(FILE *in, int *pntaxa, char ***ptaxnames, int *nsites, int *protein) { char **seqs, **taxnames, *p; int gap=0, interleave = FALSE, matchchar = 0, missing = 0; seqs = NULL; *nsites = 0; taxnames = NULL; *pntaxa = 0; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "DIMENSIONS") == 0) { *nsites = process_chars_dim(in, pntaxa); if(*pntaxa > 0) taxnames = (char **)malloc(*pntaxa * sizeof(char *)); if(*pntaxa > 0 && taxnames == NULL) { *pntaxa = 0; seqs = NULL; skip_block(in); break; } } else if(strcmp(p, "FORMAT") == 0) gap = process_chars_format(in, protein, &interleave, &matchchar, &missing); else if(strcmp(p, "MATRIX") == 0) { if(interleave) seqs = process_chars_m_interleave(in, *nsites, gap, *pntaxa, taxnames, TRUE, matchchar, missing, *protein); else seqs = process_chars_matrix(in, *nsites, gap, *pntaxa, taxnames, TRUE, matchchar, missing, *protein); } else skip_command(in); } *ptaxnames = taxnames; return seqs; } char **process_block_characters(FILE *in, int *pntaxa, char ***taxnames, int *nsites, int *protein) { char *p, **seqs; int interleave=0, gap, matchchar = 0, missing = 0; seqs = NULL; *nsites = 0; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "DIMENSIONS") == 0) *nsites = process_chars_dim(in, pntaxa); else if(strcmp(p, "FORMAT") == 0) gap = process_chars_format(in, protein, &interleave, &matchchar, &missing); else if(strcmp(p, "TAXLABELS") == 0) *taxnames = process_taxa_taxlabels(in, *pntaxa); else if(strcmp(p, "MATRIX") == 0) { if(interleave) seqs = process_chars_m_interleave(in, *nsites, gap, *pntaxa, *taxnames, FALSE, matchchar, missing, *protein); else seqs = process_chars_matrix(in, *nsites, gap, *pntaxa, *taxnames, FALSE, matchchar, missing, *protein); } else skip_command(in); } return seqs; } char **process_block_notes(FILE *in, int ntaxa, char **taxnames) { char *p, **notes; int num; /* notes[0 - ntaxa[ comments des seqs indiv */ notes = (char **)malloc(ntaxa * sizeof(char *)); if(notes == NULL) {skip_block(in); return NULL; } for(num = 0; num < ntaxa; num++) notes[num] = NULL; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "TEXT") == 0) process_notes_text(in, ntaxa, taxnames, notes); else skip_command(in); } return notes; } char *process_sets_taxset(FILE *in, int ntaxa, char **taxnames, char **setname) { char *p, *set = NULL; p = next_token(in); if(p != NULL) *setname = (char *)malloc(strlen(p) + 1); if( p == NULL || *setname == NULL) { skip_command(in); return NULL; } strcpy(*setname, p); next_token(in); /* skip = */ set = build_list(in, ntaxa, taxnames); return set; } list_segments *process_sets_charset(FILE *in, char **setname, int max_chars) { char *p; p = next_token(in); if(p != NULL) *setname = (char *)malloc(strlen(p) + 1); if( p == NULL || *setname == NULL) { skip_command(in); return NULL; } strcpy(*setname, p); next_token(in); /* skip = */ return build_list_pairs(in, max_chars); } int process_translate(FILE *in, char ***ptaxnames) { char *p, **taxnames; int rank; taxnames = (char **) malloc(10000*sizeof(char*)); while (TRUE) { p = next_token(in); if (*p == ',') continue; if (*p == ';') break; sscanf(p, "%d", &rank); p = next_token(in); taxnames[rank - 1] = strdup(p); } taxnames = (char **)realloc(taxnames, rank * sizeof(char*)); *ptaxnames = taxnames; return rank; } char *replace_ranks_by_names(char *tree, int ntaxa, char **taxnames) { char *p = tree, *q, *r; char *newtree; char bootstrap_comment[50]; int rank, l; float pp; l = strlen(tree); for (int i = 0; i < ntaxa; i++) { l += strlen(taxnames[i]); } newtree = (char*)malloc(l); q = newtree; while (TRUE) { if (*p == ';') break; if (*p == '[') { // skip comments do p++; while (*p != ']'); p++; continue; } if (*p == ')' && *(p+1) == '[') { // a comment with a PP value *q++ = *p++; r = bootstrap_comment; do { *r = *p++; if ((unsigned)(r - bootstrap_comment) < sizeof(bootstrap_comment) - 1) r++; } while (*p != ']'); p++; *r = 0; if ( strncmp(bootstrap_comment, "[&prob=", 7) == 0) { sscanf(bootstrap_comment + 7, "%f", &pp); sprintf(q, "%.2f", pp); q += strlen(q); } continue; } if ( (*p == '(' || *p == ',') && isdigit(*(p+1))) { // a taxon rank is found *q++ = *p++; sscanf(p, "%d", &rank); sprintf(q, "%s", taxnames[rank - 1]); q += strlen(q); p++; while (isdigit(*p)) p++; continue; } *q++ = *p++; } *q++ = ';'; *q = 0; free(tree); newtree = (char *)realloc(newtree, (q - newtree) + 1); return newtree; } int process_block_trees(FILE *in, char ***ptrees, char ***pnames) { char **trees, **names, **taxnames; char *p, c; int maxi = 5, ntaxa = 0; trees = (char **)calloc(maxi, sizeof(char *)); names = (char **)calloc(maxi, sizeof(char *)); int count = 0; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "TRANSLATE") == 0) { ntaxa = process_translate(in, &taxnames); } if(strcmp(p, "TREE") == 0) { if(count >= maxi) { maxi += 5; trees = (char **)realloc(trees, maxi * sizeof(char *)); names = (char **)realloc(names, maxi * sizeof(char *)); } names[count] = strdup(next_token(in)); next_token(in); //skip = while ( isspace(c=fgetc(in)) ) ; // skip white space trees[count] = (char *)malloc(500000); p = trees[count]; do { *p++ = c; // first char (can be '[' for tree header) while(TRUE) { *p = fgetc(in); if(*p == '\n' || *p == '\r') continue; if(*p++ == ';') break; } do c = fgetc(in); while (isspace(c)); } while (c == '(' || c == '['); ungetc(c, in); *p = 0; trees[count] = (char *)realloc(trees[count] , p - trees[count] + 1); if (ntaxa > 0) trees[count] = replace_ranks_by_names(trees[count], ntaxa, taxnames); count++; } } trees = (char **)realloc(trees, count * sizeof(char *)); names = (char **)realloc(names, count * sizeof(char *)); *ptrees = trees; *pnames = names; if (ntaxa > 0) { for (int i = 0; i < ntaxa; i++) free(taxnames[i]); free(taxnames); } return count; } void process_block_sets(FILE *in, int ntaxa, char **taxnames, int max_chars, linked_strings **taxsets, list_regions **charsets) { char *p, *set, *setname; list_segments *limits; linked_strings *chain_tax = *taxsets, *elt; list_regions *elt_reg, *chain_char = *charsets, *end_chain; region *maregion; end_chain = chain_char; if(end_chain != NULL) while(end_chain->next != NULL) end_chain = end_chain->next; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "TAXSET") == 0 && ( set = process_sets_taxset(in, ntaxa, taxnames, &setname)) != NULL ) { elt = (linked_strings *)malloc(sizeof(linked_strings)); if(elt != NULL) { elt->data = (void *)set; elt->name = setname; elt->next = chain_tax; chain_tax = elt; } } else if(strcmp(p, "CHARSET") == 0 && (limits = process_sets_charset(in, &setname, max_chars)) != NULL) { maregion = (region *)calloc(1, sizeof(region)); elt_reg = (list_regions *)malloc(sizeof(list_regions)); if(maregion != NULL && elt_reg != NULL) { maregion->list = limits; maregion->name = setname; elt_reg->element = maregion; elt_reg->next = NULL; if(end_chain != NULL) end_chain->next = elt_reg; else chain_char = elt_reg; end_chain = elt_reg; } } else skip_command(in); } *taxsets = chain_tax; *charsets = chain_char; return; } void process_notes_text(FILE *in, int ntaxa, char **taxnames, char **notes) { char *p, *q; int num, count; num = -1; do { p = next_token(in); if(p == NULL) break; majuscules(p); if(strcmp(p, "TAXON") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; num = find_by_name_num(p, ntaxa, taxnames); if(num == -1) { skip_command(in); break; } } else if(strcmp(p, "TEXT") == 0) { if(num == -1) { skip_command(in); break; } next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; q = p; count = 0; while( (q = strchr(q, '\n')) != NULL) { count++; q++; } notes[num] = (char *)malloc(strlen(p) + 5 + count); if(notes[num] != NULL) { q = notes[num]; *q = ';'; q++; while(*p != 0) { *q = *p; if(*p == '\n' && *(p+1) != 0) *(++q) = ';'; q++; p++; } *q = 0; } } } while(*p != ';'); } linked_strings *process_block_seaview(FILE *in, char **header) { char *p, *q, *name, *text; int count; linked_strings *chain = NULL, *elt; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "TEXT") == 0 ) { text = process_seaview_text(in, &name); if(text == NULL) continue; if(name == NULL) { /* text contains a header: add ;; at start of lines */ q = text; count = 0; while( (q = strchr(q, '\n')) != NULL) { count++; q++; } *header = (char *)malloc(strlen(text) + 5 + 2 * count); if(*header != NULL) { q = *header; p = text; *q = ';'; q++; *q = ';'; q++; while(*p != 0) { *q = *p; if(*p == '\n' && *(p+1) != 0) { *(++q) = ';'; *(++q) = ';'; } q++; p++; } *q = 0; } } else { /* text contains a footer */ /* remove line breaks from footer */ p = text; q = (char *)malloc(strlen(p) + 1); elt = (linked_strings *)malloc(sizeof(linked_strings)); if(q != NULL && elt != NULL) { elt->data = (void *)q; do { if(*p != '\n' && *p != '\r') *(q++)= *p; } while (*(p++) != 0); elt->name = name; elt->next = chain; chain = elt; } } free(text); } else skip_command(in); } return chain; } char *process_seaview_text(FILE *in, char **name) { char *p, *text = NULL; *name = NULL; do { p = next_token(in); if(p == NULL) break; majuscules(p); if(strcmp(p, "FOOTER") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; *name = (char *)malloc(strlen(p) + 1); if(*name == NULL) { skip_command(in); return NULL; } strcpy(*name, p); } else if(strcmp(p, "HEADER") == 0) { *name = NULL; } else if(strcmp(p, "TEXT") == 0) { next_token(in); /* skip = */ p = next_token(in); if(p == NULL) break; text = (char *)malloc(strlen(p) + 1); if(text != NULL) strcpy(text, p); } } while(*p != ';'); return text; } char **process_block_unaligned(FILE *in, int *ntaxa, char ***taxnames, int *nsites, int *protein) { char *p, **seqs = NULL; int i, l, max_l; *protein = FALSE; while(TRUE) { p = next_token(in); if(is_block_end(p)) break; if(strcmp(p, "DIMENSIONS") == 0) *ntaxa = process_unal_dim(in); else if(strcmp(p, "FORMAT") == 0) *protein = process_unal_format(in); else if(strcmp(p, "TAXLABELS") == 0) *taxnames = process_taxa_taxlabels(in, *ntaxa); else if(strcmp(p, "MATRIX") == 0) { seqs = process_unal_matrix(in, *ntaxa, *taxnames); } else skip_command(in); } l = max_l = 0; for(i = 0; seqs != NULL && i < *ntaxa; i++) { if(seqs[i] != NULL) l = strlen(seqs[i]); if(l > max_l) max_l = l; } *nsites = max_l; return seqs; } int process_unal_dim(FILE *in) { char *p; int number = 0; p = next_token(in); if(p!=NULL)majuscules(p); if(p == NULL || strcmp(p, "NEWTAXA") != 0) { skip_command(in); return 0; } p = next_token(in); if(p!=NULL)majuscules(p); if(p == NULL || strcmp(p, "NTAX") != 0) { skip_command(in); return 0; } next_token(in); /* skip = */ p = next_token(in); if(p != NULL) sscanf(p, "%d", &number); if(number <= 0) number = 0; if(p != NULL && *p != ';') skip_command(in); return number; } int process_unal_format(FILE *in) { char *p; int protein = 0; p = next_token(in); if(p!=NULL)majuscules(p); if(p == NULL || strcmp(p, "DATATYPE") != 0) { skip_command(in); return 0; } next_token(in); /* skip = */ p = next_token(in); if(p!=NULL)majuscules(p); if(p != NULL) protein = (strcmp(p, "PROTEIN") == 0); if(p != NULL && *p != ';') skip_command(in); return protein; } char **process_unal_matrix(FILE *in, int ntaxa, char **taxnames) { int num, c, lseq; char *p, **seq, *q; const int block = 5000; seq = (char **)malloc(ntaxa * sizeof(char *)); if(seq == NULL) { skip_command(in); return NULL;} for(num = 0; num < ntaxa; num++) seq[num] = NULL; while(TRUE) { p = next_token(in); if(p == NULL) break; num = find_by_name_num(p, ntaxa, taxnames); if(num == -1) { /* bad format */ skip_command(in); return seq; } lseq = 0; p = seq[num]; while(TRUE) { c = fgetc(in); if(c == ';' || c == ',' || c == EOF) break; if(isspace(c)) continue; if(p >= seq[num] + lseq) { lseq += block; q = (char *)malloc(lseq + 1); if(q == NULL) { skip_command(in); free(seq); return NULL; } if(p > seq[num]) memcpy(q, seq[num], p - seq[num]); p = q + (p - seq[num]); if(seq[num] != NULL) free(seq[num]); seq[num] = q; } *(p++) = c; } *p = 0; if(c == ';' || c == EOF) break; } return seq; } int read_nexus_align(char *fname, char ***pseqs, char ***pseqnames, char ***pcomments, char **pheader, char **err_message, list_regions **charsets, int *pnum_species_sets, int ***list_species_sets, char ***name_species_sets, int *ptot_comment_lines, char ***comment_name, char ***comment_line, int **comment_length, int *protein, SEA_VIEW *view) { FILE *in; int lseqs, i, tot, tot_trees = 0; char **tree_names, **trees = NULL; if( (in = is_nexus_file(fname) ) == NULL) { *err_message = (char *)"not a NEXUS file"; return 0; } tot = read_nexus_file(in, pseqs, &lseqs, protein, pseqnames, pcomments, pheader, pnum_species_sets, list_species_sets, name_species_sets, charsets, ptot_comment_lines, comment_name, comment_line, &tot_trees, &trees, &tree_names); if(tot == 0 && tot_trees == 0) { *err_message = (char *)"format error"; return 0; } for(i = 0; i < tot_trees; i++) { view->menu_trees->add(tree_names[i], trees_callback, NULL, 0); int rank = view->menu_trees->vlength(); (view->menu_trees->vitem(rank - 1))->labelfont(FL_HELVETICA_ITALIC); free(tree_names[i]); } if(tot_trees > 0) { free(tree_names); view->trees = (char**)realloc(view->trees, (view->tot_trees + tot_trees) * sizeof(char*)); memcpy(view->trees + view->tot_trees, trees, tot_trees * sizeof(char*)); } view->tot_trees += tot_trees; if(*pcomments == NULL) { *pcomments = (char **)calloc(tot, sizeof(char *)); } if(*ptot_comment_lines > 0) { *comment_length = (int *)malloc(*ptot_comment_lines * sizeof(int)); if(*comment_length == NULL) *ptot_comment_lines = 0; for(i = 0; i < *ptot_comment_lines; i++) (*comment_length)[i] = strlen((*comment_line)[i]); } return tot; } int read_nexus_file(FILE *in, char ***pseqs, int *nchars, int *protein, char ***taxnames, char ***notes, char **header, int *pnum_species_sets, int ***list_species_sets, char ***name_species_sets, list_regions **charsets, int *tot_comment_lines, char ***comment_name, char ***comment_line, int *p_ntrees, char ***p_trees, char ***p_tree_names) { char *p, **seqs = NULL; linked_strings *footers, *taxsets, *tmplist; int ntaxa, count, num; ntaxa = *nchars = *tot_comment_lines = *pnum_species_sets = 0; *protein = FALSE; *taxnames = *notes = NULL; *header = NULL; taxsets = footers = NULL; *charsets = NULL; *name_species_sets = NULL; *list_species_sets = NULL; while(TRUE) { p = next_block_name(in); if(p == NULL) break; if(strcmp(p, "TAXA") == 0) ntaxa = process_block_taxa(in, taxnames); else if(strcmp(p, "CHARACTERS") == 0) seqs = process_block_characters(in, &ntaxa, taxnames, nchars, protein); else if(strcmp(p, "UNALIGNED") == 0) seqs = process_block_unaligned(in, &ntaxa, taxnames, nchars, protein); else if(strcmp(p, "DATA") == 0) seqs = process_block_data(in, &ntaxa, taxnames, nchars, protein); else if(strcmp(p, "NOTES") == 0) *notes = process_block_notes(in, ntaxa, *taxnames); else if(strcmp(p, "SETS") == 0) process_block_sets(in, ntaxa, *taxnames, *nchars, &taxsets, charsets); else if(strcmp(p, "TREES") == 0) *p_ntrees = process_block_trees(in, p_trees, p_tree_names); else if(strcmp(p, "SEAVIEW") == 0) footers = process_block_seaview(in, header); else skip_block(in); } fclose(in); if(seqs == NULL) { *pseqs = NULL; if(*taxnames != NULL) for(num = 0; num < ntaxa; num++) if((*taxnames)[num] != NULL) free((*taxnames)[num]); return 0; } if(footers != NULL) *tot_comment_lines = linked_to_series(footers, comment_name, comment_line); count = 0; tmplist = taxsets; while(tmplist != NULL) { tmplist = tmplist->next; count++; } if(count > 0) { *name_species_sets = (char **)malloc(count * sizeof(char *)); if(*name_species_sets == NULL) count = 0; *list_species_sets = (int **)malloc(count * sizeof(int *)); if(*list_species_sets == NULL) count = 0; else { for(num = 0; num < count; num++) { (*list_species_sets)[num] = (int *)calloc(ntaxa, sizeof(int)); if((*list_species_sets)[num] == NULL) count = 0; } } if(count == 0) taxsets = NULL; } *pnum_species_sets = count; while(taxsets != NULL) { count--; (*name_species_sets)[count] = taxsets->name; p = (char *)taxsets->data - 1; while( (p = strchr(p + 1, '1')) != NULL) { num = p - (char *)taxsets->data; (*list_species_sets)[count][num] = TRUE; } free(taxsets->data); tmplist = taxsets; taxsets = taxsets->next; free(tmplist); } *pseqs = seqs; return ntaxa; } int linked_to_series(linked_strings *linked, char ***names, char ***lines) { int i, count = 0; linked_strings *elt, *old; elt = linked; while(elt != NULL) { count++; elt = elt->next; } *names = (char **)malloc(count *sizeof(char *)); *lines = (char **)malloc(count *sizeof(char *)); if(*names == NULL || *lines == NULL) return 0; elt = linked; i = count; while(elt != NULL) { i--; (*names)[i] = elt->name; (*lines)[i] = (char *)elt->data; old = elt; elt = elt->next; free(old); } return count; } char *out_with_apostrophe(char *p) { static char out[1000]; char *q = out; if (p == NULL) return NULL; if(strchr(p, APOSTROPHE) == NULL) return p; while (TRUE) { *(q++) = *p; if(*p == 0) break; if(*p == APOSTROPHE) *(q++) = APOSTROPHE; p++; } return out; } char *out_with_optional_protection(char *p) { static char out[1000]; char *q = p - 1; int protect = FALSE; while(*(++q) != 0) { if(*q == ' ' || strchr(PUNCTUATION, *q) != NULL) { protect = TRUE; break; } } if(!protect) return p; else { sprintf(out, "'%s'", out_with_apostrophe(p)); return out; } } void out_table_by_series(FILE *out, int *table, int dim) { int num, pre = -1; for(num = 0; num < dim; num++) { if(!table[num]) { pre = -1; continue; } if(pre == - 1) { fprintf(out, " %d", num + 1); pre = num; continue; } if(num < dim - 1 && table[num + 1]) continue; fprintf(out, "-%d", num + 1); pre = -1; } } int save_nexus_file(const char *fname, int ntaxa, int protein, char **seqs, char **taxnames, char **notes, char *header, int num_species_sets, int **list_species_sets, char **name_species_sets, list_regions *charsets, int tot_comment_lines, char **comment_name, char **comment_line, region *region_used, int *sel_seqs, int tot_sel_seqs, int *eachlength, int tot_trees, char **trees, const Fl_Menu_Item *items) { FILE *out; int i, j, lmax, num, vtotseqs, current, ecrit; char *p, date_ligne[50]; list_segments *psegment, all_sequence; region maregion; time_t heure; out = fopen(fname, "w"); if(out == NULL) return TRUE; if(region_used == NULL) { /* on veut tout sauver */ tot_sel_seqs = 0; all_sequence.debut = 1; all_sequence.fin = eachlength[0]; for(i = 1; i < ntaxa; i++) if( all_sequence.fin < eachlength[i] ) all_sequence.fin = eachlength[i]; all_sequence.next = NULL; maregion.list = &all_sequence; region_used = &maregion; } /* calcul longueur des regions */ lmax = 0; psegment = region_used->list; while(psegment != NULL) { lmax += psegment->fin - psegment->debut + 1; psegment = psegment->next; } vtotseqs = 0; for(i=0; i < ntaxa; i++) if(tot_sel_seqs == 0 || sel_seqs[i]) ++vtotseqs; time(&heure); strcpy(date_ligne, ctime(&heure)); num = strlen(date_ligne) - 1; if(date_ligne[num] == '\n') date_ligne[num] = 0; fprintf(out,"#NEXUS\n[saved by seaview on %s]\n", date_ligne); fprintf(out, "BEGIN DATA;\n DIMENSIONS NTAX=%d NCHAR=%d;\n", vtotseqs, lmax); fprintf(out, " FORMAT DATATYPE=%s\n GAP=-\n ;\nMATRIX\n", (protein ? "PROTEIN" : "DNA") ); num = 0; for(i = 0; i < ntaxa; i++) { if(tot_sel_seqs != 0 && ! sel_seqs[i]) continue; fprintf(out, "[%d] %s\n", ++num, out_with_optional_protection(taxnames[i])); current = 0; psegment = region_used->list; all_sequence.fin = eachlength[i]; do { ecrit = output_next_res_from_region(seqs[i], eachlength[i], &psegment, ¤t, out, 60, FALSE); if( ecrit > 0) putc('\n', out); else if(ecrit == -1) break; } while(ecrit != 0); if( (ecrit = lmax - eachlength[i]) > 0) { for(j = 1; j <= ecrit; j++) { putc('-', out); if(j % 60 == 0) putc('\n', out); } putc('\n', out); } if(ferror(out)) break; } fprintf(out, ";\nEND;\n"); if(notes != NULL) { num = 0; current = 0; for(i = 0; i < ntaxa; i++) { if(tot_sel_seqs != 0 && ! sel_seqs[i]) continue; ++num; if(notes[i] == NULL || strcmp(notes[i], ";") == 0 || strcmp(notes[i], ";\n") == 0) continue; if(current == 0) { fputs("BEGIN NOTES;\n", out); current++; } fprintf(out, " TEXT TAXON=%d TEXT='", num); p = notes[i] + 1; while(*p != 0) { fputc(*p, out); if(*p == APOSTROPHE) fputc(APOSTROPHE, out); if(*p == '\n' && *(p+1) != 0) p++; p++; } fputs("';\n", out); } if(current != 0) fprintf(out, "END;\n"); } if(num_species_sets != 0 || charsets != NULL) { fprintf(out, "BEGIN SETS;\n"); for(num = 0; num < num_species_sets; num++) { fprintf(out, " TAXSET '%s' =", out_with_apostrophe(name_species_sets[num])); out_table_by_series(out, list_species_sets[num], ntaxa); fputs(";\n", out); } while(charsets != NULL) { list_segments *pair; fprintf(out, " CHARSET '%s' =", out_with_apostrophe(charsets->element->name)); pair = charsets->element->list; while(pair != NULL) { if(pair->debut != pair->fin) fprintf(out, " %d-%d", pair->debut, pair->fin); else fprintf(out, " %d", pair->debut); pair = pair->next; } fputs(";\n", out); charsets = charsets->next; } fprintf(out, "END;\n"); } if(tot_trees != 0) { fprintf(out, "BEGIN TREES;\n"); for(num = 0; num < tot_trees; num++) { fprintf(out, " TREE '%s'= ", (items+num)->label()); int l = 0; p = trees[num]; do { fputc(*p, out); if(++l > 70 && (*p == ',' || *p == ')')) { fputc('\n', out); l = 0; } p++; } while(*p != 0); fputc('\n', out); } fprintf(out, "END;\n"); } if(header != NULL || tot_comment_lines != 0) { fprintf(out, "BEGIN seaview;\n"); if(header != NULL) { fputs(" TEXT HEADER TEXT='", out); p = header + 2; while(*p != 0) { fputc(*p, out); if(*p == APOSTROPHE) fputc(APOSTROPHE, out); if(*p == '\n' && *(p+1) != 0) p += 2; p++; } fputs("';\n", out); } for(i = 0; i < tot_comment_lines; i++) { fprintf(out, " TEXT FOOTER='%s' TEXT='", out_with_apostrophe(comment_name[i])); p = comment_line[i]; j = 0; while(*p != 0) { fputc(*p, out); j++; if(*p == APOSTROPHE) fputc(APOSTROPHE, out); if(j >= 50) { fputc('\n', out); j = 0; } p++; } fputs("';\n", out); } fprintf(out, "END;\n"); } fclose(out); return FALSE; } seaview/pdf_or_ps.cxx000644 000765 000024 00000024342 12406634417 015537 0ustar00mgouystaff000000 000000 #include "pdf_or_ps.h" #include #include #include #include #include #include extern char *run_and_close_native_file_chooser(Fl_Native_File_Chooser *chooser, int keepalive=0); extern char *prepare_ps_or_pdf_font(int font_num); extern const char *extract_filename(const char *fname); #ifdef NO_PDF int Fl_PDF_or_PS_File_Device::begin_document(const char* fixedfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { file = fopen(fixedfilename, "w"); if (!file) return 1; filename = strdup(fixedfilename); return Fl_PostScript_File_Device::start_job(file, 0, format, layout); } int Fl_PDF_or_PS_File_Device::start_job(const char *defaultname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->title("Set PostScript filename"); chooser->filter("PS Files\t*.ps"); int l = defaultname ? strlen(defaultname) : 0; char *preset = new char[l + 5]; strcpy(preset, defaultname ? defaultname : "" ); char *p = strchr(preset, '.'); if (p) *p = 0; strcat(preset, ".ps"); chooser->preset_file(extract_filename(preset)); delete[] preset; chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); char *plotfilename = run_and_close_native_file_chooser(chooser); if(plotfilename == NULL) return 1; return begin_document(plotfilename, format, layout); } Fl_PDF_or_PS_File_Device::~Fl_PDF_or_PS_File_Device() { if (file) { fclose(file); free(filename); } } #else // NO_PDF #include #include #ifdef WIN32 extern PDF *win32_PDF_new(); extern int win32_PDF_begin_document(PDF *p, const char *filename, int len, const char *optlist); extern void win32_PDF_end_document(PDF *p, const char *optlist); extern void win32_PDF_delete(PDF *p); #define PDF_begin_document win32_PDF_begin_document #define PDF_end_document win32_PDF_end_document #define PDF_new win32_PDF_new #define PDF_delete win32_PDF_delete #endif // WIN32 Fl_PDF_File_Device::Fl_PDF_File_Device() { driver(new Fl_PDF_Graphics_Driver); filename = NULL; } Fl_PDF_File_Device::~Fl_PDF_File_Device() { PDF *p = ((Fl_PDF_Graphics_Driver*)driver())->pdf; if (p) PDF_delete(p); delete driver(); if (filename) free(filename); } int Fl_PDF_File_Device::start_job(const char *defaultname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->title("Set PDF filename"); chooser->filter("PDF Files\t*.pdf"); int l = defaultname ? strlen(defaultname) : 0; char *preset = new char[l + 5]; strcpy(preset, defaultname ? defaultname : "" ); char *p = strchr(preset, '.'); if (p) *p = 0; strcat(preset, ".pdf"); chooser->preset_file(preset); delete[] preset; chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); char *plotfilename = run_and_close_native_file_chooser(chooser); if(plotfilename == NULL) return 1; return begin_document(plotfilename, format, layout); } int Fl_PDF_File_Device::begin_document(const char* fixedfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { if (layout == LANDSCAPE) { return begin_custom(fixedfilename, page_formats[format].height, page_formats[format].width); } return begin_custom(fixedfilename, page_formats[format].width, page_formats[format].height); } int Fl_PDF_File_Device::begin_custom(const char* plotfilename, int pwidth, int pheight) { width = pwidth; height = pheight; PDF *pdf = PDF_new(); if (pdf == NULL) return 1; Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); d->pdf = pdf; if (PDF_begin_document(pdf, plotfilename, 0, "compatibility=1.3") == -1) { fl_alert("Error opening %s for writing\n", plotfilename); return 1; } PDF_set_info(pdf, "Title", plotfilename ); PDF_set_info(pdf, "Creator", "seaview"); previous_surface = Fl_Surface_Device::surface(); PDF_set_parameter(pdf, "topdown", "true"); if (width == page_formats[Fl_Paged_Device::A4].width) { left_margin = 18; top_margin = 18; } else { left_margin = 12; top_margin = 12; } filename = strdup(plotfilename); set_current(); return 0; } int Fl_PDF_File_Device::start_page() { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); PDF *p = d->pdf; PDF_begin_page_ext(p, width, height, ""); PDF_translate(p, left_margin, top_margin); PDF_setlinecap(p, 1); PDF_setlinewidth(p, 1); d->in_page = true; if (d->pdf_font != -1) { PDF_setfont(p, d->pdf_font, d->size()); } PDF_save(p); d->tr_x = d->tr_y = 0; return 0; } int Fl_PDF_File_Device::printable_rect(int *w, int *h) //returns 0 iff OK { if(w) *w = (int)((width - 2 * left_margin) + .5); if(h) *h = (int)((height - 2 * top_margin) + .5); return 0; } void Fl_PDF_File_Device::margins(int *left, int *top, int *right, int *bottom) { *left = left_margin; *top = top_margin; *right = left_margin; *bottom = top_margin; } void Fl_PDF_File_Device::origin(int x, int y) { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); d->tr_x = x; d->tr_y = y; PDF *p = d->pdf; PDF_restore(p); PDF_save(p); PDF_translate(p, x, y); } void Fl_PDF_File_Device::origin(int *px, int *py) { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); if (px) *px = d->tr_x; if (py) *py = d->tr_y; } void Fl_PDF_File_Device::translate(int x, int y) { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); PDF *p = d->pdf; PDF_save(p); PDF_translate(p, x, y); } void Fl_PDF_File_Device::untranslate() { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); PDF *p = d->pdf; PDF_restore(p); } int Fl_PDF_File_Device::end_page() { Fl_PDF_Graphics_Driver *d = (Fl_PDF_Graphics_Driver*)driver(); PDF_restore(d->pdf); PDF_end_page_ext(d->pdf, ""); d->in_page = false; return 0; } void Fl_PDF_File_Device::end_job() { PDF_end_document(((Fl_PDF_Graphics_Driver*)driver())->pdf, ""); previous_surface->set_current(); } void *Fl_PDF_File_Device::pdf() { return ((Fl_PDF_Graphics_Driver*)driver())->pdf; } void Fl_PDF_File_Device::error_catch() { Fl_Display_Device::display_device()->set_current(); PDF *pdf = (PDF*)this->pdf(); fl_alert("Error while writing pdf file:\n%s\n" "[%d] %s: %s\n", filename, PDF_get_errnum(pdf), PDF_get_apiname(pdf), PDF_get_errmsg(pdf) ); } int Fl_PDF_File_Device::surface_catch() { return pdf_catch(((Fl_PDF_Graphics_Driver*)driver())->pdf); } void Fl_PDF_File_Device::surface_try(jmp_buf **jbuf) { PDF *p = ((Fl_PDF_Graphics_Driver*)driver())->pdf; *jbuf = &( pdf_jbuf(p)->jbuf ); } Fl_PDF_Graphics_Driver::Fl_PDF_Graphics_Driver() { #ifdef __APPLE__ encoding = "macroman"; #else encoding = "iso8859-1"; #endif pdf = NULL; pdf_font = -1; in_page = false; } void Fl_PDF_Graphics_Driver::line(int x1, int y1, int x2, int y2) { PDF_moveto(pdf, x1, y1); PDF_lineto(pdf, x2, y2); PDF_stroke(pdf); } void Fl_PDF_Graphics_Driver::xyline(int x, int y, int x1) { line(x, y, x1, y); } void Fl_PDF_Graphics_Driver::xyline(int x, int y, int x1, int y2) { line(x, y, x1, y); line(x1,y,x1,y2); } void Fl_PDF_Graphics_Driver::yxline(int x, int y, int y1) { line(x, y, x, y1); } void Fl_PDF_Graphics_Driver::yxline(int x, int y, int y1, int x2) { line(x, y, x, y1); line(x,y1,x2,y1); } void Fl_PDF_Graphics_Driver::rect(int x, int y, int w, int h) { PDF_rect(pdf, x, y+h, w, h); PDF_stroke(pdf); } void Fl_PDF_Graphics_Driver::rectf(int x, int y, int w, int h) { PDF_rect(pdf, x, y+h, w, h); PDF_fill(pdf); } void Fl_PDF_Graphics_Driver::draw(const char *str, int n, int x, int y) { PDF_show_xy2(pdf, str, n, x, y); } void Fl_PDF_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) { PDF_save(pdf); PDF_translate(pdf, x, y); PDF_rotate(pdf, angle); PDF_show_xy2(pdf, str, n, 0, 0); PDF_restore(pdf); } void Fl_PDF_Graphics_Driver::font(int f, int s) { char *current_ps_font = prepare_ps_or_pdf_font(f); pdf_font = PDF_load_font(pdf, current_ps_font, 0, encoding, ""); Fl_Graphics_Driver::font(f, s); if (in_page) PDF_setfont(pdf, pdf_font, s); } void Fl_PDF_Graphics_Driver::color(Fl_Color c) { uchar red, green, blue; Fl::get_color(c, red, green, blue); color(red, green, blue); } void Fl_PDF_Graphics_Driver::color(uchar red, uchar green, uchar blue) { float r, g, b; r = red/255.; g = green/255.; b = blue/255.; PDF_setcolor(pdf, "fillstroke", "rgb", r, g, b, 0); } double Fl_PDF_Graphics_Driver::width(const char* str, int l) { return PDF_stringwidth2(pdf, str, l, pdf_font, size()); } int Fl_PDF_Graphics_Driver::height() { return size(); } int Fl_PDF_Graphics_Driver::descent() { return (int)(-PDF_get_value(pdf, "descender", pdf_font) * size() + 0.5) + 1; } void Fl_PDF_Graphics_Driver::draw(const char* str, int n, float fx, float fy) { draw(str, n, (int)fx, (int)fy); } void Fl_PDF_Graphics_Driver::push_clip(int x, int y, int w, int h) { PDF_save(pdf); PDF_moveto(pdf, x, y); PDF_lineto(pdf, x + w, y); PDF_lineto(pdf, x + w, y + h); PDF_lineto(pdf, x, y + h); PDF_closepath(pdf); PDF_clip(pdf); } void Fl_PDF_Graphics_Driver::pop_clip() { PDF_restore(pdf); } void Fl_PDF_Graphics_Driver::draw_image(const uchar*, int, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw_image_mono(const uchar*, int, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw(Fl_RGB_Image*, int, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw(Fl_Pixmap*, int, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::draw(Fl_Bitmap*, int, int, int, int, int, int) {} void Fl_PDF_Graphics_Driver::line_style(int style, int width, char *dashes) {} void Fl_PDF_Graphics_Driver::rtl_draw(const char*, int, int, int) {} #endif // NO_PDF seaview/pdf_or_ps.h000644 000765 000024 00000012332 12404325714 015153 0ustar00mgouystaff000000 000000 #ifndef PDF_OR_PS_H #define PDF_OR_PS_H #include #if !(defined(__APPLE__) || defined(WIN32)) && 100*FL_MAJOR_VERSION + 10*FL_MINOR_VERSION + FL_PATCH_VERSION == 130 // for X11 under 1.3.0 only #include class corr_Fl_Printer : public Fl_Printer { int count, m, M; public: corr_Fl_Printer(); int start_job(int pagecount, int *frompage=NULL, int *topage=NULL); int start_page(); }; #define Fl_Printer corr_Fl_Printer class corr_Fl_PostScript_File_Device : public Fl_PostScript_File_Device { int count, m, M; public: corr_Fl_PostScript_File_Device(); int start_job (int pagecount, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); int start_job (FILE* file, int pagecount, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); int start_page(); }; #define Fl_PostScript_File_Device corr_Fl_PostScript_File_Device #endif #ifdef NO_PDF #include class Fl_PDF_or_PS_File_Device : public Fl_PostScript_File_Device { FILE *file; char *filename; public: Fl_PDF_or_PS_File_Device() { file = NULL; } int begin_document(const char* fixedfilename, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); int start_job(const char *defaultname, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); Fl_Graphics_Driver *driver() { return Fl_PostScript_File_Device::driver(); } const char *outfname() {return filename; } ~Fl_PDF_or_PS_File_Device(); }; #else // NO_PDF #include #include class Fl_PDF_Graphics_Driver : public Fl_Graphics_Driver { private: int pdf_font; const char *encoding; bool in_page; int tr_x, tr_y; public: PDF *pdf; Fl_PDF_Graphics_Driver(); void rect(int x, int y, int w, int h); void rectf(int x, int y, int w, int h); void line_style(int style, int width, char *dashes=0); void line(int x1, int y1, int x2, int y2); void xyline(int x, int y, int x1); void xyline(int x, int y, int x1, int y2); void yxline(int x, int y, int y1); void yxline(int x, int y, int y1, int x2); void font(int f, int s); void draw(const char *str, int n, int x, int y); void draw(const char*, int, float, float) ; void draw(int, const char*, int, int, int) ; void rtl_draw(const char*, int, int, int) ; void color(uchar r, uchar g, uchar b); void color(Fl_Color c); void push_clip(int x, int y, int w, int h) ; void pop_clip(); void draw_image(const uchar*, int, int, int, int, int, int) ; void draw_image_mono(const uchar*, int, int, int, int, int, int) ; void draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw(Fl_RGB_Image*, int, int, int, int, int, int) ; void draw(Fl_Pixmap*, int, int, int, int, int, int) ; void draw(Fl_Bitmap*, int, int, int, int, int, int) ; double width(const char*, int) ; int height() ; int descent() ; friend class Fl_PDF_File_Device; }; class Fl_PDF_File_Device : public Fl_Paged_Device { int width, height; Fl_Surface_Device *previous_surface; int left_margin, top_margin; char *filename; public: Fl_PDF_File_Device(); int start_job(const char *defaultname, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); int begin_document(const char* fixedfilename, enum Fl_Paged_Device::Page_Format format=Fl_Paged_Device::A4, enum Fl_Paged_Device::Page_Layout layout=Fl_Paged_Device::PORTRAIT); int begin_custom(const char* fixedfilename, int pwidth, int pheight); int printable_rect(int *w, int *h); void margins(int *left, int *top, int *right, int *bottom); void origin(int x, int y); void origin (int *x, int *y); void translate(int x, int y); void untranslate(); int start_page (void); int end_page (void); void end_job (void); void error_catch(); int surface_catch(); void surface_try(jmp_buf** b); void *pdf(); const char *outfname() {return filename; } ~Fl_PDF_File_Device(); }; typedef Fl_PDF_File_Device Fl_PDF_or_PS_File_Device; #endif // NO_PDF #if defined(__APPLE__) #include #if (!__LP64__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1070 #define USE_PICT #endif #endif #if (defined(__APPLE__) || defined(WIN32)) class Fl_Copy_Surface : public Fl_Surface_Device { #ifdef __APPLE__ bool use_pict; CFMutableDataRef pdfdata; CGContextRef oldgc; CGContextRef gc; #ifdef USE_PICT PicHandle mypicture; void MyCopyPictToClipboard(); QDPictRef MyPictToQDPict(); #endif static size_t MyPutBytes (void* info, const void* buffer, size_t count); void prepare_copy_pdf_and_pict(int w, int h); void complete_copy_pdf_and_pict(); void init_PDF_context(int w, int h); #else HDC oldflgc; #endif public: #ifdef __APPLE__ Fl_Copy_Surface(bool use_pict, int w, int h); #else Fl_Copy_Surface(int w, int h); #endif ~Fl_Copy_Surface(); }; #endif #endif // PDF_OR_PS_H seaview/pseudoterminal.cxx000644 000765 000024 00000027161 12404325714 016614 0ustar00mgouystaff000000 000000 #ifdef WIN32 #include #elif defined(__APPLE__) #include #include #else //X11 #include #ifdef sun #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum {running, completed, aborted, closed}; struct listener_data { int status; Fl_Multiline_Output *o; #ifdef WIN32 HANDLE pid; #else pid_t pid; #endif int fd; Fl_Button *ok, *interrupt; Fl_Scrollbar *bar; int nl; // current number of complete lines in buffer int view_nl; // max no of visible lines in Fl_Multiline_Output char *from; // start in buffer of displayed text during running char *next; // just after last displayed buffer byte char *eol; // points to where new bytes will be put in buffer bool modified; char buffer[10000000]; // buffer to hold text. Start from beginning again when more text than buffer size }; typedef void (*thread_function_t) (void *); extern int fl_create_thread(thread_function_t f, void* p, unsigned stack_size_KB); static void inter_callback(Fl_Widget *o, struct listener_data *data) { data->status = aborted; #ifdef WIN32 BOOL ok = TerminateProcess(data->pid, 0); if (ok) { while ( WaitForSingleObject(data->pid, 0) != WAIT_OBJECT_0) Fl::wait(0.1); } #else kill(data->pid, SIGKILL); #endif } static void ok_callback(Fl_Widget *o, struct listener_data *data) { data->status = closed; } static void bar_callback(Fl_Scrollbar *wgt, Fl_Multiline_Output *o) { int first_line = wgt->value(); const char *p = o->value(); do { if(*p == '\n') first_line--; p++; } while(*p != 0 && first_line > 0); o->position(p - o->value()); o->redraw(); } static void copy_callback(Fl_Widget *wgt, Fl_Multiline_Output *o) { o->position(o->size(), 0); o->copy(1); } void ext_prog_listener(struct listener_data *data) {//transmits data from fd to FLTK viewer with CR emulation char *p; static char fd_buff[2000]; int l; while (data->status == running) { l = read(data->fd, fd_buff, sizeof(fd_buff)); if (l <= 0) break; Fl::lock(); if (data->next + l >= data->buffer + sizeof(data->buffer)) { data->next = data->from = data->eol = data->buffer; data->nl = 0; } for (p = fd_buff; p < fd_buff + l; p++) { if (*p == '\r') { if (p+1 >= fd_buff + l || *(p+1) != '\n') { while(data->eol > data->buffer && *(data->eol - 1) != '\n') (data->eol)--; } } else { if (*p == '\n') { data->eol = data->next; data->nl++; if(data->nl >= data->view_nl) data->from = strchr(data->from, '\n') + 1; } *(data->eol++) = *p; if(data->eol > data->next) data->next = data->eol; } } data->modified = true; Fl::unlock(); } Fl::lock(); if (data->status == running) { data->o->static_value(data->buffer, data->next - data->buffer); data->o->position(data->next - data->buffer, data->next - data->buffer); data->o->redraw(); data->bar->value(data->nl, data->view_nl, 0, data->nl); data->bar->show(); if (!data->ok->active()) { data->ok->activate(); data->interrupt->label("Cancel"); data->status = completed; } } Fl::unlock(); } Fl_Window *create_and_run_pseudoterminal(const char *label, struct listener_data *data) #define FL_min(a,b) ( (a) < (b) ? (a):(b) ) { static char message[100]; Fl_Double_Window *w = new Fl_Double_Window( FL_min(700, Fl::w()), FL_min(600, Fl::h()-22 ) ); w->xclass("Terminal"); w->label(label); w->callback((Fl_Callback*)inter_callback, data); Fl_Multiline_Output *o = new Fl_Multiline_Output(0, 3, w->w() - 15, w->h() - 40); o->textfont(FL_COURIER); o->textsize(12); o->maximum_size(5000000); data->bar = new Fl_Scrollbar(o->x() + o->w(), o->y(), 15, o->h()); data->bar->callback((Fl_Callback*)bar_callback, o); data->view_nl = o->h() / o->textsize(); #ifdef WIN32 data->view_nl = (int)(data->view_nl * 0.80); #endif data->bar->value(0, data->view_nl, 0, data->view_nl); data->bar->hide(); sprintf(message, "Wait for %s completion", label); Fl_Box *w_message = new Fl_Box(0, o->y() + o->h() + 3, w->w(), 20, message); Fl_Button *w_copy = new Fl_Button(w->w()/2 - 30, w_message->y(), 60, 20, "Copy all"); w_copy->hide(); w_copy->callback((Fl_Callback*)copy_callback, o); data->status = running; data->o = o; data->nl = 0; data->from = data->next = data->eol = data->buffer; Fl_Button *interrupt = new Fl_Button(5, w->h() - 35, 70, 30, "Interrupt"); interrupt->callback((Fl_Callback*)inter_callback, data); interrupt->labelfont(FL_HELVETICA_BOLD); Fl_Return_Button *ok = new Fl_Return_Button(w->w() - 60, interrupt->y(), 50, 30, "OK"); ok->callback((Fl_Callback*)ok_callback, data); ok->labelfont(FL_HELVETICA_BOLD); ok->deactivate(); data->ok = ok; data->interrupt = interrupt; data->modified = false; w->end(); w->position( (Fl::w() - w->w())/2, (Fl::h() - w->h())/2 ); Fl_Box *r = new Fl_Box(interrupt->x() + interrupt->w(), o->y(), ok->x() - interrupt->x() - interrupt->w(), o->h()); w->resizable(r); w->show(); #ifndef MICRO w->hotspot(w); #endif fl_create_thread( (thread_function_t)ext_prog_listener, data, 0); while (data->status == running) { if (data->modified) { data->modified = false; data->o->static_value(data->from, data->next - data->from); data->o->redraw(); } Fl::wait(0.1); } w_message->hide(); w_copy->show(); #ifdef WIN32 _close(data->fd); #else close(data->fd); #endif return w; } int run_external_prog_in_pseudoterm(char *cmd, const char *dialogfname, const char *label) /* cmd can be: prog arg1 arg2 ... or: "prog" arg1 "arg2" ... > outfile and: prog can also use file named in dialogfname as stdin (NULL if no such file) label: short name of operation that is run returns 0 iff cmd completed correctly */ { static struct listener_data data; static bool inuse = 0; if(inuse) { fl_alert("Operation %s is not possible while another alignment/tree-building is in progress", label); return 1; } inuse = 1; Fl_Window *w; #ifdef WIN32 HANDLE ChildInput, ChildStdoutRd, ChildStdoutWr, stdouthandle = NULL; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION pi; STARTUPINFOW si; char *p, *q; if(dialogfname != NULL) { FILE *in = fopen(dialogfname, "r"); if(in == NULL) { inuse = 0; return 1; } ChildInput = (HANDLE)_get_osfhandle(fileno(in)); } p = cmd;//is there stdout redirection in cmd ? if(*p == '"') p = strchr(p+1, '"') + 1; p = strchr(p, '>'); if(p != NULL) { *p = 0; p++; while(*p == ' ') p++; if (*p == '"') { q = strchr(++p, '"'); if (q) *q = 0; } char *stdoutfname = strdup(p); FILE *out = fopen(stdoutfname, "w"); free(stdoutfname); if(out != NULL) stdouthandle = (HANDLE)_get_osfhandle(fileno(out)); } saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; CreatePipe(&ChildStdoutRd, &ChildStdoutWr, &saAttr, 0/*suggested buffer size*/); DWORD written; WriteFile(ChildStdoutWr, "Running ", 8, &written, NULL); WriteFile(ChildStdoutWr, cmd, strlen(cmd), &written, NULL); WriteFile(ChildStdoutWr, "\n ", 1, &written, NULL); SetHandleInformation(ChildStdoutRd, HANDLE_FLAG_INHERIT, 0); ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) ); ZeroMemory( &si, sizeof(STARTUPINFOW) ); si.cb = sizeof(STARTUPINFOW); si.hStdError = ChildStdoutWr; si.hStdOutput = stdouthandle ? stdouthandle : ChildStdoutWr; if(dialogfname != NULL) si.hStdInput = ChildInput; else si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags |= STARTF_USESTDHANDLES; //conversion of utf-8 cmd into a WCHAR string int wlen = MultiByteToWideChar(CP_UTF8, 0, cmd, -1, NULL, 0); WCHAR *wcmd = new WCHAR[wlen]; MultiByteToWideChar(CP_UTF8, 0, cmd, -1, wcmd, wlen); int retval = CreateProcessW(NULL, wcmd, 0,0,TRUE,CREATE_NO_WINDOW,0,0, &si, &pi); delete wcmd; CloseHandle(ChildStdoutWr); if(stdouthandle != NULL) CloseHandle(stdouthandle); if(dialogfname != NULL) CloseHandle(ChildInput); if(retval == 0) { CloseHandle(ChildStdoutRd); inuse = 0; return 1; } CloseHandle(pi.hThread); data.pid = pi.hProcess; data.fd = _open_osfhandle( # ifdef _WIN64 (intptr_t) # else (long) # endif ChildStdoutRd, _O_RDONLY); w = create_and_run_pseudoterminal(label, &data); CloseHandle(pi.hProcess); #else // creates a pseudoterminal pid_t pid; int masterfd; char *slavename; #if defined(__APPLE__) char slavename2[50]; if (fl_mac_os_version < 100500) { //special for Mac OS X 10.4 + i386 slavename = slavename2; pid = forkpty(&masterfd, slavename2, NULL, NULL); } else #endif { masterfd = posix_openpt(O_RDWR|O_NOCTTY); grantpt(masterfd); unlockpt(masterfd); slavename = ptsname(masterfd); if(masterfd == -1 || slavename == NULL) { inuse = 0; return 1; } pid = fork(); } if(pid == -1) { inuse = 0; return 1; } else if(pid > 0) {// the parent data.pid = pid; data.fd = masterfd; w = create_and_run_pseudoterminal(label, &data); } else {//the child if(dialogfname != NULL) {//case of use of dialog file freopen(dialogfname, "r", stdin); } freopen(slavename, "a", stderr); #ifdef sun ioctl(fileno(stderr), I_PUSH, "ptem"); // ioctl(fileno(stderr), I_PUSH, "ldterm"); // ioctl(fileno(stderr), I_PUSH, "ttcompat"); #endif fputs(cmd, stderr); fputc('\n', stderr); fflush(stderr);//show command //decode progname char *p, *q, *progpath, **argv; int argc, newout = -1; close(masterfd); p = cmd; while(*p == ' ') p++; if(*p == '"') q = strchr(++p, '"'); else { q = strchr(p, ' '); if(q == NULL) q = p + strlen(p); } progpath = new char[q-p+1]; memcpy(progpath, p, q-p); progpath[q-p] = 0; //goto end of progname p = q; if(*p == '"') p++; // take care of stdout // bug in Mac OS X 10.4 i386 requires us to close stdout and reopen it on fd = 1 fclose(stdout); if((q = strchr(p, '>')) != NULL) {//open desired stdout file char stdoutfile[200]; FILE *f; *q = 0; do q++; while(*q == ' '); if (*q == '"') q++; strcpy(stdoutfile, q); q = stdoutfile + strlen(stdoutfile) - 1; while (q > stdoutfile && (*q == ' ' || *q == '"') ) q--; *(q + 1) = 0; f = fopen(stdoutfile, "w"); if(f) newout = fileno(f); } else { newout = open(slavename, O_WRONLY|O_APPEND); } if(newout != 1 && newout != -1) { dup2(newout, 1); } //count args argc = 1; q = p - 1; while (*++q) { if (isspace(*q)) continue; argc++; if (*q == '"') { q = strchr(q + 1, '"'); if (!q) break; } else { do q++; while ( *q && !isspace(*q) ); q--; } } //put args in argv array argv = (char **)malloc((argc + 1)*sizeof(char *)); argv[0] = progpath; argv[argc] = NULL; q = p - 1; int i = 1; while (*++q) { if (isspace(*q)) continue; if (*q == '"') { argv[i++] = ++q; q = strchr(q, '"'); if (!q) break; *q = 0; } else { argv[i++] = q; do q++; while ( *q && !isspace(*q) ); if (*q == 0) { break; } *q = 0; } } int err = 1; const char *errmess; if(access(progpath, X_OK) != 0) errmess = "executable"; else { err = execv(progpath, argv); errmess = "a valid program"; } fprintf(stderr, "\n\n\n%s is not %s\n", progpath, errmess); exit(err); } #endif while(data.status == completed) Fl::wait(); delete w; if(dialogfname != NULL) remove(dialogfname); inuse = 0; return data.status == aborted; } seaview/racnuc_fetch.cxx000644 000765 000024 00000047636 12404534445 016221 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include extern "C" { #include "raa_acnuc.h" } struct runningw_struct { raa_db_access *raa; SEA_VIEW *view; FILE *infile; int listrank; int elt; int count, interrupted, use_spec_name, truncated; Fl_Box *runb; }; /* local functions */ int racnuc_fetch(const char *db_name, const char *name, FILE *list, int use_spec_name, SEA_VIEW *view, Fl_Window *, Fl_Menu_Item *feature_item, const char *scan_word, Fl_Widget *, Fl_Button*); int racnuc_fetch_file_or_list(FILE *list, int listrank, int use_spec_name, raa_db_access *raa, SEA_VIEW *view); static void idle_callback(void *data); void racnuc_dialog(SEA_VIEW *view); void use_key_callback(Fl_Widget *ob, void *data); void dbchoice_callback(Fl_Widget *ob, void *data); void acnuc_url_callback(Fl_Widget *ob, void *data); void ok_callback(Fl_Widget *ob, void *data); void fsel_callback(Fl_Widget *ob, void *data); void more_callback(Fl_Widget *ob, void *data); void close_cb(Fl_Widget *ob, void *data); raa_db_access *open_acnuc_socket(Fl_Widget *, Fl_Button*); char *import_one_seq(raa_db_access *raa, const char *id, int use_spec_name, int *plength, int *ptruncated, SEA_VIEW *view, int try_as_keyword, Fl_Menu_Item *feature_item, const char *scan_word); int import_one_keyword(raa_db_access *raa, const char *keyword, int use_spec_name, int *ptruncated, SEA_VIEW *view, Fl_Menu_Item *feature_item, const char *scan_word); static int scan_list(raa_db_access *raa, int mylist, const char *scan_word, const char *feature_name); extern void interrupt_callback(Fl_Widget *ob, void *data); extern int compute_size_params(SEA_VIEW *view, int force_recompute); extern void update_comment_gc(int seqnum, int ncbigc, SEA_VIEW *view); extern char *get_res_value(const char *name, const char *def_value); extern int set_res_value(const char *name, const char *value); extern int compute_wid_names(SEA_VIEW *view, int totseqs); extern int fl_create_thread(void (*f) (void *), void* p, unsigned stack_size_KB); extern "C" int get_ncbi_gc_number(int gc); /* globals */ static const char def_acnuc_server[] = "pbil.univ-lyon1.fr:5558"; int racnuc_fetch(const char *db_name, const char *name, FILE *listfile, int use_spec_name, SEA_VIEW *view, Fl_Window *w, Fl_Menu_Item *feature_item, const char *scan_word, Fl_Widget *ok, Fl_Button *close_b) /* return value: 0 iff OK */ { raa_db_access *raa; int err, length, truncated = FALSE; raa = open_acnuc_socket(ok, close_b); if(raa == NULL) return 1; err = raa_opendb(raa, (char *)db_name); if(err) { if(listfile != NULL) fclose(listfile); raa_acnucclose(raa); fl_message("DataBase %s is offline. Please try again later.", db_name); return 1; } if(view->masename == NULL) { const char *p = fl_input("Sequence alignment name ?", name); if(p == NULL) p = "newseqs"; view->masename = strdup(p); } err = 0; my_watch_cursor(w); if(listfile == NULL) { if(import_one_seq(raa, name, use_spec_name, &length, &truncated, view, TRUE, feature_item, scan_word) == NULL) { fl_reset_cursor(w); if(feature_item == NULL) fl_message("Sequence/Keyword %s not found in %s", name, db_name); else if (scan_word != NULL) fl_message("No feature key matches %s", scan_word); else fl_message("Sequence %s or feature key not found.", name); } } else { truncated = racnuc_fetch_file_or_list(listfile, 0, use_spec_name, raa, view); } raa_acnucclose(raa); view->wid_names = compute_wid_names(view, view->tot_seqs); compute_size_params(view, TRUE); view->DNA_obj->damage(FL_DAMAGE_ALL); view->horsli->damage(FL_DAMAGE_ALL); view->vertsli->damage(FL_DAMAGE_ALL); fl_reset_cursor(w); if(truncated) fl_message("Some seqs have been truncated to the length of %d", view->max_seq_length); return err; } int racnuc_fetch_file_or_list(FILE *listfile, int listrank, int use_spec_name, raa_db_access *raa, SEA_VIEW *view) { runningw_struct runningw_data; Fl_Window *runw = new Fl_Window(330,60); runw->label("importing sequences"); runningw_data.runb = new Fl_Box(FL_UP_FRAME, 5, 5, 320, 20, ""); Fl_Button *runi = new Fl_Button(130,30, 60, 20, "Interrupt"); runi->callback(interrupt_callback, &(runningw_data.interrupted)); runw->end(); runw->position((Fl::w() - runw->w())/2, (Fl::h() - runw->h())/2); runw->set_modal(); runw->callback(interrupt_callback, &(runningw_data.interrupted)); runw->show(); #ifndef MICRO runw->hotspot(runw); #endif runningw_data.raa=raa; if(listfile != NULL) runningw_data.infile=listfile; else { runningw_data.listrank = listrank; runningw_data.infile = NULL; runningw_data.elt = 1; } runningw_data.interrupted = FALSE; runningw_data.truncated = FALSE; runningw_data.use_spec_name = use_spec_name; runningw_data.view = view; runningw_data.count = 0; Fl::add_idle(idle_callback, &runningw_data); if(listfile != NULL) { while(runningw_data.infile != NULL) Fl::wait(); } else { while(runningw_data.listrank != 0) Fl::wait(); } delete runw; return runningw_data.truncated; } static void idle_callback(void *data) { static char aux[150]; char line[100], *p, *mnemo; int length, doit, next; runningw_struct *runningw_data = (runningw_struct *)data; doit = FALSE; if(!runningw_data->interrupted) { if(runningw_data->infile != NULL) { if( fgets(line, sizeof(line), runningw_data->infile) != NULL ) doit = TRUE; } else if((next = raa_nexteltinlist(runningw_data->raa, runningw_data->elt, runningw_data->listrank, &mnemo, NULL)) != 0) { strcpy(line, mnemo); runningw_data->elt = next; doit = TRUE; } } if(doit) { p = line + strlen(line) - 1; if(p > line && *p == '\n') *p = 0; mnemo = import_one_seq(runningw_data->raa, line, runningw_data->use_spec_name, &length, &runningw_data->truncated, runningw_data->view, FALSE, 0, NULL); if(mnemo != NULL) sprintf(aux, "Name: %s Count: %d", mnemo, ++runningw_data->count); else sprintf(aux, "Name: %s not found", line); runningw_data->runb->label(aux); runningw_data->runb->window()->redraw(); } else { Fl::remove_idle(idle_callback, data); if(runningw_data->infile != NULL){ fclose(runningw_data->infile); runningw_data->infile = NULL; } runningw_data->listrank = 0; } } void raa_win_cb(Fl_Widget *ob, void *data) { Fl_Button *b = (Fl_Button*)data; b->do_callback(); } struct raa_dialog_struct { SEA_VIEW *view; Fl_Input *seq_name_field; Fl_Choice *dbchoice; Fl_Choice *namingchoice; Fl_Check_Button *use_key; Fl_Choice *key_choice; Fl_Input *scan_field; Fl_Return_Button *ok; Fl_Button *close_b; }; void racnuc_dialog(SEA_VIEW *view) { static Fl_Window *load_form = NULL; static raa_dialog_struct raa_fields; if(load_form == NULL) { int newx, x, w; load_form = new Fl_Window(450,190); load_form->box(FL_FLAT_BOX); load_form->label("Database Sequence Import"); raa_fields.dbchoice = new Fl_Choice(80, 5, 105, 20, "Database:"); raa_fields.dbchoice->add("embl|genbank|swissprot"); raa_fields.dbchoice->value(0); raa_fields.dbchoice->callback(dbchoice_callback, &raa_fields); fl_font(raa_fields.dbchoice->labelfont(), raa_fields.dbchoice->labelsize()); raa_fields.namingchoice = new Fl_Choice(300, 5, 145, 20, "Name using:"); raa_fields.namingchoice->add("ID-LOCUS name|Species name"); raa_fields.namingchoice->value(0); new Fl_Box(FL_UP_FRAME, 5, 30, 440, 60, ""); x = 205; w = 175; raa_fields.seq_name_field = new Fl_Input(0, 35, w, 20, "Name/Accession no./Keyword:"); newx = (int)fl_width(raa_fields.seq_name_field->label()) + 10 + 3; raa_fields.seq_name_field->resize(newx, raa_fields.seq_name_field->y(), x - newx + w, raa_fields.seq_name_field->h() ); raa_fields.ok = new Fl_Return_Button(390, 35, 50, 20 , "OK"); raa_fields.ok->callback(ok_callback, &raa_fields); raa_fields.use_key = new Fl_Check_Button(10, 65, 20, 20, ""); raa_fields.use_key->callback(use_key_callback, &raa_fields); raa_fields.key_choice = new Fl_Choice(0, raa_fields.use_key->y(), 100, 20, "Feature key:"); x = raa_fields.use_key->x() + raa_fields.use_key->w() + (int)fl_width(raa_fields.key_choice->label()) + 3 + 3; raa_fields.key_choice->position(x, raa_fields.key_choice->y()); raa_fields.key_choice->deactivate(); raa_fields.scan_field = new Fl_Input(0, raa_fields.key_choice->y(), 1, 20, "Matching string:"); newx = raa_fields.key_choice->x() + raa_fields.key_choice->w() + (int)fl_width(raa_fields.scan_field->label()) + 6; raa_fields.scan_field->resize(newx, raa_fields.scan_field->y(), 440 - newx, raa_fields.scan_field->h() ); raa_fields.scan_field->deactivate(); new Fl_Box(FL_DOWN_FRAME, 220, 95, 20, 20, "or"); new Fl_Box(FL_UP_FRAME, 5, 120, 440, 30, ""); Fl_Box *b = new Fl_Box(FL_NO_BOX, 35, 125, 150, 20, "File of names/acc. nos.:"); newx = b->x() + (int)fl_width(b->label()) + 5; Fl_Button *fsel = new Fl_Button(0, 125, 1, 20 , "Browse for file"); fsel->resize(newx, fsel->y(), (int)fl_width(fsel->label()) + 8, fsel->h() ); fsel->callback(fsel_callback, &raa_fields); raa_fields.close_b = new Fl_Button(380, 160, 65, 20 , "Close"); raa_fields.close_b->callback(close_cb, NULL); raa_fields.close_b->shortcut(FL_COMMAND | 'w'); Fl_Check_Button *more = new Fl_Check_Button(5, 160, 135, 20 , "More Databases"); more->callback(more_callback, &raa_fields); Fl_Button *acnuc_url_button = new Fl_Button(more->x() + more->w() + 5, more->y(), 200, more->h(), "Set DB server address"); acnuc_url_button->callback(acnuc_url_callback, NULL); load_form->end(); load_form->position((Fl::w() - load_form->w())/2, (Fl::h() - load_form->h())/2); load_form->set_modal(); load_form->hotspot(load_form); load_form->callback(raa_win_cb, raa_fields.close_b); } raa_fields.seq_name_field->value(""); raa_fields.seq_name_field->take_focus(); raa_fields.view = view; load_form->show(); } void use_key_callback(Fl_Widget *ob, void *data) { raa_db_access *raa; char *name; int num, total; raa_dialog_struct *raa_fields = (raa_dialog_struct *)data; raa_fields->key_choice->clear(); raa_fields->scan_field->value(NULL); if(((Fl_Button *)ob)->value() ) { raa = open_acnuc_socket(raa_fields->ok, raa_fields->close_b); if(raa == NULL || raa_opendb(raa, (char *)raa_fields->dbchoice->text()) || raa->swissprot) { ((Fl_Button *)ob)->value(0); if(raa) raa_acnucclose(raa); return; } my_watch_cursor(ob->window()); total = raa_read_first_rec(raa, raa_smj); for(num = 2; num <= total; num++) { name = raa_readsmj(raa, num, NULL, NULL); if(strncmp(name, "04", 2) != 0) continue; if(strcmp(name, "04ID") == 0) continue; if(strcmp(name, "04LOCUS") == 0) continue; int item_rank = raa_fields->key_choice->add(name + 2, 0, NULL, NULL); ((Fl_Menu_Item*)(raa_fields->key_choice->menu() + item_rank))->argument(num); } raa_fields->key_choice->value(0); raa_fields->key_choice->activate(); raa_fields->scan_field->activate(); raa_acnucclose(raa); fl_reset_cursor(ob->window()); } else { raa_fields->key_choice->deactivate(); raa_fields->scan_field->deactivate(); } } void dbchoice_callback(Fl_Widget *ob, void *data) { raa_dialog_struct *raa_fields = (raa_dialog_struct *)data; raa_fields->use_key->value(0); raa_fields->key_choice->clear(); raa_fields->key_choice->deactivate(); raa_fields->scan_field->deactivate(); if( strcmp( ((Fl_Choice *)ob)->text(), "swissprot") == 0) raa_fields->use_key->deactivate(); else raa_fields->use_key->activate(); } void acnuc_url_callback(Fl_Widget *ob, void *data) { const char *url2 = fl_input("Enter address of remote acnuc server\n" "(currently %s)", def_acnuc_server, get_res_value("racnuc", def_acnuc_server) ); if(url2 != NULL) set_res_value("racnuc", url2); } void ok_callback(Fl_Widget *ob, void *data) { raa_dialog_struct *raa_fields = (raa_dialog_struct *)data; Fl_Menu_Item *feature_item; const char *scan_word = NULL; if(strlen(raa_fields->seq_name_field->value()) == 0) return; int use_spec_name = raa_fields->namingchoice->value() == 1; if(raa_fields->use_key->value() ) { feature_item = (Fl_Menu_Item *)raa_fields->key_choice->mvalue(); scan_word = raa_fields->scan_field->value(); if(scan_word != NULL) { const char *p = scan_word; while(*p == ' ') p++; if(*p == 0) scan_word = NULL; else scan_word = p; } } else feature_item = NULL; racnuc_fetch(raa_fields->dbchoice->text(), raa_fields->seq_name_field->value(), NULL, use_spec_name, raa_fields->view, raa_fields->dbchoice->window(), feature_item, scan_word, raa_fields->ok, raa_fields->close_b); } void fsel_callback(Fl_Widget *ob, void *data) { #define MESSAGE "Select file of list of seq. names" raa_dialog_struct *raa_fields = (raa_dialog_struct *)data; Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file chooser->title(MESSAGE); char *filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; FILE *list = fopen(filename, "r"); int use_spec_name = raa_fields->namingchoice->value() == 1; if(list != NULL) { racnuc_fetch(raa_fields->dbchoice->text(), NULL, list, use_spec_name, raa_fields->view, raa_fields->dbchoice->window(), 0, NULL, raa_fields->ok, raa_fields->close_b); } } void more_callback(Fl_Widget *ob, void *data) { raa_dialog_struct *raa_fields = (raa_dialog_struct *)data; raa_db_access *raa; char **names, **descriptions; int num, tot; Fl_Check_Button *b = (Fl_Check_Button *)ob; if(b->value()) { raa = open_acnuc_socket(raa_fields->ok, raa_fields->close_b); if(raa == NULL) { b->value(0); return; } b->deactivate(); tot = raa_knowndbs(raa, &names, &descriptions); for(num = 0; num < tot; num++) { raa_fields->dbchoice->add(names[num], 0, NULL, 0, 0); } raa_acnucclose(raa); } } struct intr_struct { char *server_ip; int port; raa_db_access *raa; int err; bool killed; bool done; }; void close_cb(Fl_Widget *ob, void *data) { if (data == NULL) { ob->window()->hide(); } else { intr_struct *ss = (intr_struct*)data; ss->killed = true; ss->done = true; ob->user_data(NULL); } } static void do_nothing_error_mess_proc(raa_db_access* raa, char* message) { } static void open_socket_thread(intr_struct *ss) //runs in a background thread { raa_error_mess_proc = do_nothing_error_mess_proc; ss->err = raa_open_socket(ss->server_ip, ss->port, (char *)"seaview", &(ss->raa)); if (ss->killed) { delete ss; return; } Fl::lock(); ss->done = true; Fl::awake(); Fl::unlock(); } raa_db_access *open_acnuc_socket(Fl_Widget *ok, Fl_Button *close_b) // attempt to open remote acnuc socket using interruptible thread // returns NULL iff error or interrupted { raa_db_access *raa = NULL; char *server_ip; int port, err; char *url = get_res_value("racnuc", def_acnuc_server); err = raa_decode_address(url, &server_ip, &port, NULL); if (!err) { intr_struct *ss = new intr_struct; ss->server_ip = server_ip; ss->port = port; ss->raa = NULL; ss->done = false; ss->killed = false; ss->err = 0; my_watch_cursor(ok->window()); close_b->user_data(ss); close_b->label("Interrupt"); ok->deactivate(); if (fl_create_thread((void(*)(void*))open_socket_thread, (void*)ss, 0) ) { open_socket_thread(ss); // run in main thread if child thread creation failed } else { while ( !ss->done ) Fl::wait(); // wait for end/kill of child thread } fl_reset_cursor(ok->window()); ok->activate(); close_b->user_data(NULL); close_b->label("Close"); if (ss->killed) { fl_alert("%s", "Connection attempt was cancelled"); delete ss; return NULL; } err = ss->err; raa = ss->raa; delete ss; } if (err) { fl_alert("Can't connect to remote acnuc server:\n%s", url); raa = NULL; } return raa; } /*static void interrupt_callback(Fl_Widget *ob, void *data) { *(int *)data = TRUE; }*/ char *import_one_seq(raa_db_access *raa, const char *id, int use_spec_name, int *plength, int *ptruncated, SEA_VIEW *view, int try_as_keyword, Fl_Menu_Item *feature_item, const char *scan_word) { char *mnemo, *acc, *specname, *descr, *p, *seq; int length, frame, gencode, rank, type, pext, num, next, list1, matchinglist, count, err; static char line[500]; mnemo = raa_getattributes(raa, id, &rank, &length, &frame, &gencode, &acc, &descr, &specname, feature_item == NULL ? &seq : NULL); if(mnemo == NULL) { if(try_as_keyword) { return (import_one_keyword(raa, id, use_spec_name, ptruncated, view, feature_item, scan_word) ? NULL : (char *)id); } else return NULL; } if(feature_item != NULL) { if(scan_word != NULL) { sprintf(line, "n=%s and t=%s", mnemo, feature_item->label()); err = raa_proc_query(raa, line, NULL, (char *)"mylist", &list1, &count, NULL, NULL); if(err || count == 0) return NULL; matchinglist = scan_list(raa, list1, scan_word, feature_item->label() ); if(matchinglist == 0) return NULL; racnuc_fetch_file_or_list(NULL, matchinglist, use_spec_name, raa, view); return (char *)"OK"; } else { mnemo = raa_readsub(raa, rank, NULL, &type, &pext, NULL, NULL, NULL, NULL); int desired_type = (int)feature_item->argument(); if(type != desired_type ) { next = -pext; while(next > 0) { next = raa_readlng(raa, next); for (num = 0; num < raa->SUBINLNG; num++) { rank = raa->rlng_buffer->sub[num]; if(rank == 0) break; mnemo = raa_readsub(raa, rank, NULL, &type, NULL, NULL, NULL, NULL, NULL); if(type == desired_type) break; } if(type == desired_type) break; } if(type != desired_type) return NULL; } } mnemo = raa_getattributes(raa, mnemo, NULL, &length, &frame, &gencode, &acc, &descr, &specname, &seq); } gencode = get_ncbi_gc_number(gencode); if(frame == 1) { seq -= 2; /* this terrible thing is possible after raa_getattributes */ length += 2; *seq = '-'; *(seq + 1) = '-'; } else if(frame == 2) { seq -= 1; length += 1; *seq = '-'; } add_seq_to_align(view, use_spec_name ? specname : mnemo, seq, length); *plength = length; if(view->comments == NULL) view->comments = (char **)calloc(view->tot_seqs, sizeof(char *)); p = view->comments[view->tot_seqs-1]; *line = 0; if(p != NULL && strcmp(p, ";\n") != 0) strcpy(line, p); if(p != NULL) free(p); p = strchr(descr, ' '); /* skip 1st word (name) from descr */ if(p != NULL) p++; else p = descr; sprintf(line + strlen(line), ";%s\n", p); p = line + strlen(line); if(use_spec_name) sprintf(p, ";Name=%s\n;Acc=%s\n", mnemo, acc); else sprintf(p, ";/organism=\"%s\"\n;Acc=%s\n", specname, acc); if(frame != 0 && strstr(line, "/codon_start=") == NULL) sprintf(line + strlen(line), ";/codon_start=%d\n", frame + 1); int l = strlen(line); p = (char *)malloc(l + 1); if(p != NULL) strcpy(p, line); view->comments[view->tot_seqs-1] = p; if(view->comments != NULL && gencode != 1) update_comment_gc(view->tot_seqs - 1, gencode, view); return mnemo; } int import_one_keyword(raa_db_access *raa, const char *keyword, int use_spec_name, int *ptruncated, SEA_VIEW *view, Fl_Menu_Item *feature_item, const char *scan_word) /* returns 0 iff keyword exists */ { int numlist, err; char query[WIDTH_MAX + 50]; sprintf(query, "k=%s", keyword); if(feature_item != NULL) { sprintf(query + strlen(query), " and t=%s", feature_item->label()); } err = raa_proc_query(raa, query, NULL, (char *)"bykeyword", &numlist, NULL, NULL, NULL); if(err) return 1; if(scan_word != NULL) { numlist = scan_list(raa, numlist, scan_word, feature_item->label() ); if(numlist == 0) return 1; } *ptruncated = racnuc_fetch_file_or_list(NULL, numlist, use_spec_name, raa, view); return 0; } static int scan_list(raa_db_access *raa, int mylist, const char *scan_word, const char *feature_name) // returns rank of modified list or 0 if error { int err, matchinglist; char line[50], *p; sprintf(line, "prep_getannots&nl=1\n%s|%s\n", raa->embl ? "FT" : "FEATURES", feature_name); sock_fputs(raa, line); p = read_sock(raa); if(strncmp(p, "code=0", 6) != 0) return 0; err = raa_modifylist(raa, mylist, (char *)"scan", (char *)scan_word, &matchinglist, NULL, NULL); return (err != 0 || raa_bcount(raa, matchinglist) == 0) ? 0 : matchinglist; } seaview/README000644 000765 000024 00000005040 12502536442 013706 0ustar00mgouystaff000000 000000 HOW TO COMPILE SEAVIEW ON UNIX/LINUX SYSTEMS The seaview program requires the FLTK library for its graphical user interface. Version 1.3.0 or later of FLTK is necessary. The FLTK library is available as packages for a number of Linux distributions. If this package is installed on your system, go to step II. If no such package is available for your system, or if version 1.3.0 is not available, or if you don't want to use such package, you can compile the FLTK library as follows. I COMPILING THE FLTK LIBRARY FROM SOURCE ======================================== The source code of the FLTK library is available at the "Download" item of http://www.fltk.org/. - Get the stable release source archive, currently fltk-1.3.3-source.tar.gz - Compile the FLTK library on your system: cd fltk-1.3.3 ./configure make It's not necessary to do "make install". II COMPILING THE SEAVIEW PROGRAM ================================ First unpack the seaview source archive (seaview.tar.gz). IIa Preparing the seaview makefile If the FLTK library is installed on your system (i.e., include files in /usr/include/FL, and libraries at /usr/lib/libfltk*), go to step IIb. Otherwise, edit Makefile from the seaview source directory which contains these 5 lines: #to use your own, uninstalled FLTK library, #uncomment the next 3 lines and adapt the 1st to your local file system #FLTK = $(HOME)/fltk-1.3 #IFLTK = -I$(FLTK) #CONFIG = $(FLTK)/fltk-config Transform these lines into: #to use your own, uninstalled FLTK library, #uncomment the next 3 lines and adapt the 1st to your local file system FLTK = $(HOME)/fltk-1.3 IFLTK = -I$(FLTK) CONFIG = $(FLTK)/fltk-config and also change the FLTK = $(HOME)/fltk-1.3 line so it gives the location in your system of the top of the FLTK source tree. IIb Compile/link the seaview program In the seaview source directory, run make III Install seaview external programs ===================================== Seaview drives 4 external programs (clustalo, muscle, Gblocks, phyml). Linux executables of these are available from the linux items of http://pbil.univ-lyon1.fr/software/seaview.html They are also available as packages of most Linux distributions. These programs should be put in your PATH or in the same directory as the seaview executable for seaview to drive them. By default seaview searches for the phyml executable under the names PhyML-3.1_linux32 or PhyML-3.1_linux64. If they are installed under other names on your system, seaview will ask you for their name and location which are remembered for subsequent runs. seaview/regions.cxx000644 000765 000024 00000126241 12404325714 015226 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include #include #ifdef WIN32 #include extern "C" { int _wsystem(const wchar_t *command ); } #endif enum position_mask {custom_mask = -1, gblocks_sites, position_1, position_2, position_3, position_12, variable_sites }; const char *position_mask_names[] = {"Gblocks", "First codon pos.", "Second codon pos.", "Third codon pos.", "1st+2nd codon pos.", "Variable sites"}; int position_mask_count = sizeof(position_mask_names)/sizeof(char*); /* prototypes of included functions */ region *duplicate_region(region *source, const char *name); void free_region(region *reg); region *copy_region(region *from, region *to); int create_full_region(SEA_VIEW *view, const char *name); void save_active_region(SEA_VIEW *view ); void hide_region_line(SEA_VIEW *view); int create_codon_position_mask(SEA_VIEW *view, position_mask mask, const char *regname); int rename_current_region(SEA_VIEW *view, const char *name); void delete_region(SEA_VIEW *view, int rang); void activate_region_line(SEA_VIEW *view, int rang); void ajout_segment(region *maregion, int debut, int fin); int suppr_segment(region *maregion, int site, char *line); list_segments *get_segment(region *maregion, int site); void draw_region_line(Fl_Widget *ob, SEA_VIEW *view); const char *site_mask_creation_dialog(SEA_VIEW *view, position_mask *outmask); void regions_menu_callback(Fl_Widget *ob, void *extra); int begin_change_segment(SEA_VIEW *view, int new_site); int continue_change_segment(SEA_VIEW *view, int new_site); void end_change_segment(SEA_VIEW *view); int extend_segment_at_left(SEA_VIEW *view, int new_site); static void delete_in_region_line(SEA_VIEW *view, int numsite, int total); void delete_region_part(SEA_VIEW *view, int numsite, int total); static void insert_in_active_region(SEA_VIEW *view, int numsite, int total); void insert_region_part(SEA_VIEW *view, int numsite, int total); list_regions *parse_regions_from_header(char *header); void draw_region_background(SEA_VIEW *view, int f_seq0, int l_seq0); const char *create_species_set(SEA_VIEW *view, const char *set_name); void species_menu_callback(Fl_Widget *ob, void *extra); int parse_species_sets_from_header(char *header, int **list_species_sets, char **name_species_sets, int totseqs); extern void adjust_menu_edit_modes(SEA_VIEW *view); int compute_size_params(SEA_VIEW *view, int force_recompute); extern char *create_tmp_filename(void); extern void delete_tmp_filename(const char *base_fname); region *duplicate_region(region *source, const char *name) { region *destin; list_segments *pseg, *dest_seg, *prev; destin = (region *)calloc(1, sizeof(region)); if(destin == NULL) return NULL; if(name != NULL) { size_t l; l = strlen(name); destin->name = (char *)calloc(l+1, 1); if(destin->name == NULL) return NULL; memcpy(destin->name, name, l+1); } if(source == NULL) return destin; pseg = source->list; if(pseg == NULL) return destin; destin->list = (list_segments *)calloc(1, sizeof(list_segments)); if(destin->list == NULL) return NULL; *(destin->list) = *pseg; destin->list->next = NULL; pseg = pseg->next; prev = destin->list; while(pseg != NULL) { dest_seg = (list_segments *)calloc(1, sizeof(list_segments)); if(dest_seg == NULL) return NULL; *dest_seg = *pseg; dest_seg->next = NULL; prev->next = dest_seg; prev = dest_seg; pseg = pseg->next; } destin->hide_when_viewasprots = source->hide_when_viewasprots; return destin; } void free_region(region *reg) { list_segments *pseg, *suiv; if(reg == NULL) return; pseg = reg->list; while(pseg != NULL) { suiv = pseg->next; free(pseg); pseg = suiv; } if(reg->name != NULL) free(reg->name); free(reg); } region *copy_region(region *from, region *to) { region *retval; char *name; name = to->name; to->name = NULL; free_region(to); retval = duplicate_region(from, NULL); if(retval == NULL) out_of_memory(); retval->name = name; return retval; } int create_full_region(SEA_VIEW *view, const char *name) { list_regions *old, *new_list; region *maregion; /* le nom existe-t-il deja? */ old = view->regions; while(old != NULL) { if(strcmp(name, old->element->name) == 0) return FALSE; old = old->next; } maregion = (region *)calloc(1,sizeof(region)); if(maregion == NULL) out_of_memory(); maregion->name = (char *)malloc(strlen(name)+1); if(maregion->name == NULL) out_of_memory(); strcpy(maregion->name, name); maregion->list = (list_segments *)calloc(1, sizeof(list_segments)); if(maregion->list == NULL) out_of_memory(); maregion->list->debut = 1; maregion->list->fin = view->seq_length; new_list = (list_regions *)calloc(1, sizeof(list_regions)); if(new_list == NULL) out_of_memory(); new_list->element = maregion; /* placer nouvelle region en fin de liste des regions connues */ if(view->regions == NULL) view->regions = new_list; else { old = view->regions; while(old->next != NULL) old = old->next; old->next = new_list; } view->active_region = duplicate_region(maregion, name); if(view->active_region == NULL) return TRUE; /*mess no mem serait mieux */ Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE_REGIONS].activate(); view->region_length = view->seq_length; memset(view->region_line, 'X', view->region_length); view->region_line[view->region_length] = 0; compute_size_params(view, TRUE); return TRUE; } void create_variable_mask(SEA_VIEW *view, region *maregion) { int i, j, in_variable = FALSE; list_segments *segment, *previous; previous = NULL; for(i = 1; i <= view->seq_length; i++) { for (j = 1; j < view->tot_seqs; j++) { if(toupper(view->sequence[j][i-1]) != toupper(view->sequence[0][i-1])) break; } if(j < view->tot_seqs) { if(in_variable) continue; in_variable = TRUE; segment = (list_segments *)calloc(1, sizeof(list_segments)); segment->debut = i; if(previous != NULL) previous->next = segment; else maregion->list = segment; previous = segment; } else { if( ! in_variable) continue; in_variable = FALSE; segment->fin = i - 1; for(j = segment->debut; j <= segment->fin; j++) view->region_line[j-1] = 'X'; } } if(in_variable) { segment->fin = view->seq_length; for(j = segment->debut; j <= segment->fin; j++) view->region_line[j-1] = 'X'; } } int run_gblocks_dialog(int *pb5_val, int *pb4_val, int *pb3_val, int *pb2_val) { Fl_Widget *o; Fl_Window *w = new Fl_Window(370,100); w->label("Gblocks options dialog"); Fl_Box *b = new Fl_Box(5, 5, w->w(), 20, "Options for a less stringent selection:"); b->align(FL_ALIGN_LEFT + FL_ALIGN_INSIDE); b->labelfont(FL_TIMES_BOLD); Fl_Check_Button *b4 = new Fl_Check_Button(10,30, 350, 20, "Allow smaller final blocks"); Fl_Check_Button *b5 = new Fl_Check_Button(10,50, 350, 20, "Allow gap positions within the final blocks"); Fl_Check_Button *b2 = new Fl_Check_Button(10,70, 350, 20, "Allow less strict flanking positions"); Fl_Box *box2 = new Fl_Box(5, b2->y() + 20, w->w(), 20, "Option for a more stringent selection:"); box2->align(FL_ALIGN_LEFT + FL_ALIGN_INSIDE); box2->labelfont(FL_TIMES_BOLD); Fl_Check_Button *b3 = new Fl_Check_Button(10,box2->y()+20, 350, 20, "Do not allow many contiguous nonconserved positions"); Fl_Button *cancel = new Fl_Button(10, b3->y()+30, 50, 20, "Cancel"); Fl_Return_Button *ret = new Fl_Return_Button(w->w()-60, cancel->y(), 50, 20, "OK"); w->size(w->w(), ret->y()+22); w->end(); w->set_non_modal(); w->show(); while(TRUE) { o = Fl::readqueue(); if (!o) Fl::wait(); else if(o == cancel || o == w) { return 1; } else if(o == ret) break; } *pb5_val = b5->value(); // -b5=h *pb4_val = b4->value(); // -b4=5 *pb3_val = b3->value(); // -b3=4 *pb2_val = b2->value(); // -b2=(50% of species) Fl::delete_widget(w); if (o == cancel || o == w) return 1; return 0; } int create_gblocks_mask(SEA_VIEW *view, region *maregion, int no_gui=false, int b5_val=0, int b4_val=0, int b3_val=0, int b2_val=0) /* return 0 iff OK */ { char cmd[500]; char base_fname[PATH_MAX], fname[PATH_MAX], *p, *q, *last; int status, segment_count = -1, num, l; FILE *in; list_segments *segment, *previous; void (*alert)(const char*,...) = (no_gui ? Fl::fatal : fl_alert); q = get_full_path( "Gblocks" #ifdef WIN32 ".exe" #endif ); if (!q) { alert("Program Gblocks not found." #if !(defined(WIN32) || defined(__APPLE__)) "\nTo use Gblocks, download it from http://molevol.cmima.csic.es/castresana/Gblocks.html\n" "and put it in a directory of your PATH" #endif ); return 1; } if (!no_gui && run_gblocks_dialog(&b5_val, &b4_val, &b3_val, &b2_val)) return 1; p = create_tmp_filename(); if(p == NULL) return 1; strcpy(base_fname, p); sprintf(fname, "%s.fst", base_fname); char **newnames = new char*[view->tot_seqs]; for (int i = 0; i < view->tot_seqs; i++) { newnames[i] = new char[15]; sprintf(newnames[i], "Seq_%d", i); } status = save_fasta_file(fname, view->sequence, NULL, newnames, view->tot_seqs, view->each_length, NULL, NULL, 0, FALSE, TRUE); for (int i = 0; i < view->tot_seqs; i++) delete newnames[i]; delete[] newnames; if (status) { alert("Cannot write to temporary file %s", fname); delete_tmp_filename(base_fname); return 1; } sprintf(cmd, "\"%s\" \"%s\" -p=s -t=%c", q, fname, view->protein?'p':'d'); if (b5_val) strcat(cmd, " -b5=h"); if (b4_val) strcat(cmd, " -b4=5"); if (b3_val) strcat(cmd, " -b3=4"); if (b2_val) sprintf(cmd + strlen(cmd), " -b2=%d", view->tot_seqs/2 + 1); #ifdef WIN32 //conversion of utf-8 cmd into a WCHAR string int wlen = MultiByteToWideChar(CP_UTF8, 0, cmd, -1, NULL, 0); WCHAR *wcmd = new WCHAR[wlen]; MultiByteToWideChar(CP_UTF8, 0, cmd, -1, wcmd, wlen); //_wsystem(wcmd); PROCESS_INFORMATION pi; STARTUPINFOW si; ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) ); ZeroMemory( &si, sizeof(STARTUPINFOW) ); l = CreateProcessW(NULL, wcmd, 0,0,FALSE,CREATE_NO_WINDOW,0,0, &si, &pi); if (l) { while ( WaitForSingleObject(pi.hProcess, 0) != WAIT_OBJECT_0) Fl::wait(0.1); } delete[] wcmd; #else strcat(cmd, " > /dev/null"); system(cmd); #endif sprintf(fname, "%s.fst-gb.txts", base_fname); in = fopen(fname, "r"); if (in == NULL) status = 1; if (!status) { do { p = fgets(cmd, sizeof(cmd), in); if (p == NULL) { status = 1; break; } } while(strncmp(cmd, "Flank positions of the", 22) != 0); if (p) { sscanf(cmd + 22, "%d", &segment_count); p = fgets(cmd, sizeof(cmd), in); if (p == NULL || segment_count < 0 || strncmp(cmd, "Flanks:", 7) != 0) status = 1; } } if (status == 0 && segment_count == 0) { alert("Gblocks didn't find any block of conserved sites"); status = 1; } if (!status) { p = cmd; previous = NULL; for (num = 0; num < segment_count; num++) { q = NULL; p = strchr(p, '['); if (p != NULL) q = strchr(p, ']'); if (q == NULL) { l = strlen(cmd); memmove(cmd, last, l + 1 - (last - cmd)); l -= (last - cmd); p = cmd; fgets(cmd + l, sizeof(cmd) - l, in); p = strchr(p, '['); if (p != NULL) q = strchr(p, ']'); if (p == NULL || q == NULL) break; } p++; segment = (list_segments*)calloc(sizeof(list_segments), 1); sscanf(p, "%d", &segment->debut); p = strchr(p, ' '); sscanf(p, "%d", &segment->fin); p = strchr(p, ']'); last = p; if (previous) previous->next = segment; else maregion->list = segment; previous = segment; for(int j = segment->debut; j <= segment->fin; j++) view->region_line[j-1] = 'X'; } if (num < segment_count) status = 1; maregion->hide_when_viewasprots = FALSE; } if (in) fclose(in); delete_tmp_filename(base_fname); return status; } int create_codon_position_mask(SEA_VIEW *view, position_mask mask, const char *regname) /* return values: 0 no region was created 1 OK 2 name is already used */ { list_regions *old, *new_list; region *maregion; list_segments *segment, *previous; int i; /* le nom existe-t-il deja? */ old = view->regions; while (old != NULL) { if(strcmp(regname, old->element->name) == 0) break; old = old->next; } if (old != NULL) { if (mask != gblocks_sites) return 2; int taille, valeur; taille = view->menu_sites->vlength(); valeur = taille; while(old->next) { old = old->next; valeur--; } delete_region(view, valeur); } maregion = (region *)calloc(1,sizeof(region)); if(maregion == NULL) out_of_memory(); maregion->name = (char *)malloc(strlen(regname) + 1); if(maregion->name == NULL) out_of_memory(); strcpy(maregion->name, regname); if(!view->protein) maregion->hide_when_viewasprots = TRUE; memset(view->region_line, '-', view->seq_length); if (mask == gblocks_sites) { if (create_gblocks_mask(view, maregion) ) { free(maregion->name); free(maregion); return 0; } } else if (mask >= position_1 && mask <= position_12) { previous = NULL; for(i = 1; i <= view->seq_length; i += 3) { segment = (list_segments *)calloc(1, sizeof(list_segments)); if(mask == position_12) { segment->debut = i; segment->fin = i + 1; view->region_line[i - 1] = 'X'; view->region_line[i] = 'X'; } else { segment->debut = i + mask - position_1; segment->fin = segment->debut; view->region_line[i - 1 + mask - position_1] = 'X'; } if(previous != NULL) previous->next = segment; else maregion->list = segment; previous = segment; } } else if (mask == variable_sites) create_variable_mask(view, maregion); view->region_length = view->seq_length; view->region_line[view->region_length] = 0; new_list = (list_regions *)calloc(1, sizeof(list_regions)); if(new_list == NULL) out_of_memory(); new_list->element = maregion; /* placer nouvelle region en fin de liste des regions connues */ if(view->regions == NULL) view->regions = new_list; else { old = view->regions; while(old->next != NULL) old = old->next; old->next = new_list; } view->active_region = duplicate_region(maregion, maregion->name); if(view->active_region == NULL) return TRUE; /*mess no mem serait mieux */ Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE_REGIONS].activate(); compute_size_params(view, TRUE); return 1; } int rename_current_region(SEA_VIEW *view, const char *name) { list_regions *old, *new_list; region *maregion; size_t l; char *p; /* le nom existe-t-il deja? */ old = view->regions; while(old != NULL) { if(strcmp(name, old->element->name) == 0) return FALSE; old = old->next; } l = strlen(name); p = (char *)calloc(l+1, 1); if(p == NULL) return TRUE; /*mess no mem serait mieux */; save_active_region(view); memcpy(p, name, l+1); free(view->active_region->name); view->active_region->name = p; maregion = duplicate_region(view->active_region, name); if(maregion == NULL) return TRUE; /*mess no mem serait mieux */ new_list = (list_regions *)calloc(1, sizeof(list_regions)); if(new_list == NULL) out_of_memory(); new_list->element = maregion; /* placer nouvelle region en fin de liste des regions connues */ if(view->regions == NULL) view->regions = new_list; else { old = view->regions; while(old->next != NULL) old = old->next; old->next = new_list; } Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE_REGIONS].activate(); return TRUE; } void save_active_region(SEA_VIEW *view) { /* save changes in current region */ list_regions *list; list_segments *act_seg, *mem_seg; int tmp, taille; if(view->menu_sites == NULL) return; tmp = view->menu_sites->value(); if(tmp == 0) return; taille = view->menu_sites->vlength(); list = view->regions; if(tmp > 1) while( --tmp) list= list->next; /* compare active and region in list */ act_seg = list->element->list; mem_seg = view->active_region->list; while ( (act_seg != NULL && mem_seg != NULL) || (act_seg == NULL && mem_seg == NULL) ) { if( act_seg == NULL && mem_seg == NULL ) return; if(act_seg->debut != mem_seg->debut || act_seg->fin != mem_seg->fin) break; act_seg = act_seg->next; mem_seg = mem_seg->next; } list->element = copy_region(view->active_region, list->element); if(view->format_for_save == MASE_FORMAT || view->format_for_save == NEXUS_FORMAT) { set_seaview_modified(view, TRUE); } } void hide_region_line(SEA_VIEW *view) { free_region(view->active_region); view->active_region = NULL; Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; if (view->tot_sel_seqs == 0) items[SAVE_REGIONS].deactivate(); compute_size_params(view, TRUE); } void delete_region(SEA_VIEW *view, int rang) { list_regions *list, *previous; region *maregion; list_segments *segment, *next; view->menu_sites->remove(rang-1); list = view->regions; if(rang == 1) view->regions = list->next; else { while( --rang) { previous = list; list= list->next; } previous->next = list->next; } maregion = list->element; segment = maregion->list; while(segment != NULL) { next = segment->next; free(segment); segment = next; } free(maregion->name); free(maregion); free(list); hide_region_line(view); } void activate_region_line(SEA_VIEW *view, int rang) { list_regions *list; list_segments *segment; list = view->regions; while ( --rang ) list = list->next; if(view->viewasprots && list->element->hide_when_viewasprots) return; if(view->active_region == NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE_REGIONS].activate(); } view->active_region = duplicate_region(list->element, list->element->name); view->region_length = view->seq_length; memset(view->region_line, '-', view->region_length); view->region_line[view->region_length] = 0; segment = view->active_region->list; while(segment != NULL) { memset(view->region_line + segment->debut - 1, 'X', segment->fin - segment->debut + 1); segment = segment->next; } } void ajout_segment(region *maregion, int debut, int fin) /* toutes inferferences entre nouveau segment et anciens sont acceptees */ { list_segments *psegment, *next, *prev; prev = NULL; psegment = maregion->list; while(psegment != NULL) { /* recherche premier segment apres le nouveau */ if(debut <= psegment->fin + 1) break; prev = psegment; psegment = psegment->next; } if(psegment == NULL || fin < psegment->debut - 1) { /* nouveau sans interference*/ next = (list_segments *)calloc(1, sizeof(list_segments)); if(next == NULL) out_of_memory(); next->debut = debut; next->fin = fin; next->next = psegment; if(prev != NULL) prev->next = next; else maregion->list = next; return; } /* nouveau segment interfere avec un(des) autre(s) */ psegment->debut = FL_min(debut, psegment->debut); psegment->fin = FL_max(fin, psegment->fin); while(psegment->next != NULL && psegment->fin >= psegment->next->debut - 1) { psegment->fin = FL_max(psegment->fin, psegment->next->fin); next = psegment->next->next; free(psegment->next); psegment->next = next; } return; } int suppr_segment(region *maregion, int site, char *line) /* suppression du segment entier exact contenant le site site et la ligne-regions ligne est mise a jour avec des - (sauf si line==NULL) valeur rendue TRUE si pas de segment supprime, FALSE si ok. */ { list_segments *psegment, *prev, *next; int debut, fin; psegment = maregion->list; prev = NULL; while(psegment != NULL && psegment->fin < site) { prev = psegment; psegment = psegment->next; } if(psegment == NULL || psegment->debut > site) return TRUE; next = psegment->next; debut = psegment->debut; fin = psegment->fin; free(psegment); if(prev != NULL) prev->next = next; else maregion->list = next; if(line != NULL) memset(line+debut-1, '-', fin-debut+1); return FALSE; } list_segments *get_segment(region *maregion, int site) /* rend le segment contenant site ou NULL si site n'est pas dans un segment */ { list_segments *psegment; psegment = maregion->list; while(psegment != NULL && psegment->fin < site) { psegment = psegment->next; } if(psegment == NULL || psegment->debut > site) return NULL; return psegment; } void draw_region_line(Fl_Widget *ob, SEA_VIEW *view) { int offset, x, y, l_line; x = view->x_seq; y = view->y_seq + FL_min(view->tot_lines, view->tot_seqs) * view->line_height; fl_font(ob->labelfont(),ob->labelsize()); /* clear the background of the region line */ fl_color(ob->color()); fl_rectf(x - view->char_width, y - view->line_height + fl_descent(), (view->tot_sites + 2) * view->char_width, view->line_height); /* write region line */ offset= view->first_site - 1; l_line = ( offset + view->tot_sites < view->region_length ? view->tot_sites : view->region_length - offset); if(l_line <= 0) return; fl_color(view->region_color); fl_draw(view->region_line + offset, l_line, x, y); } const char *site_mask_creation_dialog(SEA_VIEW *view, position_mask *outmask) { const char *retval; static char custom_name[50]; *outmask = custom_mask; Fl_Window *w = new Fl_Window(300,220); w->label("Site set creation dialog"); Fl_Input *input = new Fl_Input(180, 20, 100, 20, "Name of custom site set?"); input->value("all sites"); Fl_Group *g = new Fl_Group(0,40,w->w(),130); Fl_Round_Button *mask[6]; mask[0] = new Fl_Round_Button(30, input->y() + 30, 150, 20, position_mask_names[0]); mask[0]->type(FL_RADIO_BUTTON); mask[1] = new Fl_Round_Button(mask[0]->x(), mask[0]->y() + 20, 150, 20, position_mask_names[1]); mask[1]->type(FL_RADIO_BUTTON); mask[2] = new Fl_Round_Button(mask[0]->x(), mask[1]->y() + 20, 150, 20, position_mask_names[2]); mask[2]->type(FL_RADIO_BUTTON); mask[3] = new Fl_Round_Button(mask[0]->x(), mask[2]->y() + 20, 180, 20, position_mask_names[3]); mask[3]->type(FL_RADIO_BUTTON); mask[4] = new Fl_Round_Button(mask[0]->x(), mask[3]->y() + 20, 120, 20, position_mask_names[4]); mask[4]->type(FL_RADIO_BUTTON); mask[5] = new Fl_Round_Button(mask[0]->x(), mask[4]->y() + 20, 120, 20, position_mask_names[5]); mask[5]->type(FL_RADIO_BUTTON); g->end(); if(view->protein) { for(int i = 1; i <= 4; i++) mask[i]->deactivate(); } Fl_Return_Button *ok = new Fl_Return_Button(170, mask[5]->y() + mask[5]->h() + 10, 50, 30, "Ok"); Fl_Button *cancel = new Fl_Button(ok->x() + ok->w() + 5, ok->y(), 60, 30, "Cancel"); w->end(); w->set_non_modal(); w->show(); while(TRUE) { Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); else if(o == mask[0] || o == mask[1] || o == mask[2] || o == mask[3] || o == mask[4] || o == mask[5]) { ((Fl_Round_Button*)o)->setonly(); ok->take_focus(); input->deactivate(); if(o == mask[0]) {*outmask = gblocks_sites;} else if(o == mask[1]) {*outmask = position_1;} else if(o == mask[2]) {*outmask = position_2;} else if(o == mask[3]) {*outmask = position_3;} else if(o == mask[4]) {*outmask = position_12;} else if(o == mask[5]) {*outmask = variable_sites;} retval = position_mask_names[*outmask]; } else if(o == cancel || o == w) { retval = NULL; break; } else if(o == ok) { if(input->active()) { strncpy(custom_name, input->value(), sizeof(custom_name) - 1); retval = custom_name; } break; } } delete w; return retval; } void regions_menu_callback(Fl_Widget *ob, void *extra) { SEA_VIEW *view; const char *reg_name; position_mask mask; Fl_Menu_ *menu = (Fl_Menu_*)ob; view = (SEA_VIEW *) ob->user_data(); int reponse = menu->mvalue() - view->menu_sites->get_menu(); int ok; Fl_Menu_Item *items = view->menu_sites->get_menu(); if(reponse == 0) { /* create new region */ reg_name = site_mask_creation_dialog(view, &mask); if(reg_name == NULL) return; if(mask == custom_mask) ok = create_full_region(view, reg_name); else { int retval = create_codon_position_mask(view, mask, reg_name); if (retval == 0) return; if (retval == 2) ok = 0; else ok = 1; } if(!ok) { fl_alert("This name is already used: %s", reg_name); return; } view->DNA_obj->redraw(); items[0].deactivate(); items[1].activate(); items[2].activate(); items[3].activate(); view->menu_sites->add(reg_name, regions_menu_callback, NULL, FL_MENU_RADIO); view->menu_sites->value(view->menu_sites->vlength()); } else if(reponse == 1) { /* duplicate current region */ reg_name = fl_input("New set name?", view->active_region->name); if(reg_name == NULL) return; if( !rename_current_region(view, reg_name) ) { fl_alert("This name is already used: %s",reg_name); return; } view->DNA_obj->redraw(); view->menu_sites->add(reg_name, regions_menu_callback, NULL, FL_MENU_RADIO); view->menu_sites->value(view->menu_sites->vlength()); } else if(reponse == 2) { /* hide current region */ save_active_region(view); hide_region_line(view); view->DNA_obj->redraw(); items[0].activate(); items[1].deactivate(); items[2].deactivate(); items[3].deactivate(); view->menu_sites->value(0); } else if(reponse == 3) { /* delete current region */ list_regions *list; int valeur, tmp; valeur = view->menu_sites->value(); if (!valeur) return; tmp = valeur; list = view->regions; if(tmp > 1) while( --tmp) list= list->next; if( fl_choice("Confirm deletion of set:\n%s", "Cancel", "Delete", NULL, list->element->name) ) { delete_region(view, valeur); view->menu_sites->value(0); view->DNA_obj->redraw(); items[0].activate(); items[1].deactivate(); items[2].deactivate(); items[3].deactivate(); } } else { /* choix d'une region courante */ save_active_region(view); int valeur = menu->mvalue() - view->menu_sites->vitem(0) + 1; activate_region_line(view, valeur); compute_size_params(view, TRUE); view->DNA_obj->redraw(); view->menu_sites->value(valeur); items[0].deactivate(); items[1].activate(); items[2].activate(); items[3].activate(); } } static int new_debut, new_fin, prev_site; static list_segments *modified_segment; int begin_change_segment(SEA_VIEW *view, int new_site) /* returns TRUE si click sur extremite d'un segment ou entre 2 segments, FALSE sinon et enleve le site clique de la region */ { int tmp; modified_segment = get_segment(view->active_region, new_site); if ( modified_segment != NULL && new_site != modified_segment->debut && new_site != modified_segment->fin) { /* enlever un site au milieu d'un segment */ tmp = modified_segment->fin; modified_segment->fin = new_site - 1; ajout_segment(view->active_region, new_site+1, tmp); view->region_line[new_site - 1] ='-'; return FALSE; } if(modified_segment != NULL) { new_debut = modified_segment->debut; new_fin = modified_segment->fin; } else { new_debut = new_fin = new_site; view->region_line[new_site - 1] ='X'; } prev_site = new_site; return TRUE; } int continue_change_segment(SEA_VIEW *view, int new_site) { int min; char *pos, new_char; list_segments *current_segment; if(new_site == prev_site) return FALSE; current_segment = get_segment(view->active_region, new_site); if( current_segment != NULL && current_segment != modified_segment)return FALSE; pos = view->region_line + new_site - 1; if( *pos == '-' ) new_char = 'X'; else new_char = '-'; min = FL_min(prev_site, new_site); memset( view->region_line + min - 1, new_char, abs(prev_site - new_site) + 1 ); view->region_line[new_site - 1] = 'X'; if(new_char == 'X') { new_debut = FL_min(new_debut, new_site); new_fin = FL_max(new_fin, new_site); } else { if(new_site > prev_site) new_debut = new_site; else new_fin = new_site; } prev_site = new_site; return TRUE; } void end_change_segment(SEA_VIEW *view) { if(modified_segment == NULL ) /* nouveau segment */ ajout_segment(view->active_region, new_debut, new_fin); else { if (new_fin > modified_segment->fin) /* segment rallonge par sa fin */ ajout_segment(view->active_region, modified_segment->debut, new_fin); else if( new_fin < modified_segment->fin ) /*segment raccourci par sa fin */ modified_segment->fin = new_fin; if (new_debut < modified_segment->debut) /* segment rallonge par son debut */ ajout_segment(view->active_region, new_debut, modified_segment->fin); else if( new_debut > modified_segment->debut ) /* segment raccourci par son debut */ modified_segment->debut = new_debut; } } int extend_segment_at_left(SEA_VIEW *view, int new_site) { list_segments *segment; segment = view->active_region->list; if(segment == NULL || segment->debut > new_site) return TRUE; if(get_segment(view->active_region, new_site) != NULL) return TRUE; while(segment->next != NULL) { if(segment->next->debut > new_site) break; segment = segment->next; } memset(view->region_line + segment->fin, 'X', new_site - segment->fin); ajout_segment(view->active_region, segment->fin, new_site); return FALSE; } static void delete_in_region_line(SEA_VIEW *view, int numsite, int total) /* delete total sites in pos numsite of view->region_line */ { char *site; int l; l = view->region_length; site = view->region_line + numsite - 1; memmove(site - total, site, l - numsite + 2); view->region_length -= total; } void delete_region_part(SEA_VIEW *view, int numsite, int total) { int debut, fin, vnumsite, vtotal; list_segments *segment, *previous; list_regions *next_region; list_regions active; if(total >= numsite) total = numsite - 1; if(total == 0) return; if(view->active_region != NULL) delete_in_region_line(view, numsite, total); /* pour toutes les regions en commencant par active_region */ if(view->active_region != NULL) { active.element = view->active_region; active.next = view->regions; next_region = &active; } else next_region = view->regions; while(next_region != NULL) { if(view->viewasprots && next_region->element->hide_when_viewasprots) { vtotal = total * 3; vnumsite = numsite * 3; } else { vtotal = total; vnumsite = numsite; } segment = next_region->element->list; while(segment != NULL) { debut = segment->debut; fin = segment->fin; if(debut >= vnumsite) debut -= vtotal; else if(debut >= vnumsite - vtotal) debut = vnumsite - vtotal; if(fin >= vnumsite - vtotal) { fin -= vtotal; if(fin < debut) { debut = segment->debut; segment = segment->next; suppr_segment(next_region->element, debut, NULL); } else { segment->debut = debut; segment->fin = fin; segment = segment->next; } } else segment = segment->next; } /* il peut etre necessaire de fusionner 2 segments consecutifs */ segment = next_region->element->list; previous = NULL; while(segment != NULL) { if(previous != NULL && segment->debut == previous->fin + 1) { fin = segment->fin; suppr_segment(next_region->element, segment->debut, NULL); ajout_segment(next_region->element, previous->debut, fin); segment = previous; } previous = segment; segment = segment->next; } next_region = next_region->next; } } static void insert_in_active_region(SEA_VIEW *view, int numsite, int total) /* insert total sites in pos numsite of view->region_line and of ->active_region */ { char *site, new_char; list_segments *segment; site = view->region_line + numsite - 1; memmove(site + total, site, view->region_length - numsite + 2); view->region_length += total; segment = view->active_region->list; new_char = '-'; while(segment != NULL) { if(segment->debut <= numsite && segment->fin >= numsite) { new_char = 'X'; } if(segment->debut > numsite) segment->debut += total; if(segment->fin >= numsite) segment->fin += total; segment = segment->next; } memset(site, new_char, total); } void insert_region_part(SEA_VIEW *view, int numsite, int total) /* insert total sites in pos numsite of all known regions */ { list_segments *segment; list_regions *next_region; int vtotal, vnumsite; if(total + view->region_length > view->max_seq_length) total = view->max_seq_length - view->region_length; if(total == 0) return; if(view->active_region != NULL) insert_in_active_region(view, numsite, total); next_region = view->regions; while(next_region != NULL) { segment = next_region->element->list; if(view->viewasprots && next_region->element->hide_when_viewasprots) { vtotal = total * 3; vnumsite = numsite * 3; } else { vtotal = total; vnumsite = numsite; } while(segment != NULL) { if(segment->debut > vnumsite) segment->debut += vtotal; if(segment->fin >= vnumsite) segment->fin += vtotal; segment = segment->next; } next_region = next_region->next; } } list_regions *parse_regions_from_header(char *header) /* parse the region information from header lines and remove it from them */ { char *p, reg_name[200], aux[200], separ[5], *i, *j, *new_header, *fin_new_header, *old_header; int nreg, tot_reg, l, *endpoints, l_header; region *maregion; list_segments *segment; list_regions *rlist, *deb_rlist = NULL, *cur_list; if(header == NULL) return NULL; old_header = header; l_header=strlen(header); if( (new_header = (char *)malloc(l_header+1)) == NULL) out_of_memory(); fin_new_header = new_header; *new_header = 0; while (*header!= 0) { if(strncmp(header,";;#",3) == 0) { p=strchr(header,'=') + 1; while(*p == ' ') p++; sscanf(p,"%d",&tot_reg); endpoints = (int *)malloc(2*tot_reg*sizeof(int)); if(endpoints==NULL) out_of_memory(); while(*p != ' ' && *p != '\n') p++; while(*p == ' ') p++; if( *p == '\n') { /* no region name in file */ strcpy(reg_name, "regions"); header = p; } else { header = strchr(p,'\n'); memcpy(reg_name, p, header - p); l = header - p; reg_name[l] = 0; while(reg_name[--l]==' ') reg_name[l] = 0; } header++; nreg=0; while(nreg <= 2*tot_reg-1) { j = (char *)memccpy(aux, header, '\n', sizeof(aux)); if(j == NULL) goto next_line; *(j - 1) = 0; strcpy(separ,";, "); j=aux; while( (i=strtok(j,separ)) != NULL) { sscanf(i,"%d",&l); if( nreg > 0 && l <= *(endpoints+nreg-1) - nreg%2 ) { fprintf(stderr, "Region endpoints are not in increasing order: %d\n",l); goto next_line; } *(endpoints + nreg++) = l; j = NULL; } header = strchr(header,'\n') + 1; } maregion = (region *)calloc(1,sizeof(region)); if(maregion == NULL) out_of_memory(); l=strlen(reg_name); maregion->name = (char *)malloc(l+1); if(maregion->name == NULL) out_of_memory(); strcpy(maregion->name, reg_name); for(nreg = 2*tot_reg -1; nreg >= 0; nreg -= 2) { segment = (list_segments *) malloc(sizeof(list_segments)); if(segment == NULL) out_of_memory(); segment->fin = endpoints[nreg]; segment->debut = endpoints[nreg - 1]; segment->next = maregion->list; maregion->list = segment; } free(endpoints); rlist = (list_regions *)malloc(sizeof(list_regions)); if(rlist == NULL) out_of_memory(); rlist->element = maregion; rlist->next = NULL; if(deb_rlist == NULL) deb_rlist = rlist; else { cur_list = deb_rlist; while(cur_list->next != NULL) cur_list = cur_list->next; cur_list->next = rlist; } continue; } else { j=(char *)memccpy(fin_new_header, header, '\n', l_header); fin_new_header += (j - fin_new_header); } next_line: header = strchr(header,'\n') + 1; } *fin_new_header = 0; strcpy(old_header, new_header); free(new_header); return deb_rlist; } void draw_region_background(SEA_VIEW *view, int f_seq0, int l_seq0) { list_segments *segment; int nb_sites, debut, der_site, h, x, y, w, seqnum, y0; Fl_Widget *ob = view->DNA_obj; if(view->active_region == NULL || view->numb_gc == 1) return; segment = view->active_region->list; if(segment == NULL) return; der_site = view->first_site + view->tot_sites - 1; if(view->mod_seq == 0) { /* toutes les seqs */ h = FL_min(view->tot_lines, view->tot_seqs - view->first_seq + 1) * view->line_height; y0 = view->y_seq - view->line_height + fl_descent(); f_seq0 = l_seq0 = 0; } else if(view->mod_seq == -1) { /* les seqs selectionnees seulement */ h = view->line_height; y0 = view->y_seq - view->line_height + fl_descent() + (f_seq0 + 1 - view->first_seq) * view->line_height; } else { /* la seq mod_seq seulement */ h = view->line_height; y0 = view->y_seq - view->line_height + fl_descent() + (view->mod_seq - view->first_seq) * view->line_height; f_seq0 = l_seq0 = 0; } fl_color(ob->selection_color()); do { if(segment->debut > der_site) break; if(segment->fin < view->first_site) continue; debut = FL_max(segment->debut, view->first_site); nb_sites = FL_min(segment->fin, der_site) - debut + 1; x = view->x_seq + (debut - view->first_site) * view->char_width; y = y0; w = nb_sites * view->char_width; for(seqnum = f_seq0; seqnum <= l_seq0; seqnum++) { if(view->mod_seq != -1 || view->sel_seqs[seqnum]) fl_rectf( x, y, w, h); y += view->line_height; } } while( (segment = segment->next) != NULL ); } const char *create_species_set(SEA_VIEW *view, const char *set_name) { int newnumb, i; if(view->numb_species_sets >= MAX_SPECIES_SETS) return "Cannot create more sets"; /* le nom existe-t-il deja? */ for(i=0; i< view->numb_species_sets; i++) { if(strcmp(set_name, view->name_species_sets[i]) == 0) return "Name already used"; } newnumb = view->numb_species_sets + 1; view->list_species_sets[newnumb-1] = (int *)calloc(view->tot_seqs, sizeof(int)); if(view->list_species_sets[newnumb-1] == NULL) return "Not enough memory"; view->name_species_sets[newnumb-1] = (char *)calloc(strlen(set_name)+1, sizeof(char)); if(view->name_species_sets[newnumb-1] == NULL) return "Not enough memory"; memcpy(view->list_species_sets[newnumb-1], view->sel_seqs, view->tot_seqs * sizeof(int) ); strcpy(view->name_species_sets[newnumb-1], set_name); view->numb_species_sets = newnumb; return NULL; } void species_menu_callback(Fl_Widget *ob, void *extra) { SEA_VIEW *view; Fl_Menu_* menu = (Fl_Menu_*)ob; const char *set_name; const char *message; int i, rang, numset, taille; view = (SEA_VIEW *)ob->user_data(); int reponse = menu->mvalue() - view->menu_species->get_menu(); taille = view->menu_species->vlength(); rang = view->menu_species->value(); if (reponse == 0) { /* create new set of species */ if(view->tot_sel_seqs == 0) return; set_name = (char *)fl_input("New species set name?", "good seqs"); if(set_name == NULL) return; if( (message = create_species_set(view, set_name) ) != NULL ) { fl_alert("%s\n%s", message, set_name); return; } view->menu_species->add(set_name, species_menu_callback, NULL, FL_MENU_TOGGLE); view->menu_species->value(++taille); view->menu_species->get_menu()->deactivate(); (view->menu_species->get_menu()+1)->activate(); } else if(reponse == 1) { /* effacer un set */ Fl_Menu_Item *items = view->menu_species->get_menu(); items[1].deactivate(); if(rang == 0) return; /* par securite */ numset = rang - 1; view->menu_species->remove(numset); items[0].deactivate(); free(view->list_species_sets[numset]); free(view->name_species_sets[numset]); memcpy(view->list_species_sets + numset, view->list_species_sets + numset + 1, (view->numb_species_sets - numset - 1)*sizeof(int *) ); memcpy(view->name_species_sets + numset, view->name_species_sets + numset + 1, (view->numb_species_sets - numset - 1)*sizeof(char *) ); (view->numb_species_sets)--; view->tot_sel_seqs = 0; memset(view->sel_seqs, 0, view->tot_seqs * sizeof(int)); view->DNA_obj->redraw(); } else { /* choix d'un set courant */ int minvis, maxvis, visible = FALSE, premier = 0; rang = menu->mvalue() - view->menu_species->vitem(0) + 1; memcpy(view->sel_seqs, view->list_species_sets[rang-1], view->tot_seqs * sizeof(int) ); view->tot_sel_seqs = 0; minvis = view->first_seq; maxvis = minvis + view->tot_lines - 1; for(i=0; i< view->tot_seqs; i++) if(view->sel_seqs[i]) { ++(view->tot_sel_seqs); if(!visible) visible = (i+1 >= minvis && i+1 <= maxvis); if(premier == 0) premier = i + 1; } if(premier != 0 && !visible ) { int maxi; maxi = (int)((Fl_Slider *)view->vertsli)->maximum(); if(premier > maxi) premier = maxi; view->first_seq = premier; ((Fl_Slider *)view->vertsli)->value(premier); } view->DNA_obj->redraw(); view->menu_species->value(rang); (view->menu_species->get_menu()+1)->activate(); adjust_menu_edit_modes(view); } } vlength_menu::vlength_menu(Fl_Menu_ *m, const char *name, const Fl_Menu_Item *init, int clength) { menu_ = m; offset = clength; vlen = 0; val = 0; items = (Fl_Menu_Item*)malloc((offset+1)*sizeof(Fl_Menu_Item)); memcpy(items, init, offset*sizeof(Fl_Menu_Item)); memset(items + offset, 0, sizeof(Fl_Menu_Item)); rank = menu_->add(name, 0, NULL, items, FL_SUBMENU_POINTER); } void vlength_menu::add(const char *txt, Fl_Callback *cb, void *data, int flags) { items = (Fl_Menu_Item*)realloc(items, (offset + vlen + 2)*sizeof(Fl_Menu_Item)); ((Fl_Menu_Item*)(menu_->menu() + rank))->user_data( items ); memset(items + offset + vlen, 0, 2*sizeof(Fl_Menu_Item)); (items + offset + vlen)->label( strdup(txt) ); (items + offset + vlen)->callback(cb, data); (items + offset + vlen)->flags = flags; vlen++; } void vlength_menu::remove(int rank) { if (rank >= vlen) return; free( (void*)vitem(rank)->label() ); memmove(items + offset + rank, items + offset + rank + 1, (vlen - rank)*sizeof(Fl_Menu_Item)); vlen--; } Fl_Menu_Item* vlength_menu::find_item(const char* txt) { for (int i = 0; i < vlen; i++) { if (strcmp(vitem(i)->label(), txt) == 0) return vitem(i); } return NULL; } void vlength_menu::value(int v) { if (v) vitem(v - 1)->setonly(); else if (val) vitem(val - 1)->clear(); val = v; } void vlength_menu::vclear() { for (int i = 0; i < vlen; i++) { free( (void*)(items+offset+i)->label() ); } vlen = 0; val = 0; memset(items + offset, 0, sizeof(Fl_Menu_Item)); } vlength_menu::~vlength_menu() { for (int i = 0; i < vlen; i++) { free( (void*)(items+offset+i)->label() ); } free(items); ((Fl_Menu_Item*)(menu_->menu() + rank))->user_data( NULL ); ((Fl_Menu_Item*)(menu_->menu() + rank))->flags = 0; } int parse_species_sets_from_header(char *header, int **list_species_sets, char **name_species_sets, int totseqs) /* parse the species sets information from header lines and remove it from them */ { char *p, set_name[200], aux[200], separ[5], *i, *j, *new_header, *fin_new_header, *old_header; int numset, tot_spec, l, l_header, num; if(header == NULL) return 0; old_header = header; l_header=strlen(header); if( (new_header = (char *)malloc(l_header+1)) == NULL) out_of_memory(); fin_new_header = new_header; *new_header = 0; numset = -1; while (*header!= 0) { if(strncmp(header,";;@ of species =", 16) == 0) { numset++; p=strchr(header,'=') + 1; while(*p == ' ') p++; sscanf(p,"%d",&tot_spec); list_species_sets[numset] = (int *)calloc(totseqs, sizeof(int)); if(list_species_sets[numset]==NULL) out_of_memory(); while(*p != ' ' && *p != '\n') p++; while(*p == ' ') p++; if( *p == '\n') { /* no set name in file */ strcpy(set_name, "species set"); header = p; } else { header = strchr(p,'\n'); memcpy(set_name, p, header - p); l = header - p; set_name[l] = 0; while(set_name[--l]==' ') set_name[l] = 0; } l = (int) strlen(set_name); name_species_sets[numset] = (char *)malloc(l+1); if(name_species_sets[numset] == NULL) out_of_memory(); memcpy(name_species_sets[numset], set_name, l+1); header++; num = 0; while(num < tot_spec) { j = (char *)memccpy(aux, header, '\n', sizeof(aux)); if(j == NULL) goto next_line; *(j - 1) = 0; strcpy(separ,";, "); j=aux; while( (i=strtok(j,separ)) != NULL) { sscanf(i,"%d",&l); if( l>= 1 && l <= totseqs) list_species_sets[numset][l-1] = 1; num++; j = NULL; } header = strchr(header,'\n') + 1; } continue; } else { j=(char *)memccpy(fin_new_header, header, '\n', l_header); fin_new_header += (j - fin_new_header); } next_line: header = strchr(header,'\n') + 1; } *fin_new_header = 0; strcpy(old_header, new_header); free(new_header); return numset + 1; } seaview/resource.cxx000644 000765 000024 00000013050 12424253075 015402 0ustar00mgouystaff000000 000000 #include #include #include #include // included functions void load_resources(const char *progname); char *get_res_value(const char *name, const char *def_value); int int_res_value(const char *name, int def_value); int bool_res_value(const char *name, int def_value); int set_res_value(const char *name, const char *value); int save_resources(void); void delete_res_value(const char *name); #if defined(__APPLE__) #include /* for Mac OS X */ char *get_res_value(const char *name, const char *def_value) { CFStringRef cfname; CFPropertyListRef cfvalue; static char value[400]; cfname = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if(cfname == NULL) return (char *)def_value; cfvalue = CFPreferencesCopyAppValue(cfname, kCFPreferencesCurrentApplication); CFRelease(cfname); if(cfvalue == NULL) return (char *)def_value; Boolean ok = CFStringGetCString( (CFStringRef)cfvalue, value, sizeof(value), kCFStringEncodingUTF8); CFRelease(cfvalue); return (ok ? value : (char *)def_value); } int set_res_value(const char *name, const char *value) { CFStringRef cfname, cfvalue; cfname = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if(cfname == NULL) return 1; cfvalue = CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); if(cfvalue == NULL) return 1; CFPreferencesSetAppValue(cfname, cfvalue, kCFPreferencesCurrentApplication); CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); CFRelease(cfname); CFRelease(cfvalue); return 0; } void delete_res_value(const char *name) { CFStringRef cfname; cfname = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if(cfname == NULL) return; CFPreferencesSetAppValue(cfname, NULL, kCFPreferencesCurrentApplication); CFRelease(cfname); } int save_resources(void) { // nothing to do, taken care of by the system return 0; } void load_resources(const char *progname) { // nothing to do, taken care of by the system return; } #else /* for X11 and win32 */ typedef struct _item { struct _item *before; char *name; char *value; struct _item *next; } item; static item *firstitem = NULL; extern char *get_prog_dir(void); void delete_res_value(const char *name) { item *elt = firstitem; while(elt != NULL) { if(strcmp(elt->name, name) == 0) { if(elt->before == NULL) { firstitem = elt->next; } else { elt->before->next = elt->next; } if(elt->next != NULL) elt->next->before = elt->before; free(elt->name); free(elt->value); free(elt); break; } elt = elt->next; } return; } char *res_filename(void) { static char fname[FILENAME_MAX]; char *p; #ifdef WIN32 p = get_prog_dir(); if(p == NULL) return NULL; strcpy(fname, p); strcat(fname, "\\seaview.ini"); #else p = getenv("HOME"); if(p == NULL) return NULL; strcpy(fname, p); strcat(fname, "/.seaviewrc"); #endif return fname; } void load_resources(const char *progname) { FILE *in; char *fname, *p, line[500]; item *elt, *last = NULL; fname = res_filename(); if(fname == NULL) return; in = fopen(fname, "r"); if(in == NULL) return; while((p = fgets(line, sizeof(line), in)) != NULL) { p = strchr(line, '\n'); if(p != NULL) *p = 0; p = strchr(line, '='); if(p == NULL) continue; *(p++) = 0; while(isspace(*p)) p++; if(*p == 0) continue; elt = (item *)malloc(sizeof(item)); if(elt == NULL) break; elt->name = strdup(line); elt->value = strdup(p); if(elt->name == NULL || elt->value == NULL) break; if(last != NULL) last->next = elt; else firstitem = elt; elt->before = last; last = elt; elt->next = NULL; } fclose(in); } char *get_res_value(const char *name, const char *def_value) { item *elt = firstitem; while(elt != NULL) { if(strcmp(name, elt->name) == 0) return elt->value; elt = elt->next; } return (char *)def_value; } int set_res_value(const char *name, const char *value) { item *elt, *last = NULL; elt = firstitem; while(elt != NULL) { if(strcmp(elt->name, name) == 0) { free(elt->value); elt->value = strdup(value); return 0; } last = elt; elt = elt->next; } elt = (item *)malloc(sizeof(item)); if(elt == NULL) return 1; elt->name = strdup(name); elt->value = strdup(value); if(elt->name == NULL || elt->value == NULL) return 1; if(last != NULL) last->next = elt; else firstitem = elt; elt->before = last; elt->next = NULL; return 0; } int sort_items(const void *i1, const void *i2) { return strcmp( (*(item **)i1)->name, (*(item **)i2)->name); } int save_resources(void) { char *fname; item *elt; FILE *out; int count, i; item **table; fname = res_filename(); if(fname == NULL) return 1; out = fopen(fname, "w"); if(out == NULL) return 1; elt = firstitem; count = 0; while(elt != NULL) { count++; elt = elt->next; } table = (item **)malloc(count * sizeof(item *)); if(table != NULL) { elt = firstitem; i = 0; while(elt != NULL) { table[i++] = elt; elt = elt->next; } qsort(table, count, sizeof(item *), sort_items); for(i = 0; i < count; i++) fprintf(out, "%s=%s\n", table[i]->name, table[i]->value); free(table); } else { elt = firstitem; while(elt != NULL) { fprintf(out, "%s=%s\n", elt->name, elt->value); elt = elt->next; } } fclose(out); return 0; } #endif int int_res_value(const char *name, int def_value) { int val = def_value; char *p = get_res_value(name, NULL); if( p != NULL ) sscanf(p, "%d", &val); return val; } int bool_res_value(const char *name, int def_value) { char *p = get_res_value(name, NULL); if( p == NULL ) return def_value; return (*p == 'T' || *p == 't'); } seaview/seaview.1000644 000765 000024 00000007017 12404325714 014560 0ustar00mgouystaff000000 000000 .\" Title: SEAVIEW .\" Author: Manolo Gouy .\" Generator: DocBook XSL Stylesheets v1.73.2 .\" Date: 05/27/2009 .\" Manual: Seaview Manual .\" Source: seaview 4.0 .\" .TH "SEAVIEW" "1" "05/27/2009" "seaview 4.0" "Seaview Manual" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .SH "NAME" seaview \- a multiplatform, graphical user interface for multiple sequence alignment and molecular phylogeny. .SH "SYNOPSIS" .HP 8 \fBseaview\fR [\fIfilename\fR] .SH "DESCRIPTION" .PP \fBseaview\fR is the program that starts the SeaView GUI\&. .PP SeaView is a graphical interface for multiple sequence alignment and molecular phylogeny\&. It is able to read various alignment formats (MSF, CLUSTAL, FASTA, PHYLIP, MASE, NEXUS) and the Newick tree format, and allows one to manually edit the alignment, to run DOT\-PLOT, CLUSTAL or MUSCLE programs to locally improve the alignment, and also to compute, draw and edit phylogenetic trees\&. .PP If started from the command line with \fIfilename\fR as an argument, seaview will open the alignment or tree stored in \fIfilename\fR\& and display/draw it on screen. Filename can be in any of the mase, clustal, phylip, msf, fasta, or nexus alignment formats or in the Newick tree format. .SH "OPTIONS" .PP \fB\-fast\fR .RS 4 Suppresses double buffering for display\&. This should only accelerate display on very slow systems\&. .RE .PP \fB\-fontsize\fR \fIn\fR .RS 4 Sets the font size to \fIn\fR\&. .RE .SH "FILES" .PP \fI\fI$HOME\fR\fR\fI/\&.seaviewrc\fR holds the user\'s configuration for SeaView\&. .SH "SEE ALSO" .PP The program is fully documented online\&. Press the "help" button in the main window\&. On Debian systems, the text template for SeaView\'s help can be found in \fI/usr/share/doc/seaview/seaview\&.html\fR\&. .PP Two multiple alignment programs can be called from whithin SeaView: \fBmuscle\fR(1) and \fBclustalw\fR(1)\&. .PP The home page of SeaView is http://pbil\&.univ\-lyon1\&.fr/software/seaview\&.html\&. .PP SeaView usees some components of the PHYLIP package, see \(oqhttp://evolution\&.genetics\&.washington\&.edu/phylip\&.html\(cq\&. .SH "REFERENCE" .PP If you use SeaView in a published work, please cite the following reference: Galtier, N\&., Gouy, M\&. and Gautier, C\&. (1996) SeaView and Phylo_win, two graphic tools for sequence alignment and molecular phylogeny\&. Comput\&. Applic\&. Biosci\&., 12, 543\-548\&. .SH "AUTHORS" .PP \fBManolo Gouy\fR <\&mgouy@biomserv\&.univ\-lyon1\&.fr\&> .sp -1n .IP "" 4 Upstream author of SeaView\&. .PP \fBStéphane Bortzmeyer\fR <\&bortzmeyer@debian\&.org\&> .sp -1n .IP "" 4 Wrote this manpage in DocBook XML for the Debian distribution\&. .PP \fBCharles Plessy\fR <\&plessy@debian\&.org\&> .sp -1n .IP "" 4 Updated this manpage in DocBook XML for the Debian distribution\&. .SH "COPYRIGHT" Copyright \(co 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Manolo Gouy .br Copyright \(co 1999 Stéphane Bortzmeyer .br Copyright \(co 2006, 2007, 2008, 2009 Charles Plessy .br .PP SeaView is released under the GNU General Public Licence, with a special permission to use some source files from the PHYLIP package\&. Because these files are used, you are not allowed generate revenue with SeaView\&. .PP You can redistribute and/or modify this manpage under same terms as SeaView itself\&. .PP On Debian systems, the complete text of the GNU General Public License version 2 can be found in \fI/usr/share/common\-licenses/GPL\-2\fR\&. .sp seaview/seaview.1.xml000644 000765 000024 00000014606 12404325714 015361 0ustar00mgouystaff000000 000000 Debian"> GNU"> GPL"> ]> &dhtitle; &dhpackage; &dhrelease; Manolo Gouy Upstream author of SeaView.
mgouy@biomserv.univ-lyon1.fr
Stéphane Bortzmeyer Wrote this manpage in DocBook XML for the Debian distribution.
bortzmeyer@debian.org
&dhfirstname; &dhsurname; Updated this manpage in DocBook XML for the Debian distribution.
&dhemail;
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 Manolo Gouy 1999 Stéphane Bortzmeyer 2006 2007 2008 2009 Charles Plessy SeaView is released under the GNU General Public Licence, with a special permission to use some source files from the PHYLIP package. Because these files are used, you are not allowed generate revenue with SeaView. You can redistribute and/or modify this manpage under same terms as SeaView itself. On Debian systems, the complete text of the GNU General Public License version 2 can be found in /usr/share/common-licenses/GPL-2.
&dhucpackage; &dhsection; &dhpackage; a multiplatform, graphical user interface for multiple sequence alignment and molecular phylogeny. &dhpackage; filename DESCRIPTION &dhpackage; is the program that starts the SeaView GUI. SeaView is a graphical interface for multiple sequence alignment and molecular phylogeny. It is able to read various alignment formats (MSF, CLUSTAL, FASTA, PHYLIP, MASE, NEXUS) and the Newick tree format, and allows one to manually edit the alignment, to run DOT-PLOT, CLUSTAL or MUSCLE programs to locally improve the alignment, and also to compute, draw and edit phylogenetic trees. If started from the command line with filename as an argument, &dhpackage; will open the alignment stored in filename and display/draw it on screen. Filename can be in any of the mase, clustal, phylip, msf, fasta, or nexus alignment formats or in the Newick tree format. OPTIONS Suppresses double buffering for display. This should only accelerate display on very slow systems. n Sets the font size to n. FILES $HOME/.seaviewrc holds the user's configuration for SeaView. SEE ALSO The program is fully documented online. Press the "help" button in the main window. On Debian systems, the text template for SeaView's help can be found in /usr/share/doc/seaview/seaview.html. Two multiple alignment programs can be called from whithin SeaView: muscle1 and clustalw1. The home page of SeaView is http://pbil.univ-lyon1.fr/software/seaview.html. SeaView uses some components of the PHYLIP package, see ‘http://evolution.genetics.washington.edu/phylip.html’. REFERENCE If you use SeaView in a published work, please cite the following reference: Galtier, N., Gouy, M. and Gautier, C. (1996) SeaView and Phylo_win, two graphic tools for sequence alignment and molecular phylogeny. Comput. Applic. Biosci., 12, 543-548.
seaview/seaview.appdata.xml000644 000765 000024 00000004117 12511564471 016633 0ustar00mgouystaff000000 000000 seaview.desktop CC0-1.0 GPL-3.0 SeaView GUI for multiple sequence alignment and molecular phylogeny

SeaView is a multiplatform, graphical user interface for multiple sequence alignment and molecular phylogeny.

  • SeaView reads and writes various file formats (NEXUS, MSF, CLUSTAL, FASTA, PHYLIP, MASE, Newick) of DNA and protein sequences and of phylogenetic trees.
  • SeaView drives programs muscle or Clustal-Omega for multiple sequence alignment, and also allows to use any external alignment algorithm able to read and write FASTA-formatted files.
  • Seaview drives the Gblocks program to select blocks of evolutionarily conserved sites.
  • SeaView computes phylogenetic trees by:
  • - parsimony, using PHYLIP's dnapars/protpars algorithm,
  • - distance, with NJ or BioNJ algorithms on a variety of evolutionary distances,
  • - maximum likelihood, driving program PhyML 3.1.
  • SeaView prints and draws phylogenetic trees on screen, SVG, PDF or PostScript files.
  • SeaView allows to download sequences from EMBL/GenBank/UniProt using the Internet.
http://doua.prabi.fr/binaries/seaview4.png The main alignment window used in the color-by-codon mode http://doua.prabi.fr/binaries/seaview-tree.png The tree window with some zoom-in applied http://doua.prabi.fr/software/seaview_data/PhyML-dialog.png Dialog window to perform Maximum-Likelihood tree-building http://doua.prabi.fr/software/seaview manolo.gouy_at_univ-lyon1.fr
seaview/seaview.cxx000644 000765 000024 00000521640 12536046274 015234 0ustar00mgouystaff000000 000000 // // Copyright 1996-2015 by Manolo Gouy. // // This program, except where indicated, is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; // either version 3 of the License, or (at your option) any later version. // // Three files (dnapars.c, protpars.c and seq.c) have a distinct license // which authorizes distribution. They are Copyright Joseph Felsenstein // // Three files (bionj.c, phyml_util.c and phyml_util.h) are also covered by the // GNU General Public License but are copyright Stephane Guindon. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // Additional permission under GNU GPL version 3 section 7 // // If you modify this Program, or any covered work, by linking or combining it with PHYLIP // (or a modified version of that library), containing parts covered by the terms of // the University of Washington license, the licensor of this Program grants you additional // permission to convey the resulting work. // // A copy of the GNU General Public License is available // from http://www.gnu.org/licenses/gpl.txt . // // Please report all bugs and problems to "manolo.gouy@univ-lyon1.fr". /* Version 4.2 10_OCT_2009 Added cladogram tree display and copy fasta-seqs to clipboard. Version 4.1 27_JUN_2009 Added nucleotide ambiguity symbols in consensus DNA sequences Version 4.0 27_MAY_2009 Added tree computing and drawing Version 3.2 22_OCT_2008 Import from databases: can use keyword 15_OCT_2008 WIN32: correct display of UTF8 filenames in window and messages Version 3.1 08_OCT_2008 now use Fl_Native_File_Chooser (with slightly changed macOS version) MacOS: correct display of UTF8 filenames in windows and menu and in messages for left-to-right scripts Version 3.0 11_SEP_2008 added File:Import from DB Version 2.4 04_MAR_2008 phylip format allows to customize max name length Version 2.3 22_FEB_2008 corrected bug if deleting/adding/moving seqs when in 'view as proteins' mode Version 2.2 6_OCT_2007 added support for multiple alignment windows Version 2.1 19_SEP_2007 added interface to external multiple alignment programs Version 2.0 22_AUG_2007 added Props:View as proteins added Edit:Set genetic code added Edit:Align all sequences added File:Save prot alignmnt */ #if !defined(WIN32) #include #endif #include "seaview.h" #include "treedraw.h" #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(__APPLE__) #include "seaview.xpm" #if !defined(WIN32) && SEAVIEW_FLTK_VERSION < 133 Fl_Offscreen seaview_X11_icon; #endif #endif /* allongement maximal prevu pour les seqs suite a edition */ #define MAX_SEQ_ALLONG 5000 #define CLIPBOARDMARK "seaview_alignment_clipboard:" /* Purpose resource argument type default exemple Default file format for saving operations save -save {mase, phylip, mase phylip clustal, msf, fasta, nexus} Control of printout options printoutblock N/A integer 10 3 printoutcpl N/A integer 80 90 [this is the paper width, not the # of residues desired on each line] printoutlpp N/A integer 66 90 Name of help file helpfile N/A string "seaview.help" Standard coloring of protein sequences (<= 10 colors + white for gaps) (colors are red, green, yellow, blue, cyan, magenta, salmon, purple, aquamarine, and dark-gray) stdcolorgroups N/A string EDQNHRKBZ,ILMV,APSGT,FY,WC BZDE,ACWY,FGHIK,LMNPQRSTV Alternate coloring of protein sequences altcolorgroups N/A string \0 AC,DEFGHIK,LMNPQRS,WY,TV Faster but less smooth writing fast -fast no-value False Residues colored on background inverted -inverted no-value False N/A filename */ Fl_Group *create_dna_scroller(SEA_VIEW *view, int x, int y, int w, int h, int dbl_buff); SEA_VIEW *create_the_form(int double_buffer); int prep_custom_colors(int *colors, char *customcolors, int max_colors); color_choice prep_aa_color_code(char *list_std, char *list_alt, int maxprotcolors, int *numb_stdprotcolors, int *numb_altprotcolors); void deplacer_grp_seqs(SEA_VIEW *view, int target); void del_gap_only_sites(SEA_VIEW *view); void reference_toggle(SEA_VIEW *view, int on); void help_callback(Fl_Widget *ob, void *unused); void help_items_callback(Fl_Widget *ob, void *data); void direct_help_callback(Fl_Widget *wgt, void *data); void handle_paste(SEA_VIEW *view, char *clipboard, int doing_dnd); void handle_mouse(SEA_VIEW *view, int mx, int my, int *p_selecting_seqs, int *p_sel_seq_move, int *p_modifying_segment); void handle_keyboard(SEA_VIEW *view, unsigned int key, int istext); void handle_push(SEA_VIEW *view, int mx, int my, int key, int *p_modifying_segment, int *p_selecting_seqs, int *p_sel_seq_move); int delete_gaps_before(SEA_VIEW *view, int numseq, int numsite, int total); void set_save_format(SEA_VIEW *view, int val); Fl_Window *use_initial_file(SEA_VIEW *view, char *masename, int doing_dnd); Fl_Window* pdfps_options_dialog(SEA_VIEW *view, bool autonomous); void mainwin_close_callback(Fl_Widget *form, void *data); void to_do_at_exit(void); SEA_VIEW *newwindow_callback(SEA_VIEW *old_view); //void fix_paste_timeout(void *); void hide_window_callback(Fl_Widget *ob, void *data); void free_colranks_by_difference(char **alt_col_rank, int total); char *create_tmp_filename(void); void delete_tmp_filename(const char *base_fname); void draw_seq_names(Fl_Widget *ob, SEA_VIEW *view); /* external functions */ void draw_comment_lines(Fl_Widget *ob, SEA_VIEW *view); char* seaview_file_chooser_save_as(const char* message, const char* fname, SEA_VIEW *view, known_format* new_format); void load_resources(const char *progname); char *get_res_value(const char *name, const char *def_value); int int_res_value(const char *name, int def_value); int bool_res_value(const char *name, int def_value); void minuscules(char *); known_format what_format(const char *filename); extern void custom_callback(Fl_Widget *obj, void *data); extern void stats_callback(Fl_Widget *obj, void *data); void adjust_menu_edit_modes(SEA_VIEW *view); extern void *set_viewasprots(SEA_VIEW * view, int onoff); extern void racnuc_dialog(SEA_VIEW *view); extern void disconnect_tree_windows(SEA_VIEW *view); extern void concatenate_dialog(SEA_VIEW *view); extern int get_ncbi_gc_from_comment(char *comment); extern "C" { char codaa(char *codon, int code); int get_acnuc_gc_number(int ncbi_gc); void compact(char *chaine); } #ifdef __APPLE__ extern char *mac_GetOutputFName_Plus(const char *dfault, const char *message, int use_only_button, const char *dirname); extern int find_windowmenuitem(Fl_Window *w); extern int add_windowmenuitem(const char *name, Fl_Window *w); extern void rename_windowmenuitem(const char *name, int rank); extern void delete_windowmenuitem(int rank); extern int set_res_value(const char *name, const char *value); extern void fl_mac_set_about( Fl_Callback *cb, void *user_data, int shortcut ); extern void MG_apple_inits(void); extern void mac_tmp_dir_name(char *buffer, int l); #elif defined(WIN32) extern char **getutf8args(int *pargc); #else extern void inform_prog_dir(const char *arg0); #endif extern int printout(SEA_VIEW *view, const char *filename, int fontsize, int block_size, Fl_Paged_Device::Page_Format pageformat, int vary_only, int ref0, int pdfkindvalue, Fl_Paged_Device::Page_Layout layout, int svg_width = 0); extern void set_ncbi_genetic_code(SEA_VIEW *view); extern void cre_align_menu(SEA_VIEW *view); extern void init_msa_algos(void); extern void parse_trees_from_header(char *header, SEA_VIEW *view); extern void decode_codon_colors(int *colors); extern void select_deselect_in_tree(SEA_VIEW *view); extern void format_conversion(int argc, char **argv); extern void command_line_phylogeny(int argc, char **argv); extern int command_line_align(int argc, char **argv); extern void concatenate_no_gui(int argc, char *argv[]); extern void save_bootstrap_replicates(const char *fname, int replicates, SEA_VIEW *view); /* global variables */ /* to control parameters of option printout */ Fl_Paged_Device::Page_Format printout_pageformat; Fl_Paged_Device::Page_Layout printout_layout = Fl_Paged_Device::PORTRAIT; int printout_block, printout_fontsize, printout_black = PDF_COLOR, print; int printout_vary = FALSE; const char *f_format_names[] = {"Mase", "Phylip", "Clustal", "MSF", "Fasta", "NEXUS"}; const char *f_format_exts[] = {"mase", "phy", "aln", "msf", "fst", "nxs"}; int nbr_formats = sizeof(f_format_names)/sizeof(char *); //char def_stdcolorgroups[] = "EDQNHRKBZ,ILMV,APSGT,FY,WC"; char def_stdcolorgroups[] = "KR,AFILMVW,NQST,HY,C,DE,P,G"; //int def_protcolors[] = // { FL_WHITE, FL_RED, FL_GREEN, FL_YELLOW, FL_BLUE, FL_CYAN, // FL_MAGENTA, 9/*salmon*/, 13/*purple*/, 14/*aquamarine*/, 8/*darkgray*/}; int def_protcolors_rgb[] = {255,255,255, /* white */ 230,51,25, 25,128,230, 25,204,25, 25,179,179, 230,128,128, 204,77,204, 204,204,0, 230,153,77, 128,128,128, 100,100,100 }; int numb_stdprotcolors, numb_altprotcolors; color_choice curr_color_choice; int max_protcolors = sizeof(def_protcolors_rgb) / sizeof(int) / 3; int *def_protcolors; const char *progname = "seaview"; char *clipboardfname = NULL; // name of temporary file used to hold copied data extern char aminoacids[]; // from misc_acnuc.c static int defaultfontsize = #ifdef WIN32 12; #else 14; #endif #ifdef WIN32 #define LINE_HEIGHT_FACTOR 0.85 #else #define LINE_HEIGHT_FACTOR 1. #endif static int pasted_from_what_source; // gives what source was used for paste: 0=selection, 1=clipboard extern void plotonly(int argc, char *argv[]); extern void printout_cmdline(int argc, char **argv); extern bool isarg(int argc, char *argv[], const char *arg); extern char *argname(int argc, char *argv[], const char *arg); int main(int argc, char *argv[]) { #if defined(WIN32) argv = getutf8args(&argc); #endif if (isarg(argc, argv, "-h")) { fputs("Usage:\nseaview [options] [alignment-or-tree-file]\n" "where alignment-or-tree-file is an optional sequence alignment or tree file to be read (always the last argument) and options are:\n" "-h display all program options and exit\n" "-fontsize n font size used for the tree plot or alignment windows\n" "-fast sequences will be displayed faster but less smoothly\n" " Options for non-interactive usage driven by command-line arguments\n" "(Use exactly one for a non-interactive seaview run. Add any sub-option described below)\n" "-convert convert an input alignment to another format (no window creation)\n" "-concatenate concatenate alignment(s) to the end of an input alignment (no window creation)\n" "-align align an input sequence file (no window creation)\n" "-build_tree compute a phylogenetic tree from an input alignment file (no window creation)\n" #ifndef NO_PDF "-printout draws a multiple sequence alignment to PDF/SVG (no window creation)\n" "-reroot modify the rooting of, or process otherwise, an input tree (no window creation)\n" "-plotonly draw an input tree in a pdf or svg file (no window creation)\n" #endif "\n" " Sub-options for -convert\n" " Use '-' as last argument to read alignment from standard input\n" "-output_format fmt format of the converted alignment file (mase, phylip, clustal, msf, fasta, or nexus)\n" "-o fname use fname as name of the converted alignment (default is built from input filename)\n" "-o - write the output alignment to standard output\n" "-translate translate input sequences to protein before outputting them (don't use -sites)\n" "-no_terminal_stop translate terminal stop codons as a gap (with -translate option)\n" "-del_gap_only_sites remove all gap-only sites from alignment (don't use the -sites option)\n" "-def_species_group group_name,group_member_ranks create a species group of given name and members\n" " (species group members are expressed with their ranks as in this example: 3-8,12,19)\n" "-def_site_selection name,endpoints create a selection of sites of given name and endpoints\n" " (site selection endpoints are expressed as in this example: 10-200,305,310-342)\n" "-gblocks create under the name 'Gblocks' a set of blocks of conserved sites with the Gblocks program\n" " (requires the nexus or mase output formats)\n" " -gblocks-specific options:\n" " -b4 allow smaller final blocks\n" " -b5 allow gaps within final blocks \n" " -b2 less strict flanking positions \n" " -b3 don't allow many contiguous nonconserved positions\n" "-sites selection_name use the named selection of sites from the input alignment \n" "-species species_group_name use the named group of species from the input alignment \n" "-bootstrap n writes n bootstrap replicates of the input alignment to the output file \n" "\n" " Sub-options for -concatenate \n" " Use '-' as last argument to read alignment from standard input\n" "-concatenate align1,... name(s) of alignment files to add at the end of the input alignment\n" "-by_rank identify sequences by their rank in alignments (rather than by their name)\n" "-output_format fmt format of the concatenated alignment (mase, phylip, clustal, msf, fasta, or nexus)\n" "-o fname use fname as name of the concatenated alignment (default is built from input filename)\n" "-o - write the concatenated alignment to standard output\n" "\n" " Sub-options for -align \n" " Use '-' as last argument to read sequence file from standard input\n" "-align_algo n rank (in seaview from 0) of alignment algorithm, otherwise use seaview's default alignment algorithm\n" "-align_extra_opts \"option1 ...\" additional options to use when running the alignment algorithm\n" "-align_at_protein_level translate and align input sequences and reproduce alignment at DNA level.\n" "-output_format fmt format of the output alignment (mase, phylip, clustal, msf, fasta, or nexus)\n" "-o fname use fname as name of the output alignment (default is built from input filename)\n" "-o - write the output alignment to standard output\n" "\n" " Sub-options for -build_tree (either -distance or -parsimony is required)\n" " Use '-' as last argument to read alignment from standard input\n" "-o fname use fname as name of the output tree\n" "-o - write the output tree to standard output\n" "-distance dist_name computes the tree with a distance method using dist_name (observed, JC, K2P, logdet, Ka, Ks, Poisson or Kimura)\n" "-distance_matrix fname don't compute the tree, but write to fname the matrix of pairwise distances\n" "-NJ compute the distance tree by the Neighbor-Joining method (default is BioNJ)\n" "-parsimony compute the tree by the parsimony method \n" "-search more|less|one controls how much rearrangement is done to find better trees (DNA parsimony only)\n" "-nogaps remove all gap-containing sites before computations\n" "-replicates n use n bootstrap replicates to compute tree branch support\n" "-jumbles n jumble sequence order n times (parsimony only)\n" "-gaps_as_unknown encode gaps as unknown character state (parsimony only)\n" "-sites selection_name use the named selection of sites from the input alignment \n" "-species species_group_name use the named group of species from the input alignment \n" #ifndef NO_PDF "\n" " Sub-options for -printout (-o fname is required)\n" " Use '-' as last argument to read alignment from standard input\n" "-o fname use fname as name of the output PDF/SVG file\n" "-o - write the printout to standard output\n" "-fontsize n font size used for the alignment printout (10 by default)\n" "-blocksize n divide sequences in blocks of size n (10 by default) separated by one space\n" "-svg w produce a file in SVG format of width w pixels\n" " (without this option, the output is in PDF format)\n" "-landscape write the alignment in landscape orientation (PDF output only)\n" "-letter write the alignment using Letter-sized pages (A4 by default, PDF output only)\n" "\n" " Sub-options for -reroot\n" " Use '-' as last argument to read input tree from standard input\n" "-outnewick filename write the resulting tree to named file in Newick format\n" "-outgroup name use tree leaf labelled 'name' as tree outgroup\n" "-outgroup \"name1,name2,name3\" use node at center of the 3 names as tree center\n" " and name3-containing clade as outgroup\n" "-ingroup \"name1,name2,name3\" use node at center of the 3 names as tree center\n" " and name1-containing clade as ingroup\n" "-root_at_center reroot the tree at its center\n" "-unroot remove the root from the input tree, if any\n" "-patristic_distances fname write to named file patristic distances for leaves of input tree\n" "-remove_bootstrap remove branch support values present in input tree\n" "\n" " Sub-options for -plotonly\n" "options -outgroup, -ingroup, -outnewick above plus the following:\n" " Use '-' as last argument to read tree from standard input\n" "-o fname use fname as name of the output plot (.pdf or .svg)\n" "-o - write the output plot to standard output (svg only)\n" "-svg draw the input tree in a .svg file (default is .pdf file)\n" "-unrooted draw the input tree in unrooted (circular) form\n" "-pagecount n number of pages used for the tree plot (pdf only)\n" "-letter use letter-sized paper for the tree plot\n" "-fontsize n font size used in the tree plot\n" "-lengths display branch lengths in the tree plot\n" "-bootstrap display branch support values in the tree plot\n" "-bootstrap_threshold x display branch supports if >= x\n" "-size WxH pixel Width and Height of tree plot (svg only) (default is 595x842)\n" "-match text display in color (red by default) tree labels containing this text (case is not significant)\n" "-color RRGGBB hexadecimal color used for matching labels (example: 00FF00 means green)\n" "-branch_width_as_support draw plot with branches of increasing widths with increasing support\n" "-support_threshold_high f support above which a branch is drawn with maximal width (def=.95)\n" "-support_threshold_low f support below which a branch is drawn with minimal width (def=.8)\n" #endif , stdout); fputs("\nSee http://doua.prabi.fr/software/seaview_data/seaview#Program%20arguments for more details\n", stdout); return 0; } #if !(defined(WIN32) || defined(__APPLE__)) inform_prog_dir(argv[0]); #endif #ifndef NO_PDF if ( isarg(argc, argv, "-remove_bootstrap") && !isarg(argc, argv, "-reroot")) { fprintf(stderr, "Must use also -reroot when -remove_bootstrap is used\n"); exit(1); } if (isarg(argc, argv, "-plotonly") || isarg(argc, argv, "-reroot")) { plotonly(argc, argv); return 0; } if (isarg(argc, argv, "-printout")) { printout_cmdline(argc, argv); return 0; } #endif if (isarg(argc, argv, "-convert")) { format_conversion(argc, argv); return 0; } if (isarg(argc, argv, "-build_tree")) { command_line_phylogeny(argc, argv); return 0; } if (isarg(argc, argv, "-concatenate")) { concatenate_no_gui(argc, argv); return 0; } if (isarg(argc, argv, "-align")) { return command_line_align(argc, argv); } #ifdef __APPLE__ MG_apple_inits(); #elif SEAVIEW_FLTK_VERSION >= 133 Fl_Pixmap* px = new Fl_Pixmap(seaview_xpm); const Fl_RGB_Image* icon = new Fl_RGB_Image(px); delete px; Fl_Window::default_icon(icon); delete icon; #elif !defined(WIN32) fl_open_display(); Fl_Pixmap *pixmap = new Fl_Pixmap(seaview_xpm); seaview_X11_icon = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), pixmap->w(), pixmap->h(), fl_visual->depth); fl_gc = XCreateGC(fl_display, seaview_X11_icon, 0, 0); fl_begin_offscreen(seaview_X11_icon); pixmap->draw(0,0); fl_end_offscreen(); delete pixmap; XFreeGC(fl_display, fl_gc); #endif Fl_Window::default_xclass("FLTK"); char *masename; int i; static int quick_and_dirty; load_resources(progname); init_msa_algos(); // access to resources #ifdef __APPLE__ quick_and_dirty = TRUE; #else quick_and_dirty = bool_res_value("fast", FALSE); #endif printout_block = int_res_value("printoutblock", 10); printout_fontsize = int_res_value("printoutfontsize", 10); if(strcmp( get_res_value("printoutpageformat", "A4") , "A4") == 0) printout_pageformat = Fl_Paged_Device::A4; else printout_pageformat = Fl_Paged_Device::LETTER; defaultfontsize = int_res_value("sequencefontsize", defaultfontsize); fl_message_font(FL_HELVETICA_BOLD, FL_NORMAL_SIZE ); // argument processing masename = NULL; i = 1; while(i < argc) { if(argv[i][0] != '-') masename = argv[i]; if(strcmp(argv[i], "-fast") == 0) quick_and_dirty = TRUE; if(strcmp(argv[i], "-fontsize") == 0) { if(++i < argc) sscanf(argv[i], "%d", &defaultfontsize); } i++; } clipboardfname = strdup( create_tmp_filename() ); atexit(to_do_at_exit); SEA_VIEW *view = create_the_form(!quick_and_dirty); //Fl::add_timeout(0.5, fix_paste_timeout); if (masename != NULL) use_initial_file(view, masename, FALSE); Fl::lock(); Fl::run(); return 0; } #ifdef __APPLE__ static void del_widget_callback(void *data) { ((Fl_Widget*)data)->do_callback(); } #endif Fl_Window *use_initial_file(SEA_VIEW *view, char *masename, int doing_dnd) /* returns the window containing the loaded data (alignment or tree) or NULL */ { known_format defaultformat; Fl_Window *w = NULL; defaultformat = what_format(masename); if ((int)defaultformat >= 0) { w = load_alignment_file(view, masename, NULL, defaultformat, doing_dnd); } else if((int)defaultformat == -2) {// a Newick tree FILE *in = fopen(masename, "r"); fseek(in, 0, SEEK_END); long l = ftell(in); fseek(in, 0, SEEK_SET); char *tree = (char *)malloc(l + 1); char *p = tree; while(l-- > 0) { char c = fgetc(in); if(c != '\n' && c != '\r') *(p++) = c; } *p = 0; fclose(in); w = treedraw(tree, view, extract_filename(masename), FALSE); if (view != NULL && view->tot_seqs == 0) { // closes an empty alignment window that opened the tree #ifdef __APPLE__ // necessary ≥ 10.10 when dropping treefile to program icon, or the empty window does not close well Fl::add_timeout(0.0, del_widget_callback, view->dnawin); #else view->dnawin->do_callback(); #endif } } else fl_alert("File %s\nis not of a format readable by seaview", masename); return w; } #ifdef _AIX /* sur IBM RISC __filbuf est en fait _filbuf utilise a l'interieur de xforms */ int __filbuf(FILE *fich) { return _filbuf(fich); } #endif class DNA_obj : public Fl_Widget { FL_EXPORT void draw(void); FL_EXPORT int handle(int); public: FL_EXPORT DNA_obj(int x,int y,int w,int h, void *view) : Fl_Widget(x,y,w,h,NULL) { this->user_data(view); } }; void out_of_memory(void) { Fl_Window *w; while((w = Fl::first_window()) != NULL) w->hide(); fl_alert("Seaview error: Not enough memory!"); exit(1); } void minuscules(char *p) { if(p == NULL) return; while(*p) { *p = tolower(*p); p++; } return; } const char *extract_filename(const char *fname) { static const char *p, *q; q = fname; if(q == NULL) return (char *)""; do { #ifdef __VMS p = strchr(q,']'); if(p == NULL) p = strchr(q,':'); #elif defined(WIN32) p = strchr(q,'\\'); #else p = strchr(q,'/'); #endif if(p != NULL) q = p+1; } while (p != NULL); return q; } char *create_tmp_filename() // returns a temporary file name in private memory or NULL // need to call delete_tmp_filename() after all temporary files usage { #if defined(WIN32) static char *buff = NULL; static int lbuff = 0; wchar_t *wc = _wtempnam(NULL, L"seaview_tmp"); if (wc != NULL) { FILE *in = _wfopen(wc, L"w"); if (in != NULL) fclose(in); int l = wcslen(wc); unsigned l2 = fl_utf8fromwc(NULL, 0, wc, l); if (l2+1 > lbuff) { lbuff = l2+1; buff = (char*)realloc(buff, lbuff); } fl_utf8fromwc(buff, l2+1, wc, l); } return buff; #else char *retval; int fd; static char buffer[PATH_MAX]; #ifdef __APPLE__ mac_tmp_dir_name(buffer, PATH_MAX); #else strcpy(buffer, "/tmp/"); #endif strcat(buffer, "seaview.XXXXXX"); if ((fd = mkstemp(buffer)) == -1) return NULL; close(fd); retval = buffer; return retval; #endif // WIN32 } #ifndef WIN32 void delete_tmp_filename(const char *base_fname) { char fname[PATH_MAX]; sprintf(fname, "PATH=/bin:/usr/bin rm \"%s\"*", base_fname); system(fname); } #endif void allonge_seqs(char **seq, int totseqs, int maxlen, int *eachlength, int tot_comment_lines, char **comment_line, char **pregion_line) { int num, l; char *newseq; for(num = 0; num < totseqs; num++) { l = eachlength[num]; newseq = (char *)malloc(maxlen+1); if(newseq==NULL) out_of_memory(); memcpy(newseq,seq[num],l+1); free(seq[num]); seq[num] = newseq; } for(num = 0; num < tot_comment_lines; num++) { l = strlen(comment_line[num]); newseq = (char *)malloc(maxlen+1); if(newseq == NULL) out_of_memory(); memcpy(newseq, comment_line[num], l+1); free(comment_line[num]); comment_line[num] = newseq; } if (pregion_line) *pregion_line = (char*)realloc(*pregion_line, maxlen + 1); } /* memoire pour contenir coloriage standard */ static int color_for_aa_gaps; static char std_aminoacids[30]; static int std_aa_color[30]; /* memoire pour contenir coloriage alternatif */ static char alt_aminoacids[30] = ""; static int alt_aa_color[30]; /* pointeurs vers coloriage courant */ static char *current_aminoacids; static int *current_aa_color; int decode_color_scheme(char *vlist, char *aas, int *aa_color, int maxprotcolors) { int nbr_colors = 1, current = 0, i; char *p, *list; list = strdup(vlist); if(list == NULL) return 1; aas[0] = 0; p=strtok(list,","); while( p!= NULL && nbr_colors < maxprotcolors) { strcat(aas,p); for(i=0; i < (int) strlen(p); i++) aa_color[current++] = nbr_colors; nbr_colors++; p=strtok(NULL,","); } free(list); return nbr_colors; } int prep_custom_colors(int *colors, char *customcolors, int max_colors) { char *nom; int rank = 0, r, g, b; Fl_Color col; if(*customcolors == 0) return max_colors; nom = strtok(customcolors, ","); while(nom != NULL && rank < max_colors - 1) { r = g = b = -1; sscanf(nom, "%d%d%d", &r, &g, &b); if( r>=0 && g>=0 && b>=0 ) col = fl_rgb_color(r, g, b); else col = FL_BLACK; colors[++rank] = (int)col; nom = strtok(NULL, ","); } return rank + 1; } color_choice prep_aa_color_code(char *list_std, char *list_alt, int maxprotcolors, int *numb_stdprotcolors, int *numb_altprotcolors) { /* couleur pour gaps = 1ere couleur connue (comptee a partir de 0) */ color_for_aa_gaps = 0; current_aminoacids = std_aminoacids; current_aa_color = std_aa_color; /* decodage du coloriage standard des proteines */ *numb_stdprotcolors = decode_color_scheme(list_std, std_aminoacids, std_aa_color, maxprotcolors); *numb_altprotcolors = 0; if(*list_alt == 0) return NO_ALT_COLORS; /* decodage du coloriage alternatif des proteines */ *numb_altprotcolors = decode_color_scheme(list_alt, alt_aminoacids, alt_aa_color, maxprotcolors); return USING_STANDARD_COLORS; } void set_aa_color_mode(color_choice choice) { if(choice == USING_ALT_COLORS) { current_aminoacids = alt_aminoacids; current_aa_color = alt_aa_color; } else { current_aminoacids = std_aminoacids; current_aa_color = std_aa_color; } } int get_color_for_aa( int key ) /* returns the color # used to display character key in protein */ { char *pos; pos = strchr(current_aminoacids, toupper(key) ); return ( pos == NULL ? color_for_aa_gaps : current_aa_color[pos - current_aminoacids] ); } int get_color_for_base( int key ) /* returns the color # used to display character key in DNA */ { int retval; if(key=='A' || key == 'a') retval = 1; else if(key=='C' || key == 'c') retval = 2; else if(key=='G' || key == 'g') retval = 3; else if(key=='T' || key == 't' || key=='U' || key == 'u') retval = 4; else retval = 0; return retval; } char **prepcolranks(char **seq, int totseqs, int maxlen, int *eachlength, int (*calc_color_function)( int ), int numb_gc, int allow_lower) { int num, l, i; char **colrank; if(totseqs == 0 || numb_gc == 1) return NULL; colrank=(char **)malloc(totseqs*sizeof(char *)); if(colrank == NULL) return NULL; for(num=0; numuser_data() ; int x, y, cursor_x, cursor_y, c, max_curs_coord; char *debut, *fin; int background, foreground; static char lettre[]="A"; static char cursor_coord[200]; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); int byreference = (menu_props + props_parts->reference)->value(); if( (!cursor_in_comment) && (seq == 0 || site > view->each_length[seq-1] + 1) ) return; cursor_x = site - view->first_site; if(cursor_in_comment) { if(view->tot_comment_lines == 0 || !view->show_comment_lines) return; if(cursor_x < 0 || cursor_x >= view->tot_sites ) return; if(seq <= 0 || seq > view->tot_comment_lines ) return; y = view->y_seq + (seq + view->pos_first_comment_line - 2) * view->line_height; x = view->x_seq + cursor_x * view->char_width; lettre[0] = view->comment_line[seq-1][site-1]; } else { if(view->tot_seqs == 0) return; if (view->old_cursor_seq != seq) { view->draw_names = view->old_cursor_seq; // ecrire en noir nom ancien curseur draw_seq_names(view->DNA_obj, view); } view->draw_names = seq; // ecrire en jaune nom nouveau curseur draw_seq_names(view->DNA_obj, view); view->draw_names = -1; cursor_y = seq - view->first_seq; if(cursor_x < 0 || cursor_x >= view->tot_sites || cursor_y < 0 || cursor_y >= view->tot_lines ) { return; } y = view->y_seq + cursor_y * view->line_height; x = view->x_seq + cursor_x * view->char_width; lettre[0] = view->sequence[seq-1][site-1]; if(!view->allow_lower) lettre[0] = toupper(lettre[0]); if(byreference && (!on_off) && seq >= 2) { if(toupper(lettre[0]) == toupper(view->sequence[0][site-1])) lettre[0] = '.'; } } if(view->numb_gc == 1) { /* cas noir et blanc */ if(on_off) { foreground = FL_WHITE; background = FL_BLACK; } else { foreground = FL_BLACK; background = FL_WHITE; } } else if( (!cursor_in_comment) && view->inverted_colors) { /* cas inverted colors */ if(site <= view->each_length[seq - 1]) { if( (c = (int)view->col_rank[seq-1][site-1]) == 0) background = ob->color(); else background = view->curr_colors[c]; } else background = ob->color(); if(on_off) { foreground = background; background = FL_BLACK; } else { if(view->active_region == NULL || view->region_line[site - 1] == 'X') foreground = FL_BLACK; else foreground = ob->selection_color(); } } else if(cursor_in_comment) { /* dans les lignes comment sur ecran couleur */ if(on_off) { foreground = FL_WHITE; background = FL_BLACK; } else { foreground = FL_BLACK; background = ob->color(); } } else { /* cas colored letters */ if( site <= view->each_length[seq - 1]) { foreground = view->curr_colors[(unsigned)view->col_rank[seq-1][site-1]]; } else { lettre[0] = ' '; foreground = FL_BLACK; } if(on_off) { background = FL_BLACK; } else { if( (!cursor_in_comment) && view->active_region != NULL && view->region_line[site - 1] == 'X') background = ob->selection_color(); else background = ob->color(); } } fl_font(ob->labelfont(), ob->labelsize()); fl_color(background); fl_rectf( x, y - view->line_height + fl_descent(), view->char_width, view->line_height); fl_color(foreground); fl_draw(lettre, 1, x, y); if(on_off) { /* ecriture des coordonnees du curseur */ max_curs_coord = view->tot_sites - 14; x = view->x_seq + 7 * view->char_width; y = view->y_seq - view->line_height; fl_font(FL_COURIER, ob->labelsize()); fl_color(ob->color()); fl_rectf( x, y - view->line_height, (max_curs_coord ) * view->char_width, view->line_height + fl_descent()); if(!cursor_in_comment) { debut = view->sequence[seq-1] - 1; fin = debut + site; c = 0; if(*fin == 0) fin--; while(++debut <= fin) if( *debut != '-' ) c++; sprintf(cursor_coord, "Seq:%d", seq); if(view->curr_colors == view->codoncolors) {//codon mode: write amino acid name int aanum; static char aa3[] = "ArgLeuSerThrProAlaGlyValLysAsnGlnHisGluAspTyrCysPheIleMetTrpTER??? "; char *codonstart = view->sequence[seq - 1] + ((site - 1)/3) * 3; if(codonstart+2 - view->sequence[seq - 1] < view->each_length[seq-1] && memchr(codonstart, '-', 3) == NULL) {//gap-less codon char aa = codaa(codonstart, get_acnuc_gc_number(get_ncbi_gc_from_comment(view->comments[seq - 1]))); aanum = strchr(aminoacids, aa) - aminoacids; } else aanum = 22;//write spaces for gap-with codon sprintf(cursor_coord + strlen(cursor_coord), " %.3s", aa3 + 3 * aanum); } sprintf(cursor_coord + strlen(cursor_coord), " Pos:%d|%d [%.150s]", site, c, view->seqname[seq - 1]); } else sprintf(cursor_coord, "Pos:%d", site); fl_color(view->namecolor); if (max_curs_coord >= 0 && (unsigned)max_curs_coord < sizeof(cursor_coord)) cursor_coord[max_curs_coord] = 0; fl_draw(cursor_coord, x, y); } } void draw_seq_names(Fl_Widget *ob, SEA_VIEW *view) { int x, y, num, debut, fin; int couleur; static char trunc_name[20]; x = view->x_name; y = view->y_name; fl_font(FL_COURIER, ob->labelsize() ); debut = view->first_seq - 1; fin = view->first_seq - 2 + view->tot_lines; if(fin >= view->tot_seqs) fin = view->tot_seqs - 1; if(view->draw_names == -1) { /* ecrire tous les noms */ fl_color(ob->color()); fl_rectf( ob->x(), ob->y(), /* fond pour les noms */ view->x_seq - ob->x(), ob->h() - 4 /* 2 * BORDER_WIDTH */); /* write region name */ if(view->active_region != NULL) { fl_color(view->region_color); fl_font(ob->labelfont(), ob->labelsize()); fl_draw(view->active_region->name, FL_min((unsigned)view->wid_names, strlen(view->active_region->name)), view->x_name, view->y_name + FL_min(view->tot_lines, view->tot_seqs) * view->line_height ); fl_font(FL_COURIER, ob->labelsize() ); } } else if(view->draw_names == -2) { /* ecrire tous les noms mais rien qu'eux */ fl_color(ob->color()); fl_rectf( ob->x(), /* fond pour les noms */ y - view->line_height + fl_descent(), view->x_seq - ob->x(), (fin - debut + 1) * view->line_height); } else { /* ecrire un seul nom */ debut = fin = view->draw_names - 1; if(debut < view->first_seq - 1) return; y += view->line_height * (view->draw_names - view->first_seq); if( !view->sel_seqs[view->draw_names - 1] ) { fl_color(ob->color()); fl_rectf( x, y - view->line_height + fl_descent(), (view->wid_names+1) * view->char_width, view->line_height); } } if(view->tot_seqs > 0) { /* nbre de seqs selectionnees */ fl_color(ob->color()); fl_rectf( x, view->y_name - 2 * view->line_height, (view->wid_names+1) * view->char_width, view->line_height); sprintf(trunc_name, "sel=%d", view->tot_sel_seqs); fl_color(view->namecolor); fl_draw(trunc_name, x, view->y_name - view->line_height ); } /* le(s) nom(s) a ecrire */ for(num = debut; num <= fin; num++) { if(view->sel_seqs[num]) { fl_color(FL_BLACK); fl_rectf( x, y - view->line_height + fl_descent(), (view->wid_names+1) * view->char_width, view->line_height); couleur = FL_WHITE; } else couleur = view->namecolor; if (num == view->cursor_seq - 1) { // set name of cursor-containing seq in bold if (view->sel_seqs[num]) couleur = FL_DARK2; fl_font(fl_font()|FL_BOLD, fl_size()); } fl_color(couleur); fl_draw(view->seqname[num], FL_min((unsigned)view->wid_names, strlen(view->seqname[num])), x, y ); if (num == view->cursor_seq - 1) { fl_font(fl_font()&~FL_BOLD, fl_size()); } y += view->line_height; } } void draw_header(Fl_Widget *ob, SEA_VIEW *view) { static char site_line[10]; if(view->mod_seq) return; if(view->tot_seqs == 0) return; if(view->active_region != NULL) draw_region_line(ob, view); /* write site numbers */ if (view->tot_sites < 7) return; fl_color(ob->color()); fl_rectf( view->x_seq, view->y_seq - 2 * view->line_height + fl_descent(), view->tot_sites * view->char_width, view->line_height); fl_color(view->namecolor); fl_font(FL_COURIER, ob->labelsize() ); sprintf(site_line, "%d", view->first_site); fl_draw(site_line, view->x_seq, view->y_seq - view->line_height); sprintf(site_line, "%7d", view->first_site + view->tot_sites - 1); fl_draw(site_line, view->x_seq + (view->tot_sites - 7)*view->char_width, view->y_seq - view->line_height); } void draw_dna_seqs(Fl_Widget *ob, SEA_VIEW *view) { int nline, offset, x, y, i, l_line, y_back, need_back, isreference; char *pos; int debut, fin, use_region; list_segments *segment, *first_segment; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); int byreference = (menu_props + props_parts->reference)->value(); static int first = TRUE; static char **clines;//holds color-specific lines if(first) { first = FALSE; clines = new char*[22]; for(i=0; i < 22; i++) clines[i] = new char[1000]; } if(view->mod_seq == 0) { /* draw all lines */ debut = view->first_seq - 1; fin = FL_min(view->first_seq + view->tot_lines - 1, view->tot_seqs) - 1; } else if(view->mod_seq == -1) { /* draw only selected lines */ debut = view->first_seq - 1; fin = FL_min(view->first_seq + view->tot_lines - 1, view->tot_seqs) - 1; while(fin >= debut && !view->sel_seqs[fin]) fin--; if(debut > fin) return; while(!view->sel_seqs[debut]) debut++; } else { /* draw just line # view->mod_seq */ debut = fin = view->mod_seq - 1; if(debut < view->first_seq - 1) fin = debut - 1; } // prepare for drawing region background use_region = (view->active_region != NULL && view->numb_gc > 1 && (first_segment = view->active_region->list) != NULL); if(use_region) { do { if(first_segment->debut > view->first_site + view->tot_sites - 1) { use_region = FALSE; break; } if(first_segment->fin >= view->first_site) break; first_segment = first_segment->next; } while(first_segment != NULL); if(first_segment == NULL) use_region = FALSE; } need_back = TRUE; if(use_region) { if(first_segment->debut <= view->first_site && first_segment->fin >= view->first_site + view->tot_sites - 1) need_back = FALSE; } /* write sequences */ fl_font( ob->labelfont(), ob->labelsize() ); x = view->x_seq; y = view->y_seq + (debut - (view->first_seq - 1)) * view->line_height; y_back = y - view->line_height + fl_descent(); offset = view->first_site - 1; for(nline = debut; nline <= fin; nline++) { isreference = (byreference && (nline > 0)); if( view->mod_seq != -1 || view->sel_seqs[nline] ) { if(need_back) { /* write seq background */ fl_color(ob->color()); fl_rectf( x, y_back, view->tot_sites * view->char_width, view->line_height); } if(use_region) { /* write regions background */ int deb_block, fin_block; fl_color(ob->selection_color()); segment = first_segment; do { deb_block = FL_max( segment->debut, view->first_site); fin_block = FL_min(segment->fin, view->first_site + view->tot_sites - 1); fl_rectf(x+(deb_block - view->first_site)* view->char_width, y_back, (fin_block - deb_block + 1) * view->char_width, view->line_height); segment = segment->next; } while(segment != NULL && segment->debut <= view->first_site + view->tot_sites - 1); } if(view->each_length[nline] > offset) { l_line = FL_min( view->tot_sites, view->each_length[nline] - offset ); // write DNA seqs if(view->numb_gc > 1) { char residue; pos = view->sequence[nline] + offset; char *pos0 = view->sequence[0] + offset; for(i=0; i < view->numb_gc; i++) { memset(clines[i], ' ', l_line); clines[i][l_line] = 0; } for( i = 0; i < l_line; i++) {//fill color-specific lines if(isreference && toupper(*pos) == toupper(*pos0)) residue = '.'; else residue = *pos; if(!view->allow_lower) residue = toupper(residue); clines[ (unsigned)view->col_rank[nline][offset + i] ][i] = residue; pos++; pos0++; } for(i=0; i < view->numb_gc; i++) {//draw color-specific lines fl_color(view->curr_colors[i]); fl_draw(clines[i], l_line, x, y); } } else { pos = view->sequence[nline]; fl_color(view->curr_colors[0]); fl_draw(pos + offset, l_line, x, y ); } } } y += view->line_height; y_back += view->line_height; } draw_header(ob, view); } void draw_dna_seqs_inverted(Fl_Widget *ob, SEA_VIEW *view) { int nline, c, offset, x, y, l_line, xx, yy, firstline, lastline, use_region, debut, fin, der_site; int pos; list_segments *segment, *first_segment; int save_col0; static char up_line[1000]; char *p, *q, *r; int i; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); int byreference = (menu_props + props_parts->reference)->value(); if(view->tot_seqs == 0) { return; } fl_font(ob->labelfont(), ob->labelsize() ); save_col0 = view->curr_colors[0]; view->curr_colors[0] = ob->color(); /* write sequences */ x = view->x_seq; offset= view->first_site - 1; if(view->mod_seq <= 0) { firstline = view->first_seq-1; lastline = FL_min(view->first_seq + view->tot_lines -1, view->tot_seqs); } else { firstline = view->mod_seq - 1; lastline = firstline + 1; if(firstline < view->first_seq - 1) lastline = firstline - 1; } use_region = (view->active_region != NULL && (first_segment = view->active_region->list) != NULL); if(use_region) { do { if(first_segment->fin >= view->first_site) break; first_segment = first_segment->next; } while(first_segment != NULL); } y = view->y_seq + (firstline - view->first_seq + 1) * view->line_height; yy = y - view->line_height + fl_descent(); //ecriture du fond gris fl_color(ob->color()); fl_rectf( x, yy, view->tot_sites * view->char_width, (lastline - firstline) * view->line_height); // for(nline=firstline; nline < lastline; /* ecriture des fonds de couleur */ nline++, y += view->line_height, yy += view->line_height ) { l_line = ( offset + view->tot_sites < view->each_length[nline] ? view->tot_sites : view->each_length[nline] - offset); l_line = FL_max(l_line, 0); /* nbre de caract a ecrire */ if(l_line > 0) { xx = x; for(pos = offset; pos < offset + l_line; pos++) { if( (c = (int)view->col_rank[nline][pos]) != 0 ) { fl_color(view->curr_colors[c]); fl_rectf( xx, yy, view->char_width, view->line_height); } xx += view->char_width; } } if(l_line < view->tot_sites) { /* au dela de la fin de la seq */ fl_color(ob->color()); fl_rectf( x + l_line * view->char_width, yy, view->char_width * (view->tot_sites - l_line), view->line_height); } if(l_line == 0) continue; /*ecriture des seqs: regions en noir et autres en col2 */ fl_color( use_region ? ob->selection_color() : FL_BLACK ); p = view->sequence[nline] + offset; memcpy(up_line, p, l_line); up_line[l_line] = 0; p = up_line; if(!view->allow_lower) majuscules(up_line); if(byreference && nline != 0) { q = p + l_line; i = 0; r= view->sequence[0] + offset; while( p < q) { up_line[i++] = (toupper(*p) == toupper(*r) ? '.' : *p); p++; r++; } p = up_line; } fl_draw(p, l_line, x, y); if(use_region) { /* re-ecrire les regions en noir */ der_site = view->first_site + l_line - 1; segment = first_segment; fl_color( FL_BLACK ); while( segment != NULL ) { if(segment->debut > der_site) break; debut = FL_max(segment->debut, view->first_site); fin = FL_min(segment->fin, der_site); p = up_line + debut - offset - 1; fl_draw(p, fin - debut + 1, x + (debut - offset - 1)*view->char_width, y); segment = segment->next; } } } view->curr_colors[0] = save_col0; draw_header(ob, view); } void set_tot_lines(SEA_VIEW *view, int new_val) { int l; double x; view->tot_lines = new_val; l = view->tot_seqs - view->tot_lines + 1; if(l<1) l=1; if(view->first_seq > l) { view->first_seq = l; } if(view->tot_seqs > 0) { x = view->tot_lines / ( (double) view->tot_seqs ); if(x>1) x=1; } else x = 1; view->vertsli->slider_size(x); view->vertsli->bounds(1, l); view->vertsli->Fl_Slider::value(view->first_seq); } int compute_size_params(SEA_VIEW *view, int force_recompute) { static int old_w = 0; static int old_h = 0; static Fl_Widget *old_dna_obj = NULL; Fl_Widget *ob = view->DNA_obj; double x; int l, tot_lines, possible_lines; if( !force_recompute && old_dna_obj == ob && ob->w() == old_w && ob->h() == old_h) return FALSE; old_w = ob->w(); old_h = ob->h(); old_dna_obj = ob; view->x_name = view->char_width/2 + ob->x(); view->y_name = 2 * view->line_height + ob->y(); view->x_seq = (view->wid_names +2) * view->char_width + ob->x(); view->y_seq = view->y_name; view->tot_sites = ( ob->w() - view->x_seq - ob->x() ) / view->char_width; possible_lines = ( ob->h() - 4 ) / view->line_height - 1; tot_lines = possible_lines; if(view->active_region != NULL) tot_lines--; if(view->show_comment_lines) { tot_lines -= view->tot_comment_lines; view->pos_first_comment_line = FL_min(tot_lines, view->tot_seqs) + 1; if(view->active_region != NULL) ++(view->pos_first_comment_line); } /* init sliders bounds and size */ if(view->tot_seqs > 0) { x = ( (double) view->tot_sites ) / ( view->seq_length + 3 ); if(x>1) x=1; } else x = 1; view->horsli->slider_size(x); l = view->seq_length - view->tot_sites+3; if(l<1) l=1; view->horsli->bounds(1,l); if(view->first_site > l) { view->first_site = l; } view->horsli->Fl_Slider::value(view->first_site); set_tot_lines(view, tot_lines); if(view->tot_seqs + (view->show_comment_lines ? view->tot_comment_lines : 0) + (view->active_region != NULL ? 1 : 0) < possible_lines) { /* forcer effacement de tout l'alignement pour ne pas garder de mauvaises lignes regions ou footers en bas */ ob->parent()->redraw(); } return TRUE; } int compute_wid_names(SEA_VIEW *view, int totseqs) { int i, l, maxnamewidth, wid_names = 0; for(i=0; iseqname[i]); while(l > 0 && view->seqname[i][l-1] == ' ') l--; view->seqname[i][l] = 0; if(l > wid_names) wid_names = l; } if(totseqs > 0 && wid_names < 10) wid_names = 10; maxnamewidth = int_res_value("maxnamewidth", 20); if(wid_names > maxnamewidth) wid_names = maxnamewidth; return wid_names; } int calc_max_seq_length(int seq_length, int tot_seqs) { int max_seq_length = (int)(1.3 * seq_length); if(tot_seqs <= 5000) { max_seq_length = FL_max(max_seq_length, seq_length + MAX_SEQ_ALLONG); } else { max_seq_length = FL_max(max_seq_length, seq_length + 500); } return max_seq_length; } void init_dna_scroller(SEA_VIEW *view, int totseqs, const char *masename, int protein, char *header) { int i, l; list_regions *mylregion; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); Fl_Menu_Item *item; view->header = header; view->tot_seqs = totseqs; view->seq_length = 0; view->protein = protein; view->allow_seq_edit = FALSE; view->viewasprots = NULL; item = menu_props + props_parts->viewasprots; item->clear(); if(protein) item->deactivate(); else item->activate(); item = menu_props + props_parts->edit; item->activate(); item->clear(); item = menu_props + props_parts->keys; item->clear(); (item + 1)->clear(); (item + 2)->clear(); item = menu_props + props_parts->keys - 1; if(protein) item->deactivate(); else item->activate(); item = menu_props + props_parts->reference; item->clear(); item->deactivate(); view->hjkl = FALSE; set_seaview_modified(view, FALSE); if(masename != NULL) { view->masename = (char *)malloc(strlen(masename)+1); if(view->masename == NULL) out_of_memory(); strcpy(view->masename, masename); view->dnawin->label(extract_filename(view->masename)); #ifdef __APPLE__ rename_windowmenuitem(view->dnawin->label(), find_windowmenuitem(view->dnawin)); #endif } else view->masename = NULL; if(totseqs > 0) { view->each_length = (int *)malloc(totseqs * sizeof(int)); if(view->each_length == NULL) out_of_memory(); } for(i = 0; i < totseqs; i++) { l = strlen(view->sequence[i]); view->each_length[i] = l; if(l > view->seq_length) view->seq_length = l; } for(i = 0; i < view->tot_comment_lines; i++) { l = strlen(view->comment_line[i]); if(l > view->seq_length) view->seq_length = l; } view->max_seq_length = calc_max_seq_length(view->seq_length, view->tot_seqs); view->wid_names = compute_wid_names(view, totseqs); allonge_seqs(view->sequence, totseqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, NULL); if(view->numb_dnacolors > 1 && view->menu_props != NULL) { /* DNA/prot modes useful only with colors */ item = menu_props + props_parts->colors; if(view->alt_colors != NO_ALT_COLORS) (item+2)->activate(); if(protein) { if(view->alt_colors == USING_ALT_COLORS) { (item+2)->setonly(); set_aa_color_mode(USING_ALT_COLORS); view->numb_gc = view->numb_altprotcolors; view->curr_colors = view->altprotcolors; } else { (item+1)->setonly(); set_aa_color_mode(USING_STANDARD_COLORS); view->numb_gc = view->numb_stdprotcolors; view->curr_colors = view->stdprotcolors; } } else { item->setonly(); view->numb_gc = view->numb_dnacolors; view->curr_colors = view->dnacolors; } } if(view->numb_gc > 1) { view->col_rank = prepcolranks(view->sequence, totseqs, view->max_seq_length, view->each_length, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); if(view->col_rank == NULL) out_of_memory(); view->alt_col_rank = NULL; } view->first_seq = view->first_site = 1; #ifdef WIN32 Fl::flush();//necessary against bug with "Edit/Create seq" with FLTK 1.3 #endif fl_font(view->DNA_obj->labelfont(), view->DNA_obj->labelsize()); view->line_height = (int)( LINE_HEIGHT_FACTOR * fl_height() ); view->char_width = (int)(fl_width("W") + 0.5); view->draw_names = -1; view->mod_cursor = FALSE; view->mod_seq = 0; view->multipl->argument(0); if(view->tot_seqs == 0) view->cursor_seq = view->cursor_site = 0; else view->cursor_seq = view->cursor_site = 1; view->old_cursor_seq = view->cursor_seq; view->old_cursor_site = view->cursor_site; view->cursor_in_comment = view->old_cursor_in_comment = FALSE; view->tot_sel_seqs = 0; if(view->menu_edit != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_edit; items[RENAME_SEQ].deactivate(); items[EDIT_COMMENTS].deactivate(); items[EDIT_SEQ].deactivate(); items[DUPLICATE_SEQ].deactivate(); items[DELETE_SEQ].deactivate(); items[COMPLEMENT_SEQ].deactivate(); items[REVERSE_SEQ].deactivate(); items[EXCHANGE_UT].deactivate(); items[DOT_PLOT].deactivate(); items[CONSENSUS_SEQ].deactivate(); items[DELETE_GAP_ONLY_SITES].activate(); items[SET_GCODE].deactivate(); items[COPY_SEQS].deactivate(); } if(view->menu_align != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_align; items[ALIGN_SELECTED_SEQS].deactivate(); items[ALIGN_SITES].deactivate(); items[PROFILE].deactivate(); items[UNALIGN].deactivate(); } if(view->tot_seqs > 0) { view->sel_seqs = (int *)calloc(view->tot_seqs, sizeof(int)); if(view->sel_seqs == NULL) out_of_memory(); } /* initialiser les regions et leur menu avec pas de region active */ view->mod_region_line = FALSE; if(view->tot_seqs > 0) { view->region_line = (char *)malloc(view->max_seq_length + 1); if(view->region_line == NULL) out_of_memory(); } view->region_length = 0; view->active_region = NULL; if(view->menu_sites != NULL) { if(view->tot_seqs > 0) (view->menu_sites->get_menu())->activate(); mylregion = view->regions; view->menu_sites->vclear(); while(mylregion != NULL) { view->menu_sites->add(mylregion->element->name, regions_menu_callback, NULL, FL_MENU_RADIO); mylregion = mylregion->next; } } if(view->menu_species != NULL) { view->menu_species->vclear(); for (i=0; i < view->numb_species_sets; i++) { view->menu_species->add(view->name_species_sets[i], species_menu_callback, NULL, FL_MENU_RADIO); } } view->show_comment_lines = (view->tot_comment_lines > 0); view->active_comment_line = 0; update_menu_footers(view); compute_size_params(view, TRUE); view->DNA_obj->take_focus(); } void mod_multipl(SEA_VIEW *view, int newval) { Fl_Widget *obj = view->multipl; static char label[16]; int old = obj->argument(); if(newval == 0) sprintf(label, "%s-+_", view->movekeys); else sprintf(label, "mult=%d", newval); obj->argument(newval); obj->label(label); if(newval != old) obj->redraw(); } void rename_sequence(SEA_VIEW *view) { char *new_name; const char *rep; int num; if(view->tot_sel_seqs != 1) return; /* only by security, should not happen */ num = 0; while( ! view->sel_seqs[num] ) num++; rep = fl_input("Rename:",view->seqname[num]); if(rep == NULL) return; new_name = (char *)malloc(strlen(rep)+1); if(new_name == NULL) return; free(view->seqname[num]); strcpy(new_name, rep); view->seqname[num] = new_name; if(num+1 >= view->first_seq && num+1 <= view->first_seq+view->tot_lines-1) { view->wid_names = compute_wid_names(view, view->tot_seqs); compute_size_params(view, TRUE); view->DNA_obj->redraw(); } set_seaview_modified(view, TRUE); } void del_gap_only_sites(SEA_VIEW *view) { int position, numseq, allgaps, inrun, debut, count; view->seq_length = 0; for(numseq = 0; numseq < view->tot_seqs; numseq++) if(view->each_length[numseq] > view->seq_length) view->seq_length = view->each_length[numseq]; inrun = FALSE; position = -1; while( ++position <= view->seq_length) { for(numseq = 0; numseq < view->tot_seqs; numseq++) if(position < view->each_length[numseq] && view->sequence[numseq][position] != '-') break; allgaps = (numseq >= view->tot_seqs); if(position >= view->seq_length) allgaps = FALSE; if(inrun == allgaps) continue; if(allgaps && !inrun) { inrun = TRUE; debut = position; } else { inrun = FALSE; count = position - debut; for(numseq = 1; numseq <= view->tot_seqs; numseq++) delete_gaps_before(view, numseq, debut + count + 1, count); view->seq_length -= count; if(view->cursor_site > position) view->cursor_site -= count; if(view->regions != NULL) delete_region_part(view, debut + count + 1, count); if(view->tot_comment_lines > 0) delete_in_all_comments(count, debut + count + 1, view); position -= count; } } view->seq_length = 0; for(numseq = 0; numseq < view->tot_seqs; numseq++) if(view->each_length[numseq] > view->seq_length) view->seq_length = view->each_length[numseq]; } int delete_selected_seqs(SEA_VIEW *view) { void **temp_data; char **viewasprots = (char **)view->viewasprots; int new_tot_seqs, i, j, *temp_int, numset; new_tot_seqs = view->tot_seqs - view->tot_sel_seqs; if(new_tot_seqs > 0) { temp_data = (void **)malloc(new_tot_seqs * sizeof(void *)); if(temp_data == NULL) return TRUE; temp_int = (int *)malloc(new_tot_seqs * sizeof(int)); if(temp_int == NULL) return TRUE; } for(i = 0, j = 0; i< view->tot_seqs; i++) /* process sequences */ if( ! view->sel_seqs[i] ) temp_data[j++] = (void *) view->sequence[i]; else free(view->sequence[i]); memcpy(view->sequence , temp_data, new_tot_seqs * sizeof(char *) ); if(viewasprots != NULL) { for(i = 0, j = 0; i< view->tot_seqs; i++) /* process sequences */ if( ! view->sel_seqs[i] ) temp_data[j++] = (void *) viewasprots[i]; else free(viewasprots[i]); memcpy(viewasprots, temp_data, new_tot_seqs * sizeof(char *) ); } if(view->comments != NULL) { for(i = 0, j = 0; i< view->tot_seqs; i++) /* process comments */ if( ! view->sel_seqs[i] ) temp_data[j++] = (void *) view->comments[i]; else if( view->comments[i]!= NULL) free(view->comments[i]); memcpy(view->comments , temp_data, new_tot_seqs * sizeof(char *) ); } for(i = 0, j = 0; i< view->tot_seqs; i++) /* process seq names */ if( ! view->sel_seqs[i] ) temp_data[j++] = (void *) view->seqname[i]; else free(view->seqname[i]); memcpy(view->seqname , temp_data, new_tot_seqs * sizeof(char *) ); for(i = 0, j = 0; i< view->tot_seqs; i++) /* process seq lengths */ if( ! view->sel_seqs[i] ) temp_int[j++]= view->each_length[i]; memcpy(view->each_length , temp_int, new_tot_seqs * sizeof(int) ); if(view->numb_gc > 1) { /* process color-coded sequences */ for(i = 0, j = 0; i< view->tot_seqs; i++) if( ! view->sel_seqs[i] ) temp_data[j++] = (void *) view->col_rank[i]; else free(view->col_rank[i]); memcpy(view->col_rank , temp_data, new_tot_seqs * sizeof(char *) ); } for(numset = 0; numset < view->numb_species_sets; numset++) { /* process species sets */ for(i = 0, j = 0; i < view->tot_seqs; i++) { if( ! view->sel_seqs[i] ) temp_int[j++]= view->list_species_sets[numset][i]; } memcpy(view->list_species_sets[numset], temp_int, new_tot_seqs * sizeof(int) ); } if(! view->cursor_in_comment) view->cursor_seq = 1; memset(view->sel_seqs, 0, new_tot_seqs * sizeof(int)); view->tot_seqs = new_tot_seqs; select_deselect_seq(view, 0); if(view->menu_species != NULL) { numset = 0; while(numset < view->numb_species_sets) { /* check for empty sets */ for(i = 0, j = 0; i < view->tot_seqs; i++) if( view->list_species_sets[numset][i] ) j++; if( j == 0 ) { /* set became empty => remove it */ free(view->list_species_sets[numset]); free(view->name_species_sets[numset]); memcpy(view->list_species_sets + numset, view->list_species_sets + numset + 1, (view->numb_species_sets - numset - 1)*sizeof(int *) ); memcpy(view->name_species_sets + numset, view->name_species_sets + numset + 1, (view->numb_species_sets - numset - 1)*sizeof(char *) ); view->menu_species->remove(numset); view->menu_species->value(0); (view->numb_species_sets)--; } else numset++; } } set_seaview_modified(view, TRUE); return FALSE; } void vh_sliders_callback(Fl_Widget *ob, void *data) { int old, new_val, page; int which = ((user_data_plus *)data)->value; SEA_VIEW *view = (SEA_VIEW *)((user_data_plus *)data)->p; Fl_Scrollbar *sli = (Fl_Scrollbar *)ob; new_val = sli->value(); if (which == 0) { /* vertical */ old = view->first_seq; if( Fl::event_is_click() ) { page = view->tot_lines - 2; if(page < 1) page = 1; if(new_val > old + sli->linesize() ) new_val = old + page; else if(new_val < old - sli->linesize() ) new_val = old - page; new_val = (int) sli->clamp(new_val); ((Fl_Valuator *)sli)->value(new_val); } view->first_seq = new_val; if(old != new_val) view->DNA_obj->redraw(); } else { /* horizontal */ old = view->first_site; if( Fl::event_is_click() ) { page = view->tot_sites - 20; if(page < 10) page = 10; if(new_val > old + sli->linesize() ) new_val = old + page; else if(new_val < old - sli->linesize() ) new_val = old - page; new_val = (int)sli->clamp(new_val); ((Fl_Valuator *)sli)->value(new_val); } view->first_site = new_val; view->draw_names = 0; if(old != new_val) view->DNA_obj->damage(1); } view->DNA_obj->take_focus(); } void lrdu_button_callback(Fl_Widget *ob, void *data) { Fl_Slider *sli; int *pval, newval=0; int mini, maxi; int which = ((user_data_plus *)data)->value; SEA_VIEW *view = (SEA_VIEW *)((user_data_plus *)data)->p; if(which <= 3) { /* mouvement horizontal */ sli = view->horsli; pval = &view->first_site; } else { /* mouvement vertical */ sli = view->vertsli; pval = &view->first_seq; } mini = (int)(sli->minimum()); maxi = (int)(sli->maximum()); if(which == 1 || which == 5) newval = mini; else if(which == 3 || which == 7) newval = maxi; if(newval < mini) newval = mini; if(newval > maxi) newval = maxi; if(newval != *pval) { *pval = newval; sli->value(*pval); if(which <= 3) view->draw_names = 0; view->DNA_obj->damage(view->draw_names ? FL_DAMAGE_ALL : 1); } view->DNA_obj->take_focus(); } void font_callback(Fl_Widget *ob, void *data) { int taille; SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); sscanf( ((Fl_Menu_ *)ob)->text(), "%d", &taille); if(view->DNA_obj->labelsize() == taille ) return; my_watch_cursor(view->dnawin); view->DNA_obj->labelsize(taille); fl_font( view->DNA_obj->labelfont(), view->DNA_obj->labelsize() ); view->line_height = (int)( LINE_HEIGHT_FACTOR * fl_height() ); view->char_width = (int)(fl_width("W") + 0.5); compute_size_params(view, TRUE); view->DNA_obj->parent()->redraw(); fl_reset_cursor(view->dnawin); view->DNA_obj->take_focus(); } void set_save_format(SEA_VIEW *view, int val) { if(val >= nbr_formats) return; if( view->format_for_save == (known_format)val) return; view->format_for_save = (known_format)val; Fl_Menu_Item *items = (Fl_Menu_Item*)view->menu_file; if(view->masename != NULL) { items[SAVE].activate(); } } void colors_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *parts = (props_menu_parts *)view->menu_props->user_data(); int reponse = ((Fl_Menu_*)ob)->mvalue() - menu_props; Fl_Menu_Item *item; /* processing inverted colors */ if(reponse == parts->inverted) { int style; my_watch_cursor(view->dnawin); view->inverted_colors = !view->inverted_colors; if(view->inverted_colors) { style = FL_COURIER; } else { style = FL_COURIER_BOLD; } view->DNA_obj->labelfont(style); view->DNA_obj->redraw(); fl_reset_cursor(view->dnawin); return; } /* changing DNA / protein / Alternate protein / Codon mode */ enum {DNARNA, Protein, Alt, Codon }; int debut = parts->colors; reponse -= debut; if(reponse == Protein && view->protein && ( view->alt_colors == USING_STANDARD_COLORS || view->alt_colors == NO_ALT_COLORS) ) return; if(reponse == Alt && view->alt_colors == USING_ALT_COLORS) return; view->protein = (reponse == Protein || reponse == Alt); my_watch_cursor(view->dnawin); if(view->numb_gc > 1) { /* free col_rank */ int num; for(num = 0; num < view->tot_seqs; num++) { free(view->col_rank[num]); } free(view->col_rank); } if(reponse == DNARNA) { view->numb_gc = view->numb_dnacolors; view->curr_colors = view->dnacolors; } else if(reponse == Protein) { set_aa_color_mode(USING_STANDARD_COLORS); view->numb_gc = view->numb_stdprotcolors; view->curr_colors = view->stdprotcolors; } else if(reponse == Alt) { set_aa_color_mode(USING_ALT_COLORS); view->numb_gc = view->numb_altprotcolors; view->curr_colors = view->altprotcolors; } else if(reponse == Codon) { view->numb_gc = 22; view->curr_colors = view->codoncolors; } item = menu_props + parts->edit; adjust_menu_edit_modes(view); if(reponse != Codon) { view->col_rank = prepcolranks(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, (view->protein ? get_color_for_aa : get_color_for_base), view->numb_gc, view->allow_lower); } else view->col_rank = prepcolranks_by_codon(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->comments); if(view->col_rank == NULL) out_of_memory(); if (reponse == Protein) view->alt_colors = NO_ALT_COLORS; if (reponse == Alt) view->alt_colors = USING_ALT_COLORS; view->DNA_obj->redraw(); view->DNA_obj->take_focus(); fl_reset_cursor(view->dnawin); } void allow_edit_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); Fl_Menu_Item *item = (Fl_Menu_Item*)((Fl_Menu_*)ob)->mvalue(); view->allow_seq_edit = !view->allow_seq_edit; if(view->allow_seq_edit) item->set(); else item->clear(); view->DNA_obj->take_focus(); } void viewasprots_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); props_menu_parts *parts = (props_menu_parts *)view->menu_props->user_data(); int oldedit, num; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; Fl_Menu_Item *item = (Fl_Menu_Item*)((Fl_Menu_*)ob)->mvalue(); Fl_Menu_Item *item2 = menu_props + parts->edit; Fl_Menu_Item *fileitems = (Fl_Menu_Item *)view->menu_file; Fl_Menu_Item *edititems = (Fl_Menu_Item *)view->menu_edit; if(view->tot_seqs == 0) return; oldedit = item2->value(); if(view->viewasprots != NULL) { view->viewasprots = set_viewasprots(view, FALSE); if(parts->usingcodoncolors) { for(num = 0; num < view->tot_seqs; num++) free(view->col_rank[num]); free(view->col_rank); Fl_Menu_Item *codoncolor = menu_props + parts->colors + 3; codoncolor->setonly(); view->numb_gc = 22; view->curr_colors = view->codoncolors; view->col_rank = prepcolranks_by_codon(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->comments); } } else { parts->usingcodoncolors = (view->curr_colors == view->codoncolors); view->viewasprots = set_viewasprots(view, TRUE); } if(oldedit) item2->set(); if(view->viewasprots != NULL) { item->set(); item->activate(); item2->deactivate(); view->allow_seq_edit = FALSE; fileitems[ACNUC_IMPORT].deactivate(); fileitems[SAVE_PROT_ALIGN].activate(); fileitems[SAVE].deactivate(); fileitems[SAVE_AS].deactivate(); fileitems[SAVE_REGIONS].deactivate(); edititems[PASTE_SEQS].deactivate(); edititems[CREATE_SEQ].deactivate(); edititems[LOAD_SEQ].deactivate(); edititems[EDIT_SEQ].deactivate(); edititems[DUPLICATE_SEQ].deactivate(); edititems[COMPLEMENT_SEQ].deactivate(); edititems[REVERSE_SEQ].deactivate(); edititems[CONSENSUS_SEQ].deactivate(); } else { item->clear(); item2->activate(); view->allow_seq_edit = item2->value(); fileitems[ACNUC_IMPORT].activate(); fileitems[SAVE_PROT_ALIGN].deactivate(); fileitems[SAVE].activate(); fileitems[SAVE_AS].activate(); if (view->active_region) fileitems[SAVE_REGIONS].activate(); edititems[PASTE_SEQS].activate(); edititems[CREATE_SEQ].activate(); edititems[LOAD_SEQ].activate(); } view->DNA_obj->take_focus(); } void consensus_allowgaps_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); int *poption = &(view->consensus_allowgaps); *poption = !(*poption); } void consensus_iupac_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); int *poption = &(view->consensus_allowiupac); *poption = !(*poption); } void slow_fast_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); Fl_Menu_Item *item = (Fl_Menu_Item*)((Fl_Menu_*)ob)->mvalue(); view->double_buffer = !view->double_buffer; if(!view->double_buffer) item->set(); else item->clear(); Fl_Window *win = (Fl_Window *)view->DNA_obj->parent(); Fl_Group *win_parent = (Fl_Group *)win->parent(); int x,y,w,h; x = win->x(); y = win->y(); w = win->w(); h = win->h(); int size = view->DNA_obj->labelsize(); int font = view->DNA_obj->labelfont(); Fl_Color col = view->DNA_obj->color(); Fl_Color sel_col = view->DNA_obj->selection_color(); win->hide(); win_parent->remove(*win); delete win; Fl_Group::current(win_parent); if(view->double_buffer) win = (Fl_Window *)new Fl_Double_Window(x, y, w, h ); else win = new Fl_Window(x,y,w,h); win->box(FL_DOWN_BOX); win->resizable(win); view->DNA_obj = (Fl_Widget*)new DNA_obj(3, 3, w - 6, h - 6, view); view->DNA_obj->labelfont(font); view->DNA_obj->labelsize(size); view->DNA_obj->color(col, sel_col); win->color(col); win->end(); win->show(); view->DNA_obj->take_focus(); } void allow_lower_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); Fl_Menu_Item *item = (Fl_Menu_Item *)((Fl_Menu_*)ob)->mvalue(); view->allow_lower = !view->allow_lower; if(view->allow_lower) item->set(); else item->clear(); view->DNA_obj->parent()->redraw(); view->DNA_obj->take_focus(); } void toggle_reference_callback(Fl_Widget *ob, void *data) { int on; SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); props_menu_parts *parts = (props_menu_parts *)view->menu_props->user_data(); Fl_Menu_Item *item = (Fl_Menu_Item *)view->menu_props + parts->edit; on = (view->menu_props + parts->reference)->value(); reference_toggle(view, on); if(on) { item->deactivate(); } else { item->activate(); if(view->allow_seq_edit) item->set(); else item->clear(); } } void dnakeys_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); props_menu_parts *parts = (props_menu_parts *)view->menu_props->user_data(); int reponse = (((Fl_Menu_*)ob)->mvalue() - view->menu_props) - parts->keys; if( ! view->hjkl ) { /* activer un choix */ view->hjkl = reponse + 1; } else if(view->hjkl == reponse + 1) { /* desactiver choix courant */ ((Fl_Menu_Item*)((Fl_Menu_*)ob)->mvalue())->clear(); view->hjkl = 0; } else { /* changer de choix */ view->hjkl = reponse + 1; } } void consensus_opt_callback(Fl_Widget *ob, void *data) { props_menu_parts *parts = (props_menu_parts *)data; SEA_VIEW *view = (SEA_VIEW*)ob->user_data(); Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; const char *rep; char tmp[100]; int value; sprintf(tmp, "%d %%", view->consensus_threshold); rep = fl_input("Set consensus threshold value in %%", tmp ); if(rep == NULL) return; value = -1; sscanf(rep, "%d", &value); if(value <= 0 || value > 100) return; view->consensus_threshold = value; sprintf(tmp, "%d %%", view->consensus_threshold); (menu_props + parts->consensusopt)->label(strdup(tmp)); } void create_props_menu(SEA_VIEW *view, int my_color_choice, int inverted, int black_and_white, int def_fontsize) { #define NBER_FONTSIZES 10 int defaut; static int first = TRUE; static props_menu_parts *parts; if (first) { first = FALSE; parts = (props_menu_parts *)malloc(sizeof(props_menu_parts)); parts->colors = 1 + NBER_FONTSIZES + 3; parts->viewasprots = parts->colors - 2; parts->inverted = parts->colors + 4; parts->reference = parts->inverted + 3; parts->edit = parts->reference - 1; parts->keys = parts->reference + 2; parts->consensusopt = parts->keys + 5; parts->slow_fast = parts->consensusopt + 5; parts->allow_lower = parts->slow_fast + 1; } static const Fl_Menu_Item propsitems_static[] = { {"Fontsize", 0, 0, 0, FL_SUBMENU}, {"8", 0, font_callback, 0, FL_MENU_RADIO}, {"10", 0, font_callback, 0, FL_MENU_RADIO}, {"12", 0, font_callback, 0, FL_MENU_RADIO}, {"14", 0, font_callback, 0, FL_MENU_RADIO}, {"16", 0, font_callback, 0, FL_MENU_RADIO}, {"18", 0, font_callback, 0, FL_MENU_RADIO}, {"24", 0, font_callback, 0, FL_MENU_RADIO}, {"28", 0, font_callback, 0, FL_MENU_RADIO}, {"32", 0, font_callback, 0, FL_MENU_RADIO}, {"36", 0, font_callback, 0, FL_MENU_RADIO}, {0}, {"View as proteins", 0, viewasprots_callback, 0, FL_MENU_TOGGLE | FL_MENU_INACTIVE}, {"Colors", 0, 0, 0, FL_SUBMENU}, {"DNA-RNA colors", 0, colors_callback, 0, FL_MENU_RADIO}, {"Protein colors", 0, colors_callback, 0, FL_MENU_RADIO}, {"Alt. colors", 0, colors_callback, 0, FL_MENU_RADIO}, {"Codon colors", 0, colors_callback, 0, FL_MENU_RADIO | FL_MENU_DIVIDER}, {"Inverted colors", 0, colors_callback, 0, FL_MENU_TOGGLE}, {0}, {"Allow seq. editing", 0, allow_edit_callback, 0, FL_MENU_TOGGLE}, {"by Reference", FL_COMMAND | 'r', toggle_reference_callback, 0, FL_MENU_TOGGLE}, {"DNA keys", 0, 0, 0, FL_SUBMENU}, {"hjkl => GATCN", 0, dnakeys_callback, 0, FL_MENU_RADIO}, {"hjkl => TCGAN", 0, dnakeys_callback, 0, FL_MENU_RADIO}, {"hjkl => ACGTN", 0, dnakeys_callback, 0, FL_MENU_RADIO}, {0}, {"Consensus options", 0, 0, 0, FL_SUBMENU}, {"%", 0, NULL, 0, FL_MENU_DIVIDER}, {"allow gaps", 0, consensus_allowgaps_callback, 0, FL_MENU_TOGGLE}, {"use IUPAC symbols", 0, consensus_iupac_callback, 0, FL_MENU_TOGGLE}, {"Edit threshold", 0, consensus_opt_callback, parts, 0}, {0}, {"Fast-Rough", 0, slow_fast_callback, 0, FL_MENU_TOGGLE}, {"Allow lowercase", 0, allow_lower_callback, 0, FL_MENU_TOGGLE}, {"Customize", 0, custom_callback, NULL, 0}, {"Statistics", 0, stats_callback, NULL, 0}, {0} }; Fl_Menu_Item *propsitems = new Fl_Menu_Item[sizeof(propsitems_static)/sizeof(Fl_Menu_Item)]; memcpy(propsitems, propsitems_static, sizeof(propsitems_static)); view->menu_props = propsitems; view->menubar->add("Props", 0, NULL, (void*)view->menu_props, FL_SUBMENU_POINTER); propsitems->user_data(parts); /* partie Fontsize */ for(defaut = 1; defaut <= NBER_FONTSIZES; defaut++) { int taille; sscanf( propsitems[defaut].label(), "%d", &taille); if(taille >= def_fontsize) break; } if(defaut > NBER_FONTSIZES) defaut = 4; (propsitems + defaut)->set(); /* partie View as proteins */ /* partie Colors */ if(black_and_white) { (propsitems + parts->colors - 1)->deactivate(); } else { defaut = parts->colors; if(view->protein) defaut++; (propsitems + defaut)->set(); if(my_color_choice == NO_ALT_COLORS) (propsitems + parts->colors + 2)->deactivate(); if(inverted) (propsitems + parts->inverted)->set(); } /* partie Edit */ /* partie by reference */ /* partie keys */ /* partie consensus options */ char tmp[50]; sprintf(tmp, "%d %%", view->consensus_threshold); (propsitems + parts->consensusopt)->label(strdup(tmp)); /* partie Fast/Slow */ (propsitems + parts->slow_fast)->flags = #ifdef __APPLE__ FL_MENU_INVISIBLE; #else (view->double_buffer ? FL_MENU_TOGGLE : FL_MENU_TOGGLE | FL_MENU_VALUE); #endif /* partie allow lower case */ if (view->allow_lower) (propsitems + parts->allow_lower)->set(); if (black_and_white) (propsitems + parts->allow_lower)->deactivate(); /* partie customize */ /* partie statistiques */ } /*int clipboard_contains_alignment(const char *clip) { extern char *fl_selection_buffer[]; if(clip == NULL) clip = fl_selection_buffer[0]; return (clip != NULL && memcmp(clip, CLIPBOARDMARK, strlen(CLIPBOARDMARK)) == 0); } void fix_all_paste_items(const char *p) { Fl_Window *w; SEA_VIEW *view; int mode; if(clipboard_contains_alignment(p) ) mode = 0; else mode = FL_MENU_INACTIVE; #ifdef WIN32 Fl::check(); // calls Fl::do_widget_deletion(), crashes without this when closing window #endif w = Fl::first_window(); while(w != NULL) { if(w->callback() == mainwin_close_callback) { view = (SEA_VIEW *)w->user_data(); if (view) { Fl_Menu_Item* items = (Fl_Menu_Item*)view->menu_edit; if (view->viewasprots || mode == FL_MENU_INACTIVE) items[PASTE_SEQS].deactivate(); else items[PASTE_SEQS].activate(); } } w = Fl::next_window(w); } } void fix_paste_timeout(void *u) { fix_all_paste_items(NULL); Fl::repeat_timeout(0.5, fix_paste_timeout); }*/ void edit_menu_callback(Fl_Widget *ob, void* data) { SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); int reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_edit; if(reponse == COPY_SEQS) { /* copy selected sequences */ region *myregion; myregion = view->active_region; if(myregion == NULL) { myregion = (region *)malloc(sizeof(region)); if(myregion == NULL) return; myregion->list = (list_segments *)malloc(sizeof(list_segments)); if(myregion->list == NULL) return; myregion->list->debut = 1; myregion->list->fin = view->seq_length; myregion->list->next = NULL; myregion->name = (char *)"all"; } char *err = save_alignment_or_region(clipboardfname, view->sequence, view->comments, NULL, view->seqname, view->tot_seqs, view->each_length, NULL, myregion, MASE_FORMAT, 0, NULL, NULL, view->sel_seqs, view->tot_sel_seqs, view->protein, 0, NULL, NULL, view->phylipwidnames, 0, NULL, NULL, FALSE); if(view->active_region == NULL) { free(myregion->list); free(myregion); } if(err == NULL) { //put filename on the selection clipboard (0) char tmp[200]; sprintf(tmp, CLIPBOARDMARK"%s", clipboardfname); Fl::copy(tmp, strlen(tmp), 0); //put Fasta sequences on the primary clipboard (1) char *buf, *p; int i, l = 0; for( i = 0; i < view->tot_seqs; i++) { if(!view->sel_seqs[i]) continue; l += strlen(view->seqname[i]) + view->each_length[i] + 3; } buf = (char *)malloc(l + 10); if(buf != NULL) { p = buf; for( i = 0; i < view->tot_seqs; i++) { if(!view->sel_seqs[i]) continue; sprintf(p, ">%s\n", view->seqname[i]); p += strlen(p); strcpy(p, view->sequence[i]); p += strlen(p); *(p++) = '\n'; } Fl::copy(buf, p - buf, 1); free(buf); } } else { FILE *tmpf = fopen(clipboardfname, "w"); if (tmpf) fclose(tmpf); Fl::copy("", 0, 0); Fl::copy("", 0, 1); } } else if(reponse == PASTE_SEQS) { /* paste first from the selection buffer */ pasted_from_what_source = 0; Fl::paste(*(view->DNA_obj), 0 ); } else if(reponse == SELECT_ALL) { /* select all sequences */ if(view->multipl->argument() > 0) mod_multipl(view,0); select_deselect_seq(view, -1); view->draw_names = -2; // ceci signifie redraw partiel commande' par draw_names, mod_cursor, ... view->DNA_obj->damage(1); } else if(reponse == RENAME_SEQ) { /* rename the selected sequence */ rename_sequence(view); } else if(reponse == EDIT_COMMENTS) { edit_comments_dialog(view); } else if(reponse == EDIT_SEQ) { edit_sequence_dialog(view); } else if(reponse == DELETE_SEQ) { /* delete selected sequences from alignment */ if( fl_choice("Confirm request of deletion of %d sequence(s)", "Cancel", "Delete", NULL, view->tot_sel_seqs) ) { if( delete_selected_seqs(view) ) fl_alert("Not enough memory for this operation"); else { compute_size_params(view, TRUE); update_menu_footers(view); view->DNA_obj->redraw(); view->vertsli->redraw(); } } } else if(reponse == CREATE_SEQ) { /* create a new sequence */ char *newname; newname = (char *) fl_input("Name of the new sequence?", ""); if(newname == NULL || strlen(newname) == 0) return; add_seq_to_align(view, newname, (char *)"-", 1); } else if(reponse == LOAD_SEQ) { /* load a new sequence */ load_seq_dialog(view); } else if(reponse == DUPLICATE_SEQ || reponse == COMPLEMENT_SEQ || reponse == REVERSE_SEQ) { int num, lenseq, old_first_seq; char *newseq, *p, *q, *newname; if(view->tot_sel_seqs != 1 ) return; /* par securite */ if(reponse != DUPLICATE_SEQ && view->protein) return; /* par securite */ for(num = 0; num < view->tot_seqs; num++) if(view->sel_seqs[num]) break; lenseq = view->each_length[num]; newseq = (char *)malloc(lenseq + 1); if(newseq == NULL) { fl_alert("Not enough memory\nto create a new sequence"); Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_edit; items[reponse].deactivate(); return; } if(reponse == DUPLICATE_SEQ) { strcpy(newseq, view->sequence[num]); } else { p = view->sequence[num]; q = newseq + lenseq - 1; while( *p != 0) { if(reponse == COMPLEMENT_SEQ) *q = complement_base(*p); else *q = *p; p++; q--; } newseq[lenseq] = 0; } newname = (char*)malloc(strlen(view->seqname[num]) + 3); if(reponse == COMPLEMENT_SEQ) strcpy(newname,"C_"); else if(reponse == REVERSE_SEQ) strcpy(newname,"R_"); else strcpy(newname,"D_"); strcat(newname,view->seqname[num]); old_first_seq = view->first_seq; add_seq_to_align(view, newname , newseq, lenseq); free(newseq); free(newname); /* placer la nouvelle seq apres celle de depart */ view->sel_seqs[num] = FALSE; view->sel_seqs[view->tot_seqs - 1] = TRUE; deplacer_grp_seqs( view, FL_min(num + 2, view->tot_seqs) ); /* montrer les 2 seqs concernees */ if(old_first_seq > num + 1) view->first_seq = FL_min(num + 1, view->tot_seqs - view->tot_lines + 1); else if(old_first_seq + view->tot_lines - 1 < num + 2) view->first_seq = FL_min(num + 2, view->tot_seqs - view->tot_lines + 1); else view->first_seq = old_first_seq; view->vertsli->Fl_Slider::value(view->first_seq); } else if(reponse == EXCHANGE_UT) { /* exchange Us and Ts */ int num; char *p; if(view->tot_sel_seqs == 0 || view->protein) return; /* par securite */ my_watch_cursor(view->dnawin); for(num = 0; num < view->tot_seqs; num++) { if( ! view->sel_seqs[num] ) continue; p = view->sequence[num] - 1; while( *(++p) != 0 ) { if( *p == 'U' ) { *p = 'T'; } else if( *p == 'T' ) { *p = 'U'; } else if( *p == 't' ) { *p = 'u'; } else if( *p == 'u' ) { *p = 't'; } } } set_seaview_modified(view, TRUE); view->draw_names = 0; view->DNA_obj->damage(1); fl_reset_cursor(view->dnawin); } else if(reponse == DOT_PLOT) { /* dot plot */ int num1, num2; extern void show_dot_plot(char *seq1, char *seq2, char *seqname1, char *seqname2, int l1, int l2, int maxseqlength, void *seaview_data); if(view->tot_sel_seqs != 2) return; for(num1 = 0; num1 < view->tot_seqs; num1++) if(view->sel_seqs[num1]) break; for(num2 = num1 + 1; num2 < view->tot_seqs; num2++) if(view->sel_seqs[num2]) break; show_dot_plot(view->sequence[num1], view->sequence[num2], view->seqname[num1], view->seqname[num2], view->each_length[num1], view->each_length[num2], view->max_seq_length, (void *)view); } else if (reponse == CONSENSUS_SEQ) { char *newseq, newname[100]; int old_total, *tmp, new_pos, i, old_first_seq; if(view->tot_sel_seqs <= 1 ) return; /* par securite */ newseq = cre_consensus(view, newname); if(newseq == NULL) { fl_alert("Not enough memory\nto create a new sequence"); Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_edit; items[reponse].deactivate(); return; } old_first_seq = view->first_seq; old_total = view->tot_seqs; add_seq_to_align(view, newname , newseq, strlen(newseq)); free(newseq); for(i=0; i < view->tot_seqs; i++) if(view->sel_seqs[i]) new_pos = i; new_pos += 2; if(view->tot_seqs == old_total || new_pos == view->tot_seqs) { return; } /* placer la nouvelle seq apres la derniere des selectionnees */ tmp = (int *)calloc(view->tot_seqs, sizeof(int)); if(tmp == NULL) { return; } memcpy(tmp, view->sel_seqs, view->tot_seqs * sizeof(int) ); memset(view->sel_seqs, 0, view->tot_seqs * sizeof(int) ); view->sel_seqs[view->tot_seqs - 1] = TRUE; old_total = view->tot_sel_seqs; view->tot_sel_seqs = 1; deplacer_grp_seqs( view, new_pos ); memcpy(view->sel_seqs, tmp, view->tot_seqs * sizeof(int) ); view->tot_sel_seqs = old_total; free(tmp); /* montrer la seq concernee */ if(old_first_seq > new_pos ) view->first_seq = FL_min(new_pos - 2, 1); else if(old_first_seq + view->tot_lines - 1 < new_pos) view->first_seq = FL_min(new_pos - 2, view->tot_seqs - view->tot_lines + 1); else view->first_seq = old_first_seq; view->vertsli->Fl_Slider::value(view->first_seq); } else if(reponse == DELETE_GAP_ONLY_SITES) { if( !fl_choice("Confirm remove all gap_containing sites?", "Cancel", "Remove", NULL) ) return; my_watch_cursor(view->dnawin); del_gap_only_sites(view); compute_size_params(view, TRUE); view->DNA_obj->redraw(); view->horsli->redraw(); fl_reset_cursor(view->dnawin); } else if(reponse == SET_GCODE) { if( (!view->protein) && view->tot_sel_seqs != 0 ) set_ncbi_genetic_code(view); } } void set_and_show_new_cursor_site(SEA_VIEW *view, int new_pos, int center, int force_redraw) { int old_pos; old_pos = view->cursor_site; if(new_pos != old_pos) view->cursor_site = new_pos; if(new_pos >= view->first_site && new_pos < view->first_site + view->tot_sites - 1) { if( !force_redraw && ( (view->cursor_in_comment && view->mod_comment_line == 0) || (!view->cursor_in_comment && view->mod_seq == 0) ) ) view->mod_cursor = TRUE; } else { if(center) view->first_site = view->cursor_site - view->tot_sites/2; else { if(new_pos >= old_pos) view->first_site = view->cursor_site + 10 - view->tot_sites; else view->first_site = view->cursor_site - 10; } if(view->first_site + view->tot_sites - 1 > view->seq_length + 1 ) view->first_site = view->seq_length - view->tot_sites + 2; if(view->first_site <=0 ) view->first_site = 1; view->horsli->Fl_Slider::value(view->first_site); view->mod_seq = 0; view->mod_comment_line = 0; } view->draw_names = 0; view->DNA_obj->damage(1); } void set_and_show_new_cursor_seq(SEA_VIEW *view, int new_pos) { if(view->cursor_in_comment) { if(view->comment_length[new_pos - 1] + 1 < view->cursor_site) { fl_beep(FL_BEEP_DEFAULT); return; } if(new_pos == view->cursor_seq) return; view->cursor_seq = new_pos; view->mod_cursor = TRUE; view->draw_names = 0; view->DNA_obj->damage(1); return; } if(view->each_length[new_pos - 1] + 1 < view->cursor_site) { fl_beep(FL_BEEP_DEFAULT); return; } if(new_pos != view->cursor_seq || new_pos < view->first_seq || view->cursor_site != view->old_cursor_site || new_pos >= view->first_seq + view->tot_lines) { view->cursor_seq = new_pos; if(new_pos >= view->first_seq && new_pos < view->first_seq + view->tot_lines) { view->mod_cursor = TRUE; view->draw_names = 0; view->DNA_obj->damage(1); } else { view->first_seq = view->cursor_seq - view->tot_lines/2; if(view->first_seq + view->tot_lines >= view->tot_seqs ) view->first_seq = view->tot_seqs - view->tot_lines + 1; if(view->first_seq <=0 ) view->first_seq = 1; view->vertsli->Fl_Slider::value(view->first_seq); view->draw_names = -1; view->DNA_obj->redraw(); } } } void goto_callback(Fl_Widget *ob, void *data) { Fl_Input *input; SEA_VIEW *view; int maxi, num, new_pos = -1, numerique = TRUE; unsigned l; char *p, *q, target[50]; static char *upname; static int l_upname = 0; user_data_plus *data_plus = (user_data_plus *)data; int which = data_plus->value; if(which == 0) { /* appele par bouton goto */ input = (Fl_Input *)data_plus->p; data_plus = (user_data_plus *)input->user_data(); } else input = (Fl_Input*)ob; view = (SEA_VIEW *)data_plus->p; if(view->tot_seqs == 0) return; p = (char *)input->value(); q = p - 1; while(*(++q) != 0) { if(!isdigit(*q)) numerique = FALSE; } if(numerique) { /* aller a une position de l'alignement */ sscanf(p,"%d",&new_pos); if(view->cursor_in_comment) maxi = view->comment_length[view->cursor_seq - 1]; else maxi = view->each_length[view->cursor_seq - 1]; if( new_pos <= 0 || new_pos > maxi ) { input->value(""); fl_beep(FL_BEEP_DEFAULT); } else { set_and_show_new_cursor_site(view, new_pos, TRUE, FALSE); } } else { /* recherche d'une seq par son nom */ l = strlen(p); if (l > sizeof(target) - 1) l = sizeof(target) - 1; strncpy(target, p, l); target[l] = 0; majuscules(target); if(view->wid_names > l_upname) { if(l_upname > 0) free(upname); upname = (char *)malloc(view->wid_names + 1); l_upname = view->wid_names; } for(num = 0; num < view->tot_seqs; num++) { strncpy(upname, view->seqname[num], l_upname); upname[l_upname] = 0; majuscules(upname); if(strstr(upname, target) != NULL) break; } if(num >= view->tot_seqs) { fl_beep(FL_BEEP_DEFAULT); return; } if(view->cursor_site < view->first_site || view->cursor_site >= view->first_site + view->tot_sites) view->cursor_site = view->first_site; set_and_show_new_cursor_seq(view, num + 1); } view->DNA_obj->take_focus(); } char *search_with_gaps(char *target, char *debut) { char *cherche, *trouve = debut - 1; do { debut = trouve + 1; trouve = NULL; cherche = target; do { while( *debut == '-' ) debut++; if(trouve == NULL) trouve = debut; if ( toupper(*debut) != *cherche ) break; cherche++; debut++; } while( *cherche != 0 ); } while( *trouve != 0 && *cherche != 0); return ( *cherche == 0 ? trouve : (char*)NULL ); } void search_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view; char *target, *pos, *debut; int new_pos; user_data_plus *data_plus = (user_data_plus *)data; int which = data_plus->value; if(which == 1) { /* appele par champ input */ pos = (char *)((Fl_Input*)ob)->value(); } else { /* appele par bouton search */ Fl_Input *champ = (Fl_Input *)data_plus->p; pos = (char *)champ->value(); data_plus = (user_data_plus *) champ->user_data(); } view = (SEA_VIEW *)data_plus->p; if(view->tot_seqs == 0) return; target = strdup(pos); while((pos = strchr(target, '\n')) != NULL) *pos = ' '; while((pos = strchr(target, '\r')) != NULL) *pos = ' '; compact(target); if( strlen(target) == 0 ) {free(target); return; } majuscules(target); if(view->cursor_in_comment) debut = view->comment_line[view->cursor_seq - 1] + view->cursor_site; else debut = view->sequence[view->cursor_seq - 1] + view->cursor_site; pos = search_with_gaps(target, debut); free(target); if(pos == NULL) fl_beep(FL_BEEP_DEFAULT); else { if(view->cursor_in_comment) new_pos = pos - view->comment_line[view->cursor_seq - 1] + 1; else new_pos = pos - view->sequence[view->cursor_seq - 1] + 1; set_and_show_new_cursor_site(view, new_pos, TRUE, FALSE); } view->DNA_obj->take_focus(); } void free_alignment(SEA_VIEW *view) { int num; if(view->header!=NULL) { free(view->header); view->header = NULL; } if(view->alt_col_rank != NULL) free_colranks_by_difference(view->alt_col_rank, view->tot_seqs); for(num = 0; num < view->tot_seqs; num++) { free(view->sequence[num]); free(view->seqname[num]); if(view->comments != NULL && view->comments[num] != NULL) { free(view->comments[num]); view->comments[num] = NULL; } if(view->numb_gc > 1) { free(view->col_rank[num]); } } if( view->tot_seqs > 0 ) { free(view->sequence); free(view->seqname); if(view->comments != NULL) free(view->comments); } if( view->numb_gc > 1 && view->tot_seqs > 0 ) free(view->col_rank); if(view->masename != NULL) { free(view->masename); view->masename = NULL; } if( view->tot_seqs >= 1 ) { free(view->each_length); free(view->sel_seqs); free(view->region_line); } if(view->viewasprots != NULL) { char **seqs = (char **)view->viewasprots; for(num = 0; num < view->tot_seqs; num++) { free(seqs[num]); } free(seqs); } view->tot_seqs = 0; while (view->regions != NULL) delete_region(view, 1); for(num = 0; num < view->numb_species_sets; num++) { free(view->list_species_sets[num]); free(view->name_species_sets[num]); } view->numb_species_sets = 0; view->tot_sel_seqs = 0; view->cursor_seq = 0; if(view->active_region != NULL) { free_region(view->active_region); view->active_region = NULL; } if(view->menu_file != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE].deactivate(); items[SAVE_AS].deactivate(); items[SAVE_REGIONS].deactivate(); items[SAVE_BOOTSTRAPS].deactivate(); } if(view->tot_comment_lines > 0) { for(num = 0; num < view->tot_comment_lines; num++) { free(view->comment_name[num]); free(view->comment_line[num]); } free(view->comment_name); free(view->comment_line); free(view->comment_length); view->tot_comment_lines = 0; view->show_comment_lines = FALSE; } for(num = 0; num < view->tot_trees; num++) free(view->trees[num]); if(view->tot_trees > 0) free(view->trees); view->tot_trees = 0; } char *run_and_close_native_file_chooser(Fl_Native_File_Chooser *chooser, int keepalive) //returns chosen file in static memory or NULL if user cancelled { static char filename[PATH_MAX]; char *retval = NULL; #ifndef MICRO static char last_visited_directory[PATH_MAX] = ""; char *p; if ( chooser->directory() == NULL && (chooser->preset_file() == NULL || *chooser->preset_file() != '/') ) { if( *last_visited_directory )chdir(last_visited_directory); chooser->directory(last_visited_directory); p = (char *)chooser->preset_file(); if(p != NULL && *p != 0) { p = strdup(extract_filename(p)); if(p != NULL) { chooser->preset_file(p); free(p); } } } #endif if ( chooser->show() == 0 ) { strcpy(filename, chooser->filename()); #ifndef MICRO strcpy(last_visited_directory, filename); p = strrchr(last_visited_directory, '/'); if(p != NULL) *p = 0; #endif retval = filename; } if(!keepalive) delete chooser; return retval; } Fl_Window *load_alignment_file(SEA_VIEW *view, char *filename, const char *message, known_format file_format, int doing_dnd) /* returns the window containing the new alignment or NULL */ { char *err_message; int protein; if(filename == NULL) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->title(message); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file if ((int)file_format != -1) { char wpattern[100]; sprintf(wpattern, "%s \t*.%s", f_format_names[file_format], f_format_exts[file_format]); chooser->filter(wpattern); } filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return NULL; } if ((int)file_format == -1) { file_format = what_format(filename); if(file_format < 0) { fl_alert("File %s\nis not of a format readable by seaview", filename); return NULL; } } if(view != NULL && view->alt_col_rank != NULL) { reference_toggle(view, FALSE); } // search for empty alignment window; if none, create a new one Fl_Window *w = Fl::first_window(); while(w != NULL) { if(w->callback() == mainwin_close_callback) { view = (SEA_VIEW *)w->user_data(); if(view && view->tot_seqs == 0) break; } w = Fl::next_window(w); } if(w == NULL) { view = newwindow_callback(view); } #ifdef WIN32 Fl::check();//to redraw window after file dialog box closes (FLTK bug fixed in FLTK 1.3.4) #endif my_watch_cursor(view->dnawin); if(file_format == MASE_FORMAT) { view->tot_seqs = read_mase_seqs_header(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); /* interpreter les regions du header du fichier mase */ view->regions = parse_regions_from_header(view->header); /* interpreter les species sets du fichier mase */ view->numb_species_sets = parse_species_sets_from_header(view->header, view->list_species_sets, view->name_species_sets, view->tot_seqs); /* interpreter les trees du fichier mase */ parse_trees_from_header(view->header, view); /* interpreter les comment lines du header */ view->tot_comment_lines = parse_comment_lines_from_header(view->header, &(view->comment_line), &(view->comment_name), &(view->comment_length) , &(view->max_seq_length)); } else if(file_format == FASTA_FORMAT) view->tot_seqs = read_fasta_align(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message, view->spaces_in_fasta_names); else if(file_format == PHYLIP_FORMAT) view->tot_seqs = read_phylip_align(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == CLUSTAL_FORMAT) view->tot_seqs = read_clustal_align(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == MSF_FORMAT) view->tot_seqs = read_msf_align(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == NEXUS_FORMAT) { int **list_sp = NULL; char **name_sp = NULL; int i; view->tot_seqs = read_nexus_align(filename, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message, &view->regions, &view->numb_species_sets, &list_sp, &name_sp, &view->tot_comment_lines, &view->comment_name, &view->comment_line, &view->comment_length, &protein, view); for(i= 0; i < view->numb_species_sets; i++) { view->list_species_sets[i] = list_sp[i]; view->name_species_sets[i] = name_sp[i]; } if(list_sp != NULL) free(list_sp); if(name_sp != NULL) free(name_sp); } if(view->tot_seqs == 0 && view->tot_trees == 0) { fl_reset_cursor(view->dnawin); fl_alert("Error while reading file %s\n%s", filename, err_message); view->DNA_obj->parent()->redraw(); return NULL; } if(file_format != NEXUS_FORMAT) protein = is_a_protein_seq(view->sequence[0]); if(view->menu_file != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; if(file_format == view->format_for_save) { items[SAVE].activate(); items[SAVE_AS].activate(); } else { items[SAVE_AS].activate(); if(view->masename != NULL) { free(view->masename); view->masename = filename = NULL; } } items[SAVE_BOOTSTRAPS].activate(); } int keep_dnawin = TRUE; if(view->tot_seqs > 0) { extern char *position_mask_names[]; extern int position_mask_count; list_regions *mylist = view->regions; while(mylist) { // hide each region named as in position_mask_names array for(int l = 0; l < position_mask_count; l++) { if(strcmp(mylist->element->name, position_mask_names[l]) == 0) { mylist->element->hide_when_viewasprots = TRUE; } } mylist = mylist->next; } init_dna_scroller(view, view->tot_seqs, filename, protein, view->header); set_save_format(view, file_format); view->DNA_obj->parent()->redraw(); w = view->dnawin; } else {//there was only a tree in the file read const char *p = view->menu_trees->vitem(0)->label(); keep_dnawin = doing_dnd || view->tot_trees > 1; w = treedraw(strdup(view->trees[0]), view, p, keep_dnawin); if(keep_dnawin) w = view->dnawin; else view->dnawin->do_callback();//closes an empty alignment window that opened the tree } if( keep_dnawin) fl_reset_cursor(view->dnawin); return w; } void mainwin_close_callback(Fl_Widget *form, void *data) { SEA_VIEW *view = (SEA_VIEW *)data; Fl_Window *w , *w2; if(view->modif_but_not_saved) { if( fl_choice("Alignment %s was modified but not saved\n" "Do you want to close it anyway?", "Cancel", "Close", NULL, extract_filename(view->masename)) == 0) return; } free_alignment(view); #ifdef __APPLE__ char value[50]; sprintf(value, "%dx%d", view->dnawin->w(), view->dnawin->h() ); delete_windowmenuitem(find_windowmenuitem(view->dnawin)); #endif //disconnect all tree windows pointing to the deleted seaview window disconnect_tree_windows(view); //when a callback destroys its own widget delete is bad; Fl::delete_widget is to be called Fl::delete_widget(form); //search for last alignment window and not the one scheduled for deletion w = Fl::first_window(); w2 = NULL; while(w != NULL) { if(w != form && w->callback() == mainwin_close_callback) w2 = w; w = Fl::next_window(w); } if(w2 != NULL) { // set focus to last open alignment window ((SEA_VIEW *)w2->user_data())->DNA_obj->take_focus(); } else { // this was the last alignment window #ifdef __APPLE__ set_res_value("window", value); #endif } view->DNA_obj->user_data(NULL); delete[] view->menu_file; delete[] view->menu_edit; delete[] view->menu_align; delete[] view->menu_props; delete view->menu_sites; delete view->menu_species; delete[] view->menu_footers; delete view->menu_trees; free(view); form->user_data(NULL); } void to_do_at_exit(void) { delete_tmp_filename(clipboardfname); } void close_all_saved_wins(Fl_Widget *ob) { //this rather complicated stuff seems necessary for WIN32 Fl_Window *w, *mine; int count = 0, i = 0; mine = ob->window(); //count and memorize all top-level windows except that containing the calling menu w = Fl::first_window(); while( w != NULL) { if(w->window() == NULL && w != mine) count++; w = Fl::next_window(w); } Fl_Window **tabwins = (Fl_Window **)malloc(count * sizeof(Fl_Window *)); w = Fl::first_window(); while( w != NULL) { if(w->window() == NULL && w != mine) tabwins[i++] = w; w = Fl::next_window(w); } //attempt closing all these windows for(i = 0; i < count; i++) { Fl::handle(FL_CLOSE, tabwins[i]); Fl::wait(0);//this does close operation for good if needed } free(tabwins); //finally attempt closing the calling menu-containing window Fl::handle(FL_CLOSE, mine); return; } SEA_VIEW *newwindow_callback(SEA_VIEW *old_view) { SEA_VIEW *view = create_the_form( old_view != NULL ? old_view->double_buffer : TRUE ); return view; } void file_menu_callback(Fl_Widget *ob, void *data) { SEA_VIEW *view; char pattern[20]; static char fsel_message[] = "seaview: choose file and format"; char *filename; view = (SEA_VIEW *)ob->user_data(); int reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_file; sprintf(pattern, "*.%s", f_format_exts[view->format_for_save]); if(reponse == CLOSE_WINDOW) { ob->window()->do_callback(); } else if(reponse == QUIT) { close_all_saved_wins(ob); } else if(reponse == NEW_WINDOW) { newwindow_callback(view); } else if(reponse == CONCATENATE) { concatenate_dialog(view); } else if(reponse == OPEN_ANY) { #ifdef WIN32 Fl::e_state = 0; // fix bug where CTRL remains ON if Ctrl-O shortcut was used #endif Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->title("Choose an alignment/tree file"); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; use_initial_file(view, filename, FALSE); } else if(reponse == OPEN_MASE) { load_alignment_file(view, NULL, "Choose a .mase file", MASE_FORMAT, FALSE); } else if(reponse == OPEN_PHYLIP ) { load_alignment_file(view, NULL, "Choose a Phylip file" , PHYLIP_FORMAT, FALSE); } else if(reponse == OPEN_CLUSTAL ) { load_alignment_file(view, NULL, "Choose a Clustal file" , CLUSTAL_FORMAT, FALSE); } else if(reponse == OPEN_MSF ) { load_alignment_file(view, NULL, "Choose an MSF file", MSF_FORMAT, FALSE); } else if(reponse == OPEN_FASTA ) { load_alignment_file(view, NULL, "Choose a Fasta file", FASTA_FORMAT, FALSE); } else if(reponse == OPEN_NEXUS ) { load_alignment_file(view, NULL, "Choose a NEXUS file", NEXUS_FORMAT, FALSE); } else if(reponse == ACNUC_IMPORT ) { racnuc_dialog(view); } else if(reponse == SAVE || reponse == SAVE_AS) { char *err; if(reponse == SAVE_AS) { /* Save as */ known_format new_format; filename = seaview_file_chooser_save_as(fsel_message, view->masename, view, &new_format); if(filename==NULL) return; set_save_format(view, new_format); } else { filename = view->masename; } my_watch_cursor(view->dnawin); save_active_region(view); err = save_alignment_or_region(filename, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, view->regions, NULL, view->format_for_save, view->numb_species_sets, view->list_species_sets, view->name_species_sets, NULL, 0, view->protein, view->tot_comment_lines, view->comment_name, view->comment_line, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); fl_reset_cursor(view->dnawin); if(err != NULL) fl_alert("%s", err); else { if(reponse == SAVE_AS) { if(view->masename != NULL) free(view->masename); view->masename=(char *)malloc(strlen(filename)+1); if(view->masename == NULL) out_of_memory(); strcpy(view->masename,filename); view->dnawin->label(extract_filename(filename)); #ifdef __APPLE__ rename_windowmenuitem(view->dnawin->label(), find_windowmenuitem(view->dnawin)); #endif Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_file; items[SAVE].activate(); } set_seaview_modified(view, FALSE); } } else if(reponse == SAVE_REGIONS) { /* save current regions choice */ char *err; region *myregion; known_format region_format; static char regions_only_filename[200]; static int first = TRUE; if(first) { strcpy(regions_only_filename, "regions"); if( strchr(pattern,'.') != NULL) strcat(regions_only_filename, pattern+1); first = FALSE; } filename = seaview_file_chooser_save_as(fsel_message, regions_only_filename, view, ®ion_format); if(filename==NULL) return; my_watch_cursor(view->dnawin); myregion = view->active_region; if(myregion == NULL) { myregion = (region *)malloc(sizeof(region)); if(myregion == NULL) return; myregion->list = (list_segments *)malloc(sizeof(list_segments)); if(myregion->list == NULL) return; myregion->list->debut = 1; myregion->list->fin = view->seq_length; myregion->list->next = NULL; myregion->name = (char *)"all"; } err = save_alignment_or_region(filename, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, NULL, myregion, region_format, 0, NULL, NULL, view->sel_seqs, view->tot_sel_seqs, view->protein, 0, NULL, NULL, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); if(view->active_region == NULL) { free(myregion->list); free(myregion); } fl_reset_cursor(view->dnawin); if(err != NULL) fl_alert("%s", err); else strcpy(regions_only_filename, extract_filename(filename)); } else if(reponse == SAVE_PROT_ALIGN) { /* save alignmt at protein level */ char *err; known_format new_format; filename = seaview_file_chooser_save_as(fsel_message, view->masename, view, &new_format); if(filename==NULL) return; my_watch_cursor(view->dnawin); err = save_alignment_or_region(filename, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, view->regions, NULL, new_format, view->numb_species_sets, view->list_species_sets, view->name_species_sets, NULL, 0, TRUE, 0, NULL, NULL, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); fl_reset_cursor(view->dnawin); if(err != NULL) fl_alert("%s", err); } else if(reponse == SAVE_BOOTSTRAPS && view->tot_seqs > 0) { /* save bootstrap replicates */ char suggested[300], *p; int replicates = -1; strcpy(suggested, view->masename); p = strrchr(suggested, '.'); if (p != NULL) *p = 0; strcat(suggested, "_bootstraps.phy"); Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Enter output bootstrap Phylip filename"); chooser->directory(extract_dirname(suggested)); chooser->preset_file(extract_filename(suggested)); filename = run_and_close_native_file_chooser(chooser); if (filename == NULL) return; const char *rep = fl_input("Desired number of bootstrap replicates:", "100"); if (!rep) return; sscanf(rep, "%d", &replicates); if (replicates == -1) return; my_watch_cursor(view->dnawin); save_bootstrap_replicates(filename, replicates, view); fl_reset_cursor(view->dnawin); } else if(reponse == PRINTOUT && view->tot_seqs > 0) { int anerr; char suggested[200], *p; strcpy(suggested, view->masename); p = strrchr(suggested, '.'); if(p != NULL) *p = 0; if(printout_black == TEXT_ONLY) strcat(suggested, ".txt"); else { strcat(suggested, "."PDF_OR_PS_EXT); } if( view->alt_col_rank != NULL ) { for(anerr = 0; anerr < view->tot_seqs; anerr++) if(view->sel_seqs[anerr]) break; } else anerr = -1; #if defined(__APPLE__) filename = mac_GetOutputFName_Plus(extract_filename(suggested), "Enter an output file name", (anerr >= 0 ? TRUE : FALSE), extract_dirname(view->masename) ); #else Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Enter an output file name"); chooser->directory(extract_dirname(suggested)); chooser->preset_file(extract_filename(suggested)); if(printout_black == TEXT_ONLY) chooser->filter("Text Files\t*.txt"); else { #ifdef NO_PDF chooser->filter("PostScript Files\t*.ps"); #else chooser->filter("PDF Files\t*.pdf"); #endif } filename = run_and_close_native_file_chooser(chooser); #endif if(filename == NULL) return; my_watch_cursor(view->dnawin); anerr = printout(view, filename, printout_fontsize, printout_block, printout_pageformat, printout_vary, anerr, printout_black, printout_layout); fl_reset_cursor(view->dnawin); if( anerr ) fl_alert("Error while writing to file %s", filename); } #if !defined(__APPLE__) else if(reponse == PDFOPTIONS ) { pdfps_options_dialog(view, true); } #endif } #if !defined( __APPLE__) static void printout_callback(Fl_Widget *obj, void *data) { const char *p; p = ((Fl_Input *)obj)->value(); sscanf(p, "%d", (int *)data); } static void ok_callback(Fl_Widget *obj) { if(obj->window() == NULL) obj->hide(); else obj->window()->hide(); } static void paper_callback(Fl_Widget *obj) { printout_pageformat = ((Fl_Choice *)obj)->value() == 0 ? Fl_Paged_Device::A4 : Fl_Paged_Device::LETTER; } static void layout_callback(Fl_Widget *obj) { printout_layout = ((Fl_Check_Button *)obj)->value() == 0 ? Fl_Paged_Device::PORTRAIT : Fl_Paged_Device::LANDSCAPE; } static void variable_callback(Fl_Widget *obj) { printout_vary = ! printout_vary; } static void radio_callback(Fl_Widget *obj) { Fl_Group *group; if( ! ((Fl_Round_Button *)obj)->value() ) { ((Fl_Round_Button *)obj)->setonly(); return; } group = obj->parent(); if ( ((Fl_Round_Button *)group->child(0))->value() ) printout_black = PDF_COLOR; if ( ((Fl_Round_Button *)group->child(1))->value() )printout_black = PDF_BW; if ( ((Fl_Round_Button *)group->child(2))->value() ) printout_black = TEXT_ONLY; } Fl_Window* pdfps_options_dialog(SEA_VIEW *view, bool autonomous) { static Fl_Window *pdf_form = NULL; static Fl_Input *sizeinput, *blockinput; static Fl_Choice *paper; static Fl_Round_Button *colorb, *blackb, *tob; static Fl_Check_Button *variable, *landscape; Fl_Button *ok; Fl_Group *radiog; int x, y, w, h; char txt[20]; if(pdf_form == NULL) { fl_font(FL_HELVETICA, FL_NORMAL_SIZE); pdf_form = new Fl_Window(415, 90); pdf_form->box(FL_FLAT_BOX); pdf_form->label("Set "PDF_OR_PS" output options"); x = 5 + (int)fl_width("block size:"); y = 5; w = 50; h = 25; sizeinput = new Fl_Input(x, y, w, h, "font size:"); sizeinput->callback(printout_callback, &printout_fontsize); blockinput = new Fl_Input(x, y + sizeinput->h() + 5 , w, h, "block size:"); blockinput->callback(printout_callback, &printout_block); paper = new Fl_Choice(x + sizeinput->w() + (int)fl_width("paper size:") + 15, y, (int)fl_width("LETTER") + 30, h, "paper size:"); paper->add("A4|LETTER"); paper->callback(paper_callback); landscape = new Fl_Check_Button(paper->x(), paper->y() + 30, 20, 20, "landscape"); landscape->callback(layout_callback); landscape->align(FL_ALIGN_LEFT); x = paper->x() + paper->w() + 5; radiog = new Fl_Group(x, y, (int)fl_width(PDF_OR_PS" color") + 25, 3 * h + 3); radiog->box(FL_DOWN_FRAME); colorb = new Fl_Round_Button(x, y, radiog->w(), h, PDF_OR_PS" color"); blackb = new Fl_Round_Button(x, y + colorb->h() + 5, radiog->w(), h, PDF_OR_PS" B&&W"); tob = new Fl_Round_Button(x, y + colorb->h() + blackb->h() + 5, radiog->w(), h, "Text File"); colorb->callback(radio_callback); colorb->type(FL_RADIO_BUTTON); blackb->callback(radio_callback); blackb->type(FL_RADIO_BUTTON); tob->callback(radio_callback); tob->type(FL_RADIO_BUTTON); radiog->end(); x = blockinput->x() + blockinput->w() + 5; variable = new Fl_Check_Button(x, blockinput->y() + blockinput->h(), (int)fl_width("Variable sites only") + 25, h, "Variable sites only"); variable->box(FL_DOWN_FRAME); variable->callback(variable_callback); ok = new Fl_Button(radiog->x() + radiog->w() + 5, variable->y(), 25, h, "OK"); ok->callback(ok_callback); pdf_form->end(); pdf_form->size(ok->x() + ok->w() + 5 , pdf_form->h() ); pdf_form->resizable(NULL); if (autonomous) pdf_form->set_modal(); else { ok->hide(); pdf_form->box(FL_DOWN_BOX); pdf_form->set_visible(); } } sprintf(txt, "%d", printout_fontsize); sizeinput->value(txt); sprintf(txt, "%d", printout_block); blockinput->value(txt); paper->value(printout_pageformat == Fl_Paged_Device::A4 ? 0 : 1); landscape->value(printout_layout == Fl_Paged_Device::LANDSCAPE ? 1 : 0); if(printout_black == PDF_COLOR) colorb->setonly() ; else if(printout_black == PDF_BW) blackb->setonly() ; else tob->setonly() ; variable->value(printout_vary); if(view->alt_col_rank != NULL && view->tot_sel_seqs == 1) variable->activate(); else variable->deactivate(); if (autonomous) pdf_form->show(); return pdf_form; } #endif void hide_window_callback(Fl_Widget *ob, void *data) { ob->window()->hide(); } void free_colranks_by_difference(char **alt_col_rank, int total) { int num; if(alt_col_rank == NULL) return; for(num = 0; num < total; num++) { free(alt_col_rank[num]); } if( total > 0 ) free(alt_col_rank); } void reference_toggle(SEA_VIEW *view, int on) { char **tmp; static int old_pos; if(view->numb_gc == 1) return; Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); if(on) { /* tenter de passer en mode par reference */ if( view->tot_sel_seqs != 1 || view->numb_gc == 1) { (menu_props + props_parts->reference)->clear(); return; } my_watch_cursor(view->dnawin); for(old_pos = 0; old_pos < view->tot_seqs; old_pos++) if(view->sel_seqs[old_pos]) break; deplacer_grp_seqs(view, 1); set_seaview_modified(view, FALSE); view->first_seq = 1; view->vertsli->Fl_Slider::value(1); view->alt_col_rank = prepcolranks_by_difference(view->sequence, view->tot_seqs, 0, view->max_seq_length, view->each_length, ( view->protein ? get_color_for_aa : get_color_for_base ), view->numb_gc, view->allow_lower); fl_reset_cursor(view->dnawin); if(view->alt_col_rank == NULL) { view->DNA_obj->redraw(); (menu_props + props_parts->reference)->clear(); return; } tmp = view->alt_col_rank; view->alt_col_rank = view->col_rank; view->col_rank = tmp; view->DNA_obj->redraw(); (menu_props + props_parts->colors - 1)->deactivate(); (menu_props + props_parts->reference)->set(); ((Fl_Menu_Item*)view->menubar->find_item("Edit"))->deactivate(); view->menu_species->bar_item()->deactivate(); view->menubar->redraw(); } else { /* retour mode normal */ my_watch_cursor(view->dnawin); tmp = view->alt_col_rank; view->alt_col_rank = view->col_rank; view->col_rank = tmp; free_colranks_by_difference(view->alt_col_rank, view->tot_seqs); view->alt_col_rank = NULL; deplacer_grp_seqs(view, old_pos + 1); set_seaview_modified(view, FALSE); view->DNA_obj->redraw(); (menu_props + props_parts->colors - 1)->activate(); (menu_props + props_parts->reference)->clear(); ((Fl_Menu_Item*)view->menubar->find_item("Edit"))->activate(); view->menu_species->bar_item()->activate(); view->menubar->redraw(); fl_reset_cursor(view->dnawin); } } static Fl_Help_Dialog *help_viewer = NULL; void help_callback(Fl_Widget *ob, void *unused) { if(help_viewer == NULL) { char *help_file; #ifndef DEFAULT_HELPFILE /* to ease FreeBSD port */ #define DEFAULT_HELPFILE "seaview.html" #endif help_file = get_res_value("helpfile", DEFAULT_HELPFILE); help_file = get_full_path(help_file); if(help_file == NULL) { fl_alert( #ifdef __APPLE__ "No help information in program resources" #else "Help file %s\nnot found in PATH directories nor in current directory", help_file #endif ); return; } my_watch_cursor(ob->window()); help_viewer = new Fl_Help_Dialog(); if(help_viewer == NULL) return; #ifdef MICRO help_viewer->resize(help_viewer->x(), help_viewer->y(), 695, 500); help_viewer->textsize(14); #else help_viewer->resize(help_viewer->x(), help_viewer->y(), 740, 500); help_viewer->textsize(12); #endif help_viewer->load(help_file); help_viewer->show(); fl_reset_cursor(ob->window()); #ifndef MICRO //for X11 control where the window appears, useful if multiple screens Fl_Window *w = Fl::first_window();// gives the help_viewer window if(w) w->hotspot(w);//so the window is close to the mouse #endif } else help_viewer->show(); } void direct_help_callback(Fl_Widget *wgt, void *data) { help_callback(wgt, NULL); if(help_viewer != NULL) help_viewer->topline((char *)data); } int insert_gaps_at(SEA_VIEW *view, int seq, int site, int total) { char *pos, **psequence; int l, gapcolor, *plength; if(view->cursor_in_comment) { psequence = view->comment_line; plength = view->comment_length; } else { psequence = view->sequence; plength = view->each_length; if (view->col_rank) gapcolor = ( view->protein ? get_color_for_aa('-') : get_color_for_base('-') ); } l = plength[seq-1]; if(site > l + 1) return total; if( l + total > view->max_seq_length) total = view->max_seq_length - l; pos = psequence[seq-1] + site - 1; memmove(pos+total, pos, l - site + 2); memset(pos, '-', total); if( (!view->cursor_in_comment) && view->col_rank) { pos = view->col_rank[seq-1] + site - 1; memmove(pos+total, pos, l - site + 1); memset(pos, gapcolor, total); } plength[seq-1] += total; if( (!view->cursor_in_comment) && view->curr_colors == view->codoncolors && view->col_rank) { char **tmp = prepcolranks_by_codon(&view->sequence[seq-1], 1, view->max_seq_length, &view->each_length[seq-1], &view->comments[seq-1]); free(view->col_rank[seq-1]); view->col_rank[seq-1] = tmp[0]; free(tmp); } if (view->col_rank) set_seaview_modified(view, TRUE); return total; } int delete_gaps_before(SEA_VIEW *view, int numseq, int numsite, int total) { char *site, *finseq, **psequence; int count = -1, l, retval, *plength; psequence = view->sequence; plength = view->each_length; site = psequence[numseq-1] + numsite - 1; finseq = psequence[numseq-1] + plength[numseq-1] - 1; do { site--; count++; } while ( count < total && site >= psequence[numseq-1] && ( view->allow_seq_edit || *site == '-' || site > finseq) ); if(count == 0) return 0; /* ne rien faire si on efface au dela de la fin de la seq */ if(numsite - count > plength[numseq-1]) return count; l = plength[numseq-1]; retval = count; if(numsite > l) { /* effacer depuis au dela fin jusqu'a interieur seq */ count -= (numsite - l - 1); numsite = l + 1; } site = psequence[numseq-1] + numsite - 1; memmove(site-count, site, l - numsite + 2); if( view->numb_gc > 1) { site= view->col_rank[numseq-1] + numsite - 1; memmove(site - count, site, l - numsite + 1); } plength[numseq-1] -= count; if ( view->curr_colors == view->codoncolors && view->col_rank) { char **tmp = prepcolranks_by_codon(&view->sequence[numseq-1], 1, view->max_seq_length, &view->each_length[numseq-1], &view->comments[numseq-1]); free(view->col_rank[numseq-1]); view->col_rank[numseq-1] = tmp[0]; free(tmp); } if (view->col_rank) set_seaview_modified(view, TRUE); return retval; } void adjust_menu_edit_modes(SEA_VIEW *view) { if(view->menu_edit != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_edit; Fl_Menu_Item *align_items = (Fl_Menu_Item *)view->menu_align; if(view->tot_sel_seqs != 0) { items[DELETE_SEQ].activate(); items[COPY_SEQS].activate(); align_items[PROFILE].activate(); align_items[UNALIGN].activate(); ((Fl_Menu_Item*)view->menu_file)[SAVE_REGIONS].activate(); if(view->protein) items[EXCHANGE_UT].deactivate(); else items[EXCHANGE_UT].activate(); } else { items[DELETE_SEQ].deactivate(); items[EXCHANGE_UT].deactivate(); items[COPY_SEQS].deactivate(); align_items[PROFILE].deactivate(); align_items[UNALIGN].deactivate(); if (view->active_region == NULL) ((Fl_Menu_Item*)view->menu_file)[SAVE_REGIONS].deactivate(); } if(view->tot_sel_seqs != 0 && ! view->protein) items[SET_GCODE].activate(); else items[SET_GCODE].deactivate(); Fl_Menu_Item *menu_props = (Fl_Menu_Item *)view->menu_props; props_menu_parts *props_parts = (props_menu_parts *)menu_props->user_data(); Fl_Menu_Item *byref = menu_props + props_parts->reference; if(view->tot_sel_seqs == 1 && view->curr_colors != view->codoncolors) byref->activate(); else byref->deactivate(); if(view->tot_sel_seqs == 1) { items[RENAME_SEQ].activate(); if(view->viewasprots == NULL) items[DUPLICATE_SEQ].activate(); items[EDIT_COMMENTS].activate(); if(view->viewasprots == NULL) items[EDIT_SEQ].activate(); if(view->protein) { items[COMPLEMENT_SEQ].deactivate(); items[REVERSE_SEQ].deactivate(); } else if(view->viewasprots == NULL) { items[COMPLEMENT_SEQ].activate(); items[REVERSE_SEQ].activate(); } } else { items[RENAME_SEQ].deactivate(); items[DUPLICATE_SEQ].deactivate(); items[EDIT_COMMENTS].deactivate(); items[EDIT_SEQ].deactivate(); items[COMPLEMENT_SEQ].deactivate(); items[REVERSE_SEQ].deactivate(); } if(view->tot_sel_seqs == 2) items[DOT_PLOT].activate(); else items[DOT_PLOT].deactivate(); if(view->tot_sel_seqs >= 2) { align_items[ALIGN_SELECTED_SEQS].activate(); align_items[ALIGN_SITES].activate(); if(view->viewasprots == NULL) items[CONSENSUS_SEQ].activate(); } else { align_items[ALIGN_SELECTED_SEQS].deactivate(); align_items[ALIGN_SITES].deactivate(); items[CONSENSUS_SEQ].deactivate(); } } } void select_deselect_seq(SEA_VIEW *view, int new_seq, int from_tree) { /* new_seq = # seq a select/deselect; si 0: tout deselectionner; si -1: tout selectionner si -2: ne pas changer la selection mais ajuster l'interface selon son etat */ if(new_seq > 0) { /* traiter une sequence */ view->sel_seqs[new_seq-1] = !view->sel_seqs[new_seq-1]; if(view->sel_seqs[new_seq-1]) ++view->tot_sel_seqs; else --view->tot_sel_seqs; } else if(new_seq == 0) { /* tout deselectionner */ view->tot_sel_seqs = 0; memset(view->sel_seqs, 0, view->tot_seqs * sizeof(int)); } else if(new_seq == -1) { /* tout selectionner */ int i; view->tot_sel_seqs = view->tot_seqs; for(i=0; i < view->tot_seqs; i++) view->sel_seqs[i] = TRUE; } adjust_menu_edit_modes(view); if(view->menu_species != NULL) { Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_species->get_menu(); if(items != NULL) { if(view->tot_sel_seqs == 0) items[0].deactivate(); else items[0].activate(); items[1].deactivate(); view->menu_species->value(0); } } if (!from_tree) { select_deselect_in_tree(view); } } void deplacer_grp_seqs(SEA_VIEW *view, int target) { /* deplacer toutes les seqs selectionnees pour positionner la premiere d'entre elles en position target */ int *new_rank, *old_rank, old, new_val, numset; char **aux; -- target; new_rank = (int *)malloc(view->tot_seqs * sizeof(int)); old_rank = (int *)malloc(view->tot_seqs * sizeof(int)); aux = (char **)malloc( view->tot_seqs * sizeof(char *) ); if(new_rank == NULL || old_rank == NULL || aux == NULL) out_of_memory(); /* compute old_rank[new_val] = old */ new_val = -1; /* place first all non selected seqs */ for(old = 0; old < view->tot_seqs; old++) { if(!view->sel_seqs[old]) old_rank[++new_val] = old; } /* allocate room for selected seqs */ if(target + view->tot_sel_seqs > view->tot_seqs) target = view->tot_seqs - view->tot_sel_seqs; old = view->tot_seqs - view->tot_sel_seqs - target; if(old != 0) memmove(old_rank + target + view->tot_sel_seqs, old_rank + target, old * sizeof(int)); /* insert selected seqs */ for(old = 0; old < view->tot_seqs; old++) if(view->sel_seqs[old]) old_rank[target++] = old; /* compute new_rank[old] = new_val */ for(new_val = 0; new_val < view->tot_seqs; new_val++) new_rank[old_rank[new_val]] = new_val; /* displace all sequence order-dependent ingredients */ /* deplacer la position du curseur */ if(!view->cursor_in_comment) { view->cursor_seq = new_rank[view->cursor_seq - 1] + 1; view->old_cursor_seq = view->cursor_seq; } /* deplacer les seqs */ for(old = 0; old < view->tot_seqs; old++) aux[new_rank[old]] = view->sequence[old]; memcpy(view->sequence, aux, view->tot_seqs * sizeof(char *) ); /* deplacer les noms */ for(old = 0; old < view->tot_seqs; old++) aux[new_rank[old]] = view->seqname[old]; memcpy(view->seqname, aux, view->tot_seqs * sizeof(char *) ); if(view->comments != NULL) { /* deplacer les commentaires */ for(old = 0; old < view->tot_seqs; old++) aux[new_rank[old]] = view->comments[old]; memcpy(view->comments, aux, view->tot_seqs * sizeof(char *) ); } if(view->viewasprots != NULL) { /* deplacer les DNA seqs conservees pour mode vision traduction */ char **viewasprots = (char **)view->viewasprots; for(old = 0; old < view->tot_seqs; old++) aux[new_rank[old]] = viewasprots[old]; memcpy(viewasprots, aux, view->tot_seqs * sizeof(char *) ); } /* deplacer les seqs en couleurs */ if(view->numb_gc > 1) { for(old = 0; old < view->tot_seqs; old++) aux[new_rank[old]] = view->col_rank[old]; memcpy(view->col_rank, aux, view->tot_seqs * sizeof(char *) ); } /* deplacer les sequences selectionnees */ for(old = 0; old < view->tot_seqs; old++) old_rank[new_rank[old]] = view->sel_seqs[old]; memcpy(view->sel_seqs, old_rank, view->tot_seqs * sizeof(int) ); /* deplacer les longueurs de sequences */ for(old = 0; old < view->tot_seqs; old++) old_rank[new_rank[old]] = view->each_length[old]; memcpy(view->each_length, old_rank, view->tot_seqs * sizeof(int) ); /* process species sets */ for(numset = 0; numset < view->numb_species_sets; numset++) { for(old = 0; old < view->tot_seqs; old++) old_rank[new_rank[old]] = view->list_species_sets[numset][old]; memcpy(view->list_species_sets[numset], old_rank, view->tot_seqs * sizeof(int) ); } free(aux); free(old_rank); free(new_rank); set_seaview_modified(view, TRUE); } void update_current_seq_length(int newlength, SEA_VIEW *view) { double x; int l; if(newlength > view->seq_length) { view->seq_length = ( newlength+20 < view->max_seq_length ? newlength+20 : view->max_seq_length ); l = view->seq_length - view->tot_sites+3; if(l<1) l=1; view->horsli->bounds(1,l); x = ( (double) view->tot_sites ) / ( view->seq_length + 3 ) ; if(x>1) x=1; view->horsli->slider_size(x); } } int insert_char_in_seq( int key, int total, SEA_VIEW *view) /* to insert the typed key in the sequence at cursor location if it is visible returns # of inserted chars if ok, 0 if error (= cursor not visible or max seq size is reached) */ { char *pos; int l, c, *plength; if(view->cursor_in_comment) { if( view->cursor_seq < 1 || view->cursor_seq >= view->tot_comment_lines || view->cursor_site < view->first_site || view->cursor_site >= view->first_site + view->tot_sites ) return 0; l = view->comment_length[view->cursor_seq - 1]; } else { if( view->cursor_seq < view->first_seq || view->cursor_seq >=view->first_seq+view->tot_lines || view->cursor_site < view->first_site || view->cursor_site >= view->first_site + view->tot_sites ) return 0; l = view->each_length[view->cursor_seq-1]; } if(view->cursor_site > l + 1) return 0; if( l + total > view->max_seq_length) total = view->max_seq_length - l; if(total <= 0) return 0; if(view->cursor_in_comment) pos = view->comment_line[view->cursor_seq - 1] + view->cursor_site - 1; else pos = view->sequence[view->cursor_seq - 1] + view->cursor_site - 1; memmove(pos+total, pos, l - view->cursor_site + 2); memset(pos, view->cursor_in_comment || view->allow_lower ? key : toupper(key) , total); if( (!view->cursor_in_comment) && view->numb_gc > 1) { pos= &view->col_rank[view->cursor_seq-1][view->cursor_site-1]; memmove(pos+total, pos, l - view->cursor_site + 1); c = (view->protein ? get_color_for_aa(key) : get_color_for_base(key) ); memset(view->col_rank[view->cursor_seq-1] + view->cursor_site - 1, c, total); } if(view->cursor_in_comment) plength = &(view->comment_length[view->cursor_seq-1]); else plength = &(view->each_length[view->cursor_seq-1]); (*plength) += total; update_current_seq_length(*plength, view); if( (!view->cursor_in_comment) && view->curr_colors == view->codoncolors) { char **tmp = prepcolranks_by_codon(&view->sequence[view->cursor_seq-1], 1, view->max_seq_length, &view->each_length[view->cursor_seq-1], &view->comments[view->cursor_seq-1]); free(view->col_rank[view->cursor_seq-1]); view->col_rank[view->cursor_seq-1] = tmp[0]; free(tmp); } set_seaview_modified(view, TRUE); return total; } /* The routine that does drawing */ void DNA_obj::draw(void) { SEA_VIEW *view = (SEA_VIEW *)this->user_data(); if(view == NULL) return; //this is necessary after deletion of an alignment window /* returns TRUE if window size was changed by user */ if( compute_size_params( view, FALSE) ) { view->horsli->redraw(); view->vertsli->redraw(); } if( ( this->damage() & FL_DAMAGE_ALL ) != 0 ) { // appel autre que uniquement par damage partiel view->draw_names = -1; view->mod_cursor = view->mod_region_line = view->mod_comment_line = FALSE; view->mod_seq = 0; } if(view->draw_names) { /* soit tous (<= -1) soit un seul ( >= 1) */ draw_seq_names(view->DNA_obj, view); if(view->draw_names > 0 || view->draw_names == -2){ /* si > 0 ou -2, ne pas ecrire les seqs*/ view->draw_names = -1; return; } } if(view->mod_cursor) { /* effacer old_cursor en ecrivant dessus */ draw_cursor(view->DNA_obj, FALSE, view->old_cursor_site, view->old_cursor_seq, view->old_cursor_in_comment); view->mod_cursor = FALSE; } else if(view->mod_region_line) { draw_region_line(view->DNA_obj, view); view->mod_region_line = FALSE; } else if(view->mod_comment_line) { draw_comment_lines(view->DNA_obj, view); view->mod_comment_line = FALSE; } else { if(view->tot_seqs == 0) { #define DRAG_MESS "alignment file drag zone" fl_color(FL_WHITE); fl_font(FL_TIMES_BOLD_ITALIC, 28 ); fl_draw(DRAG_MESS, (int)(this->x()+this->w()/2-fl_width(DRAG_MESS)/2 + 0.5), this->y()+this->h()/2); } if(view->inverted_colors) draw_dna_seqs_inverted(view->DNA_obj, view); else draw_dna_seqs(view->DNA_obj, view); draw_comment_lines(view->DNA_obj, view); } view->mod_seq = 0; view->draw_names = -1; draw_cursor(view->DNA_obj, TRUE , view->cursor_site, view->cursor_seq, view->cursor_in_comment); view->old_cursor_seq = view->cursor_seq; view->old_cursor_site = view->cursor_site; view->old_cursor_in_comment = view->cursor_in_comment; } int my_event_button(void) /* returns mouse button number 1=left, 2=centre, 3=right. on Mac or Win32, extra buttons can also be emulated by modifier keys (shift for right, ctrl for middle) Also returns 4 for cmd-Click (Mac) alt-Click (win32) meta-Click (X11) */ { #ifdef __APPLE__ #define EXTRA_MODIF_KEY FL_META #elif defined(WIN32) #define EXTRA_MODIF_KEY FL_ALT #else #define EXTRA_MODIF_KEY FL_META #endif int key; key = Fl::event_button(); /* key: 1=gauche, 2=centre, 3=droit souris */ if(key == 1) {//emulate mouse buttons by modifiers if(Fl::event_state(FL_CTRL)) key = 2;// bouton du milieu par Ctrl-Click else if(Fl::event_state(FL_SHIFT)) key = 3;// bouton droit par Shift-Click } if(Fl::event_state(EXTRA_MODIF_KEY)) key = 4;// cmd-Click (Mac) alt-Click (win32) meta-Click (X11) return key; } int DNA_obj::handle(int event) { SEA_VIEW *view; /* numero courant de la derniere seq selectionnee pendant selection de seqs par glissement de la souris */ static int selecting_seqs = 0, sel_seq_move = 0; static int modifying_segment = 0; int mx = Fl::event_x(); int my = Fl::event_y(); static int doing_dnd = FALSE; view = (SEA_VIEW *) ( this->user_data() ); if(view == NULL) return 1; switch (event) { case FL_DND_ENTER: return view->tot_seqs == 0; case FL_DND_DRAG: return view->tot_seqs == 0; case FL_DND_RELEASE: if(view->tot_seqs == 0) { doing_dnd = TRUE; return 1; } else return 0; case FL_PASTE: char *p; p = (char*)Fl::event_text(); #if ! ( defined(__APPLE__) || defined(WIN32) ) if(doing_dnd) { char *q; if(strncmp(p, "file://", 7) == 0) p += 7; if((q = strchr(p, '\r')) != NULL) *q = 0; if((q = strchr(p, '\n')) != NULL) *q = 0; #if 100*FL_MAJOR_VERSION + 10*FL_MINOR_VERSION + FL_PATCH_VERSION == 130 char *zero = p + strlen(p); q = p; while (*q) { if (*q == '%') { // non-ascii chars are recoded by %## using their hexadecimal value int h; sscanf(q+1, "%2X", &h); *q = h; memmove(q+1, q+3, zero - (q+2)); zero -= 2; } q++; } #else fl_decode_uri(p); #endif } #endif handle_paste(view, p, doing_dnd); doing_dnd = FALSE; Fl::focus(this); return 1; case FL_FOCUS: case FL_UNFOCUS: return 1; case FL_PUSH: int key; key = my_event_button(); if( key == 1 && Fl::event_clicks() ) { /* left double click */ int new_seq; Fl::event_clicks(0); new_seq = (my + view->line_height/2 - view->y_seq)/view->line_height + view->first_seq; if( new_seq < view->first_seq || new_seq > view->tot_seqs || new_seq >= view->first_seq + view->tot_lines ) break; if(mx < view->x_name || mx >= view->x_seq - view->char_width || key != 1) break; /* double click sur nom de seq: selection de toutes les seqs */ /* if(view->alt_col_rank != NULL) break; if(view->multipl->argument() > 0) mod_multipl(view,0); select_deselect_seq(view, -1); selecting_seqs = 0; view->draw_names = -2; // ceci signifie redraw partiel commande' par draw_names, mod_cursor, ... this->damage(1); */ } else { /* simple click */ Fl::focus(this); handle_push(view, mx, my, key, &modifying_segment, &selecting_seqs, &sel_seq_move); } break; case FL_DRAG: /* mouvement avec souris enfoncee */ handle_mouse(view, mx, my, &selecting_seqs, &sel_seq_move, &modifying_segment); break; case FL_RELEASE: // case FL_LEAVE: if(selecting_seqs) { if(sel_seq_move) { select_deselect_seq(view, sel_seq_move); view->draw_names = sel_seq_move; this->damage(1); } else select_deselect_seq(view, -2); selecting_seqs = 0; } else if(modifying_segment) { end_change_segment(view); view->draw_names = 0; this->damage(1); modifying_segment = 0; } break; case FL_KEYBOARD: if( Fl::event_state(FL_COMMAND) ) { /* vrai si touche ctrl */ return 0; /* ne pas traiter ici car shortcut d'autres widgets */ } key = Fl::event_key(); if(key == FL_Delete || key == FL_BackSpace || key == FL_Right || key == FL_Left || key == FL_Up || key == FL_Down || key == FL_Page_Up || key == FL_Page_Down) { handle_keyboard(view, key, FALSE ); return 1; } if(Fl::event_length() > 0) { // du vrai texte handle_keyboard(view, Fl::event_text()[0], TRUE ); } break; default : return 0; } return 1; } void handle_paste(SEA_VIEW *view, char *clipboard, int doing_dnd) { if (doing_dnd) { use_initial_file(view, clipboard, doing_dnd); return; } char **seqs, **seqnames, **comments, *p, *message; int count, i, num, changedwname = FALSE; if (pasted_from_what_source == 1 || memcmp(clipboard, CLIPBOARDMARK, strlen(CLIPBOARDMARK)) ) { if (pasted_from_what_source == 0) { pasted_from_what_source = 1; // try to paste from clipboard that may contain fasta data Fl::paste(*(view->DNA_obj), 1); return; } if (*clipboard != '>') return; char *header, *err_message; char *fname = create_tmp_filename(); FILE *out = fopen(fname, "w"); fputs(clipboard, out); fclose(out); count = read_fasta_align(fname, &seqs, &seqnames, &comments, &header, &err_message, false); delete_tmp_filename(fname); if (count) { i = fl_choice("You are about to add to this alignment %d sequence%s (%s) \n" "present in the clipboard.", "Cancel", "Confirm", NULL, count, (count > 1 ? "s" : ""), seqnames[0]); if (!i) return; } } else { p = (char*)strchr(clipboard, ':') + 1; count = read_mase_seqs_header(p, &seqs, &seqnames, &comments, NULL, &message); } if (count == 0) return; if (view->tot_seqs == 0 && view->masename == NULL) { view->masename = strdup("newfile"); changedwname = TRUE; } for (i = 0; i < count; i++) { num = add_seq_to_align(view, seqnames[i], seqs[i], strlen(seqs[i])); if(num != 0) view->comments[view->tot_seqs - 1] = comments[i]; } if (changedwname) { #ifdef __APPLE__ rename_windowmenuitem(view->dnawin->label(), find_windowmenuitem(view->dnawin)); #endif ((Fl_Menu_Item*)view->menu_file)[SAVE].deactivate(); } } void handle_mouse(SEA_VIEW *view, int mx, int my, int *p_selecting_seqs, int *p_sel_seq_move, int *p_modifying_segment) { /* mouvement avec souris enfoncee */ int debut, fin, step, num, new_seq, new_site; if(*p_selecting_seqs != 0) { new_seq = (my + view->line_height/2 - view->y_seq)/view->line_height + view->first_seq; if(new_seq == *p_selecting_seqs) return; if( new_seq < view->first_seq || new_seq > view->tot_seqs || new_seq >= view->first_seq + view->tot_lines ) return; if(!view->sel_seqs[new_seq - 1]) { debut= new_seq; fin = *p_selecting_seqs; } else { debut= *p_selecting_seqs; fin = new_seq; } if(debut < fin) step = 1; else step = -1; *p_selecting_seqs = new_seq; for(num = debut; num != fin; num += step) { new_seq = debut + fin - step - num - 1; if(view->sel_seqs[new_seq]) { view->sel_seqs[new_seq] = FALSE; --(view->tot_sel_seqs); } else { view->sel_seqs[new_seq] = TRUE; ++(view->tot_sel_seqs); } if(*p_sel_seq_move == new_seq + 1) *p_sel_seq_move = 0; } if(*p_sel_seq_move) { if( view->sel_seqs[*p_sel_seq_move - 1] ) { view->sel_seqs[*p_sel_seq_move - 1] = FALSE; --(view->tot_sel_seqs); } else { view->sel_seqs[*p_sel_seq_move - 1] = TRUE; ++(view->tot_sel_seqs); } *p_sel_seq_move = 0; } view->draw_names = -2; view->DNA_obj->damage(1); } else if(*p_modifying_segment != 0) { new_site = (mx - view->x_seq )/view->char_width + view->first_site; if(new_site == *p_modifying_segment) return; if( new_site < view->first_site || new_site > view->first_site + view->tot_sites || new_site > view->region_length ) return; if( continue_change_segment(view, new_site) ) { *p_modifying_segment = new_site; view->draw_names = 0; view->mod_region_line = TRUE; view->DNA_obj->damage(1); } } } void handle_push(SEA_VIEW *view, int mx, int my, int key, int *p_modifying_segment, int *p_selecting_seqs, int *p_sel_seq_move) /* key: 1=bouton gauche, 2=centre, 3=droit de la souris */ { int new_site, new_seq, new_line; if(view->multipl->argument() > 0) mod_multipl(view,0); new_seq = (my + view->line_height/2 - view->y_seq)/view->line_height + view->first_seq; new_line = new_seq - view->first_seq + 1; new_site = (mx - view->x_seq )/view->char_width + view->first_site; if(view->active_region != NULL && new_seq == view->first_seq + FL_min(view->tot_lines,view->tot_seqs) && new_site >= view->first_site && new_site < view->first_site + view->tot_sites && new_site <= view->region_length ) { /* work with segments: extend, or create, or delete */ if(key == 2) { /* middle button:extend left neighbor segment */ new_seq = extend_segment_at_left(view, new_site); if(new_seq) fl_beep(FL_BEEP_DEFAULT); else { view->draw_names = 0; } } else if(key == 3) { /* right button=>delete segment */ new_seq = suppr_segment(view->active_region, new_site, view->region_line); if(new_seq) fl_beep(FL_BEEP_DEFAULT); else { view->draw_names = 0; } } else { /* left button=>extend or create segment */ new_seq = begin_change_segment(view, new_site); if(new_seq) { view->mod_region_line = TRUE; *p_modifying_segment = new_site; } view->draw_names = 0; } if(view->draw_names == 0) { view->DNA_obj->damage(1); } return; } if( view->show_comment_lines && new_line >= view->pos_first_comment_line && new_line < view->pos_first_comment_line + view->tot_comment_lines ) { /* dans les comment lines */ int num, old; if(key != 1) return; num = new_line - view->pos_first_comment_line + 1; if(mx >= view->x_name && mx < view->x_seq - view->char_width) { /* click sur nom de comment line: selection/deselection */ old = view->active_comment_line; if(old == num) view->active_comment_line = 0; else view->active_comment_line = num; if(old == num || old == 0) view->mod_comment_line = num; else { view->mod_comment_line = 0; view->mod_seq = 1; // astuce } view->draw_names = 0; update_menu_footers(view); view->DNA_obj->damage(1); } else if( new_site >= view->first_site && new_site < view->first_site + view->tot_sites && new_site <= view->comment_length[num - 1] + 1 ) { /* click sur comment: positionnement du curseur */ view->cursor_site = new_site; view->cursor_seq = num; view->draw_names = 0; view->mod_cursor = TRUE; view->cursor_in_comment = TRUE; view->DNA_obj->damage(1); } return; } if( new_seq < view->first_seq || new_seq > view->tot_seqs || new_seq >= view->first_seq + view->tot_lines ) return; if(mx >= view->x_name && mx < view->x_seq - view->char_width) { /* click sur nom de seq: selection/deselection */ if(view->alt_col_rank != NULL) return; if(key == 1) { *p_selecting_seqs = new_seq; *p_sel_seq_move = new_seq; return; } else if(key == 3) { select_deselect_seq(view, 0); view->draw_names = -2; view->DNA_obj->damage(1); return; } else if(key == 4) { //cmd-Click select from last selected to here int i; for(i = new_seq; i > 0; i--) { if(view->sel_seqs[i - 1]) break; } if(i == 0) return; while(++i <= new_seq) { if(!view->sel_seqs[i - 1]) { view->sel_seqs[i - 1] = TRUE; view->tot_sel_seqs++; } } select_deselect_seq(view, -2); view->draw_names = -2; view->DNA_obj->damage(1); return; } else { /* milieu: depl des seqs selectionnees */ if(view->tot_sel_seqs == 0 || view->sel_seqs[new_seq - 1]) { fl_beep(FL_BEEP_DEFAULT); return; } deplacer_grp_seqs(view, new_seq); view->DNA_obj->redraw(); } return; } if(key != 1) return; /* click sur seq: positionnement du curseur */ if( new_site >= view->first_site && new_site < view->first_site + view->tot_sites && new_site <= view->each_length[new_seq-1] + 1 ) { view->cursor_site = new_site; view->cursor_seq = new_seq; view->cursor_in_comment = FALSE; view->draw_names = 0; view->mod_cursor = TRUE; view->DNA_obj->damage(1); } return; } void handle_keyboard(SEA_VIEW *view, unsigned int key, int istext) { int new_pos, multipl, num; multipl = view->multipl->argument(); if(multipl == 0) multipl = 1; if(key == FL_Right) { /* right arrow */ new_pos = view->cursor_site + multipl; if(view->cursor_in_comment) { if(new_pos > view->comment_length[view->cursor_seq-1]+1) new_pos = view->comment_length[view->cursor_seq-1]+1; } else { if(new_pos > view->each_length[view->cursor_seq-1] + 1) new_pos = view->each_length[view->cursor_seq-1] + 1; } set_and_show_new_cursor_site(view, new_pos,FALSE,FALSE); } else if(key == FL_Left) { /* left arrow */ new_pos = FL_max(1, view->cursor_site - multipl); set_and_show_new_cursor_site(view, new_pos,FALSE,FALSE); } else if(key == FL_Up) { /* up arrow */ new_pos = FL_max(1, view->cursor_seq - multipl); set_and_show_new_cursor_seq(view, new_pos); } else if(key == FL_Down){ /* down arrow */ new_pos = view->cursor_seq + multipl; if(view->cursor_in_comment) { if(new_pos > view->tot_comment_lines) new_pos = view->tot_comment_lines; } else { if(new_pos > view->tot_seqs) new_pos = view->tot_seqs; } set_and_show_new_cursor_seq(view, new_pos); } else if(key == FL_Page_Up) { /* page up key */ new_pos = FL_max(1, view->cursor_seq - view->tot_lines + 1); set_and_show_new_cursor_seq(view, new_pos); } else if(key == FL_Page_Down) { /* page down key */ new_pos = FL_min(view->tot_seqs, view->cursor_seq + view->tot_lines - 1); set_and_show_new_cursor_seq(view, new_pos); } else if(view->cursor_in_comment && view->active_comment_line == view->cursor_seq) { unsigned char c_key = (unsigned)key; if(view->alt_col_rank != NULL) return; if( key == 0x7f || key == 0x8 || key == FL_Delete || key == FL_BackSpace ) /* del or BS */ delete_char_in_comment(view, 1, view->active_comment_line, view->cursor_site, FALSE); else if( istext && ( ( c_key >= 32 && c_key <= 126 ) || ( c_key >= 160 /* && c_key <= 255 */ ) ) ) insert_char_in_comment(c_key, 1, view); else return; } else if(strchr(view->movekeys, key) != NULL) { /* ][>< touches depl droite/gauche */ int oldpos; int upper_step=50, bracket_step=5 ; int max_w; max_w = (int)(view->horsli->maximum()); oldpos = (int)( view->horsli->value() ); new_pos = oldpos; upper_step *= multipl; bracket_step *= multipl; if ((int)key == view->movekeys[2] /* > */ ) { new_pos=oldpos+upper_step; if(new_pos>max_w) new_pos=max_w; } else if((int)key == view->movekeys[3] /* < */ ) { new_pos=oldpos-upper_step; if(new_pos<1) new_pos=1; } else if((int)key == view->movekeys[0] /* ] */ ) { new_pos=oldpos+bracket_step; if(new_pos>max_w) new_pos=max_w; } else if((int)key == view->movekeys[1] /* [ */ ) { new_pos=oldpos-bracket_step; if(new_pos<1) new_pos=1; } if(new_pos!=oldpos) { view->horsli->Fl_Slider::value(new_pos); view->draw_names = 0; view->first_site = new_pos; view->DNA_obj->damage(1); } } else if(key == 0x7f || key == 0x8 || key == FL_Delete || key == FL_BackSpace ) { /* delete or backspace */ int count, count_each, debut, fin, test; if(view->multipl->argument() > 0) mod_multipl(view,0); if(view->cursor_in_comment) test = view->cursor_seq < 1 || view->cursor_seq > view->tot_comment_lines; else test = view->cursor_seq < view->first_seq || view->cursor_seq >= view->first_seq+view->tot_lines; if( test || view->cursor_site < view->first_site || view->cursor_site >=view->first_site+view->tot_sites) { fl_beep(FL_BEEP_DEFAULT); return; } if(view->cursor_in_comment) { if( delete_char_in_comment(view, multipl, view->cursor_seq, view->cursor_site, TRUE) != multipl) fl_beep(FL_BEEP_DEFAULT); return; } if(view->alt_col_rank != NULL) return; if(view->tot_sel_seqs > 1 && view->sel_seqs[view->cursor_seq - 1]) { debut = 1; fin = view->tot_seqs; test = TRUE;} else { debut = fin = view->cursor_seq; test = FALSE;} if(multipl > view->cursor_site - 1) multipl = view->cursor_site - 1; for(num = debut; num<=fin; num++) { if(test && !view->sel_seqs[num-1]) continue; count_each = delete_gaps_before(view, num, view->cursor_site, multipl); if(count_each < multipl) fl_beep(FL_BEEP_DEFAULT); if(num == view->cursor_seq) count = count_each; } /* si ttes seqs selectionnees, traiter aussi regions et comments */ if(count_each == multipl && (!view->cursor_in_comment) && view->tot_sel_seqs == view->tot_seqs ) { if(view->regions != NULL) delete_region_part(view, view->cursor_site,multipl); if(view->tot_comment_lines > 0) delete_in_all_comments(multipl, view->cursor_site, view); } new_pos = view->cursor_site - count; if(new_pos <= 0) new_pos = 1; if(view->cursor_in_comment) { view->mod_comment_line = view->cursor_seq; } else { if(view->tot_sel_seqs > 1 && view->tot_sel_seqs != view->tot_seqs && view->sel_seqs[view->cursor_seq - 1]) view->mod_seq = -1; else if(view->tot_sel_seqs <= 1 || !view->sel_seqs[view->cursor_seq - 1]) view->mod_seq = view->cursor_seq; } set_and_show_new_cursor_site(view, new_pos, FALSE,TRUE); } else if(key == '_' ) { /* del gap in all but current seq(s) */ int count_each; if(view->multipl->argument() > 0) mod_multipl(view,0); if(view->cursor_in_comment) return; if( view->cursor_seq < view->first_seq || view->cursor_seq >=view->first_seq+view->tot_lines || view->cursor_site < view->first_site || view->cursor_site >= view->first_site + view->tot_sites || view->tot_sel_seqs == view->tot_seqs ) { fl_beep(FL_BEEP_DEFAULT); return; } if(view->alt_col_rank != NULL) return; for( num = 1; num <= view->tot_seqs; num++) { if(num == view->cursor_seq || (view->sel_seqs[view->cursor_seq-1] && view->sel_seqs[num-1] ) ) continue; count_each = delete_gaps_before(view, num, view->cursor_site, multipl); if(count_each < multipl) { fl_beep(FL_BEEP_DEFAULT); return; } } if(count_each == multipl && view->regions != NULL) delete_region_part(view, view->cursor_site, multipl); if(count_each == multipl && view->tot_comment_lines > 0) delete_in_all_comments(multipl, view->cursor_site, view); new_pos = view->cursor_site - multipl; if(new_pos <= 0) new_pos = 1; set_and_show_new_cursor_site(view, new_pos, FALSE, TRUE); } else if( key == '-' || (key == ' ' && !view->hjkl) /* gap key = - or space */ || key == '+' ) { /* insert gap in other seqs key */ int newlength = 0, count = 0, count_each, debut, fin, test; if(view->multipl->argument() > 0) mod_multipl(view,0); if(view->cursor_in_comment && key == '+') return; if(view->cursor_in_comment) test = FALSE; else test = view->cursor_seq < view->first_seq || view->cursor_seq >=view->first_seq+view->tot_lines; if( test || view->cursor_site < view->first_site || view->cursor_site >= view->first_site + view->tot_sites ) { fl_beep(FL_BEEP_DEFAULT); return; } if(view->alt_col_rank != NULL) return; if(key != '+') { /* gap key */ if(view->tot_sel_seqs > 1 && (!view->cursor_in_comment) && view->sel_seqs[view->cursor_seq - 1]) { debut = 1; fin = view->tot_seqs; test = TRUE;} else { debut = fin = view->cursor_seq; test = FALSE;} for(num = debut; num<=fin; num++) { if(test && !view->sel_seqs[num-1]) continue; count_each = insert_gaps_at(view, num, view->cursor_site, multipl); if(count_each < multipl) fl_beep(FL_BEEP_DEFAULT); if(num == view->cursor_seq) count = count_each; if(view->cursor_in_comment) { if(newlength < view->comment_length[num-1]) newlength = view->comment_length[num-1]; } else { if(newlength < view->each_length[num-1]) newlength = view->each_length[num-1]; } } /* si ttes seqs selectionnees, traiter aussi regions et comments */ if(count_each == multipl && (!view->cursor_in_comment) && view->tot_sel_seqs == view->tot_seqs) { if(view->regions != NULL) insert_region_part(view, view->cursor_site, multipl); if(view->tot_comment_lines > 0) insert_gap_all_comments(multipl,view->cursor_site, view); } } else { /* + ==> gap in other sequences */ if(view->tot_sel_seqs == view->tot_seqs) { fl_beep(FL_BEEP_DEFAULT); return; } for( num = 1; num <= view->tot_seqs; num++) { if(num == view->cursor_seq || (view->sel_seqs[view->cursor_seq-1] && view->sel_seqs[num-1] ) ) continue; count_each = insert_gaps_at(view, num, view->cursor_site, multipl); if(count_each < multipl) { fl_beep(FL_BEEP_DEFAULT); return; } if(newlength < view->each_length[num-1]) newlength = view->each_length[num-1]; } count = multipl; if(count_each == multipl && view->regions != NULL) insert_region_part(view, view->cursor_site, multipl); if(count_each == multipl && view->tot_comment_lines > 0) { insert_gap_all_comments(multipl,view->cursor_site, view); } } new_pos = view->cursor_site + count; if(view->cursor_in_comment) { if(new_pos> view->comment_length[view->cursor_seq-1]+1) new_pos= view->comment_length[view->cursor_seq-1]+1; } else { if(new_pos > view->each_length[view->cursor_seq-1] + 1) new_pos = view->each_length[view->cursor_seq-1] + 1; } if(view->cursor_in_comment) view->mod_comment_line = view->cursor_seq; else if(key != '+' ) { if(view->tot_sel_seqs > 1 && view->tot_sel_seqs != view->tot_seqs && view->sel_seqs[view->cursor_seq - 1]) view->mod_seq = -1; else if(view->tot_sel_seqs <= 1 || !view->sel_seqs[view->cursor_seq - 1] ) view->mod_seq = view->cursor_seq; } update_current_seq_length(newlength, view); set_and_show_new_cursor_site(view, new_pos, FALSE,TRUE); } else if( key >= '0' && key <= '9' ) { /* multiplicateur */ multipl = view->multipl->argument() * 10; multipl += (key - '0'); mod_multipl(view, multipl); return; } else if( view->allow_seq_edit && (view->alt_col_rank == NULL) && (!view->cursor_in_comment) && isprint(key) /* a user asked for inserting special characters in sequences */ ) { if(view->hjkl) { static char typedkey[]= "hjklHJKL "; static char dnaequivs[3][10]={ "gatcGATCN", "tcgaTCAGN", "acgtACGTN"}; char *p; p = strchr(typedkey, key); if(p != NULL) key = *( dnaequivs[view->hjkl - 1] + (p - typedkey) ); } if(key == ' ') num = 0; else num = insert_char_in_seq(key, multipl, view); if( num == 0 ) fl_beep(FL_BEEP_DEFAULT); else { view->mod_seq = view->cursor_seq; set_and_show_new_cursor_site(view, view->cursor_site + num, FALSE, TRUE); } } else return; if(view->multipl->argument() > 0) mod_multipl(view, 0); } Fl_Group *create_dna_scroller(SEA_VIEW *view, int x, int y, int w, int h, int double_buffer) { Fl_Group *dna_group; Fl_Widget *obj; int wmultipl, x_pos; user_data_plus *data; dna_group = new Fl_Group(x,y,w,h); int scroll_w = 15; #ifdef __APPLE__ #define DELTA_G 13 // laisser place pour poignée de dimensionnement de fenetre #else #define DELTA_G 0 #endif /* screen move haut */ view->up_screen_move = obj = (Fl_Widget*)new Fl_Repeat_Button(x+3, y,scroll_w,scroll_w,"@8>>"); obj->labeltype(FL_SYMBOL_LABEL); data = new user_data_plus; data->p = view; data->value = 5; obj->callback(lrdu_button_callback, data); /* ascenc. vertical */ view->vertsli = new Fl_Scrollbar(x+3, y + scroll_w + 2, scroll_w, h - 3*scroll_w - 12, ""); view->vertsli->box(FL_DOWN_BOX); data = new user_data_plus; data->p = view; data->value = 0; ((Fl_Scrollbar *)view->vertsli)->linesize(1); view->vertsli->callback(vh_sliders_callback, data); view->vertsli->bounds(1,1); view->vertsli->slider_size(1); view->vertsli->Fl_Slider::value(1); view->vertsli->step(1); view->vertsli->when(FL_WHEN_CHANGED); /* screen move bas */ view->down_screen_move = obj = (Fl_Widget*)new Fl_Repeat_Button(x+3, y + h - 2 * scroll_w - 8, scroll_w, scroll_w, "@2>>"); obj->labeltype(FL_SYMBOL_LABEL); data = new user_data_plus; data->p = view; data->value = 7; obj->callback(lrdu_button_callback, data); int y_scroll = y + h - scroll_w - 3; /* valeur du multiplicateur */ fl_font(FL_HELVETICA, FL_NORMAL_SIZE); wmultipl = (int)fl_width("mult=9999"); x_pos = 5; view->multipl = obj = (Fl_Widget*)new Fl_Box(FL_FLAT_BOX, x+x_pos, y_scroll - 2, wmultipl, FL_NORMAL_SIZE + 4, ""); x_pos += wmultipl + 5; obj->labelfont(FL_HELVETICA); obj->labelsize(FL_NORMAL_SIZE); obj->align(FL_ALIGN_CENTER); /* screen move gauche */ view->left_screen_move = obj = (Fl_Widget*)new Fl_Repeat_Button(x+x_pos,y_scroll,scroll_w,scroll_w,"@<<"); obj->labeltype(FL_SYMBOL_LABEL); x_pos += scroll_w + 2; data = new user_data_plus; data->p = view; data->value = 1; obj->callback(lrdu_button_callback, data); /* ascens. horizontal */ view->horsli = new Fl_Scrollbar(x + x_pos, y_scroll, w - x_pos - scroll_w - 2 - DELTA_G, scroll_w,""); view->horsli->type(FL_HORIZONTAL); view->horsli->box(FL_DOWN_BOX); ((Fl_Scrollbar *)view->horsli)->linesize(1); data = new user_data_plus; data->p = view; data->value = 1; view->horsli->callback(vh_sliders_callback, data); view->horsli->bounds(1,1); view->horsli->slider_size(1); view->horsli->Fl_Slider::value(1); view->horsli->step(1); view->horsli->when(FL_WHEN_CHANGED); /* screen move a droite */ view->right_screen_move = obj = (Fl_Widget*)new Fl_Repeat_Button(x+w - scroll_w - DELTA_G, y_scroll, scroll_w, scroll_w,"@>>"); obj->labeltype(FL_SYMBOL_LABEL); data = new user_data_plus; data->p = view; data->value = 3; obj->callback(lrdu_button_callback, data); /* noms + sequences */ Fl_Window *viewer; if(double_buffer) viewer = (Fl_Window *)new Fl_Double_Window( x+25-3, y, w - 25 - 1 + 6, h - 30 + 6); else viewer = new Fl_Window(x+25, y+3, w - 25 - 1, h - 30); viewer->box(FL_DOWN_BOX); viewer->resizable(viewer); view->double_buffer = double_buffer; view->DNA_obj = (Fl_Widget*)new DNA_obj(3, 3, w - 25 - 1, h - 30, view); view->DNA_obj->labelfont(FL_COURIER_BOLD); viewer->end(); dna_group->end(); Fl_Box *resizable_box = new Fl_Box(x + x_pos, y + scroll_w + 2, w - x_pos - scroll_w - 2 - DELTA_G, h - 3*scroll_w - 12); dna_group->add_resizable(*resizable_box); resizable_box->hide(); return dna_group; } SEA_VIEW *create_the_form(int double_buffer) { Fl_Group *dna_group; Fl_Window *my_form; Fl_Widget *obj, *bouton_search, *champ_search, *bouton_goto, *champ_goto, *bouton_help; int black_and_white, inverted; SEA_VIEW *view; user_data_plus *data; int labelSize = 12; int borderWidth = 2; int i, w_w, w_h, back_color, region_back_color, defaultformat; char *win_size, *save_format; static int first = TRUE; static int dnacolors[] = { FL_WHITE, FL_RED, FL_GREEN, FL_YELLOW, FL_BLUE }; static int numb_dnacolors = sizeof(dnacolors) / sizeof(int); static char *customdnacolors; static int *protcolors; static int *codoncolors = NULL; static char **possible_formats; if(first) { first = FALSE; //DNA colors customdnacolors = get_res_value("dnacolors", ""); prep_custom_colors(dnacolors, customdnacolors, numb_dnacolors); //protein colors static char stdcolorgroups[50], altcolorgroups[50], customprotcolors[300]; strcpy(stdcolorgroups, get_res_value("stdcolorgroups", def_stdcolorgroups)); strcpy(altcolorgroups, get_res_value("altcolorgroups", "")); strcpy(customprotcolors, get_res_value("protcolors", "")); protcolors = (int *)malloc(max_protcolors * sizeof(int)); def_protcolors = (int *)malloc(max_protcolors * sizeof(int)); for(i=0; i= nbr_formats ) defaultformat = NEXUS_FORMAT; else defaultformat = i; #ifdef MICRO black_and_white = FALSE; #else black_and_white = (fl_xpixel(FL_BLACK) == fl_xpixel(FL_RED)); #endif if (black_and_white) inverted = FALSE; else inverted = bool_res_value("inverted", TRUE); #ifdef WIN32 back_color = FL_DARK1; region_back_color = 43; #else back_color = FL_GRAY; region_back_color = FL_DARK2; #endif back_color = int_res_value("background", back_color); region_back_color = int_res_value("sites_background", region_back_color); win_size = get_res_value("window", "790x500"); sscanf(win_size, "%dx%d", &w_w, &w_h); my_form = new Fl_Window( FL_min(w_w, Fl::w()), FL_min(w_h, Fl::h()-22) ); my_form->xclass(SEAVIEW_WINDOW); #ifdef MICRO int w_x = (Fl::w() - my_form->w())/2; int w_y = (Fl::h() - my_form->h())/2; {static int count = 0; w_x += count * 30; w_y += (count++) * 30; count = count % 5; } my_form->position(w_x, w_y); #endif my_form->color(FL_LIGHT1); my_form->label(progname); my_form->box(FL_FLAT_BOX); view = (SEA_VIEW *)calloc(1, sizeof(SEA_VIEW)); if(view == NULL) out_of_memory(); Fl_Pack *menus = new Fl_Pack(1,5,10,25); /* groupe fixe des menus */ menus->type(FL_HORIZONTAL); menus->spacing(2); #ifdef MICRO const int mbw = 415; #else const int mbw = 438; #endif Fl_Menu_Bar *menubar = new Fl_Menu_Bar(0,0, mbw, 30); menubar->user_data(view); menubar->box(FL_UP_BOX); view->menubar = menubar; /* menu File */ static const Fl_Menu_Item fileitems_static[] = { {"Open", FL_COMMAND | 'o',file_menu_callback, 0, FL_MENU_DIVIDER}, {"Open Mase", 0,file_menu_callback, 0, 0}, {"Open Phylip", 0,file_menu_callback, 0, 0}, {"Open Clustal", 0,file_menu_callback, 0, 0}, {"Open MSF", 0,file_menu_callback, 0, 0}, {"Open Fasta", 0,file_menu_callback, 0, 0}, {"Open NEXUS", 0,file_menu_callback, 0, FL_MENU_DIVIDER}, {"Import from DBs", 0,file_menu_callback, 0, FL_MENU_DIVIDER}, {"Save", FL_COMMAND | 's',file_menu_callback, 0, FL_MENU_INACTIVE}, {"Save as...", 0,file_menu_callback, 0, FL_MENU_INACTIVE}, {"Save selection", 0,file_menu_callback, 0, FL_MENU_INACTIVE}, {"Save prot alignmt", 0,file_menu_callback, 0, FL_MENU_INACTIVE}, {"Save bootstrap replicates", 0,file_menu_callback, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER}, #if !defined(__APPLE__) {"Prepare "PDF_OR_PS"", 0, file_menu_callback, 0, 0}, {""PDF_OR_PS" options...", 0, file_menu_callback, 0, FL_MENU_DIVIDER}, #else {"Prepare "PDF_OR_PS"", 0, file_menu_callback, 0, FL_MENU_DIVIDER}, #endif {"Concatenate", 0,file_menu_callback, 0, FL_MENU_DIVIDER}, {"New window", FL_COMMAND | 'n', file_menu_callback, 0, 0}, {"Close window", FL_COMMAND | 'w', file_menu_callback, 0, 0}, #if ! defined( __APPLE__) {"Quit", FL_COMMAND | 'q', file_menu_callback, 0, 0 }, #endif {0} }; Fl_Menu_Item *fileitems = new Fl_Menu_Item[sizeof(fileitems_static)/sizeof(Fl_Menu_Item)]; memcpy(fileitems, fileitems_static, sizeof(fileitems_static)); menubar->add("File", 0, 0, fileitems, FL_SUBMENU_POINTER); view->menu_file = fileitems; // to delete[] at window close /* menu Edit */ static const Fl_Menu_Item edititems_static [] = { {"Copy selected seqs", FL_COMMAND | 'c', edit_menu_callback, 0, FL_MENU_INACTIVE}, {"Paste alignment data", FL_COMMAND | 'v', edit_menu_callback, 0, 0}, {"Select All", FL_COMMAND | 'a', edit_menu_callback, 0, 0}, {"Rename sequence", 0, edit_menu_callback, 0, 0}, {"Edit comments", 0, edit_menu_callback, 0, 0}, {"Edit sequence", 0, edit_menu_callback, 0, 0}, {"Delete sequence(s)", 0, edit_menu_callback, 0, 0}, {"Create sequence", 0, edit_menu_callback, 0, 0}, {"Load sequence", 0, edit_menu_callback, 0, 0}, {"Duplicate sequence", 0, edit_menu_callback, 0, 0}, {"Complement sequence", 0, edit_menu_callback, 0, 0}, {"Reverse sequence", 0, edit_menu_callback, 0, 0}, {"Exchange Us and Ts", 0, edit_menu_callback, 0, 0}, {"Dot plot", 0, edit_menu_callback, 0, 0}, {"Consensus sequence", 0, edit_menu_callback, 0, 0}, {"Del. gap-only sites", 0, edit_menu_callback, 0, 0}, {"Set genetic code", 0, edit_menu_callback, 0, 0}, {0} }; Fl_Menu_Item *edititems = new Fl_Menu_Item[sizeof(edititems_static)/sizeof(Fl_Menu_Item)]; memcpy(edititems, edititems_static, sizeof(edititems_static)); menubar->add("Edit", 0, 0, edititems, FL_SUBMENU_POINTER); view->menu_edit = edititems; // to delete[] at window close /* menu align */ cre_align_menu(view); /* menu Props */ view->inverted_colors = inverted; view->consensus_threshold = 60; create_props_menu(view, curr_color_choice, view->inverted_colors, black_and_white, defaultfontsize); /* menu regions */ static const Fl_Menu_Item siteitems_static[] = { {"Create set", 0, regions_menu_callback, 0, FL_MENU_INACTIVE}, {"Duplicate set", 0, regions_menu_callback, 0,FL_MENU_INACTIVE}, {"Hide set", 0, regions_menu_callback, 0, FL_MENU_INACTIVE}, {"Delete set", 0, regions_menu_callback, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER}, }; view->menu_sites = new vlength_menu(view->menubar, "Sites", siteitems_static, 4); /* menu species */ static const Fl_Menu_Item speciesitems_static[] = { {"Create group", 0, species_menu_callback, 0, FL_MENU_INACTIVE}, {"Delete group", 0, species_menu_callback, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER}, }; view->menu_species = new vlength_menu(view->menubar, "Species", speciesitems_static, 2); /* menu footers */ const static Fl_Menu_Item footeritems_static[] = { {"Show footers", 0, footers_menu_callback, NULL, FL_MENU_INACTIVE}, {"Create footer", 0, footers_menu_callback, NULL, 0}, {"Delete footer", 0, footers_menu_callback, NULL, FL_MENU_INACTIVE}, {0} }; Fl_Menu_Item *footeritems = new Fl_Menu_Item[4]; memcpy(footeritems, footeritems_static, sizeof(footeritems_static)); menubar->add("Footers", 0, 0, footeritems, FL_SUBMENU_POINTER); view->menu_footers = footeritems; /* menu trees */ const static Fl_Menu_Item treeitems_static[] = { {"Parsimony", 0, trees_callback, 0, 0}, {"Distance methods", 0, trees_callback, 0, 0}, {"PhyML", 0, trees_callback, 0, FL_MENU_DIVIDER}, {"Import tree", 0, trees_callback, 0, 0}, {"New tree window", 0, trees_callback, 0, FL_MENU_DIVIDER}, }; view->menu_trees = new vlength_menu(view->menubar, "Trees", treeitems_static, 5); #define calc_width(nom) \ (fl_font(FL_HELVETICA, labelSize), (int)fl_width(nom) + 4 * borderWidth) #define add_button(nom) new Fl_Button(0,0,calc_width(nom),25,nom) /* bouton search + champ Search */ bouton_search = obj = add_button("Search:"); obj->labelsize(labelSize); data = new user_data_plus; data->value = 0; obj->callback(search_callback, data); champ_search = obj = (Fl_Widget*)new Fl_Input(0,0, 80, 25, ""); ((Fl_Input*)obj)->type(FL_NORMAL_INPUT); ((Fl_Input*)obj)->when(FL_WHEN_ENTER_KEY); data = new user_data_plus; data->value = 1; champ_search->callback(search_callback, data); data = (user_data_plus *)bouton_search->user_data(); data->p = champ_search; /* bouton + champ Goto */ bouton_goto = obj = add_button("Goto:"); obj->labelsize(labelSize); data = new user_data_plus; data->value = 0; obj->callback(goto_callback, data); champ_goto = obj = (Fl_Widget*)new Fl_Input(0, 0, 80, 25, ""); ((Fl_Input*)obj)->type(FL_NORMAL_INPUT); data = new user_data_plus; data->value = 1; champ_goto->callback(goto_callback, data); data = (user_data_plus *)bouton_goto->user_data(); data->p = champ_goto; ((Fl_Input*)obj)->when(FL_WHEN_ENTER_KEY); /* bouton help */ bouton_help = add_button("Help"); bouton_help->labelsize(labelSize); bouton_help->callback(help_callback); #undef add_button #undef calc_width menus->end(); menus->resizable(NULL); /* tout le groupe scroller */ dna_group = create_dna_scroller(view, 0, 35, my_form->w() - 5, my_form->h() - 35, double_buffer); my_form->resizable( dna_group ); my_form->end(); my_form->callback(mainwin_close_callback, view); /* initialisation independantes des sequences */ static char movekeys[5]; strcpy(movekeys, get_res_value("movekeys", MOVEKEYS_DEFAULT)); view->movekeys = movekeys; data = (user_data_plus *)champ_search->user_data(); data->p = view; data = (user_data_plus *)champ_goto->user_data(); data->p = view; view->format_for_save = (known_format)defaultformat; /* default format for saving */ view->tot_seqs = 0; view->first_seq = 1; view->tot_sites = 1; view->numb_gc = 1; view->line_height = 1; view->char_width = 1; view->draw_names = -1; view->mod_seq = 0; view->mod_comment_line = 0; view->consensus_allowgaps = FALSE; view->consensus_allowiupac = FALSE; view->dnawin = my_form; view->max_seq_length = 0; mod_multipl(view, 0); view->spaces_in_fasta_names = bool_res_value("spacesinfastanames", FALSE); if ( ! black_and_white) { /* couleurs du fond pour seqs */ view->DNA_obj->color(back_color, region_back_color); view->region_color = FL_WHITE; if(view->inverted_colors) { view->DNA_obj->labelfont( FL_COURIER); } view->allow_lower = bool_res_value("lowercase", 0); } else { /* the Black and White case */ numb_dnacolors = numb_stdprotcolors = numb_altprotcolors = 1; dnacolors[0] = FL_BLACK; /* couleur du fond pour seqs */ view->DNA_obj->color(FL_WHITE, FL_WHITE); view->region_color = FL_BLACK; view->numb_gc = 1; view->curr_colors = dnacolors; view->allow_lower = TRUE; } view->DNA_obj->parent()->color( view->DNA_obj->color() ); /* taille par defaut des lettres des sequences */ view->DNA_obj->labelsize(defaultfontsize); view->dnacolors = dnacolors; view->numb_dnacolors = numb_dnacolors; view->stdprotcolors = protcolors; view->numb_stdprotcolors = numb_stdprotcolors; view->altprotcolors = protcolors; view->numb_altprotcolors = numb_altprotcolors; view->codoncolors = codoncolors; view->namecolor = FL_BLACK; view->alt_colors = curr_color_choice; view->clustal_options = NULL; view->show_comment_lines = FALSE; view->tot_comment_lines = 0; view->phylipwidnames = int_res_value("phylipwidnames", 30); #if !(defined(__APPLE__) || defined(WIN32)) && SEAVIEW_FLTK_VERSION < 133 my_form->icon( (void*)seaview_X11_icon ); #endif my_form->show(); #ifndef MICRO my_form->hotspot(my_form); #endif #ifdef __APPLE__ add_windowmenuitem(NULL, my_form); #elif ! defined(WIN32) //for X11 only my_form->make_current(); // 3 lines so the Fl_Pack gets its true width menus->damage(FL_DAMAGE_ALL); ((Fl_Widget*)menus)->draw(); int min_w = menus->x() + menus->w() + 5; //min_w = width of the menu bar if (min_w > my_form->w()) {//make sure window is as wide as menu bar my_form->size(min_w, my_form->h()); } #endif view->DNA_obj->take_focus(); return view; } seaview/seaview.h000644 000765 000024 00000037660 12475103046 014656 0ustar00mgouystaff000000 000000 #ifndef SEAVIEW_H #define SEAVIEW_H #include #include #include #include #include #if 100*FL_MAJOR_VERSION + FL_MINOR_VERSION < 103 #error Seaview requires FLTK version 1.3.0 or higher #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif #if defined(__APPLE__) || defined(WIN32) #define MICRO #endif #ifdef NO_PDF #define PDF_OR_PS "PostScript" #define PDF_OR_PS_EXT "ps" #else #define PDF_OR_PS "PDF" #define PDF_OR_PS_EXT "pdf" #endif #define fgets(a,b,c) my_fgets(a,b,c) extern char *my_fgets(char *s, int n, FILE *f); // FL_COMMAND is the modifier for menu shortcuts (Meta on Apple and Ctrl otherwise) #ifndef FL_COMMAND #if defined(__APPLE__) #define FL_COMMAND FL_META #else #define FL_COMMAND FL_CTRL #endif #endif #ifdef WIN32 extern void my_bell(void); #define fopen(a,b) fl_fopen(a, b) #define memccpy _memccpy #elif defined __APPLE__ #else #include "FL/x.H" #endif #define FL_max(a,b) ( (a) > (b) ? (a):(b) ) #define FL_min(a,b) ( (a) < (b) ? (a):(b) ) #ifdef __APPLE__ #define PREPARE_LABEL(p) mac_fname_to_roman(p) extern void set_seaview_modified(struct _SEA_VIEW *view, int ismodified); #else #if defined(WIN32) extern const char *win32_UTF8_to_CP1252(const char *in); #define PREPARE_LABEL(p) win32_UTF8_to_CP1252(p) #else #define PREPARE_LABEL(p) p #endif #define set_seaview_modified(view, ismodif) view->modif_but_not_saved = ismodif #endif typedef struct _user_data_plus { void *p; int value; } user_data_plus; extern void fl_reset_cursor(Fl_Window *win); #define MAXLENCOM 50000 /* long max des commentaires sous mase */ #define MAX_SPECIES_SETS 50 /* nbre max de species sets */ #define MSF_WID_NAME 15 #define CLU_BLOCK_LEN 5000 /* block pour allocation mem format Clustal */ #define MAX_GAP_SITES 1000 #define MOVEKEYS_DEFAULT "][><" typedef struct _list_segments { /* one segment + pointer to its successor */ int debut, fin; struct _list_segments *next; } list_segments; typedef struct { /* one region = name + pointer to list of segments */ char *name; int hide_when_viewasprots; /* TRUE iff this region shd not be enabled in view as protein mode */ list_segments *list; } region; typedef struct _list_regions { /* region list = pointer to region + pointer to successor in list */ region *element; struct _list_regions *next; } list_regions; typedef struct { int pos; int l[2]; } gap_site; typedef enum {MASE_FORMAT, PHYLIP_FORMAT, CLUSTAL_FORMAT, MSF_FORMAT, FASTA_FORMAT, NEXUS_FORMAT } known_format; typedef enum {OPEN_ANY, OPEN_MASE, OPEN_PHYLIP, OPEN_CLUSTAL, OPEN_MSF, OPEN_FASTA, OPEN_NEXUS, ACNUC_IMPORT, SAVE, SAVE_AS, SAVE_REGIONS, SAVE_PROT_ALIGN, SAVE_BOOTSTRAPS, PRINTOUT, #if !defined(__APPLE__) PDFOPTIONS, #endif CONCATENATE, NEW_WINDOW, CLOSE_WINDOW,QUIT } file_menu_choice; typedef enum {NO_ALT_COLORS, USING_STANDARD_COLORS, USING_ALT_COLORS} color_choice; typedef enum {COPY_SEQS, PASTE_SEQS, SELECT_ALL, RENAME_SEQ, EDIT_COMMENTS, EDIT_SEQ, DELETE_SEQ, CREATE_SEQ, LOAD_SEQ, DUPLICATE_SEQ, COMPLEMENT_SEQ, REVERSE_SEQ, EXCHANGE_UT, DOT_PLOT, CONSENSUS_SEQ, DELETE_GAP_ONLY_SITES, SET_GCODE} edit_choice; typedef enum { ALIGN_ALL, ALIGN_SELECTED_SEQS, ALIGN_SITES, PROFILE, UNALIGN, ALIGN_OPTIONS } align_choice; typedef enum {SHOW_HIDE_FOOTERS, CREATE_FOOTER, DELETE_FOOTER } footers_menu_choice; typedef enum {PDF_COLOR, PDF_BW, TEXT_ONLY, SVG} pdf_kind; class vlength_menu // an FL_SUBMENU_POINTER-attached variable-length series of Fl_Menu_Item's { int offset; // # of fixed items int vlen; // # of variable items Fl_Menu_Item *items; // array of fixed + variable menu items Fl_Menu_ *menu_; // menu of which this is a submenu int rank; // rank of menu item to which this is a submenu int val; // rank (from 1) of currently selected variable item public: vlength_menu(Fl_Menu_ *m, const char *name, const Fl_Menu_Item *init, int clength); int vlength() {return vlen;} // lenth of variable part int value() { return val; } // 0 if unset, >=1 if one if set void value(int v); // 0 to clear, >=1 to set one Fl_Menu_Item *get_menu() {return items;} // fixed + variable parts void add(const char *txt, Fl_Callback *cb, void *data, int flags); // add at end of variable part Fl_Menu_Item* vitem(int r) { return items + offset + r; } // one of the variable items Fl_Menu_Item* bar_item() { return (Fl_Menu_Item*)menu_->menu() + rank; } void remove(int rank); // remove variable item of rank (from 0) Fl_Menu_Item* find_item(const char*txt); void vclear(); // remove all the variable part ~vlength_menu(); }; #define TREE_WINDOW "Tree" #define SEAVIEW_WINDOW "Seaview" typedef struct _SEA_VIEW { Fl_Widget *DNA_obj; /* free object for names + seqs */ Fl_Scrollbar *horsli; /* horizontal scrollbar */ Fl_Scrollbar *vertsli; /* vertical scrollbar */ Fl_Widget *right_screen_move, *left_screen_move, *up_screen_move, *down_screen_move; /* 4 big jump arrows */ Fl_Widget *multipl; /* box displaying the multiplier value */ Fl_Menu_Bar *menubar; const Fl_Menu_Item *menu_file; /* menu items of file operations */ const Fl_Menu_Item *menu_edit; /* menu items of edit operations */ const Fl_Menu_Item *menu_align; /* menu of align operations */ const Fl_Menu_Item *menu_props; /* menu of properties */ vlength_menu *menu_sites; /* menu of site operations */ vlength_menu *menu_species; /* menu of species */ const Fl_Menu_Item *menu_footers; /* menu of footers */ vlength_menu *menu_trees; /* menu of trees */ Fl_Widget *bouton_reference; /* bouton_reference */ char **sequence; /* array of sequences */ char **comments; /* array of sequence comments */ char *header; /* header of mase file */ char **col_rank; /* array of color ranks of sequence sites */ char **alt_col_rank; /* alternate array of color ranks of sequence sites for by reference */ char **seqname; /* array of sequence names */ char *masename; /* mase file name */ int protein; /* TRUE iff protein data */ known_format format_for_save; /* what file format used when saving */ int wid_names; /* width of largest sequence name */ int first_seq, first_site; /* first seq and site currently displayed */ int tot_seqs; /* total number of sequences in memory */ int seq_length; /* current length of longest sequence */ int max_seq_length; /*max length allowed for longest sequence to grow */ int *each_length; /* array of each individual sequence length */ int tot_sites, tot_lines; /* sites and lines fitting in DNA_obj */ int x_name, y_name, x_seq, y_seq; /* top left to start writing names and sequences */ int draw_names; /*controle ecriture noms 0: pas ecrits; -1: tous ecrits puis aussi les seqs; -2: tous ecrits mais pas les seqs; >=1: 1 seul ecrit et pas de seq ni de curseur ecrit*/ int mod_seq; /* -1: seqs selectionnees; 0: normal; >= 1: 1 seul seq ecrite */ int mod_cursor; /* FALSE: cursor ancien ignore; TRUE: ancien efface */ int char_width, line_height; /* taille en pixels des caracteres */ int cursor_seq, cursor_site; /* position courante du curseur */ int old_cursor_seq, old_cursor_site; /* position precedente du curseur*/ int tot_sel_seqs; /* nbre courant de seqs selectionnees */ int *sel_seqs; /* tableau des seqs selectionnees: T/F pour chacune */ int *curr_colors; /*tableau des couleurs pour chaque valeur col_rank */ int inverted_colors; /* TRUE iff use black letters on colored square */ int namecolor; /* couleur utilisee pour les noms */ int numb_gc; /* 1 en N&B, >1 en couleurs */ int *dnacolors; /* tableau des couleurs pour DNA/RNA */ int numb_dnacolors; /* nbre de couleurs pour DNA/RNA */ int *stdprotcolors; /*tableau des couleurs standard pour prots*/ int numb_stdprotcolors; /* nbre de couleurs standard pour prots */ int *altprotcolors;/*tableau des couleurs alternatives pour prots*/ int numb_altprotcolors; /*nbre de couleurs alternatives pour prots*/ int *codoncolors; /*tableau des couleurs standard pour codons*/ color_choice alt_colors; /* current aa color use */ list_regions *regions; /* list of known regions */ region *active_region; /* active region (NULL when none) */ char *region_line; /* region line (of length region_length) */ int region_color; /* color used to display region line */ int region_length; /* length of region_line (==seq_length) */ int mod_region_line; /* TRUE region line changed=>redraw only it */ int numb_species_sets; /* number of known species sets */ int *list_species_sets[MAX_SPECIES_SETS];/*list of known species sets*/ char *name_species_sets[MAX_SPECIES_SETS];/*names of species sets*/ int allow_seq_edit; /* when TRUE can type sequence data in */ void *viewasprots; /* !=NULL when DNA displayed as proteins */ int hjkl; /* when TRUE, keys hjklHJKL produce TCGA */ int modif_but_not_saved; /* set/unset through function set_seaview_modified */ Fl_Window *dnawin; /* full seaview window */ int double_buffer; /* true iff DNA_obj is double buffered */ int alignment_algorithm; /* rank (from 0) of chosen alignment algorithm */ int count_msa_algos; /* number of usable alignment algorithms */ char *clustal_options; /* options for clustalw if != NULL */ int consensus_threshold; /* min threshold (%) for residue in consensus*/ int consensus_allowgaps; /* TRUE iff gaps count as residue for consensus*/ int consensus_allowiupac; /* TRUE iff IUPAC codes are used in consensus DNA sequences */ int tot_comment_lines; /* number of comment lines */ char **comment_line; /* array of comment lines */ char **comment_name; /* array of comment names */ int *comment_length; /* array of comment lengths */ int show_comment_lines; /* TRUE when displayed */ int pos_first_comment_line; /* rank on screen of this line */ int mod_comment_line; /* 0: normal, >=1 celle-ci ecrite */ int active_comment_line; /* 0: none, >=1 target of keyboard */ int cursor_in_comment; /* TRUE when cursor is in comments not in seqs */ int old_cursor_in_comment; /*previous place of cursor seq vs. comments*/ char *movekeys; /* default ][>< keys to move seq right or left */ int allow_lower; /* TRUE iff lowercase displayed in seqs */ int phylipwidnames; /* max name length when writing PHYLIP files */ int spaces_in_fasta_names; //TRUE iff spaces dont mark end of seq name n FASTA format int tot_trees; /* number of trees in next array */ char **trees; /* array of trees */ } SEA_VIEW; typedef struct _props_menu_parts { int colors, viewasprots, inverted, edit, reference, keys, consensusopt, slow_fast, allow_lower; int usingcodoncolors; } props_menu_parts; extern void out_of_memory(void); extern "C" void majuscules(char *s); extern void init_dna_scroller(SEA_VIEW *view, int totseqs, const char *masename, int protein, char *header); extern const char *extract_filename(const char *fname); extern const char *extract_dirname(const char *pathname); extern void draw_region_line(Fl_Widget *ob, SEA_VIEW *view); extern void props_button_callback(Fl_Widget *ob, long mainpop); extern void regions_menu_callback(Fl_Widget *ob, void *extra); extern void species_menu_callback(Fl_Widget *ob, void *extra); extern void footers_menu_callback(Fl_Widget *ob, void *extra); extern int suppr_segment(region *maregion, int site, char *line); extern int begin_change_segment(SEA_VIEW *view, int new_site); extern int continue_change_segment(SEA_VIEW *view, int new_site); extern void end_change_segment(SEA_VIEW *view); extern int extend_segment_at_left(SEA_VIEW *view, int new_site); extern void delete_region_part(SEA_VIEW *view, int numsite, int total); extern void insert_region_part(SEA_VIEW *view, int numsite, int total); extern void delete_region(SEA_VIEW *view, int rang); extern list_regions *parse_regions_from_header(char *header); extern int parse_species_sets_from_header(char *header, int **list_species_sets, char **name_species_sets, int totseqs); extern void set_tot_lines(SEA_VIEW *view, int new_val); extern int read_mase_seqs_header(const char *, char ***pseq,char ***pseqname, char ***pcomments, char **pheader, char **err_message); extern int read_fasta_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message, int spaces_in_names); extern int read_phylip_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **); extern int read_clustal_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); extern int read_msf_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); extern int read_nexus_align(char *fname, char ***pseqs, char ***pseqnames, char ***pcomments, char **pheader, char **err_message, list_regions **charsets, int *pnum_species_sets, int ***list_species_sets, char ***name_species_sets, int *ptot_comment_lines, char ***comment_name, char ***comment_line, int **comment_length, int *protein, SEA_VIEW *view); extern char *save_alignment_or_region(const char *fname, char **seq, char **comments, char *header, char **seqname, int totseqs, int *eachlength, list_regions *regions, region *region_used, known_format format, int numb_species_sets, int **list_species_sets, char **name_species_sets, int *sel_seqs, int tot_sel_seqs, int protein, int tot_comment_lines, char **comment_name, char **comment_line, int phylipwidnames, int tot_trees, char **trees, const Fl_Menu_Item *menu_tree_items, int spaces_in_fasta_names); extern Fl_Window *load_alignment_file(SEA_VIEW *view, char *filename, const char *message, known_format file_format, int doing_dnd); extern int is_a_protein_seq(char *seq); extern char *get_full_path(const char *fname); extern void draw_region_background(SEA_VIEW *view, int f_seq0, int l_seq0); extern void load_seq_dialog(SEA_VIEW *view); extern void edit_comments_dialog(SEA_VIEW *view); extern void edit_sequence_dialog(SEA_VIEW *view); extern int add_seq_to_align(SEA_VIEW *view, char *newname, char *newseq, int lenseq, bool no_gui = false); extern int get_color_for_base( int key ); extern int get_color_for_aa( int key ); extern char **prepcolranks(char **seq, int totseqs, int maxlen, int *eachlength, int (*calc_color_function)( int ), int numb_gc, int allow_lower); extern char complement_base(char old); extern void select_deselect_seq(SEA_VIEW *view, int new_seq, int from_tree = 0); extern void save_active_region(SEA_VIEW *view); extern void align_selected_parts(SEA_VIEW *view, align_choice my_align_choice, bool no_gui = false); extern void free_region(region *reg); extern void my_watch_cursor(Fl_Window *win); extern void update_current_seq_length(int newlength, SEA_VIEW *view); extern char *cre_consensus(SEA_VIEW *view, char *newname); extern int parse_comment_lines_from_header(char *header, char ***plines, char ***pnames, int **plengths, int *pmax_seq_length); extern int insert_char_in_comment(int key, int num, SEA_VIEW *view); extern int delete_char_in_comment(SEA_VIEW *view, int count, int comnum, int depart, int protect); extern void update_menu_footers(SEA_VIEW *view); extern int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view); extern int delete_in_all_comments(int numdels, int pos, SEA_VIEW *view); extern char* fl_file_chooser(const char* message, const char* pat, const char* fname, int); extern char *run_and_close_native_file_chooser(Fl_Native_File_Chooser *chooser, int keepalive=0); extern void trees_callback(Fl_Widget *ob, void *data); extern int save_fasta_file(const char *fname, char **seq, char **comments, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int spaces_in_names, int pad_to_max_length=FALSE); #ifdef __APPLE__ extern char *mac_fname_to_roman(const char *in); #endif #endif seaview/seaview.html000644 000765 000024 00000200323 12606676751 015375 0ustar00mgouystaff000000 000000 Seaview on-line help
Help items
File Menu Edit Menu Align Menu Props Menu Sites Menu Species Menu
Footers Menu Search Goto Trees Menu Alignment panel Tree windows
Dot plot Mase file format Program arguments Sequence coloring Miscellaneous options Customization
About seaview

Program seaview was published in:
Gouy, M. Guindon, S. & Gascuel., O. (2010) SeaView version 4 : a multiplatform graphical user interface for sequence alignment and phylogenetic tree building. Molecular Biology and Evolution 27(2):221-224.
Galtier, N., Gouy, M. & Gautier, C. (1996) SEAVIEW and PHYLO_WIN: two graphic tools for sequence alignment and molecular phylogeny. Comput. Appl. Biosci., 12:543-548.

Version 4.5.4

Binaries and full source code available from http://doua.prabi.fr/software/seaview

© 1996-2015 Manolo Gouy
Laboratoire de Biométrie et Biologie Evolutive
CNRS / Université de Lyon

Licensed under the GNU General Public Licence.

Seaview drives the Muscle, Clustal Omega, Gblocks, and PhyML programs and uses code from the PHYLIP package for parsimony. Please quote:

Seaview uses the FLTK project for its user interface.

Some seaview versions use the PDFlib Lite library for pdf output under the "Open Source Developer Exemption" of the PDFlib Lite License Agreement.


Alignment panel

Mouse Use:

  • Click on a site to position cursor (current cursor position -- sequence number, positions in alignment and in sequence -- appears at panel top center)
  • Click or drag mouse on several sequence names to select them (names will appear in black background). Alignment operations (gap insertions/deletions) will operate on all selected sequences simultaneously.
  • Click with middle mouse button or Ctrl-Click somewhere in sequence names to move selected sequences to another place in alignment.
  • Click with right mouse button or Shift-Click to deactivate the current selection.
  • Cmd-Click(Mac), Alt-Click(PC), or Meta-Click (unix) on sequence name to select from last selected sequence to here.
Active keys:
  • The 4 keyboard arrows move the cursor. Page up/down keys move it one pageful.
  • > < move the view by 50 sites to right and left (other keys can be used)
  • ] [ move the view by 5 sites to right and left (other keys can be used) see Miscellaneous options for how to use other keys for same purpose
  • - or <space> insert a gap in the cursor sequence and members of its group if any
  • <delete> or <backspace> delete a gap at left of cursor
  • + inserts a gap in all sequences but that under the cursor and members of its group if any
  • _ ("underscore") deletes a gap in all sequences but that under the cursor and members of its group if any
  • 1234567890 (digit keys) allow to compose a number (appearing under mult=number at bottom left of panel) used as a multiplier to an operation to follow (e.g., keys 4, 5, and - in sequence will insert 45 gaps)
  • ctrl/cmd+S (according to platform) saves the alignment in the current filename using its current format.
Mouse use on the site line (when there is one, white line at bottom):
  • Click mouse to select/unselect a site.
  • Drag with the mouse button an extremity of a block of sites to extend or reduce it.
  • Click with the middle mouse button or Ctrl-Click to extend the block of sites at left.
  • Click with the right mouse button or Shift-Click on a block of sites to delete it.

File Menu

Open: opens a sequence alignment file in any of the supported formats, or a Newick-formatted tree file.
Open Mase, Open Phylip, Open Clustal, Open MSF, Open Fasta, Open NEXUS: to load an alignment in one of these formats.
Formats Phylip, Clustal and Fasta use _ instead of space in names. Only the interleaved version of the Phylip format is supported. Mase and Nexus formats have the useful feature of allowing extra data beyond sequences and names (comments, accession numbers are really useful!). They can also store trees, site sets [see Sites Menu], species sets, footers, genetic code information.

Import from DBs: to import one or several sequences from various databases (EMBL, GenBank, SwissProt/UniProt) into the alignment window. Importation requires an internet connection that allows outbound access to port # 5558. See Troubleshooting Importation from Databases if you experience problems with this function. Imported sequences will be named in the alignment window either by the name of their ID or LOCUS record or by their species. Sequences can be identified by two means:
1. By name, accession number or keyword. Protein IDs, without their extension (e.g., CAA06608 from /protein_id="CAA06608.1"), are processed as keywords attached to sequences, so can also be used. Because imported sequences are named with information taken from their ID/LOCUS record, the protein ID won't be used to name the sequence.
2. By a local text file of names or accession nos (one per line, strict text file, e.g., not a .doc or .odt file).
In case 1. and for nucleotide databases, it is also possible to import sequence fragments corresponding to a specified feature key (e.g., CDS, rRNA, tRNA) and, optionally, to require a given string to be present in the feature's annotations. If no matching string is specified, only the first matching feature key is imported. CDSs are imported with their correct genetic code and reading frame. Access to a series of other databases is also possible.

Save: when active, saves the alignment in the current file (which name appears as window title). The shortcut for this operation is ctrl-S (cmd-S on Mac).

Save as...: to save the alignment under a name and a format to be chosen in the file selector appearing next. This item is unavailable when a nucleotide alignment is translated to proteins. Use "Save prot alignmt" below instead.

Save selection: only active when some sequences are selected or when a site line is displayed; allows to save in a file selected sites, or selected sequences, or selected sites of selected sequences.

Save prot alignmt: only active when a nucleotide alignment is translated to proteins; allows to save resulting protein sequences in any format.

Save bootstrap replicates: allows to store in a PHYLIP-formatted output file bootstrap replicates of the sequences of the alignment window. This command operates on selected sequences, and on selected sites if a sequence or site selection is currently active. It operates with protein sequences when a nucleotide alignment is translated to proteins. It asks for the desired output filename and number of bootstrap replicates. The "phylip names width" item of the "Props/Customize" dialog window allows to control the maximum name length used in the output file.

Prepare PDF/PostScript and PDF/PostScript options: Writes the alignment as a PDF/PostScript file with optional choices set through the "PDF/PostScript options..." menu item (or the save dialog on Mac OS):

  • font size: sets the fontsize (font is Courier)
  • block size: alignment lines may be divided in blocks (e.g., of size 10 for DNA/RNA sequences or 3 for protein coding sequences) separated by one space to ease alignment reading.
  • paper size: two paper formats can be used: A4 or LETTER
  • landscape: select to use the Landscape page layout
  • color/B&W/Text File: choose between colored alignment, or one with all black letters, or to write the alignment as a text-only file.
  • variable sites only: available only in reference mode (see Props menu), allows to output only variable sites of the alignment and their positions.

Concatenate: To add one alignment (source) to the end of another (target). Can be done "by name" (seqs with same name are concatenated) or "by rank" (seqs with same rank in alignments are concatenated). Option "add gaps" replaces names absent in either alignment by gap-only sequences ("by name" only).

New window: Opens a new, empty alignment window.

Close window: Closes the alignment window.

Quit: guess what?


Edit Menu

Copy selected seqs: only active when some sequences are selected; copies in clipboard these sequences, or only their selected sites if a site line is displayed.
Paste alignment data: To paste sequence data from the clipboard to the bottom of the current alignment window (inactive in "View as protein" mode). The clipboard can either contain sequences that were previously copied in seaview using "Copy selected seqs", or sequence data in Fasta format copied from anywhere. In the latter case, the user is asked for confirmation before adding sequences to the alignment.
Select all: Selects all sequences from the alignment.
Rename sequence: To rename the currently selected (= name in black background) sequence.
Edit comments: To see or change comments of the currently selected sequence (Comments can only be saved in mase/NEXUS formats).
Edit sequence: To edit the selected sequence, typically by pasting external data, or by opening two edit sequence windows and transferring sequence data between them. The edit window is limited to sequences of length < 32000.
Delete sequence(s): Deletes all selected sequences from the alignment.
Create sequence: Allows to create a new, empty sequence in the alignment; set "Allow seq. edition" from Props menu ON to be able to type the sequence in.
Load sequence: Allows to load a new sequence in the alignment. The sequence can be typed in or pasted from a selection made in another window. The "Sequence loading window" is limited to sequences of length < 32000.
Duplicate sequence: Duplicates the currently selected sequence with prefix D_ in its name.
Complement sequence: Creates a new sequence equal to the complementary strand of the currently selected sequence with prefix C_ in its name.
Reverse sequence: Creates a new sequence by reading 3' -> 5' the currently selected sequence and named with prefix R_
Exchange Us and Ts: Exchange bases Us and Ts in all currently selected sequences.
Dot plot: Performs a dot plot analysis of the two selected sequences.
Consensus sequence: Computes the consensus of all currently selected sequences. The consensus sequence is added to the alignment with the name "Consensus##" below all selected sequences. At any site, the consensus residue is the most frequent one if its frequency is above a threshold value. Below threshold, N or X is used. See Consensus options of menu Props for more details.
Del gap-only sites: Deletes all gap-only sites from the alignment.
Set genetic code: Allows to specify the genetic code used to translate to protein the selected sequence(s). Active only with nucleotide alignments. Genetic codes are saved if the mase or NEXUS file formats are used.


Align Menu

Align all
Align selected sequences:
Runs the chosen alignment program on all or on selected sequences. Alignment program is chosen with Alignment options of menu Align. With MSWindows and Unix, the chosen alignment program is searched in the directory of the seaview program and in directories of your PATH.
Align selected sites: Runs the chosen alignment program on the block of selected sites and the set of selected sequences. A window will ask for choosing the reference sequence: gaps present before alignment in the chosen sequence will be preserved in the new alignment.
Profile alignment: Align selected sequences against a profile, that is, a group of pre-aligned sequences.
Possible operations for making a profile alignment:

  1. select members of the profile group;
  2. do 'Create group' of menu Species;
  3. select sequences you want to align against the profile group;
  4. do 'Profile alignment' of menu Align;
  5. choose the profile group in the dialog menu;
  6. choose alignment algorithm;
  7. if using clustalo, choose between "each sequence to profile" and "profile to profile" (with "profile to profile", selected sequences are expected to be pre-aligned to each other.
  8. Uncheck "Propagate gaps to sites" if you don't want gaps created in the profile group by the profile alignment to be propagated to all your site selections (menu "Sites").

De-align selection: Remove all gaps from selected sequences.
Alignment options:
  • clustalo, muscle, ...: Allows to choose the desired alignment method.
  • Edit options: Without options, the algorithm's default parameter settings, adequate for many problems, are used. This item allows to define custom alignment parameter settings by listing a series of options (e.g., -verbose -maxiters=5 for muscle) that will be transmitted to the alignment algorithm. Options are active unless you switch them off by unchecking the check box. Thus a set of options can be memorized and turned on and off.
  • Add external method: Interfaces seaview with an external multiple sequence alignment method. Any external alignment program able to read a fasta file and output a fasta file and that can be run by a 'name + arguments' command line is usable. Select the external program from your computer or enter its name. Under MSWindows and Unix, the name is searched in seaview's directory and in all PATH directories. Under Mac OS, the name is searched in all PATH directories, and in directory <seaview-bundle>/Contents/Resources. Enter its arguments replacing the method's input and output filenames by %f.pir and %f.out, respectively. Under MSWindows, it's recommended to bracket filenames by double quotes (e.g., "%f.out"). The yellow tip message that appears when the mouse remains on the "Arguments" field gives three examples of external program interfacing. Standard output redirection to a file with > is possible.
  • Delete method: To delete currently selected alignment method. clustalo and muscle can't be deleted.

Props Menu

Fontsize: 8, 10, ..., 36: Sets the font size used to display sequences.
View as proteins: When ON, DNA sequences are displayed as translated to protein sequences. This allows to align them, and to go back to the DNA level by unselecting this item. Items Save/Save as of menu File and sequence edition are impossible when ON.
Colors:

  • DNA/RNA colors: Forces sequences to be colored as DNA/RNA in case they were erroneously recognized as protein data.
  • Protein colors: Forces sequences to be colored as proteins in case they were erroneously recognized as DNA/RNA data.
  • Alt. colors: Uses alternate coloring rules defined for protein sequences [see Sequence coloring help topic].
  • Codon colors: Each codon gets colored according to its corresponding aminoacid.
  • Inverted colors: Display residues as black letters on colored background instead of as colored letters on grey background.

Allow seq. editing: When ON, residues can be deleted/inserted. When OFF (normally), only gaps can be deleted/inserted.
by Reference: To display the alignment by reference to a particular sequence: residues identical to that of the ref. seq. are displayed as dots. Possible only when one sequence, the reference, is selected. Alignment edition is impossible while in the reference mode. When used, item "Prepare pdf" of menu "File" produces an output by reference. Combination ctrl/cmd+R is a shortcut for calling/exiting this mode.
DNA keys: Allows to use keys "hjkl" to enter DNA sequences. "Allow seq. edition" should be ON for this item to be usable. Choose in the submenu what bases will be mapped to these keys: hjkl => GATC, hjkl => TCGA, hjkl => ACGT. Also, the space bar will be mapped to base N.
Consensus options: Allows to set the threshold fraction of identical residues needed to define a residue when building a consensus sequence (the default value is 60 %). Sites where this fraction is not reached are filled with N or X (or, for DNA, with nucleotide ambiguity symbols if "Use IUPAC symbols" is on). If "allow gaps" is off, gaps are ignored to compute which residue will appear in the consensus; this option in effect treats gaps as missing information. If "allow gaps" is on, gaps are treated as another character state to compute consensus.
IUPAC nucleotide ambiguity symbols
SymbolMRWS YK VHDB
NucleotidesACAGATUGCCTUGTU ACGACTUAGTUCGTU

Allow lowercase: If set, lowercase residues will be apparent. If not set, lowercase residues in sequence files display as uppercase.
Customize: To change, possibly permanently, various display settings. See Miscellaneous options and Sequence coloring help items. Apply: applies changes in current program session. Set changes permanent: applies changes in current and future program sessions. Close: ignores changes.
Statistics: Displays base or amino acid sequence compositions, and transition and transversion counts. These statistics apply to all sequences or to selected sequences only. When two nucleotide sequences are selected, the frequency of all pairs of homologous bases is also computed. Statistics can also be saved to a user-chosen text file.
Sites Menu

Site sets allow to specify parts of a multiple alignment to be retained for further analyses (e.g., those parts of the alignment taken as reliably aligned). Retained sites are depicted as series of Xs on a special line at bottom of the alignment panel. Mouse clicks and drags on this line allow to construct/alter the set (see Mouse use on the site line).

Several sets of sites can be created and stored with the alignment if the Mase or NEXUS formats of alignment files are used. Each set has a name chosen by the user. One set of sites at most can be displayed at any time through this menu.

Item Save selection of menu "File" allows to save in an alignment file only those sites of the alignment pertaining to the currently displayed site set.

Create set: Several kinds of sets of sites are possible:

  • custom site set: should be named by the user. It is initially defined to contain all alignment sites, and can be manually modified by mouse operations on the site line at the bottom of the alignment.
  • Gblocks: the Gblocks program is run to compute a set of sites suitable for phylogenetic analysis. A dialog window presents several optional choices to control the stringency level of site selection. Further information can be found in the Gblocks online documentation. Some seaview versions don't include the Gblocks program. It can be downloaded from its web site.
  • codon position masks (not available for protein alignments).
  • variable sites.
Non-custom site sets are better used once alignment operations are completed.
Duplicate set: duplicates the current set of sites under a new name
Hide set: hides (but remembers) the current set of sites
Delete set: removes the currently displayed set of sites from list of known sets
name: shows the site line of name name. It can have been read in together with the alignment data, or previously created by "Create set".
Species Menu

Species sets can be created and stored with the alignment if the Mase or NEXUS formats of alignment files are used.

To select one or several species, click or drag on their names; they will appear in black background.

To memorize the current set of selected species, choose "Create set" from this menu. The program will ask for a name for this set.

Delete set: deletes (just from memory) the current set of species.
name: displays with black background the set of species memorized under that name.


Footers Menu

Comment lines can be created and displayed at bottom of the screen. These lines can contain any text and the program will maintain the vertical alignment between this text and sequences. This text can be saved using the mase or NEXUS file formats only.

To edit this text, click on the line name, position the cursor, and type text.
Click again on the line name to stop editing this text.

Show / Hide footers: To show / hide all footer lines
Create footer: To create a new footer line
Delete footer: To delete the currently selected footer line


Search

Type a string in box at right and strike <return> key or push button to position the cursor in the next occurence of this string from its current place.

Push button to position the cursor at next occurence of the current search string.

Sequence gaps are ignored by the search procedure.


Goto

Moves the cursor to desired position or sequence:

  • position: type a number in box at right and hit <return> key or push button to position the cursor at that position of the alignment.
  • sequence: type a (fragment of) sequence name in box at right and hit <return> key or push button to position the cursor in that sequence. Case is not significant.

Trees Menu

This menu allows to compute, draw, save, and import DNA or protein phylogenetic trees.
Protein-coding DNA sequences displayed as protein sequences (item "View as proteins" of menu Props) are treated as protein sequences.
All tree computations apply to selected sequences (or all if none) and selected sites (or complete alignment if none).
All trees, sequence, and site selections can be saved together with the alignment data in either the mase or Nexus formats.

Parsimony:
Computes parsimony trees using PHYLIP's v3.696 dnapars or protpars algorithms and returns the consensus of all most parsimonious trees found.

  • The DNA-level algorithm (dnapars) computes most parsimonious trees with branch lengths equal to the average of the number of reconstructed changes of state over all sites and over all possible most parsimonious placements of the changes of state among branches. A branch exists only if some site has a most parsimonious reconstruction that would involve change in that branch. Dnapars can thus return a multifurcated tree even if a single most parsimonious tree is found. When several most parsimonious trees are found, their consensus tree is computed, and its branch lengths are recomputed, thus they can differ from their values in any most parsimonious tree.
  • The protein-level algorithm (protpars) returns the consensus of all most parsimonious trees found without branch lengths.

Randomize seq. order: to repeat n times the search for shortest trees with randomized sequence order.
Ignore all gap sites: if on, all gap-containing sites are excluded from analysis.
Gaps as unknown states: if on, gap-containing sites are coded as unknown states so don't introduce parsimony steps; if off, they are treated as an additional character state. The interface forbids the meaningless configuration that would ignore gaps and treat them as unknown states.
More/Less thorough tree search/Rearrange on best tree: (DNA only) these 3 options control, in decreasing order, how, and how much, rearrangement is done on the tied trees to find shorter trees.
  • More thorough: rearrange on all parts of all currently found equally best trees to find better ones.
  • Less thorough: collapse all branches that have no evidence that there is any change on that branch before attempting rearrangements.
  • Rearrange on best tree: only the first of the tied best trees is used for rearrangement.
It may be necessary to select the second or third option when the data set contains many (near-)identical sequences.
Equally best trees retained (DNA only): maximum number of equally best trees retained in search.
% level for consensus tree building: Parsimony often identifies several most parsimonious trees, and seaview computes their consensus and displays it. The default 100% consensus level corresponds to the strict consensus rule. The 50% level corresponds to the majority rule consensus. Intermediate values v include in the consensus tree all species groups present in at least a fraction v of the most parsimonious trees.
Bootstrap: performs bootstrap evaluation of clade statistical support (can be interrupted). Furthermore, if "Show bootstrap trees" is checked, individual bootstrap trees will appear in a second tree window, in addition to the main parsimony tree window. Each bootstrap tree has a weight that appears at the top left of the tree window when this tree is displayed. The weights of all equally parsimonious trees add up to 1 for each bootstrap replicate.
User tree: computes the number of steps of a user-given tree taken from those in the "Trees" menu. Such trees can have been previously computed or imported from an external source in Newick format.

Distance methods:
Computes NJ or BioNJ trees on a variety of pairwise phylogenetic distances.
NJ/BioNJ: to select the tree-building algorithm
Save to file: does not compute any tree but saves sequence pairwise distances to a local file.
Distance: select one among a variety of evolutionary distances: J-C: Jukes & Cantor (1969); K2P: Kimura (1980) JME 16:111; HKY: Rzhetsky & Nei (1995) MBE 12:131; LogDet: Lake (1994) PNAS 91:1455; Lockhart et al. (1994) MBE 11:605; Ka/Ks: Li (1993) JME 36:96.
ignore all gap sites: if on, all gap-containing sites are excluded from analysis; if off, not all sequence pairs use the same set of sites for computation of distances.
Bootstrap: performs bootstrap evaluation of clade statistical support (can be interrupted). Furthermore, if "Show bootstrap trees" is checked, individual bootstrap trees will appear in a second tree window, in addition to the main distance tree window.
User tree: computes least squares branch lengths for selected user tree topology.

PhyML:
Computes trees using PhyML v3.0 as an external program.
If needed, PhyML can be downloaded from its web site
Under Unix, file $HOME/.seaviewrc may contain the name of the PhyML executable used by seaview.
Please quote: Guindon S., Dufayard J.F., Lefort V., Anisimova M., Hordijk W., Gascuel O. (2010) New Algorithms and Methods to Estimate Maximum-Likelihood Phylogenies: Assessing the Performance of PhyML 3.0. Systematic Biology 59(3):307-321.
Model: select one among a variety of evolutionary models.
Branch support: can be omitted (None) or estimated either by the approximate likelihood ratio test approach (aLRT) or by bootstrap. In the last case, if "Show bootstrap trees" is checked, individual bootstrap trees will appear in a second tree window, in addition to the main PhyML tree window.
Nucleotide/Amino acid equilibrium frequencies: Residue frequencies can be estimated by counting their frequencies in the sequence alignment ("Empirical" option). Alternatively, they can be optimized by maximum likelihood ("Optimized" option for DNA data) or fixed to a set of model-given values ("Model-given" option for protein data).
Ts/Tv ratio: (applies to some nucleotide models only) optimize or fix a priori this ratio.
Invariable sites: ignore (None), optimize, or set to an a priori value (Fixed) the fraction of invariable sites.
Across site rate variation: ignore (None), optimize, or set to an a priori value (Fixed) the alpha parameter of the gamma distribution of rates across sites. If not ignored, the # of rate categories must also be set.
Tree searching operations: NNI (nearest-neighbor interchange), SPR (subtree pruning and regrafting) and 'best of NNI & SPR' are options improving the search for the most likely tree but requiring increasing computation time.
Starting tree: controls the tree used to start tree-space search; can be BioNJ, a user-given tree from the trees menu, or a number of random trees (possible only with SPR). Turn off "Optimize tree topology" to compute the likelihood of a user-given tree.
Quiet: If ON, no indication of the computation progression will appear. Turning this ON also ensures that runs requiring large memory don't block with the "WARNING: this analysis requires at least ## Mo of memory space." message.

Import tree: to import an external, Newick-formatted tree.

New tree window: opens a new, empty tree window.


Tree windows
Plots/saves/prints/copies phylogenetic trees that can be rooted or unrooted, with or without branch lengths, binary or multibranched, with or without branch support values.
A tree window can contain several trees. In that case, left and right arrows at top right of the window allow to circulate around them. Multiple-tree windows can occur after these operations:
  • open a Newick file containing several trees consecutively;
  • paste to an empty tree window a clipboard containing several Newick strings consecutively;
  • a parsimony analysis yielded several equally parsimonious trees: the tree window contains first their consensus, and then each single equally parsimonious tree.

File menu


Save to Trees menu: to save in menu Trees of alignment window a previously computed tree.
Remove from Trees menu: removes a tree from menu Trees of alignment window.
Save rooted (unrooted) (sub)tree: saves displayed tree or subtree to a local file as rooted or unrooted form.
Save all trees: writes all trees attached to the tree window to a single file (active only when several trees are attached to the tree window and arrows at window top-right allow to circulate around them).
Save patristic distances: writes in a file the patristic distances for all pairs of tree leaves (= sum of the lengths of branches connecting the two leaves). Computes also the tree length equal to the sum of all tree branch lengths. Computations are restricted to the subtree if the tree display is currently limited to a subtree. For trees without branch lengths, the computation is run as if all branch lengths were equal to 1, except the two branches that stem from the root of length taken as equal to 0.5.
Print: prints displayed tree (see also 'Page count' below).
Save as PDF/PostScript: saves displayed tree to PDF (or PostScript) local file (see Page Count).
Save as SVG: saves displayed (sub)tree to a scalable vector graphics (SVG) local file suitable to be edited using appropriate programs (e.g., Inkscape).
A4 - Letter: controls the page format for PDF/PostScript operations.
Page count>#: controls the # of pages used for print/PDF/PostScript operations.
Reorder following tree: reorders sequences of alignment window as in displayed tree.
Select in alignment: selects in alignment window all members of subtree (active when only a subtree is plotted).
Open tree or alignment: opens a new tree (Newick format; the file can contain several trees consecutively) or alignment file (any format).
New window: opens a new, empty tree window where a Newick-formatted tree can be pasted from clipboard.
Close window: closes the displayed tree that gets lost unless it had been saved to Trees menu.

Edit menu


Copy: (Mac OS and MSWindows only) copies tree plot to clipboard for pasting to external programs.
Paste tree: (only if window is empty) to paste a Newick-formatted tree contained in the clipboard. The clipboard may contain several trees.
Find: finds sequence names in tree that contain a user-given string, and red-colors them in tree display (case insensitive).
Again: repeats 'Find' operation with same matching rules.
Edit tree header: to change the tree's brief descriptive header line.
Branch support threshold: only branch support values above given threshold become displayed.
Root at tree center: roots the tree in the middle of the largest path between two leaves (when branch lengths exist).
Get or Set window size: to control the size of the current tree window.
Edit tree shape: to alter tree shape by moving or deleting sequence groups. A new window displays the tree without branch lengths. Clicking on a square selects a sequence group that appears in red. It can be moved to another branch of tree by clicking on another square, or deleted ("Delete group" button). "Select group" button allows to select another group for further move or delete operations. Complete edits by pressing "End edit" button, and, possibly, "File/Save to Trees menu".

Font menu: to control font, style and size of all text in tree display.

Br lengths: toggles display of branch length values next to each branch (very small values are not displayed).
Br support: toggles display of support values (typically, bootstrap, posterior probabilities, or aLRT) next to branches.

squared/circular/cladogram: toggles display between squared plot convenient for rooted trees, circular plot convenient for unrooted trees, and cladogram which displays trees with all branch lengths a multiple of a unit length and all leaves aligned at right. Cladogram is not available for branch length-free trees because it is equivalent to the squared display for them.

Full: normal, full tree display.
Swap: to swap branches around a node. Click on relevant square that appears.
Re-root: to set tree outgroup. Click on relevant square that appears.
Select: to select/unselect alignment sequences from a tree. Click in the tree on a square at a sequence name or at a node to select/unselect it in the corresponding alignment window. Conversely, click on sequence names in the alignment window to select/unselect them in the tree. Selected sequences appear with a red square in the tree, and with their name on black background in the alignment.
Subtree: to limit display to a subtree. Click on relevant square that appears.
Subtree up: when a subtree is being displayed, adds one more node towards tree root to display.

Zoom: vertical zoom for tree display; one or two scrollers appear. The tree can be moved by the scrollers, the mouse wheel, or by clicking on and dragging the plot.


Dot Plot
Performs a "dot plot" analysis of two sequences

Enter desired values for the window size and # of matches/window, and click on button "Compute", the dot plot will appear.

Click in the dot plot, the corresponding sequence regions appear in the alignment panel above the dot plot. Use "Magnify" to take a close look.
Click on arrows at left to move the hit point by one residue in either of six directions.
Move the slider below the alignment panel to control the number of displayedresidues.

Fit to window, Reduce, Magnify: perform zoom in and out operations
Write PDF/ps: saves the dot plot to a PDF or PostScript file.
Close: closes the dot plot window

To perform a dot plot-guided alignment

Click on a diagonal representing two sequence parts to be aligned, then click on button "align". Repeat this for each sequence parts you want to be aligned to each other.
To transfer into the multiple alignment the result of these operations, click on button "Record alignment".
Most often, one of the two compared sequences is already aligned to other sequences of the multiple alignment, while the other one is not. Choose which of the two sequences is already aligned by clicking on the arrow next to "Ref. sequence".
Mase file format
Mase files follow the following format:

Zero or more header lines each beginning with ;;
Next, for each sequence in the alignment:
One or more comment lines each beginning with ;
Sequence name alone on a line (may be long and may contain spaces)
Sequence data in free form, possibly with numbers and spaces ignored while reading the file. Dashes denote gaps.

Header lines may contain any text and also contain descriptions of trees, site sets and species groups when such data have been defined.

Trees are as in this example:


;;$ BioNJ tree
;;[BioNJ 658 sites J-C](((boli_haplo_03:0.00146,boli_haplo_06:0.00159)
;;:0.00159,boli_haplo_05:0.00146):0.02886,boli_haplo_01:0.03142);

Site sets are written as in this example:


;;# of segments=10  mychoice
;; 14,74 221,256 416,449 990,1148 1363,1384 1474,1483 1556,1668 
;; 2034,2062 2114,2139 2756,2859
where "mychoice" is the name of the set of sites and where the series of pairs of numbers lists the endpoints of successive block of sites.

Species groups are written as in this example:


;;@ of species = 4 distant outgroup
;; 2, 3, 4, 5
where "distant outgroup" is the name of the species group and where the series of numbers lists the ranks of sequences members of the species group.
Program arguments
Seaview can be run by using a command line:
seaview [options] [alignment-or-tree-file]
where alignment-or-tree-file is an optional sequence alignment or tree file to be read (always the last argument) and options are as in the following table:
-h display all program options and exit
-fast sequences will be displayed faster but less smoothly
-fontsize n font size used for the tree or alignment windows
Options for non-interactive usage driven by command-line arguments
Use exactly one of these options to get a non-interactive seaview run. Add any of the sub-options described below.
-convert convert an input alignment to another format (no window creation)
-concatenate concatenate alignment(s) to the end of an input alignment (no window creation)
-align align an input sequence file (no window creation)
-build_tree compute a phylogenetic tree from an input alignment file (no window creation)
-printout draw a multiple sequence alignment to PDF/SVG (no window creation)
-reroot modify the rooting of, or process otherwise, an input tree (no window creation)
-plotonly draw an input tree in a pdf or svg file (no window creation)
 
Sub-options for -convert
Use '-' as last argument to read alignment from standard input
-output_format fmt format of the converted alignment file (mase, phylip, clustal, msf, fasta, or nexus). The format of the input file is the default.
-o fname use fname as name of the converted alignment (default is built from input filename)
-o - write the output alignment to standard output
-translate translate input sequences to protein before outputting them (don't use the -sites option)
-no_terminal_stop translate terminal stop codons as a gap (with -translate option)
-del_gap_only_sites remove all gap-only sites from alignment (don't use the -sites option)
-def_species_group group_name,group_members create a species group of given name and members (species group members are expressed with their ranks as in this example: 3-8,12,19)
-def_site_selection name,endpoints create a selection of sites of given name and endpoints (site selection endpoints are expressed as in this example: 10-200,305,310-342)
-gblocks create under the name 'Gblocks' a set of blocks of conserved sites with the Gblocks program. Requires the nexus or mase output formats: the output file contains a new site selection called 'Gblocks'. A second command line with -convert -sites Gblocks allows to extract the set of conserved sites identified by Gblocks. Further options can be used to modify the Gblocks run:
-b4 allow smaller final blocks
-b5 allow gaps within final blocks
-b2 less strict flanking positions
-b3 don't allow many contiguous nonconserved positions
-sites selection_name use the named selection of sites from the input alignment
-species group_name use the named group of species from the input alignment
-bootstrap n writes n bootstrap replicates of the input sequence alignment to the output file. Can be combined with the species and sites selection options, -translate (-no_terminal_stop is implied), and -del_gap_only_sites. The -output_format option is not necessary because the output file is always in phylip format.
 
Sub-options for -concatenate
Use '-' as last argument to read alignment from standard input
-concatenate align1,...name(s) of alignment files to add at the end of the input alignment
-by_rankidentify sequences by their rank in alignments, i.e., the 1st seq. of align1 will be added at the end of the 1st seq of the input file, the 2nd with the 2nd, and so on. Without this option, sequences with the same name in alignment files are concatenated.
-output_format fmtformat of the concatenated alignment file (mase, phylip, clustal, msf, fasta, or nexus). Default is the format of the input alignment.
-o fname use fname as name of the concatenated alignment (default is built from input filename)
-o - write the concatenated alignment to standard output
 
Sub-options for -align
Use '-' as last argument to read sequence file from standard input
-align_algo n rank (in seaview, from 0) of alignment algorithm. 0 is clustalo, 1 is muscle. Other algorithms can be used after having been added as external alignment method in seaview. Without this option, seaview's default alignment algorithm is used. This can be changed using seaview's GUI.
-align_extra_opts "option1 ..."additional options to use when running the alignment algorithm
-align_at_protein_level input sequences are translated to protein; those protein sequences are aligned; and the resulting alignment is reproduced at the DNA level.
-o fname use fname as name of the output alignment
-o - write the output alignment to standard output
-output_format fmt format of the output alignment (mase, phylip, clustal, msf, fasta, or nexus)
 
Sub-options for -build_tree (either -distance or -parsimony is required and -o or -distance_matrix)
Use '-' as last argument to read alignment from standard input
-o fname use fname as name of the output tree
-o - write the output tree to standard output
-distance dist_name computes the tree with a distance method using the named distance (one among observed, JC, K2P, logdet, Ka, Ks, Poisson or Kimura)
-usertree tree_file_name tree_file_name is the name of a user-given tree file (in Newick format). In association with -distance, branch lengths of the user tree are computed. In association with -parsimony, the length of the tree is computed (and its branch lengths too for DNA sequences).
-distance_matrix fname don't compute the tree, but write to file fname the matrix of pairwise distances
-NJ compute the distance tree by the Neighbor-Joining method (default is BioNJ)
-parsimony compute the tree by the parsimony method
-search more|less|onefor parsimony on DNA only: controls, in decreasing order, how much rearrangement is done to find better trees (more is the default, corresponds to the S option of the dnapars program)
-nogaps remove all gap-containing sites before computations
-replicates n use n bootstrap replicates to compute tree branch support
-jumbles n jumble input sequence order n times (parsimony only)
-gaps_as_unknown encode gaps as unknown character state (parsimony only, by default they are encoded as an extra character state)
-sites selection_name use the named selection of sites from the input alignment
-species group_name use the named group of species from the input alignment
 
Sub-options for -printout (-o is required, available only in seaview versions able to create PDF files)
Use '-' as last argument to read alignment from standard input
-o fname use fname as name of the output PDF/SVG file
-o - send the printout to standard output
-fontsize n font size used for the alignment printout (10 by default)
-blocksize n divide sequences in blocks of size n (10 by default) separated by one space
-svg w produce a file in SVG format of width w pixels (without this option, the output is in PDF format)
-landscape write the alignment in landscape orientation (PDF output only)
-letter write the alignment using Letter-sized pages (A4 by default, PDF output only)
 
Sub-options for -reroot (available only in seaview versions able to create PDF files)
Use '-' as last argument to read input tree from standard input
-outnewick filename write the resulting tree to named file in Newick format
-outgroup name use tree leaf labelled 'name' as tree outgroup
-outgroup "name1,name2,name3" use node at center of the 3 named leaves as tree center and name3-containing clade as outgroup
-ingroup "name1,name2,name3" use node at center of the 3 named leaves as tree center and name1-containing clade as ingroup
-root_at_center reroot the tree at its center
-unroot remove the root from the input tree, if any
-patristic_distances fname write to named file patristic distances between leaves of input tree
-remove_bootstrap remove branch support values present in input tree
 
Sub-options for -plotonly (available only in seaview versions able to create PDF files)
options -outgroup, -ingroup, -outnewick above can be used as well as the following ones:
Use '-' as last argument to read tree from standard input
-o fname use fname as name of the output plot (.pdf or .svg)
-o - write the output plot to standard output (svg only)
-svg draw the input tree in a .svg file (default is .pdf file)
-unrooted draw the input tree in unrooted (circular) form
-pagecount n number of pages used for the tree plot (pdf only)
-letter use letter-sized paper for the tree plot
-fontsize n font size used in the tree plot
-lengths display branch lengths in the tree plot
-bootstrap display branch support values in the tree plot
-bootstrap_threshold x display branch supports if they are ≥ x
-size WxH pixel Width and Height of tree plot (svg only) (default is 595x842)
-match text display in color (red by default) tree labels containing this text (case is not significant)
-color RRGGBB hexadecimal color used for matching labels (example: 00FF00 means green)
-branch_width_as_support draw plot with branches of increasing widths with increasing support
-support_threshold_high f support above which a branch is drawn with maximal width (def=.95)
-support_threshold_low f support below which a branch is drawn with minimal width (def=.8)

Use item "Customize" of menu Props to further customize the program.


Sequence Coloring
The item "Customize" of menu Props allows to control colors.

SETTING DNA/RNA SEQUENCE COLORING
A,C,G,T/U buttons show the colors that are in use for the corresponding nucleotide.
Click on a button to open a color chooser and select the desired color (OK will accept the new choice; reset will use the starting shade).
"reset" will use default colors.
"Apply" or "Set changes permanent" will apply new shades to current alignment.

SETTING PROTEIN SEQUENCE COLORING
aa coloring scheme: by default, amino acids are split in 8 families each displayed in a different color. These families can be customized, up to a maximum of 10. Also, an alternative coloring scheme can be defined, and seaview will allow to switch between the first and the alternative coloring schemes.

catalog of amino acid colors: colors used for each amino acid family. Click on any to control the desired shade, as explained above. White is used for gaps and for unlisted residues.

Example: with the default coloring scheme, groups of amino acids KR and AFILMVW are displayed with the first and second catalog colors starting from left, respectively.

Click "reset" to use default amino acid families and color catalog. "Apply" or "Set changes permanent" to apply new shades to current alignment.

SETTING SYNONYMOUS CODON COLORING
Click on "Change" button. A window with a series of color cells appear. The 21 sets of synonymous codons and of stop codons can be colored with any of these colors. Click on a color cell and type a one-letter amino acid (or * to refer to stop codons) to reaffect a codon set to a new color. Repeat these operations as many times as necessary. Click on "OK" button when color re-assignments are complete.
Back to "Customization" window, "Apply" applies color re-assignments to this session's windows, "Set changes permanent" applies them to future seaview sessions as well.


Miscellaneous options
The item "Customize" of menu Props allows to set these options:
  • [sites] background grey: move the slider to change the grey shade of the alignment panel background; the "sites" shade applies to selected sites only; "reset" gives default values to both shades.
  • right-left movement keys: define 4 keys that move cursor right and left by 5 or 50 residues; reset uses default keys.
  • display lowercase: select so that lowercase characters present in sequence data are not displayed as uppercase.
  • inverted: select to display sequences as black letters on colored background.
  • spaces in FASTA names: If on, all characters after the '>' will be interpreted as sequence name in FASTA files. If off, the name ends at the first encountered space and the rest of the line (if any, e.g., length information) is interpreted as sequence annotation data.
  • alignment algorithm: to set the default alignment algorithm used by menu Align.
  • default save format: sets the default format of the "File:save as" menu item.
  • pdf/ps page: sets the page format used by all PDF- or PostScript-producing operations.
  • pdf/ps fontsize sets the font size used by item "Prepare pdf/ps" of menu File.
  • max name width: the maximum width at which sequence names are displayed; names longer than that are accepted but aren't entirely displayed.
  • phylip names width: sequence names longer than this value are truncated when saving PHYLIP-formatted alignments. Value 10 should be used to interface with the PHYLIP package. Larger values are more convenient for, e.g., PhyML, PAML.
  • sequence font size: the default fontsize used to display sequence alignments.

Customization
  • Mac OS: Custom settings are stored in file fr.cnrs.seaview.plist of the user's Library/Preferences folder.
  • MSWindows: Custom settings are stored in file seaview.ini in the same folder as the seaview program itself.
  • Unix/Linux: Custom settings are stored in file .seaviewrc in the user's home directory.
Note for users of Mac OS 10.9 and above: deleting the file $HOME/Library/Preferences/fr.cnrs.seaview.plist is no longer enough to reset seaview's preferences. You can enter this in a terminal:
defaults delete fr.cnrs.seaview
You may also force using a given fr.cnrs.seaview.plist file with this command:
defaults read fr.cnrs.seaview
Troubleshooting Importation from Databases
If you experience problems importing sequences from databases with the "Import from DBs" item of the File menu, open a terminal (or command prompt) window, and type in it:
telnet pbil.univ-lyon1.fr 5558
If you see this :
OK acnuc socket started
then sequence importation will work.
If the terminal remains blocked for some time and the above OK message does not appear, your communication to the database server is most probably blocked by your firewall. Please, contact your local network administrators, and ask them to allow outbound communications to the port number 5558. seaview/seaview.svg000644 000765 000024 00000011633 12404325714 015216 0ustar00mgouystaff000000 000000 image/svg+xml S E A - seaview/seaview.xcf000644 000765 000024 00000010374 12404325714 015200 0ustar00mgouystaff000000 000000 gimp xcf file  BÈBÈ$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) ¹°"E ° ß:-ÿ      gimp-text-layerû(text "-") (font "Sans") (font-size 18.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "fr-fr") (base-direction ltr) (color (color-rgba 0.000000 0.000000 0.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit pixels) vŠššššMÿÿ? Aÿ     gimp-text-layerû(text "A") (font "Sans") (font-size 18.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "fr-fr") (base-direction ltr) (color (color-rgba 0.000000 0.000000 0.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit pixels) m  ‘3ûììû[ÿÿZûÃÿÿÂù*ÿÆËÿ)ù‘ÿdaÿ÷ ïõ îî ÷`ÿ¡Žÿ_÷Èÿ@&þÇþ/ÿÿû.–ÿÿù• ñýøýñ eÿ·ù¸ÿdÌÿUüUÿÌ: Eÿ     ÿÿÿþgimp-text-layerû(text "E") (font "Sans") (font-size 18.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "fr-fr") (base-direction ltr) (color (color-rgba 0.000000 0.000000 0.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit pixels) ß ó òòò-ÿÿÿÿÿÿÿÿÿÿÿÿÿ7 Sÿ     ÿÿÿþgimp-text-layerû(text "S") (font "Sans") (font-size 18.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "fr-fr") (base-direction ltr) (color (color-rgba 0.000000 0.000000 0.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit pixels)     &òòò-øA¸îûàŸ;ýQýÿÿ÷Ôÿ²)VÀüúÿûßÿ}÷aÿÿþÜ©^üA²óÿÿýÒù*fÜÿ¤ü#ÿíïÿúÉj(2¹ÿÓÿÿóüP2ŽÑöúä«:7 &Nouveau calque#1ÿ     ÿÿÿþ ] & q & ÀÀÀ…øA¸îûàŸ;ÿýQýÿÿÿ÷Ôÿ²)VÀÿ üúÿ ÿ ûßÿ} ÿ ÷aÿÿþÜ©^ÿüA²óÿÿýÒÿ ù*fÜÿ¤ÿü#ÿíÿüÿúÿ öÉj(2¹ÿÓÿ ÿýüPÿ÷2ŽÑöúä«:ÿiûììû[ÿÿZûÃÿÿÂù*ÿÆËÿ)ù‘ÿdaÿ÷ ïõ îî ÿ÷`ÿ¡Žÿ_ÿ÷Èÿ@&þÇþ/ÿÿþ.þ–ÿÿþ•û ñýûýñ üeÿ·ü¸ÿdüÌÿUüUÿ̱ Nouveau calqueÿ      ’  ¦ ¶ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌMÌM€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿ€ÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿæÿÿ Arrière-planÿ     ä ø  Masque de sélection ” ¨ ¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿseaview/seaview.xpm000644 000765 000024 00000007255 12404325714 015230 0ustar00mgouystaff000000 000000 /* XPM */ static const char * seaview_xpm[] = { "32 32 95 2", " c None", ". c #19CC19", "+ c #CC4DCC", "@ c #129812", "# c #063806", "$ c #010D01", "% c #000300", "& c #031803", "* c #094C09", "= c #139C13", "- c #000000", "; c #118B11", "> c #000100", ", c #042204", "' c #073D07", ") c #14AB14", "! c #18C818", "~ c #16BB16", "{ c #108710", "] c #063206", "^ c #000400", "/ c #17BD17", "( c #031903", "_ c #0C680C", ": c #17BC17", "< c #0F7E0F", "[ c #031C03", "} c #084408", "| c #0F800F", "1 c #010901", "2 c #042404", "3 c #16B916", "4 c #18C918", "5 c #14AA14", "6 c #0F7A0F", "7 c #084808", "8 c #15B015", "9 c #010E01", "0 c #052B05", "a c #0E770E", "b c #15AC15", "c c #18C618", "d c #18C718", "e c #14A414", "f c #042304", "g c #000200", "h c #118C11", "i c #0B5A0B", "j c #000700", "k c #021502", "l c #084308", "m c #139D13", "n c #1980E6", "o c #FFFFFF", "p c #187CDF", "q c #010911", "r c #105293", "s c #105294", "t c #051E36", "u c #051E37", "v c #146AC0", "w c #051C33", "x c #051A2E", "y c #146BC1", "z c #0A3763", "A c #0F4D8B", "B c #0F4F8E", "C c #0A3764", "D c #187BDD", "E c #01080E", "F c #000509", "G c #1779DA", "H c #01080F", "I c #0F4F8F", "J c #092F54", "K c #0B3865", "L c #0F5090", "M c #051B31", "N c #125FAC", "O c #156CC3", "P c #051C32", "Q c #1468BB", "R c #1468BC", "S c #0A345E", "T c #0A355F", "U c #1779DB", "V c #01070C", "W c #000101", "X c #1671CB", "Y c #177ADC", "Z c #0F4D8A", "` c #072440", " . c #062340", ".. c #05192E", "+. c #105599", ". . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + ", ". . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + ", ". . . . . @ # $ % & * = . . . . + + + + - - - - - - - - + + + + ", ". . . . ; > - - - - - - . . . . + + + + - - - - - - - - + + + + ", ". . . . , - ' ) ! ~ { ] . . . . + + + + - - + + + + + + + + + + ", ". . . . ^ - / . . . . . . . . . + + + + - - + + + + + + + + + + ", ". . . . ( - _ : . . . . . . . . + + + + - - + + + + + + + + + + ", ". . . . < - - - [ } | ! . . . . + + + + - - - - - - - - + + + + ", ". . . . . @ ' 1 - - - 2 3 . . . + + + + - - - - - - - - + + + + ", ". . . . . . . 4 5 6 [ - 7 . . . + + + + - - + + + + + + + + + + ", ". . . . . . . . . . 8 - 9 . . . + + + + - - + + + + + + + + + + ", ". . . . . . . . . . : - ^ . . . + + + + - - + + + + + + + + + + ", ". . . . 0 a b c d e # - f . . . + + + + - - + + + + + + + + + + ", ". . . . - - - - - - - g h . . . + + + + - - - - - - - - + + + + ", ". . . . e i 2 j ^ k l m . . . . + + + + - - - - - - - - + + + + ", ". . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + ", "n n n n n n n n n n n n n n n n o o o o o o o o o o o o o o o o ", "n n n n n n n n n n n n n n n n o o o o o o o o o o o o o o o o ", "n n n n n n p q q p n n n n n n o o o o o o o o o o o o o o o o ", "n n n n n n r - - s n n n n n n o o o o o o o o o o o o o o o o ", "n n n n n n t - - u n n n n n n o o o o o o o o o o o o o o o o ", "n n n n n v - w x - y n n n n n o o o o o o o o o o o o o o o o ", "n n n n n z - A B - C n n n n n o o o o o o o o o o o o o o o o ", "n n n n D E F G D H H D n n n n o o o o o o - - - - - o o o o o ", "n n n n I - J n n K - L n n n n o o o o o o - - - - - o o o o o ", "n n n n M - N n n O - P n n n n o o o o o o o o o o o o o o o o ", "n n n Q - - - - - - - - R n n n o o o o o o o o o o o o o o o o ", "n n n S - - - - - - - - T n n n o o o o o o o o o o o o o o o o ", "n n U V W X n n n n X W V Y n n o o o o o o o o o o o o o o o o ", "n n Z - ` n n n n n n .- A n n o o o o o o o o o o o o o o o o ", "n n ..- +.n n n n n n +.- ..n n o o o o o o o o o o o o o o o o ", "n n n n n n n n n n n n n n n n o o o o o o o o o o o o o o o o "}; seaview/statistics.cxx000644 000765 000024 00000043456 12404325714 015760 0ustar00mgouystaff000000 000000 #include "seaview.h" #include #include int nbaagroup=5; int aagroup[30]; char aalist[30] = "ACDEFGHIKLMNPQRSTVWY"; int TRANSVONLY=0; char infotext[10000]; extern void *check_alloc(int nbrelt, int sizelt); void bydefault_aagroups(){ int i; sprintf(aalist, "EDQNHRKILMVAPSGTFYWC"); for(i=0;i<7;i++) aagroup[i]=0; for(;i<11;i++) aagroup[i]=1; for(;i<16;i++) aagroup[i]=2; for(;i<18;i++) aagroup[i]=3; for(;i<20;i++) aagroup[i]=4; } /* basecomp */ /* Write in comp the composition (percent of 4 bases) of sequence seq */ int basecomp(char* seq, double* comp){ int i, lg=0; for(i=0;i<4;i++) comp[i]=0.; for(i=0;seq[i];i++){ if(seq[i]=='A') comp[0]++; else if(seq[i]=='C') comp[1]++; else if(seq[i]=='G') comp[2]++; else if(seq[i]=='T') comp[3]++; else lg--; lg++; } if(lg<=0) return 0; for(i=0;i<4;i++) comp[i]=comp[i]*100/lg; return lg; } /* aaclass */ /* Return the class of aminoacid aa */ int aaclass(char aa){ int i=0; while(aalist[i]!=aa && aagroup[i]!=-1) i++; if(aagroup[i]==-1) return 5; return(aagroup[i]); } /* aacomp */ /* Compute aminoacid composition of proteic sequence seq. */ /* The whole composition (percent of 20 aminoacid) is written in comp, */ /* ordered as in aalist. */ /* Percent of each aminoacid group are written in compgroup. */ int aacomp(char* seq, double* comp, double* compgroup){ int i, j, lg=0, nbaa; int c; nbaa=(int)strlen(aalist); for(i=0;iseq_length; list_segments start_end = {1, lgseq, NULL}; if (active == NULL) active = &start_end; /*if(view->protein){ sel1=sel2=sel3=1; } else{ if(GetStatus(po1i)) sel1=1; if(GetStatus(po2i)) sel2=1; if(GetStatus(po3i)) sel3=1; }*/ sel1=sel2=sel3=1; if(sel1 && sel2 && sel3){ while(active) { for(i = active->debut - 1; i < active->fin; i++) selected[i]=1; active = active->next; } } else{ /*if(sel1 && sel2 && !sel3){ for(i=0;iuser_data()); fputs(ml->value(), out); fclose(out); } void geni_act(SEA_VIEW *view) { int i, j, k, l, ii, nb, lgtot, lg, lgvar, lginfo, *lgcomp, totlgcomp, nc=0; int *selected, nbaa, nbcp; double **comp, *compall, compcomp[4], **compgroup, *compgroupall, min[4], max[4]; double P, Psum=0., Q, Qsum=0., Pmin, Pmax, Qmin, Qmax, titvratio, titvmin, titvmax, freq[16], mat_obs[16], *ti, *tv; char **genseq, **genname, *text, *minname[4], *maxname[4], nt[4]={'A', 'C', 'G', 'T'}; char *titvminname1, *titvminname2, *titvmaxname1, *titvmaxname2; int lgseq = view->seq_length; int nbseq = view->tot_seqs; bydefault_aagroups(); text=(char*)check_alloc(10000, sizeof(char)); nb=lgtot=0; selected=(int*)check_alloc(lgseq, sizeof(int)); reg_and_pos(view, selected, view->active_region ? view->active_region->list : NULL); nbaa=(int)strlen(aalist); /* SET UP DATA */ for(i=0;itot_sel_seqs == 0 || view->sel_seqs[i]) nb++; genseq=(char**)check_alloc(nb, sizeof(char*)); genname=(char**)check_alloc(nb, sizeof(char*)); for(i=0;itot_sel_seqs == 0 || view->sel_seqs[i]){ genname[j]=view->seqname[i]; l=0; for(k=0;ksequence[i][k]); } j++; } } ti=(double*)check_alloc(nb*(nb-1)/2, sizeof(double)); tv=(double*)check_alloc(nb*(nb-1)/2, sizeof(double)); /* ALL SITES : COMPOSITION */ lgcomp=(int*)check_alloc(nb, sizeof(int)); comp=(double**)check_alloc(nb, sizeof(double*)); for(i=0;iprotein?nbaa:4, sizeof(double)); compall=(double*)check_alloc(view->protein?nbaa:4, sizeof(double)); if(view->protein){ compgroup=(double**)check_alloc(nb, sizeof(double*)); for(i=0;iprotein); lg=(int)strlen(genseq[0]); lgvar=variable(genseq, nb); lginfo=informative(genseq, nb); /* COMPOSITION */ if(!view->protein && lg!=0){ for(i=0;imax[i]){ max[i]=comp[j][i]; maxname[i]=genname[j]; } } } } /* CHANGES */ if(!view->protein && lg!=0){ for(ii=0;ii<16;ii++) mat_obs[ii]=0.; k=0; nbcp=0; titvmin=100000.; titvmax=0.; for(i=0;i0.1){ titvratio=P/Q; if(titvratiotitvmax){ titvmax=titvratio; titvmaxname1=genname[i]; titvmaxname2=genname[j]; Pmax=P; Qmax=Q; } nbcp++; } k++; } } for(ii=0;ii<16;ii++) mat_obs[ii]/=(nb*(nb-1)/(2*100.)); /* printf("observed matrix :\n"); printf("AA : %.1f CC : %.1f GG : %.1f TT : %.1f\n", mat_obs[0], mat_obs[5], mat_obs[10], mat_obs[15]); printf("AG : %.1f CT : %.1f\n", mat_obs[2]+mat_obs[8], mat_obs[7]+mat_obs[13]); printf("AC : %.1f AT : %.1f CG : %.1f GT : %.1f\n", mat_obs[1]+mat_obs[4], mat_obs[3]+mat_obs[12], mat_obs[6]+mat_obs[9], mat_obs[11]+mat_obs[14]); */ /* titvf=fopen("TITV", "w"); fprintf(titvf, "Ti\tTv\n"); for(i=0;iprotein && nb==2 && lg!=0) freq_obs(genseq[0], genseq[1], freq); /* DISPLAY INTO NEW WINDOW */ char *p; Fl_Window *win = new Fl_Window(600, 500, "Statistics"); Fl_Multiline_Output *ml = new Fl_Multiline_Output(2, 2, win->w()-4, win->h()-24); ml->textfont(FL_COURIER); ml->user_data(view->masename); win->resizable(ml); Fl_Button *b = new Fl_Button(win->w()/2 - 25 , win->h() - 23, 50, 20, "Save"); b->callback(save_stat_cb, ml); Fl_Return_Button *ok = new Fl_Return_Button(win->w() - 55 , win->h() - 23, 50, 20, "OK"); if(view->tot_sel_seqs == 0) sprintf(text, "%d species\n", nb); else { sprintf(text, "%d selected species\n", nb); } if(view->tot_sel_seqs > 0 && nb<=20){ for(i=0;itot_seqs;i++){ if(!view->sel_seqs[i]) continue; strcat(text, view->seqname[i]); strcat(text, ", "); if((i+1)%4==0 || i==nb-1) strcat(text, "\n"); } strcat(text, "\n"); } p = text + strlen(text); sprintf(p, "\n%d selected sites\n", lgtot); p += strlen(p); if(view->protein) sprintf(p, " including %d complete (no gaps, no X)\n", lg); else sprintf(p, " including %d complete (no gaps, no N)\n", lg); p += strlen(p); if(nb>=2 && lg!=0){ sprintf(p, " including %d variable (%.1f%% of complete)\n", lgvar, (double)lgvar*100/lg); p += strlen(p); if(nb>=4){ sprintf(p, " including %d informative (%.1f%% of complete)\n", lginfo, (double)lginfo*100/lg); p += strlen(p); } } if(view->protein){ int k; sprintf(p, "\nAMINOACID COMPOSITION (all sites) :\n"); p += strlen(p); j=0; for(i=0;i1 && lg!=0){ sprintf(p, " Complete sites only :\n"); p += strlen(p); sprintf(p, " Minimum Maximum:\n"); p += strlen(p); for(i=0;i<4;i++){ sprintf(p, " %c : %.1f %% ", nt[i], compcomp[i]); p += strlen(p); sprintf(p, "%.1f%% (%s) ", min[i], minname[i]); p += strlen(p); sprintf(p, "%.1f%% (%s)\n", max[i], maxname[i]); p += strlen(p); } } } if(!view->protein && nb>1 && lg!=0){ sprintf(p, "\nOBSERVED CHANGES (complete sites)\n"); p += strlen(p); if(nb>2) sprintf(p, "Transition/transversion ratio : %.3f (mean over all sequence pairs)\n", (double)Psum/Qsum); else sprintf(p, "Transition/transversion ratio : %.3f\n", (double)Psum/Qsum); p += strlen(p); if(nb>2){ sprintf(p, "Minimum : %.3f (%s - %s, %d transitions, %d transversions)\n", titvmin, titvminname1, titvminname2, (int)Pmin, (int)Qmin); p += strlen(p); sprintf(p, "Maximum : %.3f (%s - %s, %d transitions, %d transversions)\n", titvmax, titvmaxname1, titvmaxname2, (int)Pmax, (int)Qmax); //p += strlen(p); } else { sprintf(p, "Observed nucleotide pairs :\n"); p += strlen(p); sprintf(p, "%35s%s\n" "%36s A C G T\n", "", genname[1], ""); p += strlen(p); for(i=0;i<4;i++){ sprintf(p, "%30s %c", i==1 ? genname[0] : "", nt[i]); p += strlen(p); for(j=0;j<4;j++){ sprintf(p, "%6d", (int)(freq[4*i+j]*lgtot)); p += strlen(p); } *p++ = '\n'; } } } ml->value(text); win->end(); win->show(); while (TRUE) { Fl_Widget* obj = Fl::readqueue(); if (!obj) Fl::wait(); else if (obj == ok || obj == win) { delete win; break; } } free(selected); free(text); for(i=0;iprotein){ for(i=0;iuser_data()); } seaview/svg.cxx000644 000765 000024 00000017707 12404325714 014365 0ustar00mgouystaff000000 000000 #include "treedraw.h" #include "unrooted.h" #include "svg.h" #ifndef NO_PDF #include "pdf_or_ps.h" #endif extern void do_plot(FD_nj_plot *fd_nj_plot, int doing_print); extern void frame_and_draw_unrooted(FD_unrooted *fd_unrooted); extern "C" int trim_key(char *name); /* remove trailing spaces */ const char *Fl_SVG_File_Surface::class_id = "Fl_SVG_File_Device"; Fl_SVG_File_Surface::~Fl_SVG_File_Surface() { delete driver(); } void Fl_SVG_File_Surface::end() { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); fputs("\n", driver->file()); fflush(driver->file()); } Fl_SVG_Graphics_Driver::Fl_SVG_Graphics_Driver(FILE *f) { out_ = f; width_ = 1; linecap_ = "butt"; family_ = ""; bold_ = ""; style_ = ""; red_ = green_ = blue_ = 0; } Fl_SVG_Graphics_Driver::~Fl_SVG_Graphics_Driver() { } void Fl_SVG_Graphics_Driver::rect(int x, int y, int w, int h) { fprintf(out_, "\n", x, y, w, h, red_, green_, blue_, width_); } void Fl_SVG_Graphics_Driver::rectf(int x, int y, int w, int h) { fprintf(out_, "\n", x, y, w, h, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::line(int x1, int y1, int x2, int y2) { fprintf(out_, "\n", x1,y1,x2,y2, red_, green_, blue_, width_, linecap_); } void Fl_SVG_Graphics_Driver::font_(int ft, int s) { Fl_Graphics_Driver::font(ft, s); int famnum = ft/4; if (famnum == 0) family_ = "Helvetica"; else if (famnum == 1) family_ = "Courier"; else family_ = "Times"; int modulo = ft % 4; int use_bold = modulo == 1 || modulo == 3; int use_italic = modulo >= 2; bold_ = ( use_bold ? " font-weight=\"bold\"" : "" ); style_ = ( use_italic ? " font-style=\"italic\"" : "" ); if (use_italic && famnum != 2) style_ = " font-style=\"oblique\""; } void Fl_SVG_Graphics_Driver::font(int ft, int s) { Fl_Display_Device::display_device()->driver()->font(ft, s); font_(ft, s); } void Fl_SVG_Graphics_Driver::line_style(int style, int width, char *dashes) { if (width == 0) width = 1; width_ = width; if (style & FL_CAP_SQUARE) linecap_ = "square"; if (style & FL_CAP_ROUND) linecap_ = "round"; else linecap_ = "butt"; } void Fl_SVG_Graphics_Driver::draw(const char *str, int n, int x, int y) { // Caution: Internet Explorer ignores the xml:space="preserve" attribute // work-around: replace all spaces by no-break space = U+00A0 = 0xC2-0xA0 (UTF-8) before sending to IE fprintf(out_, "%.*s\n",x, y, family_, bold_, style_, size(), red_, green_, blue_, n, str); } void Fl_SVG_Graphics_Driver::draw(const char* str, int n, float fx, float fy) { return draw(str, n, (int)fx, (int)fy); } void Fl_SVG_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) { fprintf(out_, "", x, y, -angle); draw(str, n, 0, 0); fputs("\n", out_); } void Fl_SVG_Graphics_Driver::rtl_draw(const char*, int, int, int) {} void Fl_SVG_Graphics_Driver::color(Fl_Color c) { Fl_Graphics_Driver::color(c); Fl::get_color(c, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::color(uchar r, uchar g, uchar b) { red_ = r; green_ = g; blue_ = b; } void Fl_SVG_Graphics_Driver::draw_image(const uchar*, int, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw_image_mono(const uchar*, int, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw(Fl_RGB_Image*, int, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw(Fl_Pixmap*, int, int, int, int, int, int) {} void Fl_SVG_Graphics_Driver::draw(Fl_Bitmap*, int, int, int, int, int, int) {} double Fl_SVG_Graphics_Driver::width(const char* str, int l) { return Fl_Display_Device::display_device()->driver()->width(str, l); } int Fl_SVG_Graphics_Driver::height() { return Fl_Display_Device::display_device()->driver()->height(); } int Fl_SVG_Graphics_Driver::descent() { return Fl_Display_Device::display_device()->driver()->descent(); } #ifndef NO_PDF Fl_SVG_PDF_width_Graphics_Driver::Fl_SVG_PDF_width_Graphics_Driver(FILE *f) : Fl_SVG_Graphics_Driver(f), pdf_driver(new Fl_PDF_Graphics_Driver) { pdf_driver->pdf = PDF_new(); PDF_begin_document(pdf_driver->pdf, "", 0, ""); PDF_begin_page_ext(pdf_driver->pdf, 100, 100, ""); } Fl_SVG_PDF_width_Graphics_Driver::~Fl_SVG_PDF_width_Graphics_Driver() { PDF_end_page_ext(pdf_driver->pdf, ""); PDF_end_document(pdf_driver->pdf, ""); PDF_delete(pdf_driver->pdf); delete pdf_driver; } int Fl_SVG_PDF_width_Graphics_Driver::descent() { return pdf_driver->descent(); } int Fl_SVG_PDF_width_Graphics_Driver::height() { return pdf_driver->height(); } double Fl_SVG_PDF_width_Graphics_Driver::width(const char* str, int l) { return pdf_driver->width(str, l); } void Fl_SVG_PDF_width_Graphics_Driver::font(int ft, int s) { font_(ft, s); pdf_driver->font(ft, s); } #endif // NO_PDF Fl_SVG_File_Surface::Fl_SVG_File_Surface(int w, int h, FILE *f, bool use_pdf_width) : Fl_Surface_Device(NULL) { fprintf(f, "\n" "\n" "\n", w, h, w, h); width_ = w; height_ = h; #ifndef NO_PDF if (use_pdf_width) { driver(new Fl_SVG_PDF_width_Graphics_Driver(f)); } else #endif driver(new Fl_SVG_Graphics_Driver(f)); } void svg_tree_save(FD_nj_plot *fd_nj_plot, Fl_SVG_File_Surface *svg) { svg->set_current(); fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size); fd_nj_plot->char_height = fl_height(); fd_nj_plot->ascent = fl_height() - fl_descent(); fl_color(FL_GRAY); fl_rect(0, 0, svg->width(), svg->height()); fl_color(FL_BLACK); fl_line_style(FL_CAP_SQUARE, 1); if(fd_nj_plot->fd_unrooted == NULL) { do_plot(fd_nj_plot, TRUE); } else { FD_unrooted *fd_unrooted = (FD_unrooted *)fd_nj_plot->fd_unrooted; fd_unrooted->previous_w = 0; fd_unrooted->previous_h = 0; fd_unrooted->comp_phys_bounds = TRUE; int old_x = fd_unrooted->x_offset; int old_y = fd_unrooted->y_offset; fd_unrooted->x = fd_unrooted->x_offset = 0; fd_unrooted->y = fd_unrooted->y_offset = 0; fd_unrooted->w = svg->width(); fd_unrooted->h = svg->height(); frame_and_draw_unrooted(fd_unrooted); fd_unrooted->x_offset = old_x; fd_unrooted->y_offset = old_y; fd_unrooted->comp_phys_bounds = FALSE; } Fl_Display_Device::display_device()->set_current(); svg->end(); fclose(((Fl_SVG_Graphics_Driver*)svg->driver())->file()); delete svg; } void svg_tree_dialog_and_save(FD_nj_plot *fd_nj_plot) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->title("Enter SVG filename"); chooser->filter("SVG Files\t*.{svg}"); char tmp[100]; strcpy(tmp, extract_filename(fd_nj_plot->tree_name)); char *p = strrchr(tmp, '.'); if(p != NULL) *p = 0; strcat(tmp, ".svg"); chooser->preset_file(tmp); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); char *plotfilename = run_and_close_native_file_chooser(chooser); if (plotfilename == NULL) return; FILE *out; if (!(out = fopen(plotfilename, "w"))) return; svg_tree_save(fd_nj_plot, new Fl_SVG_File_Surface(fd_nj_plot->panel->w(), fd_nj_plot->panel->h(), out)); } ���������������������������������������������������������seaview/svg.h���������������������������������������������������������������������������������������000644 �000765 �000024 �00000004606 12404325714 014004� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef FL_SVG_GRAPHICS_DRIVER_H #define FL_SVG_GRAPHICS_DRIVER_H #include #include #ifndef NO_PDF #include "pdf_or_ps.h" #endif class Fl_SVG_Graphics_Driver : public Fl_Graphics_Driver { FILE *out_; int width_; const char *linecap_; uchar red_, green_, blue_; public: Fl_SVG_Graphics_Driver(FILE*); ~Fl_SVG_Graphics_Driver(); FILE* file() {return out_;} protected: const char *family_; const char *bold_; const char *style_; void rect(int x, int y, int w, int h); void rectf(int x, int y, int w, int h); void line_style(int style, int width, char *dashes=0); void line(int x1, int y1, int x2, int y2); void font_(int f, int s); void font(int f, int s); void draw(const char *str, int n, int x, int y); void draw(const char*, int, float, float) ; void draw(int, const char*, int, int, int) ; void rtl_draw(const char*, int, int, int) ; void color(uchar r, uchar g, uchar b); void color(Fl_Color c); void draw_image(const uchar*, int, int, int, int, int, int) ; void draw_image_mono(const uchar*, int, int, int, int, int, int) ; void draw_image(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw_image_mono(void (*)(void*, int, int, int, uchar*), void*, int, int, int, int, int) ; void draw(Fl_RGB_Image*, int, int, int, int, int, int) ; void draw(Fl_Pixmap*, int, int, int, int, int, int) ; void draw(Fl_Bitmap*, int, int, int, int, int, int) ; double width(const char*, int) ; int height() ; int descent() ; }; class Fl_SVG_File_Surface : public Fl_Surface_Device { int width_, height_; public: static const char *class_id; const char *class_name() {return class_id;}; Fl_SVG_File_Surface(int, int, FILE*, bool use_pdf_width = false); void end(); int width() { return width_; } int height() { return height_; } ~Fl_SVG_File_Surface(); }; #ifndef NO_PDF /* Fl_SVG_PDF_width_Graphics_Driver uses a PDF graphics driver only to compute string widths and heights, to allow creation of SVG data without calling fl_open_display(). */ class Fl_SVG_PDF_width_Graphics_Driver : public Fl_SVG_Graphics_Driver { Fl_PDF_Graphics_Driver *pdf_driver; public: Fl_SVG_PDF_width_Graphics_Driver(FILE *f); ~Fl_SVG_PDF_width_Graphics_Driver(); int descent(); int height(); double width(const char* str, int l); void font(int ft, int s); }; #endif // ! NO_PDF #endif // FL_SVG_GRAPHICS_DRIVER_H ��������������������������������������������������������������������������������������������������������������������������seaview/threads.cxx���������������������������������������������������������������������������������000644 �000765 �000024 �00000003135 12404325714 015206� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* default thread stack sizes Mac OS X 512 KB (8 MB for main thread) Linux 2 MB WIN32 1 MB */ // included function int fl_create_thread(void (*f) (void *), void* p, unsigned stack_size_KB); // if stack_size_KB == 0, the thread is created with its default size // returns 0 iff OK #ifdef NO_THREADS int fl_create_thread(void (*f) (void *), void* p, unsigned stack_size_KB) { f(p); return 0; } #else #ifndef HAVE_PTHREAD #ifdef WIN32 #define HAVE_PTHREAD 0 #else #define HAVE_PTHREAD 1 #endif #endif #if HAVE_PTHREAD // Use POSIX threading... #include int fl_create_thread(void (*f) (void *), void* p, unsigned stack_size_KB) { pthread_t t; int err = 0; pthread_attr_t threadAttribute; size_t stackSize = 0; int retval; err = pthread_attr_init(&threadAttribute); if (err) return err; pthread_attr_setdetachstate(&threadAttribute, PTHREAD_CREATE_DETACHED); if (stack_size_KB > 0) { err = pthread_attr_getstacksize(&threadAttribute, &stackSize); if (err) return err; if (stackSize < stack_size_KB * 1024) { err = pthread_attr_setstacksize(&threadAttribute, stack_size_KB * 1024); if (err) return err; } } retval = pthread_create(&t, &threadAttribute, (void* (*) (void *))f, p); pthread_attr_destroy(&threadAttribute); return retval; } #else // Use Windows threading... #include int fl_create_thread(void (*f) (void *), void* p, unsigned stack_size_KB) // returns 0 iff OK { unsigned long t; t = _beginthread(f, stack_size_KB * 1024, p); return t == -1L; } #endif // HAVE_PTHREAD #endif // NO_THREADS �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/treedraw.cxx��������������������������������������������������������������������������������000644 �000765 �000024 �00000406577 12600216121 015377� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������//njplot coords = pdf coords: bottom to top //QuickDraw coords: top to bottom #include #include #include #include #include #include #include #include #include #include #include #include "unrooted.h" #include "treedraw.h" #include "pdf_or_ps.h" #include "svg.h" #include #define MAX_FRAC 0.95 #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif #include #include #include /* typedefs */ typedef enum { helvetica, courier, times} font_name; enum {save_to_trees_menu, remove_from_trees_menu, save_rooted, save_unrooted, save_all_trees, save_patristic, print_tree, save_as_ps_pdf, save_as_svg, A4_format, letter_format, page_count}; enum {reorder_align_following_tree = page_count + 14, select_seqs_in_alignment, open_tree_or_align, new_window, close_window}; typedef struct branche { /* une branche definie par ses deux extremites */ struct noeud *bouta; struct noeud *boutb; char *br_label; } branche; #define s_noeud sizeof(struct noeud) /* prototypes of included functions */ #ifdef MICRO static void copy(Fl_Widget *wgt, void *data); #endif static void paste(Fl_Widget *wgt, void *data); void toggle_br_lengths(Fl_Widget *wgt, void *data); void toggle_bootstrap(Fl_Widget *wgt, void *data); void change_ffam(Fl_Widget *wgt, void *data); char *prepare_ps_or_pdf_font(int font_num); void subtreeup_callback(Fl_Widget *wgt, void *data); void operation_callback(Fl_Widget *wgt, void *data); void do_plot(FD_nj_plot *fd_nj_plot, int doing_print); int calc_text_size(char *text, int *pheight, int *pascent); void plotstring(const char *nom); void dir_moveto(double x,double y); void dir_lineto(double x,double y); void dir_plotsquare(double x, double y, int edge, int use_color); void scale_window(double lxmin, double lxmax, double lymin, double lymax, double pxmin, double pxmax, double pymin, double pymax); void ch_echelle(double lx, double ly, double *px, double *py); void init_tree(char *fname, char *displayname); const char *preptree(FD_nj_plot *fd_nj_plot); char *check_alloc(int nbrelt, int sizelt); const char *loadphylip(FD_nj_plot *fd_nj_plot, char *arbre, char *last_bootstrap); struct noeud *unrootedset(FD_nj_plot *fd_nj_plot, char *deb, char *fin, branche **p_int_br); char *nextpar(char *pospar); const char *make_binary_or_unrooted(char *arbre); int make_binary(char *arbre, char *debut, char *fin, int go_down); void mydrawstring(double x, double y, char *nom, char option, int height); void moveto(double x,double y); void lineto(double x,double y); int calc_brl_for_lengthless(struct noeud *centre, struct noeud *pere); void add_value_downstream(struct noeud *centre, int value); double place_midpoint_root(struct noeud *from, struct noeud *racine, int notu, int fixed_outgroup); double get_length_down(struct noeud *, struct noeud *); void runtree(FD_nj_plot *fd_nj_plot); void mem_plot(FD_nj_plot *fd_nj_plot, struct noeud *pere, struct noeud *centre, double currx, double *curry); void mem_point(FD_nj_plot *fd_nj_plot, double x, double y, int number); void mem_nom(FD_nj_plot *fd_nj_plot, double x, double y, char *nom, char option); void mem_trait(FD_nj_plot *fd_nj_plot, double xd, double yd, double xf, double yf, int width); char *get_br_label(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b); char *get_br_label_with_threshold(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b); int get_br_from_bouts(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b); void free_tree(FD_nj_plot *fd_nj_plot); char *ecrit_arbre_parenth_unrooted(FD_nj_plot *fd_nj_plot, struct noeud *root); char *ecrit_arbre_parenth(FD_nj_plot *fd_nj_plot, struct noeud *root); char *recur_ecrit_arbre(FD_nj_plot *fd_nj_plot, struct noeud *centre, char *arbre, char *finarbre); void removeroot(FD_nj_plot *fd_nj_plot); double length_log_phys(double p); double length_phys_log(double p); double arrondi_echelle(double x); double calc_echelle(double larg); void draw_scale(FD_nj_plot *fd_nj_plot); int calc_n_desc(struct noeud *pere); void majuscules(char *p); void treeplotw_callback(Fl_Widget *wgt, void *data); void scrollnotu(FD_nj_plot *fd_nj_plot); void zoom_callback(Fl_Widget *wgt, void *data); void scroller_callback(Fl_Widget *wgt, void *data); static void patristic_callback(Fl_Widget *wgt, void *unused); static void file_callback(Fl_Widget *wgt, void *data); void remove_from_tree_menu(FD_nj_plot *fd_nj_plot, const char *name); void add_to_tree_menu(FD_nj_plot *fd_nj_plot); void physic_to_logic(double px, double py, double *lx, double *ly); void tree_click_proc(tree_panel *panel, int mx, int my); void disconnect_tree_windows(SEA_VIEW *view); void reorder_following_tree(struct noeud *root, int notu, SEA_VIEW *view); static void search_callback(Fl_Widget *wgt, void *data); void bt_threshold_callback(Fl_Widget *wgt, void *data); void midpoint_callback(Fl_Widget *wgt, void *data); void edit_tree_header(Fl_Widget *wgt, void *data); void set_win_size_callback(Fl_Widget *wgt, void *data); int compare_newick_with_names(const char *tree, char **names, int notu, char **pname); void edit_shape_callback(Fl_Widget *obj, void *data); void select_clade_callback(Fl_Widget *obj, void *data); void delete_clade_callback(Fl_Widget *obj, void *data); void complete_edit_callback(Fl_Widget *obj, void *data); void select_in_alignment(FD_nj_plot *fd_nj_plot); bool is_parent(struct noeud *centre, struct noeud *from, const char *label); struct noeud * span_nodes(struct noeud *centre, struct noeud *from); double recur_patristic_distances(FD_nj_plot *fd_nj_plot, struct noeud *centre, float **d, int **listdesc); void calc_patristic_distances(FD_nj_plot *fd_nj_plot, FILE *out); void print_plot(FD_nj_plot *fd_nj_plot, bool to_ps_file, const char *directname = NULL); static double midpoint_rooting(struct noeud *from, int notu, double *p_root_br_length); char *extract_one_tree(char *from, char **pnext); void replace_with_new_tree(FD_nj_plot *fd_nj_plot, char *newtree); void tree_counter_callback(Fl_Widget *, void *data); int calc_tree_count(char *tree); //extern variables & functions extern void help_callback(Fl_Widget *ob, void *data); extern Fl_Window *use_initial_file(SEA_VIEW *view, char *masename, int doing_dnd); extern void direct_help_callback(Fl_Widget *wgt, void *data); extern void rooted_unrooted_callback(Fl_Widget *o, void *data); extern void free_unrooted(FD_unrooted *data); extern void unrooted_search(FD_unrooted *fd_unrooted, const char *select); extern void svg_tree_save(FD_nj_plot *fd_nj_plot, Fl_SVG_File_Surface *svg); extern int debut_arbre(const char *tree, FD_unrooted *fd_unrooted); extern int testbit(int *plist, int num); extern void bit1(int *plist, int num); #ifdef __APPLE__ extern int add_windowmenuitem(const char *name, Fl_Window *w); extern void rename_windowmenuitem(const char *name, int rank); extern void delete_windowmenuitem(int rank); extern int find_windowmenuitem(Fl_Window *w); #endif /* globals */ static int page_x_offset = 0;// +/- quantity to add to all horizontal drawing coordinates static int page_y_offset = 0;// +/- quantity to add to all vertical drawing coordinates char *end_br_length; double physx,physy,physx_min,physy_min,physx_corr,physy_corr; /* window scaling variables */ double tek_xmin,tek_ymin,tek_dx,tek_dy; double maxx, maxy, nexty; int num_noeud, nextotu; char list_ps_font_name[3][15] = { "Helvetica", "Courier", "Times"}; extern Fl_Paged_Device::Page_Format printout_pageformat; // will contain the two end nodes of the root-containing branch static struct noeud *current_cote1=NULL, *current_cote2=NULL; static const char bad_tree[] = "Incorrect tree data."; static char *outotu=0, *inotu=0; static char *target1=0, *target2=0, *target3=0; // for -outgroup option Fl_Window *treedraw(char *trees, SEA_VIEW *view, const char *name, int from_tree_menu, int tree_count) /* returns the created window or NULL if none created tree_count: optional # of input trees in string trees */ { if (trees && tree_count == 1) tree_count = calc_tree_count(trees); FD_nj_plot *fd_nj_plot = (FD_nj_plot *)calloc(1, sizeof(FD_nj_plot)); fd_nj_plot->trees = trees; fd_nj_plot->current_tree = trees; fd_nj_plot->rank = 0; fd_nj_plot->view = view; #ifdef unix putenv((char *)"LC_NUMERIC=C"); #endif fd_nj_plot->swap = 0; fd_nj_plot->tree_name = NULL; fd_nj_plot->show_bootstrap = 0; fd_nj_plot->plot_br_l = 0; fd_nj_plot->choix = show_tree; fd_nj_plot->need_runtree = FALSE; Fl_Window *w = new Fl_Window(530, 530); w->xclass(TREE_WINDOW); Fl_Group *g = new Fl_Group(0, 0, 528, 50); Fl_Menu_Bar* menubar = new Fl_Menu_Bar(3, 3, 130, 20); menubar->user_data(fd_nj_plot); int left = menubar->x() + menubar->w() + 1; static const Fl_Menu_Item fileitems[] = { {"Save to Trees menu", 0, file_callback, NULL, 0}, {"Remove from Trees menu", 0, file_callback, NULL, 0}, {"Save rooted tree", 0, file_callback, NULL, 0}, {"Save unrooted tree", 0, file_callback, NULL, 0}, {"Save all trees", 0, file_callback, NULL, 0}, {"Save patristic distances", 0, patristic_callback, NULL, FL_MENU_DIVIDER}, {"Print", FL_COMMAND | 'p', file_callback, NULL, 0}, {"Save as "PDF_OR_PS"", 0, file_callback, NULL, 0}, {"Save as SVG", 0, file_callback, NULL, 0}, {"A4", 0, file_callback, NULL, FL_MENU_RADIO | 0}, {"Letter", 0, file_callback, NULL, FL_MENU_RADIO | 0}, {"Page count", 0, NULL, NULL, FL_SUBMENU | FL_MENU_DIVIDER}, {"1", 0, file_callback, NULL, FL_MENU_RADIO | FL_MENU_VALUE}, {"2", 0, file_callback, NULL, FL_MENU_RADIO}, {"3", 0, file_callback, NULL, FL_MENU_RADIO}, {"4", 0, file_callback, NULL, FL_MENU_RADIO}, {"5", 0, file_callback, NULL, FL_MENU_RADIO}, {"6", 0, file_callback, NULL, FL_MENU_RADIO}, {"7", 0, file_callback, NULL, FL_MENU_RADIO}, {"8", 0, file_callback, NULL, FL_MENU_RADIO}, {"9", 0, file_callback, NULL, FL_MENU_RADIO}, {"10", 0, file_callback, NULL, FL_MENU_RADIO}, {"11", 0, file_callback, NULL, FL_MENU_RADIO}, {"other value", 0, file_callback, NULL, 0}, {0}, {"Reorder following tree", 0, file_callback, NULL, 0}, {"Select in alignment", 0, file_callback, NULL, FL_MENU_INACTIVE | FL_MENU_DIVIDER}, {"Open tree or alignment", FL_COMMAND | 'o', file_callback, NULL, 0}, {"New window", FL_COMMAND | 'n', file_callback, NULL, 0}, {"Close window", FL_COMMAND | 'w', file_callback, NULL, 0} }; fd_nj_plot->menu_file = new vlength_menu(menubar, "File", fileitems, sizeof(fileitems)/sizeof(Fl_Menu_Item)); (fd_nj_plot->menu_file->get_menu() + (printout_pageformat == Fl_Paged_Device::A4 ? A4_format : letter_format))->setonly(); if(view == NULL || view->tot_seqs == 0) { (fd_nj_plot->menu_file->get_menu() + reorder_align_following_tree)->deactivate(); fd_nj_plot->menu_file->get_menu()->deactivate(); } if(!from_tree_menu) (fd_nj_plot->menu_file->get_menu() + remove_from_trees_menu)->deactivate(); fd_nj_plot->page_count = 1; static const Fl_Menu_Item edititems[] = { #ifdef MICRO {"Copy", FL_COMMAND | 'c', copy, NULL, 0}, #else {"Copy", 0, NULL, NULL, FL_MENU_INVISIBLE}, #endif {"Paste tree", FL_COMMAND | 'v', paste, NULL, 0}, {"Find", FL_COMMAND | 'f', search_callback, NULL, 0}, {"Again", FL_COMMAND | 'a', search_callback, NULL, 0}, {"Edit tree header", 0, edit_tree_header, NULL, 0}, {"Branch support threshold", 0, 0, NULL, FL_SUBMENU}, {"0", 0, NULL, NULL, FL_MENU_DIVIDER}, {"Edit threshold", 0, bt_threshold_callback, NULL, 0}, {0}, {"Root at tree center", 0, midpoint_callback, NULL, 0}, {"Get or Set Window size", 0, set_win_size_callback, NULL, FL_MENU_DIVIDER}, {"Edit tree shape", 0, edit_shape_callback, NULL, 0}, }; fd_nj_plot->center_rank = 9; fd_nj_plot->edit_shape_rank = 11; fd_nj_plot->menu_edit = new vlength_menu(menubar, "Edit", edititems, sizeof(edititems)/sizeof(Fl_Menu_Item)); fd_nj_plot->bootstrap_threshold = 0; static const Fl_Menu_Item fontitems[] = { // 1st item useful against FLTK bug when array of Fl_Menu_Item's begins with radio items {"invisible", 0, NULL, NULL, FL_MENU_INVISIBLE}, {"Helvetica", 0, change_ffam, NULL, FL_MENU_RADIO}, {"Courier", 0, change_ffam, NULL, FL_MENU_RADIO}, {"Times", 0, change_ffam, NULL, FL_MENU_RADIO | FL_MENU_DIVIDER | FL_MENU_VALUE}, {"Bold", 0, change_ffam, NULL, FL_MENU_TOGGLE}, {"Italic", 0, change_ffam, NULL, FL_MENU_TOGGLE | FL_MENU_DIVIDER}, {"8", 0, change_ffam, NULL, FL_MENU_RADIO}, {"10", 0, change_ffam, NULL, FL_MENU_RADIO}, {"12", 0, change_ffam, NULL, FL_MENU_RADIO | FL_MENU_VALUE}, {"14", 0, change_ffam, NULL, FL_MENU_RADIO}, {"16", 0, change_ffam, NULL, FL_MENU_RADIO}, {"18", 0, change_ffam, NULL, FL_MENU_RADIO}, {"24", 0, change_ffam, NULL, FL_MENU_RADIO}, }; fd_nj_plot->menu_font = new vlength_menu(menubar, "Font", fontitems, sizeof(fontitems)/sizeof(Fl_Menu_Item)); fd_nj_plot->l_button = new Fl_Check_Button(left,3,92, 20, "Br lengths"); fd_nj_plot->l_button->value(fd_nj_plot->plot_br_l); fd_nj_plot->bt_button = new Fl_Check_Button(fd_nj_plot->l_button->x() + fd_nj_plot->l_button->w() + 1,3,90, 20, "Br support"); fd_nj_plot->bt_button->value(fd_nj_plot->show_bootstrap); fd_nj_plot->root_unroot = new Fl_Choice(fd_nj_plot->bt_button->x() + fd_nj_plot->bt_button->w() + 2, fd_nj_plot->bt_button->y(), 98, 20, ""); fd_nj_plot->root_unroot->add("squared"); fd_nj_plot->root_unroot->add("circular"); fd_nj_plot->root_unroot->add("cladogram"); fd_nj_plot->root_unroot->value(0); fd_nj_plot->root_unroot->clear_visible_focus(); Fl_Button *help_button = new Fl_Button(g->w() - 52,3,50, 20, "Help"); help_button->callback(direct_help_callback, (void *)"Tree windows"); fd_nj_plot->full = new Fl_Round_Button(3,26,47, 20, "Full"); fd_nj_plot->full->type(FL_RADIO_BUTTON); fd_nj_plot->swap_button = new Fl_Round_Button(52,26,60, 20, "Swap"); fd_nj_plot->swap_button->type(FL_RADIO_BUTTON); fd_nj_plot->new_outgroup = new Fl_Round_Button(110,26,73, 20, "Re-root"); fd_nj_plot->new_outgroup->type(FL_RADIO_BUTTON); fd_nj_plot->select = new Fl_Round_Button(183,26,65, 20, "Select"); fd_nj_plot->select->type(FL_RADIO_BUTTON); fd_nj_plot->subtree = new Fl_Round_Button(248,26,75, 20, "Subtree"); fd_nj_plot->subtree->type(FL_RADIO_BUTTON); fd_nj_plot->full->setonly(); fd_nj_plot->up = new Fl_Button(323, 26, 90, 20, "Subtree Up"); fd_nj_plot->up->deactivate(); fd_nj_plot->zoom = new Fl_Simple_Counter(fd_nj_plot->up->x() + fd_nj_plot->up->w() + 45, fd_nj_plot->up->y(), 70, 20, "Zoom"); fd_nj_plot->zoom->callback(zoom_callback, fd_nj_plot); fd_nj_plot->zoom->align(FL_ALIGN_LEFT); fd_nj_plot->zoom->value(1.); fd_nj_plot->zoom->bounds(1., 100.); fd_nj_plot->zoom->step(0.4); fd_nj_plot->zoom->clear_visible_focus(); fd_nj_plot->zoomvalue = 1; fd_nj_plot->change_tree = new Fl_Simple_Counter(fd_nj_plot->root_unroot->x() + fd_nj_plot->root_unroot->w() + 5, fd_nj_plot->root_unroot->y(), 50, 20, ""); fd_nj_plot->change_tree->value(1); fd_nj_plot->change_tree->step(1); fd_nj_plot->change_tree->bounds(1, tree_count); fd_nj_plot->change_tree->callback(tree_counter_callback, fd_nj_plot); if (tree_count == 1) { fd_nj_plot->change_tree->hide(); (fd_nj_plot->menu_file->get_menu() + save_all_trees)->deactivate(); } g->end(); g->resizable(NULL); Fl_Box *down = new Fl_Box(FL_DOWN_FRAME, 4, 50, w->w()-8, w->h()-54, NULL); Fl_Window *w2 = (Fl_Window*)new Fl_Window(down->x()+3, down->y()+3, down->w()-6, down->h()-6); w->resizable(w2); w2->box(FL_FLAT_BOX); w2->color(FL_WHITE); fd_nj_plot->panel = new tree_panel(0, 0, w2->w(), w2->h()); fd_nj_plot->panel->user_data(fd_nj_plot); fd_nj_plot->root_unroot->callback(rooted_unrooted_callback, fd_nj_plot); fd_nj_plot->scroller = new Fl_Scrollbar(w2->w() - 15, fd_nj_plot->panel->y(), 15, fd_nj_plot->panel->h() #ifdef __APPLE__ - 5 #endif ); Fl_Box *b = new Fl_Box(0, 0, w2->w() - fd_nj_plot->scroller->w(), w2->h()); b->hide(); w2->resizable(b); fd_nj_plot->scroller->hide(); fd_nj_plot->scroller->callback(scroller_callback, fd_nj_plot); fd_nj_plot->scroller->bounds(0, 1); fd_nj_plot->scroller->linesize(1); fd_nj_plot->scroller->slider_size(1); ((Fl_Slider *)fd_nj_plot->scroller)->value(0); w2->end(); fd_nj_plot->l_button->callback(toggle_br_lengths, fd_nj_plot->panel); fd_nj_plot->bt_button->callback(toggle_bootstrap, fd_nj_plot->panel); fd_nj_plot->font_family = FL_TIMES; fd_nj_plot->font_size = 12; fd_nj_plot->full->callback(operation_callback, fd_nj_plot->panel); fd_nj_plot->swap_button->callback(operation_callback, fd_nj_plot->panel); fd_nj_plot->new_outgroup->callback(operation_callback, fd_nj_plot->panel); fd_nj_plot->select->callback(operation_callback, fd_nj_plot->panel); fd_nj_plot->subtree->callback(operation_callback, fd_nj_plot->panel); fd_nj_plot->up->callback(subtreeup_callback, fd_nj_plot->panel); w->end(); w->callback(treeplotw_callback, fd_nj_plot); if(name != NULL) { const char *mess; if( (mess = preptree(fd_nj_plot)) != NULL ) { fl_alert("%s", mess); fd_nj_plot->notu = 0; w->do_callback(); return NULL; } else { fd_nj_plot->need_runtree = TRUE; if(!fd_nj_plot->has_br_length) { fd_nj_plot->l_button->deactivate(); (fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->center_rank)->hide(); ((Fl_Menu_Item *)fd_nj_plot->root_unroot->menu() + 2)->hide(); } if(!fd_nj_plot->has_internal)fd_nj_plot->bt_button->deactivate(); (fd_nj_plot->menu_edit->get_menu() + 1)->deactivate(); fd_nj_plot->tree_name = strdup(name); } } else fd_nj_plot->tree_name = strdup("no tree"); w->copy_label(fd_nj_plot->tree_name); #if !(defined(__APPLE__) || defined(WIN32)) && SEAVIEW_FLTK_VERSION < 133 extern Fl_Offscreen seaview_X11_icon; w->icon( (void*)seaview_X11_icon ); #endif w->show(); #ifndef MICRO w->hotspot(w); #endif #ifdef __APPLE__ add_windowmenuitem(w->label(), w); #endif return w; } void tree_panel::draw(void) { static int old_w = 0; static int old_h = 0; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)this->user_data(); if(fd_nj_plot->notu == 0) return; fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size); fl_color(FL_BLACK); if(fd_nj_plot->need_runtree || this->w() != old_w || this->h() != old_h) { old_w = this->w(); old_h = this->h(); physx = this->w(); physy = this->h(); maxy = 1000.; runtree(fd_nj_plot); fd_nj_plot->need_runtree = FALSE; fd_nj_plot->swap = 0; } do_plot(fd_nj_plot, FALSE); } #ifdef MICRO extern void frame_and_draw_unrooted(FD_unrooted *fd_unrooted); static void copy(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); Fl_Widget *g; if(fd_nj_plot->fd_unrooted != NULL) g = ((FD_unrooted*)(fd_nj_plot->fd_unrooted))->unrooted_plot; else g = fd_nj_plot->panel; Fl_Surface_Device *current = Fl_Surface_Device::surface(); Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface( #ifdef __APPLE__ fd_nj_plot->fd_unrooted == NULL, #endif g->w(), g->h()); copy_surf->set_current(); if(fd_nj_plot->fd_unrooted != NULL) { frame_and_draw_unrooted((FD_unrooted *)fd_nj_plot->fd_unrooted); } else { g->draw(); } delete copy_surf; current->set_current(); } #endif // MICRO static void paste(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); Fl::paste(*fd_nj_plot->panel, 1); } char *prepare_ps_or_pdf_font(int font_num) { /* prepare PDF name of font */ static char current_ps_font[80]; int modulo = font_num % 4; int use_bold = modulo == 1 || modulo == 3; int use_italic = modulo >= 2; int fam_num = font_num/4; strcpy(current_ps_font, list_ps_font_name[fam_num]); if( use_bold && use_italic ) { if(fam_num == times) strcat(current_ps_font,"-BoldItalic"); else strcat(current_ps_font,"-BoldOblique"); } else if( use_bold ) strcat(current_ps_font,"-Bold"); else if( use_italic ) { if(fam_num == times) strcat(current_ps_font,"-Italic"); else strcat(current_ps_font,"-Oblique"); } else if(fam_num == times) strcat(current_ps_font,"-Roman"); return current_ps_font; } void toggle_br_lengths(Fl_Widget *wgt, void *data) { tree_panel *g = (tree_panel *)data; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)g->user_data(); fd_nj_plot->plot_br_l = ((Fl_Check_Button *)wgt)->value(); fd_nj_plot->need_runtree = TRUE; g->window()->redraw(); } void toggle_bootstrap(Fl_Widget *wgt, void *data) { tree_panel *g = (tree_panel *)data; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)g->user_data(); fd_nj_plot->show_bootstrap = ((Fl_Check_Button *)wgt)->value(); fd_nj_plot->need_runtree = TRUE; g->window()->redraw(); } void change_ffam(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); int val = ((Fl_Menu_*)wgt)->mvalue() - 1 - fd_nj_plot->menu_font->get_menu(); if(val < 3) fd_nj_plot->font_family = FL_HELVETICA + 4 * val; else if (val >= 5) sscanf( ((Fl_Menu_ *)wgt)->text(), "%d", &fd_nj_plot->font_size); fd_nj_plot->font_family = 4*(fd_nj_plot->font_family/4); const Fl_Menu_Item* menu = fd_nj_plot->menu_font->get_menu(); int bold = (menu[4].flags & FL_MENU_VALUE); int italic = (menu[5].flags & FL_MENU_VALUE); if(bold && italic) fd_nj_plot->font_family += 3; else if (bold) fd_nj_plot->font_family += 1; else if (italic) fd_nj_plot->font_family += 2; if( fd_nj_plot->fd_unrooted != NULL) { FD_unrooted *fd_unrooted = (FD_unrooted *)fd_nj_plot->fd_unrooted; fd_unrooted->current_font = fd_nj_plot->font_family; fd_unrooted->font_size = fd_nj_plot->font_size; fd_unrooted->comp_phys_bounds = TRUE; fd_unrooted->unrooted_plot->window()->redraw(); } else { fd_nj_plot->need_runtree = TRUE; fd_nj_plot->panel->window()->redraw(); } } int tree_panel::handle(int event) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)this->user_data(); const char *p; char *q; Fl_Window *w; int my = Fl::event_y(), count = 1; static int start_y; static int start_sy; static int changed_cursor = FALSE; switch (event) { case FL_PUSH: tree_click_proc(this, Fl::event_x(), Fl::event_y()); start_y = my; start_sy = fd_nj_plot->scroller->value(); break; case FL_DRAG: if(fd_nj_plot->zoomvalue > 1) { if(!changed_cursor) this->window()->cursor(FL_CURSOR_NS); changed_cursor = TRUE; int val = (int)fd_nj_plot->scroller->clamp(start_sy - (my - start_y) * fd_nj_plot->scroller->maximum() / (fd_nj_plot->zoomvalue - 1) / (this->h()-2.6*fd_nj_plot->char_height) ); ((Fl_Slider *)fd_nj_plot->scroller)->value(val); fd_nj_plot->scroller->do_callback(); } break; case FL_RELEASE: if(fd_nj_plot->zoomvalue > 1) { fl_reset_cursor(this->window()); changed_cursor = FALSE; } break; case FL_PASTE: p = Fl::event_text(); fd_nj_plot->trees = (char *)malloc(strlen(p) + 1); fd_nj_plot->current_tree = fd_nj_plot->trees; q = fd_nj_plot->trees; while(*p != 0) { if(*p != '\n' && *p != '\r') *q++ = *p; p++; } *q = 0; if(preptree(fd_nj_plot) != NULL) { fl_alert("Clipboard does not contain Newick-formatted tree"); break; } fd_nj_plot->need_runtree = TRUE; count = calc_tree_count(fd_nj_plot->trees); if(!fd_nj_plot->has_br_length) { fd_nj_plot->l_button->deactivate(); (fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->center_rank)->hide(); ((Fl_Menu_Item *)fd_nj_plot->root_unroot->menu() + 2)->hide(); } if(!fd_nj_plot->has_internal)fd_nj_plot->bt_button->deactivate(); (fd_nj_plot->menu_edit->get_menu() + 1)->deactivate(); fd_nj_plot->tree_name = strdup("pasted tree"); w = fd_nj_plot->full->window(); w->copy_label(fd_nj_plot->tree_name); #ifdef __APPLE__ rename_windowmenuitem(w->label(), find_windowmenuitem(w)); #endif if (count > 1) { fd_nj_plot->change_tree->show(); fd_nj_plot->change_tree->bounds(1, count); } fd_nj_plot->panel->window()->redraw(); break; default : return 0; // other events are not processed here } return 1; // from processed events } void scrollnotu(FD_nj_plot *fd_nj_plot) { int lines; float old; int count = fd_nj_plot->subtree_notu; old = fd_nj_plot->scroller->value() / (float)fd_nj_plot->scroller->maximum(); lines = (int)((count + 1) * (1 - 1/fd_nj_plot->zoomvalue) + 0.5); if(lines < 3) lines = 3; fd_nj_plot->scroller->maximum(lines); ((Fl_Slider *)fd_nj_plot->scroller)->value(old * lines); fd_nj_plot->scroller->slider_size(1/fd_nj_plot->zoomvalue); } void zoom_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; if(((Fl_Counter *)wgt)->value() > fd_nj_plot->zoomvalue) fd_nj_plot->zoomvalue *= 1.4; else fd_nj_plot->zoomvalue /= 1.4; fd_nj_plot->zoomvalue = ((Fl_Counter *)wgt)->clamp(fd_nj_plot->zoomvalue); ((Fl_Counter *)wgt)->value(fd_nj_plot->zoomvalue); if(fd_nj_plot->zoomvalue <= 1.1) { fd_nj_plot->panel->size(fd_nj_plot->panel->parent()->w(), fd_nj_plot->panel->h()); fd_nj_plot->scroller->hide(); } else { fd_nj_plot->panel->size(fd_nj_plot->panel->parent()->w() - 15, fd_nj_plot->panel->h()); fd_nj_plot->scroller->show(); } scrollnotu(fd_nj_plot); fd_nj_plot->panel->parent()->redraw(); } void scroller_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; fd_nj_plot->panel->parent()->redraw(); } static void patristic_callback(Fl_Widget *wgt, void *unused) { char *outfname, *p; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); outfname = new char[strlen(fd_nj_plot->tree_name)+10]; strcpy(outfname, fd_nj_plot->tree_name); p = strrchr(outfname, '.'); if (!p) p = outfname + strlen(outfname); strcpy(p, ".dist"); chooser->preset_file(outfname); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Choose filename to store patristic distances"); char *filename = run_and_close_native_file_chooser(chooser); delete[] outfname; if (filename == NULL) return; FILE *out = fopen(filename, "w"); if (!out) return; calc_patristic_distances(fd_nj_plot, out); fclose(out); } static void file_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); Fl_Menu_Item *item = fd_nj_plot->menu_file->get_menu(); int reponse = ((Fl_Menu_*)wgt)->mvalue() - item; if(reponse == save_to_trees_menu) {//save to tree menu add_to_tree_menu(fd_nj_plot); } else if(reponse == remove_from_trees_menu) {//remove from tree menu remove_from_tree_menu(fd_nj_plot, wgt->window()->label()); } else if(reponse == save_rooted || reponse == save_unrooted) {//save to file int saved_notu = fd_nj_plot->subtree_center != NULL ? fd_nj_plot->subtree_notu : fd_nj_plot->notu; if( (reponse == save_rooted && saved_notu < 2) || (reponse == save_unrooted && saved_notu < 3) ) return; Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Set tree filename"); chooser->preset_file(fd_nj_plot->tree_name); char *filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; struct noeud *center = fd_nj_plot->subtree_center != NULL ? fd_nj_plot->subtree_center : fd_nj_plot->racine; char *tree; if(reponse == save_rooted) tree = ecrit_arbre_parenth(fd_nj_plot, center); else tree = ecrit_arbre_parenth_unrooted(fd_nj_plot, center); FILE *out = fopen(filename, "w"); if(out) { fputs(tree, out); fputs("\n", out); fclose(out); free(tree); } else fl_alert("Incorrect output filename: %s", filename); } else if (reponse == save_all_trees) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Set multiple-tree filename"); chooser->preset_file(fd_nj_plot->tree_name); char *filename = run_and_close_native_file_chooser(chooser); if (filename == NULL) return; FILE *out = fopen(filename, "w"); if (out) { char *p = fd_nj_plot->trees; while (*p) { fputc(*p, out); if (*p == ';') fputc('\n', out); p++; } fclose(out); } } else if(reponse == print_tree) {//print print_plot(fd_nj_plot, false); } else if(reponse == save_as_ps_pdf) {//save to PDF/PS print_plot(fd_nj_plot, true); } else if(reponse == save_as_svg) {// SVG extern void svg_tree_dialog_and_save(FD_nj_plot *fd_nj_plot); svg_tree_dialog_and_save(fd_nj_plot); } else if(reponse == A4_format) {// A4 printout_pageformat = Fl_Paged_Device::A4; } else if(reponse == letter_format) {// Letter printout_pageformat = Fl_Paged_Device::LETTER; } else if(reponse >= page_count+1 && reponse <= page_count+12) {// page counts if(reponse >= page_count+1 && reponse <= page_count+10) {// fixed page counts fd_nj_plot->page_count = reponse - page_count; } else if(reponse == page_count+11) {// variable page count sscanf((item + page_count+11)->label(), "%d", &fd_nj_plot->page_count); } else if(reponse == page_count+12) { int newval; const char *reply = fl_input("Enter page count (>= 11)", "11"); if(reply == NULL) return; sscanf(reply, "%d", &newval); if(newval >= 1) fd_nj_plot->page_count = newval; if(newval >= 11) { if (strcmp((item + page_count + 11)->label(), "11") != 0) free((void*)(item + page_count + 11)->label()); (item + page_count + 11)->label(strdup(reply)); (item + page_count + 11)->setonly(); } else if(newval >= 1) { (item + page_count + fd_nj_plot->page_count)->setonly(); } } char tmp[20]; sprintf(tmp, "Page count (%d)", fd_nj_plot->page_count); if (strcmp((item + page_count)->label(), "Page count") != 0) free((void*)(item + page_count)->label()); (item + page_count)->label(strdup(tmp)); } else if(reponse == reorder_align_following_tree) { reorder_following_tree(fd_nj_plot->racine, fd_nj_plot->notu, fd_nj_plot->view); } else if(reponse == select_seqs_in_alignment) { select_in_alignment(fd_nj_plot); } else if(reponse == open_tree_or_align) {//open tree/alignment Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); chooser->title("Choose a Newick tree or alignment file"); char *filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; Fl_Window *w = use_initial_file(fd_nj_plot->view, filename, FALSE); //close the opening window if it was empty and a new tree window was successfully created const char *c; if(w != NULL && fd_nj_plot->notu == 0 && (c = w->xclass()) != NULL && strcmp(c, TREE_WINDOW) == 0) fd_nj_plot->full->window()->do_callback(); } else if(reponse == new_window) {//new tree window treedraw(NULL, fd_nj_plot->view, NULL, FALSE); } else if(reponse == close_window) {//close wgt->window()->do_callback(); } } void remove_from_tree_menu(FD_nj_plot *fd_nj_plot, const char *name) { SEA_VIEW *view = fd_nj_plot->view; if(view == NULL) return; vlength_menu *menu_trees = view->menu_trees; Fl_Menu_Item *item; Fl_Menu_Item *items = menu_trees->vitem(0); if( (item = menu_trees->find_item(name)) == NULL) return; int rank = item - items; menu_trees->remove(rank); items = fd_nj_plot->menu_file->get_menu(); items->activate(); (items + remove_from_trees_menu)->deactivate(); free(view->trees[rank]); (view->tot_trees)--; for(int i = rank; i < view->tot_trees; i++) view->trees[i] = view->trees[i + 1]; if(view->tot_trees == 0) free(view->trees); } void add_to_tree_menu(FD_nj_plot *fd_nj_plot) { SEA_VIEW *view = fd_nj_plot->view; char *p, *fulltree; if(view == NULL) return; char *name = fd_nj_plot->tree_name; vlength_menu *menu_trees = view->menu_trees; name = (char *)fl_input("Enter tree name:", name); if(name == NULL) return; free(fd_nj_plot->tree_name); char *newname = NULL; int count=2; if( menu_trees->find_item(name) != NULL) {//check if same name already exists newname = new char[strlen(name) + 5]; do sprintf(newname, "%s_%d", name, count++); while( menu_trees->find_item(newname) != NULL); name = newname; } fd_nj_plot->tree_name = strdup(name); fd_nj_plot->full->window()->copy_label(fd_nj_plot->tree_name); menu_trees->add(name, trees_callback, NULL, 0); int rank = menu_trees->vlength(); menu_trees->vitem(rank - 1)->labelfont(FL_HELVETICA_ITALIC); if(newname != NULL) delete[] newname; if(view->tot_trees == 0) view->trees = (char **)malloc(sizeof(char *)); else view->trees = (char **)realloc(view->trees, (view->tot_trees + 1) * sizeof(char *)); if (fd_nj_plot->change_tree->visible()) { fulltree = strdup(fd_nj_plot->trees); } else { p = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); if(fd_nj_plot->tree_label != NULL) { fulltree = (char *)malloc(strlen(p) + strlen(fd_nj_plot->tree_label) + 3); sprintf(fulltree, "[%s]%s", fd_nj_plot->tree_label, p); free(p); } else fulltree = p; } view->trees[view->tot_trees] = fulltree; view->tot_trees++; (fd_nj_plot->menu_file->get_menu() + remove_from_trees_menu)->activate(); } void treeplotw_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; if(fd_nj_plot->fd_unrooted != NULL) { FD_unrooted *fd_unrooted = (FD_unrooted *)fd_nj_plot->fd_unrooted; free_unrooted(fd_unrooted); } if(fd_nj_plot != NULL) { free_tree(fd_nj_plot); delete fd_nj_plot->menu_file; delete fd_nj_plot->menu_edit; delete fd_nj_plot->menu_font; free(fd_nj_plot); } #ifdef __APPLE__ int rank = find_windowmenuitem((Fl_Window *)wgt); if(rank > 0) delete_windowmenuitem(rank); #endif //when a callback destroys its own widget delete is bad; hide()+Fl::delete_widget is to be called instead wgt->hide(); Fl::delete_widget(wgt); } void subtreeup_callback(Fl_Widget *wgt, void *data) { tree_panel *g = (tree_panel *)data; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)g->user_data(); fd_nj_plot->subtree_center = fd_nj_plot->subtree_ascend; fd_nj_plot->subtree_ascend = fd_nj_plot->subtree_center->v3; if(fd_nj_plot->subtree_ascend == NULL) { fd_nj_plot->subtree_center = NULL; wgt->deactivate(); fd_nj_plot->new_outgroup->activate(); ((Fl_Menu_Item *)fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->center_rank)->activate(); fd_nj_plot->full->setonly(); (fd_nj_plot->menu_file->get_menu()+reorder_align_following_tree)->activate(); (fd_nj_plot->menu_file->get_menu()+select_seqs_in_alignment)->deactivate(); fd_nj_plot->subtree_notu = fd_nj_plot->notu; if(fd_nj_plot->root_unroot != NULL) fd_nj_plot->root_unroot->activate(); fd_nj_plot->change_tree->activate(); (fd_nj_plot->menu_file->get_menu()+save_rooted)->label("Save rooted tree"); (fd_nj_plot->menu_file->get_menu()+save_unrooted)->label("Save unrooted tree"); } else fd_nj_plot->subtree_notu = calc_n_desc(fd_nj_plot->subtree_center); fd_nj_plot->need_runtree = TRUE; fd_nj_plot->swap_button->value(0); fd_nj_plot->subtree->value(0); fd_nj_plot->select->value(0); fd_nj_plot->choix = show_tree; if(fd_nj_plot->has_internal) fd_nj_plot->bt_button->activate(); if(fd_nj_plot->has_br_length) fd_nj_plot->l_button->activate(); if(fd_nj_plot->select_clade_button != NULL) fd_nj_plot->select_clade_button->activate(); g->window()->redraw(); } void operation_callback(Fl_Widget *wgt, void *data) { tree_panel *g = (tree_panel *)data; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)g->user_data(); ((Fl_Button *)wgt)->setonly(); if(wgt == fd_nj_plot->swap_button) { fd_nj_plot->choix = permutation; fd_nj_plot->show_bootstrap = FALSE; fd_nj_plot->plot_br_l = FALSE; fd_nj_plot->l_button->deactivate(); fd_nj_plot->l_button->value(0); fd_nj_plot->bt_button->deactivate(); fd_nj_plot->bt_button->value(0); if(fd_nj_plot->select_clade_button != NULL) fd_nj_plot->select_clade_button->activate(); } else if(wgt == fd_nj_plot->new_outgroup) { fd_nj_plot->choix = depl_racine; fd_nj_plot->show_bootstrap = FALSE; fd_nj_plot->plot_br_l = FALSE; fd_nj_plot->l_button->deactivate(); fd_nj_plot->l_button->value(0); fd_nj_plot->bt_button->deactivate(); fd_nj_plot->bt_button->value(0); (fd_nj_plot->menu_file->get_menu()+reorder_align_following_tree)->deactivate(); // Re-order following tree } else if(wgt == fd_nj_plot->subtree) { fd_nj_plot->choix = subtree; fd_nj_plot->show_bootstrap = FALSE; fd_nj_plot->plot_br_l = FALSE; ((Fl_Menu_Item *)fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->center_rank)->deactivate(); fd_nj_plot->new_outgroup->deactivate(); fd_nj_plot->l_button->deactivate(); fd_nj_plot->l_button->value(0); fd_nj_plot->bt_button->deactivate(); fd_nj_plot->bt_button->value(0); fd_nj_plot->change_tree->deactivate(); if(fd_nj_plot->root_unroot != NULL) fd_nj_plot->root_unroot->deactivate(); } else if(wgt == fd_nj_plot->select) { fd_nj_plot->choix = selection; fd_nj_plot->l_button->deactivate(); fd_nj_plot->l_button->value(0); fd_nj_plot->bt_button->deactivate(); fd_nj_plot->bt_button->value(0); fd_nj_plot->show_bootstrap = FALSE; fd_nj_plot->plot_br_l = FALSE; (fd_nj_plot->menu_file->get_menu()+reorder_align_following_tree)->deactivate(); // Re-order following tree } else {//full fd_nj_plot->choix = show_tree; fd_nj_plot->subtree_notu = fd_nj_plot->notu; if(fd_nj_plot->subtree_center != NULL) scrollnotu(fd_nj_plot); fd_nj_plot->subtree_center = NULL; fd_nj_plot->new_outgroup->activate(); ((Fl_Menu_Item *)fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->center_rank)->activate(); fd_nj_plot->up->deactivate(); if(fd_nj_plot->view != NULL) (fd_nj_plot->menu_file->get_menu()+reorder_align_following_tree)->activate(); (fd_nj_plot->menu_file->get_menu()+select_seqs_in_alignment)->deactivate(); if(fd_nj_plot->has_internal) fd_nj_plot->bt_button->activate(); if(fd_nj_plot->has_br_length) fd_nj_plot->l_button->activate(); if(fd_nj_plot->root_unroot != NULL) fd_nj_plot->root_unroot->activate(); fd_nj_plot->change_tree->activate(); (fd_nj_plot->menu_file->get_menu()+save_rooted)->label("Save rooted tree"); (fd_nj_plot->menu_file->get_menu()+save_unrooted)->label("Save unrooted tree"); } fd_nj_plot->need_runtree = TRUE; g->window()->redraw(); } void select_clade(struct noeud *n, SEA_VIEW *view, int on) /* select (on is true) or deselect (on is false) all seqs in alignment placed below node n in tree */ { if (n == NULL) return; select_clade(n->v1, view, on); select_clade(n->v2, view, on); char *p = n->nom; if (n->v1 == NULL) { // a leaf int num; for ( num = 0; num < view->tot_seqs; num++) { // find what sequence it is in alignment if (strcmp(p + 1, view->seqname[num]) == 0) { if ((view->sel_seqs[num] && !on) || (!view->sel_seqs[num] && on)) select_deselect_seq(view, num+1, TRUE); break; } } } if (*p) *p = (on ? '(' : ')'); } void tree_click_proc(tree_panel *panel, int mx, int my) { double eps, x, y, epsx, epsy, px, py; int i, found=0, node_num; FD_nj_plot *fd_nj_plot = (FD_nj_plot *) panel->user_data(); if(fd_nj_plot->notu == 0) return; if(fd_nj_plot->choix != permutation && fd_nj_plot->choix != depl_racine && fd_nj_plot->choix != subtree && fd_nj_plot->choix != selection &&fd_nj_plot->choix != prune_clade && fd_nj_plot->choix != prune_clade_found) return; eps = fd_nj_plot->char_height/2.; x = mx - panel->x(); my -= panel->y(); y = panel->h() - my; //next 5 statements so that physic_to_logic apply to the clicked window tek_dx = fd_nj_plot->tek_dx; tek_dy = fd_nj_plot->tek_dy; tek_ymin = fd_nj_plot->tek_ymin; physx_min = fd_nj_plot->ascent; physy_min = 0.6 * fd_nj_plot->char_height; physic_to_logic(x, y, &x, &y); epsx = eps / tek_dx; epsy = eps / tek_dy; for(i=0; i<=fd_nj_plot->totpoints; i++ ) { px = (fd_nj_plot->points+i)->x; py = (fd_nj_plot->points+i)->y; if(x < px || x > px + epsx) continue; if(y < py - epsy/2 || y > py + epsy/2) continue; found=1; break; } if(!found)return; node_num=(fd_nj_plot->points+i)->number; if(fd_nj_plot->choix==depl_racine) { if(node_num >= 0 && node_num <= 2*fd_nj_plot->notu - 3 && node_num != fd_nj_plot->root_num) { fd_nj_plot->root_num = node_num; removeroot(fd_nj_plot); } } else if(fd_nj_plot->choix==permutation) { if(node_num >= fd_nj_plot->notu && node_num <= 2*fd_nj_plot->notu - 2) fd_nj_plot->swap = node_num; else fd_nj_plot->swap = 0; } else if(fd_nj_plot->choix==subtree) { if(node_num < fd_nj_plot->notu || node_num > 2*fd_nj_plot->notu - 2) return; fd_nj_plot->subtree_center = fd_nj_plot->tabtax[node_num]; fd_nj_plot->subtree_ascend = fd_nj_plot->subtree_center->v3; fd_nj_plot->subtree_notu = calc_n_desc(fd_nj_plot->subtree_center); scrollnotu(fd_nj_plot); fd_nj_plot->choix = show_tree; fd_nj_plot->subtree->value(0); fd_nj_plot->up->activate(); if(fd_nj_plot->select_clade_button != NULL) fd_nj_plot->select_clade_button->activate(); if(fd_nj_plot->has_br_length) { fd_nj_plot->l_button->activate(); } if(fd_nj_plot->has_internal) { fd_nj_plot->bt_button->activate(); } (fd_nj_plot->menu_file->get_menu()+reorder_align_following_tree)->deactivate(); (fd_nj_plot->menu_file->get_menu()+select_seqs_in_alignment)->activate(); (fd_nj_plot->menu_file->get_menu()+save_rooted)->label("Save rooted subtree"); (fd_nj_plot->menu_file->get_menu()+save_unrooted)->label("Save unrooted subtree"); } else if(fd_nj_plot->choix == selection) { SEA_VIEW *view = fd_nj_plot->view; if (!view) return; if(node_num >= fd_nj_plot->notu && node_num <= 2*fd_nj_plot->notu - 2) { int on = fd_nj_plot->tabtax[node_num]->nom[0] == ')'; select_clade(fd_nj_plot->tabtax[node_num], view, on); view->DNA_obj->redraw(); panel->window()->redraw(); return; } for (int num = 0; num < view->tot_seqs; num++) { if (strcmp(fd_nj_plot->tabtax[node_num]->nom + 1, view->seqname[num]) == 0) { select_deselect_seq(view, num+1, TRUE); fd_nj_plot->tabtax[node_num]->nom[0] = (view->sel_seqs[num] ? '(' : ')'); extern void set_and_show_new_cursor_seq(SEA_VIEW *view, int new_pos); if (num+1 < view->first_seq || num+1 >= view->first_seq + view->tot_lines) set_and_show_new_cursor_seq(view, num+1); view->DNA_obj->redraw(); panel->window()->redraw(); break; } } return; } else if(fd_nj_plot->choix==prune_clade) { fd_nj_plot->prune_clade_node = fd_nj_plot->tabtax[node_num]; fd_nj_plot->choix = prune_clade_found; fd_nj_plot->select_clade_button->activate(); fd_nj_plot->delete_clade_button->activate(); } else if(fd_nj_plot->choix==prune_clade_found) { struct noeud *sister, *parent, *gparent;//move selected clade to its target branch parent = fd_nj_plot->prune_clade_node->v3; sister = parent->v1 == fd_nj_plot->prune_clade_node ? parent->v2 : parent->v1; gparent = parent->v3; if(gparent != NULL) { if(gparent->v1 == parent) { gparent->v1 = sister; gparent->l1 = 1; } else { gparent->v2 = sister; gparent->l2 = 1; } sister->v3 = gparent; sister->l3 = 1; gparent = fd_nj_plot->tabtax[node_num]->v3; parent->v1 = fd_nj_plot->prune_clade_node; parent->l1 = 1; fd_nj_plot->prune_clade_node->v3 = parent; fd_nj_plot->prune_clade_node->l3 = 1; parent->v2 = fd_nj_plot->tabtax[node_num]; parent->l2 = 1; fd_nj_plot->tabtax[node_num]->v3 = parent; fd_nj_plot->tabtax[node_num]->l3 = 1; parent->v3 = gparent; parent->l3 = 1; if(gparent->v1 == fd_nj_plot->tabtax[node_num]) { gparent->v1 = parent; gparent->l1 = 1; } else { gparent->v2 = parent; gparent->l2 = 1; } } else { parent->v1 = sister->v1; parent->l1 = 1; parent->v2 = sister->v2; parent->l2 = 1; parent->v1->v3 = parent; parent->v1->l3 = 1; parent->v2->v3 = parent; parent->v2->l3 = 1; gparent = fd_nj_plot->tabtax[node_num]->v3; if(gparent->v1 == fd_nj_plot->tabtax[node_num]) { gparent->v1 = sister; gparent->l1 = 1;} else { gparent->v2 = sister; gparent->l2 = 1;} sister->v3 = gparent; sister->l3 = 1; sister->v1 = fd_nj_plot->prune_clade_node; sister->l1 = 1; sister->v2 = fd_nj_plot->tabtax[node_num]; sister->l2 = 1; fd_nj_plot->prune_clade_node->v3 = sister; fd_nj_plot->prune_clade_node->l3 = 1; fd_nj_plot->tabtax[node_num]->v3 = sister; fd_nj_plot->tabtax[node_num]->l3 = 1; } calc_brl_for_lengthless(fd_nj_plot->racine, NULL); } fd_nj_plot->need_runtree = TRUE; panel->window()->redraw(); } double length_log_phys(double p) { return p * tek_dx; } double length_phys_log(double p) { return p / tek_dx; } double arrondi_echelle(double x) { /* arrondi x a une valeur 1, 2, 5 pour echelle */ double l, n; int r; static int corresp[] = {1,1,2,2,5,5,5,10,10,10,10,10}; /* 0,1,2,3,4,5,6, 7, 8, 9,10,11 */ l = log10(x); n = floor(l); l = x * pow(10., -n); /* 10. plutot que 10 necessaire pour alpha! */ r = myrint(l); r = corresp[r]; return r * pow(10., n); /* 10. plutot que 10 necessaire pour alpha! */ } void scale_window(double lxmin, double lxmax, double lymin, double lymax, double pxmin, double pxmax, double pymin, double pymax) /* to scale the plot window for logical coords l... in physical coords p... */ { tek_xmin=lxmin; tek_ymin=lymin; tek_dx = (pxmax-pxmin)/(lxmax-tek_xmin < 1e-4 ? 1e-4 : lxmax-tek_xmin); tek_dy = (pymax-pymin)/(lymax-tek_ymin); } void ch_echelle(double lx, double ly, double *px, double *py) /* conversion coord logique lx,ly en coord physique px,py */ { *px = (lx-tek_xmin)*tek_dx + physx_min; *py = (ly-tek_ymin)*tek_dy + physy_min; } void physic_to_logic(double px, double py, double *lx, double *ly) /* conversion coord physique px,py en coord logique lx,ly */ { *lx = (px - physx_min)/tek_dx + tek_xmin; *ly = (py - physy_min)/tek_dy + tek_ymin; } double calc_echelle(double larg) { /* rend taille logique pour echelle optimale */ double log_val, phys_val; phys_val = larg/10; log_val = length_phys_log(phys_val); log_val = arrondi_echelle(log_val); return log_val; } void draw_scale(FD_nj_plot *fd_nj_plot) { char ech_name[20]; double phys_w, y, xd, xf, lc; double log_val; y = physy - 1.1 * fd_nj_plot->char_height; if(fd_nj_plot->choix == prune_clade) { fl_color(FL_RED); dir_moveto( physx * 0.01, y ); //sd be placed here to avoid pdf error plotstring("Click on a square to select sequence group or \"End edit\"."); fl_color(FL_BLACK); } else if(fd_nj_plot->choix == prune_clade_found) { fl_color(FL_BLUE); dir_moveto( physx * 0.01, y ); plotstring("Click on a square to move selection or \"Select group|Delete group|End edit\"."); fl_color(FL_BLACK); } else if(fd_nj_plot->tree_label != NULL) { dir_moveto( physx * 0.01, y ); plotstring(fd_nj_plot->tree_label); } log_val = calc_echelle(physx); phys_w = myrint(length_log_phys(log_val)); fl_font(FL_TIMES, 12); y = physy - 1.1 * 12; xf = physx * 0.95; xd = xf - phys_w; sprintf(ech_name, "%.1g", log_val); lc = calc_text_size(ech_name, NULL, NULL); if(fd_nj_plot->has_br_length) { dir_moveto(xd, y); dir_lineto(xf, y); dir_moveto(xd, y - 4); dir_lineto(xd, y + 4); dir_moveto(xf, y - 4); dir_lineto(xf, y + 4); dir_moveto( (xd + xf)/2 - lc/2, y + 2 ); plotstring(ech_name); } } void do_plot(FD_nj_plot *fd_nj_plot, int doing_print) { struct trait *p; int num; double factor, value, m = 1, v = 0, zoom = 1; if(! doing_print) { /* size of the tree plot window */ v = fd_nj_plot->scroller->value(); m = fd_nj_plot->scroller->maximum(); zoom = fd_nj_plot->zoomvalue; } factor = 1e99; for(num=0; numnotu; num++) { if(fd_nj_plot->profs[num] <= 0) continue; value = (physx - fd_nj_plot->widnames[num] - 2 * fd_nj_plot->ascent) / fd_nj_plot->profs[num]; if(value < factor) factor = value; } physx_min = fd_nj_plot->ascent; physx_corr = maxx * factor + physx_min; if(physx_corr <= physx_min + 1) { physx_corr = physx_min + 1; } physy_corr = physy - 2 * fd_nj_plot->char_height; physy_min = 0.6 * fd_nj_plot->char_height; scale_window(0, maxx, ((m-v)/m) * (maxy - maxy/zoom), ((m-v)/m) * (maxy - maxy/zoom) + maxy/zoom, physx_min, physx_corr, physy_min, physy_corr); fd_nj_plot->tek_dx = tek_dx; fd_nj_plot->tek_dy = tek_dy; fd_nj_plot->tek_ymin = tek_ymin; for(num=0; num<=fd_nj_plot->totnoms; num++) { mydrawstring( (fd_nj_plot->noms+num)->x, (fd_nj_plot->noms+num)->y , (fd_nj_plot->noms+num)->nom, (fd_nj_plot->noms+num)->disp_option, fd_nj_plot->char_height ); } for(num=0; num<=fd_nj_plot->tottraits; num++) { p= fd_nj_plot->traits+num; moveto(p->xd,p->yd); fl_line_style(0, p->width); lineto(p->xf,p->yf); } if(fd_nj_plot->choix == prune_clade_found) {//redraw in color the prune clade subtree fl_color(FL_RED); for(num=fd_nj_plot->colored_names_1; num<=fd_nj_plot->colored_names_2; num++) { mydrawstring( (fd_nj_plot->noms+num)->x, (fd_nj_plot->noms+num)->y , (fd_nj_plot->noms+num)->nom, (fd_nj_plot->noms+num)->disp_option, fd_nj_plot->char_height ); } for(num=fd_nj_plot->colored_traits_1; num<=fd_nj_plot->colored_traits_2; num++) { p= fd_nj_plot->traits+num; moveto(p->xd,p->yd); fl_line_style(0, 0); lineto(p->xf,p->yf); } fl_color(FL_BLACK); } /* echelle */ fl_line_style(0, 0); draw_scale(fd_nj_plot); } /* end of do_plot */ int calc_text_size(char *text, int *pheight, int *pascent) { int width, height, ascent; width = (int)fl_width(text); height = fl_height(); ascent = fl_height() - fl_descent(); if(pheight != NULL) *pheight = height; if(pascent != NULL) *pascent = ascent; return width; } static int moveto_x, moveto_y; void plotstring(const char *nom) { fl_draw(nom, moveto_x, moveto_y); } void dir_moveto(double x,double y) /* move to physical coord x,y */ { moveto_x = myrint(x); // moveto_y = myrint(y); moveto_x += page_x_offset; moveto_y = myrint(page_y_offset + physy - y); } void dir_lineto(double x,double y) /* draw line from current pos to physical coord x,y */ { int yi = myrint(page_y_offset + physy - y); fl_line(moveto_x, moveto_y, myrint(page_x_offset + x), yi); } void dir_plotsquare(double x, double y, int edge, int use_color) { y += edge/2; int xi = (int)(page_x_offset + x + 0.5); int yi = (int)(page_y_offset + physy - (y + 0.5)); if (use_color) fl_color(FL_RED); fl_rectf(xi, yi, edge, edge); if (use_color) fl_color(FL_BLACK); } //struct noeud *gracine; const char *preptree(FD_nj_plot *fd_nj_plot) { int i, c, maxlname, v; char *arbre, *finarbre; char *last_bootstrap, *p, *q; arbre = strdup(fd_nj_plot->current_tree); /* lecture de l'arbre et de son label entre [] */ p = arbre; while(isspace(*p)) p++; if(*p == '[') { q = p; do q++; while(*q != ']'); if(q > p + 1) { *q = 0; fd_nj_plot->tree_label = (char *)malloc(q - p); strcpy(fd_nj_plot->tree_label, p + 1); } p = q + 1; while(isspace(*p)) p++; } fd_nj_plot->notu = 2; i = 3; v = 0; if(*p == '(') { if(p > arbre) memmove(arbre, p, strlen(p) + 1); p = arbre + 1; while( (c=*(p++)) != 0 && c != ';') { if(c == ')') fd_nj_plot->notu++; if(c == '(') i++; if(c == ',') v++; } } if(i != fd_nj_plot->notu) { free(arbre); fd_nj_plot->notu = 0; return bad_tree; } finarbre = nextpar(arbre); if(finarbre == NULL) { fd_nj_plot->notu = 0; return ("Unbalanced parentheses in tree."); } finarbre++; /* memorize bootstrap value after last ) */ while(isspace(*finarbre)) finarbre++; if(*finarbre != ';' && *finarbre != 0) { last_bootstrap = strdup(finarbre); p = strchr(last_bootstrap, ';'); if(p != NULL) *p = 0; } else last_bootstrap = NULL; arbre = (char *)realloc(arbre, strlen(arbre) + 4 * v + 5 ); /* worst case add 4 chars for each , */ p = (char *)make_binary_or_unrooted(arbre); if(p != NULL) { fd_nj_plot->notu = 0; free(arbre); return p; } fd_nj_plot->long_arbre_parenth = strlen(arbre); fd_nj_plot->notu = v + 1 ; /* after this fd_nj_plot->notu = number of OTUs */ fd_nj_plot->totbranches= -1; /* allocate all memory */ fd_nj_plot->tabtax = (struct noeud **)check_alloc(2*fd_nj_plot->notu - 1,sizeof(struct noeud *)); fd_nj_plot->branches = (branche *)check_alloc(fd_nj_plot->notu - 1, sizeof(branche)); for(i=0; i<2*fd_nj_plot->notu - 1; i++) *(fd_nj_plot->tabtax+i)= (struct noeud *)check_alloc(1,s_noeud); fd_nj_plot->noms = (struct nom *)check_alloc(5*(fd_nj_plot->notu-1)+1,sizeof(struct nom)); fd_nj_plot->points = (struct mon_point *)check_alloc(2*(fd_nj_plot->notu-1)+1,sizeof(struct mon_point)); fd_nj_plot->traits = (struct trait *)check_alloc(3*(fd_nj_plot->notu-1),sizeof(struct trait)); fd_nj_plot->labels = (char **)check_alloc(fd_nj_plot->notu, sizeof(char *)); fd_nj_plot->widnames = (int *)check_alloc(fd_nj_plot->notu, sizeof(int)); fd_nj_plot->profs = (double *)check_alloc(fd_nj_plot->notu, sizeof(double)); fd_nj_plot->br_length_txt = (char *)check_alloc(2*(fd_nj_plot->notu - 1),10); p = (char *)loadphylip(fd_nj_plot, arbre, last_bootstrap); free(arbre); if(p != NULL) return p; maxlname = 0; /* largeur max des noms des feuilles */ if(nextotu != fd_nj_plot->notu - 1) return bad_tree; for(i = 0; i <= nextotu; i++) { c = strlen(fd_nj_plot->labels[i]); if(c > maxlname) maxlname = c; } for(i = 0; i < 2*fd_nj_plot->notu - 1; i++) { fd_nj_plot->tabtax[i]->nom = (char *)check_alloc(maxlname + 2 + 1, 1); /*2=place pour ) */ fd_nj_plot->tabtax[i]->rank = i; } if ( (outotu || inotu) && fd_nj_plot->rooted && fd_nj_plot->has_br_length ) { // with -outgroup or -ingroup option but rooted struct noeud *root = *(fd_nj_plot->tabtax+num_noeud); // unroot the rooted tree root->v1->v3 = root->v2; root->v1->l3 = root->l1 + root->l2; root->v2->v3 = root->v1; root->v2->l3 = root->l1 + root->l2; num_noeud--; fd_nj_plot->rooted = FALSE; } if (!fd_nj_plot->rooted) { fd_nj_plot->racine = *(fd_nj_plot->tabtax+(++num_noeud)); //gracine = fd_nj_plot->racine; if (num_noeud >= 2*fd_nj_plot->notu - 1) return bad_tree; if (fd_nj_plot->has_br_length) { struct noeud *node = NULL; if (outotu || inotu) { // with -outgroup or -ingroup option for (i = 0; i < fd_nj_plot->notu; i++) { strcpy(fd_nj_plot->tabtax[i]->nom, fd_nj_plot->labels[i]); } if (target3) { // with 3 outgroup labels node = span_nodes(fd_nj_plot->tabtax[0], NULL); // search central node } else { // with 1 outgroup leaf for (i = 0; i < fd_nj_plot->notu; i++) { // search node with outgroup leaf if (strcmp(fd_nj_plot->tabtax[i]->nom, target1) == 0) break; } if (i < fd_nj_plot->notu) node = fd_nj_plot->tabtax[i]; } if (node) { // node = tree center or outgroup leaf current_cote1 = node; if (outotu) { // -outgroup option if (!target3 || !is_parent(node, node->v3, target3)) { current_cote2 = node->v3; } else if (!is_parent(node, node->v2, target3)) { current_cote2 = node->v2; } else { current_cote2 = node->v1; } if (target3) { struct noeud *aux = current_cote1; // have target3 at bottom of plot current_cote1 = current_cote2; current_cote2 = aux; } } else { // -ingroup option if (!is_parent(node, node->v3, target1)) { current_cote2 = node->v3; } else if (!is_parent(node, node->v2, target1)) { current_cote2 = node->v2; } else { current_cote2 = node->v1; } } } } fd_nj_plot->root_br_l = place_midpoint_root(fd_nj_plot->tabtax[0], fd_nj_plot->racine, fd_nj_plot->notu, node != NULL); fd_nj_plot->rooted = TRUE; fd_nj_plot->root_num = -1;//means the tree is rooted at fd_nj_plot->racine } else { /* derniere espece est groupe externe */ fd_nj_plot->racine->v3 = NULL; fd_nj_plot->root_num = fd_nj_plot->notu - 1; } } else { fd_nj_plot->racine = *(fd_nj_plot->tabtax+num_noeud); fd_nj_plot->root_br_l= fd_nj_plot->racine->l1 + fd_nj_plot->racine->l2; fd_nj_plot->root_num = num_noeud; if(!fd_nj_plot->has_br_length) calc_brl_for_lengthless(fd_nj_plot->racine, NULL); /* y a-t-il un bootstrap sur l'une des branches racine ? */ i = get_br_from_bouts(fd_nj_plot, fd_nj_plot->racine, fd_nj_plot->racine->v1); if(i == -1) i = get_br_from_bouts(fd_nj_plot, fd_nj_plot->racine, fd_nj_plot->racine->v2); // build the exclusive OR of 2 conditions int cond1 = (i != -1 ? 1 : 0); int cond2 = 0; int j = get_br_from_bouts(fd_nj_plot, fd_nj_plot->racine, NULL); if (j != -1) { cond2 = 1; if (!cond1) i = j; } if (cond1 ^ cond2) { fd_nj_plot->branches[i].bouta = fd_nj_plot->racine->v1; fd_nj_plot->branches[i].boutb = fd_nj_plot->racine->v2; } } if(fd_nj_plot->notu < 2) return ("Tree should contain at least 2 elements."); fd_nj_plot->subtree_notu = fd_nj_plot->notu; fd_nj_plot->subtree_center = NULL; if (fd_nj_plot->up) fd_nj_plot->up->deactivate(); if (fd_nj_plot->full) fd_nj_plot->full->value(1); if(fd_nj_plot->view == NULL && fd_nj_plot->menu_file) (fd_nj_plot->menu_file->get_menu() + reorder_align_following_tree)->deactivate(); if (fd_nj_plot->new_outgroup) fd_nj_plot->new_outgroup->activate(); return NULL; } /* end of preptree */ char *check_alloc(int nbrelt, int sizelt) { char *retval; if( (retval=(char *)calloc(nbrelt,sizelt)) != NULL ) return retval; fl_alert("ERROR: Not enough memory."); exit(1); } const char *loadphylip(FD_nj_plot *fd_nj_plot, char *arbre, char *last_bootstrap) //returns NULL iff OK { char *deba,*debb,*debc, *finarbre; struct noeud *p1, *p2, *p3, *p; branche *int_br_g, *int_br_d; fd_nj_plot->has_br_length = 2; fd_nj_plot->has_internal = FALSE; /* ignore all stuff after last closing parenthesis (needed for fastDNAml output) */ finarbre= nextpar(arbre); fd_nj_plot->rooted = 0; deba=arbre+1; debb=deba; while(*debb != ',') { if(*debb == 0) return bad_tree; if(*debb == '(')debb=nextpar(debb); debb++; } debb++; debc=debb; while(*debc != ',' && debc it has 3 subtrees at its bottommost level */ debc++; } else { /* the tree is rooted */ debc=finarbre+1; fd_nj_plot->rooted = 1; } fd_nj_plot->input_was_rooted = fd_nj_plot->rooted; num_noeud = fd_nj_plot->notu - 1; nextotu = -1; p1=unrootedset(fd_nj_plot, deba,debb-2,&int_br_g); if(p1 != NULL) p2=unrootedset(fd_nj_plot, debb,debc-2,&int_br_d); p = *(fd_nj_plot->tabtax+(++num_noeud)); if(p1==NULL || p2==NULL || num_noeud >= 2*fd_nj_plot->notu - 1) return bad_tree; p->v1=p1; p1->v3=p; p->l1=p1->l3; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p1; } p->v2=p2; p2->v3=p; p->l2=p2->l3; if(int_br_d!=NULL) { int_br_d->bouta=p; int_br_d->boutb=p2; } if(!fd_nj_plot->rooted) { p3=unrootedset(fd_nj_plot, debc,finarbre-1,&int_br_g); if(p3==NULL) return bad_tree; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p3; } p->v3=p3; p3->v3=p; p->l3=p3->l3; } else { p->v3=NULL; /* recherche d'un dernier label interne */ debc=finarbre+1; while(*debc!=0 && *debc!=':' && *debc!='[') debc++; if(debc-finarbre>1) { int l=debc-finarbre-1; fd_nj_plot->has_internal = TRUE; fd_nj_plot->totbranches++; fd_nj_plot->branches[fd_nj_plot->totbranches].br_label=check_alloc(l+1,1); memcpy(fd_nj_plot->branches[fd_nj_plot->totbranches].br_label,finarbre+1,l); fd_nj_plot->branches[fd_nj_plot->totbranches].br_label[l]=0; fd_nj_plot->branches[fd_nj_plot->totbranches].bouta=p1; fd_nj_plot->branches[fd_nj_plot->totbranches].boutb=p2; } } if(fd_nj_plot->rooted && last_bootstrap != NULL) { /* attach last_bootstrap to branch racine <--> NULL */ fd_nj_plot->totbranches++; fd_nj_plot->branches[fd_nj_plot->totbranches].br_label = strdup(last_bootstrap); fd_nj_plot->branches[fd_nj_plot->totbranches].bouta=p; fd_nj_plot->branches[fd_nj_plot->totbranches].boutb=NULL; } if(last_bootstrap != NULL) free(last_bootstrap); return NULL; } struct noeud *unrootedset(FD_nj_plot *fd_nj_plot, char *deb, char *fin, branche **p_int_br) //returns NULL iff error { struct noeud *p, *pp; char *virg, *ferme; branche *int_br; static int l; static double brlength; *p_int_br=NULL; while(*deb==' ')deb++; while(*fin==' ')fin--; if(*deb != '(') { /* une feuille */ virg = strchr(deb, ':'); if(virg != NULL && virg < fin) { sscanf(virg+1, "%le", &brlength); fd_nj_plot->has_br_length=1; } else { brlength = 1; fd_nj_plot->has_br_length=0; virg = fin + 1; } virg--; while(*deb==' ')deb++; l = virg-deb+1; fd_nj_plot->labels[ ++nextotu] = (char *)check_alloc(l + 1, 1); memcpy(fd_nj_plot->labels[nextotu], deb, l); fd_nj_plot->labels[nextotu][l] = 0; p = *(fd_nj_plot->tabtax + nextotu); p->l3 = brlength; p->v1 = p->v2 = p->v3 = NULL; return p; } /* un noeud */ num_noeud++; if(num_noeud >= 2*fd_nj_plot->notu - 1) return NULL; p = *(fd_nj_plot->tabtax + num_noeud); ferme = nextpar(deb); virg=deb + 1; while(*virg != ',' && virg < fin) { if(*virg == '(') virg=nextpar(virg); virg++; } if(virg>=ferme) return NULL; pp = unrootedset(fd_nj_plot, deb + 1, virg - 1, &int_br); if(pp == NULL) return NULL; p->v1 = pp; pp->v3 = p; p->l1 = pp->l3; if(int_br != NULL) { int_br->bouta = p; int_br->boutb = pp; } pp = unrootedset(fd_nj_plot, virg + 1, ferme - 1, &int_br); if(pp == NULL) return NULL; p->v2 = pp; pp->v3 = p; p->l2 = pp->l3; if(int_br != NULL) { int_br->bouta = p; int_br->boutb = pp; } virg = strchr(ferme, ':'); if(virg != NULL && virg < fin) { /* traitement longueur */ // if(fd_nj_plot->has_br_length == 0) return NULL; sscanf(virg+1, "%le", &brlength); fd_nj_plot->has_br_length=1; if(*fin == ']') { /* bootstrap entre [] apres longueurs */ static char *q; q = fin - 1; while(q > virg && *q != '[') q--; if(*q == '[' && fin - q >= 2) { fd_nj_plot->has_internal = TRUE; fd_nj_plot->totbranches++; l = fin - q - 1; fd_nj_plot->branches[fd_nj_plot->totbranches].br_label = check_alloc(l+1,1); memcpy(fd_nj_plot->branches[fd_nj_plot->totbranches].br_label,q+1,l); fd_nj_plot->branches[fd_nj_plot->totbranches].br_label[l]=0; *p_int_br= &fd_nj_plot->branches[fd_nj_plot->totbranches]; } } } else { // if(fd_nj_plot->has_br_length == 1) return NULL; brlength = 1; fd_nj_plot->has_br_length=0; virg = fin + 1; } /* recherche bootstrap (internal label) */ while (ferme < virg-1 && *(ferme+1) == ' ') ferme++; l=virg-ferme-1; if(l>0) { fd_nj_plot->has_internal = TRUE; fd_nj_plot->totbranches++; fd_nj_plot->branches[fd_nj_plot->totbranches].br_label= check_alloc(l+1,1); memcpy(fd_nj_plot->branches[fd_nj_plot->totbranches].br_label,ferme+1,l); fd_nj_plot->branches[fd_nj_plot->totbranches].br_label[l]=0; *p_int_br= &fd_nj_plot->branches[fd_nj_plot->totbranches]; } p->l3 = brlength; return p; } char *nextpar(char *pospar) //returns NULL iff error { char *pos; pos=pospar+1; while(*pos != ')') { if(*pos == 0) return NULL; if(*pos == '(') pos=nextpar(pos); pos++; } return pos; } const char *make_binary_or_unrooted(char *arbre) //returns NULL iff OK { char *finarbre, *deba, *debb, *debc; int retval; finarbre= nextpar(arbre); *(finarbre + 1) = 0; deba=arbre+1; while (*deba == '(' && nextpar(deba) == finarbre - 1) { // remove extra enclosing parentheses *finarbre = 0; memmove(arbre, deba, finarbre - arbre); finarbre -= 2; } debb=deba; while(*debb != ',') { if(*debb == 0) return("Incorrect tree file"); if(*debb == '(')debb=nextpar(debb); debb++; } debb++; debc=debb; while(*debc != ',' && debc it has 3 subtrees or more at its bottommost level */ retval = make_binary(arbre , debb, finarbre - 1, TRUE); if(retval != -1) retval = make_binary(arbre , deba, debb - 2, TRUE); } else retval = make_binary(arbre , deba, finarbre - 1, TRUE); return (retval >= 0 ? NULL : "Cannot process multibranched tree without branch lengths"); } int make_binary(char *arbre, char *debut, char *fin, int go_down) //returns -1 iff error { int virg, l, retval; char *p, *q; p = debut; virg = 0; retval = 0; while(p < fin) { if(*p == ',') virg++; else if(*p == '(') { q = nextpar(p); if(go_down) { l = make_binary(arbre, p+1, q-1, TRUE); fin += l; retval += l; p = q + l; } else p = q; } p++; } if(virg > 1) { /* multifurcation */ /* recherche de la 2eme virgule */ p = debut; l = 0; while(TRUE) { if(*p == ',') { l++; if(l == 2) break; } else if(*p == '(') { p = nextpar(p); } p++; } l = strlen(p); memmove(p + 4, p, l + 1); memmove(debut + 1, debut, p - debut); *debut = '('; memcpy(p + 1, "):0", 3); fin += 4; retval += 4; if(virg > 2) retval += make_binary(arbre, debut, fin, FALSE); } return retval; } void mydrawstring(double x, double y, char *nom, char option, int height) { static double px,py; ch_echelle(x,y,&px,&py); if(option == '1') { /* ecrire une chaine en la montant d'un chouia */ py += height/6.; } else if(option == 'c' || option == 'r') { /* ecrire une chaine en la centrant vert. sur cette position*/ if (*nom == ')' || *nom == '(') {//indicates we want to draw a square before the name int edge = height/2; dir_plotsquare(px, py, edge, *nom == '('); nom++; while(*nom==' ')nom++; if(*nom == 0) return; px += edge; } py -= height/3.; px += height/6.; } else if(option == 't') { py -= (5./6.) * height; } else if(option == 'b') { py += height/6.; } dir_moveto(px,py); if(option == 'r') fl_color(FL_RED); plotstring(nom); if(option == 'r') fl_color(FL_BLACK); } void moveto(double x,double y) /* move from current pos to logical coord x,y */ { static double px,py; ch_echelle(x,y,&px,&py); dir_moveto(px,py); } void lineto(double x,double y) /* draw line from current pos to logical coord x,y */ { static double px,py; ch_echelle(x,y,&px,&py); dir_lineto(px,py); } int calc_brl_for_lengthless(struct noeud *centre, struct noeud *pere) /* Recursively computes branch lengths of a lengthless tree having some branches fixed to 0 to allow multifurcations so that all tips align to the right of the plot. */ { int n1 = 0, n2, depth; volatile double l; if(centre->v1 == NULL && centre->v2 == NULL) { if(centre->l3 == 0) {//no terminal branch of 0 length centre->l3 = 1E-6; if(centre->v3->v1 == centre) centre->v3->l1 = centre->l3; else centre->v3->l2 = centre->l3; } return 0;//a leaf } //rearrange with centre->v3 towards root if(centre->v1 == pere) { centre->v1 = centre->v3; centre->v3 = pere; l = centre->l3; centre->l3 = centre->l1; centre->l1 = l; } else if(centre->v2 == pere) { centre->v2 = centre->v3; centre->v3 = pere; l = centre->l3; centre->l3 = centre->l2; centre->l2 = l; } n1 = calc_brl_for_lengthless(centre->v1, centre); n2 = calc_brl_for_lengthless(centre->v2, centre); depth = n1; if(centre->l1 != 0) depth++; if(depth < n2) depth = n2; if(centre->l2 != 0 && n2 + 1 > depth) depth++; if(centre->l1 != 0) { centre->l1 = depth - n1; centre->v1->l3 = depth - n1; } else if(depth - n1 > 0) add_value_downstream(centre->v1, depth - n1); if(centre->l2 != 0) { centre->l2 = depth - n2; centre->v2->l3 = depth - n2; } else if(depth - n2 > 0) add_value_downstream(centre->v2, depth - n2); return depth; } void add_value_downstream(struct noeud *centre, int value) { if(centre->l1 != 0) { centre->l1 += value; centre->v1->l3 = centre->l1; } else add_value_downstream(centre->v1, value); if(centre->l2 != 0) { centre->l2 += value; centre->v2->l3 = centre->l1; } else add_value_downstream(centre->v2, value); } double place_midpoint_root(struct noeud *from, struct noeud *racine, int notu, int fixed_outgroup) /* to root an unrooted tree in the middle of its largest tip-to-tip path from: any leave or node of tree racine: unused node that will become the tree root notu: number of tree leaves fixed_outgroup: if true, current_cote1, current_cote2 have been previously set to two adjacent nodes where the root is wanted Returns: length of root-containing branch Requires that node->rank values have been correctly set before */ { struct noeud *aux; double laux, balance, root_br_length; if (!fixed_outgroup) { balance = midpoint_rooting(from, notu, &root_br_length); } else { double l1 = get_length_down(current_cote2, current_cote1); double l2 = get_length_down(current_cote1, current_cote2); if (current_cote2->v1 == current_cote1 ) root_br_length = current_cote2->l1; else if (current_cote2->v2 == current_cote1) root_br_length = current_cote2->l2; else root_br_length = current_cote2->l3; balance = (root_br_length - l1 + l2)/(2*root_br_length); } /* il faut toujours que la racine soit telle que racine->v1->v3=racine */ if (current_cote1->v1 == current_cote2 ) { /* echanger les voisins v1 et v3 de cote1 */ aux=current_cote1->v1; current_cote1->v1=current_cote1->v3; current_cote1->v3=aux; laux=current_cote1->l1; current_cote1->l1=current_cote1->l3; current_cote1->l3=laux; } else if (current_cote1->v2 == current_cote2) { /* echanger les voisins v2 et v3 de cote1 */ aux=current_cote1->v2; current_cote1->v2=current_cote1->v3; current_cote1->v3=aux; laux=current_cote1->l2; current_cote1->l2=current_cote1->l3; current_cote1->l3=laux; } current_cote1->v3 = racine; if (current_cote2->v1 == current_cote1 ) current_cote2->v1 = racine; else if (current_cote2->v2 == current_cote1) current_cote2->v2 = racine; else current_cote2->v3 = racine; racine->v1=current_cote1; racine->v2=current_cote2; racine->v3=NULL; racine->l3=0; /* avoid very unbalanced division of root branch */ if(balance > MAX_FRAC) balance = MAX_FRAC; else if(balance < 1 - MAX_FRAC) balance = 1 - MAX_FRAC; racine->l1 = root_br_length * balance; racine->v1->l3 = racine->l1; racine->l2 = root_br_length - racine->l1; if (current_cote2->v1 == racine ) current_cote2->l1 = racine->l2; else if (current_cote2->v2 == racine) current_cote2->l2 = racine->l2; else current_cote2->l3 = racine->l2; return root_br_length; } double get_length_down(struct noeud *pere, struct noeud *racine) /* compute the max length of the tree down a node */ { if (racine == NULL) return 0.0; else { struct noeud *gauche, *droite; double bg,bd,lg,ld; if ( racine->v1 == pere ) { gauche = racine->v2; droite = racine->v3; bg = (racine->l2); bd = (racine->l3); } else if ( racine->v2 == pere ) { gauche = racine->v1; droite = racine->v3; bg = (racine->l1); bd = (racine->l3); } else { gauche = racine->v1; droite = racine->v2; bg = (racine->l1); bd = (racine->l2); } /* conserver cette ecriture sinon plante sur PC */ lg = ld = 0; if (gauche != NULL) lg = get_length_down(racine, gauche); lg += bg; if (droite != NULL) ld = get_length_down(racine, droite); ld += bd; return lg > ld ? lg : ld; } } void clear_squares_below(struct noeud *n) { if(n == NULL) return; clear_squares_below(n->v1); clear_squares_below(n->v2); char *p = n->nom; if(p != NULL && *p == ')') memmove(p, p+1, strlen(p)); } void runtree(FD_nj_plot *fd_nj_plot) { double currx, curry; int i; struct noeud *p1, *p2; if (!fd_nj_plot->rooted) { /* place root at user-chosen place: node # fd_nj_plot->root_num */ fd_nj_plot->rooted = TRUE; p1 = fd_nj_plot->tabtax[fd_nj_plot->root_num]; p2 = p1->v3; fd_nj_plot->root_br_l = p1->l3; if(fd_nj_plot->has_br_length) { current_cote1 = p1; current_cote2 = p2; place_midpoint_root(p1, fd_nj_plot->racine, fd_nj_plot->notu, true); } else { p1->v3 = fd_nj_plot->racine; if (p2->v1 == p1 ) p2->v1 = fd_nj_plot->racine; else if (p2->v2 == p1) p2->v2 = fd_nj_plot->racine; else p2->v3 = fd_nj_plot->racine; fd_nj_plot->racine->v1=p1; fd_nj_plot->racine->v2=p2; fd_nj_plot->racine->v3=NULL; fd_nj_plot->racine->l1 = p1->l3; if (p2->v1 == fd_nj_plot->racine ) fd_nj_plot->racine->l2 = p2->l1; else if (p2->v2 == fd_nj_plot->racine) fd_nj_plot->racine->l2 = p2->l2; else fd_nj_plot->racine->l2 = p2->l3; calc_brl_for_lengthless(fd_nj_plot->racine, NULL); } } /* initialize leave and node names */ for(i = 0; i <= 2*(fd_nj_plot->notu - 1); i++) fd_nj_plot->tabtax[i]->nom[0] = 0; if (fd_nj_plot->choix == depl_racine) { for(i=0; i <= 2*(fd_nj_plot->notu - 1) - 1; i++) { if(i == fd_nj_plot->root_num) continue;//skip current root if( !fd_nj_plot->has_br_length) { if(fd_nj_plot->tabtax[i]->l3 == 0) continue;//skip internal multifurcation nodes that can't be broken by root } sprintf(fd_nj_plot->tabtax[i]->nom,")"); } } else if(fd_nj_plot->choix == permutation) for(i=fd_nj_plot->notu; i <= 2*(fd_nj_plot->notu - 1); i++) sprintf(fd_nj_plot->tabtax[i]->nom,")"); else if(fd_nj_plot->choix == subtree) for(i=fd_nj_plot->notu; i <= 2*(fd_nj_plot->notu - 1) - 1; i++) sprintf(fd_nj_plot->tabtax[i]->nom,")"); else if(fd_nj_plot->choix == selection) { int j; SEA_VIEW *view = fd_nj_plot->view; if (view) { for(i=fd_nj_plot->notu; i <= 2*(fd_nj_plot->notu - 1); i++) sprintf(fd_nj_plot->tabtax[i]->nom,")"); for (i=0; i < fd_nj_plot->notu; i++) { for (j=0; j < view->tot_seqs; j++) { if (view->sel_seqs[j] && strcmp(fd_nj_plot->labels[i], view->seqname[j]) == 0) break; } // ) means draw black square, ( means draw red square sprintf(fd_nj_plot->tabtax[i]->nom, j >= view->tot_seqs ? ")" : "("); } } } else if(fd_nj_plot->choix == prune_clade) for(i=0; i <= 2*(fd_nj_plot->notu - 1) - 1; i++) sprintf(fd_nj_plot->tabtax[i]->nom,")"); else if(fd_nj_plot->choix == prune_clade_found) { char *p; struct noeud *parent; for(i=0; i <= 2*(fd_nj_plot->notu - 1) - 1; i++) sprintf(fd_nj_plot->tabtax[i]->nom,")"); parent = fd_nj_plot->prune_clade_node->v3; parent->nom[0] = 0;//no square on clade's parent if(parent->v1 == fd_nj_plot->prune_clade_node) p = parent->v2->nom;//nor on clade's sister else p = parent->v1->nom; if(*p != 0) memmove(p, p + 1, strlen(p)); clear_squares_below(fd_nj_plot->prune_clade_node);//nor in clade } for(i=0; inotu; i++) { int j; j = strlen(fd_nj_plot->tabtax[i]->nom); strcpy(fd_nj_plot->tabtax[i]->nom + j, fd_nj_plot->labels[i]); } fd_nj_plot->totnoms = fd_nj_plot->tottraits = fd_nj_plot->totpoints = -1; end_br_length = fd_nj_plot->br_length_txt; currx = 0.; maxx = 0.; memset(fd_nj_plot->profs, 0, (fd_nj_plot->notu)*sizeof(double)); if(fd_nj_plot->subtree_center != NULL) fd_nj_plot->deltay = maxy / (fd_nj_plot->subtree_notu - 1); else { fd_nj_plot->deltay = maxy / (fd_nj_plot->notu - 1); fd_nj_plot->subtree_notu = fd_nj_plot->notu; } nexty = -fd_nj_plot->deltay; calc_text_size((char *)"Mq", &fd_nj_plot->char_height, &fd_nj_plot->ascent); if(fd_nj_plot->subtree_center == NULL) mem_plot(fd_nj_plot, NULL, fd_nj_plot->racine, currx, &curry); else mem_plot(fd_nj_plot, fd_nj_plot->subtree_ascend, fd_nj_plot->subtree_center, currx, &curry); } /* end of runtree */ void mem_plot(FD_nj_plot *fd_nj_plot, struct noeud *pere, struct noeud *centre, double currx, double *curry) /* prepare tree by memorizing all graphic requests */ { int num=0, widthd = 0, widthg = 0; char *p; struct noeud *gauche, *droite; double bg, bd, bpere; if(fd_nj_plot->choix == prune_clade_found && centre == fd_nj_plot->prune_clade_node) { fd_nj_plot->colored_names_1 = fd_nj_plot->totnoms + 1; fd_nj_plot->colored_traits_1 = fd_nj_plot->tottraits + 1; } while( *(fd_nj_plot->tabtax+num) != centre) num++; if(pere != NULL && (centre->v1 == NULL || centre->v2 == NULL || centre->v3 == NULL) ) { /* orienter le noeud centre de maniere standard: centre->v3=pere */ if( centre->v1 == pere ) { gauche =centre->v2; droite = centre->v3; bg = centre->l2; bd = centre->l3; bpere = centre->l1; } else if( centre->v2 == pere ) { gauche =centre->v1; droite = centre->v3; bg = centre->l1; bd = centre->l3; bpere = centre->l2; } else { gauche =centre->v1; droite = centre->v2; bg = centre->l1; bd = centre->l2; bpere = centre->l3; } centre->v3=pere; centre->v1=gauche; centre->v2=droite; centre->l3=bpere; centre->l1=bg; centre->l2=bd; /* write taxon name */ nexty += fd_nj_plot->deltay; mem_nom(fd_nj_plot, currx,nexty,fd_nj_plot->tabtax[num]->nom,'c'); fd_nj_plot->profs[num] = currx; fd_nj_plot->widnames[num] = calc_text_size(fd_nj_plot->tabtax[num]->nom, NULL, NULL); if(fd_nj_plot->choix==depl_racine || fd_nj_plot->choix== selection || fd_nj_plot->choix == prune_clade || fd_nj_plot->choix == prune_clade_found) mem_point(fd_nj_plot, currx, nexty, num); *curry = nexty; } else { double yg, yd, xg, xd; static int doswap; static struct noeud *tmp; /* doswap vrai ssi permutation de 2 descendants necessaire ici */ doswap = (fd_nj_plot->swap != 0 && *(fd_nj_plot->tabtax+fd_nj_plot->swap) == centre); if( centre->v1 == pere ) { if(doswap) { tmp= centre->v2;centre->v2= centre->v3;centre->v3= tmp; bg= centre->l2; centre->l2= centre->l3; centre->l3= bg; } gauche =centre->v2; droite = centre->v3; bg = centre->l2; bd = centre->l3; bpere = centre->l1; } else if( centre->v2 == pere ) { if(doswap) { tmp= centre->v1;centre->v1= centre->v3;centre->v3= tmp; bg= centre->l1; centre->l1= centre->l3; centre->l3= bg; } gauche =centre->v1; droite = centre->v3; bg = centre->l1; bd = centre->l3; bpere = centre->l2; } else { if(doswap) { tmp= centre->v1;centre->v1= centre->v2;centre->v2= tmp; bg= centre->l1; centre->l1= centre->l2; centre->l2= bg; } gauche =centre->v1; droite = centre->v2; bg = centre->l1; bd = centre->l2; bpere = centre->l3; } /* orienter le noeud centre de maniere standard: centre->v3=pere */ centre->v3=pere; centre->v1=gauche; centre->v2=droite; centre->l3=bpere; centre->l1=bg; centre->l2=bd; xg=currx+bg; xd=currx+bd; mem_plot(fd_nj_plot, centre, gauche, xg, &yg); mem_plot(fd_nj_plot, centre, droite, xd, &yd); if (fd_nj_plot->branch_width_as_support) { float f = 0; char *p = get_br_label(fd_nj_plot, pere?centre:droite, gauche); if (p) sscanf(p, "%f", &f); if (f > fd_nj_plot->support_threshold_high) widthg = 5; else if (f > fd_nj_plot->support_threshold_low) widthg = 3; else widthg = 0; p = get_br_label(fd_nj_plot, pere?centre:gauche, droite); f = 0; if (p) sscanf(p, "%f", &f); if (f > fd_nj_plot->support_threshold_high) widthd = 5; else if (f > fd_nj_plot->support_threshold_low) widthd = 3; else widthd = 0; } else { widthd = widthg = 0; } mem_trait(fd_nj_plot, currx, yg, xg, yg, widthg); mem_trait(fd_nj_plot, currx, yd, xd, yd, widthd); mem_trait(fd_nj_plot, currx, yg, currx, yd, 0); // vertical *curry = (yg+yd)/2; /* write internal fd_nj_plot->labels */ if(fd_nj_plot->choix==show_tree && fd_nj_plot->show_bootstrap) { if(pere != NULL) { /* for all but root node */ if( (p=get_br_label_with_threshold(fd_nj_plot, centre, gauche)) != NULL ) mem_nom(fd_nj_plot, currx,yg,p,'t'); if( (p=get_br_label_with_threshold(fd_nj_plot, centre, droite)) != NULL ) mem_nom(fd_nj_plot, currx,yd,p,'b'); } else {/* for root node */ if( (p=get_br_label_with_threshold(fd_nj_plot, centre, NULL)) != NULL ) { /* if root bootstrap exists */ mem_nom(fd_nj_plot, currx,*curry,p,'c'); if( (p=get_br_label_with_threshold(fd_nj_plot, centre, gauche)) != NULL ) mem_nom(fd_nj_plot, currx,yg,p,'t'); if( (p=get_br_label_with_threshold(fd_nj_plot, centre, droite)) != NULL ) mem_nom(fd_nj_plot, currx,yd,p,'b'); } else {/* if no root bootstrap any bootstrap is to be centered */ if( (p=get_br_label_with_threshold(fd_nj_plot, centre, gauche)) != NULL ) mem_nom(fd_nj_plot, currx,*curry,p,'c'); if( (p=get_br_label_with_threshold(fd_nj_plot, centre, droite)) != NULL ) mem_nom(fd_nj_plot, currx,*curry,p,'c'); if( (p=get_br_label_with_threshold(fd_nj_plot, gauche, droite)) != NULL ) mem_nom(fd_nj_plot, currx,*curry,p,'c'); } } } /* write node number */ mem_nom(fd_nj_plot, currx,*curry,fd_nj_plot->tabtax[num]->nom,'c'); mem_point(fd_nj_plot, currx, *curry, num); if(fd_nj_plot->plot_br_l && fd_nj_plot->has_br_length) { /* write branch length */ double min_br_l = 0.008; /* minimum branch length displayed */ if(bg>min_br_l) { sprintf(end_br_length,"%.3f",bg); mem_nom(fd_nj_plot, currx+bg/10,yg,end_br_length,'1'); end_br_length += (strlen(end_br_length)+1); } if(bd>min_br_l) { sprintf(end_br_length,"%.3f",bd); mem_nom(fd_nj_plot, currx+bd/10,yd,end_br_length,'1'); end_br_length += (strlen(end_br_length)+1); } } } if(fd_nj_plot->choix == prune_clade_found && centre == fd_nj_plot->prune_clade_node) { fd_nj_plot->colored_names_2 = fd_nj_plot->totnoms; fd_nj_plot->colored_traits_2 = fd_nj_plot->tottraits; } } /* end of mem_plot */ void mem_point(FD_nj_plot *fd_nj_plot, double x, double y, int number) { if( *(fd_nj_plot->tabtax[number]->nom) != ')' && *(fd_nj_plot->tabtax[number]->nom) != '(') return; ++fd_nj_plot->totpoints; (fd_nj_plot->points+fd_nj_plot->totpoints)->x = x; (fd_nj_plot->points+fd_nj_plot->totpoints)->y = y; (fd_nj_plot->points+fd_nj_plot->totpoints)->number = number; } void mem_nom(FD_nj_plot *fd_nj_plot, double x, double y, char *nom, char option) /* x,y: logical coordinates of beginning of string nom: address of string to be displayed later option: 'c' use for position of center of character height '1' put bottom of characters at y+1 pixel 't' use for position of top of character 'b' use for position of bottom of character */ { if(strlen(nom) != 0) { fd_nj_plot->totnoms++; if(x > maxx) maxx = x; (fd_nj_plot->noms+fd_nj_plot->totnoms)->x = x; (fd_nj_plot->noms+fd_nj_plot->totnoms)->y = y; (fd_nj_plot->noms+fd_nj_plot->totnoms)->nom = nom; (fd_nj_plot->noms+fd_nj_plot->totnoms)->disp_option = option; } } void mem_trait(FD_nj_plot *fd_nj_plot, double xd, double yd, double xf, double yf, int width) { fd_nj_plot->tottraits++; if(xd>maxx) maxx=xd; if(xf>maxx) maxx=xf; (fd_nj_plot->traits+fd_nj_plot->tottraits)->xd = xd; (fd_nj_plot->traits+fd_nj_plot->tottraits)->yd = yd; (fd_nj_plot->traits+fd_nj_plot->tottraits)->xf = xf; (fd_nj_plot->traits+fd_nj_plot->tottraits)->yf = yf; (fd_nj_plot->traits+fd_nj_plot->tottraits)->width = width; } char *get_br_label(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b) { int i; for(i=0; i<=fd_nj_plot->totbranches; i++) { if(fd_nj_plot->branches[i].bouta==a && fd_nj_plot->branches[i].boutb==b) { return fd_nj_plot->branches[i].br_label; } else if(fd_nj_plot->branches[i].boutb==a && fd_nj_plot->branches[i].bouta==b) { return fd_nj_plot->branches[i].br_label; } } return NULL; } char *get_br_label_with_threshold(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b) { float value; char *label = get_br_label(fd_nj_plot, a, b); if(label != NULL && fd_nj_plot->bootstrap_threshold > 0.01) { sscanf(label, "%f", &value); if(value < fd_nj_plot->bootstrap_threshold) label = NULL; } return label; } int get_br_from_bouts(FD_nj_plot *fd_nj_plot, struct noeud *a, struct noeud *b) { int i; for(i=0; i<=fd_nj_plot->totbranches; i++) { if(fd_nj_plot->branches[i].bouta==a && fd_nj_plot->branches[i].boutb==b) return i; if(fd_nj_plot->branches[i].boutb==a && fd_nj_plot->branches[i].bouta==b) return i; } return -1; } void free_tree(FD_nj_plot *fd_nj_plot) { int i; if(fd_nj_plot->notu == 0) return; /* de-allocate all memory */ for(i=0; i<2*fd_nj_plot->notu - 1; i++) { free(fd_nj_plot->tabtax[i]->nom); free(fd_nj_plot->tabtax[i]); } free(fd_nj_plot->tabtax); for(i=0; inotu - 1; i++) if(fd_nj_plot->branches[i].br_label != NULL) free(fd_nj_plot->branches[i].br_label); free(fd_nj_plot->branches); free(fd_nj_plot->widnames); free(fd_nj_plot->noms); free(fd_nj_plot->points); free(fd_nj_plot->traits); free(fd_nj_plot->profs); for(i = 0; i < fd_nj_plot->notu; i++) free(fd_nj_plot->labels[i]); free(fd_nj_plot->labels); free(fd_nj_plot->br_length_txt); if(fd_nj_plot->tree_name != NULL) { free(fd_nj_plot->tree_name); fd_nj_plot->tree_name = NULL; } if(fd_nj_plot->trees != NULL) { free(fd_nj_plot->trees); fd_nj_plot->trees = NULL; } if(fd_nj_plot->tree_label != NULL) { free(fd_nj_plot->tree_label); fd_nj_plot->tree_label = NULL; } } /* ecriture d'un arbre non racine au format phylip, multifurcations allowed */ char *ecrit_arbre_parenth_unrooted(FD_nj_plot *fd_nj_plot, struct noeud *root) { struct noeud *t1, *t2, *t3; char *p1, *p2, *p3, *p, *bootstrap; int l; float l1, l2, l3; if(root == NULL) return NULL; t1 = root->v1->v1; t2 = root->v1->v2; t3 = root->v2; l1 = root->v1->l1; l2 = root->v1->l2; if(t1 == NULL) { t1 = root->v2->v1; t2 = root->v2->v2; t3 = root->v1; l1 = root->v2->l1; l2 = root->v2->l2; } l3 = root->l1 + root->l2; bootstrap = get_br_label(fd_nj_plot, root->v1, root->v2); if(bootstrap == NULL) bootstrap = (char *)""; p1 = ecrit_arbre_parenth(fd_nj_plot, t1); *(p1 + strlen(p1) - 1) = 0; p2 = ecrit_arbre_parenth(fd_nj_plot, t2); *(p2 + strlen(p2) - 1) = 0; p3 = ecrit_arbre_parenth(fd_nj_plot, t3); *(p3 + strlen(p3) - 1) = 0; l = strlen(p1) + strlen(p2)+ strlen(p3) + 150; p = (char *)check_alloc(l, 1); if(fd_nj_plot->has_br_length) sprintf(p, "(%s:%.5f,%s:%.5f,%s%s:%.5f);", p1, l1, p2, l2, p3, bootstrap, l3); else sprintf(p, "(%s,%s,%s%s);", p1, p2, p3, bootstrap); free(p1); free(p2); free(p3); return p; } /* ecriture d'un arbre racine au format phylip, multifurcations allowed */ char *ecrit_arbre_parenth(FD_nj_plot *fd_nj_plot, struct noeud *root) { char *arbre, *fin, *p; int l, maxarbre = 2 * fd_nj_plot->long_arbre_parenth + 1000; arbre=check_alloc( maxarbre+20,1); fin=recur_ecrit_arbre(fd_nj_plot, root,arbre,arbre+maxarbre-1); /* ecriture du dernier label interne */ if( fin != NULL && (p=get_br_label(fd_nj_plot, root->v1,root->v2)) != NULL ) { l=strlen(p); if(fin+l>=arbre+maxarbre) fin= NULL; else { memcpy(fin+1,p,l); fin+=l; } } if(fin == NULL) { free(arbre); return NULL; } strcpy(fin+1,";"); arbre = (char *)realloc(arbre, strlen(arbre) + 1); return arbre; } char *recur_ecrit_arbre(FD_nj_plot *fd_nj_plot, struct noeud *centre, char *arbre, char *finarbre) { int l; char *p, *q; if(centre->v1==NULL && centre->v2==NULL) { p = centre->nom; if(*p == ')' || *p == '(') p++;//skip square mark l = strlen(p); if(arbre+l>=finarbre) return NULL; memcpy(arbre,p,l); arbre += l-1; } else { *arbre='('; p = arbre; arbre=recur_ecrit_arbre(fd_nj_plot, centre->v1,arbre+1,finarbre); if(arbre==NULL) return NULL; if(fd_nj_plot->has_br_length) { if(arbre+10>=finarbre) return NULL; sprintf(++arbre,":%.5f",centre->l1); while(*arbre!=0) arbre++; } else arbre++; *arbre=','; arbre=recur_ecrit_arbre(fd_nj_plot, centre->v2,arbre+1,finarbre); if(arbre==NULL) return NULL; if(fd_nj_plot->has_br_length) { if(arbre+10>=finarbre) return NULL; sprintf(++arbre,":%.5f",centre->l2); while(*arbre!=0) arbre++; } else arbre++; *arbre=')'; /* ecriture des fd_nj_plot->labels internes */ if( (q=get_br_label(fd_nj_plot, centre,centre->v3) ) != NULL && (fd_nj_plot->has_br_length || (centre->l3 != 0) ) ) { l=strlen(q); if(arbre+l>=finarbre) return NULL; memcpy(arbre+1,q,l); arbre+=l; } else if(centre->v3 != NULL && (!fd_nj_plot->has_br_length) && (centre->l3 == 0) ) {//multibranches processed here memmove(p, p + 1, arbre - p); arbre -= 2; } } return arbre; } void removeroot(FD_nj_plot *fd_nj_plot) { struct noeud *p1, *p2; p1=fd_nj_plot->racine->v1; p2=fd_nj_plot->racine->v2; if(p1->v1 == fd_nj_plot->racine ) {p1->v1 = p2; p1->l1 = fd_nj_plot->root_br_l;} else if (p1->v2 == fd_nj_plot->racine) {p1->v2 = p2; p1->l2 = fd_nj_plot->root_br_l;} else {p1->v3 = p2; p1->l3 = fd_nj_plot->root_br_l;} if(p2->v1 == fd_nj_plot->racine ) {p2->v1 = p1; p2->l1 = fd_nj_plot->root_br_l;} else if (p2->v2 == fd_nj_plot->racine) {p2->v2 = p1; p2->l2 = fd_nj_plot->root_br_l;} else {p2->v3 = p1; p2->l3 = fd_nj_plot->root_br_l;} fd_nj_plot->rooted = 0; } int calc_n_desc(struct noeud *pere) { if(pere->v1 == NULL) return 1; else return calc_n_desc(pere->v1) + calc_n_desc(pere->v2); } void disconnect_tree_windows(SEA_VIEW *view) //disconnect all tree windows pointing to view { Fl_Window *w = Fl::first_window(); while(w != NULL) { const char *c = w->xclass(); if(c != NULL && strcmp(c, TREE_WINDOW) == 0) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)(w->user_data()); if(fd_nj_plot->view == view) fd_nj_plot->view = NULL; } w = Fl::next_window(w); } } int calc_new_order(int *intree, struct noeud *from, char **names, int tot_seqs, int found, char **pmissing) //computes tree-based order of names //upon return, intree[old] = new //returns # of names found in array names, or 0 if any was not found { if(from->v1 == NULL && from->v2 == NULL) { int i; for(i = 0; i < tot_seqs; i++) if(intree[i] == -1 && strcmp(names[i], from->nom) == 0) break; if(i < tot_seqs) { intree[i] = found++; return found; } else { *pmissing = from->nom; return 0; } } found = calc_new_order(intree, from->v2, names, tot_seqs, found, pmissing); if(found != 0) found = calc_new_order(intree, from->v1, names, tot_seqs, found, pmissing); return found; } void reorder_following_tree(struct noeud *root, int notu, SEA_VIEW *view) { int i, j; char *missing_name; if(view == NULL || view->alt_col_rank != NULL) return; int *intree = (int *)malloc(view->tot_seqs * sizeof(int)); for( i = 0; i < view->tot_seqs; i++) intree[i] = -1; int found = calc_new_order(intree, root, view->seqname, view->tot_seqs, 0, &missing_name); if(found != notu) { fl_alert("Missing tree sequence from alignment: [%s]", missing_name); free(intree); return; } int *order = (int *)malloc(view->tot_seqs * sizeof(int)); int *fromtree = (int *)malloc(notu * sizeof(int)); for( j = 0, i = 0; i < view->tot_seqs; i++) { if(intree[i] != -1) fromtree[j++] = i; } for( i = 0; i < view->tot_seqs; i++) { if(intree[i] == -1) order[i] = i; else order[i] = fromtree[intree[i]]; } free(fromtree); free(intree); char **tmp = (char **)malloc(view->tot_seqs * sizeof(char *)); memcpy(tmp, view->sequence, view->tot_seqs * sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) view->sequence[order[i]] = tmp[i]; if(view->comments != NULL) { memcpy(tmp, view->comments, view->tot_seqs * sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) view->comments[order[i]] = tmp[i]; } memcpy(tmp, view->seqname, view->tot_seqs * sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) view->seqname[order[i]] = tmp[i]; memcpy(tmp, view->col_rank, view->tot_seqs * sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) view->col_rank[order[i]] = tmp[i]; if(view->viewasprots != NULL) { memcpy(tmp, view->viewasprots, view->tot_seqs * sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) ((char **)(view->viewasprots))[order[i]] = tmp[i]; } free(tmp); int *tmpint = (int *)malloc(view->tot_seqs * sizeof(int)); memcpy(tmpint, view->each_length, view->tot_seqs * sizeof(int)); for( i = 0; i < view->tot_seqs; i++) view->each_length[order[i]] = tmpint[i]; if(view->tot_sel_seqs != 0) { memcpy(tmpint, view->sel_seqs, view->tot_seqs * sizeof(int)); for( i = 0; i < view->tot_seqs; i++) view->sel_seqs[order[i]] = tmpint[i]; } for(int numset = 0; numset < view->numb_species_sets; numset++) { for(i = 0; i < view->tot_seqs; i++) tmpint[order[i]] = view->list_species_sets[numset][i]; memcpy(view->list_species_sets[numset], tmpint, view->tot_seqs * sizeof(int) ); } free(tmpint); if(!view->cursor_in_comment) { view->cursor_seq = order[view->cursor_seq - 1] + 1; view->old_cursor_seq = view->cursor_seq; } free(order); set_seaview_modified(view, TRUE); view->DNA_obj->redraw(); view->DNA_obj->take_focus(); } static void search_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); static char select[500] = ""; char aux[500]; int num, trouve; if(fd_nj_plot->notu == 0) return; if(strcmp(((Fl_Menu_ *)wgt)->text(), "Find") == 0) { const char *p = fl_input("Enter searched name:", select); if(p == NULL) return; strcpy(select, p); majuscules(select); } if(strlen(select) == 0) return; if(fd_nj_plot->fd_unrooted != NULL) { unrooted_search((FD_unrooted *)fd_nj_plot->fd_unrooted, select); return; } trouve = FALSE; for(num = 0; num <= fd_nj_plot->totnoms; num++) { strcpy(aux, (fd_nj_plot->noms+num)->nom); majuscules(aux); if(strstr( aux, select) != NULL) { (fd_nj_plot->noms+num)->disp_option = 'r'; trouve = TRUE; } } if(trouve) { fd_nj_plot->panel->window()->redraw(); } } void bt_threshold_callback(Fl_Widget *wgt, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); Fl_Menu_Item *item = fd_nj_plot->menu_edit->get_menu(); const char *reply = fl_input("Enter branch support threshold value", NULL); if(reply == NULL) return; char *p = (char *)(item + 6)->label(); if (strcmp(p, "0") != 0) free(p); (item + 6)->label(strdup(reply)); sscanf(reply, "%f", &fd_nj_plot->bootstrap_threshold); fd_nj_plot->need_runtree = TRUE; fd_nj_plot->panel->window()->redraw(); } void midpoint_callback(Fl_Widget *wgt, void *data) { struct noeud *v1, *v2; double l, l1, l2; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)(wgt ? wgt->user_data() : data); if(fd_nj_plot->notu == 0) return; v1 = fd_nj_plot->racine->v1; v2 = fd_nj_plot->racine->v2; l1 = fd_nj_plot->racine->l1; l2 = fd_nj_plot->racine->l2; if (fd_nj_plot->rooted) removeroot(fd_nj_plot); l = place_midpoint_root(fd_nj_plot->tabtax[0], fd_nj_plot->racine, fd_nj_plot->notu, FALSE); if(fd_nj_plot->racine->v1 != v2 || fd_nj_plot->racine->v2 != v1) {//accept new root fd_nj_plot->root_br_l = l; fd_nj_plot->root_num = -1; } else {//don't accept to only exchange v1 & v2 of previous root fd_nj_plot->racine->v1 = v1; fd_nj_plot->racine->v2 = v2; fd_nj_plot->racine->l1 = l1; fd_nj_plot->racine->l2 = l2; } fd_nj_plot->rooted = TRUE; fd_nj_plot->need_runtree = TRUE; if (fd_nj_plot->panel) fd_nj_plot->panel->window()->redraw(); } void edit_tree_header(Fl_Widget *wgt, void *unused) { char *p, *q, *newtree; int i; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); if(fd_nj_plot->notu == 0) return; SEA_VIEW *view = fd_nj_plot->view; char *reply = (char*)fl_input("Set tree header:", fd_nj_plot->tree_label); if(reply == NULL) return; while ((p = strchr(reply, '[')) != NULL) *p = ' '; // remove [ and ] from tree label while ((p = strchr(reply, ']')) != NULL) *p = ' '; if(fd_nj_plot->tree_label != NULL) free(fd_nj_plot->tree_label); fd_nj_plot->tree_label = strdup(reply); fd_nj_plot->panel->window()->redraw(); if(view == NULL) return; p = fd_nj_plot->trees; for(i = 0; i < view->tot_trees; i++) {//search for current tree among known trees if(strcmp(view->trees[i], p) == 0) break; } if(i >= view->tot_trees) return; while(*p == ' ') p++; newtree = fd_nj_plot->current_tree; if (*newtree == '[') newtree = strchr(newtree, ']') + 1; p = nextpar(newtree); while (*p != ';') p++; q = (char*)malloc(p - newtree + 2); memcpy(q, newtree, p-newtree+1); q[p-newtree+1] = 0; replace_with_new_tree(fd_nj_plot, q); free(view->trees[i]); view->trees[i] = strdup(fd_nj_plot->trees); } void set_win_size_callback(Fl_Widget *wgt, void *data) { int w = 300, h = 100; char current[30]; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)wgt->user_data(); sprintf(current, "%dx%d", fd_nj_plot->full->window()->w(), fd_nj_plot->full->window()->h() ); const char *reply = fl_input("Enter desired window size", current); if(reply == NULL) return; sscanf(reply, "%dx%d", &w, &h); fd_nj_plot->full->window()->size(w, h); fd_nj_plot->full->window()->size_range(300, 100); } int compare_newick_with_names(const char *tree, char **names, int notu, char **pname) /* returns 0 iff names in tree are the same as in names[0::notu[ 1 when name from tree absent from names and puts differing name in *pname -1 when elements in names absent from tree and puts one absent name in *pname */ { char *p = (char *)tree - 1; int found = 0, i, l, *seen, retval; char *start = NULL; static char name[200]; seen = (int *)calloc(notu, sizeof(int)); while(*(++p) != 0) { if(*p == '(' ) start = p + 1; else if(start == NULL && *p == ',') start = p + 1; else if(start != NULL && (*p == ')' || *p == ':' || *p == ',') ) { found++; while(*start == ' ') start++; memcpy(name, start, p - start); name[p - start] = 0; l = strlen(name) - 1; while( l >= 0 && name[l] == ' ') name[l--] = 0; for(i = 0; i < notu; i++) if(strcmp(name, names[i]) == 0) break; if(i == notu) { if(pname != NULL) *pname = name; free(seen); return 1; } else seen[i] = 1; if(*p != ',') start = NULL; else start = p + 1; } } for(i = 0; i < notu; i++) if(!seen[i]) break; if(i < notu) { strcpy(name, names[i]); if(pname != NULL) *pname = name; retval = -1; } else retval = 0; free(seen); return retval; } void edit_shape_callback(Fl_Widget *obj, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)obj->user_data(); Fl_Menu_Item *item = (Fl_Menu_Item*)((Fl_Menu_ *)obj)->mvalue(); if( fd_nj_plot->notu == 0) return; if( fd_nj_plot->select_clade_button == NULL || item->value() ) { char *p, *q, *oldtree, *newtree, *label; int in_name = FALSE; oldtree = ecrit_arbre_parenth( fd_nj_plot, fd_nj_plot->racine); label = fd_nj_plot->tree_label; newtree = (char *)malloc(strlen(oldtree) + 1);//rewrite tree without lengths nor bootstrap q = newtree; p = oldtree - 1; while(*(++p) != 0) { if( *p != '(' && (*(p-1) == ',' || *(p-1) == '(')) { in_name = TRUE; *q++ = *p; continue; } else if(in_name) { if(strchr(":,()", *p) != NULL) in_name = FALSE; } if(in_name || *p == ',' || *p == ')' || *p == '(') *q++ = *p; } *(q++) = ';'; *q = 0; free(oldtree); if(fd_nj_plot->select_clade_button == NULL) { Fl_Window *w = treedraw(newtree, fd_nj_plot->view, "edited_tree", FALSE); fd_nj_plot = (FD_nj_plot *)w->user_data(); int x = fd_nj_plot->l_button->x(); int y = fd_nj_plot->l_button->y(); Fl_Group::current(fd_nj_plot->l_button->parent()); fd_nj_plot->select_clade_button = new Fl_Button(x, y, 90, 20, "Select group"); fd_nj_plot->delete_clade_button = new Fl_Button(fd_nj_plot->select_clade_button->x() + fd_nj_plot->select_clade_button->w() + 5, y, 90, 20, "Delete group"); fd_nj_plot->complete_edit_button = new Fl_Button(fd_nj_plot->delete_clade_button->x() + fd_nj_plot->delete_clade_button->w() + 5, y, 65, 20, "End edit"); fd_nj_plot->select_clade_button->callback(select_clade_callback, fd_nj_plot); fd_nj_plot->delete_clade_button->callback(delete_clade_callback, fd_nj_plot); fd_nj_plot->complete_edit_button->callback(complete_edit_callback, fd_nj_plot); (fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->edit_shape_rank)->flags = FL_MENU_TOGGLE; if(label != NULL) fd_nj_plot->tree_label = strdup(label); } else { fd_nj_plot->select_clade_button->show(); fd_nj_plot->delete_clade_button->show(); fd_nj_plot->complete_edit_button->show(); } fd_nj_plot->l_button->hide(); fd_nj_plot->bt_button->hide(); if(fd_nj_plot->root_unroot != NULL) fd_nj_plot->root_unroot->hide(); (fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->edit_shape_rank)->set(); fd_nj_plot->menu_file->bar_item()->deactivate(); select_clade_callback(NULL, fd_nj_plot); } else { complete_edit_callback(NULL, fd_nj_plot); } } void select_clade_callback(Fl_Widget *obj, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; fd_nj_plot->choix = prune_clade; fd_nj_plot->select_clade_button->deactivate(); fd_nj_plot->delete_clade_button->deactivate(); fd_nj_plot->swap_button->value(0); fd_nj_plot->need_runtree = TRUE; fd_nj_plot->panel->window()->redraw(); } void delete_clade_callback(Fl_Widget *obj, void *data) { struct noeud *parent, *gparent, *sister; FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; parent = fd_nj_plot->prune_clade_node->v3; if(parent->v1 == fd_nj_plot->prune_clade_node) sister = parent->v2; else sister = parent->v1; gparent = parent->v3; if(gparent != NULL) { if(gparent->v1 == parent) { gparent->v1 = sister; gparent->l1 += sister->l3; sister->l3 = gparent->l1; } else { gparent->v2 = sister; gparent->l2 += sister->l3; sister->l3 = gparent->l2; } sister->v3 = gparent; } else { struct noeud *X, *Y; X = sister->v1; Y = sister->v2; if(X == NULL || Y == NULL) return; parent->v1 = X; parent->l1 = sister->l3 + X->l3; X->v3 = parent; X->l3 = parent->l1; parent->v2 = Y; parent->l2 = sister->l3 + Y->l3; Y->v3 = parent; Y->l3 = parent->l2; } clear_squares_below(fd_nj_plot->racine); char *newtree = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); char *p = strdup(fd_nj_plot->tree_name); char *q; if(fd_nj_plot->tree_label != NULL) q = strdup(fd_nj_plot->tree_label); else q = NULL; free_tree(fd_nj_plot); fd_nj_plot->tree_name = p; fd_nj_plot->full->window()->copy_label(p); fd_nj_plot->tree_label = q; fd_nj_plot->trees = newtree; fd_nj_plot->current_tree = newtree; fd_nj_plot->rank = 0; if(preptree(fd_nj_plot) == NULL) { select_clade_callback(NULL, data); } else { fd_nj_plot->notu = 0; fd_nj_plot->panel->window()->redraw(); } } void complete_edit_callback(Fl_Widget *obj, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; fd_nj_plot->l_button->show(); fd_nj_plot->bt_button->show(); if(fd_nj_plot->root_unroot != NULL) fd_nj_plot->root_unroot->show(); ((Fl_Menu_Item *)fd_nj_plot->menu_edit->get_menu() + fd_nj_plot->edit_shape_rank)->clear(); fd_nj_plot->select_clade_button->hide(); fd_nj_plot->delete_clade_button->hide(); fd_nj_plot->complete_edit_button->hide(); fd_nj_plot->choix = show_tree; fd_nj_plot->need_runtree = TRUE; fd_nj_plot->panel->window()->redraw(); fd_nj_plot->menu_file->bar_item()->activate(); } void sel_next_in_subtree(struct noeud *center, SEA_VIEW *view, char **missing) { if(center == NULL) return; if(center->v1 == NULL || center->v2 == NULL || center->v3 == NULL) {//a leaf int i; for(i = 0; i < view->tot_seqs; i++) if(view->sel_seqs[i] == 0 && strcmp(center->nom, view->seqname[i]) == 0) break; if(i < view->tot_seqs) { view->sel_seqs[i] = 1; } else if(*missing == NULL) *missing = center->nom; } sel_next_in_subtree(center->v1, view, missing); sel_next_in_subtree(center->v2, view, missing); } void select_in_alignment(FD_nj_plot *fd_nj_plot) //selects in alignment all members of subtree { char *missing = NULL; SEA_VIEW *view = fd_nj_plot->view; if(view == NULL || fd_nj_plot->subtree_center == NULL) return; view->tot_sel_seqs = 0; memset(view->sel_seqs, 0, view->tot_seqs * sizeof(int)); sel_next_in_subtree(fd_nj_plot->subtree_center, view, &missing); for(int i = 0; i < view->tot_seqs; i++) if(view->sel_seqs[i]) view->tot_sel_seqs++; select_deselect_seq(view, -2); view->DNA_obj->redraw(); if(view->tot_sel_seqs != fd_nj_plot->subtree_notu) fl_alert("At least one subtree leave not found in alignment: %s", missing); } static FD_nj_plot *find_matching_tree_window(SEA_VIEW *view) { // returns the FD_nj_plot of the first tree window found that refers to view // and that is in selection mode Fl_Window *win = Fl::first_window(); while (win) { const char *c; if (!win->parent() && (c = win->xclass()) != NULL && strcmp(c, TREE_WINDOW) == 0) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)(win->user_data()); if (fd_nj_plot->select->value() && fd_nj_plot->view == view) { return fd_nj_plot; } } win = Fl::next_window(win); } return NULL; } void select_deselect_in_tree(SEA_VIEW *view) { // select/deselect seqs in tree following selection in view FD_nj_plot* tree_plot = find_matching_tree_window(view); if (tree_plot) { tree_plot->need_runtree = TRUE; tree_plot->panel->window()->redraw(); } } void print_title(int x, int y, char *text, int family, int size, int p, int totp) { static char ligne[200]; time_t heure; int h; time (&heure); sprintf(ligne, "Seaview %s %s", text, ctime(&heure) ); h = strlen(ligne) - 1; ligne[h] = 0; if(totp > 1) sprintf(ligne + h, " Page %d of %d", p, totp); fl_color(FL_BLACK); fl_font(family, size); fl_draw(ligne, x, y); } extern void print_unrooted(FD_unrooted *fd_unrooted, const char *name, bool to_ps_file, const char *directname = NULL); void print_plot(FD_nj_plot *fd_nj_plot, bool to_ps_file, const char *directname) { if(fd_nj_plot->fd_unrooted != NULL) { print_unrooted((FD_unrooted *)fd_nj_plot->fd_unrooted, fd_nj_plot->tree_name, to_ps_file, directname); return; } int h, page, superpos, frompage, topage, error, title_height, title_ascent; int true_print_rect_x, true_print_rect_y, true_print_rect_w, true_print_rect_h; int title_rect_x, title_rect_y, title_rect_w, title_rect_h; if(fd_nj_plot->notu == 0) return; if (fd_nj_plot->full) my_watch_cursor(fd_nj_plot->full->window()); Fl_Printer* myprinter; if (to_ps_file) { myprinter = (Fl_Printer*)new Fl_PDF_or_PS_File_Device(); if (directname) { error = ((Fl_PDF_or_PS_File_Device*)myprinter)->begin_document(directname, printout_pageformat); } else error = ((Fl_PDF_or_PS_File_Device*)myprinter)->start_job(fd_nj_plot->tree_name, printout_pageformat); frompage = 1; topage = fd_nj_plot->page_count; } else { myprinter = new Fl_Printer(); error = myprinter->start_job(fd_nj_plot->page_count, &frompage, &topage); } if (error) { fl_reset_cursor(fd_nj_plot->full->window()); return; } #ifndef NO_PDF jmp_buf *jbuf; if (to_ps_file) ((Fl_PDF_File_Device*)myprinter)->surface_try(&jbuf); if ( (!to_ps_file) || setjmp(*jbuf) == 0) { // replaces PDF_TRY #endif myprinter->printable_rect(&true_print_rect_w, &true_print_rect_h); true_print_rect_x = true_print_rect_y = 0; fl_font(FL_TIMES, 11); calc_text_size((char*)"Mq", &title_height, &title_ascent); title_rect_x = true_print_rect_x; title_rect_y = true_print_rect_y; title_rect_w = true_print_rect_w; title_rect_h = title_ascent; true_print_rect_y += title_height; true_print_rect_h -= title_height; fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size); calc_text_size((char*)"Mq", &fd_nj_plot->char_height, &fd_nj_plot->ascent); h = true_print_rect_h; superpos = h / 30; physx = true_print_rect_w; physy = (fd_nj_plot->page_count - 1) * (h - superpos) + h - 1; page_x_offset = true_print_rect_x; page_y_offset = true_print_rect_y; page_y_offset -= (frompage - 1) * (h - superpos); for(page = frompage; page <= topage; page++) { myprinter->start_page(); fl_push_clip(title_rect_x, title_rect_y, title_rect_w, title_height); char *p = fd_nj_plot->tree_name; if (!p) p = (char*)fd_nj_plot->panel->window()->window()->label(); print_title(title_rect_x, title_rect_y + title_rect_h - 1, p, FL_TIMES, 10, page, fd_nj_plot->page_count); fl_pop_clip(); fl_push_clip(true_print_rect_x, true_print_rect_y, true_print_rect_w, true_print_rect_h ); fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size); fl_color(FL_GRAY); fl_rect(true_print_rect_x, true_print_rect_y, true_print_rect_w, true_print_rect_h); fl_color(FL_BLACK); do_plot(fd_nj_plot, TRUE); fl_pop_clip(); myprinter->end_page(); page_y_offset -= h - superpos; } myprinter->end_job(); #ifndef NO_PDF } // end of PDF_TRY if (to_ps_file && ((Fl_PDF_File_Device*)myprinter)->surface_catch()) { // replaces PDF_CATCH ((Fl_PDF_File_Device*)myprinter)->error_catch(); } #endif delete myprinter; fd_nj_plot->need_runtree = TRUE; if (fd_nj_plot->panel) fd_nj_plot->panel->redraw(); page_x_offset = 0; page_y_offset = 0; if (fd_nj_plot->full) fl_reset_cursor(fd_nj_plot->full->window()); } bool is_parent(struct noeud *centre, struct noeud *from, const char *label) { // returns true if leave label is below centre in tree (away from from) int count = 0; if (centre->v1) count++; if (centre->v2) count++; if (centre->v3) count++; if (count == 1) { // a leaf return strcmp(centre->nom, label) == 0; } if (centre->v1 == from) { return is_parent(centre->v2, centre, label) || is_parent(centre->v3,centre, label); } else if (centre->v2==from) { return is_parent(centre->v1, centre, label) || is_parent(centre->v3, centre, label); } return is_parent(centre->v1, centre, label) || is_parent(centre->v2, centre, label); } int count_node(struct noeud *centre, struct noeud *from) { // count # of matching leaves below centre int count = 0; if (centre->v1) count++; if (centre->v2) count++; if (centre->v3) count++; if (count == 1) { // a leaf if (strcmp(centre->nom, target1) == 0 || strcmp(centre->nom, target2) == 0 || strcmp(centre->nom, target3) == 0) { return 1; } return 0; } if (centre->v1 == from) { return count_node(centre->v2, centre) + count_node(centre->v3, centre); } else if (centre->v2==from) { return count_node(centre->v1, centre) + count_node(centre->v3, centre); } return count_node(centre->v1, centre) + count_node(centre->v2, centre); } struct noeud *span_nodes(struct noeud *centre, struct noeud *from) /* parcourir recursivement tous les noeuds de l'arbre sans racine a partir de centre et dans la direction opposee a son voisin from */ { if(centre == NULL) return NULL; int c1=0, c2=0, c3 =0; if (centre->v1) c1 = count_node(centre->v1, centre); if (centre->v2) c2 = count_node(centre->v2, centre); if (centre->v3) c3 = count_node(centre->v3, centre); if (c1 == 1 && c2 == 1 && c3 == 1) return centre; struct noeud *v = NULL; if (centre->v1==from) { v = span_nodes(centre->v2,centre); if (!v) v = span_nodes(centre->v3,centre); } else if (centre->v2==from) { v = span_nodes(centre->v1,centre); if (!v) v = span_nodes(centre->v3,centre); } else { v = span_nodes(centre->v1,centre); if (!v) v = span_nodes(centre->v2,centre); } return v; } float argval(int argc, char *argv[], const char *arg, float defval) { for (int i = 1; i < argc - 1; i++) { if (strcmp(argv[i], arg) == 0) { sscanf(argv[i+1], "%f", &defval); break; } } return defval; } char *argname(int argc, char *argv[], const char *arg) { for (int i = 1; i < argc - 1; i++) { if (strcmp(argv[i], arg) == 0) { return argv[i+1]; } } return NULL; } bool isarg(int argc, char *argv[], const char *arg) { for (int i = 1; i < argc; i++) { if (strcmp(argv[i], arg) == 0) return true; } return false; } #ifdef WIN32 #ifdef small #undef small // necessary under WIN32 #endif #endif double recur_patristic_distances(FD_nj_plot *fd_nj_plot, struct noeud *centre, float **d, int **listdesc) /* Recursive part of patristic distance computation. int **listdesc of size 2*notu - 1 (number of internal and terminal nodes) can hold in listdesc[rank] a bit list of notu bits where rank is the number of a tree node. listdesc of a leaf = leaf rank at one. listdesc of an internal node = union (listdesc of left son, listdesc of right son). For a node with left and right sons, and l1 length to left, and l2 length to right: d(i, j) is incremented by l1 for all i in listdesc(left) and all j not in listdesc(left), d(i, j) is incremented by l2 for all i in listdesc(right) and all j not in listdesc(right). At most depth+1 bit lists are simultaneously allocated where depth is the max # of branches from root to tip. Returns the length of the subtree rooted at centre. */ { int i, j, small, big; const int lmot = 8*sizeof(int); // bits in an int const int width = (fd_nj_plot->notu + lmot - 1)/lmot; // # of int's to hold notu bits float l; if (centre->v1 == NULL && centre->v2 == NULL) { // centre is a leaf listdesc[centre->rank] = (int*)calloc(width, sizeof(int)); bit1(listdesc[centre->rank], centre->rank + 1); } else { double left, right; left = recur_patristic_distances(fd_nj_plot, centre->v1, d, listdesc); if (fd_nj_plot->has_br_length || centre->l1 == 0) l = (float)centre->l1; else if (centre == fd_nj_plot->racine) l = 0.5; else l = 1; for (i = 0; i < fd_nj_plot->notu; i++) { if (testbit(listdesc[centre->v1->rank], i+1) == 0) continue; for (j = 0; j < fd_nj_plot->notu; j++) { if (testbit(listdesc[centre->v1->rank], j+1) == 0) { if (i < j) { small = i; big = j; } else { small = j; big = i; } d[small][big-small-1] += l; } } } right = recur_patristic_distances(fd_nj_plot, centre->v2, d, listdesc); if (fd_nj_plot->has_br_length || centre->l2 == 0) l = (float)centre->l2; else if (centre == fd_nj_plot->racine) l = 0.5; else l = 1; for (i = 0; i < fd_nj_plot->notu; i++) { if (testbit(listdesc[centre->v2->rank], i+1) == 0) continue; for (j = 0; j < fd_nj_plot->notu; j++) { if (testbit(listdesc[centre->v2->rank], j+1) == 0) { if (i < j) { small = i; big = j; } else { small = j; big = i; } d[small][big-small-1] += l; } } } for (i = 0; i < width; i++) listdesc[centre->v1->rank][i] |= listdesc[centre->v2->rank][i]; listdesc[centre->rank] = listdesc[centre->v1->rank]; free(listdesc[centre->v2->rank]); return left + centre->l1 + right + centre->l2; } return 0; } void calc_patristic_distances(FD_nj_plot *fd_nj_plot, FILE *out) /* Compute patristic distances from rooted tree in fd_nj_plot, and write them to out one line for each pair. */ { int i, j; char *n1, *n2, *p; int **listdesc = (int**)calloc(2 *fd_nj_plot->notu - 1, sizeof(int*)); float **d = (float**)calloc(fd_nj_plot->notu, sizeof(float*)); for (i = 0; i < fd_nj_plot->notu - 1; i++) d[i] = (float*)calloc(fd_nj_plot->notu - i - 1, sizeof(float)); struct noeud *center; int *testlist; if (fd_nj_plot->subtree_center) { center = fd_nj_plot->subtree_center; } else { center = fd_nj_plot->racine; testlist = NULL; } double tree_length = recur_patristic_distances(fd_nj_plot, center, d, listdesc); if (fd_nj_plot->subtree_center) { testlist = listdesc[fd_nj_plot->subtree_center->rank]; } fprintf(out, "#patristic distances (tree length=%f)\n", tree_length); for (i = 0; i < fd_nj_plot->notu; i++) { if (testlist && !testbit(testlist, i+1)) continue; for (j = i+1; j < fd_nj_plot->notu; j++) { if (testlist && !testbit(testlist, j+1)) continue; n1 = fd_nj_plot->tabtax[i]->nom; n2 = fd_nj_plot->tabtax[j]->nom; if (strcmp(n1, n2) > 0) { p = n1; n1 = n2; n2 = p; } fprintf(out, "%s,%s: %f\n", n1, n2, d[i][j-i-1]); } free(d[i]); } free(d); free(listdesc[center->rank]); free(listdesc); } #ifndef NO_PDF void plotonly(int argc, char *argv[]) { const char *fname = argv[argc-1]; // read tree in file named in last argument or in stdin FILE *in = (strcmp(fname, "-") != 0 ? fopen(fname, "r") : stdin); if (!in) return; int l = 1000; char *tree = (char*)malloc(l+1); char line[200], *p = tree, *q; while (true) { if (fgets(line, sizeof(line), in) == NULL) break; if (p - tree + (int)strlen(line) + 1 > l) { l += strlen(line) + 1000; q = (char*)realloc(tree, l + 1); p = q + (p - tree); tree = q; } q = line; while (*q) { if (*q != '\n' && *q != '\r') *p++ = *q; q++; } } *p = 0; fclose(in); FD_nj_plot *fd_nj_plot = (FD_nj_plot *)calloc(1, sizeof(FD_nj_plot)); fd_nj_plot->trees = tree; fd_nj_plot->current_tree = tree; fd_nj_plot->rank = 0; fd_nj_plot->font_size = argval(argc, argv, "-fontsize", 12); fd_nj_plot->font_family = FL_TIMES; fd_nj_plot->page_count = argval(argc, argv, "-pagecount", 1); fd_nj_plot->plot_br_l = isarg(argc, argv, "-lengths"); fd_nj_plot->show_bootstrap = isarg(argc, argv, "-bootstrap") || isarg(argc, argv, "-bootstrap_threshold"); fd_nj_plot->bootstrap_threshold = argval(argc, argv, "-bootstrap_threshold", 0); int use_svg = isarg(argc, argv, "-svg"); fd_nj_plot->choix = show_tree; printout_pageformat = isarg(argc, argv, "-letter") ? Fl_Paged_Device::LETTER : Fl_Paged_Device::A4; outotu = argname(argc, argv, "-outgroup"); if (!outotu) inotu = argname(argc, argv, "-ingroup"); if (outotu || inotu) { target1 = strtok( (outotu?outotu:inotu), ","); p = target1 + strlen(target1) - 1; while (p > target1 && *p == ' ') *p-- = 0; target2 = strtok(NULL, ","); if (target2) { while (*target2 == ' ') target2++; p = target2 + strlen(target2) - 1; while (p > target2 && *p == ' ') *p-- = 0; target3 = strtok(NULL, ","); if (target3) while (*target3 == ' ') target3++; } } if (preptree(fd_nj_plot)) { free(fd_nj_plot); return; } char *pdfname; FILE *out; if ( isarg(argc, argv, "-reroot") ) { if ( isarg(argc, argv, "-plotonly") ) { fprintf(stderr, "Can't use both -plotonly and -reroot\n"); exit(1); } if ( isarg(argc, argv, "-root_at_center") ) { midpoint_callback(NULL, fd_nj_plot); } if ( (pdfname = argname(argc, argv, "-outnewick")) == NULL) { pdfname = (char*)malloc(strlen(fname) + 10); strcpy(pdfname, fname); if ((p = strrchr(pdfname, '.')) == NULL) p = pdfname + strlen(pdfname); strcpy(p, ".tree"); if (strcmp(fname, pdfname) == 0) strcat(pdfname, "_2"); } // we must call runtree() so the tree is correctly oriented from its new root // so we must have a graphics driver to compute string widths Fl_PDF_Graphics_Driver* pdf_driver = new Fl_PDF_Graphics_Driver; fl_graphics_driver = pdf_driver; pdf_driver->pdf = PDF_new(); PDF_begin_document(pdf_driver->pdf, "", 0, ""); fl_font(FL_TIMES, 12); runtree(fd_nj_plot); if ( (p = argname(argc, argv, "-patristic_distances")) ) { out = fopen(p, "w"); if (!out) Fl::fatal("Can't open %s for writing.", p); calc_patristic_distances(fd_nj_plot, out); fclose(out); exit(0); } out = fopen(pdfname, "w"); if (out) { bool write_unrooted = false; if (isarg(argc, argv, "-unroot")) write_unrooted = true; if (isarg(argc, argv, "-remove_bootstrap")) { fd_nj_plot->totbranches = -1; // forces branch support not to appear in Nexus tree if (!fd_nj_plot->input_was_rooted) write_unrooted = true; } if (write_unrooted) tree = ecrit_arbre_parenth_unrooted(fd_nj_plot, fd_nj_plot->racine); else tree = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); fwrite(tree, 1, strlen(tree), out); free(tree); fputs("\n", out); fclose(out); } exit(0); } fd_nj_plot->tree_name = strdup(fname); maxy = 1000.; if ((pdfname = argname(argc, argv, "-o")) == NULL) { pdfname = (char*)malloc(strlen(fname) + 5); strcpy(pdfname, fname); if ((p = strrchr(pdfname, '.')) == NULL) p = pdfname + strlen(pdfname); strcpy(p, use_svg ? ".svg" : ".pdf"); } Fl_SVG_File_Surface *svg; if (use_svg) { out = (strcmp(pdfname, "-") != 0 ? fl_fopen(pdfname, "w") : stdout); if (!out) return; physx = Fl_Paged_Device::page_formats[printout_pageformat].width; physy = Fl_Paged_Device::page_formats[printout_pageformat].height; if (isarg(argc, argv, "-size")) { sscanf(argname(argc, argv, "-size"), "%lfx%lf", &physx, &physy); } svg = new Fl_SVG_File_Surface(physx, physy, out, true); svg->set_current(); } else { // we must call runtree() so we must have a graphics driver to compute string widths Fl_PDF_Graphics_Driver* pdf_driver = new Fl_PDF_Graphics_Driver; fl_graphics_driver = pdf_driver; pdf_driver->pdf = PDF_new(); PDF_begin_document(pdf_driver->pdf, "", 0, ""); } fl_font(fd_nj_plot->font_family, fd_nj_plot->font_size); if (isarg(argc, argv, "-branch_width_as_support")) { fd_nj_plot->branch_width_as_support = true; fd_nj_plot->support_threshold_high = argval(argc, argv, "-support_threshold_high", .95); fd_nj_plot->support_threshold_low = argval(argc, argv, "-support_threshold_low", .8); } runtree(fd_nj_plot); if (!use_svg) { Fl_PDF_Graphics_Driver* pdf_driver = (Fl_PDF_Graphics_Driver*)fl_graphics_driver; PDF_delete(pdf_driver->pdf); delete pdf_driver; } if (isarg(argc, argv, "-unrooted")) { tree = ecrit_arbre_parenth_unrooted(fd_nj_plot, fd_nj_plot->racine); if (tree == NULL) { return; } FD_unrooted *fd_unrooted = (FD_unrooted *) calloc(1, sizeof(FD_unrooted)); fd_nj_plot->fd_unrooted = fd_unrooted; if ( debut_arbre(tree, fd_unrooted) ) return; free(tree); fd_unrooted->font_size = fd_nj_plot->font_size; } char *select, aux[500]; if ((select = argname(argc, argv, "-match"))) { majuscules(select); bool unrooted = (fd_nj_plot->fd_unrooted != NULL); int last = unrooted ? 2 * ((FD_unrooted *)fd_nj_plot->fd_unrooted)->notu - 4 : fd_nj_plot->totnoms; for(int num = 0; num <= last; num++) { if (unrooted && ((FD_unrooted *)fd_nj_plot->fd_unrooted)->branches[num].nom == NULL) continue; strcpy(aux, unrooted ? ((FD_unrooted *)fd_nj_plot->fd_unrooted)->branches[num].nom : (fd_nj_plot->noms+num)->nom ); majuscules(aux); if(strstr( aux, select) != NULL) { if (unrooted) ((FD_unrooted *)fd_nj_plot->fd_unrooted)->branches[num].color = TRUE; else (fd_nj_plot->noms+num)->disp_option = 'r'; } } if ((select = argname(argc, argv, "-color"))) { int rgb; sscanf(select, "%x", &rgb); Fl::set_color(FL_RED, rgb >> 16, (rgb >> 8) & 0xFF, rgb & 0xFF); } } if (use_svg) { svg_tree_save(fd_nj_plot, svg); } else { print_plot(fd_nj_plot, true, pdfname); } if (argname(argc, argv, "-o") == NULL) free(pdfname); if ( (pdfname = argname(argc, argv, "-outnewick"))) { out = (strcmp(pdfname, "-") != 0 ? fopen(pdfname, "w") : stdout); if (out) { char *newick = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); fwrite(newick, 1, strlen(newick), out); free(newick); fputs("\n", out); fclose(out); } } } #endif // NO_PDF #if !(defined(__APPLE__) || defined(WIN32)) && 100*FL_MAJOR_VERSION + 10*FL_MINOR_VERSION + FL_PATCH_VERSION == 130 // for X11 under 1.3.0 only #undef Fl_Printer #undef Fl_PostScript_File_Device corr_Fl_Printer::corr_Fl_Printer() : Fl_Printer() { count = 0; } corr_Fl_PostScript_File_Device::corr_Fl_PostScript_File_Device() : Fl_PostScript_File_Device() { count = 0; } // bypass FLTK 1.3.0 bug where printable_rect() not usable before start_page() on X11 int corr_Fl_Printer::start_job(int pagecount, int *frompage, int *topage) { int retval = Fl_Printer::start_job(pagecount, frompage, topage); if (retval) return retval; start_page(); return 0; } int corr_Fl_PostScript_File_Device::start_job(int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { int retval = Fl_PostScript_File_Device::start_job(pagecount, format, layout); if (retval) return retval; start_page(); return 0; } int corr_Fl_PostScript_File_Device::start_job(FILE *file, int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { int retval = Fl_PostScript_File_Device::start_job(file, pagecount, format, layout); if (retval) return retval; start_page(); return 0; } // correct FLTK 1.3.0 Fl_PostScript_Printer bug where %%PageBoundingBox is missing. int corr_Fl_Printer::start_page() { if (count++ == 1) return 0; int retval = Fl_Printer::start_page(); Fl_PostScript_Graphics_Driver *d = (Fl_PostScript_Graphics_Driver*)driver(); if (count == 1) { m = (int)d->pw_; M = (int)d->ph_; if(m > M) { int x; x = m; m = M; M = x; } } fprintf(d->output, "%%%%PageBoundingBox: 0 0 %d %d\n", m, M); return retval; } int corr_Fl_PostScript_File_Device::start_page() { if (count++ == 1) return 0; int retval = Fl_PostScript_File_Device::start_page(); Fl_PostScript_Graphics_Driver *d = (Fl_PostScript_Graphics_Driver*)driver(); if (count == 1) { m = (int)d->pw_; M = (int)d->ph_; if(m > M) { int x; x = m; m = M; M = x; } } fprintf(d->output, "%%%%PageBoundingBox: 0 0 %d %d\n", m, M); return retval; } #endif // for X11 under 1.3.0 only typedef struct extra_node { double m; // largest root-to-tip length in subtree struct noeud *f; // child directing to largest length m } extra_node_struct; static extra_node_struct *extras; static double best_tip_to_tip; // current best tip-to-tip length static struct noeud *current_r; // node corresponding to best_tip_to_tip static struct noeud *ancestor; // ancestor of current_r node static void traverse_midpoint(struct noeud *parent, struct noeud *centre ) { extra_node_struct *extra = &extras[centre->rank]; struct noeud *left, *right; double ll, lr, ml, mr; if (centre->v1 == parent) { left = centre->v2; right = centre->v3; ll = centre->l2; lr = centre->l3; } else if (centre->v2 == parent) { left = centre->v1; right = centre->v3; ll = centre->l1; lr = centre->l3; } else { left = centre->v1; right = centre->v2; ll = centre->l1; lr = centre->l2; } if (left) traverse_midpoint(centre, left); if (right) traverse_midpoint(centre, right); ml = left ? extras[left->rank].m + ll : 0; mr = right ? extras[right->rank].m + lr : 0; if (ml > mr) { extra->m = ml; extra->f = left; } else { extra->m = mr; extra->f = right; } if (ml + mr > best_tip_to_tip) { best_tip_to_tip = ml + mr; ancestor = parent; current_r = centre; } } static double midpoint_rooting(struct noeud *from, int notu, double *p_root_br_length) { extras = (extra_node_struct*)malloc((2*notu-1)*sizeof(extra_node_struct)); best_tip_to_tip = -10000; traverse_midpoint(NULL, from); struct noeud *node, *tmp, *centre, *left, *right; if (ancestor == NULL) { centre = current_r->v3; right = extras[centre->rank].f; left = current_r; extras[left->rank].f = NULL; } else { centre = current_r; if (centre->v1 == ancestor) { left = centre->v2; right = centre->v3; } else if (centre->v2 == ancestor) {left = centre->v1; right = centre->v3; } else { left = centre->v1; right = centre->v2; } } double ll = 0, lr = 0, lb, laux; node = left; while (node) { tmp = extras[node->rank].f; if (!tmp) { break; } if (node->v1 == tmp) ll += node->l1; else if (node->v2 == tmp) ll += node->l2; else ll += node->l3; node = tmp; } node = right; while (node) { tmp = extras[node->rank].f; if (!tmp) { break; } if (node->v1 == tmp) lr += node->l1; else if (node->v2 == tmp) lr += node->l2; else lr += node->l3; node = tmp; } while ( !(ll <= best_tip_to_tip/2 && lr <= best_tip_to_tip/2) ) { if (ll > lr) { if (right->v1 == centre) lb = right->l1; else if (right->v2 == centre) lb = right->l2; else lb = right->l3; lr += lb; right = centre; centre = left; left = extras[left->rank].f; if (left->v1 == centre) lb = left->l1; else if (left->v2 == centre) lb = left->l2; else lb = left->l3; ll -= lb; } else { if (left->v1 == centre) lb = left->l1; else if (left->v2 == centre) lb = left->l2; else lb = left->l3; ll += lb; left = centre; centre = right; right = extras[right->rank].f; if (right->v1 == centre) lb = right->l1; else if (right->v2 == centre) lb = right->l2; else lb = right->l3; lr -= lb; } } free(extras); if( !left || !right) { current_cote1 = centre; current_cote2 = centre->v3; *p_root_br_length = 0; return 0; } if (left->v1 == centre) laux = left->l1; else if (left->v2 == centre) laux = left->l2; else laux = left->l3; if (right->v1 == centre) lb = right->l1; else if (right->v2 == centre) lb = right->l2; else lb = right->l3; if (lr + lb >= best_tip_to_tip/2) { node = right; ll += laux; current_cote1 = centre; current_cote2 = node; } else { node = left; lr += lb; lb = laux; current_cote1 = node; current_cote2 = centre; } *p_root_br_length = lb; return (best_tip_to_tip/2 - ll) / lb; } char *get_next_tree(FD_nj_plot *fd_nj_plot) { char *next = fd_nj_plot->current_tree; while (isspace(*next)) next++; if (*next == '[') { do next++; while (*next && *next != ']'); } while (*next && *next != '(') next++; if (*next == 0) return NULL; next = nextpar(next); if (next == 0) return NULL; next++; while (*next && *next != ';') next++; if (*next == 0) return NULL; char *p = ++next; while (*p && *p != '(') p++; if (*p == 0) return NULL; fd_nj_plot->current_tree = next; fd_nj_plot->rank++; return next; } void replace_with_new_tree(FD_nj_plot *fd_nj_plot, char *newtree) { char *p, *end = fd_nj_plot->current_tree; int found = -1; while (isspace(*end)) end++; if (*end == '[') { do end++; while (*end != ']'); } while (*end != '(') end++; end = nextpar(end); while (*end != ';') end++; end++; int lnt = strlen(newtree); int le = strlen(end); int l = (fd_nj_plot->current_tree - fd_nj_plot->trees) + lnt + le; if (fd_nj_plot->tree_label) l += strlen(fd_nj_plot->tree_label) + 2; char *s = (char*)malloc(l+1); p = s; if (fd_nj_plot->current_tree > fd_nj_plot->trees) { memcpy(s, fd_nj_plot->trees, fd_nj_plot->current_tree - fd_nj_plot->trees); p += fd_nj_plot->current_tree - fd_nj_plot->trees; } if (fd_nj_plot->tree_label) { sprintf(p, "[%s]", fd_nj_plot->tree_label); p += strlen(p); } memcpy(p, newtree, lnt); p += lnt; memcpy(p, end, le + 1); if (fd_nj_plot->view) { for (int i = 0; i < fd_nj_plot->view->tot_trees; i++) { if (strcmp(fd_nj_plot->trees, fd_nj_plot->view->trees[i]) == 0) { found = i; break; } } } free(fd_nj_plot->trees); free(newtree); fd_nj_plot->current_tree = s + (fd_nj_plot->current_tree - fd_nj_plot->trees); fd_nj_plot->trees = s; if (found >= 0) { free(fd_nj_plot->view->trees[found]); fd_nj_plot->view->trees[found] = strdup(s); } } void tree_counter_callback(Fl_Widget *wid, void *data) { char *p; Fl_Counter *counter = (Fl_Counter*)wid; FD_nj_plot *fd_nj_plot = (FD_nj_plot*)data; if (fd_nj_plot->root_unroot->value() != 0) { fd_nj_plot->root_unroot->value(0); fd_nj_plot->root_unroot->do_callback(); for (int i = 0; i < fd_nj_plot->notu; i++) { strcpy(fd_nj_plot->tabtax[i]->nom, fd_nj_plot->labels[i]); } } p = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); replace_with_new_tree(fd_nj_plot, p); // to preserve reroots/swaps char *oldtree = fd_nj_plot->current_tree; int oldrank = fd_nj_plot->rank; if (counter->value() == fd_nj_plot->rank + 2) p = get_next_tree(fd_nj_plot); else { fd_nj_plot->current_tree = fd_nj_plot->trees; fd_nj_plot->rank = 0; p = fd_nj_plot->trees; while (p && fd_nj_plot->rank < counter->value()-1) { p = get_next_tree(fd_nj_plot); } } if (!p) { counter->bounds(1, fd_nj_plot->rank + 1); if (counter->value() > counter->maximum()) counter->value(counter->maximum()); } else { char *oldtrees = fd_nj_plot->trees; fd_nj_plot->trees = NULL; char *oldname = fd_nj_plot->tree_name; fd_nj_plot->tree_name = NULL; free_tree(fd_nj_plot); fd_nj_plot->trees = oldtrees; fd_nj_plot->tree_name = oldname; const char *mess = preptree(fd_nj_plot); if (mess) { fl_alert("%s", mess); counter->bounds(1, oldrank+1); fd_nj_plot->current_tree = oldtree; preptree(fd_nj_plot); fd_nj_plot->rank = oldrank; counter->value(oldrank+1); fd_nj_plot->need_runtree = TRUE; return; } fd_nj_plot->need_runtree = TRUE; fd_nj_plot->full->setonly(); fd_nj_plot->choix = show_tree; if (fd_nj_plot->has_internal) fd_nj_plot->bt_button->activate(); if (fd_nj_plot->has_br_length) fd_nj_plot->l_button->activate(); fd_nj_plot->panel->window()->redraw(); } } int calc_tree_count(char *tree) { int count = 0; while (TRUE) { while (*tree && isspace(*tree)) tree++; if (*tree == '[') do tree++; while (*tree && *tree != ']'); while (*tree && *tree != '(') tree++; if (*tree == '(') tree = nextpar(tree); while (*tree && *tree != ';') tree++; if (*tree == 0) break; count++; } return count; } /* void check_tree(struct noeud *from, struct noeud *parent) { struct noeud *left, *right; double ll, lr; if(from->v1 == parent) {left = from->v2; right=from->v3; ll=from->l2; lr=from->l3;} else if(from->v2 == parent) {left = from->v1; right=from->v3; ll=from->l1; lr=from->l3;} else {left = from->v1; right=from->v2; ll=from->l1; lr=from->l2;} if (left==NULL && right==NULL) { if(!from->nom[0]) { printf("pb nom\n"); } return; } if (left==gracine || right==gracine) { printf( "pb racine %s\n",from->nom); } if ((!left || !right) && parent) goto bad; if ( left ) { if ( !(left->v1==from || left->v2==from || left->v3==from) ) goto bad; if ( !(left->l1==ll || left->l2==ll || left->l3==ll) ) printf( "bad l %s\n",from->nom); check_tree(left, from); } if ( right ) { if ( !(right->v1==from || right->v2==from || right->v3==from) ) goto bad; if ( !(right->l1==lr || right->l2==lr || right->l3==lr) ) printf( "bad l %s\n",from->nom); check_tree(right, from); } return; bad: printf( "pb %s\n",from->nom); } */ ���������������������������������������������������������������������������������������������������������������������������������seaview/treedraw.h����������������������������������������������������������������������������������000644 �000765 �000024 �00000005543 12476103615 015026� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef TREEDRAW_H #define TREEDRAW_H #include "seaview.h" #include #include #include #include #include #include #define myrint(x) (int)floor(x + 0.5) struct noeud { double l1,l2,l3; struct noeud *v1,*v2,*v3; char *nom; int rank; }; struct nom { double x,y; char *nom; char disp_option; }; struct mon_point { double x,y; int number; }; struct trait { double xd,yd,xf,yf; int width; }; enum operations {show_tree = 1, depl_racine, permutation, subtree, selection, prune_clade, prune_clade_found}; class tree_panel : public Fl_Widget { FL_EXPORT int handle(int); public: FL_EXPORT void draw(void); FL_EXPORT tree_panel(int x,int y,int w,int h) : Fl_Widget(x,y,w,h,NULL) { ; } }; struct FD_nj_plot { char *tree_name; char *tree_label; char *trees; // a Newick string with possibly several trees in it int rank; // rank in trees of current_tree (from 0) char *current_tree; // start of current tree within ->trees string int notu; int totbranches; int has_br_length; int lost_br_lengths; int has_internal; int root_num; int rooted; // true if tree is currently rooted int input_was_rooted; // true if tree read from Newick string was rooted struct noeud **tabtax; struct noeud *racine; char **labels; struct branche *branches; struct nom *noms; struct trait *traits; struct mon_point *points; char *br_length_txt; int totnoms; int totpoints; int tottraits; double deltay; double tek_dx, tek_dy, tek_ymin; int show_bootstrap; int need_runtree; enum operations choix; int *widnames; double *profs; int long_arbre_parenth; /* long de la chaine decrivant l'arbre lu */ struct noeud *subtree_center, *subtree_ascend; int subtree_notu; int plot_br_l; double root_br_l; int char_height; int ascent; int font_size; int font_family; int swap; float bootstrap_threshold; SEA_VIEW *view; Fl_Round_Button *full; Fl_Round_Button *swap_button; Fl_Round_Button *subtree; Fl_Round_Button *select; Fl_Round_Button *new_outgroup; Fl_Button *up; Fl_Check_Button *l_button; Fl_Check_Button *bt_button; tree_panel *panel; void *fd_unrooted; Fl_Scrollbar *scroller; vlength_menu *menu_file; vlength_menu* menu_edit; vlength_menu* menu_font; double zoomvalue; struct noeud *prune_clade_node; int colored_names_1, colored_traits_1, colored_names_2, colored_traits_2; int edit_shape_rank; int center_rank; Fl_Button *select_clade_button, *delete_clade_button, *complete_edit_button; Fl_Simple_Counter *zoom; Fl_Simple_Counter *change_tree; Fl_Choice *root_unroot; int page_count; bool branch_width_as_support; float support_threshold_high; float support_threshold_low; }; extern Fl_Window *treedraw(char *tree, SEA_VIEW *view, const char *name, int from_tree_menu, int count = 1); #endif // TREEDRAW_H �������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/trees.cxx�����������������������������������������������������������������������������������000644 �000765 �000024 �00000262265 12606712305 014711� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef WIN32 #include #endif #include "seaview.h" #include "treedraw.h" #include #include #include #include #include #include #include #include #include extern "C" { #include "phyml_util.h" } typedef enum {observed_pdist, Poisson_pdist, Kimura_pdist} protein_distances; typedef enum {observed_ndist, Jukes_Cantor, Kimura2P, HKY, LogDet, Ka, Ks} nucleotide_distances; typedef enum {more_thorough, less_thorough, rearrange_best_tree} dnapars_S_option; allseq *view_to_allseq(SEA_VIEW *view, int remove_all_gaps); void gaps_as_unknown_states(allseq *phyml_seqs, int protein); void free_after_view_to_allseq(allseq *phyml_seqs); //void initialize_random_series(void); extern "C" { double next_random(void); } void bootstrap_weights(allseq *seqs, int use_codons); void savedistinfile(matrix *mat, const char *dirname, const char *outfname); matrix *calc_dist_matrix(allseq *seqs, int distkind, int protein, char **lwlseqs, int in_bootstrap, char **p_err_mess); void phyml_dialog(SEA_VIEW *view); static void change_searching_callback(Fl_Widget *ob, void *data); static void cancel_callback(Fl_Widget *ob, void *data); static void model_callback(Fl_Widget *ob, void *data); void run_phyml_callback(Fl_Widget *ob, void *data); void distance_method_dialog(SEA_VIEW *view); matrix *run_calc_dist_matrix(allseq *seqs, int distkind, int protein, char **lwlseqs, int in_bootstrap, char **p_err_mess, int no_gui); char *run_distance_method(SEA_VIEW *view, int distkind, int remove_all_gaps, int use_bionj, int use_bootstrap, int replicates, Fl_Box *box, const char *distance_name, int using_kaks, const char* distancefname, const char *user_tree, int no_gui, void (*alert)(const char*, ...), int keep_b_trees ); char *bootstrap_reformat(char *tree, int replicates); matrix *Obs_Dist(allseq *data, model *mod); matrix *Kimura_p_Dist(allseq *data); char *alrt_reformat(char *tree); matrix *K80_dist_nogamma(allseq *data); matrix *HKY_dist(allseq *data); double hky(char* seq1, char* seq2, int lg, int *wght); int freq_obs(char* seq1, char* seq2, double* freq, int lgseq, int *wght); int informative(char** sequ, int nb); void jumble_fct(char** seq, char** name, int notu); static char *run_parsimony_method(SEA_VIEW *view, int nogaps, const char *gapsunknown, int nreplicates, int njumbles, int maxbest, int user_tree, Fl_Box *w_count, dnapars_S_option s_option, const char **pprogname, float consensus_threshold, int no_gui, char **p_bootstrap_trees, void (*alert)(const char *,...) ); void parsimony_dialog(SEA_VIEW *view); char *parsimony_with_jumble(char **pars_seqs, char **pars_names, int n_otu, int njumbles, int protein, int *psteps, int *pcount, int maxbest, Fl_Widget *w_count, dnapars_S_option s_option, int no_gui, float consensus_threshold); static char *parsimony_with_bootstrap(allseq *tmpallseq, char **pars_seqs, char **pars_names, int n_otu, int njumbles, int protein, int *psteps, int maxbest, int replicates, Fl_Box *w_count, int *preplicates_done, dnapars_S_option s_option, int no_gui, float consensus_threshold, int *pcount_best, char **p_bootstrap_trees); double *vector(long nl, long nh); void free_vector(double *v, long nl, long nh); int ludcmp(double **a, int n, int *indx, double *d); double det4(double mat[4][4]); double logdet(char* seq1, char* seq2, int lg, int *wght); matrix *LOGDET_dist(allseq *data); char *put_names_back_in_tree(char *oldtree, char **names); char *replace_tree_names_by_rank(const char *tree, char **names, int notu); void command_line_phylogeny(int argc, char **argv); void save_bootstrap_replicates(const char *fname, int replicates, SEA_VIEW *view); extern void interrupt_callback(Fl_Widget *ob, void *data); extern int save_phylip_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int phylipwidnames); extern int run_external_prog_in_pseudoterm(char *cmd, const char *dialogfname, const char *label); extern int init_add_bootstrap(char *full_tree); extern char *get_res_value(const char *name, const char *def_value); extern int process_one_replicate(char *one_tree, float w); extern char *finish_add_bootstrap(int replicates); extern int compare_newick_with_names(const char *tree, char **names, int notu, char **pname); extern const char *make_binary_or_unrooted(char *arbre); extern int save_resources(void); extern int set_res_value(const char *name, const char *value); extern char *create_tmp_filename(void); extern void delete_tmp_filename(const char *base_fname); extern int is_view_valid(SEA_VIEW *view); char *parsimony(char** seq, char** seqname, int notu, int njumbles, int* steps, char* toevaluate, int arg_maxtrees, int *bt_weights, bool protein, dnapars_S_option s_option, int no_gui, Fl_Widget *w_count); extern int fl_create_thread(void (*f) (void *), void* p, unsigned); extern char *argname(int argc, char *argv[], const char *arg); extern float argval(int argc, char *argv[], const char *arg, float defval); extern bool isarg(int argc, char *argv[], const char *arg); extern SEA_VIEW *cmdline_read_input_alignment(int argc, char **argv); extern void init_consensus_calculation(int n); extern int process_one_consensus_item(char *one_tree, char **seqnames); extern int after_consensus_items(float threshold, int item_count, int ***prows); extern char *compute_consensus_tree(char **seqnames, int **rows, int branch_count); extern "C" { void prefastlwl(void); void loadrl(void); int fastlwl(char **seq, int nbseq, int lgseq, double **ka, double **ks, double **vka, double **vks, int* sat1, int* sat2, int *wght); char* dnapars(char** seq, char** seqname, int notu, int njumbles, int *jumble_no, int *steps, char* toevaluate, int arg_maxtrees, int *bt_weights, dnapars_S_option s_option); char* protpars(char** seq, char** seqname, int notu, int njumbles, int *jumble_no, int *steps, char* toevaluate, int arg_maxtrees, int *bt_weights, dnapars_S_option s_option); char *create_tmp_filename_from_C(void); FILE *fl_fopen_from_C(const char *fname, const char *mode); int fl_unlink_from_C(const char*fname); void awake_from_C(void); } int tree_build_interrupted; char *create_tmp_filename_from_C(void) { return create_tmp_filename(); } FILE *fl_fopen_from_C(const char *fname, const char *mode) { return fl_fopen(fname, mode); } int fl_unlink_from_C(const char*fname) { return fl_unlink(fname); } void trees_callback(Fl_Widget *ob, void *data) /* 0:Distance 1:PhyML 2:import */ { SEA_VIEW *view = (SEA_VIEW *)ob->user_data(); int reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_trees->get_menu(); if(reponse <= 2) { if(view->tot_seqs < 3 || (view->tot_sel_seqs > 0 && view->tot_sel_seqs < 3) ) { fl_alert("Can't draw tree for less than 3 sequences"); return; } for(int i = 0; i < view->tot_seqs; i++) {//check that no ,():; in sequence names if(view->tot_sel_seqs > 0 && !view->sel_seqs[i]) continue; if(strchr(view->seqname[i], '(') != NULL || strchr(view->seqname[i], ')') != NULL || strchr(view->seqname[i], ',') != NULL || strchr(view->seqname[i], ':') != NULL || strchr(view->seqname[i], ';') != NULL) { fl_alert("Sequence: %s\nTrees can't be built with any of (),:; in sequence names", view->seqname[i]); return; } } } if(reponse == 0) {//Parsimony methods for (int i = 0; i < view->tot_seqs; i++) {//check that no repeated sequence names if (view->tot_sel_seqs > 0 && !view->sel_seqs[i]) continue; for (int j = i+1; j < view->tot_seqs; j++) { if (view->tot_sel_seqs > 0 && !view->sel_seqs[j]) continue; if (strcmp(view->seqname[i], view->seqname[j]) == 0) { fl_alert("The parsimony tree can't be computed if different sequences (#%d, #%d) have the same name: %s", i+1, j+1, view->seqname[i]); return; } } } parsimony_dialog(view); } else if(reponse == 1) {//Distance methods distance_method_dialog(view); } else if(reponse == 2) {//PhyML phyml_dialog(view); } else if(reponse == 3) {//Import tree Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file chooser->title("Import treefile"); char *filename = run_and_close_native_file_chooser(chooser); if(filename == NULL) return; FILE *in = fopen(filename, "r"); fseek(in, 0, SEEK_END); long l = ftell(in); fseek(in, 0, SEEK_SET); char *tree = (char *)malloc(l + 1); char c, *p = tree; while((c = fgetc(in)) != EOF) { if(c != '\n' && c != '\r') *(p++) = c; } *p = 0; fclose(in); treedraw(tree, view, extract_filename(filename), FALSE); } else if(reponse == 4) {//New empty tree window treedraw(NULL, view, NULL, FALSE); } else { reponse = ((Fl_Menu_*)ob)->mvalue() - view->menu_trees->vitem(0); char *p = view->trees[reponse]; Fl_Window *w = Fl::first_window(); while(w != NULL) { const char *c = w->xclass(); if(c != NULL && strcmp(c, TREE_WINDOW) == 0 && strcmp( ((FD_nj_plot*)w->user_data())->trees, p) == 0) { w->show(); return; } w = Fl::next_window(w); } char *tree = strdup(p); treedraw(tree, view, ((Fl_Menu_*)ob)->mvalue()->label(), TRUE); } } static void distance_callback(Fl_Widget *wgt, void *data) { if( ((Fl_Choice *)wgt)->value() >= Ka) ((Fl_Widget *)data)->deactivate(); else ((Fl_Widget *)data)->activate(); } static void dist_b_cb(Fl_Widget *wgt, void *data) { Fl_Button *me = (Fl_Button*)wgt; Fl_Button *target = (Fl_Button*)data; if (me->value()) target->activate(); else { target->deactivate(); target->value(0); } } void distance_method_dialog(SEA_VIEW *view) { static int first = TRUE; static int def_replicates = 100; static int distance_choice = Jukes_Cantor; static Fl_Window *w; static Fl_Int_Input *replicates; static Fl_Box *box; static Fl_Choice *distance; static Fl_Check_Button *ignore_all_gaps; static Fl_Round_Button *nj; static Fl_Round_Button *bionj; static Fl_Round_Button *savetofile; static Fl_Round_Button *usertree; static Fl_Choice *treechoice; static Fl_Check_Button *bootstrap; static Fl_Button *interrupt; static Fl_Return_Button *go; static int started, maxchoice; static Fl_Check_Button *keep_b_trees; if(first) { first = FALSE; w = new Fl_Window(250, 240); w->label("Distance analysis"); w->set_modal(); nj = new Fl_Round_Button(3, 3, 60, 20, "NJ"); nj->type(FL_RADIO_BUTTON); bionj = new Fl_Round_Button(nj->x() + nj->w() + 10, nj->y(), nj->w(), nj->h(), "BioNJ"); bionj->type(FL_RADIO_BUTTON); savetofile = new Fl_Round_Button(bionj->x() + bionj->w() + 10, nj->y(), 110, nj->h(), "Save to File"); savetofile->type(FL_RADIO_BUTTON); distance = new Fl_Choice(90, nj->y() + nj->h() + 15, 100, 20, "Distance"); distance->align(FL_ALIGN_LEFT); ignore_all_gaps = new Fl_Check_Button(160, distance->y() + distance->h() + 5, 50, 20, "ignore all gap sites"); ignore_all_gaps->value(1); ignore_all_gaps->align(FL_ALIGN_LEFT); int y = ignore_all_gaps->y() + ignore_all_gaps->h() + 25; bootstrap = new Fl_Check_Button(3, y, 80, 20, "Bootstrap"); replicates = new Fl_Int_Input(bootstrap->x() + bootstrap->w() + 5, y, 100, 20, "# of replicates"); replicates->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); char tmp[10]; sprintf(tmp, "%d", def_replicates); replicates->value(tmp); keep_b_trees = new Fl_Check_Button(3, bootstrap->y() + bootstrap->h() + 5, 180, 20, "Show bootstrap trees"); keep_b_trees->deactivate(); bootstrap->callback(dist_b_cb, keep_b_trees); bootstrap->when(FL_WHEN_CHANGED); box = new Fl_Box(3, keep_b_trees->y() + keep_b_trees->h() + 5, 150, 20, ""); usertree = new Fl_Round_Button(nj->x(), box->y() + box->h() + 15, 85, nj->h(), "User tree:"); usertree->type(FL_RADIO_BUTTON); treechoice = new Fl_Choice(usertree->x() + usertree->w(), usertree->y(), 155, 20, "Optimize branch lengths"); treechoice->align(FL_ALIGN_TOP|FL_ALIGN_RIGHT); bionj->setonly(); interrupt = new Fl_Button(3, w->h() - 25, 70, 20, ""); interrupt->callback(interrupt_callback, &tree_build_interrupted); go = new Fl_Return_Button(w->w() - 70 - 3, interrupt->y() , 70, 20, "Go"); go->callback(interrupt_callback, &started); w->end(); w->callback(interrupt_callback, &tree_build_interrupted); } interrupt->label("Cancel"); distance->clear(); if(view->protein) { distance->add("Observed"); distance->add("Poisson"); distance->add("Kimura"); maxchoice = Kimura_pdist; ignore_all_gaps->activate(); } else { distance->add("Observed"); distance->add("J-C"); distance->add("K2P"); distance->add("HKY"); distance->add("LogDet"); distance->add("Ka"); distance->add("Ks"); maxchoice = Ks; } distance->value( FL_min(distance_choice, maxchoice) ); distance->callback(distance_callback, ignore_all_gaps); keep_b_trees->value(0); treechoice->clear(); vlength_menu *vmenu = view->menu_trees; int count = view->menu_trees->vlength(); for (int i = 0; i < count; i++) treechoice->add( vmenu->vitem(i)->label() ); treechoice->value(0); treechoice->deactivate(); bootstrap->activate(); if (usertree->value()) bionj->setonly(); if (count) usertree->activate(); else usertree->deactivate(); started = tree_build_interrupted = 0; box->label(""); go->show(); w->show(); while(!started && !tree_build_interrupted) { Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); else if(o == usertree || o == nj || o == bionj || o == savetofile) { if( usertree->value() || savetofile->value() ) { bootstrap->value(0); bootstrap->deactivate(); bootstrap->do_callback(); } else { bootstrap->activate(); } if( usertree->value() ) { treechoice->activate(); } else { treechoice->deactivate(); } } } distance_choice = distance->value(); int using_kaks = ((!view->protein) && (distance_choice == Ka || distance_choice == Ks) ); if(!tree_build_interrupted) { sscanf(replicates->value(), "%d", &def_replicates); interrupt->label("Interrupt"); if(bootstrap->value()) { box->label("Count: 0"); } go->hide(); Fl::flush(); char *tree = run_distance_method(view, distance_choice, ignore_all_gaps->value(), bionj->value(), bootstrap->value(), def_replicates, box, distance->text(), using_kaks, savetofile->value()?"":NULL, usertree->value() ? view->trees[treechoice->value()] : NULL, false, fl_alert, keep_b_trees->value()); const char *choice = bionj->value()? "BioNJ_tree" : "NJ_tree"; const char *n = extract_filename(view->masename); char *title = NULL; if (usertree->value()) { title = new char[20]; strcpy(title, "Least_squares_brl");} else if (n) { char *q = (char*)strchr(n, '.'); if (q) *q = 0; title = new char[strlen(n) + 12]; sprintf(title, "%s-%s", n, choice); if (q) *q = '.'; } Fl_Window *treew = NULL; if (tree) treew = treedraw(tree, view, n || usertree->value() ? title:choice, FALSE); #if !defined(__APPLE__) if (keep_b_trees->value() && treew) { treew->position(treew->x() + 40, treew->y()); } #endif delete[] title; } w->hide(); } struct dist_struct { allseq *seqs; int distkind; int protein; char **lwlseqs; int in_bootstrap; char *err_mess; matrix *result; bool done; }; void prep_calc_dist_matrix(dist_struct *ds) { ds->result = calc_dist_matrix(ds->seqs, ds->distkind, ds->protein, ds->lwlseqs, ds->in_bootstrap, &(ds->err_mess)); if (tree_build_interrupted && ds->result) { Free_Mat(ds->result); ds->result = NULL; } Fl::lock(); ds->done = true; Fl::awake(); Fl::unlock(); } matrix *run_calc_dist_matrix(allseq *seqs, int distkind, int protein, char **lwlseqs, int in_bootstrap, char **p_err_mess, int no_gui) { dist_struct *ds = new dist_struct; ds->seqs = seqs; ds->distkind = distkind; ds->protein = protein; ds->lwlseqs =lwlseqs; ds->in_bootstrap = in_bootstrap; ds->err_mess = NULL; ds->result = NULL; ds->done = false; tree_build_interrupted = false; if (no_gui) { ds->result = calc_dist_matrix(ds->seqs, ds->distkind, ds->protein, ds->lwlseqs, ds->in_bootstrap, &(ds->err_mess)); } else { fl_create_thread( (void (*)(void*))prep_calc_dist_matrix, ds, 0); while (!ds->done) Fl::wait(); } matrix* m = ds->result; if (p_err_mess) *p_err_mess = ds->err_mess; delete ds; return m; } char *run_distance_method(SEA_VIEW *view, int distkind, int remove_all_gaps, int use_bionj, int use_bootstrap, int replicates, Fl_Box *box, const char *distance_name, int using_kaks, const char* distancefname, const char *user_tree, int no_gui, void (*alert)(const char*, ...), int keep_b_trees ) { char *display_tree, *bootstrap_trees = NULL, *err_mess, tree_label[100]=""; int total = 0, i, j, lbtrees; char **lwlseqs = NULL; if(using_kaks) remove_all_gaps = FALSE;//keep gaps not to alter reading frame allseq *phyml_seqs = view_to_allseq(view, remove_all_gaps); if(use_bootstrap) {//for bootstrap, seq names must be all distinct for(i = 0; i < phyml_seqs->n_otu - 1; i++) { for(j = i+1; j < phyml_seqs->n_otu; j++) { if(strcmp(phyml_seqs->c_seq[i]->name, phyml_seqs->c_seq[j]->name) == 0) { alert("Can't run bootstrap because sequence name %s is used twice", phyml_seqs->c_seq[i]->name); free_after_view_to_allseq(phyml_seqs); return NULL; } } } } if(using_kaks) { lwlseqs = (char **)malloc(phyml_seqs->n_otu * sizeof(char *)); for(i = 0; i < phyml_seqs->n_otu; i++) lwlseqs[i] = phyml_seqs->c_seq[i]->state; } matrix *phyml_mat = run_calc_dist_matrix(phyml_seqs, distkind, view->protein, lwlseqs, FALSE, &err_mess, no_gui); if(phyml_mat == NULL) { free_after_view_to_allseq(phyml_seqs); if( using_kaks ) { free(lwlseqs); if (err_mess) { alert("%s", err_mess); delete[] err_mess; } } else if (!tree_build_interrupted) alert("Can't compute distances because sequences are too divergent.\nAre they aligned?"); return NULL; } if(user_tree != NULL) {//process user tree extern char *least_squares_brl(const char *tree, int nbseq, double **dist, char **names); char *p, **usednames; int i, j; p = (char *)user_tree; if(*p== '[')p=strchr(p,']')+1; if(view->tot_sel_seqs > 0) { usednames = (char **)malloc(view->tot_sel_seqs * sizeof(char *)); j = 0; for(i = 0; i < view->tot_seqs; i++) { if(view->sel_seqs[i]) usednames[j++] = view->seqname[i]; } } else usednames = view->seqname; p = least_squares_brl(p, phyml_seqs->n_otu, phyml_mat->dist, usednames); if(view->tot_sel_seqs > 0) free(usednames); if(p != NULL) { display_tree = (char *)malloc(strlen(p) + strlen(distance_name) + 60); sprintf(display_tree, "[User-tree w/ least-squares br lengths, %d sites %s]%s", phyml_seqs->clean_len, distance_name, p); free(p); if (box) box->window()->hide();//necessary under X11 so tree is in foreground } Free_Mat(phyml_mat); free_after_view_to_allseq(phyml_seqs); return display_tree; } if(distancefname) { savedistinfile(phyml_mat, extract_dirname(view->masename), no_gui ? distancefname : NULL); Free_Mat(phyml_mat); free_after_view_to_allseq(phyml_seqs); return NULL; } phyml_mat->method = !use_bionj; //1:NJ 0:BioNJ phyml_mat->tree = Make_Tree_From_Scratch(phyml_seqs->n_otu, phyml_seqs); Bionj(phyml_mat); sprintf(tree_label, "%s %d sites %s", use_bionj ? "BioNJ" : "NJ", phyml_seqs->clean_len, distance_name ); if (use_bootstrap) { char *full_tree = Write_Tree(phyml_mat->tree); Free_Tree(phyml_mat->tree); Free_Mat(phyml_mat); int error = init_add_bootstrap(full_tree); free(full_tree); if(!error) { char *p; for (int r = 0; r < replicates; r++) { if (tree_build_interrupted) break; bootstrap_weights(phyml_seqs, using_kaks ); phyml_mat = run_calc_dist_matrix(phyml_seqs, distkind, view->protein, lwlseqs, TRUE, &err_mess, no_gui); if(phyml_mat == NULL) { if (!tree_build_interrupted) total = 0; break; } phyml_mat->method = ! use_bionj; //1:NJ 0:BioNJ phyml_mat->tree = Make_Tree_From_Scratch(phyml_seqs->n_otu, phyml_seqs); Bionj(phyml_mat); char *one_replicate_tree = Write_Tree(phyml_mat->tree); if (keep_b_trees) { if (r == 0) { lbtrees = replicates * (strlen(one_replicate_tree) + 1); bootstrap_trees = (char *)malloc(lbtrees + 1); p = bootstrap_trees; *p = 0; } int l = strlen(one_replicate_tree); if ((p-bootstrap_trees) + l + 1 > lbtrees) { lbtrees = (p-bootstrap_trees) + l + 1000; bootstrap_trees = (char*)realloc(bootstrap_trees, lbtrees + 1); p = bootstrap_trees + strlen(bootstrap_trees); } memcpy(p, one_replicate_tree, l); p += l; *p++ = '\n'; *p = 0; } Free_Tree(phyml_mat->tree); Free_Mat(phyml_mat); total += process_one_replicate(one_replicate_tree, 1.); free(one_replicate_tree); char newbox[20]; sprintf(newbox,"Count: %d", total); if (box) { box->label(newbox); box->redraw(); Fl::wait(0); } } } if(total > 0) { display_tree = finish_add_bootstrap(total); sprintf(tree_label + strlen(tree_label), " %d repl.", total); } else display_tree = NULL; } else { display_tree = Write_Tree(phyml_mat->tree); Free_Tree(phyml_mat->tree); Free_Mat(phyml_mat); } free_after_view_to_allseq(phyml_seqs); if(using_kaks) { free(lwlseqs); } if(display_tree == NULL) { if( !using_kaks) alert("Can't compute distances because sequences are too divergent.\nAre they aligned?"); return NULL; } //add label to tree char *tree = (char *)malloc(strlen(tree_label) + strlen(display_tree) + 4); sprintf(tree, "[%s] %s", tree_label, display_tree); free(display_tree); if (box) box->window()->hide();//necessary under X11 so tree is in foreground if (bootstrap_trees) { treedraw(bootstrap_trees, view, "bootstrap trees", FALSE); } return tree; } void savedistinfile(matrix *mat, const char *dirname, const char *outfname) { FILE *out; int i, j; if (!outfname) { Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); chooser->title("Set distance output filename"); chooser->directory(dirname); chooser->preset_file("seqs.dist"); outfname = run_and_close_native_file_chooser(chooser); if(outfname == NULL) return; } out = fopen(outfname, "w"); if(out == NULL) return; fputs("#distances order: d(1,2),...,d(1,n) d(2,3),...,d(2,n) ...\n", out); fprintf(out, "%d\n", mat->n_otu); for( i = 0; i < mat->n_otu - 1; i++) { for( j = i + 1; j < mat->n_otu; j++) { fprintf(out, "%.6f ", mat->dist[i][j]); } fputs("\n", out); } for( i = 0; i < mat->n_otu ; i++) { fprintf(out, "%s ", mat->name[i]); } fputs("\n\n", out); fputs("#pairwise distances\n", out); for (i = 0; i < mat->n_otu; i++) { for (j = i + 1; j < mat->n_otu; j++) { char *n1 = mat->name[i]; char *n2 = mat->name[j]; if (strcmp(n1, n2) > 0) { char *p = n1; n1 = n2; n2 = p; } fprintf(out, "%s,%s: %f\n", n1, n2, mat->dist[i][j]); } } fclose(out); } matrix *calc_dist_matrix(allseq *seqs, int distkind, int protein, char **lwlseqs, int in_bootstrap, char **p_err_mess) { matrix *phyml_mat = NULL; if(distkind == observed_pdist || distkind == observed_ndist) {//observed model jcmodel; jcmodel.stepsize = 1; jcmodel.datatype = (protein ? 1 : 0); jcmodel.ns = (protein ? 20 : 4); phyml_mat = Obs_Dist(seqs, &jcmodel); } else if(distkind == Kimura_pdist ) {//Kimura protein distance phyml_mat = Kimura_p_Dist(seqs); if(phyml_mat == NULL) return NULL; } else if(distkind == Poisson_pdist || distkind == Jukes_Cantor) {//JC or Poisson model jcmodel; jcmodel.stepsize = 1; jcmodel.datatype = (protein ? 1 : 0); jcmodel.ns = (protein ? 20 : 4); phyml_mat = JC69_Dist(seqs, &jcmodel); if(phyml_mat == NULL) return NULL; } else if((distkind == Kimura2P) && ! protein) {//K2P phyml_mat = K80_dist_nogamma(seqs); if(phyml_mat == NULL) return NULL; } else if(distkind == HKY && ! protein) {//HKY phyml_mat = HKY_dist(seqs); if(phyml_mat == NULL) return NULL; } else if(distkind == LogDet && ! protein) {//LogDet phyml_mat = LOGDET_dist(seqs); if(phyml_mat == NULL) return NULL; } else if( (distkind == Ka || distkind == Ks) && ! protein) {//Ka or Ks int sat1, sat2, count = 0, err = 0, i, j; int l3 = 3*(seqs->clean_len / 3);//dismiss partial last codon *p_err_mess = NULL; static int first = TRUE; if(first) { first = FALSE; loadrl(); // needed once only prefastlwl(); } phyml_mat = Make_Mat(seqs->n_otu); Init_Mat(phyml_mat, seqs); // Ks distances can become saturated, re-run a bootstrap replicate in this case at most 50 times do { if(in_bootstrap && err) bootstrap_weights(seqs, TRUE ); count++; if(distkind == Ka) //Ka err = fastlwl(lwlseqs, seqs->n_otu, l3, phyml_mat->dist, NULL, NULL, NULL, &sat1, &sat2, seqs->wght); else //Ks err = fastlwl(lwlseqs, seqs->n_otu, l3, NULL, phyml_mat->dist, NULL, NULL, &sat1, &sat2, seqs->wght); } while (in_bootstrap && err && count <=50); if (err) { if (!in_bootstrap && !tree_build_interrupted) { char *err_mess = new char[200]; snprintf(err_mess, 200, "Saturation between %s and %s", phyml_mat->name[sat1], phyml_mat->name[sat2]); *p_err_mess = err_mess; } Free_Mat(phyml_mat); return NULL; } for(i = 0; i < seqs->n_otu - 1; i++) { for(j = i + 1; j < seqs->n_otu; j++) { phyml_mat->dist[j][i] = phyml_mat->dist[i][j]; } } for(i = 0; i < seqs->n_otu; i++) phyml_mat->dist[i][i] = 0; } return phyml_mat; } /* a window where the return key always triggers a button */ class return_window : public Fl_Window { Fl_Return_Button *run_button; public: return_window(int w, int h, const char *t) : Fl_Window(w, h, t) {} void run(Fl_Return_Button *b) { run_button = b; } int handle(int event) { if (event == FL_KEYBOARD && (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) { run_button->do_callback(); return 1; } return Fl_Window::handle(event); } }; Fl_Input *name; Fl_Choice *mymodel; Fl_Round_Button *b_alrt; Fl_Round_Button *b_no; Fl_Int_Input *b_count; Fl_Round_Button *f_empir; Fl_Round_Button *r_estim; Fl_Float_Input *r_val; Fl_Round_Button *i_no; Fl_Round_Button *i_estim; Fl_Float_Input *i_val; Fl_Round_Button *g_no; Fl_Choice *g_cats; Fl_Round_Button *a_est; Fl_Float_Input *a_val; Fl_Round_Button *nni_b, *spr_b, *nni_spr_b; Fl_Round_Button *u_bionj, *u_menutree, *u_random; Fl_Choice *u_choice; Fl_Check_Button *u_optimize, *u_quiet, *b_keep_trees; Fl_Int_Input *u_random_count; char *phyml_path; static void support_cb(Fl_Widget *wid, void *data) { Fl_Button *b = (Fl_Button*)data; if (b->value()) b_keep_trees->activate(); else { b_keep_trees->deactivate(); b_keep_trees->value(0); } } void phyml_dialog(SEA_VIEW *view) { int y = 3; static int first = TRUE; if(first) { char *p, *q; p = get_res_value("phyml", #ifdef WIN32 "PhyML-3.1_win32.exe" #elif defined(__APPLE__) #ifdef __ppc__ "phyml_3.0_universal" #else "PhyML-3.1_macOS-MountainLion" #endif #elif defined(sparc) "phyml_3.0_sparc" #else #ifndef PHYMLNAME #ifdef __i386__ #define PHYMLNAME "PhyML-3.1_linux32" #else #define PHYMLNAME "PhyML-3.1_linux64" #endif #endif PHYMLNAME #endif ); #ifdef __APPLE__ if (fl_mac_os_version < 100800) p = (char*)"phyml_3.0_universal"; #elif defined(__linux__) if ((q = get_full_path(p)) == NULL) p = (char*)"phyml"; #endif if ((q = get_full_path(p)) == NULL) { int rep = fl_choice("Seaview does not find PhyML under the name %s.\n" "Is PhyML available on your computer ?", "No", "Available", NULL, p); if(rep == 0) return; Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); chooser->type(Fl_Native_File_Chooser::BROWSE_FILE); // let user browse a single file chooser->title("Find PhyML on your computer"); q = run_and_close_native_file_chooser(chooser); if(q == NULL) return; set_res_value("phyml", q); save_resources(); } first = FALSE; phyml_path = (char *)malloc(strlen(q) + 3); sprintf(phyml_path, "\"%s\"", q); } return_window *w = new return_window(270,130, "PhyML options"); w->set_modal(); //model mymodel = new Fl_Choice(50, y, 90, 20, "Model:"); mymodel->align(FL_ALIGN_LEFT); if(view->protein) { mymodel->add("LG"); mymodel->add("WAG"); mymodel->add("Dayhoff"); mymodel->add("JTT"); mymodel->add("Blosum62"); mymodel->add("MtREV"); mymodel->add("RtREV"); mymodel->add("CpREV"); mymodel->add("DCMut"); mymodel->add("VT"); mymodel->add("MtMam"); mymodel->add("MtArt"); mymodel->add("HIVw"); mymodel->add("HIVb"); mymodel->add("FLU"); mymodel->value(0); } else { mymodel->add("JC69"); mymodel->add("K80"); mymodel->add("F81"); mymodel->add("HKY85"); mymodel->add("F84"); mymodel->add("TN93"); mymodel->add("GTR"); mymodel->value(6); } y += mymodel->h() + 25; //bootstrap Fl_Group *b_group = new Fl_Group(0, y, w->w(), 75, "Branch Support"); b_group->box(FL_ROUNDED_BOX); b_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; b_alrt = new Fl_Round_Button(3, y, 110, 20, "aLRT (SH-like)"); b_alrt->type(FL_RADIO_BUTTON); b_no = new Fl_Round_Button(b_alrt->x() + b_alrt->w() + 10, y, 60, 20, "None"); b_no->type(FL_RADIO_BUTTON); y += b_alrt->h() + 3; Fl_Round_Button *b_yes = new Fl_Round_Button(3, y, 115, 20, "Bootstrap with"); b_yes->type(FL_RADIO_BUTTON); b_alrt->setonly(); b_count = new Fl_Int_Input(b_yes->x() + b_yes->w() + 5, y, 50, 20, "replicates"); b_count->align(FL_ALIGN_RIGHT); b_count->static_value("100"); y += b_count->h(); b_keep_trees = new Fl_Check_Button(b_yes->x(), y, 180, 20, "Show bootstrap trees"); b_keep_trees->deactivate(); b_alrt->callback(support_cb, b_yes); b_no->callback(support_cb, b_yes); b_yes->callback(support_cb, b_yes); b_group->end(); y += b_count->h() + 30; // freq + Ts/Tv group Fl_Group *fr_group = new Fl_Group(0, y, w->w(), 75, ""); // frequencies group Fl_Group *f_group = new Fl_Group(0, y, w->w(), 30, view->protein?"Amino acid equilibrium frequencies":"Nucleotide equilibrium frequencies"); f_group->box(FL_ROUNDED_BOX); f_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; f_empir = new Fl_Round_Button(3, y, 85, 20, "Empirical"); f_empir->type(FL_RADIO_BUTTON); Fl_Round_Button *f_m = new Fl_Round_Button(f_empir->x() + f_empir->w() + 5, y, 60, 20, view->protein?"Model-given":"Optimized"); f_m->type(FL_RADIO_BUTTON); (view->protein?f_m:f_empir)->setonly(); f_group->end(); y += f_group->h() + 15; //Ts/Tv ratio Fl_Group *r_group = new Fl_Group(0, y, w->w(), 30, "Ts/Tv ratio"); r_group->box(FL_ROUNDED_BOX); r_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; r_estim = new Fl_Round_Button(3, y, 85, 20, "Optimized"); r_estim->type(FL_RADIO_BUTTON); Fl_Round_Button *r_fix = new Fl_Round_Button(r_estim->x() + r_estim->w() + 5, y, 60, 20, "Fixed"); r_fix->type(FL_RADIO_BUTTON); r_fix->setonly(); r_val = new Fl_Float_Input(r_fix->x() + r_fix->w() + 10, y, 40, 20, ""); r_val->value("4.0"); r_group->end(); r_group->deactivate(); if (view->protein) r_group->hide(); else y += r_group->h() + 15; fr_group->end(); if (!view->protein) mymodel->callback(model_callback, fr_group); //invariable Fl_Group *i_group = new Fl_Group(0, y, w->w(), 30, "Invariable sites"); i_group->box(FL_ROUNDED_BOX); i_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; i_no = new Fl_Round_Button(3, y, 52, 20, "None"); i_no->type(FL_RADIO_BUTTON); i_estim = new Fl_Round_Button(i_no->x() + i_no->w() + 5, y, 85, 20, "Optimized"); i_estim->type(FL_RADIO_BUTTON); Fl_Round_Button *i_fix = new Fl_Round_Button(i_estim->x() + i_estim->w() + 2, y, 60, 20, "Fixed"); i_fix->type(FL_RADIO_BUTTON); i_no->setonly(); i_val = new Fl_Float_Input(i_fix->x() + i_fix->w() + 10, y, 40, 20, ""); i_val->value("0.10"); i_group->end(); y += i_group->h() + 15; //gamma categories Fl_Group *g_group = new Fl_Group(0, y, w->w(), 55, "Across site rate variation"); g_group->box(FL_ROUNDED_BOX); g_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; g_no = new Fl_Round_Button(3, y, 75, 20, "None"); g_no->type(FL_RADIO_BUTTON); g_cats = new Fl_Choice(g_no->x() + g_no->w() + 130, y, 50, 20, "# of rate categories"); mymodel->align(FL_ALIGN_LEFT); g_cats->add("4"); g_cats->add("6"); g_cats->add("8"); g_cats->add("10"); g_cats->add("12"); g_cats->value(0); y = g_cats->y() + g_cats->h() + 5; a_est = new Fl_Round_Button(3, y, 85, 20, "Optimized"); a_est->type(FL_RADIO_BUTTON); a_est->setonly(); Fl_Round_Button *a_fixed = new Fl_Round_Button(a_est->x() + a_est->w() + 5, y, 60, 20, "Fixed"); a_fixed->type(FL_RADIO_BUTTON); a_val = new Fl_Float_Input(a_fixed->x() + a_fixed->w() + 10, y, 40, 20, ""); a_val->value("2.0"); g_group->end(); y += a_val->h() + 25; //tree searching Fl_Group *s_group = new Fl_Group(0, y, w->w(), 35, "Tree searching operations"); s_group->box(FL_ROUNDED_BOX); s_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; nni_b = new Fl_Round_Button(3, y, 45, 20, "NNI"); nni_b->type(FL_RADIO_BUTTON); spr_b = new Fl_Round_Button(nni_b->x() + nni_b->w() + 5, y, 50, 20, "SPR"); spr_b->type(FL_RADIO_BUTTON); nni_spr_b = new Fl_Round_Button(spr_b->x() + spr_b->w() + 5, y, 150, 20, "Best of NNI && SPR"); nni_spr_b->type(FL_RADIO_BUTTON); nni_b->setonly(); nni_b->callback(change_searching_callback, NULL); spr_b->callback(change_searching_callback, NULL); nni_spr_b->callback(change_searching_callback, NULL); s_group->end(); y = s_group->y() + s_group->h() + 5; //starting tree y += 15; Fl_Group *u_group = new Fl_Group(0, y, w->w(), 80, "Starting tree"); u_group->box(FL_ROUNDED_BOX); u_group->align(FL_ALIGN_TOP|FL_ALIGN_CENTER); y += 5; u_bionj = new Fl_Round_Button(3, y, 45, 20, "BioNJ"); u_bionj->type(FL_RADIO_BUTTON); u_bionj->setonly(); u_optimize = new Fl_Check_Button(u_bionj->x() + u_bionj->w() + 30, y, 170, 20, "Optimize tree topology"); u_optimize->value(1); y += u_bionj->h() + 5; u_menutree = new Fl_Round_Button(3, y, 95, 20, "User given:"); u_menutree->type(FL_RADIO_BUTTON); u_choice = new Fl_Choice(u_menutree->x() + u_menutree->w() + 5, y, 100, 20, ""); vlength_menu *vmenu = view->menu_trees; int count = view->menu_trees->vlength(); for(int i = 0; i < count; i++) u_choice->add( vmenu->vitem(i)->label() ); u_choice->value(0); if(count <= 0) {u_menutree->deactivate(); u_choice->deactivate(); } u_random = new Fl_Round_Button(3, u_menutree->y() + u_menutree->h() + 5, 80, 20, "Add: "); u_random->deactivate(); u_random->type(FL_RADIO_BUTTON); u_random_count = new Fl_Int_Input(u_random->x() + u_random->w(), u_random->y(), 35, 20, "random starts"); u_random_count->align(FL_ALIGN_RIGHT); u_random_count->value("5"); u_group->end(); y = u_group->y() + u_group->h() + 5; // Run Fl_Button *cancel = new Fl_Button(3, y, 50, 20, "Cancel"); cancel->callback(cancel_callback, NULL); Fl_Return_Button *ok = new Fl_Return_Button(w->w() - 60, y, 55, 20, "Run"); w->run(ok); ok->callback(run_phyml_callback, view); u_quiet = new Fl_Check_Button(cancel->x() + cancel->w() + 40, y, 65, 20, "Quiet"); u_quiet->value(0); #ifndef WIN32 //u_quiet->hide(); #endif w->end(); w->size(w->w(), y + cancel->h() + 5); w->callback(cancel_callback, NULL); w->show(); } static void change_searching_callback(Fl_Widget *ob, void *unused) { if(ob == nni_b) u_random->deactivate(); else u_random->activate(); } static void cancel_callback(Fl_Widget *ob, void *data) { Fl_Window *w = ob->window(); if(w == NULL) w = (Fl_Window *)ob; w->hide(); Fl::delete_widget(w); } static void model_callback(Fl_Widget *ob, void *data) { Fl_Choice *c = (Fl_Choice *)ob; Fl_Group *fr_group = (Fl_Group*)data; Fl_Group *f_group = (Fl_Group *)fr_group->child(0); Fl_Group *r_group = (Fl_Group *)fr_group->child(1); int v = c->value(); if (v >=0 && v <= 2) f_group->deactivate(); else f_group->activate(); if (v == 1 || v == 3 || v == 4 || v == 5) r_group->activate(); else r_group->deactivate(); } void run_phyml_callback(Fl_Widget *ob, void *data) { FILE *in; SEA_VIEW *view = (SEA_VIEW *)data; char input[PATH_MAX], base_fname[PATH_MAX], invar[10], alpha[10], *p; int replicates, cats, status, seqlen, user_tree = FALSE, i; float logL; char **tmpseqs, **tmpnames, **truenames; int tot_seqs = view->tot_seqs; p = create_tmp_filename(); if(p == NULL) return; strcpy(base_fname, p); strcpy(input, base_fname); strcat(input, ".phy"); region r, *pr = &r; list_segments ls; if(view->tot_sel_seqs > 0 && view->active_region == NULL) { ls.debut = 1; ls.fin = view->seq_length; ls.next = NULL; r.list = &ls; } else { pr = view->active_region; } if(pr != NULL) { list_segments *pls; pls = pr->list; seqlen = 0; while(pls != NULL) { seqlen += pls->fin - pls->debut + 1; pls = pls->next; } } else seqlen = view->seq_length; //remove * from saved protein data if(view->protein) { tmpseqs = (char **)calloc(view->tot_seqs, sizeof(char *)); for( i = 0; i < view->tot_seqs; i++) { if(view->tot_sel_seqs > 0 && !view->sel_seqs[i]) continue; tmpseqs[i] = strdup(view->sequence[i]); char *p = tmpseqs[i]; while((p = strchr(p, '*')) != NULL) *p = '-'; } } else tmpseqs = view->sequence; //Use Seq##_ as sequence names tmpnames = (char **)calloc(view->tot_seqs, sizeof(char *)); //memorize seq names because can be changed while phyml runs truenames = (char **)calloc(view->tot_seqs, sizeof(char *)); int length = 0; for(i = 0; i < view->tot_seqs; i++) { if(view->tot_sel_seqs > 0 && !view->sel_seqs[i]) continue; tmpnames[i] = (char *)malloc(15); truenames[i] = strdup(view->seqname[i]); sprintf(tmpnames[i], "Seq%d_", i); length = FL_max(length, (int)strlen(tmpnames[i])); } status = save_phylip_file(input, tmpseqs, tmpnames, view->tot_seqs, view->each_length, pr, view->sel_seqs, view->tot_sel_seqs, length); for(i = 0; i < view->tot_seqs; i++) if(tmpnames[i] != NULL) free(tmpnames[i]); free(tmpnames); if(view->protein) { for( i = 0; i < view->tot_seqs; i++) { if(tmpseqs[i] != NULL) free(tmpseqs[i]); } free(tmpseqs); } if(status) goto way_out; if(b_alrt->value()) replicates = -4; else if (b_no->value()) replicates = 0; else sscanf(b_count->value(), "%d", &replicates); if (!u_optimize->value()) replicates = 0; if(i_no->value()) strcpy(invar, "0.0"); else if(i_estim->value()) strcpy(invar, "e"); else strcpy(invar, i_val->value()); if(g_no->value()) { cats = 1; strcpy(alpha, "2.0"); } else { sscanf(g_cats->mvalue()->label(), "%d", &cats); if(a_est->value()) strcpy(alpha, "e"); else strcpy(alpha, a_val->value()); } char modelname[20], *args; strcpy(modelname, mymodel->mvalue()->label()); //build command line args = (char *)malloc(1000); sprintf(args, "%s -d %s -m %s -b %d -v %s -c %d -a %s", phyml_path, view->protein?"aa":"nt", modelname, replicates, invar, cats, alpha); if( (!view->protein) && (strcmp(modelname,"K80")==0 || strcmp(modelname,"HKY85")==0 || strcmp(modelname,"F84")==0 || strcmp(modelname,"TN93")==0) ) { if(r_estim->value()) { strcat(args, " -t e"); } else { sprintf(args + strlen(args), " -t %s", r_val->value()); } } if( (view->protein) || (strcmp(modelname,"JC69")!=0 && strcmp(modelname,"K80")!=0 && strcmp(modelname,"F81")!=0) ) { if(f_empir->value()) { strcat(args, " -f e"); } else { strcat(args, " -f m"); } } if(spr_b->value()) strcat(args, " -s SPR"); else if(nni_spr_b->value()) strcat(args, " -s BEST"); if(!u_optimize->value()) { strcat(args, " -o lr"); user_tree = TRUE; } if (u_quiet->value()) strcat(args, " --quiet"); if(u_menutree->value()) { char *tree = view->trees[u_choice->value()]; if(*tree == '[' && (p = strchr(tree, ']')) != NULL) { //remove tree header tree = p + 1; while(*tree == ' ') tree++; } tree = replace_tree_names_by_rank(tree, view->seqname, view->tot_seqs); if(tree == NULL) { fl_alert("Names in starting tree and alignment don't match.\nStarting tree will be ignored."); } else { char tmp[PATH_MAX]; sprintf(tmp, "%s.startingtree", base_fname); FILE *out = fopen(tmp, "w"); fputs(tree, out); free(tree); fclose(out); sprintf(args + strlen(args), " -u \"%s\"", tmp); } } if(u_random->value()) { sprintf(args + strlen(args), " --rand_start --n_rand_starts %d", atoi(u_random_count->value())); } //finish with (long) input filename sprintf(args + strlen(args), " -i \"%s\"", input); ob->window()->hide(); //deletion of this window should be done totally at the end of this callback status = run_external_prog_in_pseudoterm(args, NULL, "tree-building"); free(args); sprintf(input, "%s.phy_phyml_stats.txt", base_fname); in = fopen(input, "r"); if (in == NULL) { sprintf(input, "%s.phy_phyml_stat.txt", base_fname); in = fopen(input, "r"); } logL = 0; if(in != NULL) {//search tree likelihood while(TRUE) { char line[100]; p = fgets(line, sizeof(line), in); if(p == NULL) break; if( (p=strstr(line, "Log-likelihood:")) != NULL) sscanf(p+15, "%f", &logL); else if( (p=strstr(line, "Log-likelihood :")) != NULL) sscanf(p+16, "%f", &logL); } fclose(in); } sprintf(input, "%s.phy_phyml_tree.txt", base_fname); in = fopen(input, "r"); if( status != 0 || in == NULL ) { if(in != NULL) fclose(in); if (is_view_valid(view)) fl_message("%s: tree building cancelled", extract_filename(view->masename)); } else { char *display_tree; fseek(in, 0, SEEK_END); long l = ftell(in); display_tree = (char *)malloc(l + 1); int c; p = display_tree; fseek(in, 0, SEEK_SET); while( (c = getc(in)) != EOF) { if(c != '\n' && c != '\r') *(p++) = c; } *p = 0; fclose(in); display_tree = put_names_back_in_tree(display_tree, truenames); //process bootstrap trees char *bootstrap_trees = NULL; if (replicates > 0 && b_keep_trees->value()) { sprintf(input, "%s.phy_phyml_boot_trees.txt", base_fname); in = fopen(input, "r"); if (in) { FILE *out = NULL; sprintf(input, "%s.phy_phyml_boot_trees_truename.txt", base_fname); out = fopen(input, "w"); long l = 1000; while (out) { // for all bootstrap trees char *b_tree, *q, *tree2; int c; b_tree = (char*)malloc(l + 1); q = b_tree; do { // read one line = one tree c = fgetc(in); if (c == EOF) { free(b_tree); break; } if (q - b_tree >= l) { l += 1000; tree2 = (char *)realloc(b_tree, l + 1); q = tree2 + (q - b_tree); b_tree = tree2; } *q++ = c; } while (c != '\n'); if (c == EOF) break; *q = 0; b_tree = put_names_back_in_tree(b_tree, truenames); fputs(b_tree, out); free(b_tree); } fclose(in); if (out) { fclose(out); in = fopen(input, "r"); fseek(in, 0, SEEK_END); l = ftell(in); fseek(in, 0, SEEK_SET); bootstrap_trees = (char *)malloc(l+1); fread(bootstrap_trees, l, 1, in); bootstrap_trees[l] = 0; fclose(in); } } } //clean tree internal labels if(replicates > 0) display_tree = bootstrap_reformat(display_tree, replicates); else if(replicates < 0) display_tree = alrt_reformat(display_tree); //assemble tree description char tree_label[100]; sprintf(tree_label, "PhyML ln(L)=%.1f %d sites %s", logL, seqlen, modelname); if(replicates > 0) sprintf(tree_label + strlen(tree_label), " %d replic.", replicates); if(cats > 1) sprintf(tree_label + strlen(tree_label), " %d rate classes", cats); if(user_tree) strcat(tree_label, " User-tree"); //add label to tree char *tree = (char *)malloc(strlen(tree_label) + strlen(display_tree) + 4); sprintf(tree, "[%s] %s", tree_label, display_tree); free(display_tree); if (is_view_valid(view)) { const char *n = extract_filename(view->masename); char *title = NULL; if (n) { char *q = (char*)strchr(n, '.'); if (q) *q = 0; title = new char[strlen(n) + 12]; sprintf(title, "%s-%s", n, "PhyML_tree"); if (q) *q = '.'; } Fl_Window *btreew, *treew; if (bootstrap_trees) { btreew = treedraw(bootstrap_trees, view, "bootstrap trees", FALSE); } treew = treedraw(tree, view, n ? title:"PhyML_tree", FALSE); #if !defined(__APPLE__) if (bootstrap_trees) treew->position(btreew->x() + 30, btreew->y() + 40); #endif delete[] title; } } Fl::delete_widget(ob->window()); way_out: for(i = 0; i < tot_seqs; i++) { if(truenames[i]) free(truenames[i]); } free(truenames); delete_tmp_filename(base_fname); } allseq *view_to_allseq(SEA_VIEW *view, int remove_all_gaps) { int i, j, l; list_segments *ls; char *p; allseq *phyml_seqs = (allseq *)calloc(1, sizeof(allseq)); phyml_seqs->n_otu = view->tot_sel_seqs == 0 ? view->tot_seqs : view->tot_sel_seqs; phyml_seqs->c_seq = (struct __Seq **)calloc(phyml_seqs->n_otu, sizeof(struct __Seq*)); l = 0; if(view->active_region == NULL) { for( i = 0; i < view->tot_seqs; i++) { if(view->tot_sel_seqs != 0 && !view->sel_seqs[i]) continue; if(view->each_length[i] > l) l = view->each_length[i]; } } else { ls = view->active_region->list; while(ls != NULL) { l += ls->fin - ls->debut + 1; ls = ls->next; } } phyml_seqs->clean_len = l; phyml_seqs->wght = (int *)calloc(1, l * sizeof(int)); for( i = 0; i < l; i++) { phyml_seqs->wght[i] = 1; } j = 0; for( i = 0; i < view->tot_seqs; i++) { if(view->tot_sel_seqs != 0 && !view->sel_seqs[i]) continue; phyml_seqs->c_seq[j] = (struct __Seq *)calloc(1, sizeof(struct __Seq)); phyml_seqs->c_seq[j]->name = view->seqname[i]; phyml_seqs->c_seq[j]->len = l; phyml_seqs->c_seq[j]->state = (char *)malloc(l + 1); if(view->active_region == NULL) { memcpy(phyml_seqs->c_seq[j]->state, view->sequence[i], view->each_length[i] ); if( l > view->each_length[i] ) { memset(phyml_seqs->c_seq[j]->state + view->each_length[i], '-', l - view->each_length[i]); } } else { ls = view->active_region->list; p = phyml_seqs->c_seq[j]->state; while(ls != NULL) { if(ls->fin <= view->each_length[i]) { memcpy(p, view->sequence[i] + ls->debut - 1, ls->fin - ls->debut + 1 ); } else { int lrem = view->each_length[i] - ls->debut + 1; if(lrem > 0) memcpy(p, view->sequence[i] + ls->debut - 1, lrem ); if(lrem < 0) lrem = 0; memset(p + lrem, '-', ls->fin - ls->debut + 1 - lrem); } p += ls->fin - ls->debut + 1; ls = ls->next; } } phyml_seqs->c_seq[j]->state[l] = 0; majuscules(phyml_seqs->c_seq[j]->state); p = phyml_seqs->c_seq[j]->state; if(!view->protein) { while((p = strchr(p, 'U')) != NULL) *p = 'T'; } else { while((p = strchr(p, '*')) != NULL) *p = '-'; }//replace stops by gaps if (!view->protein) { // remove non-nucleotide characters p = phyml_seqs->c_seq[j]->state; while (*p) { if (strchr("ABCDGHKMNRSTUVWXY-", *p) == NULL) *p = 'N'; p++; } } j++; } //remove gap-only or gap-with sites for( j = 0; j < phyml_seqs->clean_len; j++) { if(remove_all_gaps) {//remove any gap-containing site for( i = 0; i < phyml_seqs->n_otu; i++) { if(phyml_seqs->c_seq[i]->state[j] == '-') break; } if(i == phyml_seqs->n_otu) continue; } else {//remove gap-only sites for( i = 0; i < phyml_seqs->n_otu; i++) { if(phyml_seqs->c_seq[i]->state[j] != '-') break; } if(i != phyml_seqs->n_otu) continue; } for( i = 0; i < phyml_seqs->n_otu; i++) { memmove(phyml_seqs->c_seq[i]->state + j, phyml_seqs->c_seq[i]->state + j + 1, phyml_seqs->clean_len - j); } j--; phyml_seqs->clean_len--; } return phyml_seqs; } void gaps_as_unknown_states(allseq *phyml_seqs, int protein) { char unknown = (protein ? 'X' : 'N'); for( int i = 0; i < phyml_seqs->n_otu; i++) { for( int j = 0; j < phyml_seqs->clean_len; j++) { if(phyml_seqs->c_seq[i]->state[j] == '-') phyml_seqs->c_seq[i]->state[j] = unknown; } } } void free_after_view_to_allseq(allseq *phyml_seqs) { int i; for( i = 0; i < phyml_seqs->n_otu; i++) { free(phyml_seqs->c_seq[i]->state); free(phyml_seqs->c_seq[i]); } free(phyml_seqs->c_seq); free(phyml_seqs->wght); free(phyml_seqs); } /*void initialize_random_series(void) { static int first = TRUE; unsigned seed; if(first) { first = FALSE; #ifdef WIN32 SYSTEMTIME timing; GetSystemTime(&timing); seed = (unsigned)(timing.wMilliseconds + 1000*(timing.wSecond + 60*(timing.wMinute + 60*(timing.wHour + 24*timing.wDay)))); #else struct tms timing; seed = (unsigned)times(&timing); #endif srand(seed); } }*/ double next_random(void) { static int first = TRUE; unsigned seed; if (first) { first = FALSE; #ifdef WIN32 SYSTEMTIME timing; GetSystemTime(&timing); seed = (unsigned)(timing.wMilliseconds + 1000*(timing.wSecond + 60*(timing.wMinute + 60*(timing.wHour + 24*timing.wDay)))); srand(seed); #else struct tms timing; seed = (unsigned)times(&timing); srandom(seed); #endif } #ifdef WIN32 return rand() / (RAND_MAX +(double)1.); #else return random() / (RAND_MAX +(double)1.); #endif } void bootstrap_weights(allseq *seqs, int use_codons) { phydbl buff; int j, position; //initialize_random_series(); memset(seqs->wght, 0, seqs->clean_len * sizeof(int)); if(!use_codons) {//bootstrap sites for(j = 0; j < seqs->clean_len; j++) { /*buff = rand(); buff /= (RAND_MAX+1.);*/ buff = next_random(); buff *= seqs->clean_len; position = (int)floor(buff); seqs->wght[position] += 1; } } else {//bootstrap codons int ncodons = (seqs->clean_len/3); int l3 = 3*ncodons; for(j = 0; j < l3; j += 3) { /*buff = rand(); buff /= (RAND_MAX+1.);*/ buff = next_random(); buff *= ncodons; position = (int)floor(buff); seqs->wght[3 * position] += 1;//only 0, 3, 6,... have weights } } } matrix *Obs_Dist(allseq *data, model *mod) { int site,i,j,k; phydbl unc_len; matrix *mat; phydbl **len; len = (phydbl **)mCalloc(data->n_otu,sizeof(phydbl *)); For(i,data->n_otu) len[i] = (phydbl *)mCalloc(data->n_otu,sizeof(phydbl)); unc_len = .0; mat = Make_Mat(data->n_otu); Init_Mat(mat,data); Fors(site,data->c_seq[0]->len,mod->stepsize) { if (tree_build_interrupted) break; For(j,data->n_otu-1) { for(k=j+1;kn_otu;k++) { if((!Is_Ambigu(data->c_seq[j]->state+site,mod->datatype,mod->stepsize)) && (!Is_Ambigu(data->c_seq[k]->state+site,mod->datatype,mod->stepsize))) { len[j][k]+=data->wght[site]; len[k][j]=len[j][k]; if(strncmp(data->c_seq[j]->state+site, data->c_seq[k]->state+site, mod->stepsize)) mat->P[j][k]+=data->wght[site]; } } } } For(i,data->n_otu-1) for(j=i+1;jn_otu;j++) { if(len[i][j]) { mat->P[i][j] /= len[i][j]; } else { mat->P[i][j] = 1.; } mat->P[j][i] = mat->P[i][j]; mat->dist[i][j] = mat->P[i][j]; mat->dist[j][i] = mat->dist[i][j]; } For(i,data->n_otu) free(len[i]); free(len); return mat; } matrix *Kimura_p_Dist(allseq *data) { int i, j; model jcmodel; jcmodel.stepsize = 1; jcmodel.datatype = 1; jcmodel.ns = 20; matrix *mat = Obs_Dist(data, &jcmodel); for(i = 0; i < data->n_otu; i++) { if (tree_build_interrupted) break; for(j = i + 1; j < data->n_otu; j++) { phydbl x = 1 - mat->dist[i][j] - 0.2 * mat->dist[i][j] * mat->dist[i][j]; if(x <= 0) { Free_Mat(mat); return NULL; } mat->dist[i][j] = -log(x); mat->dist[j][i] = mat->dist[i][j]; } } return mat; } char *alrt_reformat(char *tree) //set aLRT support values to 2 decimal digits { char *p, *q, tmp[20]; float alrt; int l; p = tree; while((p = strchr(p, ')')) != NULL) { q = p++; while(TRUE) { q++; if(*q == 0 ) break; if(strchr("0123456789.-+ ", *q) == NULL) break; } if(*q != ':' ) continue; sscanf(p, "%f", &alrt); sprintf(tmp, "%.2f", alrt); l = strlen(tmp); if(l < q - p) { memset(p, ' ', q - p); memcpy(p, tmp, l); } } return tree; } char *bootstrap_reformat(char *tree, int replicates) //replace absolute bootstrap values by percentages { char *p, *q, *newtree, *pnew, *next; int count; newtree = (char *)malloc(500000); p = tree; pnew = newtree; next = tree; while((p = strchr(p, ')')) != NULL) { q = p++; while(TRUE) { q++; if(*q == 0 ) break; if(strchr("0123456789 ", *q) == NULL) break; } if(*q != ':' ) continue; memcpy(pnew, next, p - next); pnew += p - next; next = p; sscanf(p, "%d", &count); sprintf(pnew, "%d", (int)(100*count/float(replicates) + .5)); pnew += strlen(pnew); next = q; } memcpy(pnew, next, strlen(next)); pnew += strlen(next); *pnew = 0; free(tree); return newtree; } matrix *K80_dist_nogamma(allseq *data) { int i,j,k; phydbl unc_len; matrix *mat; phydbl **len; len = (phydbl **)mCalloc(data->n_otu,sizeof(phydbl *)); For(i,data->n_otu) len[i] = (phydbl *)mCalloc(data->n_otu,sizeof(phydbl)); unc_len = .0; mat = Make_Mat(data->n_otu); Init_Mat(mat,data); For(i,data->c_seq[0]->len) { if (tree_build_interrupted) break; For(j,data->n_otu-1) { for(k=j+1;kn_otu;k++) { if(((data->c_seq[j]->state[i] == 'A' || data->c_seq[j]->state[i] == 'G') && (data->c_seq[k]->state[i] == 'C' || data->c_seq[k]->state[i] == 'T'))|| ((data->c_seq[j]->state[i] == 'C' || data->c_seq[j]->state[i] == 'T') && (data->c_seq[k]->state[i] == 'A' || data->c_seq[k]->state[i] == 'G'))) { mat->Q[j][k]+=data->wght[i]; len[j][k]+=data->wght[i]; len[k][j]=len[j][k]; } else if(((data->c_seq[j]->state[i] == 'A' && data->c_seq[k]->state[i] == 'G') || (data->c_seq[j]->state[i] == 'G' && data->c_seq[k]->state[i] == 'A'))|| ((data->c_seq[j]->state[i] == 'C' && data->c_seq[k]->state[i] == 'T') || (data->c_seq[j]->state[i] == 'T' && data->c_seq[k]->state[i] == 'C'))) { mat->P[j][k]+=data->wght[i]; len[j][k]+=data->wght[i]; len[k][j]=len[j][k]; } else if((data->c_seq[j]->state[i] == 'A' || data->c_seq[j]->state[i] == 'C' || data->c_seq[j]->state[i] == 'G' || data->c_seq[j]->state[i] == 'T')&& (data->c_seq[k]->state[i] == 'A' || data->c_seq[k]->state[i] == 'C' || data->c_seq[k]->state[i] == 'G' || data->c_seq[k]->state[i] == 'T')) { len[j][k]+=data->wght[i]; len[k][j]=len[j][k]; } } } } For(i,data->n_otu-1) for(j=i+1;jn_otu;j++) { if(len[i][j]) { mat->P[i][j] /= len[i][j]; mat->Q[i][j] /= len[i][j]; } else { mat->P[i][j] = .5; mat->Q[i][j] = .5; } mat->P[j][i] = mat->P[i][j]; mat->Q[j][i] = mat->Q[i][j]; if((1-2*mat->P[i][j]-mat->Q[i][j] <= .0) || (1-2*mat->Q[i][j] <= .0)) { Free_Mat(mat); mat = NULL; goto out; } /* mat->dist[i][j] = (g_shape/2)* (pow(1-2*mat->P[i][j]-mat->Q[i][j],-1./g_shape) + 0.5*pow(1-2*mat->Q[i][j],-1./g_shape) - 1.5); */ mat->dist[i][j] = -0.5 * log(1-2*mat->P[i][j]-mat->Q[i][j]) - 0.25 * log(1-2*mat->Q[i][j]); mat->dist[j][i] = mat->dist[i][j]; } out:For(i,data->n_otu) free(len[i]); free(len); return mat; } matrix *HKY_dist(allseq *data) { int i,j; matrix *mat; double x; mat = Make_Mat(data->n_otu); Init_Mat(mat,data); For(i,data->n_otu - 1) { for(j = i + 1; j < data->n_otu; j++) { if (tree_build_interrupted) return mat; x = hky(data->c_seq[i]->state, data->c_seq[j]->state, data->clean_len, data->wght); if(x == -1) { Free_Mat(mat); return NULL; } mat->dist[i][j] = x; mat->dist[j][i] = mat->dist[i][j]; } } return mat; } /* Distance for Hasegawa, Kishino and Yano model */ double hky(char* seq1, char* seq2, int lg, int *wght) { double d, freq[16], a, c, g, t, r, y, P, P1, P2, Q, A1, A2, A3, gamma, cc, ee, va1, va2, cova1a2, cova1a3, cova2a3, delta, epsilon, ksi, eta, nu, ff; double larg1, larg2, larg3; freq_obs(seq1, seq2, freq, lg, wght); P1=freq[2]+freq[8]; P2=freq[7]+freq[13]; P=P1+P2; Q=freq[1]+freq[3]+freq[4]+freq[6]+freq[9]+freq[11]+freq[12]+freq[14]; if(P+Q == 0) return 0; a=freq[0]+(freq[1]+freq[2]+freq[3]+freq[4]+freq[8]+freq[12])/2; c=freq[5]+(freq[1]+freq[4]+freq[6]+freq[7]+freq[9]+freq[13])/2; g=freq[10]+(freq[2]+freq[6]+freq[8]+freq[9]+freq[11]+freq[14])/2; t=1.-a-c-g; r=a+g; y=c+t; larg1=1-Q/(2*r*y); larg2=1-Q/(2*r)-(r*P1)/(2*a*g); larg3=1-Q/(2*y)-(y*P2)/(2*c*t); if(larg1<=0. || larg2<=0. || larg3<=0.) return -1.; A1=(y/r)*log(larg1)-log(larg2)/r; A2=(r/y)*log(larg1)-log(larg3)/y; A3=-log(larg1); cc=1-Q/(2*r*y); ee=1-(r*P1)/(2*a*g)-Q/(2*r); ff=1-(y*P2)/(2*c*t)-Q/(2*y); delta=1/(2*ee*r*r)-1/(2*cc*r*r); epsilon=1/(2*ee*a*g); ksi=1/(2*y*y*ff)-1/(2*y*y*cc); eta=1/(2*c*t*ff); nu=1/(2*r*y*cc); va1=((delta*delta*Q+epsilon*epsilon*P1)-(delta*Q+epsilon*P1)*(delta*Q+epsilon*P1))/lg; va2=((ksi *ksi *Q+eta *eta *P2)-(ksi *Q+eta *P2)*(ksi *Q+eta *P2))/lg; cova1a2=(delta*ksi*Q*(1-Q)-delta*eta*Q*P2-epsilon*eta*P1*P2)/lg; cova1a3=nu*Q*(delta*(1-Q)-epsilon*P1)/lg; cova2a3=nu*Q*(ksi *(1-Q)-eta *P2)/lg; gamma=(va2-cova1a2)/(va1+va2-2*cova1a2) + ((r*y)/(a*g+c*t)) * ((cova1a3-cova2a3)/(va1+va2-2*cova1a2)); d=2*(a*g+c*t)*(gamma*A1+(1-gamma)*A2)+2*r*y*A3; return(d); } /* freq_obs */ /* Write at address freq observed frequencies of 16 di-nucleotides XY */ /* (X= A,C,G,T , Y=A,C,G,T) X and Y being homologous nucleotides of sequences */ /* seq1 and seq2. Alphabetic order is used : freq[0]=AA frequency, freq[1]=AC, */ /* ..., freq[15]=TT. */ int freq_obs(char* seq1, char* seq2, double* freq, int lgseq, int *wght) { int i, lgseqvrai, w; for(i=0;i<16;i++) freq[i]=0; lgseqvrai = lgseq; for(i=0;i 1) { int rank = 0; while (count-- > 0) { r = strchr(p, '\n'); sprintf(q, "[equally best tree #%d]", ++rank); q += strlen(q); memcpy(q, p, r - p + 1); q += r-p+1; p = r+1; } } *q = 0; free(tree); free(all_best); return final_tree; } static char *run_parsimony_method(SEA_VIEW *view, int nogaps, const char *gapsunknown, int nreplicates, int njumbles, int maxbest, int user_tree, Fl_Box *w_count, dnapars_S_option s_option, const char **pprogname, float consensus_threshold, int no_gui, char **p_bootstrap_trees, void (*alert)(const char *,...) ) { char *tree = 0, *final_tree = 0, *all_best; int i, steps, info, count, replicates_done, count_best; const char *p; allseq *tmpallseqs = view_to_allseq(view, nogaps); if(*gapsunknown) gaps_as_unknown_states(tmpallseqs, view->protein); char **pars_seqs = (char **)malloc(tmpallseqs->n_otu * sizeof(char *)); char **pars_names = (char **)malloc(tmpallseqs->n_otu * sizeof(char *)); for( i = 0; i < tmpallseqs->n_otu; i++) { pars_seqs[i] = tmpallseqs->c_seq[i]->state; pars_names[i] = tmpallseqs->c_seq[i]->name; } info = informative(pars_seqs, tmpallseqs->n_otu); if(view->protein) *pprogname = "Protpars"; else { *pprogname = "Dnapars"; if (tmpallseqs->clean_len >= SHRT_MAX) { alert("Can't compute parsimony with DNA seqs longer than %d.", SHRT_MAX); goto way_out; } } if (nreplicates) { tree = parsimony_with_bootstrap(tmpallseqs, pars_seqs, pars_names, tmpallseqs->n_otu, njumbles, view->protein, &steps, maxbest, nreplicates, w_count, &replicates_done, s_option, no_gui, consensus_threshold, &count_best, p_bootstrap_trees); if (tree) { final_tree = (char *)malloc(strlen(tree) + 200); char best[35] = ""; if (count_best > 1) sprintf(best, "consensus of %d best trees, ", count_best); sprintf(final_tree, "[%s, bootstrap with %d replic., %d steps, %s%d sites (%d informative)%s]%s", *pprogname, replicates_done, steps, best, tmpallseqs->clean_len, info, gapsunknown, tree); } } else if(user_tree) { char *differs, *input_tree; p = view->trees[user_tree - 1]; while(*p == ' ') p++; if(*p == '[') p = strchr(p, ']')+ 1; while(*p == ' ') p++; input_tree = strdup(p); i = compare_newick_with_names(input_tree, pars_names, tmpallseqs->n_otu, &differs); if (i != 0) { alert("Names in user-tree and target sequences differ:\n%s in %s only", differs, i == 1 ? "user-tree" : "target sequences"); tree = NULL; } else { input_tree = (char *)realloc(input_tree, strlen(input_tree) + 4 * tmpallseqs->n_otu + 6 ); if( make_binary_or_unrooted(input_tree) != NULL) return NULL; strcat(input_tree, ";"); tree = parsimony(pars_seqs, pars_names, tmpallseqs->n_otu, 0, &steps, input_tree, maxbest, NULL, view->protein, s_option, no_gui, NULL); free(input_tree); if(tree == NULL) { alert("Error in user-tree"); } else { final_tree = (char *)malloc(strlen(tree) + 150); sprintf(final_tree, "[%s, user-tree, %d steps, %d sites (%d informative)%s]%s", *pprogname, steps, tmpallseqs->clean_len, info, gapsunknown, tree); } } } else { tree = parsimony_with_jumble(pars_seqs, pars_names, tmpallseqs->n_otu, njumbles, view->protein, &steps, &count, maxbest, w_count, s_option, no_gui, consensus_threshold); if (count > 1) { // memorize all equally best trees in all_best string char *q = strchr(tree, '\n'); all_best = strdup(q + 1); *q = 0; } if (tree && count > 1 && !view->protein) { /* with DNA, fit branch lengths to consensus of most parsimonious trees */ char *input_tree = tree; int steps2; /* don't use the steps of this consensus tree because it can be larger than parsimonious steps */ tree = parsimony(pars_seqs, pars_names, tmpallseqs->n_otu, 0, &steps2, input_tree, maxbest, NULL, false, s_option, no_gui, NULL); free(input_tree); } if (tree) { char aux[30]; final_tree = (char *)malloc(strlen(tree) + 150); if (count > 1) sprintf(aux, " (%d%% consensus)", int(consensus_threshold*100 + 0.5)); else *aux = 0; sprintf(final_tree, "[%s, %d best trees%s, %d steps, %d sites (%d informative)%s]%s", *pprogname, count, aux, steps, tmpallseqs->clean_len, info, gapsunknown, tree); if (count > 1) final_tree = add_equally_best(final_tree, all_best, count); } } way_out: if (tree) free(tree); free_after_view_to_allseq(tmpallseqs); free(pars_seqs); free(pars_names); return final_tree; } static void user_tree_cb(Fl_Widget *wid, void *data) { Fl_Button *b = (Fl_Button*)data; b->value(0); b->do_callback(); } void parsimony_dialog(SEA_VIEW *view) { int njumbles, i, count, maxbest = 100, started = 0, use_bootstrap, nreplicates, user_tree, nogaps; char *final_tree, *bootstrap_trees = NULL; const char *p, *progname; dnapars_S_option s_option = more_thorough; tree_build_interrupted = 0; return_window *w = new return_window(255, view->protein ? 225: 300, "Parsimony analysis"); w->set_modal(); Fl_Check_Button *w_dojumble = new Fl_Check_Button(2, 5, 170, 20, "Randomize seq. order"); w_dojumble->value(0); Fl_Int_Input *w_jumbles = new Fl_Int_Input(w_dojumble->x() + w_dojumble->w() + 5, w_dojumble->y(), 30, 20, "times"); w_jumbles->align(FL_ALIGN_RIGHT); w_jumbles->value("5"); Fl_Check_Button *w_nogaps = new Fl_Check_Button(2, w_dojumble->y() + w_dojumble->h() + 5, 160, 20, "Ignore all gap sites"); w_nogaps->value(1); Fl_Check_Button *w_gapsunknown = new Fl_Check_Button(2, w_nogaps->y() + w_nogaps->h() + 5, 180, 20, "Gaps as unknown states"); w_gapsunknown->value(0); w_gapsunknown->deactivate(); Fl_Widget *witness = w_gapsunknown; Fl_Round_Button *thorough_b, *less_thorough_b; Fl_Int_Input *w_best; if (!view->protein) { Fl_Group *g = new Fl_Group(2, witness->y() + witness->h() + 5, w->w()-4, 70); g->box(FL_DOWN_FRAME); thorough_b = new Fl_Round_Button(7, witness->y() + witness->h() + 5, 180, 20, "More thorough tree search"); thorough_b->type(FL_RADIO_BUTTON); less_thorough_b = new Fl_Round_Button(7, thorough_b->y() + thorough_b->h() + 5, 180, 20, "Less thorough tree search"); less_thorough_b->type(FL_RADIO_BUTTON); Fl_Round_Button *rearrange_best_b = new Fl_Round_Button(7, less_thorough_b->y() + less_thorough_b->h() + 5, 180, 20, "Rearrange on best tree"); rearrange_best_b->type(FL_RADIO_BUTTON); rearrange_best_b->activate(); thorough_b->setonly(); g->end(); w_best = new Fl_Int_Input(195, rearrange_best_b->y() + rearrange_best_b->h() + 5, 50, 20, "Equally best trees retained"); w_best->align(FL_ALIGN_LEFT); w_best->value("10000"); witness = w_best; } Fl_Value_Slider* slider = new Fl_Value_Slider(2, witness->y() + witness->h() + 25, w->w()-4, 20, "% level for consensus tree building"); slider->align(FL_ALIGN_TOP); slider->type(FL_HOR_NICE_SLIDER); slider->box(FL_FLAT_BOX); slider->color(FL_YELLOW); slider->selection_color(FL_RED); slider->bounds(50, 100); slider->value(100); slider->precision(0); Fl_Round_Button *w_dobootstrap = new Fl_Round_Button(2, slider->y() + slider->h() + 10, 115, 20, "Bootstrap with"); w_dobootstrap->type(FL_RADIO_BUTTON); Fl_Int_Input *w_btrepl = new Fl_Int_Input(w_dobootstrap->x() + w_dobootstrap->w() + 5, w_dobootstrap->y() , 40, 20, "replicates"); w_btrepl->value("100"); w_btrepl->align(FL_ALIGN_RIGHT); Fl_Check_Button *keep_b_trees = new Fl_Check_Button(2, w_dobootstrap->y() + w_dobootstrap->h() + 5, 180, 20, "Show bootstrap trees"); keep_b_trees->deactivate(); w_dobootstrap->callback(dist_b_cb, keep_b_trees); w_dobootstrap->when(FL_WHEN_CHANGED); Fl_Box *w_count = new Fl_Box(0, keep_b_trees->y() + keep_b_trees->h() + 5, w->w(), 20, NULL); Fl_Round_Button *w_user = new Fl_Round_Button(2, w_count->y() + w_count->h() + 5, 85, 20, "User tree:"); w_user->type(FL_RADIO_BUTTON); w_user->callback(user_tree_cb, w_dobootstrap); Fl_Choice *w_choice = new Fl_Choice(w_user->x() + w_user->w() + 5, w_user->y(), 130, 20, ""); count = view->menu_trees->vlength(); for( i = 0; i < count; i++) w_choice->add( view->menu_trees->vitem(i)->label() ); w_choice->value(0); if (!count) {w_user->deactivate(); w_choice->deactivate(); } Fl_Button *w_interrupt = new Fl_Button(w_dobootstrap->x(), w_user->y() + w_user->h() + 5, 60, 20, "Cancel"); Fl_Return_Button *w_ok = new Fl_Return_Button(w->w() - 65, w_interrupt->y(), 60, 20, "OK"); w->run(w_ok); w_interrupt->callback(interrupt_callback, &tree_build_interrupted); w_ok->callback(interrupt_callback, &started); w->end(); w->callback(interrupt_callback, &tree_build_interrupted); w->size(w->w(), w_ok->y() + w_ok->h() + 5); w->show(); while(!started && !tree_build_interrupted) { Fl::wait(); if(w_gapsunknown->value()) { w_nogaps->value(0); w_nogaps->deactivate(); } else w_nogaps->activate(); if(w_nogaps->value()) { w_gapsunknown->value(0); w_gapsunknown->deactivate(); } else w_gapsunknown->activate(); } if (tree_build_interrupted) { delete w; return; } w_ok->hide(); w_interrupt->label("Interrupt"); if(w_dojumble->value()) { p = w_jumbles->value(); sscanf(p, "%d", &njumbles); if(njumbles < 1) njumbles = 1; } else njumbles = 0; use_bootstrap = w_dobootstrap->value(); user_tree = w_user->value(); nogaps = w_nogaps->value(); char gapsunknown[25]; if(w_gapsunknown->value()) sprintf(gapsunknown, ", gaps treated as %c", (view->protein ? 'X' : 'N') ); else gapsunknown[0] = 0; if(use_bootstrap) { p = w_btrepl->value(); sscanf(p, "%d", &nreplicates); } else { if(user_tree) user_tree = w_choice->value() + 1; } if (!view->protein) { if (thorough_b->value()) s_option = more_thorough; else if (less_thorough_b->value()) s_option = less_thorough; else s_option = rearrange_best_tree; p = w_best->value(); sscanf(p, "%d", &maxbest); } my_watch_cursor(w); final_tree = run_parsimony_method(view, nogaps, gapsunknown, use_bootstrap && nreplicates > 1 ? nreplicates : 0, njumbles, maxbest, user_tree, w_count, s_option, &progname, slider->value()/100, false, keep_b_trees->value() ? &bootstrap_trees : NULL, fl_alert); fl_reset_cursor(w); delete w; if (final_tree != NULL) { const char *n = extract_filename(view->masename); char *title = NULL; if (n) { char *q = (char*)strchr(n, '.'); if (q) *q = 0; title = new char[strlen(n) + strlen(progname) + 2]; sprintf(title, "%s-%s", n, progname); if (q) *q = '.'; } int tree_count = 0; p = final_tree; while (TRUE) { p = strchr(p+1, '\n'); if (!p) break; tree_count++; } if (tree_count == 0) tree_count = 1; Fl_Window *btreew = NULL; if (bootstrap_trees) btreew = treedraw(bootstrap_trees, view, "bootstrap trees", FALSE); Fl_Window *treew = treedraw(final_tree, view, n ? title:progname, FALSE, tree_count); #if !defined(__APPLE__) if (btreew) treew->position(btreew->x() + 30, btreew->y() + 40); #endif delete[] title; } } char *parsimony_with_jumble(char **pars_seqs, char **pars_names, int n_otu, int njumbles, int protein, int *psteps, int *pcount, int maxbest, Fl_Widget *w_count, dnapars_S_option s_option, int no_gui, float consensus_threshold) { int i, steps, count = 0; char *tree, *newtree, *p, *q; if (njumbles > 0) { if (w_count) w_count->label("First jumble attempt"); } tree = parsimony(pars_seqs, pars_names, n_otu, njumbles, &steps, NULL, maxbest, NULL, protein, s_option, no_gui, w_count); if (!tree) return NULL; p = tree - 1; while((p = strchr(p+1, '\n')) != NULL) count++;//count equally parsimonious trees if(count > 1) {//compute threshold consensus of all equally parsimonious trees p = strchr(tree, '\n'); newtree = (char *)malloc(p - tree + 1); memcpy(newtree, tree, p - tree); newtree[p - tree] = 0; p++; i = count; count = 0; init_consensus_calculation(n_otu); while(TRUE) { count += process_one_consensus_item(newtree, pars_names); free(newtree); i--; if(i == 0) break; q = strchr(p, '\n'); newtree = (char *)malloc(q - p + 1); memcpy(newtree, p, q - p); newtree[q - p] = 0; p = q + 1; } int **rows; int br_count = after_consensus_items(consensus_threshold, count, &rows); char *consensus_tree = compute_consensus_tree(pars_names, rows, br_count); for (i = 0; i < br_count; i++) free(rows[i]); free(rows); char *newtree = (char*)malloc(strlen(consensus_tree) + strlen(tree) + 2); sprintf(newtree, "%s\n%s", consensus_tree, tree); free(consensus_tree); free(tree); tree = newtree; } *psteps = steps; *pcount = count; return tree; } static char *parsimony_with_bootstrap(allseq *tmpallseqs, char **pars_seqs, char **pars_names, int n_otu, int njumbles, int protein, int *psteps, int maxbest, int replicates, Fl_Box *w_count, int *preplicates_done, dnapars_S_option s_option, int no_gui, float consensus_threshold, int *pcount_best, char **p_bootstrap_trees) { int i, j, steps, newsteps, count = 0, replicates_done = 0, repl_count, lbtrees = 0; char *tree, *newtree, *p, *q, *all_best, *bootstrap_trees = NULL; if (w_count) w_count->label("Full sequence tree"); tree = parsimony_with_jumble(pars_seqs, pars_names, n_otu, njumbles, protein, &steps, &count, maxbest, NULL, s_option, no_gui, consensus_threshold); if (!tree) return NULL; if (count > 1) { // memorize all equally best trees in all_best string p = strchr(tree, '\n'); all_best = strdup(p + 1); *p = 0; } if (count > 1 && !protein) { /* with DNA, fit branch lengths to strict consensus of most parsimonious trees */ char *input_tree = tree; /* don't use the steps of this consensus tree because it can be larger than parsimonious steps */ tree = parsimony(pars_seqs, pars_names, n_otu, njumbles, &newsteps, input_tree, maxbest, NULL, false, s_option, no_gui, NULL); free(input_tree); } *psteps = steps; init_add_bootstrap(tree); // memorize topology and br lengths of strict consensus of most parsimonious trees for(j = 0; j < replicates; j++) { if (w_count) { char tmp[30]; sprintf(tmp, "Bootstrap replicate: %d", j + 1); w_count->label(tmp); } if (tree_build_interrupted) break; bootstrap_weights(tmpallseqs, FALSE); tree = parsimony(pars_seqs, pars_names, n_otu, njumbles, &steps, NULL, maxbest, tmpallseqs->wght, protein, s_option, no_gui, NULL); if (!tree) break; p = tree - 1; repl_count = 0; while((p = strchr(p+1, '\n')) != NULL) repl_count++;//count equally parsimonious trees i = repl_count; while (TRUE) { p = strchr(tree, '\n'); newtree = (char *)malloc(p - tree + 1); memcpy(newtree, tree, p - tree); newtree[p - tree] = 0; process_one_replicate(newtree, 1./repl_count); if (p_bootstrap_trees) { // memorize all bootstrap trees if (lbtrees == 0) { lbtrees = 10000; bootstrap_trees = (char *)malloc(lbtrees + 1); q = bootstrap_trees; *q = 0; } int l = strrchr(newtree, ')') - newtree + 1; // length of (....) if ((q-bootstrap_trees) + l + 8 > lbtrees) { lbtrees = (q-bootstrap_trees) + l + 8 + 10000; char *tmpc = (char*)realloc(bootstrap_trees, lbtrees + 1); q = tmpc + (q - bootstrap_trees); bootstrap_trees = tmpc; } sprintf(q, "[%.2f]", 1./repl_count); q += strlen(q); // indicate tree weight memcpy(q, newtree, l); q += l; // (...) part of tree memcpy(q, ";\n", 3); q += 2; // end of tree } free(newtree); i--; if(i == 0) break; newtree = strdup(p+1); free(tree); tree = newtree; } ++replicates_done; free(tree); } *preplicates_done = replicates_done; tree = finish_add_bootstrap(replicates_done); if (count > 1) tree = add_equally_best(tree, all_best, count); *pcount_best = count; if (p_bootstrap_trees) *p_bootstrap_trees = bootstrap_trees; return tree; } struct pars_struct { char** seq; char** seqname; int notu; int njumbles; int *jumble_no; int *steps; char* toevaluate; int arg_maxtrees; int *bt_weights; dnapars_S_option s_option; char *result; bool protein; bool done; }; void awake_from_C(void) { Fl::lock(); Fl::awake(); Fl::unlock(); } static void parsimony_thread(pars_struct* args) { typedef char* (*pars_f)(char** seq, char** seqname, int notu, int njumbles, int *jumble_no, int *steps, char* toevaluate, int arg_maxtrees, int *bt_weights, dnapars_S_option s_option); pars_f pf = args->protein ? protpars : dnapars; args->result = (*pf)(args->seq, args->seqname, args->notu, args->njumbles, args->jumble_no, args->steps, args->toevaluate, args->arg_maxtrees, args->bt_weights, args->s_option); Fl::lock(); args->done = true; Fl::awake(); Fl::unlock(); } char *parsimony(char** seq, char** seqname, int notu, int njumbles, int *steps, char* toevaluate, int arg_maxtrees, int *bt_weights, bool protein, dnapars_S_option s_option, int no_gui, Fl_Widget *w_count) { char *p; int jumble_no = 0; int pre_jumble_no = 0; tree_build_interrupted = 0; if (no_gui) { if (protein) p = protpars(seq, seqname, notu, njumbles, NULL, steps, toevaluate, arg_maxtrees, bt_weights, s_option); else p = dnapars(seq, seqname, notu, njumbles, NULL, steps, toevaluate, arg_maxtrees, bt_weights, s_option); } else { pars_struct *args = (pars_struct*)malloc(sizeof(pars_struct)); args->seq = seq; args->seqname = seqname; args->notu = notu; args->njumbles = njumbles; args->jumble_no = &jumble_no; args->steps = steps; args->toevaluate = toevaluate; args->arg_maxtrees = arg_maxtrees; args->bt_weights = bt_weights; args->s_option = s_option; args->result = NULL; args->protein = protein; args->done = false; if ( ! fl_create_thread((void (*) (void *))parsimony_thread, args, 1024) ) { while (!args->done) { Fl::wait(); if (jumble_no > pre_jumble_no && jumble_no < njumbles && w_count) { pre_jumble_no = jumble_no; char tmp[40]; sprintf(tmp, "Jumble attempt: %d steps: %d", jumble_no + 1, *args->steps); w_count->label(tmp); } } } p = args->result; free(args); } if (tree_build_interrupted && p) { free(p); p = NULL; } return p; } /* from Numerical Recipes in C */ /* Allocation function for ludcmp function */ double *vector(long nl, long nh) { double *v; v=(double *)malloc((size_t) ((nh-nl+1+1)*sizeof(double))); if (!v) printf("allocation failure in vector()"); return v-nl+1; } /* free_vector */ /* from Numerical Recipes in C */ /* Memory freeing function for ludcmp function */ void free_vector(double *v, long nl, long nh) { free((char*) (v+nl-1)); } /* ludcmp */ /* from Numerical Recipes in C */ /* Replace matrix a by a rowwise permutation of its LU decomposition. */ int ludcmp(double **a, int n, int *indx, double *d) { int i,imax=0,j,k; double big,dum,sum,temp; double *vv; vv=vector(1,n); *d=1.0; for (i=1;i<=n;i++) { big=0.0; for (j=1;j<=n;j++) if ((temp=fabs(a[i][j])) > big) big=temp; if (big == 0.0) return 0; vv[i]=1.0/big; } for (j=1;j<=n;j++) { for (i=1;i= big) { big=dum; imax=i; } } if (j != imax) { for (k=1;k<=n;k++) { dum=a[imax][k]; a[imax][k]=a[j][k]; a[j][k]=dum; } *d = -(*d); vv[imax]=vv[j]; } indx[j]=imax; if (a[j][j] == 0.0) a[j][j]=1.0e-20; if (j != n) { dum=1.0/(a[j][j]); for (i=j+1;i<=n;i++) a[i][j] *= dum; } } free_vector(vv,1,n); return 1; } /* Returns the determinant of matrix mat(4, 4) */ double det4(double mat[4][4]) { int i, j, *indx; double *lu[5], d; for(i=1;i<5;i++){ lu[i]=(double*)calloc(5, sizeof(double)); for(j=1;j<5;j++) lu[i][j]=mat[i-1][j-1]; } indx=(int*)calloc(5, sizeof(int)); if(!ludcmp(lu, 4, indx, &d)) return 0.; for(i=1;i<5;i++) d *= lu[i][i]; for(i=1;i<5;i++) free(lu[i]); return d; } /* logdet distance */ double logdet(char* seq1, char* seq2, int lg, int *wght) { double matxy[4][4]; double freq[16], d, a1, c1, g1, t1, a2, c2, g2, t2; if(!freq_obs(seq1, seq2, freq, lg, wght)) return -1.; matxy[0][0]=freq[0]; matxy[0][1]=freq[1]; matxy[0][2]=freq[2]; matxy[0][3]=freq[3]; matxy[1][0]=freq[4]; matxy[1][1]=freq[5]; matxy[1][2]=freq[6]; matxy[1][3]=freq[7]; matxy[2][0]=freq[8]; matxy[2][1]=freq[9]; matxy[2][2]=freq[10]; matxy[2][3]=freq[11]; matxy[3][0]=freq[12]; matxy[3][1]=freq[13]; matxy[3][2]=freq[14]; matxy[3][3]=freq[15]; a1=matxy[0][0]+matxy[0][1]+matxy[0][2]+matxy[0][3]; c1=matxy[1][0]+matxy[1][1]+matxy[1][2]+matxy[1][3]; g1=matxy[2][0]+matxy[2][1]+matxy[2][2]+matxy[2][3]; t1=matxy[3][0]+matxy[3][1]+matxy[3][2]+matxy[3][3]; a2=matxy[0][0]+matxy[1][0]+matxy[2][0]+matxy[3][0]; c2=matxy[0][1]+matxy[1][1]+matxy[2][1]+matxy[3][1]; g2=matxy[0][2]+matxy[1][2]+matxy[2][2]+matxy[3][2]; t2=matxy[0][3]+matxy[1][3]+matxy[2][3]+matxy[3][3]; d=det4(matxy); if(d<=0.) return -1.; return (-log(d)+log(a1*c1*g1*t1*a2*c2*g2*t2)/2)/4; } matrix *LOGDET_dist(allseq *data) { int i,j; matrix *mat; mat = Make_Mat(data->n_otu); Init_Mat(mat,data); For(i,data->n_otu - 1) { for(j = i + 1; j < data->n_otu; j++) { if (tree_build_interrupted) return mat; double x = logdet(data->c_seq[i]->state, data->c_seq[j]->state, data->clean_len, data->wght); if(x == -1.) { Free_Mat(mat); return NULL; } mat->dist[i][j] = x; mat->dist[j][i] = x; } } return mat; } char *put_names_back_in_tree(char *oldtree, char **names) //replace Seq###_ in oldtree by names in newtree { char *p, *q, *newtree; int rank, l = 0; p = oldtree; while((p = strstr(p, "Seq")) != NULL) { p += 3; sscanf(p, "%d", &rank); l += strlen(names[rank]); } newtree = (char *)malloc(strlen(oldtree) + l + 1); p = newtree; q = oldtree; while(*q != 0) { if(strncmp(q, "Seq", 3) != 0) *p++ = *q++; else { sscanf(q + 3, "%d", &rank); l = strlen(names[rank]); strcpy(p, names[rank]); p += l; do q++; while(*q != '_'); q++; } } free(oldtree); *p = 0; newtree = (char *)realloc(newtree, strlen(newtree) + 1); return newtree; } char *replace_tree_names_by_rank(const char *tree, char **names, int notu) /* replace names from tree listed in table names by Seq##_ returns altered tree or NULL if some tree name not found in table names */ { char *p = (char *)tree - 1; char *newtree, *q, *qstart, c; int found = 0, i, l; char *start = NULL; static char name[200]; newtree = (char *)malloc(strlen(tree) + 10 * notu + 1); q = newtree; while(*(++p) != 0) { *(q++) = *p; if(*p == '(' ) { start = p + 1; qstart = q; } else if(start == NULL && *p == ',') { start = p + 1; qstart = q; } else if(start != NULL && (*p == ')' || *p == ':' || *p == ',') ) { found++; while(*start == ' ') start++; memcpy(name, start, p - start); name[p - start] = 0; l = strlen(name) - 1; while( l >= 0 && name[l] == ' ') name[l--] = 0; for(i = 0; i < notu; i++) if(strcmp(name, names[i]) == 0) break; if(i == notu) { free(newtree); return NULL; } else { c = *(q - 1); sprintf(qstart, "Seq%d_", i); q = qstart + strlen(qstart); *q++ = c; } if(*p != ',') start = NULL; else { start = p + 1; qstart = q; } } } *q = 0; return newtree; } void command_line_phylogeny(int argc, char **argv) { char *tree, *p; int replicates = 0, jumbles = 0, i; bool err = false; if (!isarg(argc, argv, "-distance") && !isarg(argc, argv, "-parsimony")) { fputs("Option -build_tree requires either -distance or -parsimony\n", stderr); exit(1); } if (isarg(argc, argv, "-distance") && !(isarg(argc, argv, "-o") || isarg(argc, argv, "-distance_matrix"))) err = true; if (isarg(argc, argv, "-parsimony") && !isarg(argc, argv, "-o")) err = true; if (err) { fputs("Missing '-o fname' option\n", stderr); exit(1); } SEA_VIEW *view = cmdline_read_input_alignment(argc, argv); if ( (p = argname(argc, argv, "-sites")) ) { list_regions *elt = view->regions; while (elt) { if (strcmp(elt->element->name, p) == 0) break; elt = elt->next; } if (elt) view->active_region = elt->element; } if ( (p = argname(argc, argv, "-species")) ) { for (i = 0; i < view->numb_species_sets; i++) { if (strcmp(view->name_species_sets[i], p) == 0) break; } if (i < view->numb_species_sets) { view->sel_seqs = view->list_species_sets[i]; view->tot_sel_seqs = 0; for (i = 0; i < view->tot_seqs; i++) if (view->sel_seqs[i]) view->tot_sel_seqs++; } } replicates = argval(argc, argv, "-replicates", 0); char *utree = NULL; if (isarg(argc, argv, "-usertree")) { char *utname; if ( (utname = argname(argc, argv, "-usertree"))) { FILE *in = fopen(utname, "r"); if (!in) { fprintf(stderr, "Usertree file not found: %s\n",utname); exit(1); } fseek(in, 0, SEEK_END); long s = ftell(in); fseek(in, 0, SEEK_SET); utree = (char*)malloc(s+1); fread(utree, s, 1, in); utree[s] = 0; fclose(in); } } if (isarg(argc, argv, "-distance")) { // distance method int distkind = 0; // == observed_p/ndist char *distname; if ( (distname = argname(argc, argv, "-distance"))) { if (strcmp(distname, "JC") == 0) distkind = Jukes_Cantor; else if (strcmp(distname, "K2P") == 0) distkind = Kimura2P; else if (strcmp(distname, "HKY") == 0) distkind = HKY; else if (strcmp(distname, "logdet") == 0) distkind = LogDet; else if (strcmp(distname, "Ka") == 0) distkind = Ka; else if (strcmp(distname, "Ks") == 0) distkind = Ks; else if (strcmp(distname, "Poisson") == 0) distkind = Poisson_pdist; else if (strcmp(distname, "Kimura") == 0) distkind = Kimura_pdist; } if (distkind == 0) distname = strdup("Observed"); view->tot_trees = 0; tree = run_distance_method(view, distkind, isarg(argc, argv, "-nogaps"), !isarg(argc, argv, "-NJ"), replicates > 1, replicates, NULL, distname, distkind == Ka || distkind == Ks, argname(argc, argv, "-distance_matrix"), utree, true, Fl::fatal, false); if (isarg(argc, argv, "-distance_matrix")) exit(0); } if (isarg(argc, argv, "-parsimony")) { // parsimony method const char *progname; jumbles = argval(argc, argv, "-jumbles", 0); char *search = argname(argc, argv, "-search"); dnapars_S_option s_option; if (search && strcmp(search, "less") == 0) s_option = less_thorough; else if (search && strcmp(search, "best") == 0) s_option = rearrange_best_tree; else s_option = more_thorough; int usertreerank = 0; if (utree) { view->tot_trees = 1; view->trees = (char**)malloc(sizeof(char*)); view->trees[0] = utree; usertreerank = 1; } tree = run_parsimony_method(view, isarg(argc, argv, "-nogaps"), isarg(argc, argv, "-gaps_as_unknown") ? ", gaps treated as ?" : "", replicates, jumbles, 10000, usertreerank, NULL, s_option, &progname, 1, true, 0, Fl::fatal); if (tree && (p = strchr(tree, ';')) != NULL) *(p+1) = 0; // tree string can contain several trees, keep first only } if (tree) { char *outfname = argname(argc, argv, "-o"); FILE *out = (strcmp(outfname, "-") != 0 ? fopen(outfname, "w") : stdout); fwrite(tree, strlen(tree), 1, out); fputs("\n", out); fflush(out); if (out != stdout) fclose(out); } } void save_bootstrap_replicates(const char *fname, int replicates, SEA_VIEW *view) { allseq *seqs = view_to_allseq(view, FALSE); int *each_length = new int[seqs->n_otu]; for (int i = 0; i < seqs->n_otu; i++) each_length[i] = seqs->clean_len; char **sequences = new char*[seqs->n_otu]; for (int i = 0; i < seqs->n_otu; i++) { sequences[i] = new char[seqs->clean_len]; } FILE *out = fl_fopen(fname, "w"); char *tmp_fname = create_tmp_filename(); for (int repl = 1; repl <= replicates; repl++) { bootstrap_weights(seqs, FALSE); for (int i = 0; i < seqs->n_otu; i++) { int l = 0; for (int j = 0; j < seqs->clean_len; j++) { for (int k = 0; k < seqs->wght[j]; k++) { sequences[i][l++] = seqs->c_seq[i]->state[j]; } } } save_alignment_or_region(tmp_fname, sequences, NULL, NULL, view->seqname, seqs->n_otu, each_length, NULL, NULL, PHYLIP_FORMAT, 0, NULL, NULL, NULL, 0, view->protein, 0, NULL, NULL, view->phylipwidnames, 0, NULL, NULL, view->spaces_in_fasta_names); // add to growing output file FILE *in = fl_fopen(tmp_fname, "r"); char line[100]; while (fgets(line, sizeof(line), in)) { fputs(line, out); } fclose(in); fl_unlink(tmp_fname); } fclose(out); for (int i = 0; i < seqs->n_otu; i++) delete[] sequences[i]; delete[] sequences; delete[] each_length; free_after_view_to_allseq(seqs); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/unrooted.cxx��������������������������������������������������������������������������������000644 �000765 �000024 �00000126675 12502331020 015414� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include "unrooted.h" #include "treedraw.h" #include "pdf_or_ps.h" #include #include /* prototypes of included functions */ void rooted_unrooted_callback(Fl_Widget *o, void *data); void unrooted_scroller_cb(Fl_Widget *wgt, void *data); void unrooted_zoom_cb(Fl_Widget *o, void *data); void frame_and_draw_unrooted(FD_unrooted *fd_unrooted); void draw_tree(FD_unrooted *ob); int debut_arbre(const char *tree, FD_unrooted *fd_unrooted); void my_draw_text(Fl_Align align, int x, int y, int size, int font, char *chaine); hit draw_line(unrooted_branch *br, FD_unrooted *ob, int doit, int char_width, int char_height, int descend, int ascent); hit try_angle_draw(float w, int *px, int *py, float *pdegrees /* clockwise degrees */, int bx, int by, int bw, int bh); hit draw_name_angle(cp_point *phys_pos, const char *nom, FD_unrooted *ob, double angle, int doit, int char_width, int char_height, int descend, int color, int ascent); void draw_scale(FD_unrooted *data, int char_height, int ascent); int my_get_char_height(int *ascend, int *descend); void free_unrooted(FD_unrooted *data); void unrooted_search(FD_unrooted *fd_unrooted, const char *select); const char *preptree_unrooted(const char *tree, FD_unrooted *data); static void loadphylip(char *arbre, FD_unrooted *data); static struct noeud *unrootedset(char *arbre, char *deb, char *fin, branche_noeud **p_int_br, FD_unrooted *data); double calc_echelle(FD_unrooted *data, int larg); bignoeud *cre_new_tree(struct noeud *debut, struct noeud *parent, bignoeud *bigparent); void remove_big_root(bignoeud *bigracine); double calc_dist_centre_feuilles(bignoeud *debut, bignoeud *parent); double proc_null_neg_branches(bignoeud *debut, bignoeud *parent); int set_angles_noeuds(bignoeud *debut, bignoeud *parent, double delta, double *p_current_angle, double rayon); void calc_cartesienne( cp_point *p); void calc_polaire( cp_point *p); cp_point calc_point_direction( cp_point *depart, cp_point *direction, double longueur, double mini_br_length); unrooted_branch *calc_position_noeuds(bignoeud *debut, bignoeud *parent, unrooted_branch *curr_branche, double mini_br_length); void mem_line(cp_point *debut, cp_point *fin, bignoeud *noeud_term, unrooted_branch *br); void free_bignoeud(bignoeud *debut, bignoeud *parent); int chg_phys(FD_unrooted *ob, hits_field *hits ); void log_to_phys(FD_unrooted *data, cp_point *log_pos, cp_point *phys_pos); double length_log_phys(FD_unrooted *data, double p); double length_phys_log(FD_unrooted *data, double p); void squared2circular(FD_nj_plot *fd_nj_plot, Fl_Choice *o); void circular2squared(FD_nj_plot *fd_nj_plot); void print_unrooted(FD_unrooted *fd_unrooted, bool to_ps_file, const char *directname = NULL); /* external functions */ extern const char *extract_filename(const char *fname); extern void majuscules(char *p); extern void *check_alloc(int nbrelt, int sizelt); extern void my_watch_cursor(Fl_Window *win); extern void fl_reset_cursor(Fl_Window *win); extern char *ecrit_arbre_parenth_unrooted(FD_nj_plot *fd_nj_plot, struct noeud *root); extern double place_midpoint_root(struct noeud *from, struct noeud *racine, int notu, int fixed_outgroup); extern const char *make_binary_or_unrooted(char *arbre); extern int make_binary(char *arbre, char *debut, char *fin, int go_down); extern char *nextpar(char *pospar); extern double arrondi_echelle(double x); extern void zoom_callback(Fl_Widget *wgt, void *data); extern void scroller_callback(Fl_Widget *wgt, void *data); extern int calc_brl_for_lengthless(struct noeud *centre, struct noeud *pere); extern const char *preptree(FD_nj_plot *fd_nj_plot); extern void free_tree(FD_nj_plot *fd_nj_plot); extern char *ecrit_arbre_parenth(FD_nj_plot *fd_nj_plot, struct noeud *root); extern void replace_with_new_tree(FD_nj_plot *fd_nj_plot, char *newtree); /* globals */ static int nextotu, num_noeud; extern Fl_Paged_Device::Page_Format printout_pageformat; void rooted_unrooted_callback(Fl_Widget *o, void *data) { FD_nj_plot *fd_nj_plot = (FD_nj_plot *)data; char *keep, *keepn, *keepl; if(((Fl_Choice *)o)->value() == 0) {//goto squared display if(fd_nj_plot->fd_unrooted != NULL) circular2squared(fd_nj_plot); if(fd_nj_plot->lost_br_lengths) { fd_nj_plot->lost_br_lengths = FALSE; keep = fd_nj_plot->trees; keepn = fd_nj_plot->tree_name; keepl = fd_nj_plot->tree_label; fd_nj_plot->trees = NULL; fd_nj_plot->tree_name = NULL; fd_nj_plot->tree_label = NULL; free_tree(fd_nj_plot); fd_nj_plot->trees = keep; fd_nj_plot->tree_name = keepn; fd_nj_plot->tree_label = keepl; preptree(fd_nj_plot);//reinterpret tree for its branch lengths } if(fd_nj_plot->has_br_length) fd_nj_plot->l_button->activate(); fd_nj_plot->new_outgroup->activate(); fd_nj_plot->swap_button->activate(); fd_nj_plot->need_runtree = TRUE; fd_nj_plot->panel->show(); fd_nj_plot->panel->window()->redraw(); } else if(((Fl_Choice *)o)->value() == 1) {//goto circular display if (fd_nj_plot->notu < 3) { fd_nj_plot->root_unroot->value(0); return; } if(fd_nj_plot->lost_br_lengths) { fd_nj_plot->lost_br_lengths = FALSE; keep = fd_nj_plot->trees; keepn = fd_nj_plot->tree_name; keepl = fd_nj_plot->tree_label; fd_nj_plot->trees = NULL; fd_nj_plot->tree_name = NULL; fd_nj_plot->tree_label = NULL; free_tree(fd_nj_plot); fd_nj_plot->trees = keep; fd_nj_plot->tree_name = keepn; fd_nj_plot->tree_label = keepl; preptree(fd_nj_plot);//reinterpret tree for its branch lengths for(int i=0; inotu; i++) { strcpy(fd_nj_plot->tabtax[i]->nom, fd_nj_plot->labels[i]); } } if(fd_nj_plot->fd_unrooted == NULL) squared2circular(fd_nj_plot, (Fl_Choice *)o); } else if(((Fl_Choice *)o)->value() == 2) {//goto Cladogram display if(fd_nj_plot->fd_unrooted != NULL) circular2squared(fd_nj_plot); keep = ecrit_arbre_parenth(fd_nj_plot, fd_nj_plot->racine); // to share reroot/swaps between squared/cladogram replace_with_new_tree(fd_nj_plot, keep); fd_nj_plot->lost_br_lengths = TRUE; fd_nj_plot->has_br_length = FALSE; calc_brl_for_lengthless(fd_nj_plot->racine, NULL); fd_nj_plot->need_runtree = TRUE; fd_nj_plot->l_button->deactivate(); fd_nj_plot->new_outgroup->deactivate(); fd_nj_plot->swap_button->deactivate(); fd_nj_plot->choix = show_tree; fd_nj_plot->full->setonly(); fd_nj_plot->panel->show(); fd_nj_plot->panel->window()->redraw(); } } void squared2circular(FD_nj_plot *fd_nj_plot, Fl_Choice *o) { Fl_Menu_Item *item = fd_nj_plot->menu_file->get_menu(); Fl_Menu_Item *edit_item = fd_nj_plot->menu_edit->get_menu(); Fl_Widget *panel = fd_nj_plot->panel; FD_unrooted *fd_unrooted; char *tree = ecrit_arbre_parenth_unrooted(fd_nj_plot, fd_nj_plot->racine); if(tree == NULL) { o->value(0); return; } fd_unrooted = (FD_unrooted *) calloc(1, sizeof(FD_unrooted)); int err = debut_arbre(tree, fd_unrooted); free(tree); if(err) { o->value(0); free(fd_unrooted); return; } panel->hide(); fd_nj_plot->scroller->hide(); fd_nj_plot->l_button->deactivate(); fd_nj_plot->bt_button->deactivate(); fd_nj_plot->full->deactivate(); fd_nj_plot->swap_button->deactivate(); fd_nj_plot->subtree->deactivate(); fd_nj_plot->new_outgroup->deactivate(); fd_nj_plot->select->deactivate(); edit_item[4].deactivate();//edit header edit_item[5].deactivate();//bootstrap threshold edit_item[9].deactivate();//root at center edit_item[fd_nj_plot->edit_shape_rank].deactivate();//edit shape item[2].deactivate();//save rooted tree item[3].deactivate();//save unrooted tree item[9].deactivate();//Page count fd_unrooted->zoomvalue = 1; fd_nj_plot->zoom->value(1); Fl_Window *w2 = (Fl_Window *)panel->parent(); Fl_Group::current(w2); fd_unrooted->vert_scroller = new Fl_Scrollbar(w2->w() - 15, 0, 15, fd_nj_plot->scroller->h()); fd_unrooted->vert_scroller->hide(); fd_unrooted->vert_scroller->bounds(0, 1); fd_unrooted->vert_scroller->slider_size(1); ((Fl_Slider *)fd_unrooted->vert_scroller)->value(0); fd_unrooted->y = 0; fd_unrooted->y_offset = 0; fd_unrooted->vert_scroller->callback(unrooted_scroller_cb, fd_unrooted); fd_nj_plot->zoom->callback(unrooted_zoom_cb, fd_unrooted); fd_unrooted->unrooted_plot = new unrooted_panel(0, 0, w2->w(), w2->h()); Fl_Box *box = new Fl_Box(0, 0, w2->w() - 15, w2->h() - 15); box->hide(); w2->resizable(box); fd_unrooted->unrooted_plot->color(FL_WHITE); fd_unrooted->unrooted_plot->user_data(fd_unrooted); fd_unrooted->hor_scroller = new Fl_Scrollbar(0, w2->h() - 15, w2->w() - 15, 15); fd_unrooted->hor_scroller->hide(); fd_unrooted->hor_scroller->type(FL_HORIZONTAL); fd_unrooted->hor_scroller->bounds(0, 1); fd_unrooted->hor_scroller->slider_size(1); ((Fl_Slider *)fd_unrooted->hor_scroller)->value(0); fd_unrooted->x = 0; fd_unrooted->x_offset = 0; fd_unrooted->hor_scroller->callback(unrooted_scroller_cb, fd_unrooted); fd_unrooted->current_font = fd_nj_plot->font_family; fd_unrooted->font_size = fd_nj_plot->font_size; fd_nj_plot->fd_unrooted = (void *)fd_unrooted; } void circular2squared(FD_nj_plot *fd_nj_plot) { Fl_Menu_Item *item = fd_nj_plot->menu_file->get_menu(); Fl_Menu_Item *edit_item = fd_nj_plot->menu_edit->get_menu(); FD_unrooted *fd_unrooted = (FD_unrooted *)fd_nj_plot->fd_unrooted; fd_unrooted->unrooted_plot->hide(); fd_unrooted->vert_scroller->hide(); fd_unrooted->hor_scroller->hide(); //dont't call delete but Fl::delete_widget after having removed it from its group!!! fd_unrooted->unrooted_plot->window()->remove( *fd_unrooted->vert_scroller ); fd_unrooted->unrooted_plot->window()->remove( *fd_unrooted->hor_scroller ); fd_unrooted->unrooted_plot->window()->remove( *fd_unrooted->unrooted_plot ); Fl::delete_widget(fd_unrooted->unrooted_plot); Fl::delete_widget(fd_unrooted->vert_scroller); Fl::delete_widget(fd_unrooted->hor_scroller); free_unrooted(fd_unrooted); fd_nj_plot->fd_unrooted = NULL; if(fd_nj_plot->has_br_length) fd_nj_plot->l_button->activate(); if(fd_nj_plot->has_internal) fd_nj_plot->bt_button->activate(); if(fd_nj_plot->zoomvalue > 1.1) fd_nj_plot->scroller->show(); fd_nj_plot->zoom->value(fd_nj_plot->zoomvalue); fd_nj_plot->zoom->callback(zoom_callback, fd_nj_plot); fd_nj_plot->full->activate(); fd_nj_plot->swap_button->activate(); fd_nj_plot->subtree->activate(); fd_nj_plot->new_outgroup->activate(); fd_nj_plot->select->activate(); edit_item[4].activate();//edit header edit_item[5].activate(); edit_item[9].activate();//root at center edit_item[fd_nj_plot->edit_shape_rank].activate();//edit shape item[2].activate(); item[3].activate(); item[9].activate(); } void unrooted_scroller_cb(Fl_Widget *wgt, void *data) { FD_unrooted *fd_unrooted = (FD_unrooted *)data; int val = ((Fl_Scrollbar *)wgt)->value(); if(wgt->type() == FL_VERTICAL) fd_unrooted->y_offset = - val; else fd_unrooted->x_offset = - val; fd_unrooted->unrooted_plot->parent()->redraw(); } void unrooted_zoom_cb(Fl_Widget *wgt, void *data) { FD_unrooted *fd_unrooted = (FD_unrooted *)data; if(((Fl_Counter *)wgt)->value() > fd_unrooted->zoomvalue) fd_unrooted->zoomvalue *= 1.4; else fd_unrooted->zoomvalue /= 1.4; fd_unrooted->zoomvalue = ((Fl_Counter *)wgt)->clamp(fd_unrooted->zoomvalue); ((Fl_Counter *)wgt)->value(fd_unrooted->zoomvalue); if(fd_unrooted->zoomvalue <= 1.1) { fd_unrooted->unrooted_plot->size(fd_unrooted->unrooted_plot->w(), fd_unrooted->unrooted_plot->parent()->h()); fd_unrooted->vert_scroller->hide(); fd_unrooted->hor_scroller->hide(); } else { fd_unrooted->unrooted_plot->size(fd_unrooted->unrooted_plot->parent()->w() - 15, fd_unrooted->unrooted_plot->parent()->h() - 15); if(!fd_unrooted->vert_scroller->visible()) fd_unrooted->vert_scroller->show(); if(!fd_unrooted->hor_scroller->visible()) fd_unrooted->hor_scroller->show(); } float count = fd_unrooted->unrooted_plot->h() * (fd_unrooted->zoomvalue - 1); count = FL_max(count, 1); float old = fd_unrooted->vert_scroller->value() / fd_unrooted->vert_scroller->maximum(); fd_unrooted->vert_scroller->maximum(count); ((Fl_Slider *)fd_unrooted->vert_scroller)->value(myrint(old * count)); fd_unrooted->y_offset = -(int)(old *count); fd_unrooted->vert_scroller->linesize(myrint(count/9)); fd_unrooted->vert_scroller->slider_size(1/fd_unrooted->zoomvalue); count = fd_unrooted->unrooted_plot->w() * (fd_unrooted->zoomvalue - 1); count = FL_max(count, 1); old = fd_unrooted->hor_scroller->value() / fd_unrooted->hor_scroller->maximum(); fd_unrooted->hor_scroller->maximum(count); ((Fl_Slider *)fd_unrooted->hor_scroller)->value(myrint(old * count)); fd_unrooted->x_offset = -(int)(old *count); fd_unrooted->hor_scroller->linesize(myrint(count/9)); fd_unrooted->hor_scroller->slider_size(1/fd_unrooted->zoomvalue); fd_unrooted->comp_phys_bounds = TRUE; fd_unrooted->previous_w = 0; fd_unrooted->previous_h = 0; fd_unrooted->unrooted_plot->parent()->redraw(); } void frame_and_draw_unrooted(FD_unrooted *fd_unrooted) { if( fd_unrooted->comp_phys_bounds ) { /* valeurs initiales des extr physiques des lignes du graphique */ fd_unrooted->phys_max_x = fd_unrooted->x + fd_unrooted->w; fd_unrooted->phys_max_y = fd_unrooted->y + fd_unrooted->h; fd_unrooted->phys_min_x = fd_unrooted->x; fd_unrooted->phys_min_y = fd_unrooted->y; } fl_line_style(FL_SOLID, 2, 0); fl_color(FL_BLACK); fl_font(fd_unrooted->current_font, fd_unrooted->font_size); draw_tree(fd_unrooted); fl_line_style(FL_SOLID, 0, 0); fd_unrooted->comp_phys_bounds = FALSE; } void unrooted_panel::draw(void) { int width, height; FD_unrooted *fd_unrooted = (FD_unrooted *)this->user_data(); if(fd_unrooted->notu == 0) return; width = myrint(this->w() * fd_unrooted->zoomvalue); height = myrint(this->h() * fd_unrooted->zoomvalue); if( width != fd_unrooted->previous_w || height != fd_unrooted->previous_h ) { /* si on a redimensionne la fenetre ou la 1ere fois */ fd_unrooted->previous_w = width; fd_unrooted->previous_h = height; fd_unrooted->comp_phys_bounds = TRUE; fd_unrooted->w = width; fd_unrooted->h = height; } fl_push_clip(this->x(), this->y(), this->w(), this->h()); frame_and_draw_unrooted(fd_unrooted); fl_pop_clip(); } int unrooted_panel::handle(int event) { FD_unrooted *fd_unrooted = (FD_unrooted *)this->user_data(); int mx = Fl::event_x(); int my = Fl::event_y(); static int start_x, start_y; static int start_sx, start_sy; switch(event) { case FL_PUSH: if(fd_unrooted->zoomvalue > 1) { this->window()->cursor(FL_CURSOR_MOVE); Fl::flush(); } start_x = mx; start_y = my; start_sx = fd_unrooted->hor_scroller->value(); start_sy = fd_unrooted->vert_scroller->value(); break; case FL_DRAG: if(fd_unrooted->zoomvalue > 1) { int val = (int)fd_unrooted->hor_scroller->clamp(start_sx - (mx - start_x)); ((Fl_Slider *)fd_unrooted->hor_scroller)->value(val); val = (int)fd_unrooted->vert_scroller->clamp(start_sy - (my - start_y)); ((Fl_Slider *)fd_unrooted->vert_scroller)->value(val); fd_unrooted->hor_scroller->do_callback(); fd_unrooted->vert_scroller->do_callback(); } break; case FL_RELEASE: if(fd_unrooted->zoomvalue > 1) { fl_reset_cursor(this->window()); } break; default : return 0; // other events are not processed here } return 1; // from processed events } void draw_tree(FD_unrooted *ob) { int char_width, char_height, num, dernier, encore = FALSE, ascend, descend; hit result; hits_field hits; char_width = myrint(fl_width("M")); char_height = my_get_char_height(&ascend, &descend); dernier = 2*ob->notu-3; if( ob->comp_phys_bounds ) { /* rendre dimensions carrees */ if (ob->phys_max_x - ob->phys_min_x > ob->phys_max_y - ob->phys_min_y) ob->phys_max_x = ob->phys_min_x + (ob->phys_max_y - ob->phys_min_y); else if(ob->phys_max_y - ob->phys_min_y > ob->phys_max_x - ob->phys_min_x) ob->phys_max_y = ob->phys_min_y + (ob->phys_max_x - ob->phys_min_x); do { hits.left = hits.right = hits.top = hits.bottom = 0; for(num = 0; num < dernier; num++) { result = draw_line(ob->branches+num, ob, FALSE, char_width, char_height, descend, ascend); if(result == LEFT_HIT) hits.left = 1; else if(result == RIGHT_HIT) hits.right = 1; else if(result == TOP_HIT) hits.top = 1; else if(result == BOTTOM_HIT) hits.bottom = 1; } encore = chg_phys(ob, &hits); } while (encore); if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) { for(num = 0; num < dernier; num++) ob->branches[num].color = FALSE; } } for(num=0; num< dernier; num++) { draw_line(ob->branches+num, ob, TRUE, char_width, char_height, descend, ascend); } if(ob->has_br_length) draw_scale(ob, char_height, ascend); } void print_unrooted(FD_unrooted *fd_unrooted, const char *name, bool to_ps_file, const char *directname) { Fl_Printer* myprinter; int old_x, old_y, error; old_x = fd_unrooted->x_offset; old_y = fd_unrooted->y_offset; if (to_ps_file) { myprinter = (Fl_Printer*)new Fl_PDF_or_PS_File_Device(); if (directname) error = ((Fl_PDF_or_PS_File_Device*)myprinter)->begin_document(directname, printout_pageformat); else error = ((Fl_PDF_or_PS_File_Device*)myprinter)->start_job(name, printout_pageformat) ; if (error) return; } else { int from, to; myprinter = new Fl_Printer(); if (myprinter->start_job(1, &from, &to) ) return; } #ifndef NO_PDF jmp_buf *jbuf; if (to_ps_file) ((Fl_PDF_File_Device*)myprinter)->surface_try(&jbuf); if ( (!to_ps_file) || setjmp(*jbuf) == 0) { // replaces PDF_TRY #endif myprinter->start_page(); fd_unrooted->previous_w = fd_unrooted->previous_h = 0; myprinter->printable_rect( &fd_unrooted->w, &fd_unrooted->h); fd_unrooted->x = fd_unrooted->y = 0; fd_unrooted->x_offset = fd_unrooted->y_offset = 0; fd_unrooted->y += 20; fd_unrooted->h -= 20; time_t heure; time(&heure); char bigline[200]; sprintf(bigline, "%s %s", extract_filename(name), ctime(&heure)); fl_font(FL_TIMES, 12); fl_color(FL_BLACK); fl_draw(bigline, fd_unrooted->x, fd_unrooted->y - 5); fl_color(FL_GRAY); fl_rect(fd_unrooted->x, fd_unrooted->y, fd_unrooted->w, fd_unrooted->h); fl_color(FL_BLACK); fd_unrooted->comp_phys_bounds = TRUE; frame_and_draw_unrooted(fd_unrooted); myprinter->end_page(); myprinter->end_job(); #ifndef NO_PDF } // end of PDF_TRY if (to_ps_file && ((Fl_PDF_File_Device*)myprinter)->surface_catch()) { // replaces PDF_CATCH ((Fl_PDF_File_Device*)myprinter)->error_catch(); } #endif delete myprinter; fd_unrooted->x_offset = old_x; fd_unrooted->y_offset = old_y; } int debut_arbre(const char *tree, FD_unrooted *fd_unrooted) //returns 0 iff OK { bignoeud *centre, *bigracine; const char *pname; int tot; double delta, current_angle, width, height; unrooted_branch *fin_branche, *br; double radius; /* read tree string */ if( (pname=preptree_unrooted(tree, fd_unrooted)) != NULL ) { char mess[150]; strcpy(mess, pname); fl_alert("%s", mess); fd_unrooted->notu = 0; return 1; } bigracine = cre_new_tree(fd_unrooted->racine, NULL, NULL); if(!fd_unrooted->has_br_length) bigracine->l2 = 0; centre = bigracine->v1; /* changer de centre si c'est une feuille */ tot=0; if(centre->v1 == NULL) tot++; if(centre->v2 == NULL) tot++; if(centre->v3 == NULL) tot++; if(tot>= 2) centre = bigracine->v2; remove_big_root(bigracine); radius = 1.1 * calc_dist_centre_feuilles(centre, NULL); /* on va remplacer les branches nulles par des branches 100 fois plus courtes que la plus courte de l'arbre */ fd_unrooted->mini_br_length = proc_null_neg_branches(centre, NULL); fd_unrooted->mini_br_length /= 100; delta = 2*M_PI / fd_unrooted->notu; current_angle = 0; set_angles_noeuds(centre, NULL, delta, ¤t_angle, radius); centre->position.r = 0; centre->position.angle = 0; calc_cartesienne(&(centre->position)); fd_unrooted->branches = (unrooted_branch *)check_alloc(2*fd_unrooted->notu-3, sizeof(unrooted_branch)); fin_branche = calc_position_noeuds(centre, NULL, fd_unrooted->branches, fd_unrooted->mini_br_length); free_bignoeud(centre, NULL); /* calcul extremites du graphique des branches */ fd_unrooted->log_min_x = fd_unrooted->log_max_x = fd_unrooted->branches->debut.x; fd_unrooted->log_min_y = fd_unrooted->log_max_y = fd_unrooted->branches->debut.y; for(br = fd_unrooted->branches; br < fin_branche; br++) { if(br->debut.x < fd_unrooted->log_min_x) fd_unrooted->log_min_x = br->debut.x; if(br->debut.x > fd_unrooted->log_max_x) fd_unrooted->log_max_x = br->debut.x; if(br->fin.x < fd_unrooted->log_min_x) fd_unrooted->log_min_x = br->fin.x; if(br->fin.x > fd_unrooted->log_max_x) fd_unrooted->log_max_x = br->fin.x; if(br->debut.y < fd_unrooted->log_min_y) fd_unrooted->log_min_y = br->debut.y; if(br->debut.y > fd_unrooted->log_max_y) fd_unrooted->log_max_y = br->debut.y; if(br->fin.y < fd_unrooted->log_min_y) fd_unrooted->log_min_y = br->fin.y; if(br->fin.y > fd_unrooted->log_max_y) fd_unrooted->log_max_y = br->fin.y; } width = fd_unrooted->log_max_x - fd_unrooted->log_min_x; height = fd_unrooted->log_max_y - fd_unrooted->log_min_y; if( width > height ) { fd_unrooted->log_min_y -= (width - height)/2; fd_unrooted->log_max_y += (width - height)/2; } else if( height > width ) { fd_unrooted->log_min_x -= (height - width)/2; fd_unrooted->log_max_x += (height - width)/2; } return 0; } void my_draw_text(Fl_Align align, int x, int y, int size, int current_font, char *chaine) { fl_font(current_font, size); if(align == FL_ALIGN_CENTER) x -= (int)(fl_width(chaine)/2); fl_draw(chaine, x, y); } hit draw_line(unrooted_branch *br, FD_unrooted *fd_unrooted, int doit, int char_width, int char_height, int descend, int ascent) { double h, w; double angle; cp_point phys_debut, phys_fin; hit result; static char txt[300]; log_to_phys(fd_unrooted, &br->debut, &phys_debut); log_to_phys(fd_unrooted, &br->fin, &phys_fin); w = phys_fin.x - phys_debut.x; h = phys_fin.y - phys_debut.y; if(doit) { phys_fin.x += fd_unrooted->x_offset; phys_fin.y += fd_unrooted->y_offset; phys_debut.x += fd_unrooted->x_offset; phys_debut.y += fd_unrooted->y_offset; fl_line((int)(phys_debut.x), (int)(phys_debut.y ), (int)(phys_fin.x ), (int)(phys_fin.y )); } if(br->nom != NULL) { /* calcul de l'angle tel que vu sur le dessin: il faut utiliser -h car les coord en y sont calculees avec 0 en haut aussi mettre angle dans [0 , 2*pi[ */ angle = atan( (-h) / w ); if( w < 0 ) angle = M_PI + angle; if(angle < 0) angle += 2*M_PI; if(angle > M_PI_2 && angle < 3 * M_PI_2) sprintf(txt,"%s ", br->nom); else sprintf(txt, " %s", br->nom); result = draw_name_angle(&phys_fin, txt, fd_unrooted, angle, doit, char_width, char_height, descend, br->color, ascent); if( result != NO_HIT ) return result; } return NO_HIT; } hit try_angle_draw(float w, int *px, int *py, float *pdegrees /* clockwise degrees */, int bx, int by, int bw, int bh) { //compute bounds x1,y1 x2,y2 x3,y3 x4,y4 of to be drawn string int x1, y1, x2, y2, x3, y3, x4, y4; float degrees = *pdegrees; x1 = *px; y1 = *py; double radians = - M_PI * degrees / 180; /* counterclockwise radians */ if(radians < 0) radians += 2 * M_PI; float cosa = cos(radians); float sina = sin(radians); if(radians > M_PI/2 && radians < 3*M_PI/2 ) {//draw string so its end is at position x,y x1 += (int)( w * cosa ); y1 -= (int)( w * sina ); radians += M_PI; degrees -= 180;/* clockwise degrees */ if(radians >= 2*M_PI) radians -= 2 * M_PI; if(degrees <= 0) degrees += 360; cosa = - cosa; sina = - sina; } x1 += (int)( (fl_size()/3) * sina );//position string midheight at position x,y y1 += (int)( (fl_size()/3) * cosa ); const float ch = 0.7; x2 = x1 - (int)(ch * fl_size() * sina); y2 = y1 - (int)(ch * fl_size() * cosa); x3 = x2 + (int)(w * cosa); y3 = y2 - (int)(w * sina); x4 = x1 + (int)(w * cosa); y4 = y1 - (int)(w * sina); int xmax = x1, ymax = y1, xmin = x1, ymin = y1; if(x2 > xmax) xmax = x2; if(x3 > xmax) xmax = x3; if(x4 > xmax) xmax = x4; if(x2 < xmin) xmin = x2; if(x3 < xmin) xmin = x3; if(x4 < xmin) xmin = x4; if(y2 > ymax) ymax = y2; if(y3 > ymax) ymax = y3; if(y4 > ymax) ymax = y4; if(y2 < ymin) ymin = y2; if(y3 < ymin) ymin = y3; if(y4 < ymin) ymin = y4; *px = x1; *py = y1; *pdegrees = degrees; if(xmin < bx) return LEFT_HIT; if(xmax > bx + bw) return RIGHT_HIT; if(ymin < by) return TOP_HIT; if(ymax > by + bh) return BOTTOM_HIT; return NO_HIT; } hit draw_name_angle(cp_point *phys_pos, const char *nom, FD_unrooted *fd_unrooted, double radians, int doit, int char_width, int char_height, int descend, int color, int ascent) { int x, y; float degrees = - radians * 180/M_PI; x = (int)phys_pos->x; y = (int)phys_pos->y; float w = fl_width(nom); hit result = try_angle_draw(w, &x, &y, °rees, fd_unrooted->x, fd_unrooted->y, fd_unrooted->w, fd_unrooted->h); if( (!doit) && result != NO_HIT) return result; if( ! doit) return NO_HIT; if(color) fl_color(FL_RED); fl_draw(-(int)degrees, nom, x, y); if(color) fl_color(FL_BLACK); return NO_HIT; } void draw_scale(FD_unrooted *fd_unrooted, int charheight, int ascent) { char ech_name[20]; int phys_w, y, xd, xf; double log_val; log_val = calc_echelle(fd_unrooted, fd_unrooted->w); phys_w = myrint(length_log_phys(fd_unrooted, log_val)); y = (int)(1.5 * charheight) + fd_unrooted->y_offset; xf = (int)(fd_unrooted->w * 0.97) + fd_unrooted->x_offset; xd = xf - phys_w; fl_line_style(FL_SOLID, 0, 0); fl_line(xd , y, xf, y); sprintf(ech_name, "%.1g", log_val); my_draw_text(FL_ALIGN_CENTER, (xd + xf)/2, y - charheight/3, 12, FL_TIMES, ech_name); fl_line(xd, y - charheight/3, xd, y + charheight/3); fl_line(xf + fd_unrooted->x, y - charheight/3, xf, y + charheight/3); } int my_get_char_height(int *ascend, int *descend) { *ascend = fl_height() - fl_descent(); *descend = fl_descent(); return *ascend + *descend ; } void free_unrooted(FD_unrooted *data) { int i; if(data->notu == 0) return; /* de-allocate all memory */ for(i=0; i<2*data->notu - 1; i++) { if(data->tabtax[i]->nom != NULL) free(data->tabtax[i]->nom); free(data->tabtax[i]); } free(data->tabtax); if(data->branche_noeuds != NULL) free(data->branche_noeuds); if(data->branches != NULL) free(data->branches); data->notu = 0; free(data); } void unrooted_search(FD_unrooted *fd_unrooted, const char *select) { int trouve, totnoms, num; char aux[500]; trouve = FALSE; totnoms = 2 * fd_unrooted->notu - 3; for(num = 0; num < totnoms; num++) { if(fd_unrooted->branches[num].nom == NULL) continue; strcpy(aux, fd_unrooted->branches[num].nom); majuscules(aux); if(strstr( aux, select) != NULL) { trouve = TRUE; fd_unrooted->branches[num].color = TRUE; } } if(trouve) { fd_unrooted->unrooted_plot->parent()->redraw(); } } const char *preptree_unrooted(const char *tree, FD_unrooted *data) { int i, c, v; char *arbre, *finarbre, *p; arbre = strdup(tree); p = arbre; while(isspace(*p)) p++; data->notu = 2; i = 3; v = 0; if(*p == '(') { if(p > arbre) memmove(arbre, p, strlen(p) + 1); p = arbre + 1; while( (c=*(p++)) != 0 && c != ';') { if(c == ')') data->notu++; if(c == '(') i++; if(c == ',') v++; } } if(i != data->notu) { free(arbre); data->notu = 0; return "Incorrect tree data."; } finarbre = nextpar(arbre); if(finarbre == NULL) { data->notu = 0; return ("Unbalanced parentheses in tree."); } arbre = (char *)realloc(arbre, strlen(arbre) + 4 * v + 5 ); /* worst case add 4 chars for each , */ p = (char *)make_binary_or_unrooted(arbre); if(p != NULL) { data->notu = 0; free(arbre); return p; } data->notu = v + 1 ; /* after this notu = number of OTUs */ data->totbranches = -1; /* allocate all memory */ data->tabtax = (struct noeud **)check_alloc(2*data->notu - 1,sizeof(struct noeud *)); if(data->notu > 3) data->branche_noeuds = (branche_noeud *)check_alloc(data->notu-3, sizeof(branche_noeud)); for (i = 0; i < 2*data->notu - 1; i++) { data->tabtax[i] = (struct noeud *)check_alloc(1, sizeof(struct noeud)); data->tabtax[i]->rank = i; } loadphylip(arbre, data); free(arbre); if(data->notu == 0) goto erreur; if(!data->rooted) { data->racine = *(data->tabtax+(++num_noeud)); if(num_noeud >= 2*data->notu - 1) return("Error: incorrect tree file"); data->root_br_l = place_midpoint_root(data->tabtax[0], data->racine, data->notu, FALSE); } else { return ("Unexpected rooted tree."); } if(data->notu < 3) return ("Tree should contain at least 3 elements."); return (NULL); erreur: return ("Not a valid tree."); } /* end of preptree_unrooted */ static void loadphylip(char *arbre, FD_unrooted *data) { char *deba,*debb,*debc, *finarbre; struct noeud *p1, *p2, *p3, *p; branche_noeud *int_br_g, *int_br_d; data->has_br_length=2; /* ignore all stuff after last closing parenthesis (needed for fastDNAml output) */ finarbre= nextpar(arbre); data->rooted=0; deba=arbre+1; debb=deba; while(*debb != ',') { if(*debb == '(')debb=nextpar(debb); debb++; } debb++; debc=debb; while(*debc != ',' && debc it has 3 subtrees at its bottommost level */ debc++; } else { /* the tree is rooted */ debc=finarbre+1; data->rooted = 1; } num_noeud = data->notu - 1; nextotu = -1; p1=unrootedset(arbre, deba, debb-2, &int_br_g, data); if(p1 != NULL) p2=unrootedset(arbre, debb, debc-2, &int_br_d, data); if(p1 == NULL || p2 == NULL || num_noeud + 1 >= 2*data->notu - 1) { data->notu = 0; return; } p = *(data->tabtax+(++num_noeud)); if(!data->has_br_length) { p1->l3 = 0.5*p1->l3; p2->l3 = 0.5*p2->l3; } p->v1=p1; p1->v3=p; p->l1=p1->l3; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p1; } p->v2=p2; p2->v3=p; p->l2=p2->l3; if(int_br_d!=NULL) { int_br_d->bouta=p; int_br_d->boutb=p2; } if(!data->rooted) { p3=unrootedset(arbre, debc, finarbre-1, &int_br_g, data); if(p3 == NULL ) { data->notu = 0; return; } if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p3; } p->v3=p3; p3->v3=p; p->l3=p3->l3; } else { p->v3=NULL; /* recherche d'un dernier label interne */ debc=finarbre+1; while(*debc!=0 && *debc!=':' && *debc!='[') debc++; if(debc-finarbre>1) { data->totbranches++; data->branche_noeuds[data->totbranches].bouta=p1; data->branche_noeuds[data->totbranches].boutb=p2; } } } static struct noeud *unrootedset(char *arbre, char *deb, char *fin, branche_noeud **p_int_br, FD_unrooted *data) { struct noeud *p; char *virg; int l; branche_noeud *int_br_g, *int_br_d; *p_int_br=NULL; while(*deb==' ' || *deb=='\'')deb++; while(*fin==' ')fin--; virg=deb; while(*virg != ',' && virg < fin) { if(*virg == '(') virg=nextpar(virg); virg++; } if(virg>fin) virg=deb; if(*virg == ',') { struct noeud *p1,*p2; p1=unrootedset(arbre,deb,virg-1,&int_br_g, data); if(p1 == NULL) return NULL; p2=unrootedset(arbre,virg+1,fin,&int_br_d, data); if(p2 == NULL) return NULL; if(num_noeud + 1 >= 2*data->notu - 1) return NULL; p = *(data->tabtax+(++num_noeud)); p->v1=p1; p1->v3=p; p->l1=p1->l3; if(int_br_g!=NULL) { int_br_g->bouta=p; int_br_g->boutb=p1; } p->v2=p2; p2->v3=p; p->l2=p2->l3; if(int_br_d!=NULL) { int_br_d->bouta=p; int_br_d->boutb=p2; } } else { double brlength; virg=deb; while(*virg != ':' && virg < fin) { if(*virg=='(')virg=nextpar(virg); virg++; } if(virg>fin) virg=deb; if(*virg == ':') { sscanf(virg+1,"%le",&brlength); virg--; data->has_br_length=1; } else { brlength=1; data->has_br_length=0; } if(*deb == '(') { char *fpar; branche_noeud *prov; fpar=nextpar(deb)-1; p=unrootedset(arbre,deb+1,fpar,&prov, data); if(p == NULL) return NULL; /* recherche internal label */ l=virg-fpar-1; if(l>0) { data->totbranches++; *p_int_br= &data->branche_noeuds[data->totbranches]; } } else { size_t n; if( virg-1>=deb && *virg=='\'' )virg--; n=virg-deb+1; ++nextotu; p= *(data->tabtax+nextotu); p->nom = (char *)check_alloc(n+1,1); memcpy(p->nom, deb, n); p->nom[n] = 0; p->v1=p->v2=p->v3=NULL; } p->l3=brlength; } return p; } bignoeud *cre_new_tree(struct noeud *debut, struct noeud *parent, bignoeud *bigparent) { bignoeud *nouveau; if(debut == NULL) return NULL; nouveau = (bignoeud *)check_alloc(1, sizeof(bignoeud) ); if(debut->v1 == parent) { nouveau->v1 = bigparent; nouveau->v2 = cre_new_tree(debut->v2, debut, nouveau); nouveau->v3 = cre_new_tree(debut->v3, debut, nouveau); } else if(debut->v2 == parent) { nouveau->v2 = bigparent; nouveau->v1 = cre_new_tree(debut->v1, debut, nouveau); nouveau->v3 = cre_new_tree(debut->v3, debut, nouveau); } else { nouveau->v3 = bigparent; nouveau->v1 = cre_new_tree(debut->v1, debut, nouveau); nouveau->v2 = cre_new_tree(debut->v2, debut, nouveau); } nouveau->l1 = debut->l1; nouveau->l2 = debut->l2; nouveau->l3 = debut->l3; nouveau->nom = debut->nom; return nouveau; } void remove_big_root(bignoeud *bigracine) { bignoeud *p1, *p2; double root_br_l; p1=bigracine->v1; p2=bigracine->v2; root_br_l = bigracine->l1 + bigracine->l2; if(p1->v1 == bigracine ) {p1->v1 = p2; p1->l1 = root_br_l;} else if (p1->v2 == bigracine) {p1->v2 = p2; p1->l2 = root_br_l;} else {p1->v3 = p2; p1->l3 = root_br_l;} if(p2->v1 == bigracine ) {p2->v1 = p1; p2->l1 = root_br_l;} else if (p2->v2 == bigracine) {p2->v2 = p1; p2->l2 = root_br_l;} else {p2->v3 = p1; p2->l3 = root_br_l;} } double calc_dist_centre_feuilles(bignoeud *debut, bignoeud *parent) { double valeur, current; if(debut == NULL) return 0; valeur = 0; /* !!!!! conserver cette ecriture sinon plante sur PC !!!!!! */ if(debut->v1 != parent) { current = calc_dist_centre_feuilles(debut->v1, debut); current += debut->l1; if(current > valeur) valeur = current; } if(debut->v2 != parent) { current = calc_dist_centre_feuilles(debut->v2, debut); current += debut->l2; if(current > valeur) valeur = current; } if(debut->v3 != parent) { current = calc_dist_centre_feuilles(debut->v3, debut); current += debut->l3; if(current > valeur) valeur = current; } return valeur; } double proc_null_neg_branches(bignoeud *debut, bignoeud *parent) /* mettre branches negatives a 0 !attention dans un seul sens! retourner la + petite branche non nulle */ { double valeur, current; if(debut == NULL) return 0; valeur = 1e50; if(debut->v1 != parent) { if(debut->l1 < 0) debut->l1 = 0; current = debut->l1; if(current < valeur && current > 0) valeur = current; current = proc_null_neg_branches(debut->v1, debut); if(current < valeur && current > 0) valeur = current; } if(debut->v2 != parent) { if(debut->l2 < 0) debut->l2 = 0; current = debut->l2; if(current < valeur && current > 0) valeur = current; current = proc_null_neg_branches(debut->v2, debut); if(current < valeur && current > 0) valeur = current; } if(debut->v3 != parent) { if(debut->l3 < 0) debut->l3 = 0; current = debut->l3; if(current < valeur && current > 0) valeur = current; current = proc_null_neg_branches(debut->v3, debut); if(current < valeur && current > 0) valeur = current; } return valeur; } int set_angles_noeuds(bignoeud *debut, bignoeud *parent, double delta, double *p_current_angle, double rayon) { int feuille = FALSE; int poids, poids1, poids2; double angle1 = -1, angle2 = -1; static int totfeuilles=0; if(debut == NULL) return 0; if(debut->v1 != parent) { poids = set_angles_noeuds(debut->v1, debut, delta, p_current_angle, rayon); if(debut->v1 == NULL) feuille = TRUE; else if (parent != NULL) { angle1 = debut->v1->position.angle; poids1 = poids; } } if(debut->v2 != parent) { poids = set_angles_noeuds(debut->v2, debut, delta, p_current_angle, rayon); if(debut->v2 == NULL) feuille = TRUE; else if (parent != NULL) { if ( angle1 == -1 ) { angle1 = debut->v2->position.angle; poids1 = poids; } else { angle2 = debut->v2->position.angle; poids2 = poids; } } } if(debut->v3 != parent) { poids = set_angles_noeuds(debut->v3, debut, delta, p_current_angle, rayon); if(debut->v3 == NULL) feuille = TRUE; else if (parent != NULL) { angle2 = debut->v3->position.angle; poids2 = poids; } } if( feuille ) { totfeuilles++; debut->position.angle = *p_current_angle; *p_current_angle += delta; poids = 1; } else if(parent != NULL) { /* faire angle moyen modulo 2.pi */ debut->position.angle = (poids1*angle1 + poids2*angle2)/(poids1+poids2); poids = poids1 + poids2; if( angle1 > angle2 ) debut->position.angle -= M_PI; } debut->position.r = rayon; calc_cartesienne(&(debut->position)); return poids; } void calc_cartesienne( cp_point *p) { p->x = p->r * cos(p->angle); p->y = p->r * sin(p->angle); return; } void calc_polaire( cp_point *p) { p->r = sqrt(p->x * p->x + p->y * p->y); if( p->x == 0 ) { if( p->y == 0) p->angle = 0; else if (p->y > 0) p->angle = M_PI_2; else p->angle = 3*M_PI_2; } else if (p->x > 0) { p->angle = atan( p->y / p->x ); if( p->angle < 0 ) p->angle += 2*M_PI; } else { p->angle = M_PI - atan( p->y / p->x ); } return; } cp_point calc_point_direction( cp_point *depart, cp_point *direction, double longueur, double mini_br_length) { static cp_point retour; double lac, eps, tmp1, tmp2; tmp1 = direction->x - depart->x; tmp2 = direction->y - depart->y; lac = sqrt( tmp1*tmp1 + tmp2*tmp2 ); /* on remplace les branches nulles par des branches tres courtes pour que le calcul de l'angle en double soit bon mais que le dessin en entier soit le meme */ if(longueur == 0) longueur = mini_br_length; eps = longueur / lac; retour.x = depart->x + eps * tmp1; retour.y = depart->y + eps * tmp2; calc_polaire(&retour); return retour; } unrooted_branch *calc_position_noeuds(bignoeud *debut, bignoeud *parent, unrooted_branch *curr_branche, double mini_br_length) { if(debut->v1 != parent && debut->v1 != NULL ) { debut->v1->position = calc_point_direction( &(debut->position), &(debut->v1->position), debut->l1, mini_br_length); curr_branche = calc_position_noeuds(debut->v1, debut, curr_branche, mini_br_length); mem_line(&debut->position, &debut->v1->position, debut->v1, curr_branche); curr_branche++; } if(debut->v2 != parent && debut->v2 != NULL ) { debut->v2->position = calc_point_direction( &(debut->position), &(debut->v2->position), debut->l2, mini_br_length); curr_branche = calc_position_noeuds(debut->v2, debut, curr_branche, mini_br_length); mem_line(&debut->position, &debut->v2->position, debut->v2, curr_branche); curr_branche++; } if(debut->v3 != parent && debut->v3 != NULL ) { debut->v3->position = calc_point_direction( &(debut->position), &(debut->v3->position), debut->l3, mini_br_length); curr_branche = calc_position_noeuds(debut->v3, debut, curr_branche, mini_br_length); mem_line(&debut->position, &debut->v3->position, debut->v3, curr_branche); curr_branche++; } return curr_branche; } void mem_line(cp_point *debut, cp_point *fin, bignoeud *noeud_term, unrooted_branch *br) { br->debut = *debut; br->fin = *fin; br->nom = noeud_term->nom; } void free_bignoeud(bignoeud *debut, bignoeud *parent) { if(debut == NULL) return; if(debut->v1 != parent) { free_bignoeud(debut->v1, debut); } if(debut->v2 != parent) { free_bignoeud(debut->v2, debut); } if(debut->v3 != parent) { free_bignoeud(debut->v3, debut); } // no need to free debut->nom because done by free(data->tabtax[i]->nom) free(debut); } int chg_phys(FD_unrooted *ob, hits_field *hits ) { int encore = FALSE; const float delta = 0.05; int value; static int lr = 0, tb = 0, oldvaluex = 0, oldvaluey = 0; if(hits->left == 1 && hits->right == 0) { if(oldvaluex == 0) value = (int)((ob->phys_max_x - ob->phys_min_x) * delta); else value = oldvaluex; if(value < 2) value = 2; if(lr == 2) { /* alternance left/right */ if(oldvaluex <= 2) { hits->right = 1; return chg_phys(ob, hits); } value = oldvaluex/2; } lr = 1; oldvaluex = value; ob->phys_min_x += value; ob->phys_max_x += value; if(ob->phys_max_x <= ob->phys_min_x) { ob->phys_max_x = ob->phys_min_x + 1; return FALSE; } encore = TRUE; } else if(hits->left == 0 && hits->right == 1) { if(oldvaluex == 0) value = (int)((ob->phys_max_x - ob->phys_min_x) * delta); else value = oldvaluex; if(value < 2) value = 2; if(lr == 1) { /* alternance left/right */ if(oldvaluex <= 2) { hits->left = 1; return chg_phys(ob, hits); } value = oldvaluex/2; } lr = 2; oldvaluex = value; ob->phys_max_x -= value; ob->phys_min_x -= value; if(ob->phys_max_x <= ob->phys_min_x) { ob->phys_max_x = ob->phys_min_x + 1; return FALSE; } encore = TRUE; } else if(hits->left == 1 && hits->right == 1) { lr = tb = 0; oldvaluex = 0; value = (int)((ob->phys_max_x - ob->phys_min_x) * delta / 2); if(value < 2) value = 2; ob->phys_min_x += value; ob->phys_max_x -= value; if(ob->phys_max_x <= ob->phys_min_x) { ob->phys_max_x = ob->phys_min_x + 1; return FALSE; } encore = TRUE; ob->phys_max_y = ob->phys_min_y + (ob->phys_max_x - ob->phys_min_x); } if(hits->top == 0 && hits->bottom == 1) { if(oldvaluey == 0) value = (int)((ob->phys_max_y - ob->phys_min_y) * delta); else value = oldvaluey; if(value < 2) value = 2; if(tb == 2) { if(oldvaluey <= 2) { hits->top = 1; return chg_phys(ob, hits); } value = oldvaluey/2; } tb = 1; oldvaluey = value; ob->phys_max_y -= value; ob->phys_min_y -= value; if(ob->phys_max_y <= ob->phys_min_y) { ob->phys_max_y = ob->phys_min_y + 1; return FALSE; } encore = TRUE; } else if(hits->top == 1 && hits->bottom == 0) { if(oldvaluey == 0) value = (int)((ob->phys_max_y - ob->phys_min_y) * delta); else value = oldvaluey; if(value < 2) value = 2; if(tb == 1) { if(oldvaluey <= 2) { hits->bottom = 1; return chg_phys(ob, hits); } value = oldvaluey/2; } tb = 2; oldvaluey = value; ob->phys_min_y += value; ob->phys_max_y += value; if(ob->phys_max_y <= ob->phys_min_y) { ob->phys_max_y = ob->phys_min_y + 1; return FALSE; } encore = TRUE; } else if(hits->top == 1 && hits->bottom == 1) { value = (int)((ob->phys_max_y - ob->phys_min_y) * delta/2); if(value < 2) value = 2; lr = tb = 0; oldvaluey = 0; ob->phys_min_y += value; ob->phys_max_y -= value; if(ob->phys_max_y <= ob->phys_min_y) { ob->phys_max_y = ob->phys_min_y + 1; return FALSE; } encore = TRUE; ob->phys_max_x = ob->phys_min_x + (ob->phys_max_y - ob->phys_min_y); } return encore; } void log_to_phys(FD_unrooted *data, cp_point *log_pos, cp_point *phys_pos) { double factorx, factory; factorx = (data->phys_max_x - data->phys_min_x) / (data->log_max_x - data->log_min_x); factory = (data->phys_max_y - data->phys_min_y) / (data->log_max_y - data->log_min_y); phys_pos->x = factorx * ( log_pos->x - data->log_min_x ) + data->phys_min_x; phys_pos->y = factory * ( log_pos->y - data->log_min_y ) + data->phys_min_y; } double length_log_phys(FD_unrooted *data, double p) { double factor; factor = (data->phys_max_x - data->phys_min_x) / (data->log_max_x - data->log_min_x); return p * factor; } double length_phys_log(FD_unrooted *data, double p) { double factor; factor = (data->phys_max_x - data->phys_min_x) / (data->log_max_x - data->log_min_x); return p / factor; } double calc_echelle(FD_unrooted *data, int larg) { /* rend taille logique pour echelle optimale */ double log_val, phys_val; phys_val = larg/10; log_val = length_phys_log(data, phys_val); log_val = arrondi_echelle(log_val); return log_val; } �������������������������������������������������������������������seaview/unrooted.h����������������������������������������������������������������������������������000644 �000765 �000024 �00000003307 12404325714 015041� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_PI_2 #define M_PI_2 (M_PI/2) #endif #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) #endif typedef enum { NO_HIT, LEFT_HIT, RIGHT_HIT, TOP_HIT, BOTTOM_HIT } hit; typedef struct { int x, y; } point; typedef struct _cp_point { double x, y, r, angle; } cp_point; typedef struct _unrooted_branch { cp_point debut, fin; int color; char *nom; } unrooted_branch; typedef struct { /* une branche definie par ses deux extremites */ struct noeud *bouta; struct noeud *boutb; } branche_noeud; typedef struct _bignoeud { struct _bignoeud *v1, *v2, *v3; double l1, l2, l3; cp_point position; char *nom; } bignoeud; typedef struct { unsigned int left : 1; unsigned int right : 1; unsigned int top : 1; unsigned int bottom : 1; } hits_field; class unrooted_panel : public Fl_Widget { public: void draw(void); int handle(int); unrooted_panel(int x,int y,int w,int h) : Fl_Widget(x,y,w,h,NULL) { ; } }; typedef struct _FD_unrooted { unrooted_panel *unrooted_plot; Fl_Scrollbar *vert_scroller, *hor_scroller; int notu; int rooted; int x, y, w, h; //dimensions of plot int x_offset, y_offset; //offset when zoomed plot is scrolled around int previous_w, previous_h; int current_font; int font_size; int comp_phys_bounds; struct noeud **tabtax; struct noeud *racine; double root_br_l; int has_br_length; unrooted_branch *branches; branche_noeud *branche_noeuds; int totbranches; double log_min_x, log_min_y, log_max_x, log_max_y, mini_br_length; int phys_min_x, phys_min_y, phys_max_x, phys_max_y; float zoomvalue; } FD_unrooted; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/use_mase_files.cxx��������������������������������������������������������������������������000644 �000765 �000024 �00000227760 12600164347 016554� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "seaview.h" #include "pdf_or_ps.h" #include "svg.h" #include #include #ifndef WIN32 #include #endif /* included functions */ int read_mase_seqs_header(const char *masefname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); int one_more_seq_found(int count1, char ***pseq, char ***pseqname, char ***pcomments); int read_fasta_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message, int spaces_in_names); int read_phylip_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); int read_clustal_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); int read_msf_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message); int is_a_protein_seq(char *seq); int save_fasta_file(const char *fname, char **seq, char **comments, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int spaces_in_names, int pad_to_max_length); int save_phylip_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int phylipwidnames); int output_next_res_from_region(char *seq, int lenseq, list_segments **segment, int *current, FILE *out, int total, int use_dots); void save_regions(list_regions *regions, FILE *out); int save_mase_file(const char *fname, char **seq, char **comments, char *header, char **seqname, int totseqs, int *eachlength, list_regions *regions, region *region_used, int numb_species_sets, int **list_species_sets, char **name_species_sets, int *sel_seqs, int tot_sel_seqs, int tot_comment_lines, char **comment_name, char **comment_line, int tot_trees, char **trees, const Fl_Menu_Item *menu_tree_items); int save_clustal_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs); int calc_gcg_check(list_segments *psegment, char *seq); int save_msf_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int protein, int *sel_seqs, int tot_sel_seqs); char *save_alignment_or_region(const char *fname, char **seq, char **comments, char *header, char **seqname, int totseqs, int *eachlength, list_regions *regions, region *region_used, known_format format, int numb_species_sets, int **list_species_sets, char **name_species_sets, int *sel_seqs, int tot_sel_seqs, int protein, int tot_comment_lines, char **comment_name, char **comment_line, int phylipwidnames, int tot_trees, char **trees, const Fl_Menu_Item *menu_tree_items, int spaces_in_fasta_names); char *get_full_path(const char *fname); static void save_species_sets(int numb_species_sets, int **list_species_sets, char **name_species_sets, int totseqs, FILE *out); void save_comment_lines(int tot_comment_lines, char **names, char **lines, FILE *out); known_format what_format(const char *filename); char* seaview_file_chooser_save_as(const char* message, const char* fname, SEA_VIEW *view, known_format* new_format); const char *extract_dirname(const char *pathname); int printout(SEA_VIEW *view, const char *filename, int fontsize, int block_size, Fl_Paged_Device::Page_Format pageformat, int vary_only, int ref0, int pdfkindvalue, Fl_Paged_Device::Page_Layout layout, int svg_width = 0); static void color_pdf_display(SEA_VIEW *view, int (*calc_color_function)( int ), char *oneline, int widnames, double x, double y, int fontsize, double char_width, double descender,int num, int current); static void color_svg_display(SEA_VIEW *view, int (*calc_color_function)( int ), char *oneline, int widnames, double x, double y, int fontsize, double char_width); static int calc_vary_lines(int *vary_pos, int widpos); static void out_vary_pos(int *vary_pos, int widnames, int widpos, int nl, FILE *textfile, double x, double y); SEA_VIEW* read_alignment_file(const char *infile); SEA_VIEW *cmdline_read_input_alignment(int argc, char **argv); void format_conversion(int argc, char **argv); char *process_output_options(int argc, char **argv, known_format& out_format, bool& std_output); #ifndef NO_PDF void printout_cmdline(int argc, char **argv); #endif /* external */ extern char *f_format_names[]; extern char *f_format_exts[]; extern int nbr_formats; extern float argval(int argc, char *argv[], const char *arg, float defval); extern int calc_max_seq_length(int seq_length, int tot_seqs); extern int max_protcolors; extern char def_stdcolorgroups[]; extern int def_protcolors_rgb[]; char *get_res_value(const char *name, const char *def_value); extern int prep_custom_colors(int *colors, char *customcolors, int max_colors); extern color_choice prep_aa_color_code(char *list_std, char *list_alt, int maxprotcolors, int *numb_stdprotcolors, int *numb_altprotcolors); extern void load_resources(const char *progname); extern void allonge_seqs(char **seq, int totseqs, int maxlen, int *eachlength, int tot_comment_lines, char **comment_line, char **pregion_line); extern int int_res_value(const char *name, int def_value); extern const char *progname; #if defined(__APPLE__) extern const char *MG_GetBundleResourcesDir(void); #else extern char *get_prog_dir(void); #endif extern int save_nexus_file(const char *fname, int ntaxa, int protein, char **seqs, char **taxnames, char **notes, char *header, int num_species_sets, int **list_species_sets, char **name_species_sets, list_regions *charsets, int tot_comment_lines, char **comment_name, char **comment_line, region *region_used, int *sel_seqs, int tot_sel_seqs, int *eachlength, int tot_trees, char **trees, const Fl_Menu_Item *items); extern char *my_fgets(char *s, int n, FILE *f); extern char *argname(int argc, char *argv[], const char *arg); extern int isarg(int argc, char *argv[], const char *arg); extern char *create_tmp_filename(void); extern void delete_tmp_filename(const char *base_fname); extern char *translate_with_gaps(char *seq, int gc); extern int get_ncbi_gc_from_comment(char *comment); extern int create_gblocks_mask(SEA_VIEW *view, region *myregion, int no_gui, int b5_val, int b4_val, int b3_val, int b2_val); extern char *back_translate_with_gaps(char *prot, char *dna); extern void del_gap_only_sites(SEA_VIEW *view); extern void save_bootstrap_replicates(const char *fname, int replicates, SEA_VIEW *view); extern "C" { int get_acnuc_gc_number(int ncbi_gc); int get_ncbi_gc_number(int ncbi_gc); } int read_mase_seqs_header(const char *masefname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message) { #define MAXLENSEQ 10000 /* unite d'allocation de memoire */ #define lline 2000 FILE *masef; char line[lline], *i, *base, *header = NULL, *provseq = NULL, *p; int l, lenseqs, lpre, lseq, l2, totseqs = -1, want_header, curr_max_header; static char ret_message[200]; char **seq, **seqname, **comments; *ret_message = 0; *err_message = ret_message; if( (masef=fopen(masefname,"r")) == NULL) { sprintf(ret_message,"File not found:%s",masefname); return 0; } want_header = (pheader != NULL); if(fgets(line, lline, masef)==NULL)goto fini; if(strchr(line, '\n') == NULL) { strcpy(ret_message,"Not a mase file!"); goto fini; } if(strncmp(line,";;",2)==0) { if(want_header) { if( (header=(char *)malloc(MAXLENCOM+1)) == NULL)goto nomem; curr_max_header = MAXLENCOM; strcpy(header,line); lpre=strlen(line); } do { if( fgets(line,lline,masef)==NULL ) goto fini; if(strncmp(line,";;",2)!=0) break; if(header != NULL) { lseq=strlen(line); if(lpre+lseq > curr_max_header) { curr_max_header += MAXLENCOM; if( (p=(char *)malloc(curr_max_header+1)) == NULL ) goto nomem; memcpy(p, header, lpre); free(header); header = p; } memcpy(header+lpre,line, lseq); lpre += lseq; } } while (1); if( want_header ) { header[lpre] = 0; header=(char *)realloc(header,lpre+1); } } if(*line != ';' ) { strcpy(ret_message,"Not a mase file!"); goto fini; } lenseqs=MAXLENSEQ; if( (provseq=(char *)malloc(lenseqs+1)) ==NULL)goto nomem; i=line; while(i!=NULL){ totseqs = one_more_seq_found(totseqs, &seq, &seqname, &comments); if(totseqs == -1) goto nomem; if(comments!=NULL) { if( (comments[totseqs]=(char *)malloc(MAXLENCOM+1)) == NULL)goto nomem; strcpy(comments[totseqs],line); lpre=strlen(line); l=MAXLENCOM; while(*fgets(line,lline,masef)==';') { lseq=strlen(line); if(lpre+lseq <= l) { strcpy(comments[totseqs]+lpre,line); lpre += lseq; } else l=lpre-1; } if(lpre0 ) l--; line[l] = 0; if( (seqname[totseqs]=(char *)malloc(l+1)) == NULL)goto nomem; strcpy(seqname[totseqs],line); lseq = 0; /* what is already put in provseq */ while( (i=fgets(line,lline,masef))!= NULL && *i != ';' ) { l2 = strlen(line); if( line[l2 - 1] == '\n' ) l2--; while(l2>0 && line[l2-1]==' ')l2--; if(lseq + l2 > lenseqs) { char *temp; lenseqs += MAXLENSEQ; temp = (char *)malloc(lenseqs+1); if(temp == NULL) goto nomem; memcpy(temp, provseq, lseq); free(provseq); provseq = temp; } memcpy(provseq+lseq, line, l2); lseq += l2; } provseq[lseq]='\0'; seq[totseqs] = (char *)malloc(lseq+1); if(seq[totseqs] == NULL) goto nomem; /* ignore space or non printable characters */ base=provseq - 1; p = seq[totseqs] - 1; while ( *(++base) != 0) { if(isprint(*base) && ! isspace(*base) ) { // *(++p) = toupper(*base); *(++p) = *base; } } *(++p) = 0; } seq = (char **)realloc(seq, (totseqs + 1)*sizeof(char *)); seqname = (char **)realloc(seqname, (totseqs + 1)*sizeof(char *)); comments = (char **)realloc(comments, (totseqs + 1)*sizeof(char *)); *pseq = seq; *pseqname = seqname; *pcomments = comments; fini: fclose(masef); if(want_header) *pheader = header; if(provseq != NULL) free(provseq); return totseqs+1; nomem: sprintf(ret_message,"Error: Not enough memory!"); totseqs = -1; goto fini; } void parse_trees_from_header(char *header, SEA_VIEW *view) { char *new_header, *old_header, *fin_new_header, *p, *q; int l_header, l; if(header == NULL) return; old_header = header; l_header=strlen(header); if( (new_header = (char *)malloc(l_header+1)) == NULL) out_of_memory(); fin_new_header = new_header; *new_header = 0; while (*header!= 0) { if(strncmp(header,";;$",3) == 0) { p = header + 3; while(*p == ' ') p++; q = strchr(p, '\n'); *q = 0; view->menu_trees->add(p, trees_callback, NULL, 0); int rank = view->menu_trees->vlength(); (view->menu_trees->vitem(rank - 1))->labelfont(FL_HELVETICA_ITALIC); *q = '\n'; p = q + 1; l = 1; while(TRUE) { q = strchr(p, '\n'); if(strncmp(q+1, ";;", 2) != 0) break; if (*(q+3) == '$' && *(q+4) != '\n') break; if (strncmp(q+1, ";;@ of species =", 16) == 0) break; if (strncmp(q+1, ";;# of segments=", 16) == 0) break; p = q + 1; l++; } if(view->tot_trees == 0) view->trees = (char **)malloc(sizeof(char *)); else view->trees = (char **)realloc(view->trees, (view->tot_trees + 1) * sizeof(char *)); view->trees[view->tot_trees] = (char *)malloc(q - header + 1); p = view->trees[view->tot_trees]; for(int i = 0; i < l; i++) { header = strchr(header, '\n') + 1; q = (char *)memccpy(p, header + 2, '\n', l_header); p += (q - p - 1); } *p = 0; view->tot_trees++; } else { p=(char *)memccpy(fin_new_header, header, '\n', l_header); fin_new_header += (p - fin_new_header); } header = strchr(header,'\n') + 1; } *fin_new_header = 0; strcpy(old_header, new_header); free(new_header); } int one_more_seq_found(int count1, char ***pseq, char ***pseqname, char ***pcomments) { static int max_count; char **seq, **seqname, **comments; if(count1 == -1) max_count = 0; if(count1 + 1 < max_count) return count1 + 1; count1++; if(max_count == 0) { max_count = 100; seq = (char **)malloc(max_count * sizeof(char *)); if(seq == NULL) return -1; seqname = (char **)malloc(max_count * sizeof(char *)); if(seqname == NULL) return -1; comments = (char **)malloc(max_count * sizeof(char *)); if(comments == NULL) return -1; } else { seq = *pseq; seqname = *pseqname; comments = *pcomments; max_count = 3 * max_count; seq = (char **)realloc(seq, max_count * sizeof(char *)); if(seq == NULL) return -1; seqname = (char **)realloc(seqname, max_count * sizeof(char *)); if(seqname == NULL) return -1; comments = (char **)realloc(comments, max_count * sizeof(char *)); if(comments == NULL) return -1; } *pseq = seq; *pseqname = seqname; *pcomments = comments; return count1; } int read_fasta_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message, int spaces_in_names) { FILE *in; int totseqs, lseq, l2, l, lenseqs; char line[300], *p, *i, c, *q, *r; static char ret_message[200]; char **seq, **seqname, **comments, *tmpseq = NULL; *ret_message = 0; *err_message = ret_message; if( (in=fopen(fname,"r")) == NULL) { sprintf(ret_message,"File not found:%s", fname); return 0; } /* calcul du nombre de sequences dans le fichier */ totseqs = 0; while(fgets(line, sizeof(line), in) != NULL) { if(*line == '>') totseqs++; } rewind(in); seq = (char **)malloc(totseqs * sizeof(char *)); if(seq == NULL) goto nomem; comments = (char **)malloc(totseqs * sizeof(char *)); if(comments == NULL) goto nomem; seqname = (char **)malloc(totseqs * sizeof(char *)); if(seqname == NULL) goto nomem; *pseq = seq; *pcomments = comments; *pseqname = seqname; lenseqs = MAXLENSEQ; tmpseq = (char *)malloc(lenseqs + 1); if(tmpseq == NULL) goto nomem; totseqs = -1; i = fgets(line, sizeof(line), in); if(line[0] != '>') { strcpy(ret_message,"File not in Fasta format!"); totseqs = -1; goto fini; } while( i != NULL ){ /* finish reading very long title line */ c = line[strlen(line) - 1]; while(c != '\n' && c != '\r' && c != EOF) c = getc(in); q = line + strlen(line) - 1; while(q > line + 1 && (*q == '\n' || *q == '\r')) *(q--) = 0; totseqs++; p = line + 1; while (*p == ' ') p++; if(spaces_in_names) { while(*p != '\n') p++; while(*(p-1) == ' ') p--; } else { while(*p != ' ' && *p != '\n') p++; } r = line + 1; while (*r == ' ') r++; l = p - r; if( (seqname[totseqs] = (char *)malloc(l+1)) == NULL)goto nomem; memcpy(seqname[totseqs], r, l); seqname[totseqs][l] = 0; /* use rest of title line, if any, as comment */ while(*p == ' ') p++; l = q - p + 1; if( l > 0) { comments[totseqs] = (char *)malloc(l + 3); if(comments[totseqs] != NULL) { strcpy(comments[totseqs], ";"); strcpy(comments[totseqs] + 1, p); strcpy(comments[totseqs] + l + 1, "\n"); } } else comments[totseqs] = NULL; lseq = 0; while( (i=fgets(line, sizeof(line), in))!= NULL && *i != '>' ) { l2 = strlen(line); if( line[l2 - 1] == '\n' ) l2--; while(l2>0 && line[l2-1]==' ')l2--; if(lseq + l2 > lenseqs) { lenseqs += MAXLENSEQ; tmpseq= (char *)realloc(tmpseq, lenseqs + 1); if(tmpseq == NULL) goto nomem; } /* copy seq data excluding spaces (because of gblocks) */ p = tmpseq+lseq; q = line; while (q < line + l2) { if(*q != ' ') *(p++) = *q; q++; } lseq += p - (tmpseq+lseq); } tmpseq[lseq]='\0'; seq[totseqs] = (char *)malloc(lseq + 1); if(seq[totseqs] == NULL) goto nomem; memcpy(seq[totseqs], tmpseq, lseq + 1); } fini: fclose(in); if(tmpseq != NULL) free(tmpseq); *pheader = NULL; return totseqs+1; nomem: sprintf(ret_message,"Error: Not enough memory!"); totseqs = -1; goto fini; } int read_phylip_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message) { FILE *in; char *p, *q; int c; static char line[300]; char **seq=0, **comments=0, **seqname=0; int totseqs, lenseqs, i, l; static char ret_message[200]; *ret_message = 0; *err_message = ret_message; in=fopen(fname,"r"); if(in==NULL) { sprintf(ret_message,"File not found:%s",fname); return 0; } fgets(line,sizeof(line),in); if( sscanf(line, "%d%d", &totseqs, &lenseqs) != 2) { sprintf(ret_message,"Not a PHYLIP file"); totseqs = 0; goto fini; } seq = (char **)malloc(totseqs * sizeof(char *)); if(seq == NULL) goto nomem; seqname = (char **)malloc(totseqs * sizeof(char *)); if(seqname == NULL) goto nomem; comments = (char **)malloc(totseqs * sizeof(char *)); if(comments == NULL) goto nomem; for(i=0; i= lenseqs) goto badfile; *(q++) = *p; } p++; } c = *p; if(c == '\n') continue; while(TRUE) { c = fgetc(in); if(c == EOF) goto badfile; if(c == '\n' || c == '\r') break; if(c != ' ') { if(q - seq[i] >= lenseqs) goto badfile; *(q++) = (char)c; } } if(c == '\r') {c = fgetc(in); if(c != '\n') ungetc(c, in); } } l = q - seq[totseqs - 1]; while( l < lenseqs) { do c = fgetc(in); while(c != '\n' && c != '\r' && c != EOF); if(c == EOF) goto badfile; if(c == '\r') {c = fgetc(in); if(c != '\n') ungetc(c, in); } for(i=0; i= lenseqs) goto badfile; *(q++) = (char)c; } } if(c == '\r') {c = fgetc(in); if(c != '\n') ungetc(c, in); } } l = q - seq[totseqs - 1]; } for(i=0; i= 0 && curr_spec == -1 && strncmp(line, seqname[0], strlen(seqname[0]) ) != 0) { break; } else { if(first) { curr_spec = one_more_seq_found(curr_spec, &seq, &seqname, &comments); if(curr_spec == -1) goto nomem; } else curr_spec++; } if(first && curr_spec == 0) { /* calcul long partie nom: enlever tout ce qui n'est pas espace en fin */ p = line + strlen(line) - 2; while(*p == ' ' || isdigit(*p) ) p--; while (*p != ' ') p--; wid_name = p - line + 1; } if(first) { seqname[curr_spec] = (char *)malloc(wid_name+1); if(seqname[curr_spec]==NULL) { goto nomem; } memcpy(seqname[curr_spec], line, wid_name); p = seqname[curr_spec] + wid_name - 1; while(*p==' ') p--; *(p+1)=0; if(curr_spec > tot_spec) tot_spec = curr_spec; seq[curr_spec] = (char *)malloc(CLU_BLOCK_LEN+1); curr_max_len = CLU_BLOCK_LEN; if(seq[curr_spec]==NULL) { goto nomem; } comments[curr_spec] = NULL; } if(curr_spec == 0) { l = strlen(line) - 1; p = line + l - 1; while(*p == ' ' || isdigit(*p) ) { p--; l--; } l -= wid_name; if(curr_len + l > curr_max_len) { curr_max_len += CLU_BLOCK_LEN; for(i=0; i<=tot_spec; i++) { p = (char *)malloc(curr_max_len+1); if(p == NULL) goto nomem; memcpy(p, seq[i], curr_len); free(seq[i]); seq[i] = p; } } next_len = curr_len + l; } memcpy(seq[curr_spec]+curr_len, line + wid_name, l); } for(i=0; i<=tot_spec; i++) seq[i][next_len] = 0; seq = (char **)realloc(seq, (tot_spec + 1)*sizeof(char *)); seqname = (char **)realloc(seqname, (tot_spec + 1)*sizeof(char *)); comments = (char **)realloc(comments, (tot_spec + 1)*sizeof(char *)); *pseq = seq; *pseqname = seqname; *pcomments = comments; fini: *pheader = NULL; fclose(in); return tot_spec + 1; nomem: sprintf(ret_message,"Error: Not enough memory!"); tot_spec = -1; goto fini; } int read_msf_align(const char *fname, char ***pseq, char ***pseqname, char ***pcomments, char **pheader, char **err_message) { FILE *in; char line[100], *p, *q; int l, curr_spec, maxwidname=0, curr_len, tot_spec, wid_1_line, wid_block; static char ret_message[200]; char **seq, **seqname, **comments; *ret_message = 0; *err_message = ret_message; in=fopen(fname,"r"); if(in==NULL) { sprintf(ret_message,"File not found:%s",fname); return 0; } /* compter le nbre de seqs dans le fichier */ tot_spec = 0; while(fgets(line, sizeof(line), in) != NULL) { if(strncmp(line, "//", 2) == 0) break; if(strstr(line, "Name: ") != NULL) tot_spec++; } rewind(in); seq = (char **)malloc(tot_spec * sizeof(char *)); if(seq == NULL) goto nomem; comments = (char **)malloc(tot_spec * sizeof(char *)); if(comments == NULL) goto nomem; seqname = (char **)malloc(tot_spec * sizeof(char *)); if(seqname == NULL) goto nomem; *pseq = seq; *pcomments = comments; *pseqname = seqname; p = NULL; while( fgets(line,sizeof(line),in) != NULL) { if( (p = strstr(line, "MSF: ")) != NULL) break; } if(p == NULL || tot_spec == 0) { strcpy(ret_message,"File not in MSF format!"); tot_spec = -1; goto fini; } tot_spec = -1; do { fgets(line,sizeof(line),in); if( (p = strstr(line, "Name:") ) == NULL) continue; tot_spec++; q = strstr(p, " Len: "); sscanf(q + 5, "%d", &l); seq[tot_spec] = (char *)malloc(l + 1); if(seq[tot_spec]==NULL) goto nomem; p += 5; while(*p == ' ') p++; while(*q == ' ') q--; l = q - p + 1; seqname[tot_spec] = (char *)malloc(l + 1); if(seqname[tot_spec]==NULL) goto nomem; memcpy(seqname[tot_spec], p, l); seqname[tot_spec][l] = 0; if(l > maxwidname) maxwidname = l; comments[tot_spec] = NULL; } while(strncmp(line, "//", 2) != 0); curr_spec = 0; curr_len = 0; wid_block = 0; while( fgets(line, sizeof(line), in) != NULL ) { p = line; while(*p == ' ') p++; l = strlen(seqname[curr_spec]); if(strncmp(p, seqname[curr_spec], l) != 0) continue; p += l; while(*p == ' ') p++; p--; q = seq[curr_spec] + curr_len; while( *(++p) != '\n') { if( *p == ' ') continue; if(*p == '.') *p = '-'; *(q++) = *p; } *q = 0; wid_1_line = q - (seq[curr_spec] + curr_len); wid_block = (wid_1_line > wid_block ? wid_1_line : wid_block); if(curr_spec == tot_spec) { curr_len += wid_block; curr_spec = 0; wid_block = 0; } else curr_spec++; } fini: *pheader = NULL; fclose(in); return tot_spec + 1; nomem: sprintf(ret_message,"Error: Not enough memory!"); tot_spec = -1; goto fini; } int is_a_protein_seq(char *seq) /* returns TRUE if seq looks like a protein sequence (less than 80% ACGTU) */ { static char dna[]="ACGTURY"; int total=0, length=0; while(*seq != 0) { if(*seq != '-' && *seq != '?' && toupper(*seq) != 'N') { if( strchr(dna, toupper(*seq)) != NULL ) total++; length++; } seq++; } return ( (float)(total) / length ) <= 0.8 ; } int save_phylip_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int phylipwidnames) /* sauver des sequences ou des regions au format phylip region_used pointe vers la region a sauver si region_used == NULL, toutes les sequences sont sauvees rend 0 si ok, 1 si erreur d'ecriture dans le fichier 2 si tentative de depasser la longueur d'une sequence */ { const int widphylin = 60; FILE *out; int lenseqs, i, j, retval = 1, current, save_current, err, vtotseqs, lu, maxlname; list_segments *psegment, all_sequence, *curr_segment; region maregion; char c; if(totseqs == 0) return 0; if( (out = fopen(fname,"w")) == NULL) return 1; if(region_used == NULL) { /* on veut tout sauver */ tot_sel_seqs = 0; all_sequence.debut = 1; all_sequence.fin = eachlength[0]; for(i = 1; i < totseqs; i++) /* calcul long max des seqs */ if( eachlength[i] > all_sequence.fin ) all_sequence.fin = eachlength[i]; all_sequence.next = NULL; maregion.list = &all_sequence; region_used = &maregion; } /* calcul longueur des regions */ lenseqs = 0; psegment = region_used->list; while(psegment != NULL) { lenseqs += psegment->fin - psegment->debut + 1; psegment = psegment->next; } /* longest seq name */ vtotseqs = 0; maxlname = 10; // 10 is the minimum name length for(i=0; i < totseqs; i++) { if(tot_sel_seqs == 0 || sel_seqs[i]) { ++vtotseqs; if( (j = strlen(seqname[i])) > maxlname) maxlname = j; } } if(maxlname > phylipwidnames) maxlname = phylipwidnames; fprintf(out,"%d %d\n", vtotseqs, lenseqs); for(i=0; i < totseqs; i++) { if(tot_sel_seqs != 0 && ! sel_seqs[i]) continue; psegment = region_used->list; current = 0; for(j = 0; j < maxlname; j++) { if( (c = seqname[i][j]) == 0) break; putc(c == ' ' ? '_' : c, out); } while(j <= maxlname) { putc( ' ', out ); j++; } lu = 0; while(lu < widphylin && psegment != NULL) { putc( ' ', out ); err = output_next_res_from_region(seq[i], eachlength[i], &psegment, ¤t, out, 10, FALSE); lu += err; } putc('\n', out); if(ferror(out)) goto fin; } while( psegment != NULL ) { putc('\n',out); curr_segment = psegment; save_current = current; for(i=0; i < totseqs; i++) { if(tot_sel_seqs != 0 && ! sel_seqs[i]) continue; psegment = curr_segment; current = save_current; for(j = 0; j <= maxlname; j++) putc( ' ', out ); lu = 0; while(lu < widphylin && psegment != NULL) { putc( ' ', out ); err = output_next_res_from_region(seq[i], eachlength[i], &psegment, ¤t, out, 10, FALSE); lu += err; } putc('\n', out); if(ferror(out)) goto fin; } } retval = 0; fin: fclose(out); return retval; } int output_next_res_from_region(char *seq, int lenseq, list_segments **segment, int *current, FILE *out, int total, int use_dots) /* ecrire dans le fichier out les total residus a partir de la position courante dans une liste de regions. lenseq est la longueur de la sequence seq. La position courante est determinee par le segment courant (*segment, qui peut etre modifie par la fonction) et par la position (from 0) dans celui-ci (*current qui est modifie par la fonction pour etre pret pour l'appel suivant). Si le segment demande va au dela de la fin de la seq, des - sont ecrits. Rend le nombre de residus effectivement ecrits, qui est tjrs celui demande. Doit etre appelle la premiere fois avec *current = 0 */ { int debut, fin, vfin, ecrit = 0, nombre; char *p; static char line[500]; if( *segment == NULL) return 0; do { debut = (*segment)->debut; fin = (*segment)->fin; vfin = fin; if(fin > lenseq) vfin = lenseq; nombre = total; if( nombre - 1 + *current + debut > vfin) nombre = vfin + 1 - *current - debut; if(nombre > 0) { memcpy(line, seq + *current + debut - 1, nombre); line[nombre] = 0; if(use_dots) { p = line; while( (p = strchr(p, '-')) != NULL) *p = '.'; } fwrite(line, 1, nombre, out); ecrit += nombre; total -= nombre; (*current) += nombre; } if( fin > lenseq && total > 0 ) { nombre = total; if( nombre - 1 + *current + debut > fin) nombre = fin + 1 - *current - debut; ecrit += nombre; (*current) += nombre; total -= nombre; while(nombre-- > 0) putc('-', out); } if( *current + debut > fin) { *segment = (*segment)->next; if(*segment == NULL) break; *current = 0; } } while(total > 0); return ecrit; } void save_regions(list_regions *regions, FILE *out) { int total; unsigned l_line; list_segments *segment; char line[80]; do { total = 0; segment = regions->element->list; while(segment != NULL) { total++; segment = segment->next; } if(total == 0) continue; fprintf(out,";;# of segments=%d %s\n",total,regions->element->name); strcpy(line, ";;"); l_line=2; segment = regions->element->list; while(segment != NULL) { if(l_line + 12 >= sizeof(line)-1) { fputs(line,out); putc('\n',out); strcpy(line,";;"); l_line=2; } sprintf(line+l_line," %d,%d", segment->debut, segment->fin); l_line += strlen(line+l_line); segment= segment->next; } fputs(line,out); putc('\n',out); } while( regions = regions->next, regions != NULL ); } int save_mase_file(const char *fname, char **seq, char **comments, char *header, char **seqname, int totseqs, int *eachlength, list_regions *regions, region *region_used, int numb_species_sets, int **list_species_sets, char **name_species_sets, int *sel_seqs, int tot_sel_seqs, int tot_comment_lines, char **comment_name, char **comment_line, int tot_trees, char **trees, const Fl_Menu_Item *menu_tree_items) /* sauver un alignement au format mase regions: l'ensemble des regions a ecrire (si on sauve tout l'alignement) NULL si on ne sauve que des regions region_used: pointeur vers la region a sauver et on ne sauve que les seqs selectionnees s'il y en a, ou NULL pour sauver tout l'alignement rend 0 si OK, 1 si erreur ecriture du fichier 2 si depassement de longueur d'une sequence (avec region seulement) */ { FILE *out; int num, retval = 1, current, ecrit, maxlength; time_t heure; list_segments *psegment, all_sequence; region maregion; if(totseqs == 0) return 0; out=fopen(fname,"w"); if(out == NULL) return 1; maxlength = 0; time(&heure); fprintf(out,";; saved by seaview on %s",ctime(&heure)); if(region_used == NULL) { /* on veut tout sauver */ all_sequence.debut = 1; all_sequence.next = NULL; maregion.list = &all_sequence; maregion.name = NULL; region_used = &maregion; tot_sel_seqs = 0; maxlength = eachlength[0]; for(num=1; numname); if(ferror(out)) goto fin; if(header != NULL && *header != 0) { fputs(header,out); if(ferror(out)) goto fin; } if(regions != NULL) { save_regions(regions, out); if(ferror(out)) goto fin; } if(tot_comment_lines > 0) { save_comment_lines(tot_comment_lines, comment_name, comment_line, out); if(ferror(out)) goto fin; } if(numb_species_sets != 0) { /* sauver les species sets */ save_species_sets(numb_species_sets, list_species_sets, name_species_sets, totseqs, out); if(ferror(out)) goto fin; } if(tot_trees > 0) { /* write trees out */ for(num = 0; num < tot_trees; num++) { fprintf(out, ";;$ %s\n", menu_tree_items[num].label()); char *tree = strdup(trees[num]); char *p; while ((p=strchr(tree, '\n')) != NULL) *p = ' '; int l = strlen(tree); for (p = tree; p < tree + l; p += 80) { while (*p == '$') { // avoid begin line with ";;$..." that marks a new tree fputs(";;$\n", out); p++; } fprintf(out, ";;%.80s\n", p); } free(tree); } } for(num=0; numlist; all_sequence.fin = eachlength[num]; if(comments != NULL && comments[num] != NULL) fputs(comments[num], out); else fputs(";no comment\n", out); if(ferror(out)) goto fin; fprintf(out,"%s\n",seqname[num]); if(ferror(out)) goto fin; do { ecrit = output_next_res_from_region(seq[num], eachlength[num], &psegment, ¤t, out, 60, FALSE); if(ferror(out)) goto fin; if( ecrit > 0) putc('\n', out); else if(ecrit == -1) {retval = 2; goto fin; } } while(ecrit != 0); if( (ecrit = maxlength - eachlength[num]) > 0) { int n; for(n = 1; n <= ecrit; n++) { putc('-', out); if(n % 60 == 0) putc('\n', out); } putc('\n', out); } if(ferror(out)) goto fin; } retval = 0; fin: if( fclose(out) != 0 ) retval = 1; return retval; } int save_fasta_file(const char *fname, char **seq, char **comments, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs, int spaces_in_names, int pad_to_max_length) /* sauver des sequences ou des regions au format fasta region_used pointe vers la liste des regions a sauver si region_used == NULL, toutes les sequences sont sauvees si pad_to_max_length == TRUE && region_used == NULL, les seqs sont allongŽes a leur longueur max rend 0 si ok, 1 si erreur d'ecriture dans le fichier 2 si tentative de depasser la longueur d'une sequence */ { FILE *out; int num, retval = 1, current, ecrit, save_full = (region_used == NULL); list_segments *psegment, all_sequence; region maregion; char *p; if(totseqs == 0) return 0; if( (out = fopen(fname,"w")) == NULL) return 1; if(region_used == NULL) { /* on veut tout sauver */ tot_sel_seqs = 0; all_sequence.debut = 1; all_sequence.fin = eachlength[0]; for(num = 1; num < totseqs; num++) if( eachlength[num] < all_sequence.fin ) all_sequence.fin = eachlength[num]; all_sequence.next = NULL; maregion.list = &all_sequence; region_used = &maregion; } for(num=0; numlist; if (!save_full || !pad_to_max_length) all_sequence.fin = eachlength[num]; fputc('>', out); p = seqname[num]; if(spaces_in_names) { fputs(p, out); } else { while(*p != 0) { fputc( *p == ' ' ? '_' : *p, out); p++; } if(comments != NULL && comments[num] != NULL) { putc(' ', out); p = comments[num] + 1; while(*p != '\n' && *p != 0) putc(*(p++), out); } } putc('\n', out); if(ferror(out)) goto fin; do { ecrit = output_next_res_from_region(seq[num], eachlength[num], &psegment, ¤t, out, 60, FALSE); if( ecrit > 0) putc('\n', out); else if(ecrit == -1) {retval = 2; goto fin; } } while(ecrit != 0); if(ferror(out)) goto fin; } retval = 0; fin: if( fclose(out) != 0 ) return 1; return retval; } int save_clustal_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int *sel_seqs, int tot_sel_seqs) /* sauver des sequences ou des regions au format clustal region_used pointe vers la liste des regions a sauver si region_used == NULL, toutes les sequences sont sauvees rend 0 si ok, 1 si erreur d'ecriture dans le fichier 2 si tentative de depasser la longueur d'une sequence */ { const int widcluslin = 60; FILE *out; int i, j, retval = 1, current, save_current, err, l, lmax; list_segments *psegment, all_sequence, *curr_segment; region maregion; if(totseqs == 0) return 0; if( (out = fopen(fname,"w")) == NULL) return 1; if(region_used == NULL) { /* on veut tout sauver */ tot_sel_seqs = 0; all_sequence.debut = 1; all_sequence.fin = eachlength[0]; for(i = 1; i < totseqs; i++) if( eachlength[i] > all_sequence.fin ) all_sequence.fin = eachlength[i]; all_sequence.next = NULL; maregion.list = &all_sequence; region_used = &maregion; } lmax = 0; for(i=0; i < totseqs; i++) { if( tot_sel_seqs != 0 && ! sel_seqs[i] ) continue; l = strlen(seqname[i]); if(l > lmax) lmax = l; } lmax += 2; fprintf(out,"CLUSTAL W (1.7) multiple sequence alignment\n\n\n"); current = 0; psegment = region_used->list; while( psegment != NULL ) { curr_segment = psegment; save_current = current; for(i=0; i < totseqs; i++) { if( tot_sel_seqs != 0 && ! sel_seqs[i] ) continue; psegment = curr_segment; current = save_current; /* remplacer espaces internes par _ */ for(j = 0; j < lmax; j++) { if(seqname[i][j] == 0) break; putc( (seqname[i][j] == ' ' ? '_' : seqname[i][j] ), out); } while( j < lmax) { putc(' ', out); j++; } err= output_next_res_from_region(seq[i], eachlength[i], &psegment, ¤t, out, widcluslin, FALSE); putc('\n', out); if(err == -1) {retval = 2; goto fin; } if(ferror(out)) goto fin; } fprintf(out, "\n\n"); } retval = 0; fin: if( fclose(out) != 0 ) return 1; return retval; } int calc_gcg_check(list_segments *psegment, char *seq) { int i, debut, fin, residue, pos = 0; long check = 0; while(psegment != NULL) { debut = psegment->debut; fin = psegment->fin; for( i=debut; i<= fin; i++) { residue = toupper(seq[i - 1]); if(residue == '-') residue = '.'; check += (( (pos++) % 57)+1) * residue; } psegment = psegment->next; } return (check % 10000); } int save_msf_file(const char *fname, char **seq, char **seqname, int totseqs, int *eachlength, region *region_used, int protein, int *sel_seqs, int tot_sel_seqs) /* sauver des sequences ou des regions au format MSF region_used pointe vers la liste des regions a sauver si region_used == NULL, toutes les sequences sont sauvees rend 0 si ok, 1 si erreur d'ecriture dans le fichier 2 si tentative de depasser la longueur d'une sequence */ { FILE *out; int i, j, k, retval = 1, current, save_current, err, lenseqs, gen_check, *check_val, curr_len, toprint, save_complete, fromseq, new_current; list_segments *psegment, all_sequence, *curr_segment, *new_segment; region maregion; if(totseqs == 0) return 0; if( (out = fopen(fname,"w")) == NULL) return 1; save_complete = (region_used == NULL); if(save_complete) { /* on veut tout sauver */ tot_sel_seqs = 0; all_sequence.debut = 1; all_sequence.fin = 0; for(i = 0; i < totseqs; i++) { if( eachlength[i] > all_sequence.fin ) all_sequence.fin = eachlength[i]; } lenseqs = all_sequence.fin; all_sequence.next = NULL; maregion.list = &all_sequence; region_used = &maregion; } else { /* calcul longueur des regions */ lenseqs = 0; psegment = region_used->list; while(psegment != NULL) { lenseqs += psegment->fin - psegment->debut + 1; psegment = psegment->next; } } for(i = 0, k = 0; i < totseqs; i++) /* nbre de seqs editees */ if( tot_sel_seqs == 0 || sel_seqs[i] ) k++; check_val = (int *)malloc( k * sizeof(int) ); if(check_val == NULL) { fclose(out); return 1; /* pas tres precis */ } gen_check = 0; for(i = 0, j = 0; i < totseqs; i++) { if( tot_sel_seqs != 0 && ! sel_seqs[i] ) continue; check_val[j] = calc_gcg_check(region_used->list, seq[i]); gen_check += check_val[j++]; } gen_check = gen_check % 10000; fprintf(out, "!!%2s_MULTIPLE_ALIGNMENT 1.0\n %s", (protein?"AA":"NA"), extract_filename(fname) ); fprintf(out," MSF: %d Type: %c Check:%6d .. \n\n", lenseqs, (protein ? 'P' : 'N'), gen_check); for(i = 0 , j = 0; i < totseqs; i++) { if( tot_sel_seqs != 0 && ! sel_seqs[i] ) continue; fprintf(out, " Name: %-15.15s Len:%5d Check:%6d Weight: 1.00\n", seqname[i], lenseqs, check_val[j++]); } fprintf(out,"\n//\n\n\n"); new_current = 0; new_segment = region_used->list; curr_len = 0; while( new_segment != NULL && curr_len < lenseqs) { curr_segment = new_segment; save_current = new_current; fprintf(out, "\n"); for(i=0; i < totseqs; i++) { if( tot_sel_seqs != 0 && ! sel_seqs[i] ) continue; psegment = curr_segment; current = save_current; for(j = 0; j < MSF_WID_NAME; j++) { if(seqname[i][j] == 0) break; putc(seqname[i][j],out); } while( j < MSF_WID_NAME + 1) { putc(' ', out); j++; } for(k = curr_len; k < curr_len + 50 && k < lenseqs; k += 10) { toprint = 10; if(k + toprint > lenseqs) toprint = lenseqs - k; fromseq = toprint; if(save_complete && k + fromseq > eachlength[i]) fromseq = eachlength[i] - k; if(fromseq < 0) fromseq = 0; if(fromseq > 0) { err= output_next_res_from_region( seq[i], eachlength[i], &psegment, ¤t, out, fromseq, TRUE); if(ferror(out)) goto fin; if(err == -1) {retval = 2; goto fin; } } while(fromseq < toprint) { putc('.', out); fromseq++; } putc(' ', out); } putc('\n', out); if( (!save_complete) || eachlength[i] == lenseqs) { new_current = current; new_segment = psegment; } if(ferror(out)) goto fin; } curr_len += 50; fprintf(out, "\n"); } retval = 0; fin: if( fclose(out) != 0 ) retval = 1; free(check_val); return retval; } char *save_alignment_or_region(const char *fname, char **seq, char **comments, char *header, char **seqname, int totseqs, int *eachlength, list_regions *regions, region *region_used, known_format format, int numb_species_sets, int **list_species_sets, char **name_species_sets, int *sel_seqs, int tot_sel_seqs, int protein, int tot_comment_lines, char **comment_name, char **comment_line, int phylipwidnames, int tot_trees, char **trees, const Fl_Menu_Item *items, int spaces_in_fasta_names) /* sauver des sequences ou des regions au format de fichier format region_used pointe vers la liste des regions a sauver si region_used == NULL, toutes les sequences entieres sont sauvees rend NULL si ok un message d'erreur sinon. */ { int err=0; static char err_message[200]; if(format == MASE_FORMAT) err = save_mase_file(fname, seq, comments, header, seqname, totseqs, eachlength, regions, region_used, numb_species_sets, list_species_sets, name_species_sets, sel_seqs, tot_sel_seqs, tot_comment_lines, comment_name, comment_line, tot_trees, trees, items); else if(format == NEXUS_FORMAT) { err = save_nexus_file(fname, totseqs, protein, seq, seqname, comments, header, numb_species_sets, list_species_sets, name_species_sets, regions, tot_comment_lines, comment_name, comment_line, region_used, sel_seqs, tot_sel_seqs, eachlength, tot_trees, trees, items); } else if(format == PHYLIP_FORMAT) err = save_phylip_file(fname, seq, seqname, totseqs, eachlength, region_used, sel_seqs, tot_sel_seqs, phylipwidnames); else if(format == CLUSTAL_FORMAT) err = save_clustal_file(fname, seq, seqname, totseqs, eachlength, region_used, sel_seqs, tot_sel_seqs); else if(format == MSF_FORMAT) err = save_msf_file(fname, seq, seqname, totseqs, eachlength, region_used, protein, sel_seqs, tot_sel_seqs); else if(format == FASTA_FORMAT) err = save_fasta_file(fname, seq, comments, seqname, totseqs, eachlength, region_used, sel_seqs, tot_sel_seqs, spaces_in_fasta_names); if(err == 0) return NULL; else if(err == 1) sprintf(err_message,"Error while writing to file %s",fname); else if(err == 2) strcpy(err_message, "Error: region goes beyond the end of one sequence"); return err_message; } #if !(defined(WIN32) || defined(__APPLE__)) static char seaview_prog_dir[200] = ""; void inform_prog_dir(const char *arg0) { char *p; if((p = (char*)strrchr(arg0, '/')) != NULL) { memcpy(seaview_prog_dir, arg0, p - arg0 + 1); seaview_prog_dir[p - arg0 + 1] = 0; } else seaview_prog_dir[0] = 0; } char *get_prog_dir(void) { return seaview_prog_dir; } #endif char *get_full_path(const char *fname) /* to get full pathname to file fname searching for its name, for it in the prog dir and then for it through all path directories returns NULL if not found */ { #define Mxdir 600 #ifdef WIN32 #define PATH_SEPAR ';' #define DIR_SEPAR '\\' #else #define PATH_SEPAR ':' #define DIR_SEPAR '/' #endif static char dir[Mxdir+1]; char *path, *deb, *fin; FILE *fich; int lf, ltot; strcpy(dir, fname); if(strchr(fname, DIR_SEPAR) != NULL) {// if fname is a pathname fich = fopen(dir, "r"); /* try first explicit filename */ goto way_out; // and don't search more } #if defined(__APPLE__) sprintf(dir, "%s/%s", MG_GetBundleResourcesDir(), fname); fich = fopen(dir, "r"); if(fich != NULL) goto way_out; #else /* try dir where program was launched */ deb = get_prog_dir(); if(deb != NULL && *deb != 0) { strcpy(dir, deb); strcat(dir, fname); fich = fopen(dir, "r"); if(fich != NULL) goto way_out; } #endif path = getenv("PATH"); // get the list of path directories, separated by : or ; if (path == NULL ) return NULL; lf = strlen(fname); deb = path; do { fin = strchr(deb,PATH_SEPAR); if(fin != NULL) { ltot = fin-deb; if(ltot > 0) strncpy(dir,deb,ltot); } else { strcpy(dir,deb); ltot=strlen(dir); } /* now one directory is in string dir */ if( ltot > 0 && ltot + lf + 1 <= Mxdir) { dir[ltot] = DIR_SEPAR; strcpy(dir+ltot+1,fname); /* now dir is appended with filename */ fich = fopen(dir,"r"); if( fich != NULL) break; } else fich = NULL; deb = fin+1; } while (fin != NULL); way_out: if(fich == NULL) return NULL; fclose(fich); #ifndef WIN32 if(*dir != '/') { if(strncmp(dir, "./", 2) == 0) memmove(dir, dir + 2, strlen(dir) - 1); char *p, *q; char *cdir = (char *)malloc(PATH_MAX); p = getcwd(cdir, PATH_MAX); q = (char *)malloc(strlen(p) + 1 + strlen(dir) + 1); sprintf(q, "%s/%s", p, dir); strcpy(dir, q); free(q); free(cdir); } #endif return dir; #undef Mxdir } static void save_species_sets(int numb_species_sets, int **list_species_sets, char **name_species_sets, int totseqs, FILE *out) { int num, i, previous, total; for(num=0; num < numb_species_sets; num++) { total = 0; for(i=0; i< totseqs; i++) if( list_species_sets[num][i] ) total++; if( total == 0 ) continue; fprintf(out,";;@ of species = %d %s\n;;", total, name_species_sets[num]); for(previous = 0; previous < totseqs; previous++) if( list_species_sets[num][previous] ) break; total = 0; for(i = previous+1; i < totseqs; i++) { if( list_species_sets[num][i] ) { fprintf(out," %d,", previous+1); previous = i; total++; if( total >= 15 ) { fprintf(out, "\n;;"); total = 0; } } } fprintf(out," %d\n", previous+1); } } void save_comment_lines(int tot_comment_lines, char **names, char **lines, FILE *out) { int num, l, pos; for(num = 0; num < tot_comment_lines; num++) { if( (l = strlen(lines[num]) ) == 0) continue; fprintf(out, ";;|%s\n", names[num]); for(pos = 0; pos < l; pos += 60) fprintf(out, ";;%.60s\n", lines[num]+pos); fprintf(out, ";;||\n"); } } known_format what_format(const char *filename) /* returns an alignment format (>= 0) -1 unknown format -2 a Newick tree */ { FILE *in; char line[100], *p; int format = -1; int nseq, lseq; in = fl_fopen(filename, "r"); if(in == NULL) return (known_format)-1; p = fgets(line, sizeof(line), in); if( p == NULL) { fclose(in); return (known_format)-1; } while(*p) { *p = toupper(*p); p++; } if(*line == ';') format = MASE_FORMAT; else if(*line == '>') format = FASTA_FORMAT; else if(*line == '(' || *line == '[') format = -2; else if(strncmp(line, "CLUSTAL", 7) == 0) format = CLUSTAL_FORMAT; else if(strncmp(line, "#NEXUS", 6) == 0) format = NEXUS_FORMAT; else { nseq = lseq = -1; sscanf(line, "%d%d", &nseq, &lseq); if(nseq != -1 && lseq != -1) format = PHYLIP_FORMAT; else { /* try MSF format */ do { p = fgets(line, sizeof(line), in); if(p != NULL && strstr(p, " MSF: ") != NULL) format = MSF_FORMAT; } while(p != NULL && strncmp(p, "//", 2) != 0 ); } } fclose(in); return (known_format)format; } char *my_fgets(char *s, int n, FILE *f) { int next_char, ahead; char *p; p = s; while(--n > 0) { next_char = getc(f); if( next_char == '\r' || next_char == '\n' ) { *(p++) = '\n'; ahead = getc(f); if(ahead == EOF) break; if( (next_char == '\r' && ahead != '\n') || (next_char == '\n' && ahead != '\r') ) { ungetc(ahead, f); } break; } else if (next_char == EOF) break; *(p++) = next_char; } *p = 0; return (p == s ? NULL : s); } char *seaview_file_chooser_save_as(const char* message, const char* fname, SEA_VIEW *view, known_format* new_format) { #ifndef MICRO const char *prev_label = Fl_File_Chooser::show_label; Fl_File_Chooser::show_label = "Format"; #endif char *p, types_list[500] = ""; Fl_Native_File_Chooser *chooser = new Fl_Native_File_Chooser(); #ifndef MICRO Fl_File_Chooser::show_label = prev_label; #endif chooser->type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); chooser->options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | chooser->options()); #if SEAVIEW_FLTK_VERSION >= 133 || defined(__APPLE__) chooser->options(Fl_Native_File_Chooser::USE_FILTER_EXT | chooser->options()); #endif chooser->title(message); chooser->directory(extract_dirname(fname)); chooser->preset_file(extract_filename(fname)); p = types_list; for(int f = 0; f < nbr_formats; f++) { sprintf(p, "%s\t*.%s\n", f_format_names[f], f_format_exts[f]); p += strlen(p); } chooser->filter(types_list); chooser->filter_value(view->format_for_save); char *filename = run_and_close_native_file_chooser(chooser, TRUE); if (filename && new_format) *new_format = (known_format)chooser->filter_value(); delete chooser; return filename; } const char *extract_dirname(const char *pathname) { static char dirname[300]; char *p; #if defined(WIN32) p = strrchr(pathname,'\\'); #else p = (char*)strrchr(pathname,'/'); #endif if(p == NULL) dirname[0] = 0; else { memcpy(dirname, pathname, p - pathname); dirname[p - pathname] = 0; } return dirname; } int printout(SEA_VIEW *view, const char *filename, int fontsize, int block_size, Fl_Paged_Device::Page_Format pageformat, int vary_only, int ref0, int pdfkindvalue, Fl_Paged_Device::Page_Layout layout, int svg_width) { int num, i, j, k, current, max_seq_length, fin, curr_lines, widnames, res_per_line, nl, firstpage, lines_per_page, use_pdf, use_svg, top_margin; Fl_Surface_Device *surface; FILE *textfile = NULL; time_t heure; static char unnamed[] = ""; static char num_line[200]; int lettre, char_per_line; short *vary_need = NULL; int *vary_pos; /* rang ds alignement de la colonne imprimŽe */ char *p, oneline[500]; int (*calc_color_function)(int); double char_width = fontsize/2, descender, margin = 25; if(view->tot_seqs == 0) return 0; if(view->protein) calc_color_function = get_color_for_aa; else calc_color_function = get_color_for_base; use_pdf = (pdfkindvalue == PDF_COLOR || pdfkindvalue == PDF_BW); use_svg = (pdfkindvalue == SVG); max_seq_length = 0; widnames = 0; for (i=0; i < view->tot_seqs; i++) { if (view->each_length[i] > max_seq_length) max_seq_length = view->each_length[i]; if ( ( fin=strlen(view->seqname[i]) ) > widnames) widnames = fin; } widnames += 2; if (use_pdf) { surface = new Fl_PDF_or_PS_File_Device(); if (((Fl_PDF_or_PS_File_Device*)surface)->begin_document(filename, pageformat, layout)) { delete surface; return 0; } } else if(use_svg) { FILE *out = fl_fopen(filename, "w"); if (out == NULL) exit(1); #ifndef NO_PDF Fl_SVG_PDF_width_Graphics_Driver *pdf_d = new Fl_SVG_PDF_width_Graphics_Driver(NULL); pdf_d->font(FL_COURIER, fontsize); char_width = pdf_d->width("X", 1); delete pdf_d; #endif margin = char_width; char_per_line = (int)( (svg_width - 2*margin) / char_width + 0.5); fin = (char_per_line - widnames + 1) / (block_size + 1); if (fin < 1) { /* garde fou */ fin = 1; block_size = char_per_line - widnames; } res_per_line = fin * block_size; int nl = (max_seq_length + res_per_line - 1) /res_per_line; int totl = nl * (view->tot_seqs + 2) + 2; surface = new Fl_SVG_File_Surface(svg_width, totl * fontsize, out, true); surface->set_current(); fl_color(210,210,210); // draw grey background fl_rectf(0,0,svg_width, totl * fontsize); } else { textfile = fopen(filename, "w"); if(textfile == NULL) return TRUE; } #ifndef NO_PDF jmp_buf* jbuf; if (use_pdf) ((Fl_PDF_or_PS_File_Device*)surface)->surface_try(&jbuf); if ( (!use_pdf) || (setjmp(*jbuf) == 0)) { #endif if (use_pdf) { surface->driver()->font(FL_COURIER, fontsize); char_width = fl_width("X"); int pwidth, pheight; ((Fl_PDF_or_PS_File_Device*)surface)->printable_rect(&pwidth, &pheight); int l, r, t, b; ((Fl_PDF_or_PS_File_Device*)surface)->margins(&l, &t, &r, &b); margin -= l; char_per_line = (int)((pwidth - 2*margin) / char_width + 0.5); lines_per_page = (int)((pheight - 2*margin) / fontsize + 0.5); descender = fl_descent(); top_margin = margin; } else if (use_svg) { surface->driver()->font(FL_COURIER, fontsize); lines_per_page = 10000000; top_margin = fontsize; } else char_per_line = 90; firstpage = TRUE; if(ref0 < 0) vary_only = FALSE; time(&heure); sprintf(oneline,"Alignment: %s", view->masename == NULL ? unnamed : PREPARE_LABEL(view->masename) ); if (use_pdf) { ((Fl_PDF_or_PS_File_Device*)surface)->start_page(); ((Fl_PDF_or_PS_File_Device*)surface)->origin(0, fontsize); fl_draw(oneline, margin, top_margin); } else if(!use_svg) {fputs(oneline, textfile); fputs("\n", textfile);} curr_lines = 1; if(vary_only) { const char fixed[] = "Displaying variable sites only."; if (use_pdf || use_svg) fl_draw(fixed, margin, top_margin + curr_lines * fontsize); else {fputs(fixed, textfile); fputs("\n", textfile);} ++curr_lines; } if (use_pdf) { sprintf(oneline,"Seaview [blocks=%d fontsize=%d %s%s] on %s", block_size, fontsize, pageformat == Fl_Paged_Device::A4 ? "A4" : "LETTER", layout == Fl_Paged_Device::LANDSCAPE ? "-landscape" : "", ctime(&heure)); p = strchr(oneline, '\n'); if (p) *p = 0; fl_draw(oneline, margin, top_margin + curr_lines * fontsize); curr_lines += 2; } else if(use_svg) { sprintf(oneline,"created by Seaview on %s", ctime(&heure)); p = strchr(oneline, '\n'); if (p) *p = 0; fl_color(FL_BLACK); fl_draw(oneline, margin, top_margin + curr_lines * fontsize); curr_lines += 1; } else { fputs("Seaview text-only output\n", textfile); curr_lines += 2; } if(vary_only) { vary_need = (short *)calloc(max_seq_length, sizeof(short)); if(vary_need == NULL) return TRUE; vary_pos = (int *)calloc(char_per_line, sizeof(int)); if(vary_pos == NULL) return TRUE; for(i = 0; i < max_seq_length; i++) { for(num = 0; num < view->tot_seqs; num++) { if( toupper(view->sequence[num][i]) != toupper(view->sequence[ref0][i]) ) { vary_need[i] = TRUE; break; } } } } /* nombre max de blocks qui tiennent sur une ligne de cpl chars */ fin = (char_per_line - widnames + 1) / (block_size + 1); if(fin < 1) { /* garde fou */ fin = 1; block_size = char_per_line - widnames; } res_per_line = fin * block_size; current = 0; while( current < max_seq_length ) { nl = 1; if(vary_only) { memset(vary_pos, 0, res_per_line * sizeof(int) ); i = -1; j = 0; k = 0; while( j < res_per_line) { if(current + i >= max_seq_length) break; if( !vary_need[current + ++i] ) continue; j++; vary_pos[k++] = current + i + 1; if( j % block_size == 0) k++; } nl = calc_vary_lines(vary_pos, k); } if( use_pdf && (!firstpage) && (curr_lines + view->tot_seqs + nl > lines_per_page)) { ((Fl_PDF_or_PS_File_Device*)surface)->end_page(); ((Fl_PDF_or_PS_File_Device*)surface)->start_page(); ((Fl_PDF_or_PS_File_Device*)surface)->origin(0, fontsize); surface->driver()->font(FL_COURIER, fontsize); curr_lines = 0; } if(vary_only) { out_vary_pos(vary_pos, widnames, k, nl, textfile, margin, top_margin + curr_lines * fontsize); curr_lines += nl; } else { sprintf(num_line, "%d", current + 1); fin = strlen(num_line); memmove(num_line + widnames - fin + 1, num_line, fin+1); if(fin <= widnames) memset(num_line, ' ', widnames - fin + 1); if( use_pdf || use_svg) fl_draw(num_line, margin, top_margin + curr_lines * fontsize); else {fputs(num_line, textfile);fputs("\n",textfile);} ++curr_lines; } for(num=0; num < view->tot_seqs; num++) { k = 0; for(j = 0; j < widnames; j++) { if(view->seqname[num][j] == 0) break; oneline[k++] = view->seqname[num][j]; } while( j < widnames) { j++; oneline[k++] = ' '; } if(vary_only) { i = -1; j = 0; while( j < res_per_line) { if(current + i >= max_seq_length) break; if( !vary_need[current + ++i] ) continue; j++; if(current + i < view->each_length[num]) { if(num != ref0) lettre = ( toupper(view->sequence[num][current+i]) == toupper(view->sequence[ref0][current+i]) ? '.' : view->sequence[num][current+i] ); else lettre = view->sequence[ref0][current+i]; oneline[k++] = lettre; } if( j % block_size == 0) oneline[k++] = ' '; } if(num == view->tot_seqs - 1) current = current + i + 1; } else { fin = res_per_line; if(current+fin > view->each_length[num]) fin = view->each_length[num] - current; if(ref0 != -1 && num != ref0) { /* ecriture par reference a seq ref0 */ for(i=0; isequence[num][current+i]) == toupper(view->sequence[ref0][current+i]) ? '.' : view->sequence[num][current+i] ); oneline[k++] = lettre; if( i < fin-1 && (i+1)%block_size == 0) oneline[k++] = ' '; } } else { /* ecriture normale de seq */ for(i=0; isequence[num][current+i]; if( i < fin-1 && (i+1)%block_size == 0) oneline[k++] = ' '; } } } oneline[k] = 0; if(!view->allow_lower) majuscules(oneline + widnames); if(use_pdf && (curr_lines >= lines_per_page)) { ((Fl_PDF_or_PS_File_Device*)surface)->end_page(); ((Fl_PDF_or_PS_File_Device*)surface)->start_page(); ((Fl_PDF_or_PS_File_Device*)surface)->origin(0, fontsize); surface->driver()->font(FL_COURIER, fontsize); curr_lines = 0; } if(!use_pdf && !use_svg) { fputs(oneline, textfile); fputs("\n", textfile); } else if(pdfkindvalue == PDF_BW) { fl_draw(oneline, margin, top_margin + curr_lines * fontsize); } else { if (use_pdf) color_pdf_display(view, calc_color_function, oneline, widnames, margin, top_margin + curr_lines * fontsize, fontsize, char_width, descender, num, current); else color_svg_display(view, calc_color_function, oneline, widnames, margin, top_margin + curr_lines * fontsize, fontsize, char_width); } ++curr_lines; firstpage = FALSE; } if(!use_pdf && !use_svg) { fputs("\n", textfile); } else if(curr_lines + 1 <= lines_per_page) { ++curr_lines; } if( ! vary_only ) current += res_per_line; } if(use_pdf) { ((Fl_PDF_or_PS_File_Device*)surface)->end_page(); ((Fl_PDF_or_PS_File_Device*)surface)->end_job(); } else if(use_svg) { fl_color(FL_GRAY); fl_line_style(0, 3); fl_rect(1,1, ((Fl_SVG_File_Surface*)surface)->width()-2, ((Fl_SVG_File_Surface*)surface)->height()-2); ((Fl_SVG_File_Surface*)surface)->end(); } else fclose(textfile); #ifndef NO_PDF } /* end of PDF_TRY */ if (use_pdf && ((Fl_PDF_or_PS_File_Device*)surface)->surface_catch()) { ((Fl_PDF_or_PS_File_Device*)surface)->error_catch(); } #endif if (use_pdf || use_svg) delete surface; return FALSE; } static void color_pdf_display(SEA_VIEW *view, int (*calc_color_function)( int ), char *oneline, int widnames, double x, double y, int fontsize, double char_width, double descender, int num, int current) { double xx; int c, l, count = 0; char *p, **clines; clines = (char **)malloc(sizeof(char *) * view->numb_gc); if(clines==NULL) return; l = strlen(oneline); for(c = 1; c < view->numb_gc; c++) { clines[c] = (char *)malloc(l + 1); if(clines[c] == NULL) return; memset(clines[c], ' ', l); clines[c][l] = 0; } for(p = oneline + widnames; *p != 0; p++) { if(*p == ' ') continue; if(view->curr_colors != view->codoncolors) c = calc_color_function(*p); else c = view->col_rank[num][current + count++]; if(c > 0) clines[c][p - oneline] = 'X'; } for(c = 1; c < view->numb_gc; c++) { if(strchr(clines[c], 'X') == NULL) continue; fl_color(view->curr_colors[c]); for(xx = x + widnames*char_width, p = clines[c] + widnames; *p != 0; p++, xx += char_width) { if(*p == ' ') continue; fl_rectf(xx, y - fontsize + descender, char_width+1, fontsize); } } fl_color(FL_BLACK); fl_draw(oneline, x, y); for(c = 1; c < view->numb_gc; c++) free(clines[c]); free(clines); } static void color_svg_display(SEA_VIEW *view, int (*calc_color_function)( int ), char *oneline, int widnames, double x, double y, int fontsize, double char_width) { double xx; int c, l; char *p; l = strlen(oneline); char *aux = (char*)malloc(l+1); fl_font(FL_COURIER_BOLD, fontsize); xx = x + widnames*char_width; for (c = 0; c < view->numb_gc; c++) { memset(aux, ' ', l-widnames); for (p = oneline+widnames; p < oneline+l; p++) { if (calc_color_function(*p) == c) aux[p-(oneline+widnames)] = *p; } fl_color(view->curr_colors[c]); fl_draw(aux, l - widnames, xx, y); } fl_font(FL_COURIER, fontsize); fl_color(FL_BLACK); fl_draw(oneline, widnames, x, y); } static int calc_vary_lines(int *vary_pos, int widpos) { int maxi = 0, num, nl; for(num = 0; num < widpos; num++) if(vary_pos[num] > maxi) maxi = vary_pos[num]; if(maxi >= 100000) nl = 6; else if(maxi >= 10000) nl = 5; else if(maxi >= 1000) nl = 4; else if(maxi >= 100) nl = 3; else if(maxi >= 10) nl = 2; else nl = 1; return nl; } static void out_vary_pos(int *vary_pos, int widnames, int widpos, int nl, FILE *textfile, double x, double y) { int num, l, k, echelle, digit, val; static char chiffre[] = "0123456789"; char oneline[300]; echelle = 1; k = 0; for(l = 2; l <= nl; l++) echelle *= 10; for(l = nl; l > 0; l--) { for(num = 0; num < widnames; num++) oneline[k++] = ' '; for(num = 0; num < widpos; num++) { val = vary_pos[num]; if(val < echelle) oneline[k++] = ' '; else { digit = (val / echelle) % 10 ; oneline[k++] = *(chiffre + digit); } } oneline[k] = 0; if(textfile == NULL) { fl_draw(oneline, x, y); y += fl_height(); } else {fputs(oneline, textfile); fputs("\n",textfile); } k = 0; echelle /= 10; } } SEA_VIEW* read_alignment_file(const char *infile ) { char *err_message; int i; SEA_VIEW* view = new SEA_VIEW; memset(view, 0, sizeof(SEA_VIEW)); view->menubar = new Fl_Menu_Bar(0,0, 30, 30); view->menu_trees = new vlength_menu(view->menubar, "Trees", NULL, 0); if (fl_access(infile, R_OK)) { fprintf(stderr, "File %s\nis not readable or does not exist", infile); return NULL; } known_format file_format = what_format(infile); if (file_format < 0) { fprintf(stderr, "File %s\nis not of a format readable by seaview", infile); return NULL; } if (file_format == MASE_FORMAT) { view->tot_seqs = read_mase_seqs_header(infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); /* interpreter les regions du header du fichier mase */ view->regions = parse_regions_from_header(view->header); /* interpreter les species sets du fichier mase */ view->numb_species_sets = parse_species_sets_from_header(view->header, view->list_species_sets, view->name_species_sets, view->tot_seqs); /* interpreter les trees du fichier mase */ parse_trees_from_header(view->header, view); /* interpreter les comment lines du header */ view->tot_comment_lines = parse_comment_lines_from_header(view->header, &(view->comment_line), &(view->comment_name), &(view->comment_length) , &(view->max_seq_length)); } else if(file_format == FASTA_FORMAT) view->tot_seqs = read_fasta_align(infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message, view->spaces_in_fasta_names); else if(file_format == PHYLIP_FORMAT) view->tot_seqs = read_phylip_align(infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == CLUSTAL_FORMAT) view->tot_seqs = read_clustal_align(infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == MSF_FORMAT) view->tot_seqs = read_msf_align(infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message); else if(file_format == NEXUS_FORMAT) { int **list_sp = NULL; char **name_sp = NULL; int i; view->tot_seqs = read_nexus_align((char*)infile, &view->sequence, &view->seqname, &view->comments, &view->header, &err_message, &view->regions, &view->numb_species_sets, &list_sp, &name_sp, &view->tot_comment_lines, &view->comment_name, &view->comment_line, &view->comment_length, &view->protein, view); for(i= 0; i < view->numb_species_sets; i++) { view->list_species_sets[i] = list_sp[i]; view->name_species_sets[i] = name_sp[i]; } if(list_sp != NULL) free(list_sp); if(name_sp != NULL) free(name_sp); } if (view->tot_seqs == 0) return NULL; if (file_format != NEXUS_FORMAT) view->protein = is_a_protein_seq(view->sequence[0]); view->each_length = new int[view->tot_seqs]; for (i = 0; i < view->tot_seqs; i++) { view->each_length[i] = strlen(view->sequence[i]); } view->seq_length = 0; for (i = 0; i < view->tot_seqs; i++) { if (view->each_length[i] > view->seq_length) view->seq_length = view->each_length[i]; } view->masename = strdup(infile); view->format_for_save = file_format; return view; } SEA_VIEW *cmdline_read_input_alignment(int argc, char **argv) { char *fname, line[500]; fname = argv[argc-1]; if (strcmp(fname, "-") == 0) { fname = create_tmp_filename(); FILE *out = fopen(fname, "w"); while (fgets(line, sizeof(line), stdin) != NULL) { fputs(line, out); } fclose(out); } SEA_VIEW *view = read_alignment_file(fname); if (strcmp(argv[argc-1], "-") == 0) delete_tmp_filename(fname); if (!view) { fputs("\n", stderr); exit(1); } view->max_seq_length = calc_max_seq_length(view->seq_length, view->tot_seqs); allonge_seqs(view->sequence, view->tot_seqs, view->max_seq_length, view->each_length, view->tot_comment_lines, view->comment_line, NULL); return view; } void format_conversion(int argc, char **argv) { char *err_message, *p; int i, j, gc; bool std_output = false; bool save_fragment = false; bool bootstrap = false; region *myregion; SEA_VIEW *view = cmdline_read_input_alignment(argc, argv); if (view == NULL) { fprintf(stderr, "No sequence found in %s", argv[argc-1]); exit(1); } known_format out_format = view->format_for_save; load_resources(progname); view->phylipwidnames = int_res_value("phylipwidnames", 30); char *outfile = process_output_options(argc, argv, out_format, std_output); if ( !view->protein && isarg(argc, argv, "-translate")) { bool no_terminal_stop = isarg(argc, argv, "-no_terminal_stop"); for (i = 0; i < view->tot_seqs; i++) { gc = (view->comments != NULL ? get_ncbi_gc_from_comment(view->comments[i]) : 1); p = translate_with_gaps(view->sequence[i], get_acnuc_gc_number(gc)); free(view->sequence[i]); view->sequence[i] = p; if (no_terminal_stop) { char *q = p + strlen(p) - 1; while (q > p && *q == '-') q--; if (q >= p && *q == '*') *q = '-'; } view->each_length[i] = strlen(p); view->regions = NULL; } view->protein = true; } while ( (p = argname(argc, argv, "-def_species_group")) != NULL) { p = strtok(p, ","); view->name_species_sets[view->numb_species_sets] = strdup(p); view->list_species_sets[view->numb_species_sets] = (int*)calloc(view->tot_seqs, sizeof(int)); while (true) { p = strtok(NULL, ","); if (!p) break; if (strchr(p, '-') == NULL) { sscanf(p, "%d", &i); view->list_species_sets[view->numb_species_sets][i-1] = 1; } else { sscanf(p, "%d-%d", &i, &j); if (i <= j) { while (i <= j) view->list_species_sets[view->numb_species_sets][i++ - 1] = 1; } } } view->numb_species_sets++; for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-def_species_group") == 0) { *argv[i] = '+'; break; } } } while ( (p = argname(argc, argv, "-def_site_selection")) != NULL) { int from, to; list_segments *current_seg; region *site_selection = (region*)calloc(1, sizeof(region)); list_regions *last_reg = (list_regions*)calloc(1, sizeof(list_regions)); last_reg->element = site_selection; if (!view->regions) { view->regions = last_reg; } else { list_regions *current_reg; current_reg = view->regions; while (current_reg->next) current_reg = current_reg->next; current_reg->next = last_reg; } p = strtok(p, ","); site_selection->name = strdup(p); while (true) { p = strtok(NULL, ","); if (!p) break; if (strchr(p, '-') == NULL) { sscanf(p, "%d", &from); to = from; } else { sscanf(p, "%d-%d", &from, &to); if (from > to) continue; } if (to > view->seq_length) to = view->seq_length; if (from > view->seq_length) continue; list_segments *seg = (list_segments*)malloc(sizeof(list_segments)); seg->debut = from; seg->fin = to; seg->next = NULL; if (!site_selection->list) { site_selection->list = seg; } else { current_seg->next = seg; } current_seg = seg; } for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-def_site_selection") == 0) { *argv[i] = '+'; break; } } } if (isarg(argc, argv, "-gblocks")) { // gblocks method myregion = (region*)malloc(sizeof(region)); myregion->name = strdup("Gblocks"); view->region_line = (char*)malloc(view->seq_length + 1); create_gblocks_mask(view, myregion, true, isarg(argc, argv, "-b5"), isarg(argc, argv, "-b4"), isarg(argc, argv, "-b3"), isarg(argc, argv, "-b2")); list_regions *r = view->regions, *pre = NULL; while (r) { if (strcmp(r->element->name, myregion->name) == 0) break; pre = r; r = r->next; } if (r) { free(r->element->name); r->element = myregion; } else { list_regions *elt = (list_regions*)malloc(sizeof(list_regions)); elt->element = myregion; elt->next = NULL; if (pre) pre->next = elt; else view->regions = elt; } } if ( (p = argname(argc, argv, "-sites")) ) { save_fragment = true; list_regions *elt = view->regions; while (elt) { if (strcmp(elt->element->name, p) == 0) break; elt = elt->next; } if (elt) view->active_region = elt->element; } if ( (p = argname(argc, argv, "-species")) ) { save_fragment = true; for (i = 0; i < view->numb_species_sets; i++) { if (strcmp(view->name_species_sets[i], p) == 0) break; } if (i < view->numb_species_sets) { view->sel_seqs = view->list_species_sets[i]; view->tot_sel_seqs = 0; for (i = 0; i < view->tot_seqs; i++) if (view->sel_seqs[i]) view->tot_sel_seqs++; } } if (isarg(argc, argv, "-del_gap_only_sites") && !isarg(argc, argv, "-sites")) del_gap_only_sites(view); if ( (p = argname(argc, argv, "-bootstrap")) ) { int replicates = -1; sscanf(p, "%d", &replicates); if (replicates == -1) replicates = 1; bootstrap = true; save_fragment = false; save_bootstrap_replicates(outfile, replicates, view); } if (save_fragment) { myregion = view->active_region; if (myregion == NULL) { myregion = (region *)malloc(sizeof(region)); myregion->list = (list_segments *)malloc(sizeof(list_segments)); myregion->list->debut = 1; myregion->list->fin = view->seq_length; myregion->list->next = NULL; myregion->name = (char *)"all"; } err_message = save_alignment_or_region(outfile, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, NULL, myregion, out_format, 0, NULL, NULL, view->sel_seqs, view->tot_sel_seqs, view->protein, 0, NULL, NULL, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); } else if (!bootstrap) { err_message = save_alignment_or_region(outfile, view->sequence, view->comments, view->header, view->seqname, view->tot_seqs, view->each_length, view->regions, NULL, out_format, view->numb_species_sets, view->list_species_sets, view->name_species_sets, NULL, 0, view->protein, view->tot_comment_lines, view->comment_name, view->comment_line, view->phylipwidnames, view->tot_trees, view->trees, view->menu_trees->vitem(0), view->spaces_in_fasta_names); } if (err_message) { fprintf(stderr, "%s\n", err_message); if (std_output) delete_tmp_filename(outfile); exit(1); } if (std_output) { char line[200]; FILE *in = fopen(outfile, "r"); while (fgets(line, sizeof(line), in) != NULL) { fputs(line, stdout); } fclose(in); fflush(stdout); fl_unlink(outfile); } exit(0); } char *process_output_options(int argc, char **argv, known_format& out_format, bool& std_output) { int i; char upper_format[20], *p; std_output = false; char *outformatname = argname(argc, argv, "-output_format"); if (outformatname) { majuscules(outformatname); for (i = 0; i < nbr_formats; i++) { strcpy(upper_format, f_format_names[i]); majuscules(upper_format); if (strcmp(upper_format, outformatname)== 0) break; } if (i >= nbr_formats) { fprintf(stderr, "'%s' is not of a format known by seaview", outformatname); exit(1); } out_format = (known_format)i; } char *outfile = argname(argc, argv, "-o"); if (outfile == NULL) { outfile = new char[strlen(argv[argc-1]) + 12]; strcpy((char*)outfile, argv[argc-1]); p = strrchr(outfile, '.'); if (!p) { p = (char*)outfile + strlen(outfile); *p = '.'; } strcpy(p+1, f_format_exts[out_format]); if (strcmp(outfile, argv[argc-1]) == 0) { strcpy(p, "_2."); strcpy(p+3, f_format_exts[out_format]); } } else if (strcmp(outfile, "-") == 0) { outfile = strdup(create_tmp_filename()); std_output = true; } return outfile; } #ifndef NO_PDF void printout_cmdline(int argc, char **argv) { bool std_output = false; SEA_VIEW *view = cmdline_read_input_alignment(argc, argv); if (view == NULL) { fprintf(stderr, "No sequence found in %s", argv[argc-1]); exit(1); } load_resources(progname); //protein colors static char stdcolorgroups[50], customprotcolors[300]; strcpy(stdcolorgroups, get_res_value("stdcolorgroups", def_stdcolorgroups)); strcpy(customprotcolors, get_res_value("protcolors", "")); int *protcolors = (int *)malloc(max_protcolors * sizeof(int)); int *def_protcolors = (int *)malloc(max_protcolors * sizeof(int)); for(int i=0; inumb_stdprotcolors, &view->numb_altprotcolors); view->max_seq_length = calc_max_seq_length(view->seq_length, view->tot_seqs); if (view->protein) { view->numb_gc = view->numb_stdprotcolors; view->curr_colors = view->stdprotcolors = protcolors; protcolors[0] = FL_BLACK; } else { view->numb_gc = view->numb_dnacolors = 5; view->curr_colors = view->dnacolors = dnacolors; } known_format out_format = view->format_for_save; char *outfile = process_output_options(argc, argv, out_format, std_output); int fontsize = (int)argval(argc, argv, "-fontsize", 10); int blocksize = (int)argval(argc, argv, "-blocksize", 10); #ifdef NO_PDF int use_svg = false; int svg_width = 0; #else int use_svg = isarg(argc, argv, "-svg"); int svg_width = (int)argval(argc, argv, "-svg", 1000); #endif int landscape = isarg(argc, argv, "-landscape"); int letter = isarg(argc, argv, "-letter"); printout(view, outfile, fontsize, blocksize, letter ? Fl_Paged_Device::LETTER : Fl_Paged_Device::A4, false, -1, use_svg ? SVG : PDF_COLOR, landscape ? Fl_Paged_Device::LANDSCAPE : Fl_Paged_Device::PORTRAIT, svg_width); if (std_output) { char line[200]; FILE *in = fopen(outfile, "r"); if (in) { while (fgets(line, sizeof(line), in) != NULL) { fputs(line, stdout); } fclose(in); fflush(stdout); } delete_tmp_filename(outfile); } exit(0); } #endif // ! NO_PDF ����������������seaview/viewasprots.cxx�����������������������������������������������������������������������������000644 �000765 �000024 �00000023113 12404325714 016140� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "seaview.h" #include #include char *translate_with_gaps(char *seq, int gc); char *back_translate_with_gaps(char *prot, char *dna); void free_col_seqs(SEA_VIEW * view); int get_ncbi_gc_from_comment(char *comment); void set_ncbi_genetic_code(SEA_VIEW *view); void update_comment_gc(int seqnum, int ncbigc, SEA_VIEW *view); extern "C" { char codaa(char *codon, int code); int get_acnuc_gc_number(int ncbi_gc); int get_ncbi_gc_number(int ncbi_gc); char *get_code_descr(int code); } extern int totcodes; extern void set_and_show_new_cursor_seq(SEA_VIEW *view, int new_pos); extern void set_and_show_new_cursor_site(SEA_VIEW *view, int new_pos, int center, int force_redraw); void *set_viewasprots(SEA_VIEW * view, int onoff) { int num, oldmodif, gc, oldtotsel, *oldselseqs, oldsites, oldcursorseq, oldcursorsite; char **protseq, **dnaseq, **olddna, **retval, *masename; oldmodif = view->modif_but_not_saved; oldtotsel = view->tot_sel_seqs; oldselseqs = view->sel_seqs; oldcursorseq = view->cursor_seq; oldcursorsite = view->cursor_site; save_active_region(view); masename = view->masename; oldsites = view->menu_sites->value(); if(onoff) { /* ON */ protseq = (char **)malloc(view->tot_seqs * sizeof(char *)); if(protseq == NULL) return NULL; for(num=0; num < view->tot_seqs; num++) { gc = (view->comments != NULL ? get_ncbi_gc_from_comment(view->comments[num]) : 1); protseq[num] = translate_with_gaps(view->sequence[num], get_acnuc_gc_number(gc)); if(protseq[num] == NULL) { while(--num >= 0) free(protseq[num]); free(protseq); return NULL; } } retval = view->sequence; view->sequence = protseq; free(view->each_length); free_col_seqs(view); if(view->region_line != NULL) free(view->region_line); init_dna_scroller(view, view->tot_seqs, masename, TRUE, view->header); set_and_show_new_cursor_site(view, (oldcursorsite - 1)/3 + 1, TRUE, FALSE); if(view->regions != NULL) { list_segments *lseg; int i = 1; list_regions *lreg = view->regions; while(lreg != NULL) { // for each region lseg = lreg->element->list; // don't change its coordinates if hide_when_viewasprots is on while( (!lreg->element->hide_when_viewasprots) && lseg != NULL) { lseg->debut = (lseg->debut - 1)/3 + 1; lseg->fin = (lseg->fin - 1)/3 + 1; lseg = lseg->next; } if(lreg->element->hide_when_viewasprots) { // inactivate in menu if hide_when_viewasprots is on view->menu_sites->vitem(i - 1)->deactivate(); if(i == oldsites) oldsites = 0; // and don't show it as active region } lreg = lreg->next; i++; } } } else { /* OFF */ int l, maxl = 0; char *p; dnaseq = (char **)malloc(view->tot_seqs * sizeof(char *)); if(dnaseq == NULL) return view->viewasprots; olddna = (char **)view->viewasprots; for(num=0; num < view->tot_seqs; num++) { dnaseq[num] = back_translate_with_gaps(view->sequence[num], olddna[num]); if(dnaseq[num] == NULL) return view->viewasprots; l = view->each_length[num] = strlen(dnaseq[num]); if(l > maxl) maxl = l; } maxl = 3*((maxl+2)/3); // desired alignment length as multiple of 3 for(num = 0; num < view->tot_seqs; num++) { // extend all seqs to maxl length with gaps free(olddna[num]); l = view->each_length[num]; if(l == maxl) continue; p = (char *)realloc(dnaseq[num], maxl + 1); if(p == NULL) continue; dnaseq[num] = p; p += l; while(l++ < maxl) *(p++) = '-'; *p = 0; } free(olddna); for(num=0; num < view->tot_seqs; num++) free(view->sequence[num]); free(view->sequence); free(view->each_length); view->sequence = dnaseq; free_col_seqs(view); if(view->region_line != NULL) free(view->region_line); init_dna_scroller(view, view->tot_seqs, masename, FALSE, view->header); set_and_show_new_cursor_site(view, 3*oldcursorsite, TRUE, FALSE); if(view->regions != NULL) { list_segments *lseg; list_regions *lreg = view->regions; while(lreg != NULL) { lseg = lreg->element->list; while( (!lreg->element->hide_when_viewasprots) && lseg != NULL) { lseg->debut = 3*(lseg->debut - 1) + 1; lseg->fin = 3*(lseg->fin); lseg = lseg->next; } lreg = lreg->next; } } retval = NULL; } set_seaview_modified(view, oldmodif); view->tot_sel_seqs = oldtotsel; set_and_show_new_cursor_seq(view, oldcursorseq); free(view->sel_seqs); free(masename); view->sel_seqs = oldselseqs; if(oldsites) { view->menu_sites->vitem(oldsites-1)->set(); view->menubar->value(view->menu_sites->vitem(oldsites-1)); view->menu_sites->vitem(oldsites-1)->callback()(view->menubar, 0); } select_deselect_seq(view, -2); view->DNA_obj->redraw(); return retval; } char *translate_with_gaps(char *seq, int gc) { int lp, l = strlen(seq); char *p, *last = seq + l; lp = 0; p = (char *)malloc(l/3 + 5); if(p == NULL) return NULL; while(seq + 2 < last) { if(strncmp(seq, "---", 3) == 0) { p[lp++] = '-'; } else { if(*seq == '-') *seq = '@'; if(*(seq + 1) == '-') *(seq + 1) = '@'; if(*(seq + 2) == '-') *(seq + 2) = '@'; // for macse, translate any !-containing codon to ! p[lp++] = ( memchr(seq, '!', 3) ? '!' : codaa(seq, gc) ); } seq += 3; } p[lp] = 0; return p; } char *back_translate_with_gaps(char *prot, char *dna) { int l, ld; char *newdna, *pd, *q; l = 3*strlen(prot) + 7; newdna = (char *)malloc(l); if(newdna == NULL) return NULL; pd = newdna; prot--; while(*(++prot) != 0) { while(memcmp(dna, "---", 3) == 0) dna += 3; if(*prot == '-') { memcpy(pd, "---", 3); pd += 3; } else { if(*dna == '@') *dna = '-'; if(*(dna + 1) == '@') *(dna + 1) = '-'; if(*(dna + 2) == '@') *(dna + 2) = '-'; memcpy(pd, dna, 3); pd += 3; dna += 3; } } *pd = 0; while(memcmp(dna, "---", 3) == 0) dna += 3; if (*dna != 0) {//if a partial codon remains at end while (*(pd-1) == '-') pd--; ld = pd - newdna; q = dna + strlen(dna); while (q > dna && *(q-1) == '-') q--; if (ld+(q-dna) >= l) { l = ld+(q-dna)+5; newdna = (char*)realloc(newdna, l); pd = newdna + ld; } memcpy(pd, dna, q - dna); pd += q - dna; *pd = 0; } return newdna; } void free_col_seqs(SEA_VIEW * view) { if(view->numb_gc > 1) { /* free col_rank */ int num; for(num = 0; num < view->tot_seqs; num++) { free(view->col_rank[num]); } free(view->col_rank); } } int get_ncbi_gc_from_comment(char *comment) { char *p; int gc = -1; if(comment == NULL) return 1; p = strstr(comment, "/transl_table="); if(p == NULL) return 1; sscanf(p+14, "%d", &gc); return (gc > 1 ? gc : 1); } void ask_gc_callback(Fl_Widget *ob, void *which) { int v = ((Fl_Hold_Browser *)which)->value(); int *status = (int *)( ob->window()->user_data() ); *status = v; } void ignore_gc_callback(Fl_Widget *ob, void *which) { *(int *)which = 0; } void set_ncbi_genetic_code(SEA_VIEW *view) /* sets desired ncbi genetic code to selected sequences (cancel possible) */ { int gc = 1, num; char line[170]; int status; static char codencbinames[19][60] = { "Standard", "Yeast mt", "Vertebrate mt", "Mold+Protozoan+Coelentarate mt, Mycoplasma Spiroplasma", "Invertebrate mt", "Alternative Yeast Nuclear", "Ciliate+Dasycladacean+Hexamita Nuclear", "Euplotid Nuclear", "Echinoderm+Flatworm mt", "Ascidian mt", "Alternative Flatworm mt", "Blepharisma Macronuclear", "Bacterial and Plant Plastid", "Chlorophycean mt", "Trematode mt", "Scenedesmus obliquus mt", "Thraustochytrium mt", "Pterobranchia mt", "Candidate Division SR1"}; if(view->comments == NULL) view->comments = (char **)calloc(view->tot_seqs, sizeof(char *)); if(view->comments == NULL) return; Fl_Window *win = new Fl_Window(750,390); win->label("Genetic code selection"); for(num = 0; num < view->tot_seqs; num++) if(view->sel_seqs[num]) break; gc = get_ncbi_gc_from_comment(view->comments[num]); Fl_Hold_Browser *obj = new Fl_Hold_Browser(5, 25, 740, 340); obj->textfont(FL_COURIER); sprintf(line, "Set genetic code for %s", view->tot_sel_seqs > 1 ? "selected sequences" : view->seqname[num]); obj->copy_label(line); obj->align(FL_ALIGN_TOP); for(num = 0; num < totcodes; num++) { sprintf(line, "%45.45s|%2d| %s", codencbinames[num], get_ncbi_gc_number(num), get_code_descr(num)); obj->add(line); } obj->value(get_acnuc_gc_number(gc) + 1); Fl_Button *b = new Fl_Return_Button(obj->x(), obj->y() + obj->h() + 3, 50, 20, "OK"); b->callback(ask_gc_callback, obj); b = new Fl_Button(obj->x() + obj->w() - 55 , b->y(), 55, 20, "Cancel"); b->callback(ignore_gc_callback, &status); b->shortcut(FL_COMMAND | 'w'); win->end(); win->resizable(new Fl_Box(obj->x() + 55, obj->y(), 50, obj->h() )); win->size_range(100, 100); win->callback(ignore_gc_callback, &status); status = -1; win->show(); #ifndef MICRO win->hotspot(win); #endif do Fl::wait(); while(status == -1); delete win; view->DNA_obj->take_focus(); if(status != 0) { gc = get_ncbi_gc_number(status - 1); for(num = 0; num < view->tot_seqs; num++) { if( view->sel_seqs[num] ) update_comment_gc(num, gc, view); } } } void update_comment_gc(int seqnum, int ncbigc, SEA_VIEW *view) /* adds or updates /transl_table=xx in seqnum's comment */ { int l; char *comm, *p, *q, *r; comm = view->comments[seqnum]; if(comm == NULL) l = 0; else l = strlen(comm); if(l > 0) p = strstr(comm, "/transl_table="); else p = NULL; if(p != NULL) { q = p+13; r = q; do r++; while (isdigit(*r)); *(q+1) = 0; p = (char *)malloc(l + 3); if(p == NULL) return; sprintf(p, "%s%d%s", comm, ncbigc, r); } else { p = (char *)malloc(l + 20); if(p == NULL) return; if(l > 2) strcpy(p, comm); else *p = 0; sprintf(p + strlen(p), ";/transl_table=%d\n", ncbigc); } if(comm != NULL) free(comm); view->comments[seqnum] = p; set_seaview_modified(view, TRUE); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/win32_extras.cxx����������������������������������������������������������������������������000644 �000765 �000024 �00000016626 12506326570 016121� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifdef WIN32 #include "pdf_or_ps.h" #include #include #include #include #ifndef NO_PDF #include #endif /* included functions */ void my_bell(void); char *get_prog_dir(void); char **getutf8args(int *pargc); int mysystem(const char *cmd); Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_Surface_Device(new Fl_GDI_Graphics_Driver()) { HDC oldflgc = fl_gc; //int factor = 32; // empirically set // exact computation of factor from screen units to EnhMetaFile units (0.01 mm) HDC hdc = GetDC(NULL); int hmm = GetDeviceCaps(hdc, HORZSIZE); int hdots = GetDeviceCaps(hdc, HORZRES); int vmm = GetDeviceCaps(hdc, VERTSIZE); int vdots = GetDeviceCaps(hdc, VERTRES); ReleaseDC(NULL, hdc); float factorw = (100. * hmm) / hdots; float factorh = (100. * vmm) / vdots + 0.5; RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh; fl_gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); if (fl_gc != NULL) { SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT); SetBkMode(fl_gc, TRANSPARENT); } else { fl_gc = oldflgc; } } Fl_Copy_Surface::~Fl_Copy_Surface() { if(oldflgc == fl_gc) oldflgc = NULL; HENHMETAFILE hmf = CloseEnhMetaFile (fl_gc); if ( hmf != NULL ) { if ( OpenClipboard (NULL) ){ EmptyClipboard (); SetClipboardData (CF_ENHMETAFILE, hmf); CloseClipboard (); } DeleteEnhMetaFile(hmf); } DeleteDC(fl_gc); fl_gc = oldflgc; delete driver(); } char *get_prog_dir(void) /* returns path of dir where calling program was launched */ { static char *dir = NULL; char *line, *p; int l; if(dir == NULL) { WCHAR *wp = GetCommandLineW(); l = 4*wcslen(wp)+1; line = new char[l]; char *keep = line; fl_utf8fromwc(line, l, wp, wcslen(wp)); //fprintf(OUT,"retour GetCommandLine line=%s\n",line);fflush(OUT); /* extract 1st word of line or first group delimited by " " */ if(*line == '"') { line++; p = strchr(line, '"'); } else p = strchr(line, ' '); if(p == NULL) p = line + strlen(line); l = p - line; while( l > 0 && line[l - 1] != '\\' ) l--; if (l == 0) {strcpy(line, ".\\"); l = 2;} if(l > 0) { dir = (char *)malloc(l + 1); memcpy(dir, line, l); dir[l] = 0; } delete[] keep; } return dir; } char **getutf8args(int *pargc) { int argc, l; wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); char **argv = (char **)malloc(argc * sizeof(char *)); for (int count = 0; count < argc; count++) { l = 4*wcslen(wargv[count])+1; argv[count] = (char *)malloc(l); fl_utf8fromwc(argv[count], l, wargv[count], wcslen(wargv[count])); } *pargc = argc; return argv; } int mysystem(const char *cmd) { DWORD retval; BOOL status; //conversion of utf-8 cmd into a WCHAR string int wlen = MultiByteToWideChar(CP_UTF8, 0, cmd, -1, NULL, 0); WCHAR *wcmd = new WCHAR[wlen]; MultiByteToWideChar(CP_UTF8, 0, cmd, -1, wcmd, wlen); PROCESS_INFORMATION pi; STARTUPINFOW si; ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) ); ZeroMemory( &si, sizeof(STARTUPINFOW) ); si.cb = sizeof(STARTUPINFOW); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); status = CreateProcessW(NULL, wcmd, 0,0,TRUE,CREATE_NO_WINDOW,0,0, &si, &pi); if (!status) return 1; do retval = WaitForSingleObject(pi.hProcess, 500); while (retval == WAIT_TIMEOUT); delete[] wcmd; return 0; } const char *win32_UTF8_to_CP1252(const char *in) { static char dst[250]; fl_utf8toa(in, strlen(in), dst, sizeof(dst)); return (const char *)dst; } #ifndef NO_PDF static size_t pdf_write_proc(PDF *p, void *data, size_t size) { FILE **output = (FILE**)PDF_get_opaque(p); return fwrite(data, 1, size, *output); } // because PDF_begin_document fails on WIN32 if non ascii filename PDF *win32_PDF_new() { FILE **output = new FILE*; PDF *pdf = PDF_new2(0,0,0,0, output); if (!pdf) delete output; return pdf; } int win32_PDF_begin_document(PDF *p, const char *filename, int len, const char *optlist) { FILE **output = (FILE**)PDF_get_opaque(p); *output = fl_fopen(filename, "wb"); // binary mode compulsory if (*output == NULL) return -1; PDF_begin_document_callback(p, pdf_write_proc, optlist); return 1; } void win32_PDF_end_document(PDF *p, const char *optlist) { FILE **output = (FILE**)PDF_get_opaque(p); #ifdef PDF_end_document #undef PDF_end_document #undef PDF_delete #endif PDF_end_document(p, optlist); fclose(*output); } void win32_PDF_delete(PDF *p) { FILE **output = (FILE**)PDF_get_opaque(p); delete output; PDF_delete(p); } #endif /* to delete all "base_fname*" files */ void delete_tmp_filename(const char *base_fname) { WIN32_FIND_DATAW data; HANDLE h; WCHAR fname[MAX_PATH]; unsigned l = strlen(base_fname); unsigned wn = fl_utf8toUtf16(base_fname, l, NULL, 0) + 2; // Query length WCHAR *wbuf = new WCHAR[wn]; wn = fl_utf8toUtf16(base_fname, l, (unsigned short*)wbuf, wn); // Convert string to WCHAR[] wbuf[wn] = '*'; // add '*' at end of base name wbuf[wn + 1] = 0; WCHAR *p = wbuf + wn; // find end of directory part in base_fname while (*p != '\\') p--; l = p - wbuf + 1; memcpy(fname, wbuf, l * sizeof(WCHAR)); // memorize directory part h = FindFirstFileW(wbuf, &data); delete[] wbuf; if (h != INVALID_HANDLE_VALUE) { do { memcpy(fname + l, data.cFileName, (wcslen(data.cFileName)+1)*sizeof(WCHAR)); // build full pathname DeleteFileW(fname); } while (FindNextFileW(h, &data) != 0); FindClose(h); } } /* void add_to_path(char *dir) /* ajoute a la variable PATH la directory dir teste si deja dedans ou si vide * { char *buffer; int l; if(dir == NULL || strlen(dir) == 0) return; buffer = (char *)malloc(10000); l = GetEnvironmentVariable("PATH", buffer, 10000); if(l == 0) *buffer = 0; if(strstr(buffer, dir) != NULL) return; if(*buffer != 0) strcat(buffer, ";"); strcat(buffer, dir); SetEnvironmentVariable("PATH", buffer); free(buffer); } char **split_args(char *all, int *pargc) { char *p, *q, **argv; int l, argc = 0; // compter les arguments p = all; while(*p != 0) { argc++; if(*p == '"') p = strchr(p+1, '"'); else p = strchr(p, ' '); if(p == NULL) break; p++; while(*p == ' ') p++; } argv = (char **)malloc(argc * sizeof(char *)); *pargc = argc; // separer les arguments, enlever les "" encadrantes si presentes p = all; argc = 0; while(*p != 0) { if(*p == '"') { p++; q = strchr(p, '"'); } else q = strchr(p, ' '); if(q == NULL) q = p + strlen(p); l = q - p; argv[argc] = (char *)malloc(l + 1); memcpy(argv[argc], p, l); argv[argc][l] = 0; if(*q == 0) break; p = q + 1; while(*p == ' ') p++; argc++; } return argv; } int mysystem(const char *command) /* command contains "cmd.exe /c prog.exe args" or "prog.exe args" the first form is compulsory if args contain "> outfile" prog is searched in dir where calling program was launched, current dir, windows system dir, windows dir, dirs in PATH. returns 0 iff OK *\ { static char buf[100]; STARTUPINFO info; PROCESS_INFORMATION pi; int retval; GetStartupInfo(&info); retval = CreateProcess(NULL, (char *)command,0,0,0,0,0,_getcwd(buf,sizeof(buf)),&info,&pi); if(retval == 0) return 1; do { Fl::check(); retval = WaitForSingleObject(pi.hProcess, 500); } while(retval == WAIT_TIMEOUT); return 0; } */ #endif // WIN32 ����������������������������������������������������������������������������������������������������������seaview/xfmatpt.cxx���������������������������������������������������������������������������������000644 �000765 �000024 �00000116307 12404325714 015245� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "matpt.h" #include "pdf_or_ps.h" #include #include #include #include #include #ifndef NO_PDF #include #endif #define MAXSEQLENGTH 10000 /* pas utilise pour interface avec seaview */ #define MAXSEGMENTS 20000 #define segment_x_ou_y(num, offset) \ (*(int *)(((char *)(segments + num)) + offset)) /* globals */ struct segment { int x, y, longueur; }; static struct segment segments[MAXSEGMENTS+1]; gap_site gap_sites[MAX_GAP_SITES]; extern Fl_Paged_Device::Page_Format printout_pageformat; /* prototypes */ void show_dot_plot(char *seq1, char *seq2, char *seqname1, char *seqname2, int l1, int l2, int maxseqlength, void *seaview_data); FD_matpt *create_form_matpt(void); static void err_message(const char *text); static char *check_alloc(int nbrelt, int sizelt); void log_to_phys(int lx, int ly, int *px, int *py, FD_matpt *matpt); void phys_to_log(int px, int py, int *lx, int *ly, FD_matpt *matpt); void reset_mat_data(FD_matpt *matpt); void reset_sliders_data(FD_matpt * matpt); void init_mat_data(FD_matpt * matpt, int seqlong1, int seqlong2, char *seqname1, char *seqname2, char *seq1, char *seq2, char *name, int maxseqlength); void set_size_data(FD_matpt *matpt); void compute_region_text(FD_matpt *matpt); void draw_rect(FD_matpt *matpt); int mat_handle_proc(Fl_Widget *ob, int event, float x, float y, char key); void center_view_on_hit(FD_matpt *matpt); void magnify_reduce_proc(Fl_Widget *ob, void *extra); void change_comput_params(Fl_Widget *ob, void *data); void compute_proc(Fl_Widget *ob, void *data); void interrupt_callback(Fl_Widget *ob, void *data); void ps_draw_line(int x1, int y1, int x2, int y2, FD_matpt *matpt); void ps_set_mat_data(FD_matpt *matpt); void plot_button_proc(Fl_Widget *ob, void *data); int really_close(FD_matpt *matpt); void exit_button_proc(Fl_Widget *ob, FD_matpt *data); void move_mat_proc(Fl_Widget *ob, void *data); void move_box_step(Fl_Widget *ob, void *extra); void region_size_proc(Fl_Widget *ob, void *data); char *readseq(FILE *infile, int *slong, char **seqname); char *readseqfile(char *fname, int *seqlong1, int *seqlong2, char **name1, char **name2, char **seq1, char **seq2); void compute_diags(FD_matpt *matpt); void compute_title(FD_matpt *matpt); int find_next_gap_site(int pos, gap_site *gap_sites, int tot_gap_sites); void new_gap_site(int pos, int l, gap_site *gap_sites, int *p_tot_gap_sites, int seqrank); int delete_gaps_bef_pos(char *seq, int pos, int number, int length, int totsegments, int offset); int insert_gaps_bef_pos(char *seq, int pos, int number, int length, int totsegments, int offset, int maxlen); int dispatch_gaps_bef(int pos, int number, char *seq, gap_site * gap_sites, int *p_tot_gap_sites, int offset, int seqlen, int totsegments, int seqrank, char *other_seq, int *other_seqlen, int other_offset, int maxlen); void align_callback(Fl_Widget *ob, void *data); void record_alignment_callback(Fl_Widget *ob, void *data); extern int insert_gaps_at(SEA_VIEW *view, int seq, int site, int total); extern void update_current_seq_length(int newlength, SEA_VIEW *view); void update_col_lines(int num, SEA_VIEW *view); void matpt_idle_cb(FD_matpt *matpt); class matpt_panel : public Fl_Widget { FL_EXPORT void draw(void); FL_EXPORT int handle(int); public: FL_EXPORT matpt_panel(int x,int y,int w,int h, void *data) : Fl_Widget(x,y,w,h,NULL) { this->user_data(data); } }; void my_watch_cursor(Fl_Window *win) { win->default_cursor(FL_CURSOR_WAIT); } void fl_reset_cursor(Fl_Window *win) { win->default_cursor(FL_CURSOR_DEFAULT); } void show_dot_plot(char *seq1, char *seq2, char *seqname1, char *seqname2, int l1, int l2, int maxseqlength, void *seaview_data) { static int first = TRUE; static FD_matpt *matpt; char *new_seq1, *new_seq2; static char *old_seq1, *old_seq2; SEA_VIEW *view = (SEA_VIEW *)seaview_data; if(first) { first = FALSE; matpt = create_form_matpt(); matpt->form->callback((Fl_Callback*)exit_button_proc, matpt); matpt->seq1 = matpt->seq2 = NULL; matpt->seaview_data = seaview_data; old_seq1 = NULL; old_seq2 = NULL; if(view->protein) { ((Fl_Input *)matpt->win_size_type_box)->value("10"); ((Fl_Input *)matpt->ident_type_box)->value("5"); } } if(matpt->seq1 == NULL || seq1 != old_seq1 || seq2 != old_seq2) { if(matpt->seq1 != NULL) { free(matpt->seq1+1); free(matpt->seq2+1); } new_seq1 = (char *)malloc(maxseqlength+1); memcpy(new_seq1, seq1, l1 + 1); new_seq2 = (char *)malloc(maxseqlength+1); memcpy(new_seq2, seq2, l2 + 1); init_mat_data(matpt, l1, l2, seqname1, seqname2, new_seq1 - 1, new_seq2 - 1, view->masename, maxseqlength); set_size_data(matpt); old_seq1 = seq1; old_seq2 = seq2; } compute_region_text(matpt); ((Fl_Slider*)(matpt->region_slider))->value(matpt->region_size); matpt->form->show(); #ifndef MICRO matpt->form->hotspot(matpt->form); #endif compute_title(matpt); } static Fl_Widget *cre_button(int x, int y, int *w, int h, int si, const char *label) { Fl_Widget *obj; fl_font(FL_HELVETICA, si); *w = (int)fl_width(label) + 4 * 2; obj = new Fl_Button(x, y, *w, h, label); obj->labelsize(si); return obj; } FD_matpt *create_form_matpt(void) { Fl_Widget *obj; FD_matpt *fdui = (FD_matpt *) check_alloc(1, sizeof(*fdui)); static char def_title[] = "Dot Plot"; Fl_Window *form; int curr_x, curr_y, fin, width, fontsize, but_height; user_data_plus *data; fdui->title = def_title; #if defined(WIN32) || defined(__APPLE__) fontsize = 10; fdui->form = form = new Fl_Window(560, 540); #else fontsize = 12; fdui->form = form = new Fl_Window(680, 815); #endif form->box(FL_FLAT_BOX); form->label("Dot Plot"); curr_y = fin = 5; but_height = fontsize + 4 * 2; Fl_Group *top = new Fl_Group(fin, curr_y, form->w() - 2 * fin, but_height); obj = cre_button(fin, curr_y, &width, but_height, fontsize, "Fit to window"); fin += width + 2; data = new user_data_plus; data->p = fdui; data->value = 1; obj->callback(magnify_reduce_proc, data); obj = cre_button(fin, curr_y, &width, but_height, fontsize, "Reduce"); fin += width + 2; data = new user_data_plus; data->p = fdui; data->value = 2; obj->callback(magnify_reduce_proc, data); Fl_Widget *magnify = cre_button(fin, curr_y, &width, but_height, fontsize, "Magnify"); fin += width + 2; data = new user_data_plus; data->p = fdui; data->value = 3; magnify->callback(magnify_reduce_proc, data); curr_x = fin; Fl_Widget *compute = cre_button(fin, curr_y, &width, but_height, fontsize, "Compute"); fin += width + 2; compute->callback(compute_proc, fdui); fdui->compute_butt = compute; Fl_Widget *postscript = cre_button(fin, curr_y, &width, but_height, fontsize, "Write "PDF_OR_PS); fin += width; postscript->callback(plot_button_proc, fdui); #ifndef WIN32 fin += 2; Fl_Widget *close = cre_button(fin, curr_y, &width, but_height, fontsize, "Close"); ((Fl_Button *)close)->shortcut(FL_COMMAND | 'w'); fin += width; close->callback((Fl_Callback*)exit_button_proc, fdui); #endif width = fin - curr_x; width = top->x() + top->w() - width; width = width - curr_x; compute->position(compute->x() + width, compute->y() ); postscript->position(postscript->x() + width, postscript->y() ); #ifndef WIN32 close->position(close->x() + width, close->y() ); #endif static char wsize_label[] = "Window size:"; fl_font(FL_HELVETICA, fontsize); width = (int)fl_width(wsize_label) + 2; curr_x = magnify->x() + magnify->w() + 2; obj = new Fl_Input(curr_x + width, curr_y, 30, but_height, wsize_label); obj->type(FL_INT_INPUT); fin = obj->x() + obj->w() + 2; obj->labelsize(fontsize); ((Fl_Input *)obj)->textsize(fontsize); obj->callback(change_comput_params, fdui); ((Fl_Input *)obj)->value("20"); fdui->win_size_type_box = obj; static char wmatch_label[] = "matches/window:"; fl_font(FL_HELVETICA, fontsize); width = (int)fl_width(wmatch_label) + 2; obj = new Fl_Input(fin + width, curr_y, 30, but_height, wmatch_label); obj->type(FL_INT_INPUT); fin = obj->x() + obj->w(); obj->labelsize(fontsize); ((Fl_Input *)obj)->textsize(fontsize); obj->callback(change_comput_params, fdui); ((Fl_Input *)obj)->value("13"); fdui->ident_type_box = obj; curr_x = magnify->x() + magnify->w() + 1; width = compute->x() - curr_x - 1; top->add_resizable(*new Fl_Box(curr_x, curr_y, width, but_height) ); top->end(); curr_y += but_height + 2; Fl_Group *align_group = new Fl_Group(top->x(), curr_y, top->w(), but_height); fin = align_group->x(); obj = cre_button(fin, curr_y, &width, but_height, fontsize, "Align"); fin += width + 2; obj->callback(align_callback, fdui); fdui->align_button = obj; obj = cre_button(fin, curr_y, &width, but_height, fontsize, "Record alignment"); fin += width + 5; obj->callback(record_alignment_callback, fdui); static char ref_choice_label[] = "Ref. sequence"; fl_font(FL_HELVETICA, fontsize); width = (int)fl_width(ref_choice_label) + 4 * 2; obj = new Fl_Choice(fin + width, curr_y, 150, but_height, ref_choice_label); obj->type(0); obj->labelfont(FL_HELVETICA); obj->labelsize(fontsize); ((Fl_Choice *)obj)->textfont(FL_HELVETICA); ((Fl_Choice *)obj)->textsize(fontsize); fdui->choice_ref_seq = obj; obj = cre_button(0, curr_y, &width, but_height, fontsize, "Interrupt"); curr_x = align_group->x() + align_group->w() - width; obj->position(curr_x, obj->y()); obj->callback(interrupt_callback, &(fdui->interrupted)); fdui->interrupt_butt = obj; curr_x = fdui->choice_ref_seq->x() + fdui->choice_ref_seq->w() + 1; width = fdui->interrupt_butt->x() - curr_x - 1; align_group->add_resizable(*new Fl_Box(curr_x, curr_y, width, but_height) ); align_group->end(); curr_y += but_height + 2; Fl_Group *region_group = new Fl_Group(top->x(), curr_y, top->w(), 80); #ifdef WIN32 #define SQW 15 #else #define SQW 20 #endif fin = region_group->x(); obj = new Fl_Repeat_Button(fin,curr_y,SQW,SQW,"@<-"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 1; obj->callback(move_box_step, data); obj = new Fl_Repeat_Button(fin + SQW,curr_y,SQW,SQW,"@->"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 2; obj->callback(move_box_step, data); curr_y += SQW; obj = new Fl_Repeat_Button(fin,curr_y,SQW,SQW,"@1->"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 3; obj->callback(move_box_step, data); obj = new Fl_Repeat_Button(fin + SQW,curr_y,SQW,SQW,"@9->"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 4; obj->callback(move_box_step, data); curr_y += SQW; obj = new Fl_Repeat_Button(fin,curr_y,SQW,SQW,"@2->"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 5; obj->callback(move_box_step, data); obj = new Fl_Repeat_Button(fin + SQW,curr_y,SQW,SQW,"@8->"); obj->labeltype(FL_SYMBOL_LABEL); obj->box(FL_ENGRAVED_BOX); data = new user_data_plus; data->p = fdui; data->value = 6; obj->callback(move_box_step, data); curr_x = fin + 2*SQW + 3; curr_y -= 2 * SQW; width = form->w() - curr_x - 3; strcpy(fdui->regionboxtext, ""); obj = new Fl_Box(FL_ENGRAVED_BOX,curr_x,curr_y,width,3*SQW,fdui->regionboxtext); obj->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); obj->labelsize(fontsize); obj->labelfont(FL_COURIER); fdui->region_box = obj; fl_font(fdui->region_box->labelfont(), fdui->region_box->labelsize() ); int debut = 4 + 10 * (int)fl_width("A"); int maxbound = (fdui->region_box->w() - 8) / (int)fl_width("A") - 6; obj = new Fl_Slider(FL_HOR_FILL_SLIDER, fdui->region_box->x() + debut, fdui->region_box->y() + fdui->region_box->h(), fdui->region_box->w() - debut, SQW, ""); obj->callback(region_size_proc, fdui); ((Fl_Slider *)obj)->when((Fl_When)(FL_WHEN_CHANGED | FL_WHEN_RELEASE)); ((Fl_Slider *)obj)->bounds(4, maxbound); fdui->region_slider = obj; region_group->resizable(fdui->region_slider); region_group->end(); curr_y += fdui->region_box->h() + fdui->region_slider->h() + 5; Fl_Group *panel_group = new Fl_Group(top->x(), curr_y, top->w(), form->h() - curr_y - 5); obj = new Fl_Slider(FL_VERT_SLIDER, panel_group->x() + panel_group->w() - SQW, panel_group->y(), SQW, panel_group->h() - SQW - 5, ""); data = new user_data_plus; data->value = 1; data->p = fdui; obj->callback(move_mat_proc, data); ((Fl_Slider*)obj)->when((Fl_When)(FL_WHEN_CHANGED | FL_WHEN_RELEASE)); fdui->y_slider = obj; obj = new Fl_Slider(FL_HOR_SLIDER, panel_group->x(), panel_group->y() + panel_group->h() - SQW, panel_group->w() - SQW -5, SQW, ""); data = new user_data_plus; data->value = 2; data->p = fdui; obj->callback(move_mat_proc, data); ((Fl_Slider*)obj)->when((Fl_When)(FL_WHEN_CHANGED | FL_WHEN_RELEASE)); fdui->x_slider = obj; /* mat_panel */ obj = new Fl_Box(FL_ENGRAVED_FRAME, panel_group->x()-3, panel_group->y()-3, fdui->x_slider->w()+6, fdui->y_slider->h()+6, ""); obj = new matpt_panel(panel_group->x(), panel_group->y(), fdui->x_slider->w(), fdui->y_slider->h(), fdui); obj->color(FL_BLACK, FL_GRAY); fdui->mat_panel = obj; fdui->gap_sites = gap_sites; panel_group->resizable(fdui->mat_panel); panel_group->end(); form->end(); form->resizable(panel_group); return fdui; } static void err_message(const char *text) { fl_alert("%s", text); exit(1); } static char *check_alloc(int nbrelt, int sizelt) { char *retval; if( (retval = (char *)calloc(nbrelt,sizelt)) != NULL ) return retval; err_message("ERROR: I cannot obtain enough memory."); return NULL; } void log_to_phys(int lx, int ly, int *px, int *py, FD_matpt *matpt) { *px = (int)floor(lx * matpt->factor + matpt->kx + 0.5); *py = (int)floor( - ly * matpt->factor + matpt->ky + 0.5); } void phys_to_log(int px, int py, int *lx, int *ly, FD_matpt *matpt) { *lx = (int)floor( (px - matpt->kx) / matpt->factor + 0.5 ); *ly = (int)floor( (matpt->ky - py) / matpt->factor + 0.5 ); } void reset_mat_data(FD_matpt *matpt) { int a, b, c, d; matpt->factor = ((double) matpt->phys_width) / matpt->view_size; a = matpt->view_x; b = a + matpt->view_size; c = matpt->mat_panel->x() + matpt->margin; d = c + matpt->phys_width; matpt->kx = (b*c - a*d) / (double) matpt->view_size; a = matpt->view_y; b = a + matpt->view_size; c = matpt->mat_panel->y() + matpt->mat_panel->h() - matpt->margin; d = c - matpt->phys_width; matpt->ky = (b*c - a*d) / (double) matpt->view_size; } void reset_sliders_data(FD_matpt * matpt) { ((Fl_Slider *)matpt->x_slider)->bounds(0, matpt->longmax - matpt->view_size); ((Fl_Slider *)matpt->x_slider)->slider_size(matpt->view_size / (double)matpt->longmax); ((Fl_Slider *)matpt->x_slider)->step(1); ((Fl_Slider *)matpt->y_slider)->bounds( - (matpt->longmax - matpt->view_size), 0); ((Fl_Slider *)matpt->y_slider)->slider_size(matpt->view_size / (double)matpt->longmax); ((Fl_Slider *)matpt->y_slider)->step(1); ((Fl_Slider *)matpt->x_slider)->value(matpt->view_x); ((Fl_Slider *)matpt->y_slider)->value(- matpt->view_y); } void init_mat_data(FD_matpt * matpt, int seqlong1, int seqlong2, char *seqname1, char *seqname2, char *seq1, char *seq2, char *name, int maxseqlength) { const int margin = 5; int fenetre, identites; matpt->rect_only = FALSE; matpt->longmax = FL_max(seqlong1, seqlong2); matpt->margin = margin; matpt->seqlong1 = seqlong1; matpt->seqlong2 = seqlong2; matpt->seq1 = seq1; matpt->seq2 = seq2; matpt->seqname1 = seqname1; matpt->seqname2 = seqname2; matpt->view_x = matpt->view_y = 0; matpt->view_size = matpt->longmax; sscanf( ((Fl_Input *)matpt->win_size_type_box)->value(), "%d", &fenetre); matpt->fenetre = fenetre; sscanf( ((Fl_Input *)matpt->ident_type_box)->value(), "%d", &identites); matpt->identites = identites; matpt->region_size = fenetre; matpt->hitx = seqlong1/2; matpt->hity = seqlong2/2; matpt->totsegments = -1; matpt->need_compute = FALSE; matpt->modif_but_not_saved = FALSE; matpt->plotname = (char *)malloc(strlen(name) + 1); strcpy(matpt->plotname, name); if(matpt->align_button != NULL) { char temp[200], name1[40], name2[40], *p; sprintf(name1, "%.30s", seqname1); if((p = strchr(name1,'|')) != NULL) *p = 0; sprintf(name2, "%.30s", seqname2); if((p = strchr(name2,'|')) != NULL) *p = 0; sprintf(temp, "align to %s|align to %s", name1, name2); ((Fl_Choice*)matpt->choice_ref_seq)->clear(); ((Fl_Choice *)matpt->choice_ref_seq)->value(0); ((Fl_Choice *)matpt->choice_ref_seq)->add(temp); ((Fl_Choice *)matpt->choice_ref_seq)->mode(0, FL_MENU_RADIO); ((Fl_Choice *)matpt->choice_ref_seq)->mode(1, FL_MENU_RADIO); matpt->tot_gap_sites = 0; matpt->maxseqlength = maxseqlength; } } void set_size_data(FD_matpt *matpt) { matpt->phys_width = FL_min(matpt->mat_panel->w(), matpt->mat_panel->h()) - 2 * matpt->margin; reset_mat_data(matpt); reset_sliders_data(matpt); } void compute_region_text(FD_matpt *matpt) { int i, matches=0, l; char *p; static char newtext[sizeof(matpt->regionboxtext)]; if(matpt->longmax == 0) return; p = newtext; sprintf(p, "%5d ", matpt->hitx); l = FL_min(matpt->region_size, matpt->seqlong1 - matpt->hitx + 1); l = FL_min(l, matpt->seqlong2 - matpt->hity + 1); memcpy(p+6, (matpt->seq1 + matpt->hitx), l); *(p + l + 6) = '\n'; p += l + 7; strcpy(p, " "); for(i=0; i < l; i++) { if( toupper(*(matpt->seq1 + matpt->hitx + i)) == toupper(*(matpt->seq2 + matpt->hity + i)) && *(matpt->seq2 + matpt->hity + i) != '-' ) { *(p + i + 6) = '|'; matches++; } else *(p + i + 6)=' '; } sprintf(p,"%d/%d", matches, matpt->region_size); *(p + strlen(p)) = ' '; *(p + 6 + l)='\n'; p += l + 7; sprintf(p, "%5d ", matpt->hity); memcpy(p+6, (matpt->seq2 + matpt->hity), l); *(p + l + 6)='\0'; if(strcmp(matpt->regionboxtext, newtext) != 0) { strcpy(matpt->regionboxtext, newtext); matpt->region_box->redraw(); } } void draw_rect(FD_matpt *matpt) { int px, py, pxf, pyf; rectangle old_rect; log_to_phys(matpt->hitx, matpt->hity, &px, &py, matpt); log_to_phys(matpt->hitx + matpt->region_size, matpt->hity + matpt->region_size, &pxf, &pyf, matpt); // rectangle mis pour avoir h > 0 old_rect.x = px; old_rect.y = pyf; old_rect.w = pxf - px; old_rect.h = py - pyf; if (old_rect.x + old_rect.w > 0 && old_rect.y + old_rect.h > 0 && old_rect.y <= matpt->form->h() && old_rect.x <= matpt->form->w()) { fl_overlay_rect(old_rect.x, old_rect.y, old_rect.w, old_rect.h); } fl_color(FL_BLACK); matpt->rect_only = FALSE; } void matpt_panel::draw(void) { FD_matpt *matpt = (FD_matpt *)this->user_data(); int i, pxd, pyd, pxf, pyf; static int old_w = 0, old_h = 0; this->clear_damage(); // tres important! if( this->w() != old_w || this->h() != old_h ) { /* was resized */ old_w = this->w(); old_h = this->h(); set_size_data(matpt); ((Fl_Slider *)matpt->region_slider)->value(matpt->region_size); } fl_push_clip(this->x(), this->y(), this->w(), this->h()); if(matpt->rect_only) goto label_draw_rect; fl_overlay_clear(); /* ecriture du fond */ fl_color(this->selection_color()); fl_rectf(this->x(), this->y(), this->w(), this->h()); fl_color(FL_BLACK); /* draw the diagonal line */ if( ( (SEA_VIEW *) matpt->seaview_data )->numb_gc > 1) { /* in red on color displays */ log_to_phys(0, 0, &pxd, &pyd, matpt); i = FL_min(matpt->seqlong1, matpt->seqlong2); log_to_phys(i, i, &pxf, &pyf, matpt); fl_color(FL_RED); fl_line(pxd, pyd, pxf, pyf); fl_color(FL_BLACK); } else { /* as a dotted line on B&W displays */ int p, q; log_to_phys(0, 0, &pxd, &pyd, matpt); i = FL_min(matpt->seqlong1, matpt->seqlong2); log_to_phys(i, i, &pxf, &pyf, matpt); q = pyd; for(p=pxd; p<=pxf; p += 2) { fl_line(p, q, p, q); q -= 2; } } log_to_phys(0, 0, &pxd, &pyd, matpt); log_to_phys(matpt->seqlong1, 0, &pxf, &pyf, matpt); fl_line(pxd, pyd, pxf, pyf); log_to_phys(0, matpt->seqlong2, &pxf, &pyf, matpt); fl_line(pxd, pyd, pxf, pyf); if(matpt->need_compute) { compute_diags(matpt); fl_pop_clip(); return; } else { for (i = 0; i <= matpt->totsegments; i++) { log_to_phys(segments[i].x, segments[i].y, &pxd, &pyd, matpt); log_to_phys(segments[i].x+segments[i].longueur, segments[i].y+segments[i].longueur, &pxf, &pyf, matpt); fl_line(pxd, pyd, pxf, pyf); } } label_draw_rect: draw_rect(matpt); fl_pop_clip(); compute_region_text(matpt); fl_reset_cursor(this->window()); } int matpt_panel::handle(int event) { FD_matpt *matpt = (FD_matpt *)this->user_data(); if(event == FL_PUSH) { int lx, ly; phys_to_log( Fl::event_x(), Fl::event_y(), &lx, &ly, matpt); if(lx <= 0 || ly <= 0 || lx > matpt->seqlong1 || ly > matpt->seqlong2) return 1; matpt->hitx = lx; matpt->hity = ly; matpt->rect_only = TRUE; matpt->mat_panel->redraw(); compute_region_text(matpt); Fl::focus(this); return 1; } else if(event == FL_KEYBOARD) { int key = Fl::event_key(); if( key != FL_Right && key != FL_Left && key != FL_Up && key != FL_Down ) return 0; if(key == FL_Left) { matpt->hitx = FL_max(matpt->hitx - 5, 1); matpt->hity = FL_max(matpt->hity - 5, 1); } else if(key == FL_Right) { matpt->hitx = FL_min(matpt->hitx + 5, matpt->seqlong1); matpt->hity = FL_min(matpt->hity + 5, matpt->seqlong2); } else if(key == FL_Up) { matpt->hity = FL_min(matpt->hity + 5, matpt->seqlong2); } else { /* FL_Down */ matpt->hity = FL_max(matpt->hity - 5, 1); } matpt->rect_only = TRUE; matpt->mat_panel->redraw(); compute_region_text(matpt); return 1; } else if(event == FL_FOCUS) { return 1; } return 0; } void center_view_on_hit(FD_matpt *matpt) { int newval; newval = matpt->hitx + (matpt->region_size - matpt->view_size) / 2; newval = FL_min( FL_max(newval, 0), matpt->longmax - matpt->view_size); matpt->view_x = newval; newval = matpt->hity + (matpt->region_size - matpt->view_size) / 2; newval = FL_min( FL_max(newval, 0), matpt->longmax - matpt->view_size); matpt->view_y = newval; reset_mat_data(matpt); reset_sliders_data(matpt); } void magnify_reduce_proc(Fl_Widget *ob, void *extra) { const int zoom = 2; FD_matpt *matpt = (FD_matpt *)((user_data_plus *)extra)->p; int data = ((user_data_plus *)extra)->value; if( data == 3 ) { /* magnify */ matpt->view_size /= zoom; } else if ( data == 1 ) { /* fit to window */ matpt->view_size = matpt->longmax; } else { /* reduce */ matpt->view_size = FL_min( matpt->view_size * zoom, matpt->longmax ); } center_view_on_hit(matpt); matpt->mat_panel->redraw(); matpt->x_slider->redraw(); matpt->y_slider->redraw(); } void change_comput_params(Fl_Widget *ob, void *data) { const char *p; int value = -1; FD_matpt *fdui = (FD_matpt *)data; p= ((Fl_Input *)ob)->value(); sscanf(p,"%d",&value); if(value<=0 || value>50) { ((Fl_Input *)ob)->value("??"); value = -1; } if(ob == fdui->win_size_type_box) fdui->fenetre = value; else fdui->identites = value; if(fdui->identites > fdui->fenetre && fdui->fenetre>0) { char tmp[10]; fdui->identites = fdui->fenetre; sprintf(tmp,"%d", fdui->identites); ((Fl_Input *)fdui->ident_type_box)->value(tmp); } } void compute_proc(Fl_Widget *ob, void *data) { FD_matpt *fdui = (FD_matpt *)data; change_comput_params(fdui->win_size_type_box, fdui); change_comput_params(fdui->ident_type_box, fdui); if(fdui->fenetre == -1 || fdui->identites == -1) return; my_watch_cursor(fdui->mat_panel->window()); fdui->need_compute = TRUE; fdui->interrupted = FALSE; fdui->mat_panel->redraw(); fdui->region_box->redraw(); if(!fdui->form->visible()) return; if(fdui->fenetre > fdui->region_size) fdui->region_size = fdui->fenetre; ((Fl_Slider *)fdui->region_slider)->value(fdui->region_size); fdui->region_slider->redraw(); } void interrupt_callback(Fl_Widget *ob, void *data) { *(int *)data = TRUE; } void ps_draw_line(int x1, int y1, int x2, int y2, FD_matpt *matpt) { int px, py, px2, py2; px = (int)floor(x1 * matpt->factor + matpt->kx + 0.5); py = (int)floor(y1 * matpt->factor + matpt->ky + 0.5); px2 = (int)floor(x2 * matpt->factor + matpt->kx + 0.5); py2 = (int)floor(y2 * matpt->factor + matpt->ky + 0.5); fl_line(px, py, px2, py2); } void ps_set_mat_data(FD_matpt *matpt) { int a, b, c, d; matpt->factor = ((double) matpt->phys_width) / matpt->view_size; a = matpt->view_x; b = a + matpt->view_size; c = matpt->margin; d = c + matpt->phys_width; matpt->kx = (b*c - a*d) / (double) matpt->view_size; a = matpt->view_y; b = a + matpt->view_size; c = matpt->margin; d = c + matpt->phys_width; matpt->ky = (b*c - a*d) / (double) matpt->view_size; } void plot_button_proc(Fl_Widget *ob, void *data) { FD_matpt *matpt = (FD_matpt *)data; int i; char message[200]; int old_phys; Fl_PDF_or_PS_File_Device* surface = new Fl_PDF_or_PS_File_Device(); if (surface->start_job(matpt->plotname, printout_pageformat)) return; // we use bottom-up coords for PDF and PS output, it's rather tricky. #ifndef NO_PDF jmp_buf *jbuf; surface->surface_try(&jbuf); if (setjmp(*jbuf) == 0) { PDF_set_parameter((PDF*)(surface->pdf()), "topdown", "false"); // set coords bottom-up #endif surface->start_page(); #ifdef NO_PDF int w, h; surface->printable_rect(&w, &h); surface->scale(1, -1); // set coords bottom-up surface->origin(30, -h+200); #else surface->origin(30, 200); #endif fl_color(FL_BLACK); fl_line(-10,-10,510,-10); fl_line(510,-10,510,510); fl_line(-10,-10,-10,510); fl_line(-10,510,510,510); old_phys = matpt->phys_width; matpt->phys_width = 500; ps_set_mat_data(matpt); ps_draw_line(0, 0, matpt->seqlong1, 0, matpt); ps_draw_line(0, 0, 0, matpt->seqlong2, matpt); for (i = 0; i <= matpt->totsegments; i++) { ps_draw_line(segments[i].x, segments[i].y, segments[i].x+segments[i].longueur, segments[i].y+segments[i].longueur, matpt); } matpt->phys_width = old_phys; reset_mat_data(matpt); sprintf(message, "Horizontal: %.30s (%d) Vertical: %.30s (%d) Window: %d Matches: %d", matpt->seqname1, matpt->seqlong1, matpt->seqname2, matpt->seqlong2, matpt->fenetre, matpt->identites); #ifdef NO_PDF surface->scale(1, 1); // back to top-down coords surface->origin(20, h-200+30); #else surface->origin(20, 170); #endif surface->driver()->font(FL_HELVETICA, 10); fl_draw(message, 0, 0); surface->end_page(); surface->end_job(); #ifndef NO_PDF } /* end of PDF_TRY */ if( surface->surface_catch() ) { surface->error_catch(); delete surface; return; } #endif #ifndef MICRO matpt->form->hide(); Fl::flush(); // because of strange bug on 32-bit Linux only #endif fl_message("Dot plot is now in file\n%s\nin "PDF_OR_PS" format", surface->outfname()); delete surface; #ifndef MICRO matpt->form->show(); Fl::flush(); #endif } int really_close(FD_matpt *matpt) { int rep; if(matpt->modif_but_not_saved) { rep = fl_choice("Changes in dot plot were not saved in alignment\n" "Do you really want to close the dot plot?", "Cancel", "Close", NULL); if(!rep) return FALSE; } free(matpt->seq1 + 1); free(matpt->seq2 + 1); matpt->seq1 = matpt->seq2 = NULL; return TRUE; } void exit_button_proc(Fl_Widget *ob, FD_matpt *matpt) { if ( really_close(matpt) ) { matpt->form->hide(); } } void move_mat_proc(Fl_Widget *ob, void *data) { int rank = ((user_data_plus *)data)->value; FD_matpt *matpt = (FD_matpt *)((user_data_plus *)data)->p; int val; val = (int)( ((Fl_Slider *)ob)->value() ); if(rank == 1) matpt->view_y = - val; else matpt->view_x = val; reset_mat_data(matpt); matpt->mat_panel->redraw(); } void move_box_step(Fl_Widget *ob, void *extra) { int data = ((user_data_plus *)extra)->value; FD_matpt *matpt = (FD_matpt *)((user_data_plus *)extra)->p; if(data == 1) { matpt->hitx = FL_max(matpt->hitx - 1, 1); } else if(data == 2) { matpt->hitx = FL_min(matpt->hitx + 1, matpt->seqlong1); } else if(data == 3) { matpt->hitx = FL_max(matpt->hitx - 1, 1); matpt->hity = FL_max(matpt->hity - 1, 1); } else if(data == 4) { matpt->hitx = FL_min(matpt->hitx + 1, matpt->seqlong1); matpt->hity = FL_min(matpt->hity + 1, matpt->seqlong2); } else if(data == 5) { matpt->hity = FL_max(matpt->hity - 1, 1); } else { matpt->hity = FL_min(matpt->hity + 1, matpt->seqlong2); } matpt->rect_only = TRUE; matpt->mat_panel->redraw(); compute_region_text(matpt); } void region_size_proc(Fl_Widget *ob, void *data) { FD_matpt *matpt = (FD_matpt *)data; matpt->region_size = (int)( ((Fl_Slider *)ob)->value() ); matpt->rect_only = TRUE; matpt->mat_panel->redraw(); matpt->region_box->redraw(); } void compute_title(FD_matpt *matpt) { static char title[150]; sprintf(title, "Horizontal: %.30s (%d) Vertical: %.30s (%d)", matpt->seqname1, matpt->seqlong1, matpt->seqname2, matpt->seqlong2); matpt->title = title; matpt->mat_panel->window()->label(title); } int find_next_gap_site(int pos, gap_site *gap_sites, int tot_gap_sites) { int num; for(num = 0; num < tot_gap_sites; num++) if(gap_sites[num].pos > pos) return num; return -1; } void new_gap_site(int pos, int l, gap_site *gap_sites, int *p_tot_gap_sites, int seqrank) { int num, i; for(num = 0; num < *p_tot_gap_sites; num++) if(gap_sites[num].pos >= pos) break; if(num < *p_tot_gap_sites && gap_sites[num].pos == pos) gap_sites[num].l[seqrank-1] += l; else { if(*p_tot_gap_sites >= MAX_GAP_SITES) return; if(num < *p_tot_gap_sites) { for(i = *p_tot_gap_sites; i > num; i--) gap_sites[i] = gap_sites[i - 1]; } (*p_tot_gap_sites)++; gap_sites[num].pos = pos; gap_sites[num].l[0] = 0; gap_sites[num].l[1] = 0; gap_sites[num].l[seqrank-1] = l; } } int delete_gaps_bef_pos(char *seq, int pos, int number, int length, int totsegments, int offset) { int i; if(number == 0) return length; memmove(seq + pos - number, seq + pos, length - pos + 2); for(i=0; i <= totsegments; i++) if(segment_x_ou_y(i, offset) + segments[i].longueur - 1 >= pos ) segment_x_ou_y(i, offset) -= number; return length - number; } int insert_gaps_bef_pos(char *seq, int pos, int number, int length, int totsegments, int offset, int maxlen) { int i; if(length + number > maxlen) return length; memmove(seq + pos + number, seq + pos, length - pos + 2); memset(seq + pos, '-', number); for(i=0; i <= totsegments; i++) if(segment_x_ou_y(i, offset) + segments[i].longueur - 1 >= pos ) segment_x_ou_y(i, offset) += number; return length + number; } int dispatch_gaps_bef(int pos, int number, char *seq, gap_site * gap_sites, int *p_tot_gap_sites, int offset, int seqlen, int totsegments, int seqrank, char *other_seq, int *other_seqlen, int other_offset, int maxlen) { int site, lnextgap, other_rank, i, seuil; site = find_next_gap_site(pos + number, gap_sites, *p_tot_gap_sites); if(site != -1) { if(gap_sites[site].l[seqrank-1] >= number) { seqlen = delete_gaps_bef_pos(seq, gap_sites[site].pos, number, seqlen, totsegments, offset); seqlen = insert_gaps_bef_pos(seq, pos, number, seqlen, totsegments, offset, maxlen); gap_sites[site].l[seqrank-1] -= number; } else { lnextgap = gap_sites[site].l[seqrank-1]; other_rank = (seqrank == 1 ? 2 : 1); seqlen = delete_gaps_bef_pos(seq, gap_sites[site].pos, lnextgap, seqlen, totsegments, offset); *other_seqlen = insert_gaps_bef_pos(other_seq, gap_sites[site].pos, number - lnextgap, *other_seqlen, totsegments, other_offset, maxlen); seqlen = insert_gaps_bef_pos(seq, pos, number, seqlen, totsegments, offset, maxlen); gap_sites[site].l[seqrank-1] = 0; gap_sites[site].l[other_rank-1] += number - lnextgap; seuil = gap_sites[site].pos; for(i = 0; i < *p_tot_gap_sites; i++) { if(gap_sites[i].pos < seuil) continue; gap_sites[i].pos += number - lnextgap; } } } else { seqlen = insert_gaps_bef_pos(seq, pos, number, seqlen, totsegments, offset, maxlen); } new_gap_site(pos + number, number, gap_sites, p_tot_gap_sites, seqrank); return seqlen; } void align_callback(Fl_Widget *ob, void *data) { int number, offset_1, offset_2; FD_matpt *matpt = (FD_matpt *)data; if(matpt->hitx == matpt->hity) return; my_watch_cursor(ob->window()); offset_1 = (char *)&(segments[0].x) - (char *)&(segments[0]); offset_2 = (char *)&(segments[0].y) - (char *)&(segments[0]); if(matpt->hitx > matpt->hity) { number = matpt->hitx - matpt->hity; matpt->seqlong2 = dispatch_gaps_bef(matpt->hity, number, matpt->seq2, matpt->gap_sites, &(matpt->tot_gap_sites), offset_2, matpt->seqlong2, matpt->totsegments, 2, matpt->seq1, &matpt->seqlong1, offset_1, matpt->maxseqlength); matpt->hity = matpt->hitx; } else { number = matpt->hity - matpt->hitx; matpt->seqlong1 = dispatch_gaps_bef(matpt->hitx, number, matpt->seq1, matpt->gap_sites, &(matpt->tot_gap_sites), offset_1, matpt->seqlong1, matpt->totsegments, 1, matpt->seq2, &matpt->seqlong2, offset_2, matpt->maxseqlength); matpt->hitx = matpt->hity; } matpt->longmax = FL_max(matpt->seqlong1, matpt->seqlong2); center_view_on_hit(matpt); matpt->mat_panel->redraw(); matpt->x_slider->redraw(); matpt->y_slider->redraw(); compute_region_text(matpt); compute_title(matpt); matpt->modif_but_not_saved = TRUE; } void update_col_lines(int num, SEA_VIEW *view) { int l, i, res; int (*calc_color_function)(int); if(view->numb_gc == 1) return; calc_color_function = ( view->protein ? get_color_for_aa : get_color_for_base ); l = view->each_length[num]; for(i=0; isequence[num][i]; view->col_rank[num][i] = (char)calc_color_function( res ); } } void record_alignment_callback(Fl_Widget *ob, void *data) { int num1, num2, site, need_big_gaps = FALSE, seqrank, num, ngaps, newlength; FD_matpt *matpt = (FD_matpt *)data; SEA_VIEW *view = (SEA_VIEW *)matpt->seaview_data; Fl_Menu_ *menu = (Fl_Menu_ *)matpt->choice_ref_seq; if( ! menu->mvalue() ) { fl_message("Please, select which is the reference sequence"); return; } seqrank = menu->value(); my_watch_cursor(ob->window()); for(site = 0; site < matpt->tot_gap_sites; site++) { if(matpt->gap_sites[site].l[seqrank] != 0) { need_big_gaps = TRUE; break; } } for(num1 = 0; num1 < view->tot_seqs; num1++) if(view->sel_seqs[num1]) break; for(num2 = num1 + 1; num2 < view->tot_seqs; num2++) if(view->sel_seqs[num2]) break; memcpy(view->sequence[num1], matpt->seq1 + 1, matpt->seqlong1 + 1); view->each_length[num1] = matpt->seqlong1; update_col_lines(num1, view); memcpy(view->sequence[num2], matpt->seq2 + 1, matpt->seqlong2 + 1); view->each_length[num2] = matpt->seqlong2; update_col_lines(num2, view); if( need_big_gaps ) { newlength = FL_max(matpt->seqlong1, matpt->seqlong2); for(site = 0; site < matpt->tot_gap_sites; site++) { ngaps = matpt->gap_sites[site].l[seqrank]; if( ngaps == 0) continue; for(num = 0; num < view->tot_seqs; num++) { if( view->sel_seqs[num] ) continue; insert_gaps_at(view, num+1, matpt->gap_sites[site].pos - ngaps, ngaps); newlength = FL_max(newlength, view->each_length[num]); } matpt->gap_sites[site].l[seqrank] = 0; insert_region_part(view, matpt->gap_sites[site].pos - ngaps, ngaps); } update_current_seq_length(newlength, view); view->horsli->redraw(); } set_seaview_modified(view, TRUE); matpt->modif_but_not_saved = FALSE; view->DNA_obj->redraw(); fl_reset_cursor(ob->window()); } void matpt_idle_cb(FD_matpt *matpt) { static char err_seg[]="Only part of the dot plot was computed"; #ifdef __APPLE__ const int step = 100; // on Mac OS, idle callbacks are slow to be called, so better give them more work #else const int step = 1; #endif int i, deb, fin, nmatch, finw, diff, lfrag, k, pp, d, deb1, fin1, fin2, deb2, pxd, pxf, pyd, pyf, erreur = FALSE; int kk0 = matpt->kk; if ( !matpt->form->visible() ) { goto label_fin; } matpt->form->make_current(); if (matpt->interrupted) { goto label_fin; } fl_push_clip(matpt->mat_panel->x(), matpt->mat_panel->y(), matpt->mat_panel->w(), matpt->mat_panel->h()); for (; matpt->kk < kk0 + step && matpt->kk <= matpt->dmax + 1; matpt->kk++) { /* pour faire la boucle k = [dmin,dmax] en partant du centre et s'eloignant */ matpt->flip = - matpt->flip; k = matpt->centre + ((matpt->kk - matpt->dmin)/2) * matpt->flip; deb= ( k>=0 ? k+1 : 1); fin= FL_min( matpt->seqlong2_nogaps+k , matpt->seqlong1_nogaps); /*on met it[1] ssi bases egales en majuscu dans les 2 seqs sur la diagonale k*/ for(i = deb; i <= fin; i++) { diff = matpt->seq1[matpt->addgaps1[i]] - matpt->seq2[matpt->addgaps2[i-k]]; matpt->it[i] = (diff == 0 || diff == 32 || diff == -32 ? 1 : 0); } matpt->it[fin + 1] = 0; /* on met it[1] ssi au moins matpt->identites bases egales dans fenetre de taille fenetre sur la diagonale k */ pp=matpt->it[deb]; nmatch=0; for (i = deb; i < deb+matpt->fenetre; i++) nmatch += matpt->it[i]; if(nmatch>=matpt->identites) matpt->it[deb]=1; else matpt->it[deb]=0; finw = fin-matpt->fenetre+1; for(i = deb+1; i <= finw; i++) { nmatch += (matpt->it[i+matpt->fenetre-1]-pp); pp=matpt->it[i]; if(nmatch>=matpt->identites) matpt->it[i]=1; else matpt->it[i]=0; } i=deb-1; /* calcul de d = debut des runs de 1, i = suivant de la fin du run de 1 */ while(iit[i]==0) continue; d=i; do { i++; if(i>finw) break; } while(matpt->it[i]==1); /* decoupage du segment sans gaps en autant de morceaux non coupes de gaps */ deb1 = matpt->addgaps1[d]; deb2 = matpt->addgaps2[d-k]; lfrag = 0; do { fin1 = deb1; fin2 = deb2; while(lfrag < i - d && matpt->seq1[fin1] != '-' && matpt->seq2[fin2] != '-') { fin1++; fin2++; lfrag++; } fin1--; fin2--; if (matpt->totsegments >= MAXSEGMENTS) { erreur = TRUE; fl_pop_clip(); goto label_fin; } matpt->totsegments++; segments[matpt->totsegments].x = deb1; segments[matpt->totsegments].y = deb2; segments[matpt->totsegments].longueur = fin1 - deb1 + 1; log_to_phys(segments[matpt->totsegments].x, segments[matpt->totsegments].y, &pxd, &pyd, matpt); log_to_phys(segments[matpt->totsegments].x + segments[matpt->totsegments].longueur, segments[matpt->totsegments].y + segments[matpt->totsegments].longueur, &pxf, &pyf, matpt); fl_line(pxd, pyd, pxf, pyf); deb1 = fin1+1; deb2 = fin2+1; while(matpt->seq1[deb1] == '-') deb1++; while(matpt->seq2[deb2] == '-') deb2++; } while(lfrag < i - d); } } fl_pop_clip(); if (matpt->kk <= matpt->dmax + 1) return; label_fin: Fl::remove_idle((Fl_Idle_Handler)matpt_idle_cb, matpt); free(matpt->it); free(matpt->addgaps1); free(matpt->addgaps2); if (matpt->form->visible()) draw_rect(matpt); fl_reset_cursor(matpt->form); if (erreur) { fl_message("%s", err_seg); } } /* dot plot pour sequences avec gaps: les segments sont calcules sans les gaps leurs coordonnees sont reportees sur les seqs avec gaps puis ils sont coupes en autant de morceaux sans gap */ void compute_diags(FD_matpt *matpt) { int longmax; static char err_mem[]="Not enough memory"; char *p; matpt->need_compute = FALSE; matpt->seqlong1_nogaps = matpt->seqlong1; matpt->seqlong2_nogaps = matpt->seqlong2; matpt->totsegments= -1; /* calcul corresp coord sans gap -> coord avec gap */ matpt->addgaps1 = (int *)malloc( (matpt->seqlong1_nogaps+2) * sizeof(int)); matpt->addgaps2 = (int *)malloc( (matpt->seqlong2_nogaps+2) * sizeof(int)); if(matpt->addgaps1 == NULL || matpt->addgaps2 == NULL) { goto way_out; } p = matpt->seq1; matpt->seqlong1_nogaps = 0; while( *(++p) != 0) { if( *p == '-') continue; matpt->addgaps1[++matpt->seqlong1_nogaps] = p - matpt->seq1; } p = matpt->seq2; matpt->seqlong2_nogaps = 0; while( *(++p) != 0) { if( *p == '-') continue; matpt->addgaps2[++matpt->seqlong2_nogaps] = p - matpt->seq2; } matpt->dmin = matpt->fenetre-matpt->seqlong2_nogaps; matpt->dmax = matpt->seqlong1_nogaps-matpt->fenetre-1; longmax = FL_max(matpt->seqlong1_nogaps, matpt->seqlong2_nogaps); matpt->it = (int *)malloc( (longmax + 2) * sizeof(int)); if(matpt->it == NULL) { goto way_out; } matpt->centre = (matpt->dmin + matpt->dmax)/2; matpt->flip = 1; matpt->kk = matpt->dmin + 1; Fl::add_idle((Fl_Idle_Handler)matpt_idle_cb, matpt); return; way_out: fl_message("%s", err_mem); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/FL/Fl_Native_File_Chooser.H�����������������������������������������������������������������000644 �000765 �000024 �00000021064 12410305022 017716� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef FL_NATIVE_FILE_CHOOSER_H #define FL_NATIVE_FILE_CHOOSER_H #include #if defined(USE_NEW_FLTK_FEATURES) && FL_PATCH_VERSION < 3 #undef FL_PATCH_VERSION #define FL_PATCH_VERSION 3 #endif #define SEAVIEW_FLTK_VERSION 100*FL_MAJOR_VERSION + 10*FL_MINOR_VERSION + FL_PATCH_VERSION #if SEAVIEW_FLTK_VERSION < 133 && !(defined(__APPLE__) || defined(WIN32)) #define Fl_Native_File_Chooser mgFl_Native_File_Chooser #endif #define USE_GTK_FILE_CHOOSER 1 /* forces use of GTK file chooser when available */ // Use Windows' chooser #ifdef WIN32 // #define _WIN32_WINNT 0x0501 // needed for OPENFILENAME's 'FlagsEx' # include # include // malloc # include # include // OPENFILENAME, GetOpenFileName() # include // BROWSEINFO, SHBrowseForFolder() #endif // Use Apple's chooser #ifdef __APPLE__ # define MAXFILTERS 80 #endif // All else falls back to FLTK's own chooser #if ! defined(__APPLE__) && !defined(WIN32) # include #else # include // FL_EXPORT #endif class mgFl_FLTK_File_Chooser; class mgFl_GTK_File_Chooser; class FL_EXPORT Fl_Native_File_Chooser { public: enum Type { BROWSE_FILE = 0, ///< browse files (lets user choose one file) BROWSE_DIRECTORY, ///< browse directories (lets user choose one directory) BROWSE_MULTI_FILE, ///< browse files (lets user choose multiple files) BROWSE_MULTI_DIRECTORY, ///< browse directories (lets user choose multiple directories) BROWSE_SAVE_FILE, ///< browse to save a file BROWSE_SAVE_DIRECTORY ///< browse to save a directory }; enum Option { NO_OPTIONS = 0x0000, ///< no options enabled SAVEAS_CONFIRM = 0x0001, ///< Show native 'Save As' overwrite confirm dialog (if supported) NEW_FOLDER = 0x0002, ///< Show 'New Folder' icon (if supported) PREVIEW = 0x0004, ///< enable preview mode USE_FILTER_EXT = 0x0008 ///< Chooser filter pilots the output file extension }; /** Localizable message */ static const char *file_exists_message; public: Fl_Native_File_Chooser(int val=BROWSE_FILE); ~Fl_Native_File_Chooser(); // Public methods void type(int t); int type() const ; void options(int o); int options() const; int count() const; const char *filename() const ; const char *filename(int i) const ; void directory(const char *val) ; const char *directory() const; void title(const char *t); const char* title() const; const char *filter() const ; void filter(const char *f); int filters() const ; void filter_value(int i) ; int filter_value() const ; void preset_file(const char*f) ; const char* preset_file() const; const char *errmsg() const ; int show() ; #ifdef WIN32 private: int _btype; // kind-of browser to show() int _options; // general options OPENFILENAMEW _ofn; // GetOpenFileName() & GetSaveFileName() struct BROWSEINFO _binf; // SHBrowseForFolder() struct char **_pathnames; // array of pathnames int _tpathnames; // total pathnames char *_directory; // default pathname to use char *_title; // title for window char *_filter; // user-side search filter char *_parsedfilt; // filter parsed for Windows dialog int _nfilters; // number of filters parse_filter counted char *_preset_file; // the file to preselect char *_errmsg; // error message // Private methods void errmsg(const char *msg); void clear_pathnames(); void set_single_pathname(const char *s); void add_pathname(const char *s); void FreePIDL(LPITEMIDLIST pidl); void ClearOFN(); void ClearBINF(); void Win2Unix(char *s); void Unix2Win(char *s); int showfile(); static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data); int showdir(); void parse_filter(const char *); void clear_filters(); void add_filter(const char *, const char *); #endif #ifdef __APPLE__ private: int _btype; // kind-of browser to show() int _options; // general options void *_panel; char **_pathnames; // array of pathnames int _tpathnames; // total pathnames char *_directory; // default pathname to use char *_title; // title for window char *_preset_file; // the 'save as' filename char *_filter; // user-side search filter, eg: // C Files\t*.[ch]\nText Files\t*.txt" char *_filt_names; // filter names (tab delimited) // eg. "C Files\tText Files" char *_filt_patt[MAXFILTERS]; // array of filter patterns, eg: // _filt_patt[0]="*.{cxx,h}" // _filt_patt[1]="*.txt" int _filt_total; // parse_filter() # of filters loaded int _filt_value; // index of the selected filter char *_errmsg; // error message // Private methods void errmsg(const char *msg); void clear_pathnames(); void set_single_pathname(const char *s); int get_saveas_basename(void); void clear_filters(); void add_filter(const char *, const char *); void parse_filter(const char *from); int post(); int runmodal(); #endif #if ! defined(__APPLE__) && !defined(WIN32) private: #if FLTK_ABI_VERSION <= 10302 int _btype; // kind-of browser to show() int _options; // general options int _nfilters; char *_filter; // user supplied filter char *_parsedfilt; // parsed filter int _filtvalue; // selected filter char *_preset_file; char *_prevvalue; // Returned filename char *_directory; char *_errmsg; // error message #endif static int have_looked_for_GTK_libs; union { mgFl_FLTK_File_Chooser *_x11_file_chooser; mgFl_GTK_File_Chooser *_gtk_file_chooser; }; #endif }; #if !defined(__APPLE__) && !defined(WIN32) class mgFl_FLTK_File_Chooser { friend class mgFl_Native_File_Chooser; protected: int _btype; // kind-of browser to show() int _options; // general options int _nfilters; char *_filter; // user supplied filter char *_parsedfilt; // parsed filter int _filtvalue; // selected filter char *_preset_file; char *_prevvalue; // Returned filename char *_directory; char *_errmsg; // error message mgFl_FLTK_File_Chooser(int val); virtual ~mgFl_FLTK_File_Chooser(); void errmsg(const char *msg); int type_fl_file(int); void parse_filter(); int exist_dialog(); Fl_File_Chooser *_file_chooser; virtual void type(int); int type() const; void options(int); int options() const; virtual int count() const; virtual const char *filename() const; virtual const char *filename(int i) const; void directory(const char *val); const char *directory() const; virtual void title(const char *); virtual const char* title() const; const char *filter() const; void filter(const char *); int filters() const; void filter_value(int i); int filter_value() const; void preset_file(const char*); const char* preset_file() const; const char *errmsg() const; virtual int show(); }; #ifdef USE_GTK_FILE_CHOOSER class mgFl_GTK_File_Chooser : public mgFl_FLTK_File_Chooser { friend class mgFl_Native_File_Chooser; private: typedef struct _GtkWidget GtkWidget; typedef struct _GtkFileFilterInfo GtkFileFilterInfo; struct pair { mgFl_GTK_File_Chooser* running; // the running mgFl_GTK_File_Chooser const char *filter; // a filter string of the chooser pair(mgFl_GTK_File_Chooser* c, const char *f) { running = c; filter = strdup(f); }; ~pair() { free((char*)filter); }; }; GtkWidget *gtkw_ptr; // used to hold a GtkWidget* without pulling GTK into everything... void *gtkw_slist; // used to hold a GLib GSList... unsigned gtkw_count; // number of files read back - if any mutable char *gtkw_filename; // last name we read back char *gtkw_title; // the title to be applied to the dialog const char *previous_filter; int fl_gtk_chooser_wrapper(); // method that wraps the GTK widget mgFl_GTK_File_Chooser(int val); virtual ~mgFl_GTK_File_Chooser(); static int did_find_GTK_libs; static void probe_for_GTK_libs(void); virtual void type(int); virtual int count() const; virtual const char *filename() const; virtual const char *filename(int i) const; virtual void title(const char *); virtual const char* title() const; virtual int show(); void changed_output_type(const char *filter); static int custom_gtk_filter_function(const GtkFileFilterInfo*, mgFl_GTK_File_Chooser::pair*); static void free_pair(pair *p); }; #endif // USE_GTK_FILE_CHOOSER #endif // !defined(__APPLE__) && !defined(WIN32) #endif /*FL_NATIVE_FILE_CHOOSER_H*/ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seaview/FL/Fl_Native_File_Chooser_common.cxx��������������������������������������������������������000644 �000765 �000024 �00000003643 12611177215 021722� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������// "$Id: Fl_Native_File_Chooser_common.cxx 10064 2014-01-16 16:10:19Z manolo $" // // FLTK native OS file chooser widget // // Copyright 1998-2010 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php // // Please report all bugs and problems to: // // http://www.fltk.org/str.php // #include #include // COPY A STRING WITH 'new' // Value can be NULL // static char *strnew(const char *val) { if ( val == NULL ) return(NULL); char *s = new char[strlen(val)+1]; strcpy(s, val); return(s); } // FREE STRING CREATED WITH strnew(), NULLS OUT STRING // Value can be NULL // static char *strfree(char *val) { if ( val ) delete [] val; return(NULL); } // 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER // Returns newly allocated string, or NULL // if s && val == NULL. // 's' can be NULL; returns a strnew(val). // 'val' can be NULL; s is returned unmodified. // // Usage: // char *s = strnew("foo"); // s = "foo" // s = strapp(s, "bar"); // s = "foobar" // #if !defined(WIN32) static char *strapp(char *s, const char *val) { if ( ! val ) { return(s); // Nothing to append? return s } if ( ! s ) { return(strnew(val)); // New string? return copy of val } char *news = new char[strlen(s)+strlen(val)+1]; strcpy(news, s); strcat(news, val); delete [] s; // delete old string return(news); // return new copy } #endif // APPEND A CHARACTER TO A STRING // This does NOT allocate space for the new character. // static void chrcat(char *s, char c) { char tmp[2] = { c, '\0' }; strcat(s, tmp); } // // End of "$Id: Fl_Native_File_Chooser_common.cxx 10064 2014-01-16 16:10:19Z manolo $". // ���������������������������������������������������������������������������������������������seaview/FL/Fl_Native_File_Chooser_FLTK.cxx����������������������������������������������������������000644 �000765 �000024 �00000036007 12410305046 021162� 0����������������������������������������������������������������������������������������������������ustar�00mgouy���������������������������staff���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #if SEAVIEW_FLTK_VERSION < 133 #include #include "Fl_Native_File_Chooser_common.cxx" #ifdef USE_GTK_FILE_CHOOSER # include "Fl_Native_File_Chooser_GTK.cxx" #endif #include #include // TMP until GTK chooser is integrated in FLTK const char *mgFl_Native_File_Chooser::file_exists_message = "File exists. Are you sure you want to overwrite?"; int mgFl_Native_File_Chooser::have_looked_for_GTK_libs = 0; /** The constructor. Internally allocates the native widgets. Optional \p val presets the type of browser this will be, which can also be changed with type(). */ mgFl_Native_File_Chooser::mgFl_Native_File_Chooser(int val) { #if FLTK_ABI_VERSION <= 10302 _btype = val; _options = NO_OPTIONS; _filter = NULL; _filtvalue = 0; _parsedfilt = NULL; _preset_file = NULL; _prevvalue = NULL; _directory = NULL; _errmsg = NULL; #endif // FLTK_ABI_VERSION #ifdef USE_GTK_FILE_CHOOSER if(have_looked_for_GTK_libs == 0) { // First Time here, try to find the GTK libs if they are installed mgFl_GTK_File_Chooser::probe_for_GTK_libs(); have_looked_for_GTK_libs = -1; } // if we found all the GTK functions we need, we will use the GtkFileChooserDialog if (mgFl_GTK_File_Chooser::did_find_GTK_libs) _gtk_file_chooser = new mgFl_GTK_File_Chooser(val); else #endif // USE_GTK_FILE_CHOOSER _x11_file_chooser = new mgFl_FLTK_File_Chooser(val); } /** Destructor. Deallocates any resources allocated to this widget. */ mgFl_Native_File_Chooser::~mgFl_Native_File_Chooser() { delete _x11_file_chooser; } /** Sets the current mgFl_Native_File_Chooser::Type of browser. */ void mgFl_Native_File_Chooser::type(int t) { return _x11_file_chooser->type(t); } /** Gets the current mgFl_Native_File_Chooser::Type of browser. */ int mgFl_Native_File_Chooser::type() const { return _x11_file_chooser->type(); } /** Sets the platform specific chooser options to \p val. \p val is expected to be one or more mgFl_Native_File_Chooser::Option flags ORed together. Some platforms have OS-specific functions that can be enabled/disabled via this method.

\code Flag Description Win Mac Other -------------- ----------------------------------------------- ------- ------- ------- NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used USE_FILTER_EXT Chooser filter pilots the output file extension. Ignored Used Ignored \endcode */ void mgFl_Native_File_Chooser::options(int o) { _x11_file_chooser->options(o); } /** Gets the platform specific mgFl_Native_File_Chooser::Option flags. */ int mgFl_Native_File_Chooser::options() const { return _x11_file_chooser->options(); } /** Returns the number of filenames (or directory names) the user selected.

\b Example: \code if ( fnfc->show() == 0 ) { // Print all filenames user selected for (int n=0; ncount(); n++ ) { printf("%d) '%s'\n", n, fnfc->filename(n)); } } \endcode */ int mgFl_Native_File_Chooser::count() const { return _x11_file_chooser->count(); } /** Return the filename the user chose. Use this if only expecting a single filename. If more than one filename is expected, use filename(int) instead. Return value may be "" if no filename was chosen (eg. user cancelled). */ const char *mgFl_Native_File_Chooser::filename() const { return _x11_file_chooser->filename(); } /** Return one of the filenames the user selected. Use count() to determine how many filenames the user selected.

\b Example: \code if ( fnfc->show() == 0 ) { // Print all filenames user selected for (int n=0; ncount(); n++ ) { printf("%d) '%s'\n", n, fnfc->filename(n)); } } \endcode */ const char *mgFl_Native_File_Chooser::filename(int i) const { return _x11_file_chooser->filename(i); } /** Preset the directory the browser will show when opened. If \p val is NULL, or no directory is specified, the chooser will attempt to use the last non-cancelled folder. */ void mgFl_Native_File_Chooser::directory(const char *val) { _x11_file_chooser->directory(val); } /** Returns the current preset directory() value. */ const char *mgFl_Native_File_Chooser::directory() const { return _x11_file_chooser->directory(); } /** Set the title of the file chooser's dialog window. Can be NULL if no title desired. The default title varies according to the platform, so you are advised to set the title explicitly. */ void mgFl_Native_File_Chooser::title(const char *t) { _x11_file_chooser->title(t); } /** Get the title of the file chooser's dialog window. Return value may be NULL if no title was set. */ const char* mgFl_Native_File_Chooser::title() const { return _x11_file_chooser->title(); } /** Returns the filter string last set. Can be NULL if no filter was set. */ const char *mgFl_Native_File_Chooser::filter() const { return _x11_file_chooser->filter(); } /** Sets the filename filters used for browsing. The default is NULL, which browses all files.

The filter string can be any of:

- A single wildcard (eg. "*.txt") - Multiple wildcards (eg. "*.{cxx,h,H}") - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt")

The format of each filter is a wildcard, or an optional user description followed by '\\t' and the wildcard.

On most platforms, each filter is available to the user via a pulldown menu in the file chooser. The 'All Files' option is always available to the user. */ void mgFl_Native_File_Chooser::filter(const char *f) { _x11_file_chooser->filter(f); } /** Gets how many filters were available, not including "All Files" */ int mgFl_Native_File_Chooser::filters() const { return _x11_file_chooser->filters(); } /** Sets which filter will be initially selected. The first filter is indexed as 0. If filter_value()==filters(), then "All Files" was chosen. If filter_value() > filters(), then a custom filter was set. */ void mgFl_Native_File_Chooser::filter_value(int i) { _x11_file_chooser->filter_value(i); } /** Returns which filter value was last selected by the user. This is only valid if the chooser returns success. */ int mgFl_Native_File_Chooser::filter_value() const { return _x11_file_chooser->filter_value(); } /** Sets the default filename for the chooser. Use directory() to set the default directory. Mainly used to preset the filename for save dialogs, and on most platforms can be used for opening files as well. */ void mgFl_Native_File_Chooser::preset_file(const char* f) { _x11_file_chooser->preset_file(f); } /** Get the preset filename. */ const char* mgFl_Native_File_Chooser::preset_file() const { return _x11_file_chooser->preset_file(); } /** Returns a system dependent error message for the last method that failed. This message should at least be flagged to the user in a dialog box, or to some kind of error log. Contents will be valid only for methods that document errmsg() will have info on failures. */ const char *mgFl_Native_File_Chooser::errmsg() const { return _x11_file_chooser->errmsg(); } /** Post the chooser's dialog. Blocks until dialog has been completed or cancelled. \returns - 0 -- user picked a file - 1 -- user cancelled - -1 -- failed; errmsg() has reason */ int mgFl_Native_File_Chooser::show() { return _x11_file_chooser->show(); } mgFl_FLTK_File_Chooser::mgFl_FLTK_File_Chooser(int val) { _btype = 0; _options = 0; _filter = NULL; _filtvalue = 0; _parsedfilt = NULL; _preset_file = NULL; _prevvalue = NULL; _directory = NULL; _errmsg = NULL; _file_chooser= NULL; if (val >= 0) { _file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); type(val); // do this after _file_chooser created } _nfilters = 0; } mgFl_FLTK_File_Chooser::~mgFl_FLTK_File_Chooser() { delete _file_chooser; _file_chooser = NULL; _filter = strfree(_filter); _parsedfilt = strfree(_parsedfilt); _preset_file = strfree(_preset_file); _prevvalue = strfree(_prevvalue); _directory = strfree(_directory); _errmsg = strfree(_errmsg); } // PRIVATE: SET ERROR MESSAGE void mgFl_FLTK_File_Chooser::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // PRIVATE: translate Native types to Fl_File_Chooser types int mgFl_FLTK_File_Chooser::type_fl_file(int val) { switch (val) { case mgFl_Native_File_Chooser::BROWSE_FILE: return(Fl_File_Chooser::SINGLE); case mgFl_Native_File_Chooser::BROWSE_DIRECTORY: return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); case mgFl_Native_File_Chooser::BROWSE_MULTI_FILE: return(Fl_File_Chooser::MULTI); case mgFl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); case mgFl_Native_File_Chooser::BROWSE_SAVE_FILE: return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); case mgFl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI | Fl_File_Chooser::CREATE); default: return(Fl_File_Chooser::SINGLE); } } void mgFl_FLTK_File_Chooser::type(int val) { _btype = val; _file_chooser->type(type_fl_file(val)); } int mgFl_FLTK_File_Chooser::type() const { return(_btype); } void mgFl_FLTK_File_Chooser::options(int val) { _options = val; } int mgFl_FLTK_File_Chooser::options() const { return(_options); } int mgFl_FLTK_File_Chooser::show() { // FILTER if ( _parsedfilt ) { _file_chooser->filter(_parsedfilt); } // FILTER VALUE // Set this /after/ setting the filter // _file_chooser->filter_value(_filtvalue); // DIRECTORY if ( _directory && _directory[0] ) { _file_chooser->directory(_directory); } else { _file_chooser->directory(_prevvalue); } // PRESET FILE if ( _preset_file ) { _file_chooser->value(_preset_file); } // OPTIONS: PREVIEW _file_chooser->preview( (options() & mgFl_Native_File_Chooser::PREVIEW) ? 1 : 0); // SHOW _file_chooser->show(); // BLOCK WHILE BROWSER SHOWN while ( _file_chooser->shown() ) { Fl::wait(); } if ( _file_chooser->value() && _file_chooser->value()[0] ) { _prevvalue = strfree(_prevvalue); _prevvalue = strnew(_file_chooser->value()); _filtvalue = _file_chooser->filter_value(); // update filter value // HANDLE SHOWING 'SaveAs' CONFIRM if ( options() & mgFl_Native_File_Chooser::SAVEAS_CONFIRM && type() == mgFl_Native_File_Chooser::BROWSE_SAVE_FILE ) { struct stat buf; if ( stat(_file_chooser->value(), &buf) != -1 ) { if ( buf.st_mode & S_IFREG ) { // Regular file + exists? if ( exist_dialog() == 0 ) { return(1); } } } } } if ( _file_chooser->count() ) return(0); else return(1); } const char *mgFl_FLTK_File_Chooser::errmsg() const { return(_errmsg ? _errmsg : "No error"); } const char* mgFl_FLTK_File_Chooser::filename() const { if ( _file_chooser->count() > 0 ) { return(_file_chooser->value()); } return(""); } const char* mgFl_FLTK_File_Chooser::filename(int i) const { if ( i < _file_chooser->count() ) return(_file_chooser->value(i+1)); // convert fltk 1 based to our 0 based return(""); } void mgFl_FLTK_File_Chooser::title(const char *val) { _file_chooser->label(val); } const char *mgFl_FLTK_File_Chooser::title() const { return(_file_chooser->label()); } void mgFl_FLTK_File_Chooser::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); parse_filter(); } const char *mgFl_FLTK_File_Chooser::filter() const { return(_filter); } int mgFl_FLTK_File_Chooser::filters() const { return(_nfilters); } void mgFl_FLTK_File_Chooser::filter_value(int val) { _filtvalue = val; } int mgFl_FLTK_File_Chooser::filter_value() const { return _filtvalue; } int mgFl_FLTK_File_Chooser::count() const { return _file_chooser->count(); } void mgFl_FLTK_File_Chooser::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } const char *mgFl_FLTK_File_Chooser::directory() const { return _directory; } // PRIVATE: Convert our filter format to fltk's chooser format // FROM TO (FLTK) // ------------------------- -------------------------- // "*.cxx" "*.cxx Files(*.cxx)" // "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})" // "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)" // // Returns a modified version of the filter that the caller is responsible // for freeing with strfree(). // void mgFl_FLTK_File_Chooser::parse_filter() { _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) _nfilters = 0; char *in = _filter; if ( !in ) return; int has_name = strchr(in, '\t') ? 1 : 0; char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard char wildcard[1024] = ""; // parsed wildcard char name[1024] = ""; // Parse filter user specified for ( ; 1; in++ ) { /*** DEBUG printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", *in, mode, name, wildcard); ***/ switch (*in) { // FINISHED PARSING NAME? case '\t': if ( mode != 'n' ) goto regchar; mode = 'w'; break; // ESCAPE NEXT CHAR case '\\': ++in; goto regchar; // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? case '\r': case '\n': case '\0': // APPEND NEW FILTER TO LIST if ( wildcard[0] ) { // OUT: "name(wild)\tname(wild)" char comp[2048]; sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""), name, wildcard); _parsedfilt = strapp(_parsedfilt, comp); _nfilters++; //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt); } // RESET wildcard[0] = name[0] = '\0'; mode = strchr(in, '\t') ? 'n' : 'w'; // DONE? if ( *in == '\0' ) return; // done else continue; // not done yet, more filters // Parse all other chars default: // handle all non-special chars regchar: // handle regular char switch ( mode ) { case 'n': chrcat(name, *in); continue; case 'w': chrcat(wildcard, *in); continue; } break; } } //NOTREACHED } void mgFl_FLTK_File_Chooser::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } const char* mgFl_FLTK_File_Chooser::preset_file() const { return _preset_file; } int mgFl_FLTK_File_Chooser::exist_dialog() { return fl_choice("%s", fl_cancel, fl_ok, NULL, mgFl_Native_File_Chooser::file_exists_message); } #endif // SEAVIEW_FLTK_VERSION < 133 seaview/FL/Fl_Native_File_Chooser_GTK.cxx000644 000765 000024 00000062644 12410305065 021056 0ustar00mgouystaff000000 000000 #include #include // for dlopen et al #include // for setlocale /* --------------------- Type definitions from GLIB and GTK --------------------- */ /* all of this is from the public gnome API, so unlikely to change */ #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif typedef void* gpointer; typedef int gint; typedef unsigned int guint; typedef unsigned long gulong; typedef gint gboolean; typedef char gchar; typedef struct _GSList GSList; struct _GSList { gpointer data; GSList *next; }; #define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) typedef struct _GtkWidget GtkWidget; typedef struct _GtkFileChooser GtkFileChooser; typedef struct _GtkDialog GtkDialog; typedef struct _GtkWindow GtkWindow; typedef struct _GdkDrawable GdkWindow; typedef struct _GtkFileFilter GtkFileFilter; typedef struct _GtkToggleButton GtkToggleButton; typedef enum { GTK_FILE_FILTER_FILENAME = 1 << 0, GTK_FILE_FILTER_URI = 1 << 1, GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, GTK_FILE_FILTER_MIME_TYPE = 1 << 3 } GtkFileFilterFlags; struct _GtkFileFilterInfo { GtkFileFilterFlags contains; const gchar *filename; const gchar *uri; const gchar *display_name; const gchar *mime_type; }; typedef struct _GtkFileFilterInfo GtkFileFilterInfo; typedef gboolean (*GtkFileFilterFunc) (const GtkFileFilterInfo *filter_info, gpointer data); typedef void (*GDestroyNotify)(gpointer data); typedef enum { GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER } GtkFileChooserAction; #define GTK_STOCK_CANCEL "gtk-cancel" #define GTK_STOCK_SAVE "gtk-save" #define GTK_STOCK_OPEN "gtk-open" const int GTK_RESPONSE_NONE = -1; const int GTK_RESPONSE_ACCEPT = -3; const int GTK_RESPONSE_DELETE_EVENT = -4; const int GTK_RESPONSE_CANCEL = -6; typedef void (*GCallback)(void); #define G_CALLBACK(f) ((GCallback) (f)) typedef int GConnectFlags; typedef struct _GClosure GClosure; typedef void (*GClosureNotify)(gpointer data, GClosure *closure); /* --------------------- End of Type definitions from GLIB and GTK --------------------- */ int mgFl_GTK_File_Chooser::did_find_GTK_libs = 0; /* These are the GTK/GLib methods we want to load, but not call by name...! */ // void g_free (gpointer mem); typedef void (*XX_g_free)(gpointer); static XX_g_free fl_g_free = NULL; // gpointer g_slist_nth_data (GSList *list, guint n); typedef gpointer (*XX_g_slist_nth_data) (GSList *, guint); static XX_g_slist_nth_data fl_g_slist_nth_data = NULL; // guint g_slist_length (GSList *list); typedef guint (*XX_g_slist_length) (GSList *); static XX_g_slist_length fl_g_slist_length = NULL; // void g_slist_free (GSList *list); typedef void (*XX_g_slist_free) (GSList *); static XX_g_slist_free fl_g_slist_free = NULL; // gboolean gtk_init_check (int *argc, char ***argv); typedef gboolean (*XX_gtk_init_check)(int *, char ***); static XX_gtk_init_check fl_gtk_init_check = NULL; // void gtk_widget_destroy (GtkWidget *widget); typedef void (*XX_gtk_widget_destroy) (GtkWidget *); static XX_gtk_widget_destroy fl_gtk_widget_destroy = NULL; // void gtk_file_chooser_set_select_multiple(GtkFileChooser *chooser, gboolean select_multiple); typedef void (*XX_gtk_file_chooser_set_select_multiple)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_select_multiple fl_gtk_file_chooser_set_select_multiple = NULL; // void gtk_file_chooser_set_do_overwrite_confirmation(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); typedef void (*XX_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_do_overwrite_confirmation fl_gtk_file_chooser_set_do_overwrite_confirmation = NULL; // void gtk_file_chooser_set_current_name (GtkFileChooser *chooser, const gchar *name); typedef void (*XX_gtk_file_chooser_set_current_name)(GtkFileChooser *, const gchar *); static XX_gtk_file_chooser_set_current_name fl_gtk_file_chooser_set_current_name = NULL; // void gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *name); typedef void (*XX_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); static XX_gtk_file_chooser_set_current_folder fl_gtk_file_chooser_set_current_folder = NULL; // void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser, gboolean create_folders); typedef void (*XX_gtk_file_chooser_set_create_folders) (GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_create_folders fl_gtk_file_chooser_set_create_folders = NULL; // gboolean gtk_file_chooser_get_select_multiple(GtkFileChooser *chooser); typedef gboolean (*XX_gtk_file_chooser_get_select_multiple)(GtkFileChooser *); static XX_gtk_file_chooser_get_select_multiple fl_gtk_file_chooser_get_select_multiple = NULL; // void gtk_widget_hide(GtkWidget *widget); typedef void (*XX_gtk_widget_hide)(GtkWidget *); static XX_gtk_widget_hide fl_gtk_widget_hide = NULL; // gchar * gtk_file_chooser_get_filename(GtkFileChooser *chooser); typedef gchar* (*XX_gtk_file_chooser_get_filename)(GtkFileChooser *); static XX_gtk_file_chooser_get_filename fl_gtk_file_chooser_get_filename = NULL; // GSList * gtk_file_chooser_get_filenames(GtkFileChooser *chooser); typedef GSList* (*XX_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); static XX_gtk_file_chooser_get_filenames fl_gtk_file_chooser_get_filenames = NULL; // gboolean gtk_main_iteration(void); typedef gboolean (*XX_gtk_main_iteration)(void); static XX_gtk_main_iteration fl_gtk_main_iteration = NULL; // gboolean gtk_events_pending(void); typedef gboolean (*XX_gtk_events_pending)(void); static XX_gtk_events_pending fl_gtk_events_pending = NULL; // GtkWidget * gtk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); typedef GtkWidget* (*XX_gtk_file_chooser_dialog_new)(const gchar *, GtkWindow *, GtkFileChooserAction, const gchar *, ...); static XX_gtk_file_chooser_dialog_new fl_gtk_file_chooser_dialog_new = NULL; // void gtk_file_chooser_add_filter(GtkFileChooser*, GtkFileFilter*); typedef void (*XX_gtk_file_chooser_add_filter)(GtkFileChooser*, GtkFileFilter*); static XX_gtk_file_chooser_add_filter fl_gtk_file_chooser_add_filter = NULL; // GtkFileFilter* gtk_file_chooser_get_filter(GtkFileChooser*); typedef GtkFileFilter* (*XX_gtk_file_chooser_get_filter)(GtkFileChooser*); static XX_gtk_file_chooser_get_filter fl_gtk_file_chooser_get_filter = NULL; // void gtk_file_chooser_set_filter(GtkFileChooser*, GtkFileFilter*); typedef void (*XX_gtk_file_chooser_set_filter)(GtkFileChooser*, GtkFileFilter*); static XX_gtk_file_chooser_set_filter fl_gtk_file_chooser_set_filter = NULL; // GtkFileFilter * gtk_file_filter_new(); typedef GtkFileFilter* (*XX_gtk_file_filter_new)(void); static XX_gtk_file_filter_new fl_gtk_file_filter_new = NULL; // void gtk_file_filter_add_pattern(GtkFileFilter*, const gchar*); typedef void (*XX_gtk_file_filter_add_pattern)(GtkFileFilter*, const gchar*); static XX_gtk_file_filter_add_pattern fl_gtk_file_filter_add_pattern = NULL; // void gtk_file_filter_add_custom(GtkFileFilter *filter, GtkFileFilterFlags needed, // GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); typedef void (*XX_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); static XX_gtk_file_filter_add_custom fl_gtk_file_filter_add_custom = NULL; // void gtk_file_filter_set_name(GtkFileFilter*, const gchar*); typedef void (*XX_gtk_file_filter_set_name)(GtkFileFilter*, const gchar*); static XX_gtk_file_filter_set_name fl_gtk_file_filter_set_name = NULL; // const gchar* gtk_file_filter_get_name(GtkFileFilter*); typedef const gchar* (*XX_gtk_file_filter_get_name)(GtkFileFilter*); static XX_gtk_file_filter_get_name fl_gtk_file_filter_get_name = NULL; // void gtk_file_chooser_set_extra_widget(GtkFileChooser *, GtkWidget *); typedef void (*XX_gtk_file_chooser_set_extra_widget)(GtkFileChooser *, GtkWidget *); static XX_gtk_file_chooser_set_extra_widget fl_gtk_file_chooser_set_extra_widget = NULL; // void gtk_widget_show_now(GtkWidget *); typedef void (*XX_gtk_widget_show_now)(GtkWidget *); static XX_gtk_widget_show_now fl_gtk_widget_show_now = NULL; // GdkWindow* gtk_widget_get_window(GtkWidget *); typedef GdkWindow* (*XX_gtk_widget_get_window)(GtkWidget *); static XX_gtk_widget_get_window fl_gtk_widget_get_window = NULL; // Window gdk_x11_drawable_get_xid(GdkWindow *); typedef Window (*XX_gdk_x11_drawable_get_xid)(GdkWindow *); static XX_gdk_x11_drawable_get_xid fl_gdk_x11_drawable_get_xid = NULL; // GtkWidget *gtk_check_button_new_with_label(const gchar *); typedef GtkWidget* (*XX_gtk_check_button_new_with_label)(const gchar *); static XX_gtk_check_button_new_with_label fl_gtk_check_button_new_with_label = NULL; // gulong g_signal_connect_data(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); typedef gulong (*XX_g_signal_connect_data)(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); static XX_g_signal_connect_data fl_g_signal_connect_data = NULL; // gboolean gtk_toggle_button_get_active(GtkToggleButton *); typedef gboolean (*XX_gtk_toggle_button_get_active)(GtkToggleButton*); static XX_gtk_toggle_button_get_active fl_gtk_toggle_button_get_active = NULL; // void gtk_file_chooser_set_show_hidden(GtkFileChooser *, gboolean); typedef void (*XX_gtk_file_chooser_set_show_hidden)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_show_hidden fl_gtk_file_chooser_set_show_hidden = NULL; // gboolean gtk_file_chooser_get_show_hidden(GtkFileChooser *); typedef gboolean (*XX_gtk_file_chooser_get_show_hidden)(GtkFileChooser *); static XX_gtk_file_chooser_get_show_hidden fl_gtk_file_chooser_get_show_hidden = NULL; // void gtk_toggle_button_set_active(GtkToggleButton *, gboolean); typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; mgFl_GTK_File_Chooser::mgFl_GTK_File_Chooser(int val) : mgFl_FLTK_File_Chooser(-1) { gtkw_ptr = NULL; // used to hold a GtkWidget* gtkw_slist = NULL; // will hold the returned file names in a multi-selection... gtkw_count = 0; // How many items were selected? gtkw_filename = NULL; // holds the last name we read back in a single file selection... gtkw_title = NULL; // dialog title _btype = val; previous_filter = NULL; } mgFl_GTK_File_Chooser::~mgFl_GTK_File_Chooser() { // Should free up resources taken for... if(gtkw_ptr) { fl_gtk_widget_destroy (gtkw_ptr); gtkw_ptr = NULL; } if(gtkw_filename) { fl_g_free(gtkw_filename); gtkw_filename = NULL; } if(gtkw_slist) { GSList *iter = (GSList *)gtkw_slist; while(iter) { if(iter->data) fl_g_free(iter->data); iter = g_slist_next(iter); } fl_g_slist_free((GSList *)gtkw_slist); gtkw_slist = NULL; } gtkw_count = 0; // assume we have no files selected now gtkw_title = strfree(gtkw_title); } void mgFl_GTK_File_Chooser::type(int val) { _btype = val; } int mgFl_GTK_File_Chooser::count() const { return gtkw_count; } const char *mgFl_GTK_File_Chooser::filename() const { if(gtkw_ptr) { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { return gtkw_filename; } else { GSList *iter = (GSList *)gtkw_slist; char *nm = (char *)iter->data; return nm; } } return(""); } const char *mgFl_GTK_File_Chooser::filename(int i) const { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { return gtkw_filename; } else { if ((unsigned)i < gtkw_count) { GSList *iter = (GSList *)gtkw_slist; char *nm = (char *)fl_g_slist_nth_data(iter, i); return nm; } } return(""); } void mgFl_GTK_File_Chooser::title(const char *val) { strfree(gtkw_title); gtkw_title = strnew(val); } const char* mgFl_GTK_File_Chooser::title() const { return gtkw_title; } /* changes the extension of the outfile in the chooser according to newly selected filter */ void mgFl_GTK_File_Chooser::changed_output_type(const char *filter) { if ( !(options()&Fl_Native_File_Chooser::USE_FILTER_EXT) ) return; if (strchr(filter, '(') || strchr(filter, '{') || strchr(filter+1, '*') || strncmp(filter, "*.", 2)) return; const char *p = fl_gtk_file_chooser_get_filename((GtkFileChooser*)gtkw_ptr); if (!p) return; p = fl_filename_name(p); const char *q = strrchr(p, '.'); if (!q) q = p + strlen(p); char *r = new char[strlen(p) + strlen(filter)]; strcpy(r, p); strcpy(r + (q - p), filter + 1); fl_gtk_file_chooser_set_current_name((GtkFileChooser*)gtkw_ptr, r); delete[] r; } /* Filters files before display in chooser. Also used to detect when the filter just changed */ gboolean mgFl_GTK_File_Chooser::custom_gtk_filter_function(const GtkFileFilterInfo *info, mgFl_GTK_File_Chooser::pair* p) { if (p->running->previous_filter != p->filter) { p->running->changed_output_type(p->filter); p->running->previous_filter = p->filter; } return (gboolean)fl_filename_match(info->filename, p->filter); } void mgFl_GTK_File_Chooser::free_pair(mgFl_GTK_File_Chooser::pair *p) { delete p; } static void hidden_files_cb(GtkToggleButton *togglebutton, gpointer user_data) { gboolean state = fl_gtk_toggle_button_get_active(togglebutton); fl_gtk_file_chooser_set_show_hidden((GtkFileChooser*)user_data, state); } int mgFl_GTK_File_Chooser::show() { // The point here is that after running a GTK dialog, the calling program's current locale is modified. // To avoid that, we memorize the calling program's current locale, and the locale as modified // by GTK after the first dialog use. We restore the calling program's current locale // before returning, and we set the locale as modified by GTK before subsequent GTK dialog uses. static bool first = true; char *p; char *before = NULL; static char *gtk_wants = NULL; // record in before the calling program's current locale p = setlocale(LC_ALL, NULL); if (p) before = strdup(p); if (gtk_wants) { // set the locale as GTK 'wants it' setlocale(LC_ALL, gtk_wants); } int retval = fl_gtk_chooser_wrapper(); // may change the locale if (first) { first = false; // record in gtk_wants the locale as modified by the GTK dialog p = setlocale(LC_ALL, NULL); if (p) gtk_wants = strdup(p); } if (before) { setlocale(LC_ALL, before); // restore calling program's current locale free(before); } return retval; } static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer data) { gint *ri = (gint *)data; *ri = response_id; } int mgFl_GTK_File_Chooser::fl_gtk_chooser_wrapper() { int result = 1; static int have_gtk_init = 0; if(!have_gtk_init) { have_gtk_init = -1; int ac = 0; fl_gtk_init_check(&ac, NULL); } if(gtkw_ptr) { // discard the previous dialog widget fl_gtk_widget_destroy (gtkw_ptr); gtkw_ptr = NULL; } // set the dialog action type GtkFileChooserAction gtw_action_type; switch (_btype) { case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: gtw_action_type = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: gtw_action_type = GTK_FILE_CHOOSER_ACTION_SAVE; break; case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: gtw_action_type = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: case Fl_Native_File_Chooser::BROWSE_FILE: default: gtw_action_type = GTK_FILE_CHOOSER_ACTION_OPEN; break; } // create a new dialog gtkw_ptr = fl_gtk_file_chooser_dialog_new (gtkw_title, NULL, /* parent_window */ gtw_action_type, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, gtw_action_type == GTK_FILE_CHOOSER_ACTION_SAVE || gtw_action_type == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); // did we create a valid dialog widget? if(!gtkw_ptr) { // fail return -1; } // set the dialog properties switch (_btype) { case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: fl_gtk_file_chooser_set_select_multiple((GtkFileChooser *)gtkw_ptr, TRUE); break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: if (_preset_file)fl_gtk_file_chooser_set_current_name ((GtkFileChooser *)gtkw_ptr, fl_filename_name(_preset_file)); /* FALLTHROUGH */ case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: fl_gtk_file_chooser_set_create_folders((GtkFileChooser *)gtkw_ptr, TRUE); fl_gtk_file_chooser_set_do_overwrite_confirmation ((GtkFileChooser *)gtkw_ptr, (_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)?TRUE:FALSE); break; case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_FILE: default: break; } if (_directory && _directory[0]) fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, _directory); GtkFileFilter **filter_tab = NULL; if (_parsedfilt) { filter_tab = new GtkFileFilter*[_nfilters]; char *filter = strdup(_parsedfilt); char *p = strtok(filter, "\t"); int count = 0; while (p) { filter_tab[count] = fl_gtk_file_filter_new(); fl_gtk_file_filter_set_name(filter_tab[count], p); p = strchr(p, '(') + 1; char *q = strchr(p, ')'); *q = 0; fl_gtk_file_filter_add_custom(filter_tab[count], GTK_FILE_FILTER_FILENAME, (GtkFileFilterFunc)mgFl_GTK_File_Chooser::custom_gtk_filter_function, new mgFl_GTK_File_Chooser::pair(this, p), (GDestroyNotify)mgFl_GTK_File_Chooser::free_pair); fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, filter_tab[count]); p = strtok(NULL, "\t"); count++; } free(filter); fl_gtk_file_chooser_set_filter((GtkFileChooser *)gtkw_ptr, filter_tab[_filtvalue]); previous_filter = NULL; if (gtw_action_type == GTK_FILE_CHOOSER_ACTION_OPEN) { GtkFileFilter* gfilter = fl_gtk_file_filter_new(); fl_gtk_file_filter_set_name(gfilter, Fl_File_Chooser::all_files_label); fl_gtk_file_filter_add_pattern(gfilter, "*"); fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, gfilter); } } GtkWidget *toggle = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label); fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, toggle); fl_g_signal_connect_data(toggle, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags) 0); Fl_Window* firstw = Fl::first_window(); fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen if (firstw) { GdkWindow* gdkw = fl_gtk_widget_get_window(gtkw_ptr); Window xw = fl_gdk_x11_drawable_get_xid(gdkw); // get the X11 ref of the GTK window XSetTransientForHint(fl_display, xw, fl_xid(firstw)); // set the GTK window transient for the last FLTK win } gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr); fl_gtk_toggle_button_set_active((GtkToggleButton *)toggle, state); gint response_id = GTK_RESPONSE_NONE; fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags) 0); while (response_id == GTK_RESPONSE_NONE) { // loop that shows the GTK dialog window fl_gtk_main_iteration(); // one iteration of the GTK event loop while (XEventsQueued(fl_display, QueuedAfterReading)) { // emulate modal dialog XEvent xevent; XNextEvent(fl_display, &xevent); if (!fl_find(xevent.xany.window)) continue; // skip events to non-FLTK windows if ( xevent.type == Expose ) fl_handle(xevent); // ignore non Expose events } Fl::flush(); // do the drawings needed after Expose events } if (response_id == GTK_RESPONSE_ACCEPT) { if (_parsedfilt) { GtkFileFilter *gfilter = fl_gtk_file_chooser_get_filter((GtkFileChooser *)gtkw_ptr); for (_filtvalue = 0; _filtvalue < _nfilters; _filtvalue++) { if (filter_tab[_filtvalue] == gfilter) break; } } // discard any filenames or lists from previous calls if(gtkw_filename) { fl_g_free(gtkw_filename); gtkw_filename = NULL; } if(gtkw_slist) { GSList *iter = (GSList *)gtkw_slist; while(iter) { if(iter->data) fl_g_free(iter->data); iter = g_slist_next(iter); } fl_g_slist_free((GSList *)gtkw_slist); gtkw_slist = NULL; } gtkw_count = 0; // assume we have no files selected now if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { gtkw_filename = fl_gtk_file_chooser_get_filename ((GtkFileChooser *)gtkw_ptr); if (gtkw_filename) { gtkw_count = 1; result = 0; //printf("single: %s\n", gtkw_filename); } } else { gtkw_slist = fl_gtk_file_chooser_get_filenames((GtkFileChooser *)gtkw_ptr); gtkw_count = fl_g_slist_length((GSList *)gtkw_slist); if(gtkw_count) result = 0; // puts("multiple"); // GSList *iter = (GSList *)gtkw_slist; // printf ("Selected %d files\n", gtkw_count); // while(iter) { // char *nm = (char *)iter->data; // printf("%s\n", nm); // iter = g_slist_next(iter); // } } } delete[] filter_tab; if ( response_id == GTK_RESPONSE_DELETE_EVENT) gtkw_ptr = NULL; else fl_gtk_widget_hide (gtkw_ptr); // I think this is analogus to doing an Fl::check() - we need this here to make sure // the GtkFileChooserDialog is removed from the display correctly while (fl_gtk_events_pending ()) fl_gtk_main_iteration (); return result; } // fl_gtk_chooser_wrapper // macro to help with the symbol loading boilerplate... #define GET_SYM(SSS, LLL) \ dlerror(); /* Clear any existing error */ \ fl_##SSS = (XX_##SSS)dlsym(LLL, #SSS); \ if ((pc_dl_error = dlerror()) != NULL) { \ fprintf(stderr, "%s\n", pc_dl_error); \ did_find_GTK_libs = 0; \ return; } static void* fl_dlopen(const char *filename1, const char *filename2) { void *ptr = dlopen(filename1, RTLD_LAZY | RTLD_GLOBAL); if (!ptr) ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); return ptr; } /* * Use dlopen to see if we can load the gtk dynamic libraries that * will allow us to create a GtkFileChooserDialog() on the fly, * without linking to the GTK libs at compile time. */ void mgFl_GTK_File_Chooser::probe_for_GTK_libs(void) { void *ptr_glib = NULL; void *ptr_gtk = NULL; # ifdef __APPLE_CC__ // allows testing on Darwin + X11 ptr_glib = dlopen("/sw/lib/libglib-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); # else ptr_glib = fl_dlopen("libglib-2.0.so", "libglib-2.0.so.0"); # endif // Try first with GTK2 # ifdef __APPLE_CC__ // allows testing on Darwin + X11 ptr_gtk = dlopen("/sw/lib/libgtk-x11-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); #else ptr_gtk = fl_dlopen("libgtk-x11-2.0.so", "libgtk-x11-2.0.so.0"); #endif if (ptr_gtk && ptr_glib) { #ifdef DEBUG puts("selected GTK-2\n"); #endif } else {// Try then with GTK3 ptr_gtk = fl_dlopen("libgtk-3.so", "libgtk-3.so.0"); #ifdef DEBUG if (ptr_gtk && ptr_glib) { puts("selected GTK-3\n"); } #endif } if((!ptr_glib) || (!ptr_gtk)) { #ifdef DEBUG puts("Failure to load libglib or libgtk"); #endif did_find_GTK_libs = 0; return; } char *pc_dl_error; // used to report errors by the GET_SYM macro... // items we need from GLib GET_SYM(g_free, ptr_glib); GET_SYM(g_slist_nth_data, ptr_glib); GET_SYM(g_slist_length, ptr_glib); GET_SYM(g_slist_free, ptr_glib); // items we need from GTK GET_SYM(gtk_init_check, ptr_gtk); GET_SYM(gtk_widget_destroy, ptr_gtk); GET_SYM(gtk_file_chooser_set_select_multiple, ptr_gtk); GET_SYM(gtk_file_chooser_set_do_overwrite_confirmation, ptr_gtk); GET_SYM(gtk_file_chooser_set_current_name, ptr_gtk); GET_SYM(gtk_file_chooser_set_current_folder, ptr_gtk); GET_SYM(gtk_file_chooser_set_create_folders, ptr_gtk); GET_SYM(gtk_file_chooser_get_select_multiple, ptr_gtk); GET_SYM(gtk_widget_hide, ptr_gtk); GET_SYM(gtk_file_chooser_get_filename, ptr_gtk); GET_SYM(gtk_file_chooser_get_filenames, ptr_gtk); GET_SYM(gtk_main_iteration, ptr_gtk); GET_SYM(gtk_events_pending, ptr_gtk); GET_SYM(gtk_file_chooser_dialog_new, ptr_gtk); GET_SYM(gtk_file_chooser_add_filter, ptr_gtk); GET_SYM(gtk_file_chooser_get_filter, ptr_gtk); GET_SYM(gtk_file_chooser_set_filter, ptr_gtk); GET_SYM(gtk_file_filter_new, ptr_gtk); GET_SYM(gtk_file_filter_add_pattern, ptr_gtk); GET_SYM(gtk_file_filter_add_custom, ptr_gtk); GET_SYM(gtk_file_filter_set_name, ptr_gtk); GET_SYM(gtk_file_filter_get_name, ptr_gtk); GET_SYM(gtk_file_chooser_set_extra_widget, ptr_gtk); GET_SYM(gtk_widget_show_now, ptr_gtk); GET_SYM(gtk_widget_get_window, ptr_gtk); GET_SYM(gdk_x11_drawable_get_xid, ptr_gtk); GET_SYM(gtk_check_button_new_with_label, ptr_gtk); GET_SYM(g_signal_connect_data, ptr_gtk); GET_SYM(gtk_toggle_button_get_active, ptr_gtk); GET_SYM(gtk_file_chooser_set_show_hidden, ptr_gtk); GET_SYM(gtk_file_chooser_get_show_hidden, ptr_gtk); GET_SYM(gtk_toggle_button_set_active, ptr_gtk); did_find_GTK_libs = 1; } // probe_for_GTK_libs seaview/csrc/bionj.c000644 000765 000024 00000027422 12404325714 015234 0ustar00mgouystaff000000 000000 /* modified from: PHYML : a program that computes maximum likelihood phylogenies from DNA or AA homologous sequences Copyright (C) Stephane Guindon. Oct 2003 onward This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . Linking PHYML statically or dynamically with other modules is making a combined work based on PHYML. Thus, the terms and conditions of the GNU General Public License cover the whole combination. In addition, as a special exception, the copyright holders of PHYML give you permission to combine PHYML with free software programs or libraries that are released under the GNU LGPL and with code included in the standard release of PHYLIP under the University of Washington license (or modified versions of such code, with unchanged license). You may copy and distribute such a system following the terms of the GNU GPL for PHYML and the licenses of the other code concerned. Note that people who make modified versions of PHYML are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU General Public License gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception. */ /* The code below is an implementation of the building tree algorithm described in "BIONJ: an improved version of the NJ algorithm based on a simple model of sequence data." (1997) O. Gascuel. Mol Biol Evol. 14:685-95. */ #include "phyml_util.h" /* included functions */ void Bionj(matrix *mat); void Finish(matrix *mat); void Compute_Sx(matrix *mat); phydbl Sum_S(matrix *mat, int i); phydbl Dist(matrix *mat, int x, int y); phydbl Q_Agglo(matrix *mat, int x, int y); phydbl Variance(matrix *mat, int x, int y); phydbl Br_Length(matrix *mat, int x, int y); void Update_Dist(matrix *mat, int x, int y); phydbl Lamda(matrix *mat, int x, int y, phydbl vxy); void Best_Pair(matrix *mat, int *x, int *y, phydbl *score); phydbl Var_Red(matrix *mat, int x, int y, int i, phydbl lamda, phydbl vxy); void Update_Tree(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl score); void Update_Mat(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl vxy, phydbl lamda); phydbl Dist_Red(matrix *mat, int x, phydbl lx, int y, phydbl ly, int i, phydbl lamda); int Bionj_Br_Length_Post(node *a, node *d, matrix *mat); void Bionj_Br_Length(matrix *mat); extern void Clean_Tree_Connections(arbre *tree); extern void Connect_One_Edge_To_Two_Nodes(node *a, node *d, edge *b, arbre *tree); extern void Free(void *p); void Bionj(matrix *mat) { int x,y,i; phydbl vxy,lx,ly,lamda,score; Clean_Tree_Connections(mat->tree); For(i,mat->tree->n_otu) mat->tip_node[i] = mat->tree->noeud[i]; mat->tree->num_curr_branch_available = 0; while(mat->r > 3) { x = y = 0; score = .0; Compute_Sx(mat); Best_Pair(mat,&x,&y,&score); vxy=Variance(mat,x,y); lx=Br_Length(mat,x,y); ly=Br_Length(mat,y,x); lamda=Lamda(mat,x,y,vxy); Update_Mat(mat,x,y,lx,ly,vxy,lamda); Update_Tree(mat,x,y,lx,ly,score); } Finish(mat); } /*********************************************************/ void Finish(matrix *mat) { phydbl dxy,dxz,dyz; int x,y,z; node *nx,*ny,*nz,*new; int i; x = y = z = -1; For(i,mat->n_otu) { if(mat->on_off[i]) { if(x < 0) x=i; else if(y < 0) y = i; else if(z < 0) z = i; } } dxy = Dist(mat,x,y); dxz = Dist(mat,x,z); dyz = Dist(mat,y,z); nx = mat->tip_node[x]; ny = mat->tip_node[y]; nz = mat->tip_node[z]; new = mat->tree->noeud[mat->curr_int]; new->num = mat->curr_int; new->v[0] = nx; new->v[1] = ny; new->v[2] = nz; nx->v[0] = new; ny->v[0] = new; nz->v[0] = new; Connect_One_Edge_To_Two_Nodes(new,nx,mat->tree->t_edges[mat->tree->num_curr_branch_available],mat->tree); mat->tree->num_curr_branch_available++; Connect_One_Edge_To_Two_Nodes(new,ny,mat->tree->t_edges[mat->tree->num_curr_branch_available],mat->tree); mat->tree->num_curr_branch_available++; Connect_One_Edge_To_Two_Nodes(new,nz,mat->tree->t_edges[mat->tree->num_curr_branch_available],mat->tree); mat->tree->num_curr_branch_available++; nx->b[0]->l = .5*(dxy-dyz+dxz); ny->b[0]->l = .5*(dyz-dxz+dxy); nz->b[0]->l = .5*(dxz-dxy+dyz); new->b[0]->l = nx->b[0]->l; new->b[1]->l = ny->b[0]->l; new->b[2]->l = nz->b[0]->l; } /*********************************************************/ void Update_Mat(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl vxy, phydbl lamda) { int i; int a,b; For(i,mat->n_otu) { if((mat->on_off[i]) && (i != x) && (i != y)) { if(x > i) { a=x; b=i; } else { a=i; b=x; } mat->dist[a][b]=Dist_Red(mat,x,lx,y,ly,i,lamda); mat->dist[b][a]=Var_Red(mat,x,y,i,lamda,vxy); } } } /*********************************************************/ void Update_Tree(matrix *mat, int x, int y, phydbl lx, phydbl ly, phydbl score) { node *new, *nx, *ny; nx = mat->tip_node[x]; ny = mat->tip_node[y]; new = mat->tree->noeud[mat->curr_int]; nx->v[0] = new; ny->v[0] = new; new->v[1] = nx; new->v[2] = ny; new->num = mat->curr_int; Connect_One_Edge_To_Two_Nodes(new,nx,mat->tree->t_edges[mat->tree->num_curr_branch_available],mat->tree); mat->tree->num_curr_branch_available++; Connect_One_Edge_To_Two_Nodes(new,ny,mat->tree->t_edges[mat->tree->num_curr_branch_available],mat->tree); mat->tree->num_curr_branch_available++; nx->b[0]->l = lx; ny->b[0]->l = ly; new->b[1]->l = lx; new->b[2]->l = ly; new->score[0] = score; nx->l[0] = lx; ny->l[0] = ly; new->l[1] = lx; new->l[2] = ly; mat->tip_node[x] = new; mat->on_off[y] = 0; mat->curr_int++; mat->r--; } /*********************************************************/ void Best_Pair(matrix *mat, int *x, int *y,phydbl *score) { int i,j/* ,n_ties */; phydbl Qmin,Qmin2; phydbl *t_Qij; /* int *ties; */ t_Qij = (phydbl *)mCalloc(mat->n_otu * mat->n_otu,sizeof(phydbl )); /* ties = (int *)mCalloc(mat->n_otu * mat->n_otu,sizeof(int )); */ Qmin = 1.e+10; For(i,mat->n_otu) { if(mat->on_off[i]) { for(j=0;jon_off[j]) { t_Qij[mat->n_otu*i+j] = Q_Agglo(mat,i,j); if(t_Qij[mat->n_otu*i+j] < Qmin - 1.E-05) { *x = i; *y = j; Qmin = t_Qij[mat->n_otu*i+j]; } } } } } /* n_ties = 0; */ /* For(i,mat->n_otu) */ /* { */ /* if(mat->on_off[i]) */ /* { */ /* for(j=0;jon_off[j]) */ /* { */ /* if((t_Qij[mat->n_otu*i+j] < Qmin + 1.E-05) && (t_Qij[mat->n_otu*i+j] > Qmin - 1.E-05)) */ /* { */ /* ties[n_ties] = mat->n_otu*i+j; */ /* n_ties++; */ /* } */ /* } */ /* } */ /* } */ /* } */ /* if(!n_ties) */ /* { */ /* printf("\n. Err in file %s at line %d\n",__FILE__,__LINE__); */ /* Warn_And_Exit(""); */ /* } */ /* /\* Useful if some pairwise distances are null *\/ */ /* if(n_ties > 1) */ /* { */ /* int cand; */ /* *x = *y = -1; */ /* cand = (int)rint(rand()/(phydbl)(RAND_MAX) * (n_ties-1)); */ /* *x = (int)(ties[cand] / mat->n_otu); */ /* *y = (int)(ties[cand] % mat->n_otu); */ /* } */ Qmin2 = 1e+10; For(i,mat->n_otu) { if((i != *y) && (i != *x) && (t_Qij[mat->n_otu*(*x)+i] < Qmin2)) Qmin2 = t_Qij[mat->n_otu*(*x)+i]; } For(i,mat->n_otu) { if((i != *y) && (i != *x) && (t_Qij[mat->n_otu*i+(*y)] < Qmin2)) Qmin2 = t_Qij[mat->n_otu*i+(*y)]; } *score = fabs(Qmin2 - Qmin)/fabs(Qmin); Free(t_Qij); /* Free(ties); */ } /*********************************************************/ void Compute_Sx(matrix *mat) { int i,j; For(i,mat->n_otu) { mat->dist[i][i] = .0; if(mat->on_off[i]) { For(j,mat->n_otu) { if((i != j) && (mat->on_off[j])) { mat->dist[i][i] += Dist(mat,i,j); } } } } } /*********************************************************/ phydbl Sum_S(matrix *mat, int i) { return mat->dist[i][i]; } /*********************************************************/ phydbl Dist(matrix *mat, int x, int y) { if(x > y) return(mat->dist[x][y]); else return(mat->dist[y][x]); } /*********************************************************/ phydbl Variance(matrix *mat, int x, int y) { if(x > y) { return(mat->dist[y][x]); } else { return(mat->dist[x][y]); } } /*********************************************************/ phydbl Br_Length(matrix *mat, int x, int y) { return .5*(Dist(mat,x,y)+ (Sum_S(mat,x)-Sum_S(mat,y))/(phydbl)(mat->r-2.)); } /*********************************************************/ phydbl Dist_Red(matrix *mat, int x, phydbl lx, int y, phydbl ly, int i, phydbl lamda) { phydbl Dui; Dui=lamda*(Dist(mat,x,i)-lx) +(1.-lamda)*(Dist(mat,y,i)-ly); return(Dui); } /*********************************************************/ phydbl Var_Red(matrix *mat, int x, int y, int i, phydbl lamda, phydbl vxy) { phydbl Vui; Vui=lamda*(Variance(mat,x,i)) +(1.-lamda)*(Variance(mat,y,i)) -lamda*(1.-lamda)*vxy; return(Vui); } /*********************************************************/ phydbl Lamda(matrix *mat, int x, int y, phydbl vxy) { phydbl lamda=0.0; int i; if(mat->method == 0) /* NJ (Saitou & Nei, 1987) */ lamda = 0.5; else /* BioNJ (Gascuel, 1997) */ { if(vxy==0.0) lamda=0.5; else { For(i,mat->n_otu) { if((x != i) && (y != i) && (mat->on_off[i])) lamda = lamda + Variance(mat,y,i) - Variance(mat,x,i); } lamda = 0.5 + lamda/(2.*(mat->r-2)*vxy); } if(lamda > 1.0) lamda = 0.5;/*1.0;*/ else if(lamda < 0.0) lamda = 0.5;/*0.0;*/ } return(lamda); } /*********************************************************/ phydbl Q_Agglo(matrix *mat, int x, int y) { phydbl Qxy; Qxy=(mat->r-2.)*Dist(mat,x,y)-Sum_S(mat,x)-Sum_S(mat,y); return(Qxy); } /*********************************************************/ void Bionj_Br_Length(matrix *mat) { int x; x = Bionj_Br_Length_Post(mat->tree->noeud[0], mat->tree->noeud[0]->v[0], mat); mat->tree->noeud[0]->b[0]->l = Dist(mat,0,x); } /*********************************************************/ int Bionj_Br_Length_Post(node *a, node *d, matrix *mat) { int i; if(d->tax) { return d->num; } else { int d_v1, d_v2; phydbl lx, ly, vxy,lamda; int x,y; d_v1 = d_v2 = -1; For(i,3) if(d->v[i] != a) {(d_v1 < 0)?(d_v1 = i):(d_v2 = i);} x = Bionj_Br_Length_Post(d,d->v[d_v1],mat); y = Bionj_Br_Length_Post(d,d->v[d_v2],mat); Compute_Sx(mat); vxy=Variance(mat,(x),(y)); lx=Br_Length(mat,(x),(y)); ly=Br_Length(mat,(y),(x)); lamda=Lamda(mat,(x),(y),vxy); Update_Mat(mat,(x),(y),lx,ly,vxy,lamda); d->b[d_v1]->l = lx; d->b[d_v2]->l = ly; mat->on_off[y] = 0; mat->r--; return x; } } /*********************************************************/ seaview/csrc/dnapars.c000644 000765 000024 00000145435 12410061533 015561 0ustar00mgouystaff000000 000000 #include "phylip.h" #include "seq.h" #include #include /* derived from file dnapars.c of PHYLIP version 3.696 with the following copyright: version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe. Copyright (c) 1993-2014, Joseph Felsenstein All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define MAXNUMTREES 1000000 /* bigger than number of user trees can be */ static jmp_buf lngjmp_env; typedef enum {more_thorough, less_thorough, rearrange_best_tree} dnapars_S_option; /* function prototypes */ extern int tree_build_interrupted; extern char *create_tmp_filename_from_C(void); extern FILE *fl_fopen_from_C(const char *fname, const char *mode); extern int fl_unlink_from_C(const char*fname); extern void awake_from_C(void); void padtosize(char *pname, char *name, int length); static void getoptions(int, dnapars_S_option ); static void allocrest(void); static void reallocchars(void); static void doinit(int, int, int, char*, dnapars_S_option); void makeweights(void); static void doinput(char** seq, char** seqname); void initdnaparsnode(node **, node **, node *, long, long, long *, long *, initops, pointarray, pointarray, Char *, Char *, FILE *); static void evaluate(node *); static void tryadd(node *, node *, node *); static void addpreorder(node *, node *, node *); void trydescendants(node *, node *, node *, node *, boolean); void trylocal(node *, node *); void trylocal2(node *, node *, node *); static void tryrearr(node *, boolean *); static void repreorder(node *, boolean *); static void rearrange(node **); static void describe(void); void dnapars_coordinates(node *, double, long *, double *); //void dnapars_printree(void); void globrearrange(void); void grandrearr(void); static void maketree(char*); void freerest(void); void load_tree(long treei); /* function prototypes */ Char infilename[FNMLNGTH], outfilename[FNMLNGTH], intreename[FNMLNGTH], *outtreename, weightfilename[FNMLNGTH]; char basechar[32]="ACMGRSVTWYHKDBNO???????????????"; node *root; long chars, col, msets, ith, njumble, jumb, maxtrees; /* chars = number of sites in actual sequences */ long inseed, inseed0; double threshold; boolean jumble, usertree, thresh, weights, thorough, rearrfirst, trout, progress, stepbox, ancseq, mulsets, justwts, firstset, mulf, multf; steptr oldweight; longer seed; pointarray treenode; /* pointers to all nodes in tree */ long *enterorder; long *zeros; /* local variables for Pascal maketree, propagated globally for C version: */ long minwhich; static double like, minsteps, bestyet, bestlike, bstlike2; boolean lastrearr, recompute; double nsteps[maxuser]; long **fsteps; node *there, *oldnufork; long *place; bestelm *bestrees; long *threshwt; baseptr nothing; gbases *garbage; node *temp, *temp1, *temp2, *tempsum, *temprm, *tempadd, *tempf, *tmp, *tmp1, *tmp2, *tmp3, *tmprm, *tmpadd; boolean *names; node *grbg; char *progname; static void getoptions(int arg_maxtrees, dnapars_S_option s_option) { /* interactively set options */ //long loopcount, loopcount2; //Char ch, ch2; //fprintf(outfile, "\nDNA parsimony algorithm, version %s\n\n",VERSION); jumble = false; njumble = 1; outgrno = 1; outgropt = false; thresh = false; //thorough = true; transvp = false; //rearrfirst = false; if (s_option == more_thorough) { thorough = true; rearrfirst = false; } else if (s_option == less_thorough) {thorough = false; rearrfirst = false; } else {thorough = false; rearrfirst = true; } maxtrees = arg_maxtrees; trout = true; usertree = false; weights = false; mulsets = false; printdata = false; progress = false; treeprint = false; stepbox = false; ancseq = false; dotdiff = true; interleaved = true; /*loopcount = 0; for (;;) { cleerhome(); printf("\nDNA parsimony algorithm, version %s\n\n",VERSION); printf("Setting for this run:\n"); printf(" U Search for best tree? %s\n", (usertree ? "No, use user trees in input file" : "Yes")); if (!usertree) { printf(" S Search option? "); if (thorough) printf("More thorough search\n"); else if (rearrfirst) printf("Rearrange on one best tree\n"); else printf("Less thorough\n"); printf(" V Number of trees to save? %ld\n", maxtrees); printf(" J Randomize input order of sequences?"); if (jumble) printf(" Yes (seed =%8ld,%3ld times)\n", inseed0, njumble); else printf(" No. Use input order\n"); } printf(" O Outgroup root?"); if (outgropt) printf(" Yes, at sequence number%3ld\n", outgrno); else printf(" No, use as outgroup species%3ld\n", outgrno); printf(" T Use Threshold parsimony?"); if (thresh) printf(" Yes, count steps up to%4.1f per site\n", threshold); else printf(" No, use ordinary parsimony\n"); printf(" N Use Transversion parsimony?"); if (transvp) printf(" Yes, count only transversions\n"); else printf(" No, count all steps\n"); printf(" W Sites weighted? %s\n", (weights ? "Yes" : "No")); printf(" M Analyze multiple data sets?"); if (mulsets) printf(" Yes, %2ld %s\n", msets, (justwts ? "sets of weights" : "data sets")); else printf(" No\n"); printf(" I Input sequences interleaved? %s\n", (interleaved ? "Yes" : "No, sequential")); printf(" 0 Terminal type (IBM PC, ANSI, none)? %s\n", ibmpc ? "IBM PC" : ansi ? "ANSI" : "(none)"); printf(" 1 Print out the data at start of run %s\n", (printdata ? "Yes" : "No")); printf(" 2 Print indications of progress of run %s\n", progress ? "Yes" : "No"); printf(" 3 Print out tree %s\n", treeprint ? "Yes" : "No"); printf(" 4 Print out steps in each site %s\n", stepbox ? "Yes" : "No"); printf(" 5 Print sequences at all nodes of tree %s\n", ancseq ? "Yes" : "No"); if (ancseq || printdata) printf(" . Use dot-differencing to display them %s\n", dotdiff ? "Yes" : "No"); printf(" 6 Write out trees onto tree file? %s\n", trout ? "Yes" : "No"); printf("\n Y to accept these or type the letter for one to change\n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); scanf("%c%*[^\n]", &ch); getchar(); if (ch == '\n') ch = ' '; uppercase(&ch); if (ch == 'Y') break; if (((!usertree) && (strchr("WSVJOTNUMI12345.60", ch) != NULL)) || (usertree && ((strchr("WSVOTNUMI12345.60", ch) != NULL)))){ switch (ch) { case 'J': jumble = !jumble; if (jumble) initjumble(&inseed, &inseed0, seed, &njumble); else njumble = 1; break; case 'O': outgropt = !outgropt; if (outgropt) initoutgroup(&outgrno, spp); break; case 'T': thresh = !thresh; if (thresh) initthreshold(&threshold); break; case 'N': transvp = !transvp; break; case 'W': weights = !weights; break; case 'M': mulsets = !mulsets; if (mulsets) { printf("Multiple data sets or multiple weights?"); loopcount2 = 0; do { printf(" (type D or W)\n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); scanf("%c%*[^\n]", &ch2); getchar(); if (ch2 == '\n') ch2 = ' '; uppercase(&ch2); countup(&loopcount2, 10); } while ((ch2 != 'W') && (ch2 != 'D')); justwts = (ch2 == 'W'); if (justwts) justweights(&msets); else initdatasets(&msets); if (!jumble) { jumble = true; initjumble(&inseed, &inseed0, seed, &njumble); } } break; case 'U': usertree = !usertree; break; case 'S': thorough = !thorough; if (!thorough) { printf("Rearrange on just one best tree?"); loopcount2 = 0; do { printf(" (type Y or N)\n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); scanf("%c%*[^\n]", &ch2); getchar(); if (ch2 == '\n') ch2 = ' '; uppercase(&ch2); countup(&loopcount2, 10); } while ((ch2 != 'Y') && (ch2 != 'N')); rearrfirst = (ch2 == 'Y'); } break; case 'V': loopcount2 = 0; do { printf("type the number of trees to save\n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); scanf("%ld%*[^\n]", &maxtrees); if (maxtrees > MAXNUMTREES) maxtrees = MAXNUMTREES; getchar(); countup(&loopcount2, 10); } while (maxtrees < 1); break; case 'I': interleaved = !interleaved; break; case '0': initterminal(&ibmpc, &ansi); break; case '1': printdata = !printdata; break; case '2': progress = !progress; break; case '3': treeprint = !treeprint; break; case '4': stepbox = !stepbox; break; case '5': ancseq = !ancseq; break; case '.': dotdiff = !dotdiff; break; case '6': trout = !trout; break; } } else printf("Not a possible option!\n"); countup(&loopcount, 100); } if (transvp) fprintf(outfile, "Transversion parsimony\n\n");*/ } /* getoptions */ static void allocrest() { long i; y = (Char **)Malloc(spp*sizeof(Char *)); for (i = 0; i < spp; i++) y[i] = (Char *)Malloc(chars*sizeof(Char)); bestrees = (bestelm *)Malloc(maxtrees*sizeof(bestelm)); for (i = 1; i <= maxtrees; i++) bestrees[i - 1].btree = (long *)Malloc(nonodes*sizeof(long)); //nayme = (naym *)Malloc(spp*sizeof(naym)); enterorder = (long *)Malloc(spp*sizeof(long)); place = (long *)Malloc(nonodes*sizeof(long)); weight = (long *)Malloc(chars*sizeof(long)); oldweight = (long *)Malloc(chars*sizeof(long)); alias = (long *)Malloc(chars*sizeof(long)); ally = (long *)Malloc(chars*sizeof(long)); location = (long *)Malloc(chars*sizeof(long)); } /* allocrest */ static void doinit(int myspp, int mychars, int arg_maxtrees, char* toevaluate, dnapars_S_option s_option) { /* initializes variables */ //inputnumbers(&spp, &chars, &nonodes, 1); spp = myspp; chars = mychars; nonodes = (spp * 2 - 1); getoptions(arg_maxtrees, s_option); usertree = (toevaluate != NULL); /*if (printdata) fprintf(outfile, "%2ld species, %3ld sites\n\n", spp, chars);*/ alloctree(&treenode, nonodes, usertree); } /* doinit */ void makeweights() { /* make up weights vector to avoid duplicate computations */ long i; for (i = 1; i <= chars; i++) { alias[i - 1] = i; oldweight[i - 1] = weight[i - 1]; ally[i - 1] = i; } sitesort(chars, weight); sitecombine(chars); sitescrunch(chars); endsite = 0; for (i = 1; i <= chars; i++) { if (ally[i - 1] == i) endsite++; } for (i = 1; i <= endsite; i++) location[alias[i - 1] - 1] = i; if (!thresh) threshold = spp; threshwt = (long *)Malloc(endsite*sizeof(long)); for (i = 0; i < endsite; i++) { weight[i] *= 10; threshwt[i] = (long)(threshold * weight[i] + 0.5); } zeros = (long *)Malloc(endsite*sizeof(long)); for (i = 0; i < endsite; i++) zeros[i] = 0; } /* makeweights */ static void doinput(char** seq, char** seqname) { /* reads the input data */ if (justwts) { if (firstset) { //inputdata(chars); y = seq; nayme = seqname; } /*for (i = 0; i < chars; i++) weight[i] = 1;*/ //inputweights(chars, weight, &weights); } else { if (!firstset){ //samenumsp(&chars, ith); reallocchars(); } //inputdata(chars); y = seq; nayme = seqname; /*for (i = 0; i < chars; i++) weight[i] = 1;*/ /*if (weights) { inputweights(chars, weight, &weights); if (printdata) printweights(outfile, 0, chars, weight, "Sites"); }*/ } makeweights(); makevalues(treenode, zeros, usertree); if (!usertree) { allocnode(&temp, zeros, endsite); allocnode(&temp1, zeros, endsite); allocnode(&temp2, zeros, endsite); allocnode(&tempsum, zeros, endsite); allocnode(&temprm, zeros, endsite); allocnode(&tempadd, zeros, endsite); allocnode(&tempf, zeros, endsite); allocnode(&tmp, zeros, endsite); allocnode(&tmp1, zeros, endsite); allocnode(&tmp2, zeros, endsite); allocnode(&tmp3, zeros, endsite); allocnode(&tmprm, zeros, endsite); allocnode(&tmpadd, zeros, endsite); } } /* doinput */ void initdnaparsnode(node **p, node **grbg, node *q, long len, long nodei, long *ntips, long *parens, initops whichinit, pointarray treenode, pointarray nodep, Char *str, Char *ch, FILE *intree) { /* initializes a node */ boolean minusread; double valyew, divisor; switch (whichinit) { case bottom: gnutreenode(grbg, p, nodei, endsite, zeros); treenode[nodei - 1] = *p; break; case nonbottom: gnutreenode(grbg, p, nodei, endsite, zeros); break; case tip: match_names_to_data (str, treenode, p, spp); break; case length: /* if there is a length, read it and discard value */ processlength(&valyew, &divisor, ch, &minusread, intree, parens); break; default: /*cases hslength,hsnolength,treewt,unittrwt,iter,*/ break; } } /* initdnaparsnode */ static void evaluate(node *r) { /* determines the number of steps needed for a tree. this is the minimum number of steps needed to evolve sequences on this tree */ long i, steps; long term; double sum; sum = 0.0; for (i = 0; i < endsite; i++) { steps = r->numsteps[i]; if ((long)steps <= threshwt[i]) term = steps; else term = threshwt[i]; sum += (double)term; if (usertree && which <= maxuser) fsteps[which - 1][i] = term; } if (usertree && which <= maxuser) { nsteps[which - 1] = sum; if (which == 1) { minwhich = 1; minsteps = sum; } else if (sum < minsteps) { minwhich = which; minsteps = sum; } } like = -sum; } /* evaluate */ static void tryadd(node *p, node *item, node *nufork) { /* temporarily adds one fork and one tip to the tree. if the location where they are added yields greater "likelihood" than other locations tested up to that time, then keeps that location as there */ long pos; double belowsum, parentsum; boolean found, collapse, changethere, trysave; if (!p->tip) { memcpy(temp->base, p->base, endsite*sizeof(long)); memcpy(temp->numsteps, p->numsteps, endsite*sizeof(long)); memcpy(temp->numnuc, p->numnuc, endsite*sizeof(nucarray)); temp->numdesc = p->numdesc + 1; if (p->back) { multifillin(temp, tempadd, 1); sumnsteps2(tempsum, temp, p->back, 0, endsite, threshwt); } else { multisumnsteps(temp, tempadd, 0, endsite, threshwt); tempsum->sumsteps = temp->sumsteps; } if (tempsum->sumsteps <= -bestyet) { if (p->back) sumnsteps2(tempsum, temp, p->back, endsite+1, endsite, threshwt); else { multisumnsteps(temp, temp1, endsite+1, endsite, threshwt); tempsum->sumsteps = temp->sumsteps; } } p->sumsteps = tempsum->sumsteps; } if (p == root) sumnsteps2(temp, item, p, 0, endsite, threshwt); else { sumnsteps(temp1, item, p, 0, endsite); sumnsteps2(temp, temp1, p->back, 0, endsite, threshwt); } if (temp->sumsteps <= -bestyet) { if (p == root) sumnsteps2(temp, item, p, endsite+1, endsite, threshwt); else { sumnsteps(temp1, item, p, endsite+1, endsite); sumnsteps2(temp, temp1, p->back, endsite+1, endsite, threshwt); } } belowsum = temp->sumsteps; multf = false; like = -belowsum; if (!p->tip && belowsum >= p->sumsteps) { multf = true; like = -p->sumsteps; } trysave = true; if (!multf && p != root) { parentsum = treenode[p->back->index - 1]->sumsteps; if (belowsum >= parentsum) trysave = false; } if (lastrearr) { changethere = true; if (like >= bstlike2 && trysave) { if (like > bstlike2) found = false; else { addnsave(p, item, nufork, &root, &grbg, multf, treenode, place, zeros); pos = 0; findtree(&found, &pos, nextree, place, bestrees); } if (!found) { collapse = collapsible(item, p, temp, temp1, temp2, tempsum, temprm, tmpadd, multf, root, zeros, treenode); if (!thorough) changethere = !collapse; if (thorough || !collapse || like > bstlike2 || (nextree == 1)) { if (like > bstlike2) { addnsave(p, item, nufork, &root, &grbg, multf, treenode, place, zeros); bestlike = bstlike2 = like; addbestever(&pos, &nextree, maxtrees, collapse, place, bestrees); } else addtiedtree(pos, &nextree, maxtrees, collapse, place, bestrees); } } } if (like >= bestyet) { if (like > bstlike2) bstlike2 = like; if (changethere && trysave) { bestyet = like; there = p; mulf = multf; } } } else if ((like > bestyet) || (like >= bestyet && trysave)) { bestyet = like; there = p; mulf = multf; } } /* tryadd */ static void addpreorder(node *p, node *item, node *nufork) { /* traverses a n-ary tree, calling function tryadd at a node before calling tryadd at its descendants */ node *q; if (p == NULL) return; tryadd(p, item, nufork); if (!p->tip) { q = p->next; while (q != p) { addpreorder(q->back, item, nufork); q = q->next; } } } /* addpreorder */ void trydescendants(node *item, node *forknode, node *parent, node *parentback, boolean trybelow) { /* tries rearrangements at parent and below parent's descendants */ node *q, *tempblw; boolean bestever=0, belowbetter, multf=0, saved, trysave; double parentsum=0, belowsum; memcpy(temp->base, parent->base, endsite*sizeof(long)); memcpy(temp->numsteps, parent->numsteps, endsite*sizeof(long)); memcpy(temp->numnuc, parent->numnuc, endsite*sizeof(nucarray)); temp->numdesc = parent->numdesc + 1; multifillin(temp, tempadd, 1); sumnsteps2(tempsum, parentback, temp, 0, endsite, threshwt); belowbetter = true; if (lastrearr) { parentsum = tempsum->sumsteps; if (-tempsum->sumsteps >= bstlike2) { belowbetter = false; bestever = false; multf = true; if (-tempsum->sumsteps > bstlike2) bestever = true; savelocrearr(item, forknode, parent, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = parent; mulf = true; } } } else if (-tempsum->sumsteps >= like) { there = parent; mulf = true; like = -tempsum->sumsteps; } if (trybelow) { sumnsteps(temp, parent, tempadd, 0, endsite); sumnsteps2(tempsum, temp, parentback, 0, endsite, threshwt); if (lastrearr) { belowsum = tempsum->sumsteps; if (-tempsum->sumsteps >= bstlike2 && belowbetter && (forknode->numdesc > 2 || (forknode->numdesc == 2 && parent->back->index != forknode->index))) { trysave = false; memcpy(temp->base, parentback->base, endsite*sizeof(long)); memcpy(temp->numsteps, parentback->numsteps, endsite*sizeof(long)); memcpy(temp->numnuc, parentback->numnuc, endsite*sizeof(nucarray)); temp->numdesc = parentback->numdesc + 1; multifillin(temp, tempadd, 1); sumnsteps2(tempsum, parent, temp, 0, endsite, threshwt); if (-tempsum->sumsteps < bstlike2) { multf = false; bestever = false; trysave = true; } if (-belowsum > bstlike2) { multf = false; bestever = true; trysave = true; } if (trysave) { if (treenode[parent->index - 1] != parent) tempblw = parent->back; else tempblw = parent; savelocrearr(item, forknode, tempblw, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -belowsum; there = tempblw; mulf = false; } } } } else if (-tempsum->sumsteps > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { if (treenode[parent->index - 1] != parent) tempblw = parent->back; else tempblw = parent; there = tempblw; mulf = false; } } } q = parent->next; while (q != parent) { if (q->back && q->back != item) { memcpy(temp1->base, q->base, endsite*sizeof(long)); memcpy(temp1->numsteps, q->numsteps, endsite*sizeof(long)); memcpy(temp1->numnuc, q->numnuc, endsite*sizeof(nucarray)); temp1->numdesc = q->numdesc; multifillin(temp1, parentback, 0); if (lastrearr) belowbetter = (-parentsum < bstlike2); if (!q->back->tip) { memcpy(temp->base, q->back->base, endsite*sizeof(long)); memcpy(temp->numsteps, q->back->numsteps, endsite*sizeof(long)); memcpy(temp->numnuc, q->back->numnuc, endsite*sizeof(nucarray)); temp->numdesc = q->back->numdesc + 1; multifillin(temp, tempadd, 1); sumnsteps2(tempsum, temp1, temp, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps >= bstlike2) { belowbetter = false; bestever = false; multf = true; if (-tempsum->sumsteps > bstlike2) bestever = true; savelocrearr(item, forknode, q->back, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = q->back; mulf = true; } } } else if (-tempsum->sumsteps >= like) { like = -tempsum->sumsteps; there = q->back; mulf = true; } } sumnsteps(temp, q->back, tempadd, 0, endsite); sumnsteps2(tempsum, temp, temp1, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps >= bstlike2) { trysave = false; multf = false; if (belowbetter) { bestever = false; trysave = true; } if (-tempsum->sumsteps > bstlike2) { bestever = true; trysave = true; } if (trysave) { if (treenode[q->back->index - 1] != q->back) tempblw = q; else tempblw = q->back; savelocrearr(item, forknode, tempblw, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = tempblw; mulf = false; } } } } else if (-tempsum->sumsteps > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { if (treenode[q->back->index - 1] != q->back) tempblw = q; else tempblw = q->back; there = tempblw; mulf = false; } } } q = q->next; } } /* trydescendants */ void trylocal(node *item, node *forknode) { /* rearranges below forknode, below descendants of forknode when there are more than 2 descendants, then unroots the back of forknode and rearranges on its descendants */ node *q; boolean bestever, multf, saved; memcpy(temprm->base, zeros, endsite*sizeof(long)); memcpy(temprm->numsteps, zeros, endsite*sizeof(long)); memcpy(temprm->oldbase, item->base, endsite*sizeof(long)); memcpy(temprm->oldnumsteps, item->numsteps, endsite*sizeof(long)); memcpy(tempf->base, forknode->base, endsite*sizeof(long)); memcpy(tempf->numsteps, forknode->numsteps, endsite*sizeof(long)); memcpy(tempf->numnuc, forknode->numnuc, endsite*sizeof(nucarray)); tempf->numdesc = forknode->numdesc - 1; multifillin(tempf, temprm, -1); if (!forknode->back) { sumnsteps2(tempsum, tempf, tempadd, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps > bstlike2) { bestever = true; multf = false; savelocrearr(item, forknode, forknode, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = forknode; mulf = false; } } } else if (-tempsum->sumsteps > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { there = forknode; mulf = false; } } } else { sumnsteps(temp, tempf, tempadd, 0, endsite); sumnsteps2(tempsum, temp, forknode->back, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps > bstlike2) { bestever = true; multf = false; savelocrearr(item, forknode, forknode, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = forknode; mulf = false; } } } else if (-tempsum->sumsteps > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { there = forknode; mulf = false; } } trydescendants(item, forknode, forknode->back, tempf, false); } q = forknode->next; while (q != forknode) { if (q->back != item) { memcpy(temp2->base, q->base, endsite*sizeof(long)); memcpy(temp2->numsteps, q->numsteps, endsite*sizeof(long)); memcpy(temp2->numnuc, q->numnuc, endsite*sizeof(nucarray)); temp2->numdesc = q->numdesc - 1; multifillin(temp2, temprm, -1); if (!q->back->tip) { trydescendants(item, forknode, q->back, temp2, true); } else { sumnsteps(temp1, q->back, tempadd, 0, endsite); sumnsteps2(tempsum, temp1, temp2, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps > bstlike2) { multf = false; bestever = true; savelocrearr(item, forknode, q->back, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = q->back; mulf = false; } } } else if ((-tempsum->sumsteps) > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { there = q->back; mulf = false; } } } } q = q->next; } } /* trylocal */ void trylocal2(node *item, node *forknode, node *other) { /* rearranges below forknode, below descendants of forknode when there are more than 2 descendants, then unroots the back of forknode and rearranges on its descendants. Used if forknode has binary descendants */ node *q; boolean bestever=0, multf, saved, belowbetter, trysave; memcpy(tempf->base, other->base, endsite*sizeof(long)); memcpy(tempf->numsteps, other->numsteps, endsite*sizeof(long)); memcpy(tempf->oldbase, forknode->base, endsite*sizeof(long)); memcpy(tempf->oldnumsteps, forknode->numsteps, endsite*sizeof(long)); tempf->numdesc = other->numdesc; if (forknode->back) trydescendants(item, forknode, forknode->back, tempf, false); if (!other->tip) { memcpy(temp->base, other->base, endsite*sizeof(long)); memcpy(temp->numsteps, other->numsteps, endsite*sizeof(long)); memcpy(temp->numnuc, other->numnuc, endsite*sizeof(nucarray)); temp->numdesc = other->numdesc + 1; multifillin(temp, tempadd, 1); if (forknode->back) sumnsteps2(tempsum, forknode->back, temp, 0, endsite, threshwt); else sumnsteps2(tempsum, NULL, temp, 0, endsite, threshwt); belowbetter = true; if (lastrearr) { if (-tempsum->sumsteps >= bstlike2) { belowbetter = false; bestever = false; multf = true; if (-tempsum->sumsteps > bstlike2) bestever = true; savelocrearr(item, forknode, other, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = other; mulf = true; } } } else if (-tempsum->sumsteps >= like) { there = other; mulf = true; like = -tempsum->sumsteps; } if (forknode->back) { memcpy(temprm->base, forknode->back->base, endsite*sizeof(long)); memcpy(temprm->numsteps, forknode->back->numsteps, endsite*sizeof(long)); } else { memcpy(temprm->base, zeros, endsite*sizeof(long)); memcpy(temprm->numsteps, zeros, endsite*sizeof(long)); } memcpy(temprm->oldbase, other->back->base, endsite*sizeof(long)); memcpy(temprm->oldnumsteps, other->back->numsteps, endsite*sizeof(long)); q = other->next; while (q != other) { memcpy(temp2->base, q->base, endsite*sizeof(long)); memcpy(temp2->numsteps, q->numsteps, endsite*sizeof(long)); memcpy(temp2->numnuc, q->numnuc, endsite*sizeof(nucarray)); if (forknode->back) { temp2->numdesc = q->numdesc; multifillin(temp2, temprm, 0); } else { temp2->numdesc = q->numdesc - 1; multifillin(temp2, temprm, -1); } if (!q->back->tip) trydescendants(item, forknode, q->back, temp2, true); else { sumnsteps(temp1, q->back, tempadd, 0, endsite); sumnsteps2(tempsum, temp1, temp2, 0, endsite, threshwt); if (lastrearr) { if (-tempsum->sumsteps >= bstlike2) { trysave = false; multf = false; if (belowbetter) { bestever = false; trysave = true; } if (-tempsum->sumsteps > bstlike2) { bestever = true; trysave = true; } if (trysave) { savelocrearr(item, forknode, q->back, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, &root, maxtrees, &nextree, multf, bestever, &saved, place, bestrees, treenode, &grbg, zeros); if (saved) { like = bstlike2 = -tempsum->sumsteps; there = q->back; mulf = false; } } } } else if (-tempsum->sumsteps > like) { like = -tempsum->sumsteps; if (-tempsum->sumsteps > bestyet) { there = q->back; mulf = false; } } } q = q->next; } } } /* trylocal2 */ static void tryrearr(node *p, boolean *success) { /* evaluates one rearrangement of the tree. if the new tree has greater "likelihood" than the old one sets success = TRUE and keeps the new tree. otherwise, restores the old tree */ node *forknode, *newfork, *other, *oldthere; double oldlike; boolean oldmulf; if (p->back == NULL) return; forknode = treenode[p->back->index - 1]; if (!forknode->back && forknode->numdesc <= 2 && alltips(forknode, p)) return; oldlike = bestyet; like = -10.0 * spp * chars; memcpy(tempadd->base, p->base, endsite*sizeof(long)); memcpy(tempadd->numsteps, p->numsteps, endsite*sizeof(long)); memcpy(tempadd->oldbase, zeros, endsite*sizeof(long)); memcpy(tempadd->oldnumsteps, zeros, endsite*sizeof(long)); if (forknode->numdesc > 2) { oldthere = there = forknode; oldmulf = mulf = true; trylocal(p, forknode); } else { findbelow(&other, p, forknode); oldthere = there = other; oldmulf = mulf = false; trylocal2(p, forknode, other); } if ((like <= oldlike) || (there == oldthere && mulf == oldmulf)) return; recompute = true; re_move(p, &forknode, &root, recompute, treenode, &grbg, zeros); if (mulf) add(there, p, NULL, &root, recompute, treenode, &grbg, zeros); else { if (forknode->numdesc > 0) getnufork(&newfork, &grbg, treenode, zeros); else newfork = forknode; add(there, p, newfork, &root, recompute, treenode, &grbg, zeros); } if (like > oldlike + LIKE_EPSILON) { *success = true; bestyet = like; } } /* tryrearr */ static void repreorder(node *p, boolean *success) { /* traverses a binary tree, calling PROCEDURE tryrearr at a node before calling tryrearr at its descendants */ node *q, *this; if (p == NULL) return; if (!p->visited) { tryrearr(p, success); p->visited = true; } if (!p->tip) { q = p; while (q->next != p) { this = q->next->back; repreorder(q->next->back,success); if (q->next->back == this) q = q->next; } } } /* repreorder */ static void rearrange(node **r) { /* traverses the tree (preorder), finding any local rearrangement which decreases the number of steps. if traversal succeeds in increasing the tree's "likelihood", PROCEDURE rearrange runs traversal again */ boolean success=true; while (success) { success = false; clearvisited(treenode); repreorder(*r, &success); } } /* rearrange */ void describe() { /* prints ancestors, steps and table of numbers of steps in each site */ /* if (treeprint) { fprintf(outfile, "\nrequires a total of %10.3f\n", like / -10.0); fprintf(outfile, "\n between and length\n"); fprintf(outfile, " ------- --- ------\n"); printbranchlengths(root); } if (stepbox) writesteps(chars, weights, oldweight, root); if (ancseq) { hypstates(chars, root, treenode, &garbage, basechar); putc('\n', outfile); } putc('\n', outfile);*/ if (trout) { col = 0; treeout3(root, nextree, &col, root); } } /* describe */ void dnapars_coordinates(node *p, double lengthsum, long *tipy, double *tipmax) { /* establishes coordinates of nodes */ node *q, *first, *last; double xx; if (p == NULL) return; if (p->tip) { p->xcoord = (long)(over * lengthsum + 0.5); p->ycoord = (*tipy); p->ymin = (*tipy); p->ymax = (*tipy); (*tipy) += down; if (lengthsum > (*tipmax)) (*tipmax) = lengthsum; return; } q = p->next; do { xx = q->v; if (xx > 100.0) xx = 100.0; dnapars_coordinates(q->back, lengthsum + xx, tipy,tipmax); q = q->next; } while (p != q); first = p->next->back; q = p; while (q->next != p) q = q->next; last = q->back; p->xcoord = (long)(over * lengthsum + 0.5); if ((p == root) || count_sibs(p) > 2) p->ycoord = p->next->next->back->ycoord; else p->ycoord = (first->ycoord + last->ycoord) / 2; p->ymin = first->ymin; p->ymax = last->ymax; } /* dnapars_coordinates */ /*void dnapars_printree() { * prints out diagram of the tree2 * long tipy; double scale, tipmax; long i; if (!treeprint) return; putc('\n', outfile); tipy = 1; tipmax = 0.0; dnapars_coordinates(root, 0.0, &tipy, &tipmax); scale = 1.0 / (long)(tipmax + 1.000); for (i = 1; i <= (tipy - down); i++) drawline3(i, scale, root); putc('\n', outfile); } * dnapars_printree * */ void globrearrange() { /* does global rearrangements */ long j; double gotlike; boolean frommulti; node *item, *nufork; recompute = true; do { //printf(" "); gotlike = bestlike = bstlike2; /* order matters here ! */ for (j = 0; j < nonodes; j++) { bestyet = -10.0 * spp * chars; if (j < spp) item = treenode[enterorder[j] -1]; else item = treenode[j]; if ((item != root) && ((j < spp) || ((j >= spp) && (item->numdesc > 0))) && !((item->back->index == root->index) && (root->numdesc == 2) && alltips(root, item))) { re_move(item, &nufork, &root, recompute, treenode, &grbg, zeros); frommulti = (nufork->numdesc > 0); clearcollapse(treenode); there = root; memcpy(tempadd->base, item->base, endsite*sizeof(long)); memcpy(tempadd->numsteps, item->numsteps, endsite*sizeof(long)); memcpy(tempadd->oldbase, zeros, endsite*sizeof(long)); memcpy(tempadd->oldnumsteps, zeros, endsite*sizeof(long)); if (frommulti){ oldnufork = nufork; getnufork(&nufork, &grbg, treenode, zeros); } addpreorder(root, item, nufork); if (frommulti) oldnufork = NULL; if (!mulf) add(there, item, nufork, &root, recompute, treenode, &grbg, zeros); else add(there, item, NULL, &root, recompute, treenode, &grbg, zeros); } /*if (progress) { if (j % ((nonodes / 72) + 1) == 0) putchar('.'); fflush(stdout); }*/ if (tree_build_interrupted) { longjmp(lngjmp_env, 0); } } /*if (progress) { putchar('\n'); }*/ } while (bestlike > gotlike); } /* globrearrange */ void load_tree(long treei) { /* restores a tree from bestrees */ long j, nextnode; boolean recompute = false; node *dummy; for (j = spp - 1; j >= 1; j--) re_move(treenode[j], &dummy, &root, recompute, treenode, &grbg, zeros); root = treenode[0]; recompute = true; add(treenode[0], treenode[1], treenode[spp], &root, recompute, treenode, &grbg, zeros); nextnode = spp + 2; for (j = 3; j <= spp; j++) { if (bestrees[treei].btree[j - 1] > 0) add(treenode[bestrees[treei].btree[j - 1] - 1], treenode[j - 1], treenode[nextnode++ - 1], &root, recompute, treenode, &grbg, zeros); else add(treenode[treenode[-bestrees[treei].btree[j-1]-1]->back->index-1], treenode[j - 1], NULL, &root, recompute, treenode, &grbg, zeros); } } void grandrearr() { /* calls global rearrangement on best trees */ long treei; boolean done; done = false; do { treei = findunrearranged(bestrees, nextree, true); if (treei < 0) done = true; else bestrees[treei].gloreange = true; if (!done) { load_tree(treei); globrearrange(); done = rearrfirst; } } while (!done); } /* grandrearr */ static void maketree(char *toevaluate) { /* constructs a binary tree from the pointers in treenode. adds each node at location which yields highest "likelihood" then rearranges the tree for greatest "likelihood" */ long i, j, numtrees, nextnode; boolean done, firsttree, goteof, haslengths; node *item, *nufork, *dummy; pointarray nodep; numtrees = 0; if (setjmp(lngjmp_env)) goto way_out; if (!usertree) { for (i = 1; i <= spp; i++) enterorder[i - 1] = i; if (jumble) randumize(seed, enterorder); recompute = true; root = treenode[enterorder[0] - 1]; add(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1], treenode[spp], &root, recompute, treenode, &grbg, zeros); /*if (progress) { printf("Adding species:\n"); writename(0, 2, enterorder); }*/ lastrearr = false; oldnufork = NULL; for (i = 3; i <= spp; i++) { bestyet = -10.0 * spp * chars; item = treenode[enterorder[i - 1] - 1]; getnufork(&nufork, &grbg, treenode, zeros); there = root; memcpy(tempadd->base, item->base, endsite*sizeof(long)); memcpy(tempadd->numsteps, item->numsteps, endsite*sizeof(long)); memcpy(tempadd->oldbase, zeros, endsite*sizeof(long)); memcpy(tempadd->oldnumsteps, zeros, endsite*sizeof(long)); addpreorder(root, item, nufork); if (!mulf) add(there, item, nufork, &root, recompute, treenode, &grbg, zeros); else add(there, item, NULL, &root, recompute, treenode, &grbg, zeros); like = bestyet; rearrange(&root); /*if (progress) { writename(i - 1, 1, enterorder); }*/ if (tree_build_interrupted) { longjmp(lngjmp_env, 0); } lastrearr = (i == spp); if (lastrearr) { bestlike = bestyet; if (jumb == 1) { bstlike2 = bestlike; nextree = 1; initbestrees(bestrees, maxtrees, true); initbestrees(bestrees, maxtrees, false); } globrearrange(); } } done = false; while (!done && findunrearranged(bestrees, nextree, true) >= 0) { grandrearr(); done = rearrfirst; } recompute = false; for (i = spp - 1; i >= 1; i--) re_move(treenode[i], &dummy, &root, recompute, treenode, &grbg, zeros); if (jumb == njumble) { collapsebestrees(&root, &grbg, treenode, bestrees, place, zeros, chars, recompute, progress); /*if (treeprint) { putc('\n', outfile); if (nextree == 2) fprintf(outfile, "One most parsimonious tree found:\n"); else fprintf(outfile, "%6ld trees in all found\n", nextree - 1); }*/ if (nextree > maxtrees + 1) { /*if (treeprint) fprintf(outfile, "here are the first %4ld of them\n", (long)maxtrees);*/ nextree = maxtrees + 1; } /*if (treeprint) putc('\n', outfile);*/ for (i = 0; i <= (nextree - 2); i++) { root = treenode[0]; add(treenode[0], treenode[1], treenode[spp], &root, recompute, treenode, &grbg, zeros); nextnode = spp + 2; for (j = 3; j <= spp; j++) { if (bestrees[i].btree[j - 1] > 0) add(treenode[bestrees[i].btree[j - 1] - 1], treenode[j - 1], treenode[nextnode++ - 1], &root, recompute, treenode, &grbg, zeros); else add(treenode[treenode[-bestrees[i].btree[j - 1]-1]->back->index-1], treenode[j - 1], NULL, &root, recompute, treenode, &grbg, zeros); } reroot(treenode[outgrno - 1], root); postorder(root); evaluate(root); treelength(root, chars, treenode); //dnapars_printree(); describe(); for (j = 1; j < spp; j++) re_move(treenode[j], &dummy, &root, recompute, treenode, &grbg, zeros); } } } else { /* Open in binary: ftell() is broken for UNIX line-endings under WIN32 */ //openfile(&intree,INTREE,"input tree", "rb",progname,intreename); //numtrees = countsemic(&intree); numtrees = 1; /*if (numtrees > 2) initseed(&inseed, &inseed0, seed); if (numtrees > MAXNUMTREES) { printf("\nERROR: number of input trees is read incorrectly from %s\n", intreename); exxit(-1); }*/ /*if (treeprint) { fprintf(outfile, "User-defined tree"); if (numtrees > 1) putc('s', outfile); fprintf(outfile, ":\n"); }*/ fsteps = (long **)Malloc(maxuser*sizeof(long *)); for (j = 1; j <= maxuser; j++) fsteps[j - 1] = (long *)Malloc(endsite*sizeof(long)); /*if (trout) fprintf(outtree, "%ld\n", numtrees);*/ nodep = NULL; which = 1; while (which <= numtrees) { char *tmpfname; firsttree = true; nextnode = 0; haslengths = true; tmpfname = strdup(create_tmp_filename_from_C()); intree = fl_fopen_from_C(tmpfname, "rb+"); fwrite(toevaluate, strlen(toevaluate), 1, intree); fflush(intree); fseek(intree, SEEK_SET, 0); treeread(intree, &root, treenode, &goteof, &firsttree, nodep, &nextnode, &haslengths, &grbg, initdnaparsnode,false,nonodes); fclose(intree); fl_unlink_from_C(tmpfname); free(tmpfname); /*if (treeprint) fprintf(outfile, "\n\n");*/ if (outgropt) reroot(treenode[outgrno - 1], root); postorder(root); evaluate(root); treelength(root, chars, treenode); //dnapars_printree(); nextree = 2; describe(); if (which < numtrees) gdispose(root, &grbg, treenode); which++; } //FClose(intree); //putc('\n', outfile); if (numtrees > 1 && chars > 1 ) standev(chars, numtrees, minwhich, minsteps, nsteps, fsteps, seed); for (j = 1; j <= maxuser; j++) free(fsteps[j - 1]); free(fsteps); } /*if (jumb == njumble) { if (progress) { printf("\nOutput written to file \"%s\"\n", outfilename); if (trout) { printf("\nTree"); if ((usertree && numtrees > 1) || (!usertree && nextree != 2)) printf("s"); printf(" also written onto file \"%s\"\n", outtreename); } } }*/ return; way_out: if (usertree) { for (j = 1; j <= maxuser; j++) free(fsteps[j - 1]); free(fsteps); } trout = false; jumb = njumble + 1; jumble = false; } /* maketree */ static void reallocchars() { /* The amount of chars can change between runs this function reallocates all the variables whose size depends on the amount of chars */ long i; for (i=0; i < spp; i++){ free(y[i]); y[i] = (Char *)Malloc(chars*sizeof(Char)); } free(weight); free(oldweight); free(alias); free(ally); free(location); weight = (long *)Malloc(chars*sizeof(long)); oldweight = (long *)Malloc(chars*sizeof(long)); alias = (long *)Malloc(chars*sizeof(long)); ally = (long *)Malloc(chars*sizeof(long)); location = (long *)Malloc(chars*sizeof(long)); } void freerest() { /* free variables that are allocated each data set */ long i; if (!usertree) { freenode(&temp); freenode(&temp1); freenode(&temp2); freenode(&tempsum); freenode(&temprm); freenode(&tempadd); freenode(&tempf); freenode(&tmp); freenode(&tmp1); freenode(&tmp2); freenode(&tmp3); freenode(&tmprm); freenode(&tmpadd); } /*for (i = 0; i < spp; i++) free(y[i]); free(y);*/ for (i = 1; i <= maxtrees; i++) free(bestrees[i - 1].btree); free(bestrees); //free(nayme); free(enterorder); free(place); free(weight); free(oldweight); free(alias); free(ally); free(location); freegrbg(&grbg); if (ancseq) freegarbage(&garbage); free(threshwt); free(zeros); freenodes(nonodes, treenode); } /* freerest */ char* dnapars(char** seq, char** seqname, int notu, int njumbles, int *pjumble_no, int *steps, char* toevaluate, int arg_maxtrees, int *bt_weights, dnapars_S_option s_option) { /* DNA parsimony by uphill search */ /* reads in spp, chars, and the data. Then calls maketree to construct the tree */ progname = "Dnapars"; //openfile(&infile,INFILE,"input file", "r",argv[0],infilename); //openfile(&outfile,OUTFILE,"output file", "w",argv[0],outfilename); //outfile = stdout; ibmpc = IBMCRT; ansi = ANSICRT; msets = 1; firstset = true; garbage = NULL; grbg = NULL; doinit(notu, strlen(seq[0]), arg_maxtrees, toevaluate, s_option); if (!toevaluate && njumbles > 0) { njumble = njumbles; jumble = true; } /*if (weights || justwts) openfile(&weightfile,WEIGHTFILE,"weights file","r",argv[0],weightfilename);*/ if (trout) { outtreename = strdup(create_tmp_filename_from_C()); //openfile(&outtree,OUTTREE,"output tree file", "w",argv[0],outtreename); outtree = fl_fopen_from_C(outtreename, "wb"); } for (ith = 1; ith <= msets; ith++) { if (!(justwts && !firstset)) allocrest(); /*if (msets > 1 && !justwts) { fprintf(outfile, "\nData set # %ld:\n\n", ith); if (progress) printf("\nData set # %ld:\n\n", ith); }*/ int i; if (bt_weights != NULL) for (i = 0; i < chars; i++) weight[i] = bt_weights[i]; else for (i = 0; i < chars; i++) weight[i] = 1; doinput(seq, seqname); if (ith == 1) firstset = false; for (jumb = 1; jumb <= njumble; jumb++) { maketree(toevaluate); if (jumble && pjumble_no) { *steps = (int)(bestlike / -10); *pjumble_no = jumb; awake_from_C(); } } if (!justwts) freerest(); } freetree(nonodes, treenode); //FClose(infile); //FClose(outfile); /*if (weights || justwts) FClose(weightfile);*/ char *tree = NULL; fclose(outtree); if (trout) { outtree = fl_fopen_from_C(outtreename, "rb"); // read tree from tmp file and return it as a char* fseek(outtree, 0, SEEK_END); long L=ftell(outtree); tree = (char*)malloc(L+1); fseek(outtree, 0, SEEK_SET); fread(tree, L, 1, outtree); tree[L] = 0; fclose(outtree); *steps = (int)(like / -10.); } fl_unlink_from_C(outtreename); free(outtreename); /*if (usertree) FClose(intree);*/ return tree; } /* DNA parsimony by uphill search */ seaview/csrc/lwl.c000644 000765 000024 00000051513 12404325714 014727 0ustar00mgouystaff000000 000000 #include #include #include #include #define check_alloc(a,b) calloc(a,b) extern int tree_build_interrupted; /* globals */ static double *rl[21]; static double *tl0[64], *tl1[64], *tl2[64], *tti0[64], *tti1[64],*tti2[64], *ttv0[64], *ttv1[64], *ttv2[64]; static int code_mt = 0; // TMP int num(char *cod) { int n1, n2, n3; //MG static const char bases[] = "ACGT"; if(strchr(bases, cod[0]) == NULL || strchr(bases, cod[1]) == NULL || strchr(bases, cod[2]) == NULL) return 64; //MG n1 = n2 = n3 = 0; if (cod[0] == 'C') n1 = 1; if (cod[1] == 'C') n2 = 1; if (cod[2] == 'C') n3 = 1; if (cod[0] == 'G') n1 = 2; if (cod[1] == 'G') n2 = 2; if (cod[2] == 'G') n3 = 2; if (cod[0] == 'T') n1 = 3; if (cod[1] == 'T') n2 = 3; if (cod[2] == 'T') n3 = 3; return 16 * n1 + 4 * n2 + n3; } int catsite (char c1, char c2, char c3, int i) { /* renvoie 0 si le site i du codon c1c2c3 est non degenere */ /* 1 2-fold degenerate */ /* 2 4-fold degenerate */ if (i == 3) { if ((c1 == 'A') && (c2 == 'T') && (c3 == 'G')) return 0; if ((c1 == 'T') && (c2 == 'G') && (c3 == 'A')) return 0; if ((c1 == 'T') && (c2 == 'G') && (c3 == 'G')) return 0; if (c2 == 'C') return 2; if ((c1 == 'C') && (c2 == 'T')) return 2; if ((c1 == 'G') && (c2 == 'T')) return 2; if ((c1 == 'G') && (c2 == 'G')) return 2; if ((c1 == 'C') && (c2 == 'G')) return 2; return 1; } if (i == 1) { if ((c1 == 'C') && (c2 == 'T') && (c3 == 'A')) return 1; if ((c1 == 'C') && (c2 == 'T') && (c3 == 'G')) return 1; if ((c1 == 'T') && (c2 == 'T') && (c3 == 'A')) return 1; if ((c1 == 'T') && (c2 == 'T') && (c3 == 'G')) return 1; if ((c1 == 'A') && (c2 == 'G') && (c3 == 'A')) return 1; if ((c1 == 'A') && (c2 == 'G') && (c3 == 'G')) return 1; if ((c1 == 'C') && (c2 == 'G') && (c3 == 'A')) return 1; if ((c1 == 'C') && (c2 == 'G') && (c3 == 'G')) return 1; return 0; } return 0; } char transf(char nt1, char nt2) { if (nt1 == nt2) { return 'S'; } if ((nt1 == 'A') && (nt2 == 'C')) return 'v'; if ((nt1 == 'A') && (nt2 == 'G')) return 'i'; if ((nt1 == 'A') && (nt2 == 'T')) return 'v'; if ((nt1 == 'G') && (nt2 == 'C')) return 'v'; if ((nt1 == 'G') && (nt2 == 'T')) return 'v'; if ((nt1 == 'C') && (nt2 == 'T')) return 'i'; if ((nt1 == 'C') && (nt2 == 'A')) return 'v'; if ((nt1 == 'G') && (nt2 == 'A')) return 'i'; if ((nt1 == 'T') && (nt2 == 'A')) return 'v'; if ((nt1 == 'C') && (nt2 == 'G')) return 'v'; if ((nt1 == 'T') && (nt2 == 'G')) return 'v'; if ((nt1 == 'T') && (nt2 == 'C')) return 'i'; printf("Erreur\n%c, %c\n", nt1, nt2); exit(0); } void titv1(char *cod1, char *cod2, double poids, double *ti, double *tv, double* l) { int i; char a, b, ci1, ci2, ci3, cj1, cj2, cj3; char transf(char, char); ci1 = cod1[0]; ci2 = cod1[1]; ci3 = cod1[2]; cj1 = cod2[0]; cj2 = cod2[1]; cj3 = cod2[2]; for (i = 0; i <= 2; i++) if (cod1[i] != cod2[i]) { l[catsite(ci1, ci2, ci3, i + 1)]+=0.5 * poids; l[catsite(cj1, cj2, cj3, i + 1)]+=0.5 * poids; a = cod1[i]; b = cod2[i]; if (transf(a, b) == 'i') { ti[catsite(ci1, ci2, ci3, i + 1)] += 0.5 * poids; ti[catsite(cj1, cj2, cj3, i + 1)] += 0.5 * poids; } else { tv[catsite(ci1, ci2, ci3, i + 1)] += 0.5 * poids; tv[catsite(cj1, cj2, cj3, i + 1)] += 0.5 * poids; } if( code_mt ) continue; /* il n'y a plus les pb de TI non-syno et de TV syno avec code_mt ! */ if (((ci2 == 'T') && (cj2 == 'T')) || ((ci2 == 'G') && (cj2 == 'G'))) { /* T ou G ensemble en pos 2 des 2 codons */ if (i==0){ /* pos 1 */ /* tous ces cas sont des transitions en un site 2-fold non-syno pour le code universel: il faut les enlever du comptage des TI 2-fold (ti[1]) et les ajouter au comptage des TV 2-fold (tv[1]) pour le code_mt ce sont des sites non dege qui ont ete traites simplement comme il faut */ if ((ci1 == 'C') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'T') && (cj2 == 'G') && (cj3 == 'A')) { ti[1] -= 0.5 * poids; /* CGA / TGA */ tv[1] += 0.5 * poids; } if ((ci1 == 'C') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'T') && (cj2 == 'G') && (cj3 == 'G')) { ti[1] -= 0.5 * poids; /* CGG / TGG */ tv[1] += 0.5 * poids; } if ((ci1 == 'A') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'G') && (cj2 == 'G') && (cj3 == 'G')) { ti[1] -= 0.5 * poids; /* AGG / GGG */ tv[1] += 0.5 * poids; } if ((ci1 == 'A') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'G') && (cj2 == 'G') && (cj3 == 'A')) { ti[1] -= 0.5 * poids; /* AGA / GGA */ tv[1] += 0.5 * poids; } if ((ci1 == 'T') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'C') && (cj2 == 'G') && (cj3 == 'A')) { ti[1] -= 0.5 * poids; /* TGA / CGA */ tv[1] += 0.5 * poids; } if ((ci1 == 'T') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'C') && (cj2 == 'G') && (cj3 == 'G')) { ti[1] -= 0.5 * poids; /* TGG / CGG */ tv[1] += 0.5 * poids; } if ((ci1 == 'G') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'A') && (cj2 == 'G') && (cj3 == 'G')) { ti[1] -= 0.5 * poids; /* GGG / AGG */ tv[1] += 0.5 * poids; } if ((ci1 == 'G') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'A') && (cj2 == 'G') && (cj3 == 'A')) { ti[1] -= 0.5 * poids; /* GGA / AGA */ tv[1] += 0.5 * poids; } /* tous ces cas sont code universel: TV syno en sites 2-fold il faut les enlever du comptage des TV 2-fold (tv[1]) et les ajouter au comptage des TI 2-fold (ti[1]) code_mt: TV non syno en site non dege qui ont ete correctement comptes */ if ((ci1 == 'C') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'A') && (cj2 == 'G') && (cj3 == 'A')) { tv[1] -= poids; /* CGA / AGA : TV syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'A') && (ci2 == 'G') && (ci3 == 'A') && (cj1 == 'C') && (cj2 == 'G') && (cj3 == 'A')) { tv[1] -= poids; /* AGA / CGA : TV syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'C') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'A') && (cj2 == 'G') && (cj3 == 'G')) { tv[1] -= poids; /* CGG / AGG : TV syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'A') && (ci2 == 'G') && (ci3 == 'G') && (cj1 == 'C') && (cj2 == 'G') && (cj3 == 'G')) { tv[1] -= poids; /* AGG / CGG : TV syno code univ, non code mt */ ti[1] += poids; } } if (i==2){ /* pos 3 */ /* tous ces cas sont code universel: des TV syno en site 2-fold il faut les enlever des TV 2-fold (iv[1]) et ajouter aux TI 2-fold (ti[1]) code_mt: ce sont des TV non syno en site 2-fold qui int ete comptees normalement */ if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'A') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'T')) { tv[1] -= poids; /* TV ATA / ATT : syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'T') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'A')) { tv[1] -= poids; /* TV ATT / ATA : syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'A') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'C')) { tv[1] -= poids; /* TV ATA / ATC : syno code univ, non code mt */ ti[1] += poids; } if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'C') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'A')) { tv[1] -= poids; /* TV ATC / ATA : syno code univ, non code mt */ ti[1] += poids; } /* ces 2 cas sont code universel: des TI non syno en site 2-fold il faut les enlever des TI 2-fold (ti[1]) et les ajouter aux TV 2-fold (tv[1]) code_mt: des TI syno en site 2-fold qui ont ete comptees normalement */ if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'A') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'G')) { ti[1] -= 0.5 * poids; /* TI ATA / ATG : non syno code univ, syno code mt */ tv[1] += 0.5 * poids; } if ((ci1 == 'A') && (ci2 == 'T') && (ci3 == 'G') && (cj1 == 'A') && (cj2 == 'T') && (cj3 == 'A')) { ti[1] -= 0.5 * poids; /* TI ATG / ATA : non syno code univ, syno code mt */ tv[1] += 0.5 * poids; } } } } } void titv2(char *cod1, char *cod2, double *ti, double *tv, double* l, int *aa, double **rl, int* pos) { char codint1[4], codint2[4]; int i, j, n, aa1, aa2, aaint1, aaint2; double l1, l2, p1, p2; void titv1(char *, char *, double, double *, double *,double*); memcpy(codint1, cod1, 3); memcpy(codint2, cod1, 3); /* codint_2_ <-- cod_1_ : no problem */ for (i = 0; i < 2; i++) { if (cod1[i] != cod2[i]){ codint1[i] = cod2[i]; break; } } for (j = i + 1; j <= 2; j++) { if (cod1[j] != cod2[j]){ codint2[j] = cod2[j]; break; } } aa1=aa[num(cod1)]; aa2=aa[num(cod2)]; aaint1=aa[num(codint1)]; aaint2=aa[num(codint2)]; l1 = *(rl[aa1] + aaint1) * *(rl[aaint1] + aa2); l2 = *(rl[aa1] + aaint2) * *(rl[aaint2] + aa2); p1 = (l1+l2)? l1 / (l1 + l2) : 0.; p2 = (l1+l2)? 1.-p1 : 0.; for (i=0;i<3;i++) if (pos[i]==0) n=i+1; l[catsite(cod1[0], cod1[1] ,cod1[2], n)]+=0.333333; l[catsite(cod2[0], cod2[1] ,cod2[2], n)]+=0.333333; l[catsite(codint1[0], codint1[1] ,codint1[2], n)]+=0.333333*p1; l[catsite(codint2[0], codint2[1] ,codint2[2], n)]+=0.333333*p2; titv1(cod1, codint1, p1, ti, tv,l); titv1(cod2, codint1, p1, ti, tv,l); titv1(cod1, codint2, p2, ti, tv,l); titv1(cod2, codint2, p2, ti, tv,l); } void titv3(char *cod1, char *cod2, double *ti, double *tv, double* l, int *aa, double **rl) { char *codint1[6], *codint2[6]; int i, j, ii,a,b,c,d,aaa,aab,aac,aad; double like[6], p[6], somli, rlab, rlbc, rlcd; void titv1(char *, char *, double, double *, double *, double*); int num(char *); for (i = 0; i < 6; i++) { if ((codint1[i] = (char *) malloc(4 * sizeof(char))) == NULL) { printf("Erreur d'allocation\n"); exit(1); } if ((codint2[i] = (char *) malloc(4 * sizeof(char))) == NULL) { printf("Erreur d'allocation\n"); exit(1); } } for (i = 0; i < 3; i++) { for (j = 0; j < 3 ; j++) if (j != i) { if ((i == 0) || ((i == 1) && (j == 0))) { ii = 3 * i + j - 1; } else { ii = 3 * i + j - 2; } /*sprintf(codint1[ii], "%s", cod1);*/ memcpy(codint1[ii], cod1, 3); *(codint1[ii] + i) = cod2[i]; /*sprintf(codint2[ii], "%s", codint1[ii]);*/ memcpy(codint2[ii], codint1[ii], 3); *(codint2[ii] + j) = cod2[j]; a=num(cod1); b=num(codint1[ii]); c=num(codint2[ii]); d=num(cod2); aaa=aa[a]; aab=aa[b]; aac=aa[c]; aad=aa[d]; rlab=*(rl[aaa]+aab); rlbc=*(rl[aab]+aac); rlcd=*(rl[aac]+aad); like[ii] = rlab*rlbc*rlcd; } } somli = 0; for (i = 0; i < 6; i++) somli += like[i]; for (i = 0; i < 6; i++) { p[i] = like[i] / somli; titv1(cod1, codint1[i], p[i], ti, tv,l); titv1(codint1[i], codint2[i], p[i], ti, tv,l); titv1(codint2[i], cod2, p[i], ti, tv,l); } } /* void prefastlwl(double **rl, double **tl0, double **tl1, double **tl2, double **tti0, double **tti1, double **tti2, double **ttv0, double **ttv1, double **ttv2) */ void prefastlwl(void) { double l[3], ti[3], tv[3]; char cod1[3], cod2[3]; int i, j, ii, jj, nbdiff, pos[3], aa[64], n1, n2, n3; void titv2(char *, char *, double *, double *, double *, int *, double **, int *pos); void titv3(char *, char *, double *, double *, double *, int *, double **); void titv1(char *, char *, double, double *, double *, double *); double minrl; /* code des acides amines: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0 F W Y H M L I V P C A G T S Q N K R E Q stop */ aa[0] = 17;/* aaa K */ aa[1] = 16;/* aac N */ aa[2] = 17;/* aag K */ aa[3] = 16;/* aat N */ aa[4] = 13;/* aca T */ aa[5] = 13;/* acc T */ aa[6] = 13;/* acg T */ aa[7] = 13;/* act T */ if(code_mt) aa[8] = 0;/* aga * */ else aa[8] = 18;/* aga R */ aa[9] = 14;/* agc S */ if(code_mt) aa[10] = 0;/* agg * */ else aa[10] = 18;/* agg R */ aa[11] = 14;/* agt S */ if(code_mt) aa[12] = 5;/* ata M */ else aa[12] = 7;/* ata I */ aa[13] = 7;/* atc I */ aa[14] = 5;/* atg M */ aa[15] = 7;/* att I */ aa[16] = 15; aa[17] = 4; aa[18] = 15; aa[19] = 4; aa[20] = 9; aa[21] = 9; aa[22] = 9; aa[23] = 9; aa[24] = 18; aa[25] = 18; aa[26] = 18; aa[27] = 18; aa[28] = 6; aa[29] = 6; aa[30] = 6; aa[31] = 6; aa[32] = 19; aa[33] = 20; aa[34] = 19; aa[35] = 20; aa[36] = 11; aa[37] = 11; aa[38] = 11; aa[39] = 11; aa[40] = 12; aa[41] = 12; aa[42] = 12; aa[43] = 12; aa[44] = 8; aa[45] = 8; aa[46] = 8; aa[47] = 8; aa[48] = 0;/* taa * */ aa[49] = 3;/* tac Y */ aa[50] = 0;/* tag * */ aa[51] = 3;/* tat Y */ aa[52] = 14;/* tca S */ aa[53] = 14;/* tcc S */ aa[54] = 14;/* tcg S */ aa[55] = 14;/* tct S */ if(code_mt) aa[56] = 2;/* tga W */ else aa[56] = 0;/* tga * */ aa[57] = 10;/* tgc */ aa[58] = 2;/* tgg W */ aa[59] = 10;/* tgt */ aa[60] = 6;/* tta */ aa[61] = 1;/* ttc */ aa[62] = 6;/* ttg */ aa[63] = 1;/* ttt */ /* ajoute par M. Gouy */ /* calcul minrl = val minimale du tableau rl */ minrl=rl[1][1]; for(i=1; i<=20; i++) for(j=i+1; j<=20; j++) if(rl[i][j] < minrl ) minrl=rl[i][j]; /* chargement rl[0][i] et rl[i][0] avec minrl correspond a aa = stop */ for(i= 0; i<=20; i++) rl[0][i] = rl[i][0] = minrl; //MG repair for (i = 0; i < 63; i++) { for (i = 0; i < 64; i++) { for (j = i; j < 64; j++) { for(ii=0;ii<3;ii++){ l[ii]=ti[ii]=tv[ii]=0; } n1 = i / 16; n2 = (i - 16 * n1) / 4; n3 = i - 16 * n1 - 4 * n2; cod1[0] = 'A'; if (n1 == 1) cod1[0] = 'C'; if (n1 == 2) cod1[0] = 'G'; if (n1 == 3) cod1[0] = 'T'; cod1[1] = 'A'; if (n2 == 1) cod1[1] = 'C'; if (n2 == 2) cod1[1] = 'G'; if (n2 == 3) cod1[1] = 'T'; cod1[2] = 'A'; if (n3 == 1) cod1[2] = 'C'; if (n3 == 2) cod1[2] = 'G'; if (n3 == 3) cod1[2] = 'T'; n1 = j / 16; n2 = (j - 16 * n1) / 4; n3 = j - 16 * n1 - 4 * n2; cod2[0] = 'A'; if (n1 == 1) cod2[0] = 'C'; if (n1 == 2) cod2[0] = 'G'; if (n1 == 3) cod2[0] = 'T'; cod2[1] = 'A'; if (n2 == 1) cod2[1] = 'C'; if (n2 == 2) cod2[1] = 'G'; if (n2 == 3) cod2[1] = 'T'; cod2[2] = 'A'; if (n3 == 1) cod2[2] = 'C'; if (n3 == 2) cod2[2] = 'G'; if (n3 == 3) cod2[2] = 'T'; nbdiff = 0; pos[0] = pos[1] = pos[2] = 0; if (cod1[0] != cod2[0]) { nbdiff++; pos[0] = 1; } if (cod1[1] != cod2[1]) { nbdiff++; pos[1] = 1; } if (cod1[2] != cod2[2]) { nbdiff++; pos[2] = 1; } if (nbdiff != 2) for (jj = 0; jj < 3; jj++) if (pos[jj] == 0) { l[catsite(cod1[0], cod1[1], cod1[2], jj + 1)] += 0.5; l[catsite(cod2[0], cod2[1], cod2[2], jj + 1)] += 0.5; } if (nbdiff == 1) titv1(cod1, cod2, 1.0, ti, tv, l); if (nbdiff == 2) titv2(cod1, cod2, ti, tv, l, aa, rl, pos); if (nbdiff == 3) titv3(cod1, cod2, ti, tv, l, aa, rl); *(tl0[i]+j)=*(tl0[j]+i)=l[0]; *(tl1[i]+j)=*(tl1[j]+i)=l[1]; *(tl2[i]+j)=*(tl2[j]+i)=l[2]; *(tti0[i]+j)=*(tti0[j]+i)=ti[0]; *(tti1[i]+j)=*(tti1[j]+i)=ti[1]; *(tti2[i]+j)=*(tti2[j]+i)=ti[2]; *(ttv0[i]+j)=*(ttv0[j]+i)=tv[0]; *(ttv1[i]+j)=*(ttv1[j]+i)=tv[1]; *(ttv2[i]+j)=*(ttv2[j]+i)=tv[2]; } } return; } int /* fastlwl(char **seq, int nbseq, int lgseq, double **ka, double **ks, double **tti0, double **tti1, double **tti2, double **ttv0, double **ttv1, double **ttv2, double **tl0, double **tl1, double **tl2, double **vka, double **vks, int* sat1, int* sat2) */ fastlwl(char **seq, int nbseq, int lgseq, double **ka, double **ks, double **vka, double **vks, int* sat1, int* sat2, int *wght) { double l[3], a[3], b[3], p[3], q[3], ti[3], tv[3], aaa[3], bb[3]; char cod1[3], cod2[3]; int i, j, ii, num1, num2, weight; *sat1=-1; *sat2=-1; if (lgseq % 3 != 0) { return 1; } for (i = 0; i < nbseq - 1; i++) { for (j = i + 1; j < nbseq; j++) { if(tree_build_interrupted) return 1; l[0] = l[1] = l[2] = 0.; ti[0] = ti[1] = ti[2] = tv[0] = tv[1] = tv[2] = 0.; for (ii = 0; ii < lgseq / 3; ii++) { weight = wght[3 * ii];//MG: use bootstrap codon weights if(weight == 0) continue; cod1[0] = *(seq[i] + 3 * ii); cod1[1] = *(seq[i] + 3 * ii + 1); cod1[2] = *(seq[i] + 3 * ii + 2); cod2[0] = *(seq[j] + 3 * ii); cod2[1] = *(seq[j] + 3 * ii + 1); cod2[2] = *(seq[j] + 3 * ii + 2); num1 = num(cod1); num2 = num(cod2); if(num1 == 64 || num2 == 64) continue;//MG ignore - or N-containing codons l[0] += weight * tl0[num1][num2]; l[1] += weight * tl1[num1][num2]; l[2] += weight * tl2[num1][num2]; ti[0] += weight * tti0[num1][num2]; ti[1] += weight * tti1[num1][num2]; ti[2] += weight * tti2[num1][num2]; tv[0] += weight * ttv0[num1][num2]; tv[1] += weight * ttv1[num1][num2]; tv[2] += weight * ttv2[num1][num2]; } for (ii = 0; ii < 3; ii++) { if (l[ii]==0.) { a[ii]=0.; b[ii]=0.; } else{ p[ii] = ti[ii] / l[ii]; q[ii] = tv[ii] / l[ii]; aaa[ii] = 1 - 2 * p[ii] - q[ii]; bb[ii] = 1 - 2 * q[ii]; /* cc[ii] = (aaa[ii] + bb[ii]) / 2; */ if (bb[ii] <= 0.) { b[ii] = -10001.; } else b[ii] = - 0.5 * (double) log(bb[ii]); //MG simpler b[ii] = 0.5 * (double) log(1./bb[ii]); if ((aaa[ii] <= 0.) || (bb[ii] <= 0.)) { a[ii] = -10001.; } else a[ii] = - 0.5 * (double) log(aaa[ii]) + 0.25 * log(bb[ii]); //MG simpler a[ii] = 0.5 * (double) log(1./aaa[ii]) - 0.25 * log(1./bb[ii]); } } if ((a[1] > -10000.) && (a[2] > -10000.) && (b[2] > -10000.) && ks){ if(l[1]+l[2]==0.) ks[i][j]=0.; else ks[i][j] = (l[1] * a[1] + l[2] * a[2]) / (l[2] + l[1]) + b[2]; } else { if (ks){ *sat1=i; *sat2=j; return 1; } } if ((a[0] > -10000.) && (b[0]> -10000.) && (b[1]> -10000.) && ka){ if(l[0]+l[1]==0.) ka[i][j]=0.; else ka[i][j] = a[0] + (l[0] * b[0] + l[1] * b[1]) / (l[0] + l[1]); } else { if (ka) { *sat1=i; *sat2=j; return 1; } } } } return 0; } /* loadrl */ /* Load rl's values = weights of aminoacids substitutions for Ka/Ks computing. */ void loadrl(void){ int i, j; for(i=0;i<64;i++){ tl0[i]=(double*)check_alloc(64, sizeof(double)); tl1[i]=(double*)check_alloc(64, sizeof(double)); tl2[i]=(double*)check_alloc(64, sizeof(double)); tti0[i]=(double*)check_alloc(64, sizeof(double)); tti1[i]=(double*)check_alloc(64, sizeof(double)); tti2[i]=(double*)check_alloc(64, sizeof(double)); ttv0[i]=(double*)check_alloc(64, sizeof(double)); ttv1[i]=(double*)check_alloc(64, sizeof(double)); ttv2[i]=(double*)check_alloc(64, sizeof(double)); } for(i=0;i<=20;i++){ rl[i]=(double*)check_alloc(21, sizeof(double)); rl[0][i]=rl[i][0]=0.; } rl[2][1]=rl[3][1]=rl[3][2]=rl[5][1]=rl[5][3]=rl[6][1]=rl[6][3]=rl[6][5]=0.382; rl[7][1]=rl[7][3]=rl[7][5]=rl[7][6]=rl[8][1]=rl[8][5]=rl[8][6]=rl[8][7]=0.382; rl[11][9]=rl[12][9]=rl[13][4]=rl[13][9]=rl[15][4]=rl[15][13]=rl[16][14]=rl[16][15]=0.382; rl[17][4]=rl[18][4]=rl[18][15]=rl[18][17]=rl[19][4]=rl[19][15]=rl[19][16]=rl[20][16]=0.382; rl[20][19]=0.382; rl[4][1]=rl[4][3]=rl[5][2]=rl[5][4]=rl[6][2]=rl[6][4]=rl[7][2]=rl[7][4]=0.343; rl[8][2]=rl[8][3]=rl[8][4]=rl[9][4]=rl[9][5]=rl[9][6]=rl[9][7]=rl[9][8]=0.343; rl[11][4]=rl[11][5]=rl[11][6]=rl[11][7]=rl[11][8]=rl[12][4]=rl[12][11]=rl[13][3]=0.343; rl[13][5]=rl[13][6]=rl[13][7]=rl[13][8]=rl[13][11]=rl[13][12]=rl[14][4]=rl[14][9]=0.343; rl[14][11]=rl[14][12]=rl[14][13]=rl[15][3]=rl[15][8]=rl[15][9]=rl[15][11]=rl[15][12]=0.343; rl[15][14]=rl[16][4]=rl[16][9]=rl[16][12]=rl[16][13]=rl[17][3]=rl[17][5]=rl[17][8]=0.343; rl[17][13]=rl[17][15]=rl[17][16]=rl[18][1]=rl[18][3]=rl[18][5]=rl[18][7]=rl[18][8]=0.343; rl[18][13]=rl[18][16]=rl[19][9]=rl[19][12]=rl[19][13]=rl[19][14]=rl[19][17]=rl[19][18]=0.343; rl[20][4]=rl[20][12]=rl[20][13]=rl[20][14]=rl[20][15]=rl[20][18]=0.343; rl[4][2]=rl[9][1]=rl[9][2]=rl[9][3]=rl[11][1]=rl[11][2]=rl[11][3]=rl[12][5]=0.128; rl[12][6]=rl[12][7]=rl[12][8]=rl[13][1]=rl[13][2]=rl[13][10]=rl[14][3]=rl[14][5]=0.128; rl[14][6]=rl[14][7]=rl[14][8]=rl[14][10]=rl[15][1]=rl[15][2]=rl[15][5]=rl[15][6]=0.128; rl[15][7]=rl[16][3]=rl[16][5]=rl[16][7]=rl[16][8]=rl[16][10]=rl[16][11]=rl[17][1]=0.128; rl[17][2]=rl[17][6]=rl[17][7]=rl[17][9]=rl[17][11]=rl[17][12]=rl[17][14]=rl[18][2]=0.128; rl[18][6]=rl[18][9]=rl[18][11]=rl[18][12]=rl[18][14]=rl[19][1]=rl[19][3]=rl[19][5]=0.128; rl[19][6]=rl[19][7]=rl[19][8]=rl[19][11]=rl[20][9]=rl[20][11]=rl[20][17]=rl[12][3]=0.128; rl[10][1]=rl[10][2]=rl[10][3]=rl[10][4]=rl[10][5]=rl[10][6]=rl[10][7]=rl[10][8]=0.040; rl[10][9]=rl[11][10]=rl[12][1]=rl[12][2]=rl[12][10]=rl[14][1]=rl[14][2]=rl[15][10]=0.040; rl[16][1]=rl[16][2]=rl[16][6]=rl[17][10]=rl[18][10]=rl[19][2]=rl[19][10]=rl[20][1]=0.040; rl[20][2]=rl[20][3]=rl[20][5]=rl[20][6]=rl[20][7]=rl[20][8]=rl[20][10]=0.040; for (i = 1; i <= 20; i++) { *(rl[i] + i) = 1.0; for (j = i + 1; j <= 20; j++) *(rl[i] + j) = *(rl[j] + i); } } seaview/csrc/md5.c000644 000765 000024 00000021617 11700350510 014606 0ustar00mgouystaff000000 000000 /* * $Id: md5.c,v 1.3 2008-11-12 09:30:52 mgouy Exp $ * * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5_Init, call MD5_Update as * needed on buffers full of bytes, and then call MD5_Final, which * will fill a supplied 16-byte array with the digest. * * Modified 12 June 2003 Jeremy Katz to handle * endianness better * */ // taken from DEBIAN package isomd5sum #include #include #ifdef WIN32 #define IS_BIG_ENDIAN 0 #else #include #if !(defined(_BIG_ENDIAN) || defined(BIG_ENDIAN)) #define IS_BIG_ENDIAN 0 #else #define IS_BIG_ENDIAN 1 #endif #endif typedef unsigned int uint32; struct MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; int doByteReverse; }; static void MD5_Transform(uint32 *buf, uint32 const *in); static void byteReverse(unsigned char *buf, unsigned longs); #ifndef ASM_MD5 /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; } while (--longs); } #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ static void MD5_Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301U; ctx->buf[1] = 0xefcdab89U; ctx->buf[2] = 0x98badcfeU; ctx->buf[3] = 0x10325476U; ctx->bits[0] = 0; ctx->bits[1] = 0; if (IS_BIG_ENDIAN) ctx->doByteReverse = 1; else ctx->doByteReverse = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ static void MD5_Update(struct MD5Context *ctx, unsigned const char *buf, unsigned len) { uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); if (ctx->doByteReverse) byteReverse(ctx->in, 16); MD5_Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); if (ctx->doByteReverse) byteReverse(ctx->in, 16); MD5_Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ static void MD5_Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); if (ctx->doByteReverse) byteReverse(ctx->in, 16); MD5_Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } if (ctx->doByteReverse) byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; MD5_Transform(ctx->buf, (uint32 *) ctx->in); if (ctx->doByteReverse) byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(struct MD5Context)); /* In case it's sensitive */ } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5_Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5_Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #endif /* function for very simple interface */ void raa_MD5String (char *in_string, char out_digest[33]) /* in_string: string to be MD5-digested out_digest: resulting digest as 32 hexadecimal digits plus final NULL */ { struct MD5Context context; unsigned int len = strlen (in_string); char *p; int i; unsigned char digest[16]; MD5_Init (&context); MD5_Update (&context, (unsigned const char *)in_string, len); MD5_Final (digest, &context); p = out_digest; for (i = 0; i < 16; i++) { sprintf (p, "%02x", digest[i]); p += 2; } } seaview/csrc/misc_acnuc.c000644 000765 000024 00000044052 12610205370 016227 0ustar00mgouystaff000000 000000 #include #include #include #include #if defined(WIN32) #include #elif defined(unix) || defined(__APPLE__) #define unixlike #include #endif /* included functions */ int trim_key(char *name); /* remove trailing spaces */ void padtosize(char *pname, char *name, int length); char *get_code_descr(int code); int calc_codon_number(char *codon); char codaa(char *codon, int code); int get_ncbi_gc_number(int gc); int get_acnuc_gc_number(int ncbi_gc); int strcmptrail(char *s1, int l1, char *s2, int l2); void majuscules(char *name); void compact(char *chaine); void *mycalloc(int nbr, size_t taille); char complementer_base(char nucl); void complementer_seq(char *deb_ch, int l); char init_codon_to_aa(char *codon, int gc); int notrail2(char *chaine, int len); int prepch(char *chaine, char **posmot); int compch(char *cible, int lcible, char **posmot, int nbrmots); int chg_acnuc(char *acnucvar, char *gcgacnucvar); void gets_no_echo(char *password, size_t lpw); int trim_key(char *name) /* remove trailing spaces */ { char *p; int l = (int)strlen(name); p = name + l - 1; while( p >= name && *p == ' ' ) *(p--) = 0; return (int)((p + 1) - name); } void padtosize(char *pname, char *name, int length) { int i; strncpy(pname,name,length); pname[length]=0; for(i=(int)strlen(pname);iacide amine */ int ncbi_gc; /* numero NCBI du meme code */ int codon_init[64]; /* tableau codon initiateur -> acide amine */ }; /* les codons sont numerotes de 1 a 64 selon ordre alphabetique; le numero 65 est attribue a tout codon avec base hors AcCcGgTtUu les acides amines sont numerotes selon l'ordre de la variable aminoacids de un a 20 + * pour stop et X pour inconnu */ /* initialisation de tous les codes genetiques */ struct genetic_code_libel genetic_code[TOTCODES] = { { /* 0: universel */ {"Universal genetic code"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,21,15,3,3,3,3,21,16,20,16,2,17,2,17,22}, /*ncbi*/1, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0} /* UUG */ } , { /* 1: yeast mt */ {"CUN=T AUA=M UGA=W"}, {9,10,9,10,4,4,4,4,1,3,1,3,19,18,19,18, 11,12,11,12,5,5,5,5,1,1,1,1,4,4,4,4, 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, 21,15,21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 3, {0,0,0,0,0,0,0,0,0,0,0,0,19,0,19,0, /* AUA, AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 2: : MITOCHONDRIAL CODE OF VERTEBRATES */ {"AGR=* AUA=M UGA=W"}, {9,10,9,10,4,4,4,4,21,3,21,3,19,18,19,18,11,12,11,12, 5,5,5,5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,21,15, 21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 2, {0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,19, /* AUN */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 3: MITOCHONDRIAL CODE OF FILAMENTOUS FUNGI */ {"UGA=W"}, {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18,11,12,11,12,5,5,5, 5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,21,15,21, 15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 4, {0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,19, /* AUN */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,19,0,19,0} /* UUR */ } , { /* 4: MITOCHONDRIAL CODE OF INSECT AND PLATYHELMINTHES */ {"AUA=M UGA=W AGR=S"}, {9,10,9,10,4,4,4,4,3,3,3,3,19,18,19,18,11,12,11,12,5,5,5, 5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,21,15,21, 15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 5, {0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,19, /* AUN */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0} /* UUG */ } , { /* 5: Nuclear code of Candida cylindracea (see nature 341:164) */ {"CUG=S"}, {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, 11,12,11,12,5,5,5,5,1,1,1,1,2,2,3,2, 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, 21,15,21,15,3,3,3,3,21,16,20,16,2,17,2,17,22}, 12, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 6: NUCLEAR CODE OF CILIATA: UAR = Gln = Q */ {"UAR=Q"}, {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18,11,12,11,12,5,5,5, 5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,11,15,11, 15,3,3,3,3,21,16,20,16,2,17,2,17,22}, 6, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 7: NUCLEAR CODE OF EUPLOTES */ {"UGA=C"}, {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18,11,12,11,12,5,5,5, 5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,21,15,21, 15,3,3,3,3,16,16,20,16,2,17,2,17,22}, 10, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 8: MITOCHONDRIAL CODE OF ECHINODERMS */ {"UGA=W AGR=S AAA=N"}, {10,10,9,10,4,4,4,4,3,3,3,3,18,18,19,18, 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, 21,15,21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 9, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 9: MITOCHONDRIAL CODE OF ASCIDIACEA */ {"UGA=W AGR=G AUA=M"}, {9,10,9,10,4,4,4,4,7,3,7,3,19,18,19,18, 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, 21,15,21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 13, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 10: MITOCHONDRIAL CODE OF PLATYHELMINTHES */ {"UGA=W AGR=S UAA=Y AAA=N"}, {10,10,9,10,4,4,4,4,3,3,3,3,18,18,19,18, 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, 15,15,21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 14, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 11: NUCLEAR CODE OF BLEPHARISMA */ {"UAG=Q"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,11,15,3,3,3,3,21,16,20,16,2,17,2,17,22}, 15, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 12: NUCLEAR CODE OF BACTERIA: differs only for initiation codons */ {"NUG=AUN=M when initiation codon"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,21,15,3,3,3,3,21,16,20,16,2,17,2,17,22}, 11, {0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,19, /* AUN */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0} /* UUG */ } , { /* 13: Chlorophycean Mitochondrial */ {"UAG=Leu"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,2,15,3,3,3,3,21,16,20,16,2,17,2,17,22}, /*ncbi*/16, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 14: MITOCHONDRIAL CODE OF TREMATODE */ {"AUA=M UGA=W AGR=S AAA=N"}, {10,10,9,10,4,4,4,4,3,3,3,3,19,18,19,18,11,12,11,12,5,5,5, 5,1,1,1,1,2,2,2,2,13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8,21,15,21, 15,3,3,3,3,20,16,20,16,2,17,2,17,22}, 21, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 15: TAG-Leu,TCA-stop */ {"UAG=L UCA=*"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,2,15,21,3,3,3,21,16,20,16,2,17,2,17,22}, /*ncbi*/22, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 16: Thraustochytrium-mt */ {"UUA=*"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,21,15,3,3,3,3,21,16,20,16,21,17,2,17,22}, /*ncbi*/23, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,19, /* AUG AUU */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* GUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } , { /* 17: MITOCHONDRIAL CODE OF Pterobranchia */ {"UGA=W AGA=S AGG=K"}, /*ANN*/ {9,10,9,10,4,4,4,4,3,3,9,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,21,15,3,3,3,3,20,16,20,16,2,17,2,17,22}, /*ncbi*/24, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0} /* UUG */ } , { /* 18: Candidate Division SR1 and Gracilibacteria */ {"UGA=G"}, /*ANN*/ {9,10,9,10,4,4,4,4,1,3,1,3,18,18,19,18, /*CNN*/ 11,12,11,12,5,5,5,5,1,1,1,1,2,2,2,2, /*GNN*/ 13,14,13,14,6,6,6,6,7,7,7,7,8,8,8,8, /*TNN*/ 21,15,21,15,3,3,3,3,7,16,20,16,2,17,2,17,22}, /*ncbi*/25, /*init*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* AUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0, /* CUG */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0} /* UUG */ } /* 1 2 1234567890123456789012 RLSTPAGVKNQHEDYCFIMW*X */ }; char *get_code_descr(int code) /* get a 60-letter (or less) description of a variant genetic code return value pointer to the description, not to be altered! */ { if(code>=0 && code= totcodes)code = 0;/*use regular code if unknown number */ pdata = &genetic_code[code]; /* ici ecriture plus compacte mal compilee sur PC*/ return aminoacids[ pdata->code[num] - 1 ]; } int get_ncbi_gc_number(int gc) { /* from acnuc to ncbi genetic code number */ return genetic_code[gc].ncbi_gc; } int get_acnuc_gc_number(int ncbi_gc) { /* from ncbi to acnuc genetic code number (returns 0 if not found) */ int num; for( num = 0; num < totcodes; num++ ) if(genetic_code[num].ncbi_gc == ncbi_gc) return num; return 0; } int strcmptrail(char *s1, int l1, char *s2, int l2) /* compare strings s1 and s2 of length l1 and l2 as done by strcmp but ignores all trailing spaces */ { char *fin; int l, flag=1; if(l1 > 0) { if( (fin = (char *)memchr(s1, 0, l1) ) != NULL) l1 = (int)(fin - s1); } if(l2 > 0) { if( (fin = (char *)memchr(s2, 0, l2) ) != NULL) l2 = (int)(fin - s2); } if(l2 > l1) { flag = -1; fin=s1; s1=s2; s2=fin; l=l1; l1=l2; l2=l; } l = l2; fin = s2 + l; while(s2 < fin) { if( *s1 != *s2 ) return (*s1 - *s2)*flag; s1++; s2++; } fin= s1+l1-l2; while(s1 < fin) { if( *s1 != ' ') return flag; s1++; } return 0; } void majuscules(char *name) { name--; while(*(++name) != 0) *name = toupper(*name); } void compact(char *chaine) { int l; char *p, *q; l= (int)strlen(chaine); p=chaine+l; while( *(--p) == ' ' && p>=chaine) *p=0; while((p=strchr(chaine,' '))!=NULL) { q=p+1; while(*q==' ') q++; l= (int)(q-p); while(*q!=0) {*(q-l) = *q; q++; } *(q-l)=0; } } void *mycalloc(int nbre, size_t size) { void *point; point = calloc(nbre,size); if(point == NULL) { fprintf(stderr,"Error: problem allocating memory.\n"); exit(1); } return point; } char complementer_base(char nucl) { switch (nucl) { case 'a': case 'A': return('t'); case 'c': case 'C': return('g'); case 'g': case 'G': return('c'); case 'u': case 'U': case 't': case 'T': return('a'); case 'r': case 'R': return('y'); case 'y': case 'Y': return('r'); default : return('n'); } } /* ~~~~~~~~~~~~ retourne le complementaire d'une sequence ~~~~~~~~~~~ * recoit l'adresse du debut d'un tableau de caractere et sa longueur * inverse et complemente cette sequence * prend en compte si c'est un adn ou un arn * -------------------------------------------------------------------- */ void complementer_seq(char *deb_ch, int l) { int ii = 0; char compl1,compl2; for(ii = 0; ii <= (l-1)/2; ii++) { compl1 = complementer_base(*(deb_ch+ii)); compl2 = complementer_base(*(deb_ch+l-ii-1)); *(deb_ch+ii) = compl2; *(deb_ch+l-ii-1) = compl1; } } char init_codon_to_aa(char *codon, int gc) { int num, aa; struct genetic_code_libel *pdata; num = calc_codon_number(codon); if(num >= 64) return 'X'; /* use regular code if unknown number */ if(gc < 0 || gc >= totcodes) gc = 0; pdata = &genetic_code[gc]; aa = pdata->codon_init[num]; /* if not listed in expected init codons */ if(aa == 0) aa = pdata->code[num]; return aminoacids[aa - 1]; } int notrail2(char *chaine, int len) { len--; while(len>=0 && chaine[len]==' ') len--; return len+1; } int prepch(char *chaine, char **posmot) { /* chaine: template a rechercher qui contient des wildcard @ posmot: tableau de pointeurs vers char au retour rempli avec des pointeurs adequats qui pointent dans chaine qui ne doit plus etre modifiee valeur rendue: nbre de pointeurs dans tableau posmot */ char *pos; int nbrmots; static char wildcard='@'; if(strchr(chaine,'@')==NULL) return 0; nbrmots= -1; pos=chaine+strlen(chaine)-1; while( pos>=chaine && *pos==' ' ) pos--; *(pos+1)=0; pos=chaine; while(*pos!=0) { if(*pos==wildcard) { posmot[++nbrmots]=NULL; *pos=0; while(*(pos+1)==wildcard) pos++; } else { posmot[++nbrmots]=pos; while( *(pos+1)!=wildcard && *(pos+1) !=0 ) pos++; } pos++; } return nbrmots+1; } int compch(char *cible, int lcible, char **posmot, int nbrmots) { /* cible: chaine a tester pour presence du template lcible: long. de cible qui n'est pas forcement finie par \0 doit etre <= 150 posmot: tableau fabrique par prepch nbrmots: valeur rendue par prepch valeur rendue: 1 ssi template present dans cible, 0 si absent */ int num= 0, l, total; char *pos; static char vcible[151]; pos=cible+lcible-1; while( pos>=cible && *pos==' ' ) pos--; lcible= (int)(pos-cible+1); memcpy(vcible,cible,lcible); vcible[lcible]=0; cible=vcible; if(posmot[nbrmots-1]==NULL) total=nbrmots-1; else total=nbrmots-2; if(posmot[0]!=NULL) { /* comparaison avec mot initial */ l= (int)strlen(posmot[0]); if(strncmp(cible,posmot[0],l)!=0) return 0; cible += l; num++; } while(numnbarguments = 0; rep->arg = NULL; return rep; } void clear_reponse(Reponse * rep) { int pti; for(pti=0; pti < rep->nbarguments; pti++) { free(rep->arg[pti]); } if(rep->arg != NULL) free(rep->arg); free(rep); } void ajout_reponse(Reponse *rep, char *pile, int len) { int pti; if (rep->nbarguments==0) rep->arg = (char **)malloc(1 * sizeof(char *)); else rep->arg= (char**) realloc(rep->arg,(rep->nbarguments+1)* sizeof(char *)) ; /* ici j'ai deja alloue donc realloc (plus de ligne) */ rep->arg[rep->nbarguments]=(char *) malloc(len + 1); /* j'alloue l'espace pour l'argument */ pti=rep->nbarguments; memcpy(rep->arg[pti], pile, len); /* je stocke l'argument */ rep->arg[pti][len] = 0; rep->nbarguments++; } /** le parseur qui rempli la structure Reponse **/ void parse(char *chaine, Reponse *rep) { char *ori; ori=chaine; while(*chaine != 0) { if (*chaine == '"' ) { do { /* chercher le prochain " en ignorant les \" sauf si en fin de partie entre " " */ chaine++; if(*chaine == 0) break; } while(*chaine != '"' || ( *(chaine-1) == '\\' && *(chaine+1) != '&' && *(chaine+1) != 0) ); if(*chaine == 0) break; chaine++; } if(*chaine == '&') { ajout_reponse(rep, ori, chaine-ori); ori=chaine+1; } chaine++; } ajout_reponse(rep, ori, chaine-ori); } /** pour rechercher la valeur d'un argument dans la structure **/ char *val(Reponse *Mono, char *argument) { int count, num, l, larg; char *retval = NULL, *debut, *p; count = Mono->nbarguments; larg = strlen(argument); for(num=0; num < count; num++) { debut = Mono->arg[num]; p = strchr(debut, '='); if(p == NULL || larg != p - debut) continue; p++; if(strncmp(argument, debut, larg) != 0) continue; l = strlen(p); retval = (char *)malloc(l+1); strcpy(retval, p); unprotect_quotes(retval); break; } return retval; } char *unprotect_quotes(char *name) /* enlever les " " encadrantes et decoder les \" internes en " */ { char *p; int l; l = strlen(name); if(*name == '"') { memmove(name, name+1, l--); /* enlever la " initiale */ if( *(name+l-1) == '"') *(name + --l) = 0; /* enlever la " terminale */ } while ((p = strstr(name, "\\\"" /* la chaine \" */ )) != NULL) { memmove(p, p+1, name + l - p); l--; } return name; } seaview/csrc/parser.h000644 000765 000024 00000000647 11671421666 015444 0ustar00mgouystaff000000 000000 #include #include typedef struct ThisReponse{ char **arg; /* je stocke les arguments */ int nbarguments; /* je stocke le nombre d'arguments */ } Reponse ; extern Reponse * initreponse(void) ; extern void clear_reponse(Reponse * rep) ; void ajout_reponse(Reponse *rep, char *pile, int len) ; extern void parse(char *chaine, Reponse *rep) ; extern char *val(Reponse *Mono, char *argument) ; seaview/csrc/phylip.c000644 000765 000024 00000246031 12410061707 015433 0ustar00mgouystaff000000 000000 /* version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe, and Dan Fineman. Copyright (c) 1993-2014, Joseph Felsenstein All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include extern double next_random(void); #include "phylip.h" #ifdef WIN32 #include /* for console code (clear screen, text color settings) */ CONSOLE_SCREEN_BUFFER_INFO savecsbi; boolean savecsbi_valid = false; HANDLE hConsoleOutput; void phyClearScreen(); void phySaveConsoleAttributes(); void phySetConsoleAttributes(); void phyRestoreConsoleAttributes(); void phyFillScreenColor(); #endif /* WIN32 */ #ifndef OLDC static void crash_handler(int signum); #endif /* #if defined(OSX_CARBON) && defined(__MWERKS__) boolean fixedpath = false; #endif */ FILE *outfile, *infile, *intree, *intree2, *outtree, *weightfile, *catfile, *ancfile, *mixfile, *factfile; long spp, words, bits; boolean ibmpc, ansi, tranvsp; //naym *nayme; /* names of species */ char **nayme; /* names of species */ static void crash_handler(int sig_num) { /* when we crash, lets print out something usefull */ printf("ERROR: "); switch(sig_num) { #ifdef SIGSEGV case SIGSEGV: puts("This program has caused a Segmentation fault."); break; #endif /* SIGSEGV */ #ifdef SIGFPE case SIGFPE: puts("This program has caused a Floating Point Exception"); break; #endif /* SIGFPE */ #ifdef SIGILL case SIGILL: puts("This program has attempted an illegal instruction"); break; #endif /* SIGILL */ #ifdef SIGPIPE case SIGPIPE: puts("This program tried to write to a broken pipe"); break; #endif /* SIGPIPE */ #ifdef SIGBUS case SIGBUS: puts("This program had a bus error"); break; #endif /* SIGBUS */ } if (sig_num == SIGSEGV) { puts( " This may have been caused by an incorrectly formatted input file"); puts( " or input tree file. You should check those files carefully."); puts(" If this seems to be a bug, please mail joe@gs.washington.edu"); } else { puts(" Most likely, you have encountered a bug in the program."); puts(" Since this seems to be a bug, please mail joe@gs.washington.edu"); } puts(" with the name of the program, your computer system type,"); puts(" a full description of the problem, and with the input data file."); puts(" (which should be in the body of the message, not as an Attachment)."); #ifdef WIN32 phyRestoreConsoleAttributes(); #endif abort(); } void init(int argc, char** argv) { /* initialization routine for all programs * anything done at the beginning for every program should be done here */ /* set up signal handler for * segfault, floating point exception, illeagal instruction, bad pipe, bus error * there are more signals that can cause a crash, but these are the most common * even these aren't found on all machines. */ #ifdef SIGSEGV signal(SIGSEGV, crash_handler); #endif /* SIGSEGV */ #ifdef SIGFPE signal(SIGFPE, crash_handler); #endif /* SIGFPE */ #ifdef SIGILL signal(SIGILL, crash_handler); #endif /* SIGILL */ #ifdef SIGPIPE signal(SIGPIPE, crash_handler); #endif /* SIGPIPE */ #ifdef SIGBUS signal(SIGBUS, crash_handler); #endif /* SIGBUS */ /* Set default terminal characteristics */ ibmpc = IBMCRT; ansi = ANSICRT; javarun = false; /* Clear the screen */ cleerhome(); #ifdef WIN32 /* Perform DOS console configuration */ phySetConsoleAttributes(); phyClearScreen(); #endif /* WIN32 */ } void scan_eoln(FILE *f) { /* Eat everything up to EOF or newline, including newline */ char ch; while (!eoff(f) && !eoln(f)) gettc(f); if (!eoff(f)) ch = gettc(f); } boolean eoff(FILE *f) { /* Return true iff next getc() is EOF */ int ch; if (feof(f)) return true; ch = getc(f); if (ch == EOF) { ungetc(ch, f); return true; } ungetc(ch, f); return false; } /*eoff*/ boolean eoln(FILE *f) { /* Return true iff next getc() is EOL or EOF */ register int ch; ch = getc(f); if (ch == EOF) return true; ungetc(ch, f); return ((ch == '\n') || (ch == '\r')); } /*eoln*/ int filexists(char *filename) { /* Return true iff file already exists */ FILE *fp; fp = fopen(filename,"r"); if (fp) { fclose(fp); return 1; } else return 0; } /*filexists*/ const char* get_command_name (const char *vektor) { /* returns the name of the program from vektor without the whole path */ char *last_slash; /* Point to the last slash... */ last_slash = strrchr (vektor, DELIMITER); if (last_slash) /* If there was a last slash, return the character after it */ return last_slash + 1; else /* If not, return the vector */ return vektor; } /* get_command_name */ void EOF_error() { /* Print a message and exit when EOF is reached prematurely. */ puts("\n\nERROR: Unexpected end-of-file.\n"); exxit(-1); } /* EOF_error */ void getstryng(char *fname) { /* read in a file name from stdin and take off newline if any */ char *end; fflush(stdout); fname = fgets(fname, FNMLNGTH, stdin); if ( fname == NULL ) EOF_error(); if ( (end = strpbrk(fname, "\n\r")) != NULL) *end = '\0'; } /* getstryng */ void countup(long *loopcount, long maxcount) { /* count how many times this loop has tried to read data, bail out if exceeds maxcount */ (*loopcount)++; if ((*loopcount) >= maxcount) { printf("\nERROR: Made %ld attempts to read input in loop. Aborting run.\n", *loopcount); exxit(-1); } } /* countup */ void openfile(FILE **fp,const char *filename,const char *filedesc, const char *mode,const char *application, char *perm) { /* open a file, testing whether it exists etc. */ FILE *of; char file[FNMLNGTH]; char filemode[3]; char input[FNMLNGTH]; char ch; const char *progname_without_path; long loopcount, loopcount2; /* #if defined(OSX_CARBON) && defined(__MWERKS__) ProcessSerialNumber myProcess; FSRef bundleLocation; unsigned char bundlePath[FNMLNGTH]; if(!fixedpath){ // change path to the bundle location instead of root directory GetCurrentProcess(&myProcess); GetProcessBundleLocation(&myProcess, &bundleLocation); FSRefMakePath(&bundleLocation, bundlePath, FNMLNGTH); chdir((const char*)bundlePath); chdir(".."); // get out of the .app directory fixedpath = true; } #endif */ progname_without_path = get_command_name(application); strcpy(file, filename); strcpy(filemode, mode); loopcount = 0; while (1){ #if ! OVERWRITE_FILES if (filemode[0] == 'w' && filexists(file)){ printf("\n%s: the file \"%s\" that you wanted to\n", progname_without_path, file); printf(" use as %s already exists.\n", filedesc); printf(" Do you want to Replace it, Append to it,\n"); printf(" write to a new File, or Quit?\n"); loopcount2 = 0; do { printf(" (please type R, A, F, or Q) \n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); if ( fgets(input, sizeof(input), stdin) == NULL ) EOF_error(); ch = input[0]; uppercase(&ch); countup(&loopcount2, 10); } while (ch != 'A' && ch != 'R' && ch != 'F' && ch != 'Q'); if (ch == 'Q') exxit(-1); if (ch == 'A') { strcpy(filemode,"a"); continue; } else if (ch == 'F') { file[0] = '\0'; loopcount2 = 0; while (file[0] =='\0') { printf("Please enter a new file name> "); fflush(stdout); getstryng(file); countup(&loopcount2, 10); } strcpy(filemode,"w"); continue; } } #endif /* ! OVERWRITE_FILES */ of = fopen(file,filemode); if (of) break; else { switch (filemode[0]){ case 'r': printf("%s: can't find %s \"%s\"\n", progname_without_path, filedesc, file); file[0] = '\0'; loopcount2 = 0; while ( file[0] =='\0' ) { printf("Please enter a new file name> "); fflush(stdout); countup(&loopcount2, 10); getstryng(file); } break; case 'w': case 'a': printf("%s: can't write %s \"%s\"\n", progname_without_path, filedesc, file); file[0] = '\0'; loopcount2 = 0; while (file[0] =='\0') { printf("Please enter a new file name> "); fflush(stdout); countup(&loopcount2, 10); getstryng(file); } continue; default: printf("There is some error in the call of openfile. Unknown mode.\n"); exxit(-1); } } countup(&loopcount, 20); } *fp = of; if (perm != NULL) strcpy(perm,file); } /* openfile */ void cleerhome() { /* home cursor and clear screen, if possible */ #ifdef WIN32 if(ibmpc || ansi){ phyClearScreen(); } else { printf("\n\n"); } #else printf("%s", ((ibmpc || ansi) ? ("\033[2J\033[H") : "\n\n")); #endif } /* cleerhome */ double randum(longer seed) { /* random number generator -- slow but machine independent This is a multiplicative congruential 32-bit generator x(t+1) = 1664525 * x(t) mod 2^32, one that passes the Coveyou-Macpherson and Lehmer tests, see Knuth ACP vol. 2 We here implement it representing each integer in base-64 notation -- i.e. as an array of 6 six-bit chunks */ long i, j, k, sum; longer mult, newseed; double x; mult[0] = 13; /* these four statements set the multiplier */ mult[1] = 24; /* -- they are its "digits" in a base-64 */ mult[2] = 22; /* notation: 1664525 = 6*64^3+22*64^2 */ mult[3] = 6; /* +24*64+13 */ for (i = 0; i <= 5; i++) newseed[i] = 0; for (i = 0; i <= 5; i++) { /* do the multiplication piecewise */ sum = newseed[i]; k = i; if (i > 3) k = 3; for (j = 0; j <= k; j++) sum += mult[j] * seed[i - j]; newseed[i] = sum; for (j = i; j <= 4; j++) { newseed[j + 1] += newseed[j] / 64; newseed[j] &= 63; } } memcpy(seed, newseed, sizeof(longer)); /* new seed replaces old one */ seed[5] &= 3; /* from the new seed, get a floating point fraction */ x = 0.0; for (i = 0; i <= 5; i++) x = x / 64.0 + seed[i]; x /= 4.0; return x; } /* randum */ void randumize(longer seed, long *enterorder) { /* randomize input order of species -- randomly permute array enterorder */ long i, j, k; for (i = 0; i < spp; i++) { //j = (long)(randum(seed) * (i+1)); j = (long)(next_random() * (i+1)); k = enterorder[j]; enterorder[j] = enterorder[i]; enterorder[i] = k; } } /* randumize */ double normrand(longer seed) {/* standardized Normal random variate */ double x; x = randum(seed)+randum(seed)+randum(seed)+randum(seed) + randum(seed)+randum(seed)+randum(seed)+randum(seed) + randum(seed)+randum(seed)+randum(seed)+randum(seed)-6.0; return(x); } /* normrand */ long readlong(const char *prompt) { /* read a long */ long res, loopcount; char string[100]; loopcount = 0; do { printf("%s", prompt); fflush(stdout); getstryng(string); if (sscanf(string,"%ld",&res) == 1) break; countup(&loopcount, 10); } while (1); return res; } /* readlong */ void uppercase(Char *ch) { /* convert ch to upper case */ *ch = (islower (*ch) ? toupper(*ch) : (*ch)); } /* uppercase */ void initseed(long *inseed, long *inseed0, longer seed) { /* input random number seed */ long i, loopcount; assert(inseed); assert(inseed0); loopcount = 0; for (;;) { printf("\nRandom number seed (must be odd)?\n"); fflush(stdout); if (scanf("%ld%*[^\n]", inseed) == 1) { getchar(); if (*inseed > 0 && (*inseed & 0x1)) break; } countup(&loopcount, 10); } *inseed0 = *inseed; for (i = 0; i <= 5; i++) seed[i] = 0; i = 0; do { seed[i] = *inseed & 63; *inseed /= 64; i++; } while (*inseed != 0); } /*initseed*/ void initjumble(long *inseed, long *inseed0, longer seed, long *njumble) { /* input number of jumblings for jumble option */ long loopcount; initseed(inseed, inseed0, seed); loopcount = 0; for (;;) { printf("Number of times to jumble?\n"); fflush(stdout); if (scanf("%ld%*[^\n]", njumble) == 1) { getchar(); if (*njumble >= 1) break; } countup(&loopcount, 10); } } /*initjumble*/ void initoutgroup(long *outgrno, long spp) { /* input outgroup number */ long loopcount; loopcount = 0; for (;;) { printf("Type number of the outgroup:\n"); fflush(stdout); if (scanf("%ld%*[^\n]", outgrno) == 1) { getchar(); if (*outgrno >= 1 && *outgrno <= spp) break; else { printf("BAD OUTGROUP NUMBER: %ld\n", *outgrno); printf(" Must be in range 1 - %ld\n", spp); } } countup(&loopcount, 10); } } /*initoutgroup*/ void initthreshold(double *threshold) { /* input threshold for threshold parsimony option */ long loopcount; loopcount = 0; for (;;) { printf("What will be the threshold value?\n"); fflush(stdout); if (scanf("%lf%*[^\n]", threshold) == 1) { getchar(); if (*threshold >= 1.0) break; else printf("BAD THRESHOLD VALUE: it must be greater than 1\n"); } countup(&loopcount, 10); } *threshold = (long)(*threshold * 10.0 + 0.5) / 10.0; } /*initthreshold*/ void initcatn(long *categs) { /* initialize category number for rate categories */ long loopcount; loopcount = 0; *categs = 0; for (;;) { printf("Number of categories (1-%d)?\n", maxcategs); fflush(stdout); if (scanf("%ld%*[^\n]", categs) == 1) { getchar(); if (*categs > maxcategs || *categs < 1) continue; else break; } countup(&loopcount, 10); } } /*initcatn*/ void initcategs(long categs, double *rate) { /* initialize category rates for HMM rates */ long i, loopcount, scanned; char line[100], rest[100]; boolean done; loopcount = 0; for (;;){ printf("Rate for each category? (use a space to separate)\n"); fflush(stdout); getstryng(line); done = true; for (i = 0; i < categs; i++){ scanned = sscanf(line,"%lf %[^\n]", &rate[i], rest); if ((scanned < 2 && i < (categs - 1)) || (scanned < 1 && i == (categs - 1))) { printf("Please enter exactly %ld values.\n", categs); done = false; break; } strcpy(line, rest); } if (done) break; countup(&loopcount, 100); } } /*initcategs*/ void initprobcat(long categs, double *probsum, double *probcat) { /* input probabilities of rate categores for HMM rates */ long i, loopcount, scanned; boolean done; char line[100], rest[100]; loopcount = 0; do { printf("Probability for each category?"); printf(" (use a space to separate)\n"); fflush(stdout); getstryng(line); done = true; for (i = 0; i < categs; i++) { scanned = sscanf(line, "%lf %[^\n]", &probcat[i], rest); if ((scanned < 2 && i < (categs - 1)) || (scanned < 1 && i == (categs - 1))) { done = false; printf("Please enter exactly %ld values.\n", categs); break; } strcpy(line, rest); } if (!done) continue; *probsum = 0.0; for (i = 0; i < categs; i++) *probsum += probcat[i]; if (fabs(1.0 - (*probsum)) > 0.001) { done = false; printf("Probabilities must add up to"); printf(" 1.0, plus or minus 0.001.\n"); } countup(&loopcount, 100); } while (!done); } /*initprobcat*/ void lgr(long m, double b, raterootarray lgroot) { /* For use by initgammacat. Get roots of m-th Generalized Laguerre polynomial, given roots of (m-1)-th, these are to be stored in lgroot[m][] */ long i; double upper, lower, x, y; boolean dwn; /* is function declining in this interval? */ if (m == 1) { lgroot[1][1] = 1.0+b; } else { dwn = true; for (i=1; i<=m; i++) { if (i < m) { if (i == 1) lower = 0.0; else lower = lgroot[m-1][i-1]; upper = lgroot[m-1][i]; } else { /* i == m, must search above */ lower = lgroot[m-1][i-1]; x = lgroot[m-1][m-1]; do { x = 2.0*x; y = glaguerre(m, b, x); } while ((dwn && (y > 0.0)) || ((!dwn) && (y < 0.0))); upper = x; } while (upper-lower > 0.000000001) { x = (upper+lower)/2.0; if (glaguerre(m, b, x) > 0.0) { if (dwn) lower = x; else upper = x; } else { if (dwn) upper = x; else lower = x; } } lgroot[m][i] = (lower+upper)/2.0; dwn = !dwn; /* switch for next one */ } } } /* lgr */ double logfac (long n) { /* log(n!) values were calculated with Mathematica with a precision of 30 digits */ long i; double x; switch (n) { case 0: return 0.; case 1: return 0.; case 2: return 0.693147180559945309417232121458; case 3: return 1.791759469228055000812477358381; case 4: return 3.1780538303479456196469416013; case 5: return 4.78749174278204599424770093452; case 6: return 6.5792512120101009950601782929; case 7: return 8.52516136106541430016553103635; case 8: return 10.60460290274525022841722740072; case 9: return 12.80182748008146961120771787457; case 10: return 15.10441257307551529522570932925; case 11: return 17.50230784587388583928765290722; case 12: return 19.98721449566188614951736238706; default: x = 19.98721449566188614951736238706; for (i = 13; i <= n; i++) x += log(i); return x; } } /* logfac */ double glaguerre(long m, double b, double x) { /* Generalized Laguerre polynomial computed recursively. For use by initgammacat */ long i; double gln, glnm1, glnp1; /* L_n, L_(n-1), L_(n+1) */ if (m == 0) return 1.0; else { if (m == 1) return 1.0 + b - x; else { gln = 1.0+b-x; glnm1 = 1.0; for (i=2; i <= m; i++) { glnp1 = ((2*(i-1)+b+1.0-x)*gln - (i-1+b)*glnm1)/i; glnm1 = gln; gln = glnp1; } return gln; } } } /* glaguerre */ void initlaguerrecat(long categs, double alpha, double *rate, double *probcat) { /* calculate rates and probabilities to approximate Gamma distribution of rates with "categs" categories and shape parameter "alpha" using rates and weights from Generalized Laguerre quadrature */ long i; raterootarray lgroot; /* roots of GLaguerre polynomials */ double f, x, xi, y; alpha = alpha - 1.0; lgroot[1][1] = 1.0+alpha; for (i = 2; i <= categs; i++) lgr(i, alpha, lgroot); /* get roots for L^(a)_n */ /* here get weights */ /* Gamma weights are (1+a)(1+a/2) ... (1+a/n)*x_i/((n+1)^2 [L_{n+1}^a(x_i)]^2) */ f = 1; for (i = 1; i <= categs; i++) f *= (1.0+alpha/i); for (i = 1; i <= categs; i++) { xi = lgroot[categs][i]; y = glaguerre(categs+1, alpha, xi); x = f*xi/((categs+1)*(categs+1)*y*y); rate[i-1] = xi/(1.0+alpha); probcat[i-1] = x; } } /* initlaguerrecat */ double hermite(long n, double x) { /* calculates hermite polynomial with degree n and parameter x */ /* seems to be unprecise for n>13 -> root finder does not converge*/ double h1 = 1.; double h2 = 2. * x; double xx = 2. * x; long i; for (i = 1; i < n; i++) { xx = 2. * x * h2 - 2. * (i) * h1; h1 = h2; h2 = xx; } return xx; } /* hermite */ void root_hermite(long n, double *hroot) { /* find roots of Hermite polynmials */ long z; long ii; long start; if (n % 2 == 0) { start = n/2; z = 1; } else { start = n/2 + 1; z=2; hroot[start-1] = 0.0; } for (ii = start; ii < n; ii++) { /* search only upwards*/ hroot[ii] = halfroot(hermite, n, hroot[ii-1]+EPSILON, 1./n); hroot[start - z] = -hroot[ii]; z++; } } /* root_hermite */ double halfroot(double (*func)(long m, double x), long n, double startx, double delta) { /* searches from the bound (startx) only in one direction (by positive or negative delta, which results in other-bound=startx+delta) delta should be small. (*func) is a function with two arguments */ double xl; double xu; double xm = 0; double fu; double fl; double fm = 100000.; double gradient; boolean dwn = false; /* decide if we search above or below startx and escapes to trace back to the starting point that most often will be the root from the previous calculation */ if (delta < 0) { xu = startx; xl = xu + delta; } else { xl = startx; xu = xl + delta; } delta = fabs(delta); fu = (*func)(n, xu); fl = (*func)(n, xl); gradient = (fl-fu)/(xl-xu); while(fabs(fm) > EPSILON) { /* is root outside of our bracket?*/ if ((fu<0.0 && fl<0.0) || (fu>0.0 && fl > 0.0)) { xu += delta; fu = (*func)(n, xu); fl = (*func)(n, xl); gradient = (fl-fu)/(xl-xu); dwn = (gradient < 0.0) ? true : false; } else { xm = xl - fl / gradient; fm = (*func)(n, xm); if (dwn) { if (fm > 0.) { xl = xm; fl = fm; } else { xu = xm; fu = fm; } } else { if (fm > 0.) { xu = xm; fu = fm; } else { xl = xm; fl = fm; } } gradient = (fl-fu)/(xl-xu); } } return xm; } /* halfroot */ void hermite_weight(long n, double * hroot, double * weights) { /* calculate the weights for the hermite polynomial at the roots using formula from Abramowitz and Stegun chapter 25.4.46 p.890 */ long i; double hr2; double numerator; numerator = exp(0.6931471805599 * ( n-1.) + logfac(n)) / (n*n); for (i = 0; i < n; i++) { hr2 = hermite(n-1, hroot[i]); weights[i] = numerator / (hr2*hr2); } } /* hermiteweight */ void inithermitcat(long categs, double alpha, double *rate, double *probcat) { /* calculates rates and probabilities */ long i; double *hroot; double std; std = SQRT2 /sqrt(alpha); hroot = (double *) Malloc((categs+1) * sizeof(double)); root_hermite(categs, hroot); /* calculate roots */ hermite_weight(categs, hroot, probcat); /* set weights */ for (i=0; i= 100.0) inithermitcat(categs, alpha, rate, probcat); else initlaguerrecat(categs, alpha, rate, probcat); } /* initgammacat */ void inithowmany(long *howmanny, long howoften) {/* input how many cycles */ long loopcount; loopcount = 0; for (;;) { printf("How many cycles of %4ld trees?\n", howoften); fflush(stdout); if (scanf("%ld%*[^\n]", howmanny) == 1) { getchar(); if (*howmanny >= 1) break; } countup(&loopcount, 10); } } /*inithowmany*/ void inithowoften(long *howoften) { /* input how many trees per cycle */ long loopcount; loopcount = 0; for (;;) { printf("How many trees per cycle?\n"); fflush(stdout); if (scanf("%ld%*[^\n]", howoften) == 1) { getchar(); if (*howoften >= 1) break; } countup(&loopcount, 10); } } /*inithowoften*/ void initlambda(double *lambda) { /* input patch length parameter for autocorrelated HMM rates */ long loopcount; loopcount = 0; for (;;) { printf("Mean block length of sites having the same rate (greater than 1)?\n"); fflush(stdout); if (scanf("%lf%*[^\n]", lambda) == 1) { getchar(); if (*lambda > 1.0) break; } countup(&loopcount, 10); } *lambda = 1.0 / *lambda; } /* initlambda */ void initfreqs(double *freqa, double *freqc, double *freqg, double *freqt) { /* input frequencies of the four bases */ char input[100]; long scanned, loopcount; printf("Base frequencies for A, C, G, T/U (use blanks to separate)?\n"); loopcount = 0; do { fflush(stdout); getstryng(input); scanned = sscanf(input,"%lf%lf%lf%lf%*[^\n]", freqa, freqc, freqg, freqt); if (scanned == 4) break; else printf("Please enter exactly 4 values.\n"); countup(&loopcount, 100); } while (1); } /* initfreqs */ void initratio(double *ttratio) { /* input transition/transversion ratio */ long loopcount; loopcount = 0; for (;;) { printf("Transition/transversion ratio?\n"); fflush(stdout); if (scanf("%lf%*[^\n]", ttratio) == 1) { getchar(); if (*ttratio >= 0.0) break; else printf("Transition/transversion ratio cannot be negative.\n"); } countup(&loopcount, 10); } } /* initratio */ void initpower(double *power) { for (;;) { printf("New power?\n"); fflush(stdout); if (scanf("%lf%*[^\n]", power) == 1) { getchar(); break; } } } /*initpower*/ void initdatasets(long *datasets) { /* handle multi-data set option */ long loopcount; loopcount = 0; for (;;) { printf("How many data sets?\n"); fflush(stdout); if (scanf("%ld%*[^\n]", datasets) == 1) { getchar(); if (*datasets > 1) break; else printf("Bad data sets number: it must be greater than 1\n"); } countup(&loopcount, 10); } } /* initdatasets */ void justweights(long *datasets) { /* handle multi-data set option by weights */ long loopcount; loopcount = 0; for (;;) { printf("How many sets of weights?\n"); fflush(stdout); if (scanf("%ld%*[^\n]", datasets) == 1) { getchar(); if (*datasets >= 1) break; else printf("BAD NUMBER: it must be greater than 1\n"); } countup(&loopcount, 10); } } /* justweights */ void initterminal(boolean *ibmpc, boolean *ansi) { /* handle terminal option */ if (*ibmpc) { *ibmpc = false; *ansi = true; } else if (*ansi) *ansi = false; else *ibmpc = true; } /*initterminal*/ void initnumlines(long *screenlines) { long loopcount; loopcount = 0; do { *screenlines = readlong("Number of lines on screen?\n"); countup(&loopcount, 10); } while (*screenlines <= 12); } /*initnumlines*/ void initbestrees(bestelm *bestrees, long maxtrees, boolean glob) { /* initializes either global or local field of each array in bestrees */ long i; if (glob) for (i = 0; i < maxtrees; i++) bestrees[i].gloreange = false; else for (i = 0; i < maxtrees; i++) bestrees[i].locreange = false; } /* initbestrees */ void newline(FILE *filename, long i, long j, long k) { /* go to new line if i is a multiple of j, indent k spaces */ long m; if ((i - 1) % j != 0 || i <= 1) return; putc('\n', filename); for (m = 1; m <= k; m++) putc(' ', filename); } /* newline */ void inputnumbersold(long *spp, long *chars, long *nonodes, long n) { /* input the numbers of species and of characters */ if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) { printf( "ERROR: Unable to read the number of species or characters in data set\n"); printf( "The input file is incorrect (perhaps it was not saved text only).\n"); } *nonodes = *spp * 2 - n; } /* inputnumbersold */ void inputnumbers(long *spp, long *chars, long *nonodes, long n) { /* Read numbers of species and characters from first line of a data set. * Return the results in *spp and *chars, respectively. Also returns * (*spp * 2 - n) in *nonodes */ if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) { printf( "ERROR: Unable to read the number of species or characters in data set\n"); printf( "The input file is incorrect (perhaps it was not saved text only).\n"); } *nonodes = *spp * 2 - n; } /* inputnumbers */ void inputnumbers2(long *spp, long *nonodes, long n) { /* read species number */ if (fscanf(infile, "%ld", spp) != 1 || *spp <= 0) { printf("ERROR: Unable to read the number of species in data set\n"); printf( "The input file is incorrect (perhaps it was not saved text only).\n"); } fprintf(outfile, "\n%4ld Populations\n", *spp); *nonodes = *spp * 2 - n; } /* inputnumbers2 */ void inputnumbers3(long *spp, long *chars) { /* input the numbers of species and of characters */ if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) { printf( "ERROR: Unable to read the number of species or characters in data set\n"); printf( "The input file is incorrect (perhaps it was not saved text only).\n"); exxit(-1); } } /* inputnumbers3 */ void samenumsp(long *chars, long ith) { /* check if spp is same as the first set in other data sets */ long cursp, curchs; if (eoln(infile)) scan_eoln(infile); if (fscanf(infile, "%ld%ld", &cursp, &curchs) == 2) { if (cursp != spp) { printf( "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith); exxit(-1); } } else { printf( "Unable to read number of species and sites from data set %ld\n\n", ith); exxit(-1); } *chars = curchs; } /* samenumsp */ void samenumsp2(long ith) { /* check if spp is same as the first set in other data sets */ long cursp; if (eoln(infile)) scan_eoln(infile); if (fscanf(infile, "%ld", &cursp) != 1) { printf("\n\nERROR: Unable to read number of species in data set %ld\n", ith); printf( "The input file is incorrect (perhaps it was not saved text only).\n"); exxit(-1); } if (cursp != spp) { printf( "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith); exxit(-1); } } /* samenumsp2 */ void readoptions(long *extranum, const char *options) { /* read option characters from input file */ Char ch; while (!(eoln(infile))) { ch = gettc(infile); uppercase(&ch); if (strchr(options, ch) != NULL) (* extranum)++; else if (!(ch == ' ' || ch == '\t')) { printf("BAD OPTION CHARACTER: %c\n", ch); exxit(-1); } } scan_eoln(infile); } /* readoptions */ void matchoptions(Char *ch, const char *options) { /* match option characters to those in auxiliary options line */ *ch = gettc(infile); uppercase(ch); if (strchr(options, *ch) == NULL) { printf("ERROR: Incorrect auxiliary options line"); printf(" which starts with %c\n", *ch); exxit(-1); } } /* matchoptions */ /*void inputweightsold(long chars, steptr weight, boolean *weights) { Char ch; int i; for (i = 1; i < nmlngth ; i++) getc(infile); for (i = 0; i < chars; i++) { do { if (eoln(infile)) scan_eoln(infile); ch = gettc(infile); if (ch == '\n') ch = ' '; } while (ch == ' '); weight[i] = 1; if (isdigit(ch)) weight[i] = ch - '0'; else if (isalpha(ch)) { uppercase(&ch); weight[i] = ch - 'A' + 10; } else { printf("\n\nERROR: Bad weight character: %c\n\n", ch); exxit(-1); } } scan_eoln(infile); *weights = true; } *inputweightsold*/ void inputweights(long chars, steptr weight, boolean *weights) { /* input the character weights, 0-9 and A-Z for weights 0 - 35 */ Char ch; long i; for (i = 0; i < chars; i++) { do { if (eoln(weightfile)) scan_eoln(weightfile); ch = gettc(weightfile); if (ch == '\n') ch = ' '; } while (ch == ' '); weight[i] = 1; if (isdigit(ch)) weight[i] = ch - '0'; else if (isalpha(ch)) { uppercase(&ch); weight[i] = ch - 'A' + 10; } else { printf("\n\nERROR: Bad weight character: %c\n\n", ch); exxit(-1); } } scan_eoln(weightfile); *weights = true; } /* inputweights */ void inputweights2(long a, long b, long *weightsum, steptr weight, boolean *weights, const char *prog) { /* input the character weights, 0 or 1 */ Char ch; long i; *weightsum = 0; for (i = a; i < b; i++) { do { if (eoln(weightfile)) scan_eoln(weightfile); ch = gettc(weightfile); } while (ch == ' '); weight[i] = 1; if (ch == '0' || ch == '1') weight[i] = ch - '0'; else { printf("\n\nERROR: Bad weight character: %c -- ", ch); printf("weights in %s must be 0 or 1\n", prog); exxit(-1); } *weightsum += weight[i]; } *weights = true; scan_eoln(weightfile); } /* inputweights2 */ /*void printweights(FILE *filename, long inc, long chars, steptr weight, const char *letters) { * print out the weights of sites * long i, j; boolean letterweights; letterweights = false; for (i = 0; i < chars; i++) if (weight[i] > 9) letterweights = true; fprintf(filename, "\n %s are weighted as follows:", letters); if (letterweights) fprintf(filename, " (A = 10, B = 11, etc.)\n"); else putc('\n', filename); for (i = 0; i < chars; i++) { if (i % 60 == 0) { putc('\n', filename); for (j = 1; j <= nmlngth + 3; j++) putc(' ', filename); } if (weight[i+inc] < 10) fprintf(filename, "%ld", weight[i + inc]); else fprintf(filename, "%c", 'A'-10+(int)weight[i + inc]); if ((i+1) % 5 == 0 && (i+1) % 60 != 0) putc(' ', filename); } fprintf(filename, "\n\n"); } * printweights */ void inputcategs(long a, long b, steptr category, long categs, const char *prog) { /* input the categories, 1-9 */ Char ch; long i; for (i = a; i < b; i++) { do { if (eoln(catfile)) scan_eoln(catfile); ch = gettc(catfile); } while (ch == ' '); if ((ch >= '1') && (ch <= ('0'+categs))) category[i] = ch - '0'; else { printf("\n\nERROR: Bad category character: %c", ch); printf(" -- categories in %s are currently 1-%ld\n", prog, categs); exxit(-1); } } scan_eoln(catfile); } /* inputcategs */ /*void printcategs(FILE *filename, long chars, steptr category, const char *letters) { * print out the sitewise categories * long i, j; fprintf(filename, "\n %s are:\n", letters); for (i = 0; i < chars; i++) { if (i % 60 == 0) { putc('\n', filename); for (j = 1; j <= nmlngth + 3; j++) putc(' ', filename); } fprintf(filename, "%ld", category[i]); if ((i+1) % 10 == 0 && (i+1) % 60 != 0) putc(' ', filename); } fprintf(filename, "\n\n"); } * printcategs */ void inputfactors(long chars, Char *factor, boolean *factors) { /* reads the factor symbols */ long i; for (i = 0; i < (chars); i++) { if (eoln(factfile)) scan_eoln(factfile); factor[i] = gettc(factfile); if (factor[i] == '\n') factor[i] = ' '; } scan_eoln(factfile); *factors = true; } /* inputfactors */ /*void printfactors(FILE *filename, long chars, Char *factor, const char *letters) { * print out list of factor symbols * long i; fprintf(filename, "Factors%s:\n\n", letters); for (i = 1; i <= nmlngth - 5; i++) putc(' ', filename); for (i = 1; i <= (chars); i++) { newline(filename, i, 55, nmlngth + 3); putc(factor[i - 1], filename); if (i % 5 == 0) putc(' ', filename); } putc('\n', filename); } * printfactors * void headings(long chars, const char *letters1, const char *letters2) { long i, j; putc('\n', outfile); j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5; if (j < nmlngth - 1) j = nmlngth - 1; if (j > 37) j = 37; fprintf(outfile, "Name"); for (i = 1; i <= j; i++) putc(' ', outfile); fprintf(outfile, "%s\n", letters1); fprintf(outfile, "----"); for (i = 1; i <= j; i++) putc(' ', outfile); fprintf(outfile, "%s\n\n", letters2); } * headings */ /*void initname(long i) { * read in species name * long j; for (j = 0; j < nmlngth; j++) { if (eoff(infile) | eoln(infile)){ printf("\n\nERROR: end-of-line or end-of-file"); printf(" in the middle of species name for species %ld\n\n", i+1); exxit(-1); } nayme[i][j] = gettc(infile); if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':') || (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[') || (nayme[i][j] == ']')) { printf("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"); printf(" In name of species number %ld there is character %c\n\n", i+1, nayme[i][j]); exxit(-1); } } } * initname */ void findtree(boolean *found, long *pos, long nextree, long *place, bestelm *bestrees) { /* finds tree given by array place in array bestrees by binary search */ /* used by dnacomp, dnapars, dollop, mix, & protpars */ long i, lower, upper; boolean below, done; below = false; lower = 1; upper = nextree - 1; (*found) = false; while (!(*found) && lower <= upper) { (*pos) = (lower + upper) / 2; i = 3; done = false; while (!done) { done = (i > spp); if (!done) done = (place[i - 1] != bestrees[(*pos) - 1].btree[i - 1]); if (!done) i++; } (*found) = (i > spp); if (*found) break; below = (place[i - 1] < bestrees[(*pos )- 1].btree[i - 1]); if (below) upper = (*pos) - 1; else lower = (*pos) + 1; } if (!(*found) && !below) (*pos)++; } /* findtree */ void addtree(long pos, long *nextree, boolean collapse, long *place, bestelm *bestrees) { /* puts tree from array place in its proper position in array bestrees */ /* used by dnacomp, dnapars, dollop, mix, & protpars */ long i; for (i = *nextree - 1; i >= pos; i--){ memcpy(bestrees[i].btree, bestrees[i - 1].btree, spp * sizeof(long)); bestrees[i].gloreange = bestrees[i - 1].gloreange; bestrees[i - 1].gloreange = false; bestrees[i].locreange = bestrees[i - 1].locreange; bestrees[i - 1].locreange = false; bestrees[i].collapse = bestrees[i - 1].collapse; } for (i = 0; i < spp; i++) bestrees[pos - 1].btree[i] = place[i]; bestrees[pos - 1].collapse = collapse; (*nextree)++; } /* addtree */ long findunrearranged(bestelm *bestrees, long nextree, boolean glob) { /* finds bestree with either global or local field false */ long i; if (glob) { for (i = 0; i < nextree - 1; i++) if (!bestrees[i].gloreange) return i; } else { for (i = 0; i < nextree - 1; i++) if (!bestrees[i].locreange) return i; } return -1; } /* findunrearranged */ boolean torearrange(bestelm *bestrees, long nextree) { /* sees if any best tree is yet to be rearranged */ if (findunrearranged(bestrees, nextree, true) >= 0) return true; else if (findunrearranged(bestrees, nextree, false) >= 0) return true; else return false; } /* torearrange */ void reducebestrees(bestelm *bestrees, long *nextree) { /* finds best trees with collapsible branches and deletes them */ long i, j; i = 0; j = *nextree - 2; do { while (!bestrees[i].collapse && i < *nextree - 1) i++; while (bestrees[j].collapse && j >= 0) j--; if (i < j) { memcpy(bestrees[i].btree, bestrees[j].btree, spp * sizeof(long)); bestrees[i].gloreange = bestrees[j].gloreange; bestrees[i].locreange = bestrees[j].locreange; bestrees[i].collapse = false; bestrees[j].collapse = true; } } while (i < j); *nextree = i + 1; } /* reducebestrees */ void shellsort(double *a, long *b, long n) { /* Shell sort keeping a, b in same order */ /* used by dnapenny, dolpenny, & penny */ long gap, i, j, itemp; double rtemp; gap = n / 2; while (gap > 0) { for (i = gap + 1; i <= n; i++) { j = i - gap; while (j > 0) { if (a[j - 1] > a[j + gap - 1]) { rtemp = a[j - 1]; a[j - 1] = a[j + gap - 1]; a[j + gap - 1] = rtemp; itemp = b[j - 1]; b[j - 1] = b[j + gap - 1]; b[j + gap - 1] = itemp; } j -= gap; } } gap /= 2; } } /* shellsort */ void getch(Char *c, long *parens, FILE *treefile) { /* get next nonblank character */ do { if (eoln(treefile)) scan_eoln(treefile); (*c) = gettc(treefile); if ((*c) == '\n' || (*c) == '\t') (*c) = ' '; } while ( *c == ' ' && !eoff(treefile) ); if ((*c) == '(') (*parens)++; if ((*c) == ')') (*parens)--; } /* getch */ void getch2(Char *c, long *parens) { /* get next nonblank character */ do { if (eoln(intree)) scan_eoln(intree); *c = gettc(intree); if (*c == '\n' || *c == '\t') *c = ' '; } while (!(*c != ' ' || eoff(intree))); if (*c == '(') (*parens)++; if (*c == ')') (*parens)--; } /* getch2 */ void findch(Char c, Char *ch, long which) { /* scan forward until find character c */ boolean done; long dummy_parens; done = false; while (!done) { if (c == ',') { if (*ch == '(' || *ch == ')' || *ch == ';') { printf( "\n\nERROR in user tree %ld: unmatched parenthesis or missing comma\n\n", which); exxit(-1); } else if (*ch == ',') done = true; } else if (c == ')') { if (*ch == '(' || *ch == ',' || *ch == ';') { printf("\n\nERROR in user tree %ld: ", which); printf("unmatched parenthesis or non-bifurcated node\n\n"); exxit(-1); } else { if (*ch == ')') done = true; } } else if (c == ';') { if (*ch != ';') { printf("\n\nERROR in user tree %ld: ", which); printf("unmatched parenthesis or missing semicolon\n\n"); exxit(-1); } else done = true; } if (*ch != ')' && done) continue; getch(ch, &dummy_parens, intree); } } /* findch */ void findch2(Char c, long *lparens, long *rparens, Char *ch) { /* skip forward in user tree until find character c */ boolean done; long dummy_parens; done = false; while (!done) { if (c == ',') { if (*ch == '(' || *ch == ')' || *ch == ':' || *ch == ';') { printf("\n\nERROR in user tree: "); printf("unmatched parenthesis, missing comma"); printf(" or non-trifurcated base\n\n"); exxit(-1); } else if (*ch == ',') done = true; } else if (c == ')') { if (*ch == '(' || *ch == ',' || *ch == ':' || *ch == ';') { printf( "\n\nERROR in user tree: unmatched parenthesis or non-bifurcated node\n\n"); exxit(-1); } else if (*ch == ')') { (*rparens)++; if ((*lparens) > 0 && (*lparens) == (*rparens)) { if ((*lparens) == spp - 2) { getch(ch, &dummy_parens, intree); if (*ch != ';') { printf( "\n\nERROR in user tree: "); printf("unmatched parenthesis or missing semicolon\n\n"); exxit(-1); } } } done = true; } } if (*ch != ')' && done) continue; if (*ch == ')') getch(ch, &dummy_parens, intree); } } /* findch2 */ void processlength(double *valyew, double *divisor, Char *ch, boolean *lengthIsNegative, FILE *treefile, long *parens) { /* read a branch length from a treefile */ long digit, ordzero, exponent, exponentIsNegative; boolean pointread, hasExponent; ordzero = '0'; *lengthIsNegative = false; pointread = false; hasExponent = false; exponentIsNegative = -1; /* 3 states: -1 = unassigned, 1 = true, 0 = false */ exponent = 0; *valyew = 0.0; *divisor = 1.0; getch(ch, parens, treefile); if ('+' == *ch) getch(ch, parens, treefile); /* ignore leading '+', because "+1.2345" == "1.2345" */ else if ('-' == *ch) { *lengthIsNegative = true; getch(ch, parens, treefile); } digit = (long)(*ch - ordzero); while ( ((digit <= 9) && (digit >= 0)) || '.' == *ch || '-' == *ch || '+' == *ch || 'E' == *ch || 'e' == *ch) { if ('.' == *ch) { if (!pointread) pointread = true; else { printf("\n\nERROR: Branch length found with more than one \'.\' in it.\n\n"); exxit(-1); } } else if ('+' == *ch) { if (hasExponent && -1 == exponentIsNegative) exponentIsNegative = 0; /* 3 states: -1 = unassigned, 1 = true, 0 = false */ else { printf("\n\nERROR: Branch length found with \'+\' in an unexpected place.\n\n"); exxit(-1); } } else if ('-' == *ch) { if (hasExponent && -1 == exponentIsNegative) exponentIsNegative = 1; /* 3 states: -1 = unassigned, 1 = true, 0 = false */ else { printf("\n\nERROR: Branch length found with \'-\' in an unexpected place.\n\n"); exxit(-1); } } else if ('E' == *ch || 'e' == *ch) { if (!hasExponent) hasExponent = true; else { printf("\n\nERROR: Branch length found with more than one \'E\' in it.\n\n"); exxit(-1); } } else { if (!hasExponent) { *valyew = *valyew * 10.0 + digit; if (pointread) *divisor *= 10.0; } else exponent = 10*exponent + digit; } getch(ch, parens, treefile); digit = (long)(*ch - ordzero); } if (hasExponent) { if (exponentIsNegative) *divisor *= pow(10.,(double)exponent); else *divisor /= pow(10.,(double)exponent); } if (*lengthIsNegative) *valyew = -(*valyew); } /* processlength */ /*void writename(long start, long n, long *enterorder) { * write species name and number in entry order * long i, j; for (i = start; i < start+n; i++) { printf(" %3ld. ", i+1); for (j = 0; j < nmlngth; j++) putchar(nayme[enterorder[i] - 1][j]); putchar('\n'); fflush(stdout); } } * writename */ void memerror() { printf("Error allocating memory\n"); exxit(-1); } /* memerror */ void odd_malloc(long x) { /* error message if attempt to malloc too little or too much memory */ printf ("ERROR: a function asked for an inappropriate amount of memory:"); printf (" %ld bytes\n", x); printf (" This can mean one of two things:\n"); printf (" 1. The input file is incorrect"); printf (" (perhaps it was not saved as Text Only),\n"); printf (" 2. There is a bug in the program.\n"); printf (" Please check your input file carefully.\n"); printf (" If it seems to be a bug, please mail joe (at) gs.washington.edu\n"); printf (" with the name of the program, your computer system type,\n"); printf (" a full description of the problem, and with the input data file.\n"); printf (" (which should be in the body of the message, not as an Attachment).\n"); /* abort() can be used to crash */ exxit(-1); } MALLOCRETURN *mymalloc(long x) { /* wrapper for malloc, allowing error message if too little, too much */ MALLOCRETURN *new_block; if ((x <= 0) || (x > TOO_MUCH_MEMORY)) odd_malloc(x); new_block = (MALLOCRETURN *)calloc(1, x); if (!new_block) { memerror(); return (MALLOCRETURN *) new_block; } else return (MALLOCRETURN *) new_block; } /* mymalloc */ void gnu(node **grbg, node **p) { /* this and the following are do-it-yourself garbage collectors. Make a new node or pull one off the garbage list */ if (*grbg != NULL) { *p = *grbg; *grbg = (*grbg)->next; } else *p = (node *)Malloc(sizeof(node)); (*p)->back = NULL; (*p)->next = NULL; (*p)->tip = false; (*p)->times_in_tree = 0.0; (*p)->r = 0.0; (*p)->theta = 0.0; (*p)->x = NULL; (*p)->protx = NULL; /* for the sake of proml */ } /* gnu */ void chuck(node **grbg, node *p) { /* collect garbage on p -- put it on front of garbage list */ p->back = NULL; p->next = *grbg; *grbg = p; } /* chuck */ void zeronumnuc(node *p, long endsite) { long i,j; for (i = 0; i < endsite; i++) for (j = (long)A; j <= (long)O; j++) p->numnuc[i][j] = 0; } /* zeronumnuc */ void zerodiscnumnuc(node *p, long endsite) { long i,j; for (i = 0; i < endsite; i++) for (j = (long)zero; j <= (long)seven; j++) p->discnumnuc[i][j] = 0; } /* zerodiscnumnuc */ void allocnontip(node *p, long *zeros, long endsite) { /* allocate an interior node */ /* used by dnacomp, dnapars, & dnapenny */ p->numsteps = (steptr)Malloc(endsite*sizeof(long)); p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long)); p->base = (baseptr)Malloc(endsite*sizeof(long)); p->oldbase = (baseptr)Malloc(endsite*sizeof(long)); p->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray)); memcpy(p->base, zeros, endsite*sizeof(long)); memcpy(p->numsteps, zeros, endsite*sizeof(long)); memcpy(p->oldbase, zeros, endsite*sizeof(long)); memcpy(p->oldnumsteps, zeros, endsite*sizeof(long)); zeronumnuc(p, endsite); } /* allocnontip */ void allocdiscnontip(node *p, long *zeros, unsigned char *zeros2, long endsite) { /* allocate an interior node */ /* used by pars */ p->numsteps = (steptr)Malloc(endsite*sizeof(long)); p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long)); p->discbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char)); p->olddiscbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char)); p->discnumnuc = (discnucarray *)Malloc(endsite*sizeof(discnucarray)); memcpy(p->discbase, zeros2, endsite*sizeof(unsigned char)); memcpy(p->numsteps, zeros, endsite*sizeof(long)); memcpy(p->olddiscbase, zeros2, endsite*sizeof(unsigned char)); memcpy(p->oldnumsteps, zeros, endsite*sizeof(long)); zerodiscnumnuc(p, endsite); } /* allocdiscnontip */ void allocnode(node **anode, long *zeros, long endsite) { /* allocate a node */ /* used by dnacomp, dnapars, & dnapenny */ *anode = (node *)Malloc(sizeof(node)); allocnontip(*anode, zeros, endsite); } /* allocnode */ void allocdiscnode(node **anode, long *zeros, unsigned char *zeros2, long endsite) { /* allocate a node */ /* used by pars */ *anode = (node *)Malloc(sizeof(node)); allocdiscnontip(*anode, zeros, zeros2, endsite); } /* allocdiscnontip */ void gnutreenode(node **grbg, node **p, long i, long endsite, long *zeros) { /* this and the following are do-it-yourself garbage collectors. Make a new node or pull one off the garbage list */ if (*grbg != NULL) { *p = *grbg; *grbg = (*grbg)->next; memcpy((*p)->numsteps, zeros, endsite*sizeof(long)); memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long)); memcpy((*p)->base, zeros, endsite*sizeof(long)); memcpy((*p)->oldbase, zeros, endsite*sizeof(long)); zeronumnuc(*p, endsite); } else allocnode(p, zeros, endsite); (*p)->back = NULL; (*p)->next = NULL; (*p)->tip = false; (*p)->visited = false; (*p)->index = i; (*p)->numdesc = 0; (*p)->sumsteps = 0.0; } /* gnutreenode */ void gnudisctreenode(node **grbg, node **p, long i, long endsite, long *zeros, unsigned char *zeros2) { /* this and the following are do-it-yourself garbage collectors. Make a new node or pull one off the garbage list */ if (*grbg != NULL) { *p = *grbg; *grbg = (*grbg)->next; memcpy((*p)->numsteps, zeros, endsite*sizeof(long)); memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long)); memcpy((*p)->discbase, zeros2, endsite*sizeof(unsigned char)); memcpy((*p)->olddiscbase, zeros2, endsite*sizeof(unsigned char)); zerodiscnumnuc(*p, endsite); } else allocdiscnode(p, zeros, zeros2, endsite); (*p)->back = NULL; (*p)->next = NULL; (*p)->tip = false; (*p)->visited = false; (*p)->index = i; (*p)->numdesc = 0; (*p)->sumsteps = 0.0; } /* gnudisctreenode */ void setupnode(node *p, long i) { /* initialization of node pointers, variables */ p->next = NULL; p->back = NULL; p->times_in_tree = (double) i * 1.0; p->index = i; p->tip = false; } /* setupnode */ node *pnode(tree *t, node *p) { /* Get the "parent nodelet" of p's node group */ return t->nodep[p->index - 1]; } long count_sibs (node *p) { /* Count the number of nodes in a ring, return the total number of */ /* nodes excluding the one passed into the function (siblings) */ node *q; long return_int = 0; if (p->tip) { printf ("Error: the function count_sibs called on a tip. This is a bug.\n"); exxit (-1); } q = p->next; while (q != p) { if (q == NULL) { printf ("Error: a loop of nodes was not closed.\n"); exxit (-1); } else { return_int++; q = q->next; } } return return_int; } /* count_sibs */ void inittrav (node *p) { /* traverse to set pointers uninitialized on inserting */ long i, num_sibs; node *sib_ptr; if (p == NULL) return; if (p->tip) return; num_sibs = count_sibs (p); sib_ptr = p; for (i=0; i < num_sibs; i++) { sib_ptr = sib_ptr->next; sib_ptr->initialized = false; inittrav(sib_ptr->back); } } /* inittrav */ void commentskipper(FILE ***intree, long *bracket) { /* skip over comment bracket contents in reading tree */ char c; c = gettc(**intree); while (c != ']') { if(feof(**intree)) { printf("\n\nERROR: Unmatched comment brackets\n\n"); exxit(-1); } if(c == '[') { (*bracket)++; commentskipper(intree, bracket); } c = gettc(**intree); } (*bracket)--; } /* commentskipper */ long countcomma(FILE **treefile, long *comma) { /* Modified by Dan F. 11/10/96 */ /* 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 */ /* The next line inserted so this function leaves the file pointing to where it found it, not just re-winding it. */ /* long orig_position = ftell (*treefile); */ fpos_t orig_position; Char c; long lparen = 0; long bracket = 0; /* Save the file position */ if ( fgetpos(*treefile, &orig_position) != 0 ) { printf("\n\nERROR: Could not save file position!\n\n"); exxit(-1); } (*comma) = 0; for (;;){ c = getc(*treefile); if (feof(*treefile)) break; if (c == ';') break; if (c == ',') (*comma)++; if (c == '(') lparen++; if (c == '[') { bracket++; commentskipper(&treefile, &bracket); } } /* Don't just rewind, */ /* rewind (*treefile); */ /* Re-set to where it pointed when the function was called */ /* fseek (*treefile, orig_position, SEEK_SET); */ fsetpos(*treefile, &orig_position); return lparen + (*comma); } /*countcomma*/ 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)) { ungetc(c, *treefile); if (fscanf((*treefile), "%ld", &return_val) != 1) { printf("Error reading number of trees in tree file.\n\n"); exxit(-1); } } 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 */ assert(p != NULL); assert(q != NULL); p->back = q; q->back = p; } /* hookup */ void unhookup(node *p, node *q) { /* unhook two nodes. Not strictly required, but helps check assumptions */ assert(p != NULL); assert(q != NULL); assert(p->back != NULL); assert(q->back != NULL); assert(p->back == q); assert(q->back == p); p->back = NULL; q->back = NULL; } 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)); p->underflows = (double *)Malloc(endsite * sizeof(double)); 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)); p->underflows = (double *)Malloc(endsite*sizeof(double)); 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 reads a name from treefile and stores it in *str. Returns the length of the name string. str must be at least MAXNCH bytes, but no effort is made to null-terminate the string. Underscores and newlines are converted to spaces. Characters beyond MAXNCH are discarded. */ long name_length = 0; do { /*if ((*ch) == '_') (*ch) = ' ';*/ //if ( name_length < MAXNCH ) str[name_length++] = (*ch); if (eoln(treefile)) scan_eoln(treefile); (*ch) = gettc(treefile); if (*ch == '\n') (*ch) = gettc(treefile); // *ch = ' '; } while ( strchr(":,)[;", *ch) == NULL ); str[name_length] = 0; 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; int l; n = 1; do { found = true; //for (i = 0; i < nmlngth; i++) { l = strlen(str) + 1; for (i = 0; i < l; 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, boolean unifok, long maxnodes) { /* 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+1]; Char str[500+1]; node *r; long furs = 0; if ((*ch) == '(') { (*nextnode)++; /* get ready to use new interior node */ nodei = *nextnode; /* do what needs to be done at bottom */ if ( maxnodes != -1 && nodei > maxnodes) { printf("ERROR in input tree file: Attempting to allocate too\n"); printf("many nodes. This is usually caused by a unifurcation.\n"); printf("To use this tree with this program use Retree to read\n"); printf("and write this tree.\n"); exxit(-1); } /* 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 */ furs++; (*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 */ /* handle blank names */ if((*ch) == ',' || (*ch) == ':'){ ungetc((*ch), treefile); *ch = 0; } else if((*ch)==')'){ ungetc((*ch), treefile); (*parens)++; *ch = 0; } addelement(&(*p)->next->back, (*p)->next, ch, parens, treefile, treenode, goteof, first, nodep, nextnode, ntips, haslengths, grbg, initnode, unifok, maxnodes); (*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) != ':'); } } if ( furs <= 1 && !unifok ) { printf("ERROR in input tree file: A Unifurcation was detetected.\n"); printf("To use this tree with this program use retree to read and"); printf(" write this tree\n"); exxit(-1); } (*p)->next = pfirst; (*p) = pfirst; } else if ((*ch) != ')') { /* if it's a species name */ for (i = 0; i < MAXNCH+1; 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); /* do what needs to be done to variable iter */ 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, boolean unifok, long maxnodes) { /* read in user-defined tree and set it up */ /* Eats blank lines and everything up to the first open paren, then * calls the recursive function addelement, which builds the * tree and calls back to initnode. */ 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); } if (haslengths != NULL) *haslengths = true; addelement(root, NULL, &ch, &parens, treefile, treenode, goteof, first, nodep, nextnode, &ntips, haslengths, grbg, initnode, unifok, maxnodes); /* Eat blank lines and end of current line*/ do { scan_eoln(treefile); } while (eoln(treefile) && !eoff(treefile)); if (first) *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, boolean unifok, long maxnodes) { /* 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; long furs = 0; if ((*ch) == '(') { current_loop_index = (*nextnode) + spp; (*nextnode)++; if ( maxnodes != -1 && current_loop_index > maxnodes) { printf("ERROR in intree file: Attempting to allocate too many nodes\n"); printf("This is usually caused by a unifurcation. To use this\n"); printf("intree with this program use retree to read and write\n"); printf("this tree.\n"); exxit(-1); } /* This is an assignment of an interior node */ p = treenode[current_loop_index]; pfirst = p; notlast = true; while (notlast) { furs++; /* 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, unifok, maxnodes); if ((*ch) == ')') { notlast = false; do { getch(ch, parens, treefile); } while ((*ch) != ',' && (*ch) != ')' && (*ch) != '[' && (*ch) != ';' && (*ch) != ':'); } } if ( furs <= 1 && !unifok ) { printf("ERROR in intree file: A Unifurcation was detected.\n"); printf("To use this intree with this program use retree to read and"); printf(" write this tree\n"); exxit(-1); } } 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)) { if (fscanf(treefile, "%lf", trweight) == 1) { 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 { printf("\n\nERROR: Expecting tree weight in last comment field.\n\n"); exxit(-1); } } } else if ((*ch) == ';') { (*trweight) = 1.0 ; if (!eoln(treefile)) printf("WARNING: tree weight set to 1.0\n"); } else if (haslengths != NULL) (*haslengths) = ((*haslengths) && q == NULL); if (q != NULL) hookup(q, pfirst); 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; } } } } /* addelement2 */ void treeread2 (FILE *treefile, node **root, pointarray treenode, boolean lngths, double *trweight, boolean *goteof, boolean *haslengths, long *no_species, boolean unifok, long maxnodes) { /* 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, unifok, maxnodes); (*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) { /* Terminate the program with exit code exitcode. * On Windows, supplying a nonzero exitcode will print a message and wait * for the user to hit enter. */ #ifdef WIN32 phyRestoreConsoleAttributes(); #endif exit (exitcode); } /* exxit */ char gettc(FILE* file) { /* Return the next character in file. * If EOF is reached, print an error and die. * DOS ('\r\n') and Mac ('\r') newlines are returned as a single '\n'. */ int ch; ch=getc(file); if ( ch == EOF ) EOF_error(); if ( ch == '\r' ) { ch = getc(file); if ( ch != '\n' ) ungetc(ch, file); ch = '\n'; } return ch; } /* gettc */ void unroot(tree *t, long nonodes) { /* used by fitch, restml and contml */ if (t->start->back == NULL) { if (t->start->next->back->tip) t->start = t->start->next->next->back; else t->start = t->start->next->back; } if (t->start->next->back == NULL) { if (t->start->back->tip) t->start = t->start->next->next->back; else t->start = t->start->back; } if (t->start->next->next->back == NULL) { if (t->start->back->tip) t->start = t->start->next->back; else t->start = t->start->back; } unroot_r(t->start,t->nodep,nonodes); unroot_r(t->start->back, t->nodep, nonodes); } void unroot_here(node* root, node** nodep, long nonodes) { node* tmpnode; double newl; /* used by unroot */ /* assumes bifurcation this is ok in the programs that use it */ newl = root->next->oldlen + root->next->next->oldlen; root->next->back->oldlen = newl; root->next->next->back->oldlen = newl; newl = root->next->v + root->next->next->v; root->next->back->v = newl; root->next->next->back->v = newl; root->next->back->back=root->next->next->back; root->next->next->back->back = root->next->back; while ( root->index != nonodes ) { tmpnode = nodep[ root->index ]; nodep[root->index] = root; root->index++; root->next->index++; root->next->next->index++; nodep[root->index - 2] = tmpnode; tmpnode->index--; tmpnode->next->index--; tmpnode->next->next->index--; } } void unroot_r(node* p, node** nodep, long nonodes) { /* used by unroot */ node *q; if ( p->tip) return; q = p->next; while ( q != p ) { if (q->back == NULL) unroot_here(q, nodep, nonodes); else unroot_r(q->back, nodep, nonodes); q = q->next; } } void clear_connections(tree *t, long nonodes) { long i; node *p; for ( i = 0 ; i < nonodes ; i++) { p = t->nodep[i]; if (p != NULL) { p->back = NULL; p->v = 0; for (p = p->next; p && p != t->nodep[i]; p = p->next) { p->next->back = NULL; p->next->v = 0; } } } } #ifdef WIN32 void phySaveConsoleAttributes() { if ( GetConsoleScreenBufferInfo(hConsoleOutput, &savecsbi) ) savecsbi_valid = true; } /* PhySaveConsoleAttributes */ void phySetConsoleAttributes() { hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); if ( hConsoleOutput == INVALID_HANDLE_VALUE ) hConsoleOutput = NULL; if ( hConsoleOutput != NULL ) { phySaveConsoleAttributes(); SetConsoleTextAttribute(hConsoleOutput, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY); } } /* phySetConsoleAttributes */ void phyRestoreConsoleAttributes() { COORD coordScreen = { 0, 0 }; DWORD cCharsWritten; DWORD dwConSize; printf("Press enter to quit.\n"); fflush(stdout); getchar(); if ( savecsbi_valid ) { dwConSize = savecsbi.dwSize.X * savecsbi.dwSize.Y; SetConsoleTextAttribute(hConsoleOutput, savecsbi.wAttributes); FillConsoleOutputAttribute( hConsoleOutput, savecsbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ); } } /* phyRestoreConsoleAttributes */ void phyFillScreenColor() { COORD coordScreen = { 0, 0 }; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ DWORD dwConSize; if ( GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ) ) { dwConSize = csbi.dwSize.X * csbi.dwSize.Y; FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ); } } /* phyFillScreenColor */ void phyClearScreen() { COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */ DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ DWORD dwConSize; /* number of character cells in the current buffer */ /* get the number of character cells in the current buffer */ if ( GetConsoleScreenBufferInfo(hConsoleOutput, &csbi) ) { dwConSize = csbi.dwSize.X * csbi.dwSize.Y; /* fill the entire screen with blanks */ FillConsoleOutputCharacter( hConsoleOutput, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten ); /* get the current text attribute */ GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ); /* now set the buffer's attributes accordingly */ FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ); /* put the cursor at (0, 0) */ SetConsoleCursorPosition( hConsoleOutput, coordScreen ); } } /* phyClearScreen */ #endif /* WIN32 */ /* These functions are temporarily used for translating the fixed-width * space-padded nayme array to an array of null-terminated char *. */ char **stringnames_new(void) { /* Copy nayme array to null terminated strings and return array of char *. * Spaces are stripped from end of naym's. * Returned array size is spp+1; last element is NULL. */ char **names; char *ch; long len, i; names = (char **)Malloc((spp+1) * sizeof(char *)); for ( i = 0; i < spp; i++ ) { len = strlen(nayme[i]); names[i] = (char *)Malloc((MAXNCH+1) * sizeof(char)); strncpy(names[i], nayme[i], MAXNCH); names[i][MAXNCH] = '\0'; /* Strip trailing spaces */ for ( ch = names[i] + MAXNCH - 1; *ch == ' ' || *ch == '\0'; ch-- ) *ch = '\0'; } names[spp] = NULL; return names; } void stringnames_delete(char **names) { /* Free a string array returned by stringnames_new() */ long i; assert( names != NULL ); for ( i = 0; i < spp; i++ ) { assert( names[i] != NULL ); free(names[i]); } free(names); } int fieldwidth_double(double val, unsigned int precision) { /* Printf a double to a temporary buffer with specified precision using %g * and return its length. Precision must not be greater than 999,999 */ char format[10]; char buf[0x200]; /* TODO: What's the largest possible? */ if (precision > 999999) abort(); sprintf(format, "%%.%uf", precision); /* %.Nf */ /* snprintf() would be better, but is it avaliable on all systems? */ return sprintf(buf, format, val); } void output_matrix_d(FILE *fp, double **matrix, unsigned long rows, unsigned long cols, char **row_head, char **col_head, int flags) { /* * Print a matrix of double to file. Headings are given in row_head and * col_head, either of which may be NULL to indicate that headings should not * be printed. Otherwise, they must be null-terminated arrays of pointers to * null-terminalted character arrays. * * The macro OUTPUT_PRECISION defines the number of significant figures to * print, and OUTPUT_TEXTWIDTH defines the maximum length of each line. * * Optional formatting is specified by flags argument, using macros MAT_* * defined in phylip.h. */ unsigned *colwidth; /* [0..spp-1] min width of each column */ unsigned headwidth; /* min width of row header column */ unsigned long linelen; /* length of current printed line */ unsigned fw; unsigned long row, col; unsigned long i; unsigned long cstart, cend; unsigned long textwidth = OUTPUT_TEXTWIDTH; const unsigned int gutter = 1; boolean do_block; boolean lower_triangle; boolean border; boolean output_cols; boolean pad_row_head; if ( flags & MAT_NOHEAD ) col_head = NULL; if ( flags & MAT_NOBREAK ) textwidth = 0; do_block = (flags & MAT_BLOCK) && (textwidth > 0); lower_triangle = flags & MAT_LOWER; border = flags & MAT_BORDER; output_cols = flags & MAT_PCOLS; pad_row_head = flags & MAT_PADHEAD; /* Determine minimal width for row headers, if given */ headwidth = 0; if ( row_head != NULL ) { for (row = 0; row < rows; row++) { fw = strlen(row_head[row]); if ( headwidth < fw ) headwidth = fw; } } /* Enforce minimum of 10 ch for machine-readable output */ if ( (pad_row_head) && (headwidth < 10) ) headwidth = 10; /* Determine minimal width for each matrix col */ colwidth = (unsigned int *)Malloc(spp * sizeof(int)); for (col = 0; col < cols; col++) { if ( col_head != NULL ) colwidth[col] = strlen(col_head[col]); else colwidth[col] = 0; for (row = 0; row < rows; row++) { fw = fieldwidth_double(matrix[row][col], PRECISION); if ( colwidth[col] < fw ) colwidth[col] = fw; } } /*** Print the matrix ***/ /* Number of columns if requested */ if ( output_cols ) { fprintf(fp, "%5lu\n", cols); } /* Omit last column for lower triangle */ if ( lower_triangle ) cols--; /* Blocks */ cstart = cend = 0; while ( cend != cols ) { if ( do_block ) { linelen = headwidth; for ( col = cstart; col < cols; col++ ) { if ( linelen + colwidth[col] + gutter > textwidth ) { break; } linelen += colwidth[col] + gutter; } cend = col; /* Always print at least one, regardless of line len */ if ( cend == cstart ) cend++; } else { cend = cols; } /* Column headers */ if ( col_head != NULL ) { /* corner space */ for ( i = 0; i < headwidth; i++ ) putc(' ', fp); if ( border ) { for ( i = 0; i < gutter+1; i++ ) putc(' ', fp); } /* Names */ for ( col = cstart; col < cend; col++ ) { for ( i = 0; i < gutter; i++ ) putc(' ', fp); /* right justify */ fw = strlen(col_head[col]); for ( i = 0; i < colwidth[col] - fw; i++ ) putc(' ', fp); fputs(col_head[col], fp); } putc('\n', fp); } /* Top border */ if ( border ) { for ( i = 0; i < headwidth + gutter; i++ ) putc(' ', fp); putc('\\', fp); for ( col = cstart; col < cend; col++ ) { for ( i = 0; i < colwidth[col] + gutter; i++ ) putc('-', fp); } putc('\n', fp); } /* Rows */ for (row = 0; row < rows; row++) { /* Row header, if given */ if ( row_head != NULL ) { /* right-justify for non-machine-readable */ if ( !pad_row_head ) { for ( i = strlen(row_head[row]); i < headwidth; i++ ) putc(' ', fp); } fputs(row_head[row], fp); /* left-justify for machine-readable */ if ( pad_row_head ) { for ( i = strlen(row_head[row]); i < headwidth; i++ ) putc(' ', fp); } } linelen = headwidth; /* Left border */ if ( border ) { for ( i = 0; i < gutter; i++ ) putc(' ', fp); putc('|', fp); linelen += 2; } /* Row data */ for (col = cstart; col < cend; col++) { /* cols */ /* Stop after col == row for lower triangle */ if ( lower_triangle && col >= row ) break; /* Break line if going over max text width */ if ( !do_block && textwidth > 0 ) { if ( linelen + colwidth[col] > textwidth ) { putc('\n', fp); linelen = 0; } linelen += colwidth[col] + gutter; } for ( i = 0; i < gutter; i++ ) putc(' ', fp); /* Print the datum */ fprintf(fp, "%*.6f", colwidth[col], matrix[row][col]); } putc('\n', fp); } /* End of row */ if (col_head != NULL) putc('\n', fp); /* blank line */ cstart = cend; } /* End of block */ free(colwidth); } /* output_matrix_d */ seaview/csrc/phylip.h000644 000765 000024 00000061456 12410062011 015433 0ustar00mgouystaff000000 000000 #ifndef _PHYLIP_H_ #define _PHYLIP_H_ /* version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe, Mike Palczewski, Doug Buxton and Dan Fineman. Copyright (c) 1980-2014, Joseph Felsenstein All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define VERSION "3.696" /* Debugging options */ /* Define this to disable assertions */ #define NDEBUG /* Define this to enable debugging code */ /* #define DEBUG */ /* machine-specific stuff: based on a number of factors in the library stdlib.h, we will try to determine what kind of machine/compiler this program is being built on. However, it doesn't always succeed. However, if you have ANSI conforming C, it will probably work. We will try to figure out machine type based on defines in stdio, and compiler-defined things as well.: */ #include #include #ifdef WIN32 #include void phyClearScreen(void); void phySaveConsoleAttributes(void); void phySetConsoleAttributes(void); void phyRestoreConsoleAttributes(void); void phyFillScreenColor(void); #endif #ifdef GNUDOS #define DJGPP #define DOS #endif #ifdef THINK_C #define MAC #endif #ifdef __MWERKS__ #ifndef WIN32 #define MAC #endif #endif #ifdef __CMS_OPEN #define CMS #define EBCDIC true #define INFILE "infile data" #define OUTFILE "outfile data" #define FONTFILE "fontfile data" #define PLOTFILE "plotfile data" #define INTREE "intree data" #define INTREE2 "intree data 2" #define OUTTREE "outtree data" #define CATFILE "categories data" #define WEIGHTFILE "weights data" #define ANCFILE "ancestors data" #define MIXFILE "mixture data" #define FACTFILE "factors data" #else #define EBCDIC false #define INFILE "infile" #define OUTFILE "outfile" #define FONTFILE "fontfile" /* on unix this might be /usr/local/lib/fontfile */ #define PLOTFILE "plotfile" #define INTREE "intree" #define INTREE2 "intree2" #define OUTTREE "outtree" #define CATFILE "categories" #define WEIGHTFILE "weights" #define ANCFILE "ancestors" #define MIXFILE "mixture" #define FACTFILE "factors" #endif #ifdef L_ctermid /* try and detect for sysV or V7. */ #define SYSTEM_FIVE #endif #ifdef sequent #define SYSTEM_FIVE #endif #ifndef SYSTEM_FIVE #include # if defined(_STDLIB_H_) || defined(_H_STDLIB) || defined(H_SCCSID) || defined(unix) # define UNIX # define MACHINE_TYPE "BSD Unix C" # endif #endif #ifdef __STDIO_LOADED #define VMS #define MACHINE_TYPE "VAX/VMS C" #endif #ifdef __WATCOMC__ #define QUICKC #define WATCOM #define DOS #include "graph.h" #endif /* watcom-c has graphics library calls that are almost identical to * * quick-c, so the "QUICKC" symbol name stays. */ #ifdef _QC #define MACHINE_TYPE "MS-DOS / Quick C" #define QUICKC #include "graph.h" #define DOS #endif #ifdef _DOS_MODE #define MACHINE_TYPE "MS-DOS /Microsoft C " #define DOS /* DOS is always defined if on a DOS machine */ #define MSC /* MSC is defined for microsoft C */ #endif #ifdef __MSDOS__ /* TURBO c compiler, ONLY (no other DOS C compilers) */ #define DOS #define TURBOC #include #include #endif #ifdef DJGPP /* DJ Delorie's original gnu C/C++ port */ #include #endif #ifndef MACHINE_TYPE #define MACHINE_TYPE "ANSI C" #endif #ifdef DOS #define MALLOCRETURN void #else #define MALLOCRETURN void #endif #ifdef VMS #define signed /* signed doesn't exist in VMS */ #endif /* default screen types */ /* if on a DOS but not a Windows system can use IBM PC screen controls */ #ifdef DOS #ifndef WIN32 #define IBMCRT true #define ANSICRT false #endif #endif /* if on a Mac cannot use screen controls */ #ifdef MAC #define IBMCRT false #define ANSICRT false #endif /* if on a Windows system can use IBM PC screen controls */ #ifdef WIN32 #define IBMCRT true #define ANSICRT false #endif /* otherwise, let's assume we are on a Linux or Unix system with ANSI terminal controls */ #ifndef MAC #ifndef DOS #ifndef WIN32 #define IBMCRT false #define ANSICRT true #endif #endif #endif #ifdef DJGPP #undef MALLOCRETURN #define MALLOCRETURN void #endif /* includes: */ #ifdef UNIX #include #else #include #endif #include #include #include /* #ifdef MAC #ifdef DRAW #include "interface.h" #else #include "macface.h" #endif #define getch gettch #endif */ /* directory delimiters */ #ifdef MAC #define DELIMITER ':' #else #ifdef WIN32 #define DELIMITER '\\' #else #define DELIMITER '/' #endif #endif #define FClose(file) if (file) fclose(file) ; file=NULL #define Malloc(x) mymalloc((long)x) typedef void *Anyptr; #define Signed signed #define Const const #define Volatile volatile #define Char char /* Characters (not bytes) */ #define Static static /* Private global funcs and vars */ #define Local static /* Nested functions */ typedef unsigned char boolean; #define true 1 #define false 0 /* Number of items per machine word in set. * Used in consensus programs and clique */ #define SETBITS 31 MALLOCRETURN *mymalloc(long); /*** UI behavior ***/ /* Set to 1 to not ask before overwriting files */ #define OVERWRITE_FILES 0 /*** Static memory parameters ***/ #define FNMLNGTH 200 /* length of array to store a file name */ //#define nmlngth 10 /* number of characters in species name */ #define MAXNCH 20 /* must be greater than or equal to nmlngth */ #define maxcategs 9 /* maximum number of site types */ #define maxcategs2 11 /* maximum number of site types + 2 */ #define point "." #define pointe '.' #define down 2 #define MAXSHIMOTREES 100 /*** Maximum likelihood parameters ***/ /* Used in proml, promlk, dnaml, dnamlk, etc. */ #define UNDEFINED 1.0 /* undefined or invalid likelihood */ #define smoothings 4 /* number of passes through smoothing algorithm */ #define iterations 8 /* number of iterates for each branch */ #define epsilon 0.0001 /* small number used in makenewv */ #define EPSILON 0.00001 /* small number used in hermite root-finding */ #define initialv 0.1 /* starting branch length unless otherwise */ #define INSERT_MIN_TYME 0.0001 /* Minimum tyme between nodes during inserts */ #define over 60 /* maximum width all branches of tree on screen */ #define LIKE_EPSILON 1e-10 /* Estimate of round-off error in likelihood * calculations. */ /*** Math constants ***/ #define SQRTPI 1.7724538509055160273 #define SQRT2 1.4142135623730950488 /*** Rearrangement parameters ***/ #define NLRSAVES 5 /* number of views that need to be saved during local * * rearrangement */ /*** Output options ***/ /* Number of significant figures to display in numeric output */ #define PRECISION 6 /* Maximum line length of matrix output - 0 for unlimited */ #define OUTPUT_TEXTWIDTH 78 /** output_matrix() flags **/ /* Block output: Matrices are vertically split into blocks that * fit within OUTPUT_TEXTWIDTH columns */ #define MAT_BLOCK 0x1 /* Lower triangle: Values on or above the diagonal are not printed */ #define MAT_LOWER 0x2 /* Print a border between headings and data */ #define MAT_BORDER 0x4 /* Do not print the column header */ #define MAT_NOHEAD 0x8 /* Output the number of columns before the matrix */ #define MAT_PCOLS 0x10 /* Do not enforce maximum line width */ #define MAT_NOBREAK 0x20 /* Pad row header with spaces to 10 char */ #define MAT_PADHEAD 0x40 /* Human-readable format. */ #define MAT_HUMAN MAT_BLOCK /* Machine-readable format. */ #define MAT_MACHINE (MAT_PCOLS | MAT_NOHEAD | MAT_PADHEAD) /* Lower-triangular format. */ #define MAT_LOWERTRI (MAT_LOWER | MAT_MACHINE) boolean javarun; typedef long *steptr; typedef long longer[6]; typedef char naym[MAXNCH]; typedef long *bitptr; typedef double raterootarray[maxcategs2][maxcategs2]; typedef struct bestelm { long *btree; boolean gloreange; boolean locreange; boolean collapse; } bestelm; extern FILE *infile, *outfile, *intree, *intree2, *outtree, *weightfile, *catfile, *ancfile, *mixfile, *factfile; extern long spp, words, bits; extern boolean ibmpc, ansi, tranvsp; //extern naym *nayme; /* names of species */ extern char* *nayme; /* names of species */ boolean firstplotblock; // for debugging BMP output #define ebcdic EBCDIC typedef Char plotstring[MAXNCH]; /* Approx. 1GB, used to test for memory request errors */ #define TOO_MUCH_MEMORY 1000000000 /* The below pre-processor commands define the type used to store group arrays. We can't use #elif for metrowerks, so we use cascaded if statements */ #include /* minimum double we feel safe with, anything less will be considered underflow */ #define MIN_DOUBLE 10e-100 /* K&R says that there should be a plus in front of the number, but no machine we've seen actually uses one; we'll include it just in case. */ #define MAX_32BITS 2147483647 #define MAX_32BITS_PLUS +2147483647 /* If ints are 4 bytes, use them */ #if INT_MAX == MAX_32BITS typedef int group_type; #else #if INT_MAX == MAX_32BITS_PLUS typedef int group_type; #else /* Else, if longs are 4 bytes, use them */ #if LONG_MAX == MAX_32BITS typedef long group_type; #else #if LONG_MAX == MAX_32BITS_PLUS typedef long group_type; /* Default to longs */ #else typedef long group_type; #endif #endif #endif #endif /* for many programs */ #define maxuser 1000 /* maximum number of user-defined trees */ typedef Char **sequence; typedef enum { A, C, G, T, O } bases; typedef enum { alanine, arginine, asparagine, aspartic, cysteine, glutamine, glutamic, glycine, histidine, isoleucine, leucine, lysine, methionine, phenylalanine, proline, serine, threonine, tryptophan, tyrosine, valine } acids; /* for Pars */ typedef enum { zero = 0, one, two, three, four, five, six, seven } discbases; /* for Protpars */ typedef enum { ala, arg, asn, asp, cys, gln, glu, gly, his, ileu, leu, lys, met, phe, pro, ser1, ser2, thr, trp, tyr, val, del, stop, asx, glx, ser, unk, quest } aas; typedef double sitelike[(long)T - (long)A + 1]; /* used in dnaml, dnadist */ typedef double psitelike[(long)valine - (long)alanine + 1]; /* used in proml */ typedef long *baseptr; /* baseptr used in dnapars, dnacomp & dnapenny */ typedef long *baseptr2; /* baseptr used in dnamove */ typedef unsigned char *discbaseptr; /* discbaseptr used in pars */ typedef sitelike *ratelike; /* used in dnaml ... */ typedef psitelike *pratelike; /* used in proml */ typedef ratelike *phenotype; /* phenotype used in dnaml, dnamlk, dnadist */ typedef pratelike *pphenotype; /* phenotype used in proml */ typedef double *sitelike2; typedef sitelike2 *phenotype2; /* phenotype2 used in restml */ typedef double *phenotype3; /* for continuous char programs */ typedef double *vector; /* used in distance programs */ typedef long nucarray[(long)O - (long)A + 1]; typedef long discnucarray[(long)seven - (long)zero + 1]; typedef enum { nocollap, tocollap, undefined } collapstates; typedef enum { bottom, nonbottom, hslength, tip, iter, length, hsnolength, treewt, unittrwt } initops; typedef double **transmatrix; typedef transmatrix *transptr; /* transptr used in restml */ typedef long sitearray[3]; typedef sitearray *seqptr; /* seqptr used in protpars */ typedef struct node { struct node *next, *back; plotstring nayme; long naymlength, tipsabove, index; double times_in_tree; /* Previously known as cons_index */ double xcoord, ycoord; long long_xcoord, long_ycoord; /* for use in cons. */ double oldlen, length, r, theta, oldtheta, width, depth, tipdist, lefttheta, righttheta; group_type *nodeset; /* used by accumulate -plc */ long ymin, ymax; /* used by printree -plc */ boolean haslength; /* haslength used in dnamlk */ boolean iter; /* iter used in dnaml, fitch & restml */ boolean initialized; /* initialized used in dnamlk & restml */ long branchnum; /* branchnum used in restml */ phenotype x; /* x used in dnaml, dnamlk, dnadist */ phenotype2 x2; /* x2 used in restml */ phenotype3 view; /* contml etc */ pphenotype protx; /* protx used in proml */ aas *seq; /* the sequence used in protpars */ seqptr siteset; /* temporary storage for aa's used in protpars*/ double v, deltav, ssq; /* ssq used only in contrast */ double bigv; /* bigv used in contml */ double tyme, oldtyme; /* used in dnamlk */ double t; /* time in kitsch */ boolean sametime; /* bookkeeps scrunched nodes in kitsch */ double weight; /* weight of node used by scrunch in kitsch */ boolean processed; /* used by evaluate in kitsch */ boolean deleted; /* true if node is deleted (retree) */ boolean hasname; /* true if tip has a name (retree) */ double beyond; /* distance beyond this node to most distant tip */ /* (retree) */ boolean deadend; /* true if no undeleted nodes beyond this node */ /* (retree) */ boolean onebranch; /* true if there is one undeleted node beyond */ /* this node (retree) */ struct node *onebranchnode; /* if there is, a pointer to that node (retree)*/ double onebranchlength; /* if there is, the distance from here to there*/ /* (retree) */ boolean onebranchhaslength; /* true if there is a valid combined length*/ /* from here to there (retree) */ collapstates collapse; /* used in dnapars & dnacomp */ boolean tip; boolean bottom; /* used in dnapars & dnacomp, disc char */ boolean visited; /* used in dnapars & dnacomp disc char */ baseptr base; /* the sequence in dnapars/comp/penny */ discbaseptr discbase; /* the sequence in pars */ baseptr2 base2; /* the sequence in dnamove */ baseptr oldbase; /* record previous sequence */ discbaseptr olddiscbase; /* record previous sequence */ long numdesc; /* number of immediate descendants */ nucarray *numnuc; /* bookkeeps number of nucleotides */ discnucarray *discnumnuc; /* bookkeeps number of nucleotides */ steptr numsteps; /* bookkeeps steps */ steptr oldnumsteps; /* record previous steps */ double sumsteps; /* bookkeeps sum of steps */ nucarray cumlengths; /* bookkeeps cummulative minimum lengths */ discnucarray disccumlengths; /* bookkeeps cummulative minimum lengths */ nucarray numreconst; /* bookkeeps number of reconstructions */ discnucarray discnumreconst; /* bookkeeps number of reconstructions */ vector d, w; /* for distance matrix programs */ double dist; /* dist used in fitch */ bitptr stateone, statezero; /* discrete char programs */ long maxpos; /* maxpos used in Clique */ Char state; /* state used in Dnamove, Dolmove & Move */ double* underflows; /* used to record underflow */ } node; typedef node **pointarray; /*** tree structure ***/ typedef struct tree { /* An array of pointers to nodes. Each tip node and ring of nodes has a * unique index starting from one. The nodep array contains pointers to each * one, starting from 0. In the case of internal nodes, the entries in nodep * point to the rootward node in the group. Since the trees are otherwise * entirely symmetrical, except at the root, this is the only way to resolve * parent, child, and sibling relationships. * * Indices in range [0, spp) point to tips, while indices [spp, nonodes) * point to fork nodes */ pointarray nodep; /* A pointer to the first node. Typically, root is used when the tree is rooted, * and points to an internal node with no back link. */ node *root; /* start is used when trees are unrooted. It points to an internal node whose * back link typically points to the outgroup leaf. */ node *start; /* In maximum likelihood programs, the most recent evaluation is stored here */ double likelihood; /* Branch transition matrices for restml */ transptr trans; /* all transition matrices */ long *freetrans; /* an array of indexes of free matrices */ long transindex; /* index of last valid entry in freetrans[] */ } tree; typedef void (*initptr)(node **, node **, node *, long, long, long *, long *, initops, pointarray, pointarray, Char *, Char *, FILE *); #ifndef OLDC /* function prototypes */ void scan_eoln(FILE *); boolean eoff(FILE *); boolean eoln(FILE *); int filexists(char *); const char* get_command_name (const char *); void EOF_error(void); void getstryng(char *); void openfile(FILE **,const char *,const char *,const char *,const char *, char *); void cleerhome(void); void loopcount(long *, long); double randum(longer); void randumize(longer, long *); double normrand(longer); long readlong(const char *); void uppercase(Char *); void initseed(long *, long *, longer); void initjumble(long *, long *, longer, long *); void initoutgroup(long *, long); void initthreshold(double *); void initcatn(long *); void initcategs(long, double *); void initprobcat(long, double *, double *); double logfac (long); double halfroot(double (*func)(long , double), long, double, double); double hermite(long, double); void initlaguerrecat(long, double, double *, double *); void root_hermite(long, double *); void hermite_weight(long, double *, double *); void inithermitcat(long, double, double *, double *); void lgr(long, double, raterootarray); double glaguerre(long, double, double); void initgammacat(long, double, double *, double *); void inithowmany(long *, long); void inithowoften(long *); void initlambda(double *); void initfreqs(double *, double *, double *, double *); void initratio(double *); void initpower(double *); void initdatasets(long *); void justweights(long *); void initterminal(boolean *, boolean *); void initnumlines(long *); void initbestrees(bestelm *, long, boolean); void newline(FILE *, long, long, long); void inputnumbers(long *, long *, long *, long); void inputnumbersold(long *, long *, long *, long); void inputnumbers2(long *, long *, long n); void inputnumbers3(long *, long *); void samenumsp(long *, long); void samenumsp2(long); void readoptions(long *, const char *); void matchoptions(Char *, const char *); void inputweights(long, steptr, boolean *); void inputweightsold(long, steptr, boolean *); void inputweights2(long, long, long *, steptr, boolean *, const char *); void printweights(FILE *, long, long, steptr, const char *); void inputcategs(long, long, steptr, long, const char *); void printcategs(FILE *, long, steptr, const char *); void inputfactors(long, Char *, boolean *); void inputfactorsnew(long, Char *, boolean *); void printfactors(FILE *, long, Char *, const char *); void headings(long, const char *, const char *); void initname(long); void findtree(boolean *,long *,long,long *,bestelm *); void addtree(long,long *,boolean,long *,bestelm *); long findunrearranged(bestelm *, long, boolean); boolean torearrange(bestelm *, long); void reducebestrees(bestelm *, long *); void shellsort(double *, long *, long); void getch(Char *, long *, FILE *); void getch2(Char *, long *); void findch(Char, Char *, long); void findch2(Char, long *, long *, Char *); void findch3(Char, Char *, long, long); void processlength(double *,double *,Char *,boolean *,FILE *,long *); void writename(long, long, long *); void memerror(void); void odd_malloc(long); void gnu(node **, node **); void chuck(node **, node *); void zeronumnuc(node *, long); void zerodiscnumnuc(node *, long); void allocnontip(node *, long *, long); void allocdiscnontip(node *, long *, unsigned char *, long ); void allocnode(node **, long *, long); void allocdiscnode(node **, long *, unsigned char *, long ); void gnutreenode(node **, node **, long, long, long *); void gnudisctreenode(node **, node **, long , long, long *, unsigned char *); void setupnode(node *, long); node * pnode(tree *t, node *p); long count_sibs (node *); void inittrav (node *); void commentskipper(FILE ***, long *); long countcomma(FILE **, long *); long countsemic(FILE **); void hookup(node *, node *); void unhookup(node *, node *); void link_trees(long, long , long, pointarray); void allocate_nodep(pointarray *, FILE **, long *); void malloc_pheno(node *, long, long); void malloc_ppheno(node *, long, long); long take_name_from_tree (Char *, Char *, FILE *); void match_names_to_data (Char *, pointarray, node **, long); void addelement(node **, node *, Char *, long *, FILE *, pointarray, boolean *, boolean *, pointarray, long *, long *, boolean *, node **, initptr,boolean,long); void treeread (FILE *, node **, pointarray, boolean *, boolean *, pointarray, long *, boolean *, node **, initptr,boolean,long); void addelement2(node *, Char *, long *, FILE *, pointarray, boolean, double *, boolean *, long *, long *, long, boolean *,boolean, long); void treeread2 (FILE *, node **, pointarray, boolean, double *, boolean *, boolean *, long *,boolean,long); void exxit (int); void countup(long *loopcount, long maxcount); char gettc(FILE* file); void unroot_r(node* p,node ** nodep, long nonodes); void unroot(tree* t,long nonodes); void unroot_here(node* root, node** nodep, long nonodes); void clear_connections(tree *t, long nonodes); void init(int argc, char** argv); char **stringnames_new(void); void stringnames_delete(char **names); int fieldwidth_double(double val, unsigned int precision); void output_matrix_d(FILE *fp, double **matrix, unsigned long rows, unsigned long cols, char **row_head, char **col_head, int flags); void debugtree (tree *, FILE *); void debugtree2 (pointarray, long, FILE *); #endif /* OLDC */ #endif /* _PHYLIP_H_ */ seaview/csrc/phyml_util.c000644 000765 000024 00000037326 12404325714 016325 0ustar00mgouystaff000000 000000 /* extracted from PHYML : a program that computes maximum likelihood phylogenies from DNA or AA homologous sequences Copyright (C) Stephane Guindon. Oct 2003 onward This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . Linking PHYML statically or dynamically with other modules is making a combined work based on PHYML. Thus, the terms and conditions of the GNU General Public License cover the whole combination. In addition, as a special exception, the copyright holders of PHYML give you permission to combine PHYML with free software programs or libraries that are released under the GNU LGPL and with code included in the standard release of PHYLIP under the University of Washington license (or modified versions of such code, with unchanged license). You may copy and distribute such a system following the terms of the GNU GPL for PHYML and the licenses of the other code concerned. Note that people who make modified versions of PHYML are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU General Public License gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception. */ #include "phyml_util.h" extern int tree_build_interrupted; /*********************************************************/ void Warn_And_Exit(char *s) { fprintf(stdout,"%s",s); fflush(NULL); #ifndef BATCH char c; fprintf(stdout,"\n. Type any key to exit.\n"); fscanf(stdin,"%c",&c); #endif exit(1); } /*********************************************************/ void *mCalloc(int nb, size_t size) { void *allocated; if((allocated = calloc((size_t)nb,(size_t)size)) != NULL) { return allocated; } else Warn_And_Exit("\n. Err: low memory\n"); return NULL; } /*********************************************************/ matrix *Make_Mat(int n_otu) { matrix *mat; int i; mat = (matrix *)mCalloc(1,sizeof(matrix)); mat->n_otu = n_otu; mat->P = (phydbl **)mCalloc(n_otu,sizeof(phydbl *)); mat->Q = (phydbl **)mCalloc(n_otu,sizeof(phydbl *)); mat->dist = (phydbl **)mCalloc(n_otu,sizeof(phydbl *)); mat->on_off = (int *)mCalloc(n_otu,sizeof(int)); mat->name = (char **)mCalloc(n_otu,sizeof(char *)); mat->tip_node = (node **)mCalloc(n_otu,sizeof(node *)); For(i,n_otu) { mat->P[i] = (phydbl *)mCalloc(n_otu,sizeof(phydbl)); mat->Q[i] = (phydbl *)mCalloc(n_otu,sizeof(phydbl)); mat->dist[i] = (phydbl *)mCalloc(n_otu,sizeof(phydbl)); } return mat; } /*********************************************************/ void Init_Mat(matrix *mat, allseq *data) { int i; mat->n_otu = data->n_otu; mat->r = mat->n_otu; mat->curr_int = mat->n_otu; mat->method = 1; For(i,data->n_otu) { mat->name[i] = strdup(data->c_seq[i]->name); mat->on_off[i] = 1; } } /*********************************************************/ matrix *JC69_Dist(allseq *data, model *mod) { int site,i,j,k; phydbl x; matrix *mat; phydbl **len; len = (phydbl **)mCalloc(data->n_otu,sizeof(phydbl *)); For(i,data->n_otu) len[i] = (phydbl *)mCalloc(data->n_otu,sizeof(phydbl)); mat = Make_Mat(data->n_otu); Init_Mat(mat,data); Fors(site,data->c_seq[0]->len,mod->stepsize) { if (tree_build_interrupted) { break; } For(j,data->n_otu-1) { for(k=j+1;kn_otu;k++) { if((!Is_Ambigu(data->c_seq[j]->state+site,mod->datatype,mod->stepsize)) && (!Is_Ambigu(data->c_seq[k]->state+site,mod->datatype,mod->stepsize))) { len[j][k]+=data->wght[site]; len[k][j]=len[j][k]; if(strncmp(data->c_seq[j]->state+site, data->c_seq[k]->state+site, mod->stepsize)) mat->P[j][k]+=data->wght[site]; } } } } For(i,data->n_otu-1) for(j=i+1;jn_otu;j++) { if(len[i][j]) { mat->P[i][j] /= len[i][j]; } else { mat->P[i][j] = 1.; } mat->P[j][i] = mat->P[i][j]; x = 1.-(mod->ns/(mod->ns-1.))*mat->P[i][j]; if(x <= .0) { Free_Mat(mat); mat = NULL; goto out; } else mat->dist[i][j] = -((mod->ns-1.)/mod->ns)*(phydbl)log(x); mat->dist[j][i] = mat->dist[i][j]; } out:For(i,data->n_otu) free(len[i]); free(len); return mat; } /*********************************************************/ void Clean_Tree_Connections(arbre *tree) { int i; For(i,2*tree->n_otu-2) { tree->noeud[i]->v[0] = NULL; tree->noeud[i]->v[1] = NULL; tree->noeud[i]->v[2] = NULL; tree->noeud[i]->b[0] = NULL; tree->noeud[i]->b[1] = NULL; tree->noeud[i]->b[2] = NULL; } } /*********************************************************/ void Make_Tree_Path(arbre *tree) { tree->curr_path = (node **)mCalloc(tree->n_otu,sizeof(node *)); } /*********************************************************/ void Init_Node_Light(node *n, int num) { n->list_of_reachable_tips = NULL; n->num = num; n->tax = -1; } /*********************************************************/ node *Make_Node_Light(int num) { node *n; n = (node *)mCalloc(1,sizeof(node)); n->v = (node **)mCalloc(3,sizeof(node *)); n->l = (phydbl *)mCalloc(3,sizeof(phydbl)); n->b = (edge **)mCalloc(3,sizeof(edge *)); n->score = (phydbl *)mCalloc(3,sizeof(phydbl)); Init_Node_Light(n,num); return n; } /*********************************************************/ void Make_All_Tree_Nodes(arbre *tree) { int i; tree->noeud = (node **)mCalloc(2*tree->n_otu-2,sizeof(node *)); tree->t_dead_nodes = (node **)mCalloc(2*tree->n_otu-2,sizeof(node *)); For(i,2*tree->n_otu-2) { tree->noeud[i] = (node *)Make_Node_Light(i); if(i < tree->n_otu) tree->noeud[i]->tax = 1; else tree->noeud[i]->tax = 0; } } /*********************************************************/ void Init_Tree(arbre *tree, int n_otu) { tree->n_otu = n_otu; tree->best_tree = NULL; tree->old_tree = NULL; tree->mat = NULL; tree->depth_curr_path = 0; tree->has_bip = 0; tree->n_moves = 0; tree->n_improvements = 0; tree->number_of_lk_calls = 0; tree->number_of_branch_lk_calls = 0; tree->init_lnL = UNLIKELY; tree->best_lnL = UNLIKELY; tree->c_lnL = UNLIKELY; tree->lnL_lower_bound = UNLIKELY; tree->n_swap = 0; tree->n_pattern = -1; tree->prop_of_sites_to_consider = 1.; tree->branch_and_bound = 0; tree->print_boot_val = 0; tree->print_alrt_val = 0; tree->num_curr_branch_available = 0; } /*********************************************************/ arbre *Make_Tree(int n_otu) { arbre *tree; int i; tree = (arbre *)mCalloc(1,sizeof(arbre )); Init_Tree(tree,n_otu); tree->t_dir = (int **)mCalloc(2*n_otu-2,sizeof(int *)); For(i,2*n_otu-2) tree->t_dir[i] = (int *)mCalloc(2*n_otu-2,sizeof(int)); return tree; } /*********************************************************/ void Copy_Tax_Names_To_Tip_Labels(arbre *tree, allseq *data) { int i; For(i,tree->n_otu) { tree->noeud[i]->name = strdup(data->c_seq[i]->name); tree->noeud[i]->tax = 1; tree->noeud[i]->num = i; } } /*********************************************************/ void Make_List_Of_Reachable_Tips(arbre *tree) { int i,j; For(i,2*tree->n_otu-2) { tree->noeud[i]->list_of_reachable_tips = (node ***)mCalloc(3,sizeof(node **)); tree->noeud[i]->n_of_reachable_tips = (int *)mCalloc(3,sizeof(int)); For(j,3) tree->noeud[i]->list_of_reachable_tips[j] = (node **)mCalloc(tree->n_otu,sizeof(node *)); } } /*********************************************************/ void Init_Edge_Light(edge *b, int num) { b->num = num; b->bip_score = 0; b->dist_btw_edges = .0; b->topo_dist_btw_edges = 0; b->has_zero_br_len = 0; b->is_p_lk_l_u2d = 0; b->is_p_lk_r_u2d = 0; b->p_lk_left = NULL; b->p_lk_rght = NULL; b->Pij_rr = NULL; } /*********************************************************/ void Make_Edge_Dirs(edge *b, node *a, node *d) { int i; if(a == b->rght) { printf("\n. a->num = %3d ; d->num = %3d",a->num,d->num); printf("\n. Err in file %s at line %d\n",__FILE__,__LINE__); Warn_And_Exit(""); } if(d == b->left) { printf("\n. a->num = %3d ; d->num = %3d",a->num,d->num); printf("\n. Err in file %s at line %d\n",__FILE__,__LINE__); Warn_And_Exit(""); } b->l_r = b->r_l = -1; For(i,3) { if((a->v[i]) && (a->v[i] == d)) { b->l_r = i; /* we consider here that 'a' is on the left handside of 'b'*/ a->b[i] = b; } if((d->v[i]) && (d->v[i] == a)) { b->r_l = i; /* we consider here that 'd' is on the right handside of 'b'*/ d->b[i] = b; } } if(a->tax) {b->r_l = 0; For(i,3) if(d->v[i]==a) {b->l_r = i; break;}} b->l_v1 = b->l_v2 = b->r_v1 = b->r_v2 = -1; For(i,3) { if(b->left->v[i] != b->rght) { if(b->l_v1 < 0) b->l_v1 = i; else b->l_v2 = i; } if(b->rght->v[i] != b->left) { if(b->r_v1 < 0) b->r_v1 = i; else b->r_v2 = i; } } } /*********************************************************/ edge *Make_Edge_Light(node *a, node *d, int num) { edge *b; b = (edge *)mCalloc(1,sizeof(edge)); Init_Edge_Light(b,num); if(a && b) { b->left = a; b->rght = d; if(a->tax) {b->rght = a; b->left = d;} /* root */ /* a tip is necessary on the right side of the edge */ (b->left == a)? (Make_Edge_Dirs(b,a,d)): (Make_Edge_Dirs(b,d,a)); b->l = a->l[b->l_r]; if(a->tax) b->l = a->l[b->r_l]; if(b->l < BL_MIN) b->l = BL_MIN; else if(b->l > BL_MAX) b->l = BL_MAX; b->l_old = b->l; } else { b->left = NULL; b->rght = NULL; } return b; } /*********************************************************/ void Make_All_Tree_Edges(arbre *tree) { int i; tree->t_edges = (edge **)mCalloc(2*tree->n_otu-3,sizeof(edge *)); tree->t_dead_edges = (edge **)mCalloc(2*tree->n_otu-3,sizeof(edge *)); For(i,2*tree->n_otu-3) tree->t_edges[i] = (edge *)Make_Edge_Light(NULL,NULL,i); } /*********************************************************/ arbre *Make_Tree_From_Scratch(int n_otu, allseq *data) { arbre *tree; tree = Make_Tree(n_otu); Make_All_Tree_Nodes(tree); Make_All_Tree_Edges(tree); Make_Tree_Path(tree); Make_List_Of_Reachable_Tips(tree); if(data) { Copy_Tax_Names_To_Tip_Labels(tree,data); tree->data = data; } return tree; } /*********************************************************/ int Is_Ambigu(char *state, int datatype, int stepsize) { int i; if(datatype == NT) { For(i,stepsize) { if(strchr("MRWSYKBDHVNXO?-.",state[i])) return 1; } } else { if(strchr("X?-.",state[0])) return 1; } return 0; } /*********************************************************/ void R_wtree(node *pere, node *fils, char *s_tree, arbre *tree) { int i,p; p = -1; if(fils->tax) { if(OUTPUT_TREE_FORMAT == 0) strcat(s_tree,fils->name); else sprintf(s_tree+(int)strlen(s_tree),"%d",fils->num+1); if((fils->b[0]) && (fils->b[0]->l != -1)) { strcat(s_tree,":"); /* sprintf(s_tree+(int)strlen(s_tree),"%.10f",fils->b[0]->l); */ sprintf(s_tree+(int)strlen(s_tree),"%f",fils->b[0]->l); } sprintf(s_tree+(int)strlen(s_tree),","); } else { s_tree[(int)strlen(s_tree)]='('; For(i,3) { if(fils->v[i] != pere) R_wtree(fils,fils->v[i],s_tree,tree); else p=i; } s_tree[(int)strlen(s_tree)-1]=')'; if(fils->b[0]->l != -1) { if(tree->print_boot_val) sprintf(s_tree+(int)strlen(s_tree),"%d",fils->b[p]->bip_score); else if(tree->print_alrt_val) sprintf(s_tree+(int)strlen(s_tree),"%f",fils->b[p]->ratio_test); strcat(s_tree,":"); /* sprintf(s_tree+(int)strlen(s_tree),"%.10f",fils->b[p]->l); */ sprintf(s_tree+(int)strlen(s_tree),"%f",fils->b[p]->l); strcat(s_tree,","); } } } /*********************************************************/ char *Write_Tree(arbre *tree) { char *s; int i; s=(char *)mCalloc(T_MAX_LINE,sizeof(char)); s[0]='('; i = 0; while((!tree->noeud[tree->n_otu+i]->v[0]) || (!tree->noeud[tree->n_otu+i]->v[1]) || (!tree->noeud[tree->n_otu+i]->v[2])) i++; R_wtree(tree->noeud[tree->n_otu+i],tree->noeud[tree->n_otu+i]->v[0],s,tree); R_wtree(tree->noeud[tree->n_otu+i],tree->noeud[tree->n_otu+i]->v[1],s,tree); R_wtree(tree->noeud[tree->n_otu+i],tree->noeud[tree->n_otu+i]->v[2],s,tree); s[(int)strlen(s)-1]=')'; s[(int)strlen(s)]=';'; return s; } /*********************************************************/ void Connect_One_Edge_To_Two_Nodes(node *a, node *d, edge *b, arbre *tree) { int i,dir_a_d; dir_a_d = -1; For(i,3) if(a->v[i] == d) {dir_a_d = i; break;} a->b[dir_a_d] = b; b->num = tree->num_curr_branch_available; b->left = a; b->rght = d; if(a->tax) {b->rght = a; b->left = d;} /* root */ /* a tip is necessary on the right side of the edge */ (b->left == a)? (Make_Edge_Dirs(b,a,d)): (Make_Edge_Dirs(b,d,a)); b->l = a->l[b->l_r]; if(a->tax) b->l = a->l[b->r_l]; if(b->l < BL_MIN) b->l = BL_MIN; else if(b->l > BL_MAX) b->l = BL_MAX; b->l_old = b->l; } /*********************************************************/ void Free(void *p) { if(p != NULL) free(p); } /*********************************************************/ void Free_Mat(matrix *mat) { int i; For(i,mat->n_otu) { Free(mat->P[i]); Free(mat->Q[i]); Free(mat->dist[i]); Free(mat->name[i]); } Free(mat->P); Free(mat->Q); Free(mat->dist); Free(mat->name); Free(mat->tip_node); Free(mat->on_off); Free(mat); } /*********************************************************/ void Free_Node(node *n) { int i; Free(n->b); Free(n->v); Free(n->l); Free(n->score); Free(n->name); if(n->list_of_reachable_tips) { For(i,3) Free(n->list_of_reachable_tips[i]); Free(n->list_of_reachable_tips); Free(n->n_of_reachable_tips); } Free(n); } /*********************************************************/ void Free_Edge(edge *b) { Free(b); } /*********************************************************/ void Free_Tree(arbre *tree) { int i,j,k; edge *b; node *n; For(i,2*tree->n_otu-2) Free(tree->t_dir[i]); Free(tree->t_dir); if(tree->has_bip) { For(i,2*tree->n_otu-2) { Free(tree->noeud[i]->bip_size); For(j,3) { Free(tree->noeud[i]->bip_node[j]); For(k,tree->n_otu) Free(tree->noeud[i]->bip_name[j][k]); Free(tree->noeud[i]->bip_name[j]); } Free(tree->noeud[i]->bip_node); Free(tree->noeud[i]->bip_name); } } Free(tree->curr_path); For(i,2*tree->n_otu-3) { b = tree->t_edges[i]; Free_Edge(b); } Free(tree->t_edges); For(i,2*tree->n_otu-2) { n = tree->noeud[i]; Free_Node(n); } Free(tree->noeud); For(i,tree->n_dead_edges) Free_Edge(tree->t_dead_edges[i]); For(i,tree->n_dead_nodes) Free_Node(tree->t_dead_nodes[i]); Free(tree->t_dead_edges); Free(tree->t_dead_nodes); Free(tree); } seaview/csrc/phyml_util.h000644 000765 000024 00000054052 12404325714 016325 0ustar00mgouystaff000000 000000 /* extracted from: PHYML : a program that computes maximum likelihood phylogenies from DNA or AA homologous sequences Copyright (C) Stephane Guindon. Oct 2003 onward This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . Linking PHYML statically or dynamically with other modules is making a combined work based on PHYML. Thus, the terms and conditions of the GNU General Public License cover the whole combination. In addition, as a special exception, the copyright holders of PHYML give you permission to combine PHYML with free software programs or libraries that are released under the GNU LGPL and with code included in the standard release of PHYLIP under the University of Washington license (or modified versions of such code, with unchanged license). You may copy and distribute such a system following the terms of the GNU GPL for PHYML and the licenses of the other code concerned. Note that people who make modified versions of PHYML are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU General Public License gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception. */ #ifndef PHYML_UTIL_H #define PHYML_UTIL_H #include #include #include #include #include #include #define VERSION "v3.0" #define For(i,n) for(i=0; i(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a)) #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); #define NNI_MOVE 0 #define SPR_MOVE 1 #define NT 0 /* nucleotides */ #define AA 1 /* amino acids */ #define ACGT 0 /* A,G,G,T encoding */ #define RY 1 /* R,Y encoding */ #define INTERFACE_DATA_TYPE 0 #define INTERFACE_MULTIGENE 1 #define INTERFACE_MODEL 2 #define INTERFACE_TOPO_SEARCH 3 #define INTERFACE_BRANCH_SUPPORT 4 #define N_MAX_OPTIONS 100 #define T_MAX_FILE 100 #define T_MAX_LINE 2000000 #define T_MAX_SEQ 2000000 #define T_MAX_OPTION 100 #define NODE_DEG_MAX 50 #define BRENT_ITMAX 10000 #define BRENT_CGOLD 0.3819660 #define BRENT_ZEPS 1.e-10 #define MNBRAK_GOLD 1.618034 #define MNBRAK_GLIMIT 100.0 #define MNBRAK_TINY 1.e-20 #define ALPHA_MIN 0.04 #define ALPHA_MAX 100 #define BL_MIN 1.e-06 #define BL_START 1.e-04 #define BL_MAX 100.0 #define GOLDEN_R 0.61803399 #define GOLDEN_C (1.0-GOLDEN_R) #define N_MAX_INSERT 20 #define N_MAX_OTU 4000 #define UNLIKELY -1.e10 #define NJ_SEUIL 0.1 #define ROUND_MAX 100 #define AROUND_LK 50.0 #define PROP_STEP 1.0 #define T_MAX_ALPHABET 100 #define MDBL_MIN 2.225074E-308 #define MDBL_MAX 1.797693E+308 #define POWELL_ITMAX 200 #define LINMIN_TOL 2.0E-04 #define LIM_SCALE 3 #define LIM_SCALE_VAL 1.E-50 /* #define LIM_SCALE 3000 */ /* #define LIM_SCALE_VAL 1.E-500 */ #define DEFAULT_SIZE_SPR_LIST 20 #define OUTPUT_TREE_FORMAT 0 /* 0-->Newick; 1-->Nexus */ #define MAX_PARS 1000000000 #define JC69 1 #define K80 2 #define F81 3 #define HKY85 4 #define F84 5 #define TN93 6 #define GTR 7 #define CUSTOM 8 #define WAG 11 #define DAYHOFF 12 #define JTT 13 #define BLOSUM62 14 #define MTREV 15 #define RTREV 16 #define CPREV 17 #define DCMUT 18 #define VT 19 #define MTMAM 20 #define MTART 21 #define HIVW 22 #define HIVB 23 #define CUSTOMAA 24 typedef double phydbl; /*********************************************************/ typedef struct __Node { struct __Node **v; /* table of pointers to neighbor nodes. Dimension = 2 x n_otu - 3 */ struct __Node ***bip_node; /* three lists of pointer to tip nodes. One list for each direction */ struct __Edge **b; /* table of pointers to neighbor branches */ struct __Node ***list_of_reachable_tips; /* list of tip nodes that can be reached in each direction from that node */ int *n_of_reachable_tips; /* sizes of the list_of_reachable_tips (in each direction) */ int *bip_size; /* Size of each of the three lists from bip_node */ int num; /* node number */ int tax; /* tax = 1 -> external node, else -> internal node */ int check_branch; /* check_branch=1 is the corresponding branch is labelled with '*' */ char ***bip_name; /* three lists of tip node names. One list for each direction */ char *name; /* taxon name (if exists) */ phydbl *score; /* score used in BIONJ to determine the best pair of nodes to agglomerate */ phydbl *l; /* lengths of the (three or one) branche(s) connected this node */ phydbl dist_to_root; }node; /*********************************************************/ typedef struct __Edge { /* syntax : (node) [edge] (left_1) . .(right_1) \ (left) (right) / \._____________./ / [b_fcus] \ / \ (left_2) . .(right_2) */ struct __Node *left,*rght; /* node on the left/right side of the edge */ int l_r,r_l,l_v1,l_v2,r_v1,r_v2; /* these are directions (i.e., 0, 1 or 2): */ /* l_r (left to right) -> left[b_fcus->l_r] = right */ /* r_l (right to left) -> right[b_fcus->r_l] = left */ /* l_v1 (left node to first node != from right) -> left[b_fcus->l_v1] = left_1 */ /* l_v2 (left node to secnd node != from right) -> left[b_fcus->l_v2] = left_2 */ /* r_v1 (right node to first node != from left) -> right[b_fcus->r_v1] = right_1 */ /* r_v2 (right node to secnd node != from left) -> right[b_fcus->r_v2] = right_2 */ struct __NNI *nni; int num; /* branch number */ phydbl l; /* branch length */ phydbl best_l; /* best branch length found so far */ phydbl l_old; /* old branch length */ int bip_score; /* score of the bipartition generated by the corresponding edge bip_score = 1 iif the branch is fond in both trees to be compared, bip_score = 0 otherwise. */ phydbl ***p_lk_left,***p_lk_rght; /* likelihoods of the subtree on the left and right side (for each site and each relative rate category) */ short int **p_lk_tip_r,**p_lk_tip_l; double ***Pij_rr; /* matrix of change probabilities and its first and secnd derivates */ int *pars_l,*pars_r; /* parsimony of the subtree on the left and right sides (for each site) */ unsigned int *ui_l, *ui_r; /* union - intersection vectors used in Fitch's parsimony algorithm */ int **p_pars_l, **p_pars_r; /* conditional parsimony vectors */ int num_st_left; /* number of the subtree on the left side */ int num_st_rght; /* number of the subtree on the right side */ /* Below are the likelihood scaling factors (used in functions `Get_All_Partial_Lk_Scale' in lk.c */ int scale_left; int scale_rght; phydbl *sum_scale_f_left; phydbl *sum_scale_f_rght; phydbl bootval; /* bootstrap value (if exists) */ short int is_alive; /* is_alive = 1 if this edge is used in a tree */ phydbl dist_btw_edges; int topo_dist_btw_edges; int has_zero_br_len; phydbl ratio_test; /* approximate likelihood ratio test */ phydbl alrt_statistic; /* aLRT statistic */ int num_tax_left, num_tax_rght; /* number of taxa in subtrees */ phydbl avg_dist_left, avg_dist_rght; /* average taxon distance in subtrees */ int is_p_lk_l_u2d; /* is the conditional likelihood vector on the left up to data ? */ int is_p_lk_r_u2d; /* is the conditional likelihood vector on the right up to data ? */ }edge; /*********************************************************/ typedef struct __Arbre { struct __Node *root; /* root node */ struct __Node **noeud; /* array of nodes that defines the tree topology */ struct __Edge **t_edges; /* array of edges */ struct __Arbre *old_tree; /* old copy of the tree */ struct __Arbre *best_tree; /* best tree found so far */ struct __Model *mod; /* substitution model */ struct __AllSeq *data; /* sequences */ struct __Option *input; /* input parameters */ struct __Matrix *mat; /* pairwise distance matrix */ struct __Edge **t_dead_edges; struct __Node **t_dead_nodes; struct __Node **curr_path; /* list of nodes that form a path in the tree */ int depth_curr_path; /* depth of the node path defined by curr_path */ int has_bip; /*if has_bip=1, then the structure to compare tree topologies is allocated, has_bip=0 otherwise */ int n_otu; /* number of taxa */ int curr_site; /* current site of the alignment to be processed */ int curr_catg; /* current class of the discrete gamma rate distribution */ int n_swap; /* number of NNIs performed */ int n_pattern; /* number of distinct site patterns */ int has_branch_lengths; /* =1 iff input tree displays branch lengths */ int print_boot_val; /* if print_boot_val=1, the bootstrap values are printed */ int print_alrt_val; /* if print_boot_val=1, the bootstrap values are printed */ int both_sides; /* both_sides=1 -> a pre-order and a post-order tree traversals are required to compute the likelihood of every subtree in the phylogeny*/ int num_curr_branch_available; /*gives the number of the next cell in t_edges that is free to receive a pointer to a branch */ int n_dead_edges; int n_dead_nodes; int **t_dir; int n_improvements; int n_moves; int dp; /* Data partition */ int s_mod_num; /* Substitution model number */ int number_of_lk_calls; int number_of_branch_lk_calls; phydbl init_lnL; phydbl best_lnL; /* highest value of the loglikelihood found so far */ phydbl c_lnL; /* loglikelihood */ phydbl *c_lnL_sorted; /* used to compute c_lnL by adding sorted terms to minimize CPU errors */ phydbl *site_lk; /* vector of likelihoods at individual sites */ phydbl **log_site_lk_cat; /* loglikelihood at individual sites and for each class of rate*/ phydbl unconstraint_lk; /* unconstrained (or multinomial) likelihood */ phydbl prop_of_sites_to_consider; phydbl lnL_lower_bound; phydbl **log_lks_aLRT; /* used to compute several branch supports */ int *site_pars; int c_pars; int *step_mat; struct __SPR **spr_list; struct __SPR *best_spr; int size_spr_list; int perform_spr_right_away; phydbl dnorm_thresh; time_t t_beg; time_t t_current; struct __Triplet *triplet_struct; int branch_and_bound; }arbre; /*********************************************************/ typedef struct __Super_Arbre { struct __Arbre *tree; struct __List_Arbre *treelist; /* list of trees. One tree for each data set to be processed */ struct __AllSeq *data_of_interest; struct __Option **optionlist; /* list of pointers to input structures (used in supertrees) */ struct __Node ***match_st_node_in_gt; /* match_st_in_gt_node[subdataset number][supertree node number] * gives the node in tree estimated from 'subdataset number' that corresponds * to 'supertree node number' in the supertree */ struct __Node *****map_st_node_in_gt; /* mat_st_gt_node[gt_num][st_node_num][direction] gives the * node in gt gt_num that maps node st_node_num in st. */ struct __Edge ***map_st_edge_in_gt; /* map_st_gt_br[gt_num][st_branch_num] gives the * branch in gt gt_num that maps branch st_branch_num * in st. */ struct __Edge ****map_gt_edge_in_st; /* mat_gt_st_br[gt_num][gt_branch_num][] is the list of * branches in st that map branch gt_branch_num * in gt gt_num. */ int **size_map_gt_edge_in_st; /* size_map_gt_st_br[gt_num][gt_branch_num] gives the * size of the list map_gt_st_br[gt_num][gt_branch_num][] */ struct __Edge ***match_st_edge_in_gt; /* match_st_edge_in_gt[gt_num][st_branch_num] gives the * branch in gt gt_num that matches branch st_branch_num */ struct __Edge ***match_gt_edge_in_st; /* match_gt_edge_in_st[gt_num][gt_branch_num] gives the * branch in st that matches branch gt_branch_num */ struct __Node ****closest_match; /* closest_match[gt_num][st_node_num][dir] gives the * closest node in st that matches a node in gt gt_num */ int ***closest_dist; /* closest_dist[gt_num][st_node_num][dir] gives the * number of edges to traverse to get to node * closest_match[gt_num][st_node_num][dir] */ int n_gt; /* number of trees */ phydbl **bl; /* bl[gt_num][gt_branch_num] gives the length of * branch gt_branch_num */ phydbl **bl_cpy; /* copy of bl */ phydbl **bl0; /* bl estimated during NNI (original topo) * See Mg_NNI. */ phydbl **bl1; /* bl estimated during NNI (topo conf 1) * See Mg_NNI. */ phydbl **bl2; /* bl estimated during NNI (topo conf 2) * See Mg_NNI. */ int *bl_partition; /* partition[gt_num] gives the edge partition number * gt_num belongs to. */ int n_bl_partition; struct __Model **s_mod; /* substitution model */ int n_s_mod; int lock_br_len; }superarbre; /*********************************************************/ typedef struct __List_Arbre { /* a list of trees */ struct __Arbre **tree; int list_size; /* number of trees in the list */ }arbrelist; /*********************************************************/ typedef struct __Seq { char *name; /* sequence name */ int len; /* sequence length */ char *state; /* sequence itself */ short int *is_ambigu; /* is_ambigu[site] = 1 if state[site] is an ambiguous character. 0 otherwise */ }seq; /*********************************************************/ typedef struct __AllSeq { struct __Seq **c_seq; /* compressed sequences */ phydbl *b_frq; /* observed state frequencies */ short int *invar; /* 1 -> states are identical, 0 states vary */ int *wght; /* # of each site in c_seq */ short int *ambigu; /* ambigu[i]=1 is one or more of the sequences at site i display an ambiguous character */ phydbl obs_pinvar; int n_otu; /* number of taxa */ int clean_len; /* uncrunched sequences lenghts without gaps */ int crunch_len; /* crunched sequences lengths */ int init_len; /* length of the uncompressed sequences */ int *sitepatt; /* this array maps the position of the patterns in the compressed alignment to the positions in the uncompressed one */ }allseq; /*********************************************************/ typedef struct __Matrix { /* mostly used in BIONJ */ phydbl **P,**Q,**dist; /* observed proportions of transition, transverion and distances between pairs of sequences */ arbre *tree; /* tree... */ int *on_off; /* on_off[i]=1 if column/line i corresponds to a node that has not been agglomerated yet */ int n_otu; /* number of taxa */ char **name; /* sequence names */ int r; /* number of nodes that have not been agglomerated yet */ struct __Node **tip_node; /* array of pointer to the leaves of the tree */ int curr_int; /* used in the NJ/BIONJ algorithms */ int method; /* if method=1->NJ method is used, BIONJ otherwise */ }matrix; /*********************************************************/ typedef struct __Model { int whichmodel; /* 1 => JC69 2 => K80 3 => F81 4 => HKY85 5 => F84 6 => TN93 7 => GTR 11 => Dayhoff 12 => JTT 13 => MtREV */ char *modelname; int ns; /* number of states (4 for ADN, 20 for AA) */ phydbl *pi; /* states frequencies */ int datatype; /* 0->DNA, 1->AA */ /* ADN parameters */ phydbl kappa; /* transition/transversion rate */ phydbl lambda; /* parameter used to define the ts/tv ratios in the F84 and TN93 models */ phydbl alpha; /* gamma shapa parameter */ phydbl *r_proba; /* probabilities of the substitution rates defined by the discrete gamma distribution */ phydbl *rr; /* substitution rates defined by the discrete gamma distribution */ int asked_n_catg; /* number of categories in the discrete gamma distribution */ int n_catg; /* number of categories in the discrete gamma distribution */ phydbl pinvar; /* proportion of invariable sites */ int invar; /* =1 iff the substitution model takes into account invariable sites */ /* Below are 'old' values of some substitution parameters (see the comments above) */ phydbl alpha_old; phydbl kappa_old; phydbl lambda_old; phydbl pinvar_old; char *custom_mod_string; /* string of characters used to define custom models of substitution */ phydbl **rr_param; /* table of pointers to relative rate parameters of the GTR or custom model */ phydbl *rr_param_values; /* relative rate parameters of the GTR or custom model */ int *rr_param_num; int *n_rr_param_per_cat; /* [3][1][2] for the previous example */ int n_diff_rr_param; /* number of different relative substitution rates in the custom model */ int update_eigen; /* update_eigen=1-> eigen values/vectors need to be updated */ double ***Pij_rr; /* matrix of change probabilities */ int seq_len; /* sequence length */ /* AA parameters */ /* see PMat_Empirical in models.c for AA algorithm explanation */ double *mat_Q; /* 20x20 amino-acids substitution rates matrix */ double *mat_Vr; /* 20x20 right eigenvectors of mat_Q */ double *mat_Vi; /* 20x20 inverse matrix of mat_Vr */ double *vct_ev; /* eigen values */ double *expt; double *vct_eDmr; /* diagonal terms of a 20x20 diagonal matrix */ double *uexpt; phydbl mr; /* mean rate = branch length/time interval */ /* mr = -sum(i)(vct_pi[i].mat_Q[ii]) */ /* term n = exp(nth eigenvalue of mat_Q / mr) */ int stepsize; /* stepsize=1 for nucleotide models, 3 for codon models */ int n_otu; /* number of taxa */ struct __Optimiz *s_opt; /* pointer to parameters to optimize */ int bootstrap; /* bootstrap values are computed if bootstrap > 0. The value give the number of replicates */ phydbl *user_b_freq; /* user-defined nucleotide frequencies */ }model; arbre *Make_Tree_From_Scratch(int n_otu, allseq *data); void Bionj(matrix *mat); char *Write_Tree(arbre *tree); void Free_Tree(arbre *tree); void Free_Mat(matrix *mat); matrix *JC69_Dist(allseq *data, model *mod); matrix *Make_Mat(int n_otu); void Init_Mat(matrix *mat, allseq *data); void *mCalloc(int nb, size_t size); int Is_Ambigu(char *state, int datatype, int stepsize); #endif seaview/csrc/protpars.c000644 000765 000024 00000161536 12410062116 016001 0ustar00mgouystaff000000 000000 #include "phylip.h" #include "seq.h" #include #include /* derived from file protpars.c of PHYLIP version 3.696 with the following copyright: version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe. Copyright (c) 1993-2014, Joseph Felsenstein. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define maxtrees 100 /* maximum number of tied trees stored */ //static int maxtrees; static int nmlngth; static jmp_buf lngjmp_env; typedef enum { universal, ciliate, mito, vertmito, flymito, yeastmito } codetype; /* nodes will form a binary tree */ typedef struct gseq { seqptr seq; struct gseq *next; } gseq; /* function prototypes */ extern int tree_build_interrupted; extern char *create_tmp_filename_from_C(void); extern FILE *fl_fopen_from_C(const char *fname, const char *mode); extern int fl_unlink_from_C(const char*fname); void padtosize(char *pname, char *name, int length); //void protgnu(gseq **); //void protchuck(gseq *); void code(void); void setup(void); static void getoptions(void); void protalloctree(void); static void protfreetree(); static void allocrest(void); static void doinit(int, int, char*); //void protinputdata(void); void protmakevalues(void); static void doinput(char** seq, char** seqname); void protfillin(node *, node *, node *); void protpreorder(node *); void protadd(node *, node *, node *); void protre_move(node **, node **); static void evaluate(node *); void protpostorder(node *); void protreroot(node *); void protsavetraverse(node *, long *, boolean *); void protsavetree(long *, boolean *); static void tryadd(node *, node **, node **); static void addpreorder(node *, node *, node *); static void tryrearr(node *, boolean *); static void repreorder(node *, boolean *); static void rearrange(node **); void protgetch(Char *); void protaddelement(node **, long *, long *, boolean *); void prottreeread(void); void protancestset(long *, long *, long *, long *, long *); void prothyprint(long , long , boolean *, node *, boolean *, boolean *); void prothyptrav(node *, sitearray *, long, long, long *, boolean *, sitearray); //void prothypstates(long *); static void describe(void); static void maketree(char*); void reallocnode(node* p); static void reallocchars(void); extern void awake_from_C(void); /* function prototypes */ Char infilename[FNMLNGTH], outfilename[FNMLNGTH], intreename[FNMLNGTH], *outtreename, weightfilename[FNMLNGTH]; node *root; long chars, col, msets, ith, njumble, jumb; /* chars = number of sites in actual sequences */ long inseed, inseed0; boolean jumble, usertree, weights, thresh, trout, progress, stepbox, justwts, ancseq, mulsets, firstset; codetype whichcode; long fullset, fulldel; pointarray treenode; /* pointers to all nodes in tree */ double threshold; steptr threshwt; longer seed; long *enterorder; sitearray translate[(long)quest - (long)ala + 1]; aas trans[4][4][4]; long **fsteps; bestelm *bestrees; boolean dummy; gseq *garbage; node *temp, *temp1; Char ch; aas tmpa; char *progname; /* Local variables for maketree, propagated globally for c version: */ long minwhich; static double like, bestyet, bestlike, minsteps, bstlike2; boolean lastrearr, recompute; node *there; double nsteps[maxuser]; long *place; boolean *names; /*void protgnu(gseq **p) { * this and the following are do-it-yourself garbage collectors. Make a new node or pull one off the garbage list * if (garbage != NULL) { *p = garbage; free((*p)->seq); (*p)->seq = (seqptr)Malloc(chars*sizeof(sitearray)); garbage = garbage->next; } else { *p = (gseq *)Malloc(sizeof(gseq)); (*p)->seq = (seqptr)Malloc(chars*sizeof(sitearray)); } (*p)->next = NULL; } * protgnu * void protchuck(gseq *p) { * collect garbage on p -- put it on front of garbage list * p->next = garbage; garbage = p; } * protchuck */ void code() { /* make up table of the code 1 = u, 2 = c, 3 = a, 4 = g */ trans[0][0][0] = phe; trans[0][0][1] = phe; trans[0][0][2] = leu; trans[0][0][3] = leu; trans[0][1][0] = ser1; trans[0][1][1] = ser1; trans[0][1][2] = ser1; trans[0][1][3] = ser1; trans[0][2][0] = tyr; trans[0][2][1] = tyr; trans[0][2][2] = stop; trans[0][2][3] = stop; trans[0][3][0] = cys; trans[0][3][1] = cys; trans[0][3][2] = stop; trans[0][3][3] = trp; trans[1][0][0] = leu; trans[1][0][1] = leu; trans[1][0][2] = leu; trans[1][0][3] = leu; trans[1][1][0] = pro; trans[1][1][1] = pro; trans[1][1][2] = pro; trans[1][1][3] = pro; trans[1][2][0] = his; trans[1][2][1] = his; trans[1][2][2] = gln; trans[1][2][3] = gln; trans[1][3][0] = arg; trans[1][3][1] = arg; trans[1][3][2] = arg; trans[1][3][3] = arg; trans[2][0][0] = ileu; trans[2][0][1] = ileu; trans[2][0][2] = ileu; trans[2][0][3] = met; trans[2][1][0] = thr; trans[2][1][1] = thr; trans[2][1][2] = thr; trans[2][1][3] = thr; trans[2][2][0] = asn; trans[2][2][1] = asn; trans[2][2][2] = lys; trans[2][2][3] = lys; trans[2][3][0] = ser2; trans[2][3][1] = ser2; trans[2][3][2] = arg; trans[2][3][3] = arg; trans[3][0][0] = val; trans[3][0][1] = val; trans[3][0][2] = val; trans[3][0][3] = val; trans[3][1][0] = ala; trans[3][1][1] = ala; trans[3][1][2] = ala; trans[3][1][3] = ala; trans[3][2][0] = asp; trans[3][2][1] = asp; trans[3][2][2] = glu; trans[3][2][3] = glu; trans[3][3][0] = gly; trans[3][3][1] = gly; trans[3][3][2] = gly; trans[3][3][3] = gly; if (whichcode == mito) trans[0][3][2] = trp; if (whichcode == vertmito) { trans[0][3][2] = trp; trans[2][3][2] = stop; trans[2][3][3] = stop; trans[2][0][2] = met; } if (whichcode == flymito) { trans[0][3][2] = trp; trans[2][0][2] = met; trans[2][3][2] = ser2; } if (whichcode == yeastmito) { trans[0][3][2] = trp; trans[1][0][2] = thr; trans[2][0][2] = met; } } /* code */ void setup() { /* set up set table to get aasets from aas */ aas a, b; long i, j, k, l, s; for (a = ala; (long)a <= (long)stop; a = (aas)((long)a + 1)) { translate[(long)a - (long)ala][0] = 1L << ((long)a); translate[(long)a - (long)ala][1] = 1L << ((long)a); } for (i = 0; i <= 3; i++) { for (j = 0; j <= 3; j++) { for (k = 0; k <= 3; k++) { for (l = 0; l <= 3; l++) { translate[(long)trans[i][j][k]][1] |= (1L << (long)trans[l][j][k]); translate[(long)trans[i][j][k]][1] |= (1L << (long)trans[i][l][k]); translate[(long)trans[i][j][k]][1] |= (1L << (long)trans[i][j][l]); } } } } translate[(long)del - (long)ala][1] = 1L << ((long)del); fulldel = (1L << ((long)stop + 1)) - (1L << ((long)ala)); fullset = fulldel & (~(1L << ((long)del))); translate[(long)asx - (long)ala][0] = (1L << ((long)asn)) | (1L << ((long)asp)); translate[(long)glx - (long)ala][0] = (1L << ((long)gln)) | (1L << ((long)glu)); translate[(long)ser - (long)ala][0] = (1L << ((long)ser1)) | (1L << ((long)ser2)); translate[(long)unk - (long)ala][0] = fullset; translate[(long)quest - (long)ala][0] = fulldel; translate[(long)asx - (long)ala][1] = translate[(long)asn - (long)ala][1] | translate[(long)asp - (long)ala][1]; translate[(long)glx - (long)ala][1] = translate[(long)gln - (long)ala][1] | translate[(long)glu - (long)ala][1]; translate[(long)ser - (long)ala][1] = translate[(long)ser1 - (long)ala][1] | translate[(long)ser2 - (long)ala][1]; translate[(long)unk - (long)ala][1] = fullset; translate[(long)quest - (long)ala][1] = fulldel; for (a = ala; (long)a <= (long)quest; a = (aas)((long)a + 1)) { s = 0; for (b = ala; (long)b <= (long)stop; b = (aas)((long)b + 1)) { if (((1L << ((long)b)) & translate[(long)a - (long)ala][1]) != 0) s |= translate[(long)b - (long)ala][1]; } translate[(long)a - (long)ala][2] = s; } } /* setup */ static void getoptions() { /* interactively set options */ //long loopcount, loopcount2; //Char ch, ch2; //fprintf(outfile, "\nProtein parsimony algorithm, version %s\n\n",VERSION); //putchar('\n'); jumble = false; njumble = 1; outgrno = 1; outgropt = false; thresh = false; trout = true; usertree = false; weights = false; whichcode = universal; printdata = false; progress = false; treeprint = false; stepbox = false; ancseq = false; dotdiff = true; interleaved = true; /*loopcount = 0; for (;;) { cleerhome(); printf("\nProtein parsimony algorithm, version %s\n\n",VERSION); printf("Setting for this run:\n"); printf(" U Search for best tree? %s\n", (usertree ? "No, use user trees in input file" : "Yes")); if (!usertree) { printf(" J Randomize input order of sequences?"); if (jumble) printf(" Yes (seed =%8ld,%3ld times)\n", inseed0, njumble); else printf(" No. Use input order\n"); } printf(" O Outgroup root?"); if (outgropt) printf(" Yes, at sequence number%3ld\n", outgrno); else printf(" No, use as outgroup species%3ld\n", outgrno); printf(" T Use Threshold parsimony?"); if (thresh) printf(" Yes, count steps up to%4.1f per site\n", threshold); else printf(" No, use ordinary parsimony\n"); printf(" C Use which genetic code? %s\n", (whichcode == universal) ? "Universal" : (whichcode == ciliate) ? "Ciliate" : (whichcode == mito) ? "Universal mitochondrial" : (whichcode == vertmito) ? "Vertebrate mitochondrial" : (whichcode == flymito) ? "Fly mitochondrial" : (whichcode == yeastmito) ? "Yeast mitochondrial" : ""); printf(" W Sites weighted? %s\n", (weights ? "Yes" : "No")); printf(" M Analyze multiple data sets?"); if (mulsets) printf(" Yes, %2ld %s\n", msets, (justwts ? "sets of weights" : "data sets")); else printf(" No\n"); printf(" I Input sequences interleaved? %s\n", (interleaved ? "Yes" : "No, sequential")); printf(" 0 Terminal type (IBM PC, ANSI, none)? %s\n", (ibmpc ? "IBM PC" : ansi ? "ANSI" : "(none)")); printf(" 1 Print out the data at start of run %s\n", (printdata ? "Yes" : "No")); printf(" 2 Print indications of progress of run %s\n", (progress ? "Yes" : "No")); printf(" 3 Print out tree %s\n", (treeprint ? "Yes" : "No")); printf(" 4 Print out steps in each site %s\n", (stepbox ? "Yes" : "No")); printf(" 5 Print sequences at all nodes of tree %s\n", (ancseq ? "Yes" : "No")); if (ancseq || printdata) printf(" . Use dot-differencing to display them %s\n", dotdiff ? "Yes" : "No"); printf(" 6 Write out trees onto tree file? %s\n", (trout ? "Yes" : "No")); if(weights && justwts){ printf( "WARNING: W option and Multiple Weights options are both on. "); printf( "The W menu option is unnecessary and has no additional effect. \n"); } printf( "\nAre these settings correct? (type Y or the letter for one to change)\n"); fflush(stdout); scanf("%c%*[^\n]", &ch); getchar(); uppercase(&ch); if (ch == 'Y') break; if (((!usertree) && (strchr("WCJOTUMI12345.60", ch) != NULL)) || (usertree && ((strchr("WCOTUMI12345.60", ch) != NULL)))){ switch (ch) { case 'J': jumble = !jumble; if (jumble) initjumble(&inseed, &inseed0, seed, &njumble); else njumble = 1; break; case 'W': weights = !weights; break; case 'O': outgropt = !outgropt; if (outgropt) initoutgroup(&outgrno, spp); else outgrno = 1; break; case 'T': thresh = !thresh; if (thresh) initthreshold(&threshold); break; case 'C': printf("\nWhich genetic code?\n"); printf(" type for\n\n"); printf(" U Universal\n"); printf(" M Mitochondrial\n"); printf(" V Vertebrate mitochondrial\n"); printf(" F Fly mitochondrial\n"); printf(" Y Yeast mitochondrial\n\n"); loopcount2 = 0; do { printf("type U, M, V, F, or Y\n"); fflush(stdout); scanf("%c%*[^\n]", &ch); getchar(); if (ch == '\n') ch = ' '; uppercase(&ch); countup(&loopcount2, 10); } while (ch != 'U' && ch != 'M' && ch != 'V' && ch != 'F' && ch != 'Y'); switch (ch) { case 'U': whichcode = universal; break; case 'M': whichcode = mito; break; case 'V': whichcode = vertmito; break; case 'F': whichcode = flymito; break; case 'Y': whichcode = yeastmito; break; } break; case 'M': mulsets = !mulsets; if (mulsets){ printf("Multiple data sets or multiple weights?"); loopcount2 = 0; do { printf(" (type D or W)\n"); #ifdef WIN32 phyFillScreenColor(); #endif fflush(stdout); scanf("%c%*[^\n]", &ch2); getchar(); if (ch2 == '\n') ch2 = ' '; uppercase(&ch2); countup(&loopcount2, 10); } while ((ch2 != 'W') && (ch2 != 'D')); justwts = (ch2 == 'W'); if (justwts) justweights(&msets); else initdatasets(&msets); if (!jumble) { jumble = true; initjumble(&inseed, &inseed0, seed, &njumble); } } break; case 'I': interleaved = !interleaved; break; case 'U': usertree = !usertree; break; case '0': initterminal(&ibmpc, &ansi); break; case '1': printdata = !printdata; break; case '2': progress = !progress; break; case '3': treeprint = !treeprint; break; case '4': stepbox = !stepbox; break; case '5': ancseq = !ancseq; break; case '.': dotdiff = !dotdiff; break; case '6': trout = !trout; break; } } else printf("Not a possible option!\n"); countup(&loopcount, 100); }*/ } /* getoptions */ void protalloctree() { /* allocate treenode dynamically */ long i, j; node *p, *q; treenode = (pointarray)Malloc(nonodes*sizeof(node *)); for (i = 0; i < (spp); i++) { treenode[i] = (node *)Malloc(sizeof(node)); treenode[i]->numsteps = (steptr)Malloc(chars*sizeof(long)); treenode[i]->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); treenode[i]->seq = (aas *)Malloc(chars*sizeof(aas)); } for (i = spp; i < (nonodes); i++) { q = NULL; for (j = 1; j <= 3; j++) { p = (node *)Malloc(sizeof(node)); p->numsteps = (steptr)Malloc(chars*sizeof(long)); p->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); p->seq = (aas *)Malloc(chars*sizeof(aas)); p->next = q; q = p; } p->next->next->next = p; treenode[i] = p; } } /* protalloctree */ static void protfreetree() { int i; node *p; for (i = 0; i < nonodes; i++) { p = treenode[i]; free(p->numsteps); free(p->siteset); free(p->seq); free(p); } free(treenode); for (i = 1; i <= maxtrees; i++) free(bestrees[i-1].btree); free(bestrees); free(enterorder); free(place); free(weight); free(threshwt); free(temp->numsteps); free(temp->siteset); free(temp->seq); free(temp); free(temp1->numsteps); free(temp1->siteset); free(temp1->seq); free(temp1); if (usertree) { for (i = 0; i < maxuser; i++) { free(fsteps[i]); } free(fsteps); } } void reallocnode(node* p) { free(p->numsteps); free(p->siteset); free(p->seq); p->numsteps = (steptr)Malloc(chars*sizeof(long)); p->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); p->seq = (aas *)Malloc(chars*sizeof(aas)); } static void reallocchars(void) { /* reallocates variables that are dependand on the number of chars * do we need to reallocate the garbage list too? */ long i; node *p; if (usertree) for (i = 0; i < maxuser; i++) { free(fsteps[i]); fsteps[i] = (long *)Malloc(chars*sizeof(long)); } for (i = 0; i < nonodes; i++) { reallocnode(treenode[i]); if (i >= spp) { p=treenode[i]->next; while (p != treenode[i]) { reallocnode(p); p = p->next; } } } free(weight); free(threshwt); free(temp->numsteps); free(temp->siteset); free(temp->seq); free(temp1->numsteps); free(temp1->siteset); free(temp1->seq); weight = (steptr)Malloc(chars*sizeof(long)); threshwt = (steptr)Malloc(chars*sizeof(long)); temp->numsteps = (steptr)Malloc(chars*sizeof(long)); temp->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); temp->seq = (aas *)Malloc(chars*sizeof(aas)); temp1->numsteps = (steptr)Malloc(chars*sizeof(long)); temp1->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); temp1->seq = (aas *)Malloc(chars*sizeof(aas)); } static void allocrest() { /* allocate remaining global arrays and variables dynamically */ long i; if (usertree) { fsteps = (long **)Malloc(maxuser*sizeof(long *)); for (i = 0; i < maxuser; i++) fsteps[i] = (long *)Malloc(chars*sizeof(long)); } bestrees = (bestelm *)Malloc(maxtrees*sizeof(bestelm)); for (i = 1; i <= maxtrees; i++) bestrees[i - 1].btree = (long *)Malloc(spp*sizeof(long)); //nayme = (naym *)Malloc(spp*sizeof(naym)); enterorder = (long *)Malloc(spp*sizeof(long)); place = (long *)Malloc(nonodes*sizeof(long)); weight = (steptr)Malloc(chars*sizeof(long)); threshwt = (steptr)Malloc(chars*sizeof(long)); temp = (node *)Malloc(sizeof(node)); temp->numsteps = (steptr)Malloc(chars*sizeof(long)); temp->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); temp->seq = (aas *)Malloc(chars*sizeof(aas)); temp1 = (node *)Malloc(sizeof(node)); temp1->numsteps = (steptr)Malloc(chars*sizeof(long)); temp1->siteset = (seqptr)Malloc(chars*sizeof(sitearray)); temp1->seq = (aas *)Malloc(chars*sizeof(aas)); } /* allocrest */ static void doinit(int myspp, int mychars, char* toevaluate) { /* initializes variables */ //inputnumbers(&spp, &chars, &nonodes, 1); spp = myspp; chars = mychars; nonodes = (spp * 2 - 1); getoptions(); usertree = (toevaluate != NULL); /*if (printdata) fprintf(outfile, "%2ld species, %3ld sites\n\n", spp, chars);*/ protalloctree(); allocrest(); } /* doinit*/ /*void protinputdata() { * input the names and sequences for each species * long i, j, k, l, aasread, aasnew = 0; Char charstate; boolean allread, done; aas aa; * temporary amino acid for input * if (printdata) headings(chars, "Sequences", "---------"); aasread = 0; allread = false; while (!(allread)) { * eat white space -- if the separator line has spaces on it* do { charstate = gettc(infile); } while (charstate == ' ' || charstate == '\t'); ungetc(charstate, infile); if (eoln(infile)) { scan_eoln(infile); } i = 1; while (i <= spp) { if ((interleaved && aasread == 0) || !interleaved) initname(i - 1); j = interleaved ? aasread : 0; done = false; while (!done && !eoff(infile)) { if (interleaved) done = true; while (j < chars && !(eoln(infile) || eoff(infile))) { charstate = gettc(infile); if (charstate == '\n' || charstate == '\t') charstate = ' '; if (charstate == ' ' || (charstate >= '0' && charstate <= '9')) continue; uppercase(&charstate); if ((!isalpha(charstate) && charstate != '?' && charstate != '-' && charstate != '*') || charstate == 'J' || charstate == 'O' || charstate == 'U') { printf("WARNING -- BAD AMINO ACID:%c",charstate); printf(" AT POSITION%5ld OF SPECIES %3ld\n",j,i); exxit(-1); } j++; aa = (charstate == 'A') ? ala : (charstate == 'B') ? asx : (charstate == 'C') ? cys : (charstate == 'D') ? asp : (charstate == 'E') ? glu : (charstate == 'F') ? phe : (charstate == 'G') ? gly : aa; aa = (charstate == 'H') ? his : (charstate == 'I') ? ileu : (charstate == 'K') ? lys : (charstate == 'L') ? leu : (charstate == 'M') ? met : (charstate == 'N') ? asn : (charstate == 'P') ? pro : (charstate == 'Q') ? gln : (charstate == 'R') ? arg : aa; aa = (charstate == 'S') ? ser : (charstate == 'T') ? thr : (charstate == 'V') ? val : (charstate == 'W') ? trp : (charstate == 'X') ? unk : (charstate == 'Y') ? tyr : (charstate == 'Z') ? glx : (charstate == '*') ? stop : (charstate == '?') ? quest: (charstate == '-') ? del : aa; treenode[i - 1]->seq[j - 1] = aa; memcpy(treenode[i - 1]->siteset[j - 1], translate[(long)aa - (long)ala], sizeof(sitearray)); } if (interleaved) continue; if (j < chars) scan_eoln(infile); else if (j == chars) done = true; } if (interleaved && i == 1) aasnew = j; scan_eoln(infile); if ((interleaved && j != aasnew) || ((!interleaved) && j != chars)){ printf("ERROR: SEQUENCES OUT OF ALIGNMENT\n"); exxit(-1);} i++; } if (interleaved) { aasread = aasnew; allread = (aasread == chars); } else allread = (i > spp); } if (printdata) { for (i = 1; i <= ((chars - 1) / 60 + 1); i++) { for (j = 1; j <= (spp); j++) { for (k = 0; k < nmlngth; k++) putc(nayme[j - 1][k], outfile); fprintf(outfile, " "); l = i * 60; if (l > chars) l = chars; for (k = (i - 1) * 60 + 1; k <= l; k++) { if (j > 1 && treenode[j - 1]->seq[k - 1] == treenode[0]->seq[k - 1]) charstate = '.'; else { tmpa = treenode[j-1]->seq[k-1]; charstate = (tmpa == ala) ? 'A' : (tmpa == asx) ? 'B' : (tmpa == cys) ? 'C' : (tmpa == asp) ? 'D' : (tmpa == glu) ? 'E' : (tmpa == phe) ? 'F' : (tmpa == gly) ? 'G' : (tmpa == his) ? 'H' : (tmpa ==ileu) ? 'I' : (tmpa == lys) ? 'K' : (tmpa == leu) ? 'L' : charstate; charstate = (tmpa == met) ? 'M' : (tmpa == asn) ? 'N' : (tmpa == pro) ? 'P' : (tmpa == gln) ? 'Q' : (tmpa == arg) ? 'R' : (tmpa == ser) ? 'S' : (tmpa ==ser1) ? 'S' : (tmpa ==ser2) ? 'S' : charstate; charstate = (tmpa == thr) ? 'T' : (tmpa == val) ? 'V' : (tmpa == trp) ? 'W' : (tmpa == unk) ? 'X' : (tmpa == tyr) ? 'Y' : (tmpa == glx) ? 'Z' : (tmpa == del) ? '-' : (tmpa ==stop) ? '*' : (tmpa==quest) ? '?' : charstate; } putc(charstate, outfile); if (k % 10 == 0 && k % 60 != 0) putc(' ', outfile); } putc('\n', outfile); } putc('\n', outfile); } putc('\n', outfile); } putc('\n', outfile); } * protinputdata */ static void convertprotseq(char **seq) { aas aa; char charstate; int i, j; for (i = 1; i <= spp; i++) { for (j = 1; j <= chars; j++) { aa = unk; charstate = seq[i-1][j-1]; aa = (charstate == 'A') ? ala : (charstate == 'B') ? asx : (charstate == 'C') ? cys : (charstate == 'D') ? asp : (charstate == 'E') ? glu : (charstate == 'F') ? phe : (charstate == 'G') ? gly : aa; aa = (charstate == 'H') ? his : (charstate == 'I') ? ileu : (charstate == 'K') ? lys : (charstate == 'L') ? leu : (charstate == 'M') ? met : (charstate == 'N') ? asn : (charstate == 'P') ? pro : (charstate == 'Q') ? gln : (charstate == 'R') ? arg : aa; aa = (charstate == 'S') ? ser : (charstate == 'T') ? thr : (charstate == 'V') ? val : (charstate == 'W') ? trp : (charstate == 'X') ? unk : (charstate == 'Y') ? tyr : (charstate == 'Z') ? glx : (charstate == '*') ? stop : (charstate == '?') ? quest: (charstate == '-') ? del : aa; treenode[i - 1]->seq[j - 1] = aa; memcpy(treenode[i - 1]->siteset[j - 1], translate[(long)aa - (long)ala], sizeof(sitearray)); } } } void protmakevalues() { /* set up fractional likelihoods at tips */ long i, j; node *p; for (i = 1; i <= nonodes; i++) { treenode[i - 1]->back = NULL; treenode[i - 1]->tip = (i <= spp); treenode[i - 1]->index = i; for (j = 0; j < (chars); j++) treenode[i - 1]->numsteps[j] = 0; if (i > spp) { p = treenode[i - 1]->next; while (p != treenode[i - 1]) { p->back = NULL; p->tip = false; p->index = i; for (j = 0; j < (chars); j++) p->numsteps[j] = 0; p = p->next; } } } } /* protmakevalues */ static void doinput(char** seq, char** seqname) { /* reads the input data */ long i; if (justwts) { if (firstset) { //protinputdata(); convertprotseq(seq); nayme = seqname; } /*for (i = 0; i < chars; i++) weight[i] = 1; inputweights(chars, weight, &weights); if (justwts) { fprintf(outfile, "\n\nWeights set # %ld:\n\n", ith); if (progress) printf("\nWeights set # %ld:\n\n", ith); } if (printdata) printweights(outfile, 0, chars, weight, "Sites");*/ } else { if (!firstset){ //samenumsp(&chars, ith); reallocchars(); } /*for (i = 0; i < chars; i++) weight[i] = 1; if (weights) { inputweights(chars, weight, &weights); } if (weights) printweights(outfile, 0, chars, weight, "Sites");*/ //protinputdata(); convertprotseq(seq); nayme = seqname; } if(!thresh) threshold = spp * 3.0; for (i = 0 ; i < (chars) ; i++){ weight[i]*=10; threshwt[i] = (long)(threshold * weight[i] + 0.5); } nmlngth = 0; for (i = 0; i < spp; i++) { if(strlen(seqname[i]) > nmlngth) nmlngth = strlen(seqname[i]); } protmakevalues(); } /* doinput */ void protfillin(node *p, node *left, node *rt) { /* sets up for each node in the tree the aa set for site m at that point and counts the changes. The program spends much of its time in this function */ boolean counted, done; aas aa; long s = 0; sitearray ls, rs, qs; long i, j, m, n; for (m = 0; m < chars; m++) { if (left != NULL) memcpy(ls, left->siteset[m], sizeof(sitearray)); if (rt != NULL) memcpy(rs, rt->siteset[m], sizeof(sitearray)); if (left == NULL) { n = rt->numsteps[m]; memcpy(qs, rs, sizeof(sitearray)); } else if (rt == NULL) { n = left->numsteps[m]; memcpy(qs, ls, sizeof(sitearray)); } else { n = left->numsteps[m] + rt->numsteps[m]; if ((ls[0] == rs[0]) && (ls[1] == rs[1]) && (ls[2] == rs[2])) { qs[0] = ls[0]; qs[1] = ls[1]; qs[2] = ls[2]; } else { counted = false; for (i = 0; (!counted) && (i <= 3); i++) { switch (i) { case 0: s = ls[0] & rs[0]; break; case 1: s = (ls[0] & rs[1]) | (ls[1] & rs[0]); break; case 2: s = (ls[0] & rs[2]) | (ls[1] & rs[1]) | (ls[2] & rs[0]); break; case 3: s = ls[0] | (ls[1] & rs[2]) | (ls[2] & rs[1]) | rs[0]; break; } if (s != 0) { qs[0] = s; counted = true; } else n += weight[m]; } switch (i) { case 1: qs[1] = qs[0] | (ls[0] & rs[1]) | (ls[1] & rs[0]); qs[2] = qs[1] | (ls[0] & rs[2]) | (ls[1] & rs[1]) | (ls[2] & rs[0]); break; case 2: qs[1] = qs[0] | (ls[0] & rs[2]) | (ls[1] & rs[1]) | (ls[2] & rs[0]); qs[2] = qs[1] | ls[0] | (ls[1] & rs[2]) | (ls[2] & rs[1]) | rs[0]; break; case 3: qs[1] = qs[0] | ls[0] | (ls[1] & rs[2]) | (ls[2] & rs[1]) | rs[0]; qs[2] = qs[1] | ls[1] | (ls[2] & rs[2]) | rs[1]; break; case 4: qs[1] = qs[0] | ls[1] | (ls[2] & rs[2]) | rs[1]; qs[2] = qs[1] | ls[2] | rs[2]; break; } for (aa = ala; (long)aa <= (long)stop; aa = (aas)((long)aa + 1)) { done = false; for (i = 0; (!done) && (i <= 1); i++) { if (((1L << ((long)aa)) & qs[i]) != 0) { for (j = i+1; j <= 2; j++) qs[j] |= translate[(long)aa - (long)ala][j-i]; done = true; } } } } } p->numsteps[m] = n; memcpy(p->siteset[m], qs, sizeof(sitearray)); } } /* protfillin */ void protpreorder(node *p) { /* recompute number of steps in preorder taking both ancestoral and descendent steps into account */ if (p != NULL && !p->tip) { protfillin (p->next, p->next->next->back, p->back); protfillin (p->next->next, p->back, p->next->back); protpreorder (p->next->back); protpreorder (p->next->next->back); } } /* protpreorder */ void protadd(node *below, node *newtip, node *newfork) { /* inserts the nodes newfork and its left descendant, newtip, to the tree. below becomes newfork's right descendant */ if (below != treenode[below->index - 1]) below = treenode[below->index - 1]; if (below->back != NULL) below->back->back = newfork; newfork->back = below->back; below->back = newfork->next->next; newfork->next->next->back = below; newfork->next->back = newtip; newtip->back = newfork->next; if (root == below) root = newfork; root->back = NULL; if (recompute) { protfillin (newfork, newfork->next->back, newfork->next->next->back); protpreorder(newfork); if (newfork != root) protpreorder(newfork->back); } } /* protadd */ void protre_move(node **item, node **fork) { /* removes nodes item and its ancestor, fork, from the tree. the new descendant of fork's ancestor is made to be fork's second descendant (other than item). Also returns pointers to the deleted nodes, item and fork */ node *p, *q, *other; if ((*item)->back == NULL) { *fork = NULL; return; } *fork = treenode[(*item)->back->index - 1]; if ((*item) == (*fork)->next->back) other = (*fork)->next->next->back; else other = (*fork)->next->back; if (root == *fork) root = other; p = (*item)->back->next->back; q = (*item)->back->next->next->back; if (p != NULL) p->back = q; if (q != NULL) q->back = p; (*fork)->back = NULL; p = (*fork)->next; do { p->back = NULL; p = p->next; } while (p != (*fork)); (*item)->back = NULL; if (recompute) { protpreorder(other); if (other != root) protpreorder(other->back); } } /* protre_move */ static void evaluate(node *r) { /* determines the number of steps needed for a tree. this is the minimum number of steps needed to evolve sequences on this tree */ long i, steps, term; double sum; sum = 0.0; for (i = 0; i < (chars); i++) { steps = r->numsteps[i]; if (steps <= threshwt[i]) term = steps; else term = threshwt[i]; sum += term; if (usertree && which <= maxuser) fsteps[which - 1][i] = term; } if (usertree && which <= maxuser) { nsteps[which - 1] = sum; if (which == 1) { minwhich = 1; minsteps = sum; } else if (sum < minsteps) { minwhich = which; minsteps = sum; } } like = -sum; } /* evaluate */ void protpostorder(node *p) { /* traverses a binary tree, calling PROCEDURE fillin at a node's descendants before calling fillin at the node */ if (p->tip) return; protpostorder(p->next->back); protpostorder(p->next->next->back); protfillin(p, p->next->back, p->next->next->back); } /* protpostorder */ void protreroot(node *outgroup) { /* reorients tree, putting outgroup in desired position. */ node *p, *q; if (outgroup->back->index == root->index) return; p = root->next; q = root->next->next; p->back->back = q->back; q->back->back = p->back; p->back = outgroup; q->back = outgroup->back; outgroup->back->back = q; outgroup->back = p; } /* protreroot */ void protsavetraverse(node *p, long *pos, boolean *found) { /* sets BOOLEANs that indicate which way is down */ p->bottom = true; if (p->tip) return; p->next->bottom = false; protsavetraverse(p->next->back, pos,found); p->next->next->bottom = false; protsavetraverse(p->next->next->back, pos,found); } /* protsavetraverse */ void protsavetree(long *pos, boolean *found) { /* record in place where each species has to be added to reconstruct this tree */ long i, j; node *p; boolean done; protreroot(treenode[outgrno - 1]); protsavetraverse(root, pos,found); for (i = 0; i < (nonodes); i++) place[i] = 0; place[root->index - 1] = 1; for (i = 1; i <= (spp); i++) { p = treenode[i - 1]; while (place[p->index - 1] == 0) { place[p->index - 1] = i; while (!p->bottom) p = p->next; p = p->back; } if (i > 1) { place[i - 1] = place[p->index - 1]; j = place[p->index - 1]; done = false; while (!done) { place[p->index - 1] = spp + i - 1; while (!p->bottom) p = p->next; p = p->back; done = (p == NULL); if (!done) done = (place[p->index - 1] != j); } } } } /* protsavetree */ static void tryadd(node *p, node **item, node **nufork) { /* temporarily adds one fork and one tip to the tree. if the location where they are added yields greater "likelihood" than other locations tested up to that time, then keeps that location as there */ long pos; boolean found; node *rute, *q; if (p == root) protfillin(temp, *item, p); else { protfillin(temp1, *item, p); protfillin(temp, temp1, p->back); } evaluate(temp); if (lastrearr) { if (like < bestlike) { if ((*item) == (*nufork)->next->next->back) { q = (*nufork)->next; (*nufork)->next = (*nufork)->next->next; (*nufork)->next->next = q; q->next = (*nufork); } } else if (like >= bstlike2) { recompute = false; protadd(p, (*item), (*nufork)); rute = root->next->back; protsavetree(&pos,&found); protreroot(rute); if (like > bstlike2) { bestlike = bstlike2 = like; pos = 1; nextree = 1; addtree(pos, &nextree, dummy, place, bestrees); } else { pos = 0; findtree(&found, &pos, nextree, place, bestrees); if (!found) { if (nextree <= maxtrees) addtree(pos, &nextree, dummy, place, bestrees); } } protre_move (item, nufork); recompute = true; } } if (like >= bestyet) { bestyet = like; there = p; } } /* tryadd */ static void addpreorder(node *p, node *item, node *nufork) { /* traverses a binary tree, calling PROCEDURE tryadd at a node before calling tryadd at its descendants */ if (p == NULL) return; tryadd(p, &item,&nufork); if (!p->tip) { addpreorder(p->next->back, item, nufork); addpreorder(p->next->next->back, item, nufork); } } /* addpreorder */ static void tryrearr(node *p, boolean *success) { /* evaluates one rearrangement of the tree. if the new tree has greater "likelihood" than the old one sets success := TRUE and keeps the new tree. otherwise, restores the old tree */ node *frombelow, *whereto, *forknode, *q; double oldlike; if (p->back == NULL) return; forknode = treenode[p->back->index - 1]; if (forknode->back == NULL) return; oldlike = bestyet; if (p->back->next->next == forknode) frombelow = forknode->next->next->back; else frombelow = forknode->next->back; whereto = treenode[forknode->back->index - 1]; if (whereto->next->back == forknode) q = whereto->next->next->back; else q = whereto->next->back; protfillin(temp1, frombelow, q); protfillin(temp, temp1, p); protfillin(temp1, temp, whereto->back); evaluate(temp1); if (like - oldlike < LIKE_EPSILON) { if (p == forknode->next->next->back) { q = forknode->next; forknode->next = forknode->next->next; forknode->next->next = q; q->next = forknode; } } else { recompute = false; protre_move(&p, &forknode); protfillin(whereto, whereto->next->back, whereto->next->next->back); recompute = true; protadd(whereto, p, forknode); *success = true; bestyet = like; } } /* tryrearr */ static void repreorder(node *p, boolean *success) { /* traverses a binary tree, calling PROCEDURE tryrearr at a node before calling tryrearr at its descendants */ if (p == NULL) return; tryrearr(p,success); if (!p->tip) { repreorder(p->next->back,success); repreorder(p->next->next->back,success); } } /* repreorder */ static void rearrange(node **r) { /* traverses the tree (preorder), finding any local rearrangement which decreases the number of steps. if traversal succeeds in increasing the tree's "likelihood", PROCEDURE rearrange runs traversal again */ boolean success = true; while (success) { success = false; repreorder(*r, &success); } } /* rearrange */ void protgetch(Char *c) { /* get next nonblank character */ do { if (eoln(intree)) scan_eoln(intree); *c = gettc(intree); if (*c == '\n' || *c == '\t') *c = ' '; } while (!(*c != ' ' || eoff(intree))); } /* protgetch */ void protaddelement(node **p,long *nextnode,long *lparens,boolean *names) { /* recursive procedure adds nodes to user-defined tree */ node *q; long i, n; boolean found; Char str[nmlngth + 1]; protgetch(&ch); if (ch == '(' ) { if ((*lparens) >= spp - 1) { printf("\nERROR IN USER TREE: TOO MANY LEFT PARENTHESES\n"); exxit(-1); } (*nextnode)++; (*lparens)++; q = treenode[(*nextnode) - 1]; protaddelement(&q->next->back, nextnode,lparens,names); q->next->back->back = q->next; findch(',', &ch, which); protaddelement(&q->next->next->back, nextnode,lparens,names); q->next->next->back->back = q->next->next; findch(')', &ch, which); *p = q; return; } /*for (i = 0; i < nmlngth; i++) str[i] = ' ';*/ n = 1; do { /*if (ch == '_') ch = ' ';*/ str[n - 1] = ch; if (eoln(intree)) scan_eoln(intree); ch = gettc(intree); n++; } while (ch != ',' && ch != ')' && ch != ':' && n <= nmlngth); str[n-1] = 0; n = 1; do { int l = strlen(nayme[n-1]); found = true; for (i = 0; i <= l; i++) found = (found && ((str[i] == nayme[n - 1][i]) /*|| ((nayme[n - 1][i] == '_') && (str[i] == ' '))*/ )); if (found) { if (names[n - 1] == false) { *p = treenode[n - 1]; names[n - 1] = true; } else { printf("\nERROR IN USER TREE: DUPLICATE NAME FOUND -- "); for (i = 0; i < l; i++) putchar(nayme[n - 1][i]); putchar('\n'); exxit(-1); } } else n++; } while (!(n > spp || found)); if (n <= spp) return; printf("CANNOT FIND SPECIES: %s\n", str); } /* protaddelement */ void prottreeread() { /* read in user-defined tree and set it up */ long nextnode, lparens, i; root = treenode[spp]; nextnode = spp; root->back = NULL; names = (boolean *)Malloc(spp*sizeof(boolean)); for (i = 0; i < (spp); i++) names[i] = false; lparens = 0; protaddelement(&root, &nextnode,&lparens,names); if (ch == '[') { do ch = gettc(intree); while (ch != ']'); ch = gettc(intree); } findch(';', &ch, which); scan_eoln(intree); free(names); } /* prottreeread */ void protancestset(long *a, long *b, long *c, long *d, long *k) { /* sets up the aa set array. */ aas aa; long s, sa, sb; long i, j, m, n; boolean counted; counted = false; *k = 0; for (i = 0; i <= 5; i++) { if (*k < 3) { s = 0; if (i > 3) n = i - 3; else n = 0; for (j = n; j <= (i - n); j++) { if (j < 3) sa = a[j]; else sa = fullset; for (m = n; m <= (i - j - n); m++) { if (m < 3) sb = sa & b[m]; else sb = sa; if (i - j - m < 3) sb &= c[i - j - m]; s |= sb; } } if (counted || s != 0) { d[*k] = s; (*k)++; counted = true; } } } for (i = 0; i <= 1; i++) { for (aa = ala; (long)aa <= (long)stop; aa = (aas)((long)aa + 1)) { if (((1L << ((long)aa)) & d[i]) != 0) { for (j = i + 1; j <= 2; j++) d[j] |= translate[(long)aa - (long)ala][j - i]; } } } } /* protancestset */ /*void prothyprint(long b1, long b2, boolean *bottom, node *r, boolean *nonzero, boolean *maybe) { * print out states in sites b1 through b2 at node * long i; boolean dot; Char ch = 0; aas aa; if (*bottom) { if (!outgropt) fprintf(outfile, " "); else fprintf(outfile, "root "); } else fprintf(outfile, "%3ld ", r->back->index - spp); if (r->tip) { for (i = 0; i < nmlngth; i++) putc(nayme[r->index - 1][i], outfile); } else fprintf(outfile, "%4ld ", r->index - spp); if (*bottom) fprintf(outfile, " "); else if (*nonzero) fprintf(outfile, " yes "); else if (*maybe) fprintf(outfile, " maybe "); else fprintf(outfile, " no "); for (i = b1 - 1; i < b2; i++) { aa = r->seq[i]; switch (aa) { case ala: ch = 'A'; break; case asx: ch = 'B'; break; case cys: ch = 'C'; break; case asp: ch = 'D'; break; case glu: ch = 'E'; break; case phe: ch = 'F'; break; case gly: ch = 'G'; break; case his: ch = 'H'; break; case ileu: ch = 'I'; break; case lys: ch = 'K'; break; case leu: ch = 'L'; break; case met: ch = 'M'; break; case asn: ch = 'N'; break; case pro: ch = 'P'; break; case gln: ch = 'Q'; break; case arg: ch = 'R'; break; case ser: ch = 'S'; break; case ser1: ch = 'S'; break; case ser2: ch = 'S'; break; case thr: ch = 'T'; break; case trp: ch = 'W'; break; case tyr: ch = 'Y'; break; case val: ch = 'V'; break; case glx: ch = 'Z'; break; case del: ch = '-'; break; case stop: ch = '*'; break; case unk: ch = 'X'; break; case quest: ch = '?'; break; } if (!(*bottom) && dotdiff) dot = (r->siteset[i] [0] == treenode[r->back->index - 1]->siteset[i][0] || ((r->siteset[i][0] & (~((1L << ((long)ser1)) | (1L << ((long)ser2)) | (1L << ((long)ser))))) == 0 && (treenode[r->back->index - 1]->siteset[i] [0] & (~((1L << ((long)ser1)) | (1L << ((long)ser2)) | (1L << ((long)ser))))) == 0)); else dot = false; if (dot) putc('.', outfile); else putc(ch, outfile); if ((i + 1) % 10 == 0) putc(' ', outfile); } putc('\n', outfile); } * prothyprint * void prothyptrav(node *r, sitearray *hypset, long b1, long b2, long *k, boolean *bottom, sitearray nothing) { boolean maybe, nonzero; long i; aas aa; long anc = 0, hset; gseq *ancset, *temparray; protgnu(&ancset); protgnu(&temparray); maybe = false; nonzero = false; for (i = b1 - 1; i < b2; i++) { if (!r->tip) { protancestset(hypset[i], r->next->back->siteset[i], r->next->next->back->siteset[i], temparray->seq[i], k); memcpy(r->siteset[i], temparray->seq[i], sizeof(sitearray)); } if (!(*bottom)) anc = treenode[r->back->index - 1]->siteset[i][0]; if (!r->tip) { hset = r->siteset[i][0]; r->seq[i] = quest; for (aa = ala; (long)aa <= (long)stop; aa = (aas)((long)aa + 1)) { if (hset == 1L << ((long)aa)) r->seq[i] = aa; } if (hset == ((1L << ((long)asn)) | (1L << ((long)asp)))) r->seq[i] = asx; if (hset == ((1L << ((long)gln)) | (1L << ((long)gly)))) r->seq[i] = glx; if (hset == ((1L << ((long)ser1)) | (1L << ((long)ser2)))) r->seq[i] = ser; if (hset == fullset) r->seq[i] = unk; } nonzero = (nonzero || (r->siteset[i][0] & anc) == 0); maybe = (maybe || r->siteset[i][0] != anc); } prothyprint(b1, b2,bottom,r,&nonzero,&maybe); *bottom = false; if (!r->tip) { memcpy(temparray->seq, r->next->back->siteset, chars*sizeof(sitearray)); for (i = b1 - 1; i < b2; i++) protancestset(hypset[i], r->next->next->back->siteset[i], nothing, ancset->seq[i], k); prothyptrav(r->next->back, ancset->seq, b1, b2,k,bottom,nothing ); for (i = b1 - 1; i < b2; i++) protancestset(hypset[i], temparray->seq[i], nothing, ancset->seq[i],k); prothyptrav(r->next->next->back, ancset->seq, b1, b2, k,bottom,nothing); } protchuck(temparray); protchuck(ancset); } * prothyptrav * void prothypstates(long *k) { * fill in and describe states at interior nodes * boolean bottom; sitearray nothing; long i, n; seqptr hypset; fprintf(outfile, "\nFrom To Any Steps? State at upper node\n"); fprintf(outfile, " "); fprintf(outfile, "( . means same as in the node below it on tree)\n\n"); memcpy(nothing, translate[(long)quest - (long)ala], sizeof(sitearray)); hypset = (seqptr)Malloc(chars*sizeof(sitearray)); for (i = 0; i < (chars); i++) memcpy(hypset[i], nothing, sizeof(sitearray)); bottom = true; for (i = 1; i <= ((chars - 1) / 40 + 1); i++) { putc('\n', outfile); n = i * 40; if (n > chars) n = chars; bottom = true; prothyptrav(root, hypset, i * 40 - 39, n, k,&bottom,nothing); } free(hypset); } * prothypstates */ static void describe() { /* prints ancestors, steps and table of numbers of steps in each site */ /*long i,j,k; if (treeprint) fprintf(outfile, "\nrequires a total of %10.3f\n", like / -10); if (stepbox) { putc('\n', outfile); if (weights) fprintf(outfile, "weighted "); fprintf(outfile, "steps in each position:\n"); fprintf(outfile, " "); for (i = 0; i <= 9; i++) fprintf(outfile, "%4ld", i); fprintf(outfile, "\n *-----------------------------------------\n"); for (i = 0; i <= (chars / 10); i++) { fprintf(outfile, "%5ld", i * 10); putc('!', outfile); for (j = 0; j <= 9; j++) { k = i * 10 + j; if (k == 0 || k > chars) fprintf(outfile, " "); else fprintf(outfile, "%4ld", root->numsteps[k - 1] / 10); } putc('\n', outfile); } } if (ancseq) { prothypstates(&k); putc('\n', outfile); } putc('\n', outfile);*/ if (trout) { col = 0; treeout(root, nextree, &col, root); } } /* describe */ static void maketree(char *toevaluate) { /* constructs a binary tree from the pointers in treenode. adds each node at location which yields highest "likelihood" then rearranges the tree for greatest "likelihood" */ long i, j, numtrees; double gotlike; node *item, *nufork, *dummy; if (setjmp(lngjmp_env)) { trout = false; goto way_out; } if (!usertree) { for (i = 1; i <= (spp); i++) enterorder[i - 1] = i; if (jumble) randumize(seed, enterorder); root = treenode[enterorder[0] - 1]; recompute = true; protadd(treenode[enterorder[0] - 1], treenode[enterorder[1] - 1], treenode[spp]); /*if (progress) { printf("\nAdding species:\n"); writename(0, 2, enterorder); }*/ lastrearr = false; for (i = 3; i <= (spp); i++) { bestyet = -30.0*spp*chars; there = root; item = treenode[enterorder[i - 1] - 1]; nufork = treenode[spp + i - 2]; addpreorder(root, item, nufork); protadd(there, item, nufork); like = bestyet; rearrange(&root); /*if (progress) writename(i - 1, 1, enterorder);*/ lastrearr = (i == spp); if (lastrearr) { /*if (progress) { printf("\nDoing global rearrangements\n"); printf(" !"); for (j = 1; j <= nonodes; j++) if ( j % (( nonodes / 72 ) + 1 ) == 0 ) putchar('-'); printf("!\n"); }*/ bestlike = bestyet; if (jumb == 1) { bstlike2 = bestlike = -30.0*spp*chars; nextree = 1; } do { /*if (progress) printf(" ");*/ gotlike = bestlike; for (j = 0; j < (nonodes); j++) { //bestyet = -30.0*spp*chars; item = treenode[j]; if (item != root) { bestyet = -30.0*spp*chars; nufork = treenode[treenode[j]->back->index - 1]; protre_move(&item, &nufork); there = root; addpreorder(root, item, nufork); protadd(there, item, nufork); } /*if (progress) { if ( j % (( nonodes / 72 ) + 1 ) == 0 ) putchar('.'); fflush(stdout); }*/ if (tree_build_interrupted) { longjmp(lngjmp_env, 0); } } /*if (progress) putchar('\n');*/ } while (bestlike > gotlike); } } /*if (progress) putchar('\n');*/ for (i = spp - 1; i >= 1; i--) protre_move(&treenode[i], &dummy); if (jumb == njumble) { /*if (treeprint) { putc('\n', outfile); if (nextree == 2) fprintf(outfile, "One most parsimonious tree found:\n"); else fprintf(outfile, "%6ld trees in all found\n", nextree - 1); }*/ if (nextree > maxtrees + 1) { /*if (treeprint) fprintf(outfile, "here are the first%4ld of them\n", (long)maxtrees);*/ nextree = maxtrees + 1; } /*if (treeprint) putc('\n', outfile);*/ recompute = false; for (i = 0; i <= (nextree - 2); i++) { root = treenode[0]; protadd(treenode[0], treenode[1], treenode[spp]); for (j = 3; j <= (spp); j++) protadd(treenode[bestrees[i].btree[j - 1] - 1], treenode[j - 1], treenode[spp + j - 2]); protreroot(treenode[outgrno - 1]); protpostorder(root); evaluate(root); //printree(root, 1.0); describe(); for (j = 1; j < (spp); j++) protre_move(&treenode[j], &dummy); } } } else { /* Open in binary: ftell() is broken for UNIX line-endings under WIN32 */ //openfile(&intree,INTREE,"input tree file", "rb",progname,intreename); //numtrees = countsemic(&intree); numtrees = 1; /*if (numtrees > 2) initseed(&inseed, &inseed0, seed);*/ /*if (treeprint) { fprintf(outfile, "User-defined tree"); if (numtrees > 1) putc('s', outfile); fprintf(outfile, ":\n\n\n\n"); }*/ which = 1; while (which <= numtrees) { char *tmpfname = strdup(create_tmp_filename_from_C()); intree = fl_fopen_from_C(tmpfname, "rb+"); fwrite(toevaluate, strlen(toevaluate), 1, intree); fflush(intree); fseek(intree, SEEK_SET, 0); prottreeread(); fclose(intree); fl_unlink_from_C(tmpfname); free(tmpfname); if (outgropt) protreroot(treenode[outgrno - 1]); protpostorder(root); evaluate(root); //printree(root, 1.0); describe(); which++; } /*printf("\n"); FClose(intree); putc('\n', outfile);*/ if (numtrees > 1 && chars > 1 ) standev(chars, numtrees, minwhich, minsteps, nsteps, fsteps, seed); } /*if (jumb == njumble && progress) { printf("Output written to file \"%s\"\n", outfilename); if (trout) printf("\nTrees also written onto file \"%s\"\n", outtreename); }*/ way_out: return; } /* maketree */ char* protpars(char** seq, char** seqname, int notu, int njumbles, int *pjumble_no, int *steps, char* toevaluate, int arg_maxtrees/*unused*/, int *bt_weights, int unused) { /* Protein parsimony by uphill search */ //init(argc,argv); progname = "Protpars"; //openfile(&infile,INFILE,"input file", "r",argv[0],infilename); //openfile(&outfile,OUTFILE,"output file", "w",argv[0],outfilename); ibmpc = IBMCRT; ansi = ANSICRT; garbage = NULL; mulsets = false; msets = 1; firstset = true; code(); setup(); doinit(notu, strlen(seq[0]), toevaluate); if (!toevaluate && njumbles > 0) { njumble = njumbles; jumble = true; } /*if (weights || justwts) openfile(&weightfile,WEIGHTFILE,"weights file","r",argv[0],weightfilename);*/ if (trout) { outtreename = strdup(create_tmp_filename_from_C()); //openfile(&outtree,OUTTREE,"output tree file", "w",argv[0],outtreename); outtree = fl_fopen_from_C(outtreename, "wb"); } for (ith = 1; ith <= msets; ith++) { int i; if (bt_weights != NULL) for (i = 0; i < chars; i++) weight[i] = bt_weights[i]; else for (i = 0; i < chars; i++) weight[i] = 1; doinput(seq, seqname); if (ith == 1) firstset = false; /*if (msets > 1 && !justwts) { fprintf(outfile, "Data set # %ld:\n\n",ith); if (progress) printf("Data set # %ld:\n\n",ith); }*/ for (jumb = 1; jumb <= njumble; jumb++) { maketree(toevaluate); if (jumble && pjumble_no) { *steps = (int)(bestyet / -10); *pjumble_no = jumb; awake_from_C(); } } protfreetree(); } /*FClose(infile); FClose(outfile); FClose(outtree); printf("\nDone.\n\n");*/ char *tree = NULL; FClose(outtree); if (trout) { outtree = fl_fopen_from_C(outtreename, "rb"); // read tree from tmp file and return it as a char* fseek(outtree, 0, SEEK_END); long L=ftell(outtree); tree = (char*)malloc(L+1); fseek(outtree, 0, SEEK_SET); fread(tree, L, 1, outtree); tree[L] = 0; fclose(outtree); *steps = (int)(like / -10); } fl_unlink_from_C(outtreename); free(outtreename); return tree; } /* Protein parsimony by uphill search */ seaview/csrc/raa_acnuc.c000644 000765 000024 00000254106 12614103371 016044 0ustar00mgouystaff000000 000000 #include "raa_acnuc.h" #include "parser.h" #include #include #include #include #include #if defined(unix) || defined(__APPLE__) #include #include #include #include #include #include #elif defined(WIN32) #if _WIN32_WINNT < 0x0501 #define _WIN32_WINNT 0x0501 #endif #include #include // for getaddrinfo, freeaddrinfo, struct addrinfo //#include #endif #define SERVER_UPDATE_MESSAGE "acnuc stop for update\n" /* seules fctions utilisables hors de ce fichier pour ecrire sur socket */ int sock_fputs(raa_db_access *f, const char *l); int sock_flush(raa_db_access *f); /* some prototypes */ void raa_acnucclose(raa_db_access *raa_current_db); static char *protect_quotes(char *name); static void raa_free_matchkeys(raa_db_access *raa_current_db); /* needed functions */ extern char init_codon_to_aa(char *codon, int gc); char codaa(char *codon, int code); void *prepare_sock_gz_r(FILE *sockr); char *z_read_sock(void *v); int close_sock_gz_r(void *v); char *unprotect_quotes(char *name); /* global variables */ void (*raa_error_mess_proc)(raa_db_access *, char *) = NULL; #define MAX_RDSHRT 50 /* max short list length read in one time */ #if defined(WIN32) static int socket_getc(raa_db_access *raa_current_db, SOCKET f) { int q; if(raa_current_db->sock_input_pos < raa_current_db->sock_input_end) { return *(raa_current_db->sock_input_pos++); } q = recv(f, raa_current_db->sock_input, SOCKBUFS, 0); if(q == 0 || q == SOCKET_ERROR) return EOF; raa_current_db->sock_input_end = raa_current_db->sock_input + q; raa_current_db->sock_input_pos = raa_current_db->sock_input; return *(raa_current_db->sock_input_pos++); } static char *sock_fgets(raa_db_access *raa_current_db, char *line, int len) { int c; char *p; p = line; while(len > 1) { c = socket_getc(raa_current_db, (SOCKET)(raa_current_db->raa_sockfdr) ); if(c == EOF) { if(p == line) return NULL; break; } *(p++) = c; if(c == '\n') break; len--; } *p = 0; return line; } static int mswin_sock_flush(raa_db_access *raa_current_db) { int w; char *p; p = raa_current_db->sock_output; while(raa_current_db->sock_output_lbuf > 0) { w = send((SOCKET)raa_current_db->raa_sockfdw, p, raa_current_db->sock_output_lbuf, 0); raa_current_db->sock_output_lbuf -= w; p += w; } return 0; } int sock_flush(raa_db_access *raa_current_db) { if(raa_current_db == NULL) return 0; return mswin_sock_flush(raa_current_db); } int sock_fputs(raa_db_access *raa_current_db, const char *s) { int l, r; if(raa_current_db == NULL) return 0; l = strlen(s); while(raa_current_db->sock_output_lbuf + l > SOCKBUFS) { r = SOCKBUFS - raa_current_db->sock_output_lbuf; memcpy(raa_current_db->sock_output + raa_current_db->sock_output_lbuf, s, r); raa_current_db->sock_output_lbuf += r; l -= r; s += r; mswin_sock_flush(raa_current_db); } if(l > 0) { memcpy(raa_current_db->sock_output + raa_current_db->sock_output_lbuf, s, l); raa_current_db->sock_output_lbuf += l; } return 0; } #else int sock_fputs(raa_db_access *raa_current_db, const char *s) { if(raa_current_db == NULL) return EOF; return fputs(s, raa_current_db->raa_sockfdw); } int sock_flush(raa_db_access *raa_current_db) { if(raa_current_db == NULL) return EOF; return fflush(raa_current_db->raa_sockfdw); } #endif /* WIN32 */ static int sock_printf(raa_db_access *raa_current_db, const char *fmt, ...) { va_list ap; int retval; va_start(ap, fmt); vsprintf(raa_current_db->buffer, fmt, ap); retval = sock_fputs(raa_current_db, raa_current_db->buffer); va_end(ap); return retval; } /******************************************************************/ /* lit une ligne au plus de la socket et transfere le resultat dans une chaine char * */ static char *read_sock_tell(raa_db_access *raa_current_db, int *wascompleteline) { int lnbuf, isfull; char *p ; if(raa_current_db == NULL || raa_current_db->was_here) return NULL; sock_flush(raa_current_db); /* tres important */ isfull = FALSE; #if defined(WIN32) p = sock_fgets(raa_current_db, raa_current_db->buffer, sizeof(raa_current_db->buffer)); #else p = fgets(raa_current_db->buffer, sizeof(raa_current_db->buffer), raa_current_db->raa_sockfdr); #endif if(p == NULL || strcmp(p, SERVER_UPDATE_MESSAGE) == 0) { if(!raa_current_db->was_here) { raa_current_db->was_here = TRUE; *raa_current_db->buffer = 0; if(raa_current_db != NULL && raa_current_db->dbname != NULL) { sprintf(raa_current_db->buffer, "%s: ", raa_current_db->dbname); } strcat(raa_current_db->buffer, ( p == NULL ? "Error: connection to acnuc server is down. Please try again." : "Error: acnuc server is down for database update. Please try again later." ) ); if(raa_error_mess_proc == NULL) { fprintf(stderr, "%s\n", raa_current_db->buffer); } else (*raa_error_mess_proc)(raa_current_db, raa_current_db->buffer); } return NULL; } raa_current_db->was_here = FALSE; lnbuf = strlen(raa_current_db->buffer); p = raa_current_db->buffer + lnbuf - 1; if(*p == '\n') isfull = TRUE; while(p >= raa_current_db->buffer && (*p == '\n' || *p == '\r') ) *(p--) = 0; if(wascompleteline != NULL) *wascompleteline = isfull; return raa_current_db->buffer; } char *read_sock(raa_db_access *raa_current_db) /* lit une ligne entiere, rend ligne dans memoire privee */ { int wasfull, l2, l = 0; char *p; do { p = read_sock_tell(raa_current_db, &wasfull); if(p == NULL) return NULL; l2 = strlen(p); if(l + l2 + 1 > raa_current_db->max_full_line) { raa_current_db->max_full_line = l + l2 + 100; raa_current_db->full_line = (char *)realloc(raa_current_db->full_line, raa_current_db->max_full_line); } memcpy(raa_current_db->full_line + l, p, l2); l += l2; } while(! wasfull); raa_current_db->full_line[l] = 0; return raa_current_db->full_line; } char *read_sock_timeout(raa_db_access *raa_current_db, int timeout_ms) { fd_set readfds; struct timeval tout; int err; #if defined(WIN32) SOCKET fd; if(raa_current_db == NULL) return NULL; fd = (SOCKET)(raa_current_db->raa_sockfdr); #else int fd; if(raa_current_db == NULL) return NULL; fd = fileno(raa_current_db->raa_sockfdr); #endif FD_ZERO(&readfds); FD_SET(fd, &readfds); tout.tv_sec = timeout_ms / 1000; tout.tv_usec = 1000*(timeout_ms % 1000); err = select(fd + 1, &readfds, NULL, NULL, &tout); if(err > 0 && FD_ISSET(fd, &readfds) ) { return read_sock(raa_current_db); } return NULL; } enum {errservname=1, /* bad server name */ cantopensocket, /* 2 error opening socket */ unknowndb, /* 3 not in list of known dbs */ unavailabledb, /* 4 db is currently unavailable */ dbisopen, /* 5 a db is already open and was not closed */ badpsswd, /* 6 bad password for protected db */ nomemory, /* 7 not enough memory */ badracnuc, /* 8 enviroment variables racnuc or acnuc undefined or inadequate */ nosocket /* 9 no socket was opened yet */ }; int raa_acnucopen (const char *clientid, raa_db_access **psock) /* opens the acnuc db using the environment variable racnuc, or, if undefined, acnuc, that should be defined to an url of the form raa://pbil.univ-lyon1.fr:5558/embl clientid: NULL or a string identifying the client */ { char *serveurName, *db_name, *p; int port, err; if( (p = getenv("racnuc")) == NULL) p = getenv("acnuc"); if(p == NULL) return badracnuc; err = raa_decode_address(p, &serveurName, &port, &db_name); if(err) return badracnuc; err = raa_acnucopen_alt (serveurName, port, db_name, clientid, psock); free(serveurName); if (db_name) free(db_name); return err; } int raa_acnucopen_alt (const char *serveurName, int port, const char *db_name, const char *clientid, raa_db_access **p) /* clientid: NULL or a string identifying the client */ { int err; err = raa_open_socket(serveurName, port, clientid, p); if(err != 0) return err; err = raa_opendb(*p, db_name); if(err != 0) { free(*p); } return err; } int raa_open_socket(const char *serveurName, int port, const char *clientid, raa_db_access **psock) /* clientid: NULL or a string identifying the client */ { raa_db_access *raa_current_db; struct addrinfo *ai; char *reponse, portstring[10]; int err; #ifdef WIN32 WSADATA mywsadata; SOCKET raa_snum; #else int raa_snum; #endif raa_current_db = (raa_db_access *)calloc(1, sizeof(raa_db_access)); if(raa_current_db == NULL) return nomemory; /* not enough memory */ /* création de la socket */ #ifdef WIN32 err = WSAStartup(MAKEWORD(2,2), &mywsadata); /* indispensable avant utilisation socket */ if (err == 0) raa_snum = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (GROUP)0, 0); if (err != 0 || raa_snum == INVALID_SOCKET) { free(raa_current_db); return cantopensocket; } #else raa_snum = socket(AF_INET, SOCK_STREAM, 0); if (raa_snum == -1) { free(raa_current_db); return cantopensocket; } #endif /* création de deux flux type FILE * */ #if defined(WIN32) raa_current_db->raa_sockfdr = (FILE *)raa_snum; raa_current_db->raa_sockfdw = (FILE *)raa_snum; #else raa_current_db->raa_sockfdr = fdopen(raa_snum,"r"); raa_current_db->raa_sockfdw = fdopen(raa_snum,"a"); #endif sprintf(portstring, "%d", port); err = getaddrinfo(serveurName, portstring, NULL, &ai); if (err) { free(raa_current_db); return errservname; } err = connect(raa_snum, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); if (err != 0) { free(raa_current_db); return cantopensocket; } // read first reply from the server reponse = read_sock_timeout(raa_current_db, 1000*60 /* 1 min */); if(reponse == NULL || strcmp(reponse, "OK acnuc socket started") != 0) { free(raa_current_db); return cantopensocket; } if(clientid != NULL) { sock_printf(raa_current_db, "clientid&id=\"%s\"\n", clientid); reponse=read_sock(raa_current_db); if(reponse == NULL) { free(raa_current_db); return cantopensocket; } } *psock = raa_current_db; return 0; } extern void raa_MD5String (char *in_string, char out_digest[33]); int raa_opendb_pw(raa_db_access *raa_current_db, const char *db_name, void *ptr, char *(*getpasswordf)(void *) ) /* getpasswordf: pointer to function that gets called if a password is needed ptr: pointer to data passed to the getpasswordf function return values : 3 not in list of known dbs 4 db is unavailable 5 a db is already open 6 failed password-based authorization */ { Reponse *rep; char *reponse, *code, *p, *challenge; int codret, totspecs, totkeys, i; if(raa_current_db == NULL) return nosocket; sock_printf(raa_current_db, "acnucopen&db=%s\n", db_name); reponse=read_sock(raa_current_db); if(reponse == NULL) return nosocket; rep=initreponse(); parse(reponse,rep); code=val(rep,"code"); codret=atoi(code); free(code); if(codret == 6) { char reply[33], tmp[300]; char *password = NULL; clear_reponse(rep); if(getpasswordf != NULL) password = getpasswordf(ptr); if(password == NULL) return badpsswd; challenge = reponse + 17; /* reply = MD5 of challenge:db_name:MD5(password) */ raa_MD5String(password, reply); memset(password, 0, strlen(password)); sprintf(tmp, "%s:%s:%s", challenge, db_name, reply); raa_MD5String(tmp, reply); memset(tmp, 0, strlen(tmp)); sock_printf(raa_current_db, "reply=%s\n", reply); reponse = read_sock(raa_current_db); rep=initreponse(); parse(reponse,rep); code=val(rep,"code"); codret=atoi(code); free(code); } if (codret != 0) { clear_reponse(rep); return codret; } /* initialiser les champs non nuls */ raa_current_db->gfrag_data.l_nseq_buf = INT_MAX; raa_current_db->nextelt_data.current_rank = -1; raa_current_db->nextelt_data.previous = -2; raa_current_db->readshrt_data.shrt_begin = S_BUF_SHRT - 1; #ifdef WIN32 raa_current_db->sock_input_pos = raa_current_db->sock_input; raa_current_db->sock_input_end = raa_current_db->sock_input; #endif p = val(rep,"type"); raa_current_db->dbname = strdup(db_name); raa_current_db->genbank = raa_current_db->embl = raa_current_db->swissprot = raa_current_db->nbrf = FALSE; if(p != NULL) { if(strcmp(p, "GENBANK") == 0) raa_current_db->genbank = TRUE; else if(strcmp(p, "EMBL") == 0) raa_current_db->embl = TRUE; else if(strcmp(p, "SWISSPROT") == 0) raa_current_db->swissprot = TRUE; else if(strcmp(p, "NBRF") == 0) raa_current_db->nbrf = TRUE; free(p); } p = val(rep,"totseqs"); raa_current_db->nseq = atoi(p); free(p); p = val(rep,"totspecs"); totspecs = atoi(p); free(p); p = val(rep,"totkeys"); totkeys = atoi(p); free(p); raa_current_db->maxa=(totspecs > totkeys ? totspecs : totkeys); raa_current_db->longa=(raa_current_db->maxa-1)/(8 * sizeof(int))+1; /* default values useful if talking to old server */ raa_current_db->WIDTH_SMJ = 20; raa_current_db->L_MNEMO = 16; raa_current_db->WIDTH_BIB = 40; raa_current_db->WIDTH_AUT = 20; raa_current_db->WIDTH_SP = 40; raa_current_db->WIDTH_KW = 40; raa_current_db->lrtxt = 60; raa_current_db->SUBINLNG=63; raa_current_db->VALINSHRT2=0; raa_current_db->ACC_LENGTH=13; /* conservative value */ p = val(rep,"L_MNEMO"); if(p != NULL) { raa_current_db->L_MNEMO = atoi(p); free(p); } p = val(rep,"WIDTH_SP"); if(p != NULL) { raa_current_db->WIDTH_SP = atoi(p); free(p); } p = val(rep,"WIDTH_KW"); if(p != NULL) { raa_current_db->WIDTH_KW = atoi(p); free(p); } p = val(rep,"WIDTH_AUT"); if(p != NULL) { raa_current_db->WIDTH_AUT = atoi(p); free(p); } p = val(rep,"WIDTH_BIB"); if(p != NULL) { raa_current_db->WIDTH_BIB = atoi(p); free(p); } p = val(rep,"WIDTH_SMJ"); if(p != NULL) { raa_current_db->WIDTH_SMJ = atoi(p); free(p); } p = val(rep,"ACC_LENGTH"); if(p != NULL) { raa_current_db->ACC_LENGTH = atoi(p); free(p); } p = val(rep,"lrtxt"); if(p != NULL) { raa_current_db->lrtxt = atoi(p); free(p); } p = val(rep,"SUBINLNG"); if(p != NULL) { raa_current_db->SUBINLNG = atoi(p); free(p); raa_current_db->rlng_buffer = (struct rlng *)calloc((raa_current_db->SUBINLNG + 1), sizeof(int)); } p = val(rep,"VALINSHRT2"); if (p != NULL) { raa_current_db->VALINSHRT2 = atoi(p); free(p); } int valinshrt = (raa_current_db->VALINSHRT2 ? raa_current_db->VALINSHRT2 : 1); for (i = raa_sub_of_bib; i <= raa_acc_of_loc; i++) { int size = 100 * valinshrt; raa_current_db->readshrt2_data[i] = (struct shrt2_list*)malloc(sizeof(int) * (size + 4)); raa_current_db->readshrt2_data[i]->size = size; raa_current_db->readshrt2_data[i]->length = 0; raa_current_db->readshrt2_data[i]->point = 0; raa_current_db->readshrt2_data[i]->next = 0; } clear_reponse(rep); return 0; } int raa_opendb(raa_db_access *raa_current_db, const char *db_name) { return raa_opendb_pw(raa_current_db, db_name, NULL, NULL); } int raa_decode_address(char *url, char **p_ip_name, int *socket, char **p_remote_db) /* decode syntax such as raa://pbil.univ-lyon1.fr:5557/embl return !=0 if error */ { char *p, *q; char *ip_name; char *remote_db; p = url; if(p == NULL) return 1; if( (q = strstr(url, "://") ) != NULL ) p = q + 3; q = strchr(p, ':'); if(q == NULL) return 1; ip_name = (char*)malloc(q-p+1); memcpy(ip_name, p, q - p); ip_name[q - p] = 0; if(p_ip_name != NULL) *p_ip_name = ip_name; if(socket != NULL) *socket = atoi(q+1); if(p_remote_db == NULL) return 0; q = strchr(p, '/'); if(q != NULL) { q++; while(*q == ' ') q++; if(*q == 0) *p_remote_db = NULL; else { remote_db = strdup(q); *p_remote_db = remote_db; } } else *p_remote_db = NULL; return 0; } static int fill_gfrag_buf(raa_db_access *raa_current_db, int nsub, int first) { char *p, *line; int lu, l, wasfull; sock_printf(raa_current_db,"gfrag&number=%d&start=%d&length=%d\n", nsub, first, RAA_GFRAG_BSIZE); /* retour: length=xx&...the seq...\n */ line = read_sock_tell(raa_current_db, &wasfull); if(line == NULL) return 0; if(strncmp(line, "length=", 7) != 0 || (p = strchr(line, '&')) == NULL ) { return 0; } lu = strlen(++p); memcpy(raa_current_db->gfrag_data.buffer, p, lu); while(! wasfull) { line = read_sock_tell(raa_current_db, &wasfull); if(line == NULL) break; l = strlen(line); if(lu+l <= RAA_GFRAG_BSIZE) memcpy(raa_current_db->gfrag_data.buffer + lu, line, l); lu += l; } raa_current_db->gfrag_data.buffer[lu] = 0; return lu; } int raa_gfrag(raa_db_access *raa_current_db, int nsub, int first, int lfrag, char *dseq) { int lu, piece; char *debut; if(raa_current_db == NULL) return 0; if(raa_current_db->gfrag_data.lbuf == 0 || nsub != raa_current_db->gfrag_data.nseq_buf || first >= raa_current_db->gfrag_data.first_buf + raa_current_db->gfrag_data.lbuf || first < raa_current_db->gfrag_data.first_buf) { if( nsub == raa_current_db->gfrag_data.nseq_buf && first > raa_current_db->gfrag_data.l_nseq_buf) lu = 0; else lu = fill_gfrag_buf(raa_current_db, nsub, first); if(lu == 0) return 0; raa_current_db->gfrag_data.lbuf = lu; if(raa_current_db->gfrag_data.lbuf < RAA_GFRAG_BSIZE) raa_current_db->gfrag_data.l_nseq_buf = first + raa_current_db->gfrag_data.lbuf - 1; else raa_current_db->gfrag_data.l_nseq_buf = INT_MAX; raa_current_db->gfrag_data.first_buf = first; raa_current_db->gfrag_data.nseq_buf = nsub; } debut = raa_current_db->gfrag_data.buffer + (first - raa_current_db->gfrag_data.first_buf); lu = raa_current_db->gfrag_data.lbuf + raa_current_db->gfrag_data.first_buf-1 - first+1; if( lu > lfrag) lu = lfrag; memcpy(dseq, debut, lu); while(lfrag > lu) { piece = raa_gfrag(raa_current_db, nsub, first + lu, lfrag - lu, dseq + lu); if(piece == 0) break; lu += piece; } dseq[lu] = 0; return lu; } static void raa_free_sp_tree(raa_node *pere) { raa_node *next, *tmp_n; struct raa_pair *liste, *tmp_p; liste = pere->list_desc; while(liste != NULL) { tmp_p = liste->next; raa_free_sp_tree(liste->value); free(liste); liste = tmp_p; } next = pere->syno; while(next != NULL && next != pere) { tmp_n = next->syno; free(next->name); free(next); next = tmp_n; } free(pere->name); if(pere->libel != NULL) free(pere->libel); if(pere->libel_upcase != NULL) free(pere->libel_upcase); free(pere); } void raa_acnucclose(raa_db_access *raa_current_db) { char *reponse; int i; if(raa_current_db == NULL) return; sock_fputs(raa_current_db, "acnucclose\n"); reponse=read_sock(raa_current_db); if(reponse != NULL) { sock_fputs(raa_current_db, "quit\n"); sock_flush(raa_current_db); } #ifdef WIN32 closesocket( (SOCKET) (raa_current_db->raa_sockfdw) ); #else fclose(raa_current_db->raa_sockfdr); fclose(raa_current_db->raa_sockfdw); #endif if(raa_current_db->tot_key_annots > 0) { for(i = 0; i < raa_current_db->tot_key_annots; i++) { free(raa_current_db->key_annots[i]); free(raa_current_db->key_annots_min[i]); } free(raa_current_db->key_annots); free(raa_current_db->key_annots_min); free(raa_current_db->want_key_annots); raa_current_db->tot_key_annots = 0; } if(raa_current_db->tid_to_rank != NULL) free(raa_current_db->tid_to_rank); if(raa_current_db->sp_tree != NULL) { raa_free_sp_tree(raa_current_db->sp_tree[2]); free(raa_current_db->sp_tree); } if(raa_current_db->dbname != NULL) free(raa_current_db->dbname); if(raa_current_db->rlng_buffer != NULL) free(raa_current_db->rlng_buffer); if(raa_current_db->readsub_data.name != NULL) free(raa_current_db->readsub_data.name); for(i = 0; i < raa_current_db->annot_data.annotcount; i++) free(raa_current_db->annot_data.annotline[i]); for(i = 0; i < BLOCK_ELTS_IN_LIST; i++) if(raa_current_db->nextelt_data.tabname[i] != NULL) free(raa_current_db->nextelt_data.tabname[i]); if(raa_current_db->readsmj_data.lastrec > 0) { free(raa_current_db->readsmj_data.plongs); for(i=2; i <= raa_current_db->readsmj_data.lastrec; i++) { if(raa_current_db->readsmj_data.names[i] != NULL) free(raa_current_db->readsmj_data.names[i]); if(raa_current_db->readsmj_data.libels[i] != NULL) free(raa_current_db->readsmj_data.libels[i]); } free(raa_current_db->readsmj_data.names); free(raa_current_db->readsmj_data.libels); raa_current_db->readsmj_data.lastrec = 0; } raa_free_matchkeys(raa_current_db); if (raa_current_db->full_line) free(raa_current_db->full_line); if (raa_current_db->namestr) free(raa_current_db->namestr); if (raa_current_db->help) free(raa_current_db->help); if (raa_current_db->tmp_prelist) free(raa_current_db->tmp_prelist); if (raa_current_db->translate_buffer) free(raa_current_db->translate_buffer); free(raa_current_db); } int raa_prep_acnuc_query(raa_db_access *raa_current_db) { /* returns -1 if error or number of free bit lists */ char *reponse, *p, *q, *annotlines; int codret, i; Reponse *rep; if(raa_current_db == NULL) return -1; rep = initreponse(); sock_fputs(raa_current_db, "countfreelists\n"); reponse=read_sock(raa_current_db); if(reponse == NULL) return -1; parse(reponse,rep); reponse=val(rep,"code"); if(reponse == NULL) return -1; codret=atoi(reponse); free(reponse); if(codret != 0) return -1; reponse=val(rep,"free"); if(reponse != NULL) { codret = atoi(reponse); free(reponse); } annotlines = val(rep, "annotlines"); raa_current_db->tot_key_annots = 0; if(annotlines != NULL) { p = annotlines - 1; do { p++; raa_current_db->tot_key_annots++; } while((p = strchr(p, '|')) != NULL); raa_current_db->want_key_annots = (unsigned char *)malloc(raa_current_db->tot_key_annots * sizeof(unsigned char)); raa_current_db->key_annots = (char **)malloc(raa_current_db->tot_key_annots * sizeof(char *)); raa_current_db->key_annots_min = (char **)malloc(raa_current_db->tot_key_annots * sizeof(char *)); p = annotlines; for(i = 0; i < raa_current_db->tot_key_annots; i++) { q = strchr(p, '|'); if(q == NULL) q = p + strlen(p); raa_current_db->key_annots[i] = malloc(q - p + 1); raa_current_db->key_annots_min[i] = malloc(q - p + 1); memcpy(raa_current_db->key_annots_min[i], p, q - p); raa_current_db->key_annots_min[i][q - p] = 0; strcpy(raa_current_db->key_annots[i], raa_current_db->key_annots_min[i]); majuscules(raa_current_db->key_annots[i]); compact(raa_current_db->key_annots[i]); p = q + 1; } free(annotlines); } else codret = -1; clear_reponse(rep); return codret; } static char *raa_requete_remote_file(raa_db_access *raa_current_db, char *oldrequete, int **plist, char **); int raa_proc_query(raa_db_access *raa_current_db, char *requete, char **message, char *nomliste, int *numlist, int *count, int *locus, int *type) { char *reponse, *code, *numlistchr, *countchr, *locuschr, *typechr, *badfname, *p; int codret, *tmp_blists; Reponse *rep; if(raa_current_db == NULL) return -1; requete = raa_requete_remote_file(raa_current_db, requete, &tmp_blists, &badfname); if(requete == NULL) { if(message != NULL) { char fmt[] = "problem accessing file: %s"; *message = (char *)malloc(strlen(fmt) + strlen(badfname) + 1); sprintf(*message, fmt, badfname); } return 1; } p = protect_quotes(requete); sock_printf(raa_current_db,"proc_query&query=\"%s\"&name=\"%s\"\n", p, nomliste); free(p); free(requete); reponse=read_sock(raa_current_db); if(reponse == NULL) { if(message != NULL) *message = strdup("connection with server is down"); return -1; } rep=initreponse(); parse(reponse,rep); code=val(rep,"code"); codret=atoi(code); if(codret == 0) { numlistchr=val(rep,"lrank"); *numlist=atoi(numlistchr); countchr=val(rep,"count"); if(count != NULL) *count=atoi(countchr); typechr=val(rep,"type"); locuschr=val(rep,"locus"); if(type != NULL) { if (strcmp(typechr,"SQ")==0) *type='S'; else if (strcmp(typechr,"KW")==0) *type='K'; else if (strcmp(typechr,"SP")==0) *type='E'; } if(locus != NULL) *locus = strcmp(locuschr,"T") == 0; free(countchr); free(locuschr); free(typechr); free(numlistchr); } else if(message != NULL) { *message = val(rep, "message"); } free(code); clear_reponse(rep); if(tmp_blists != NULL) { while(*tmp_blists != 0) raa_releaselist(raa_current_db, *(tmp_blists++) ); } return codret; } int raa_nexteltinlist(raa_db_access *raa_current_db, int first, int lrank, char **pname, int *plength) { return raa_nexteltinlist_annots(raa_current_db, first, lrank, pname, plength, NULL, NULL); } int raa_nexteltinlist_annots(raa_db_access *raa_current_db, int first, int lrank, char **pname, int *plength, raa_long *paddr, int *pdiv) { int num, next, count; char *p; Reponse *rep; if(raa_current_db == NULL) return 0; if(lrank == raa_current_db->nextelt_data.current_rank && raa_current_db->nextelt_data.previous < raa_current_db->nextelt_data.total - 1 && (raa_current_db->nextelt_data.previous == -1 || first == raa_current_db->nextelt_data.tabnum[raa_current_db->nextelt_data.previous] ) ) { raa_current_db->nextelt_data.previous++; next = raa_current_db->nextelt_data.tabnum[raa_current_db->nextelt_data.previous]; if(next != 0) { if(pname != NULL) *pname = raa_current_db->nextelt_data.tabname[raa_current_db->nextelt_data.previous]; if(plength != NULL) *plength = raa_current_db->nextelt_data.tablength[raa_current_db->nextelt_data.previous]; if(paddr != NULL) *paddr = raa_current_db->nextelt_data.taboffset[raa_current_db->nextelt_data.previous]; if(pdiv != NULL) *pdiv = raa_current_db->nextelt_data.tabdiv[raa_current_db->nextelt_data.previous]; } return next; } count = BLOCK_ELTS_IN_LIST; for(num = 0; num < count; num++) { if(raa_current_db->nextelt_data.tabname[num] != NULL) free(raa_current_db->nextelt_data.tabname[num]); } memset(raa_current_db->nextelt_data.tabname, 0, count * sizeof(char *)); sock_printf(raa_current_db,"nexteltinlist&lrank=%d&first=%d&count=%d\n",lrank,first, count); num = 0; raa_current_db->nextelt_data.current_rank = lrank; raa_current_db->nextelt_data.total = 0; do { p = read_sock(raa_current_db); if(p == NULL) return 0; rep = initreponse(); parse(p, rep); p = val(rep,"next"); if(p == NULL) { clear_reponse(rep); return 0; } next = atoi(p); free(p); raa_current_db->nextelt_data.total++; raa_current_db->nextelt_data.tabnum[num] = next; if(next != 0) { raa_current_db->nextelt_data.tabname[num] = val(rep, "name"); if( (p= val(rep, "length")) != NULL) { raa_current_db->nextelt_data.tablength[num] = atoi(p); free(p); } if((p= val(rep, "offset")) != NULL) { raa_current_db->nextelt_data.taboffset[num] = scan_raa_long(p); free(p); } if((p= val(rep, "div")) != NULL) { raa_current_db->nextelt_data.tabdiv[num] = atoi(p); free(p); } } clear_reponse(rep); num++; } while(next != 0 && --count > 0); raa_current_db->nextelt_data.previous = -1; return raa_nexteltinlist_annots(raa_current_db, first, lrank, pname, plength, paddr, pdiv); } raa_long scan_raa_long(char *txt) { raa_long val; sscanf(txt, RAA_LONG_FORMAT, &val); return val; } char *print_raa_long(raa_long val, char *buffer) { sprintf(buffer, RAA_LONG_FORMAT, val); return buffer; } static char *load_annots_buf(raa_db_access *raa_current_db, raa_long faddr, int div, int was_nextannots) /* appeler juste après avoir envoye sur socket read_annots&... ou next_annots&... : retour attendu sur socket : nl=xx[&offset=xx]&...nl lines each with \n */ { int i, nl; char *firstline, *p, *q; if(raa_current_db == NULL) return NULL; for(i=0; i < raa_current_db->annot_data.annotcount; i++) free(raa_current_db->annot_data.annotline[i]); raa_current_db->annot_data.annotcount = 0; raa_current_db->annot_data.annotaddrlast = faddr; firstline = read_sock(raa_current_db); if(firstline == NULL) return NULL; if(strncmp(firstline, "nl=", 3) != 0 || (p = strchr(firstline, '&')) == NULL ) return NULL; nl = atoi(firstline + 3); if(nl == 0) return NULL; p++; if(was_nextannots && strncmp(p, "offset=", 7) == 0) { p = strchr(p, '&'); if(p == NULL) return NULL; p++; } i = strlen(p); raa_current_db->annot_data.annotline[0] = (char *)malloc(i+1); strcpy(raa_current_db->annot_data.annotline[0], p); raa_current_db->annot_data.annotaddrlast += strlen(raa_current_db->annot_data.annotline[0]) + 1; for(i = 1; i < nl; i++) { q = read_sock(raa_current_db); if(q == NULL) return NULL; raa_current_db->annot_data.annotline[i] = strdup( q ); raa_current_db->annot_data.annotaddrlast += strlen(raa_current_db->annot_data.annotline[i]) + 1; } raa_current_db->annot_data.annotcurrent = 1; raa_current_db->annot_data.annotcount = nl; raa_current_db->annot_data.annotaddr = faddr; raa_current_db->annot_data.annotdiv = div; raa_current_db->annot_data.annotaddrfirst = faddr; strcpy(raa_current_db->annot_data.annotsbuffer, raa_current_db->annot_data.annotline[0]); return raa_current_db->annot_data.annotsbuffer; } char *raa_read_annots(raa_db_access *raa_current_db, raa_long faddr, int div) { int i; raa_long debut; char *p, buffer[40]; if(raa_current_db == NULL) return NULL; if(raa_current_db->annot_data.annotcount > 0 && div == raa_current_db->annot_data.annotdiv && faddr >= raa_current_db->annot_data.annotaddrfirst && faddr < raa_current_db->annot_data.annotaddrlast ) { debut = raa_current_db->annot_data.annotaddrfirst; for(i = 1; i <= raa_current_db->annot_data.annotcount; i++) { if(debut == faddr) { raa_current_db->annot_data.annotcurrent = i; raa_current_db->annot_data.annotaddr = debut; strcpy(raa_current_db->annot_data.annotsbuffer, raa_current_db->annot_data.annotline[raa_current_db->annot_data.annotcurrent - 1]); return raa_current_db->annot_data.annotsbuffer; } debut += strlen(raa_current_db->annot_data.annotline[i - 1]) + 1; } } sock_printf(raa_current_db,"read_annots&offset=%s&div=%d&nl=%d\n", print_raa_long(faddr, buffer), div, ANNOTCOUNT); p = load_annots_buf(raa_current_db, faddr, div, FALSE); return p; } char *raa_next_annots(raa_db_access *raa_current_db, raa_long *paddr) { raa_long faddr; char *p; if(raa_current_db == NULL) return NULL; if(raa_current_db->annot_data.annotcurrent < raa_current_db->annot_data.annotcount) { raa_current_db->annot_data.annotaddr += strlen(raa_current_db->annot_data.annotline[raa_current_db->annot_data.annotcurrent - 1]) + 1; if(paddr != NULL) *paddr = raa_current_db->annot_data.annotaddr; raa_current_db->annot_data.annotcurrent++; strcpy(raa_current_db->annot_data.annotsbuffer, raa_current_db->annot_data.annotline[raa_current_db->annot_data.annotcurrent - 1]); return raa_current_db->annot_data.annotsbuffer; } faddr = raa_current_db->annot_data.annotaddrlast; if(paddr != NULL) *paddr = faddr; sock_printf(raa_current_db, "next_annots&nl=%d\n", ANNOTCOUNT); p = load_annots_buf(raa_current_db, faddr, raa_current_db->annot_data.annotdiv, TRUE); return p; } int raa_iknum(raa_db_access *raa_current_db, char *name, raa_file cas) { char *reponse, *p; int val; if(raa_current_db == NULL) return 0; p = protect_quotes(name); sock_printf(raa_current_db,"iknum&name=\"%s\"&type=%s\n", p, (cas == raa_key ? "KW" : "SP") ); free(p); reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; p = strchr(reponse, '='); if(p == NULL) return 0; p++; sscanf(p, "%u", &val); return val; } int raa_isenum(raa_db_access *raa_current_db, char *name) { char *reponse, *p; int val; if(raa_current_db == NULL) return 0; p = protect_quotes(name); sock_printf(raa_current_db,"isenum&name=\"%s\"\n", p ); free(p); reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; p = strchr(reponse, '='); if(p == NULL) return 0; p++; sscanf(p, "%u", &val); return val; } int raa_bcount(raa_db_access *raa_current_db, int lrank) { Reponse *rep; char *reponse, *code, *countstr; int count = 0; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_printf(raa_current_db,"bcount&lrank=%d\n",lrank); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); code = val(rep,"code"); if(*code == '0') { countstr = val(rep,"count"); count = atoi(countstr); free(countstr); } free(code); clear_reponse(rep); return count; } void raa_bit1(raa_db_access *raa_current_db, int lrank, int num) { char *reponse; if(raa_current_db == NULL) return; sock_printf(raa_current_db,"bit1&lrank=%d&num=%d\n", lrank, num); reponse=read_sock(raa_current_db); } void raa_bit0(raa_db_access *raa_current_db, int lrank, int num) { char *reponse; if(raa_current_db == NULL) return; sock_printf(raa_current_db,"bit0&lrank=%d&num=%d\n", lrank, num); reponse=read_sock(raa_current_db); } int raa_btest(raa_db_access *raa_current_db, int lrank, int num) { char *reponse; if(raa_current_db == NULL) return 0; sock_printf(raa_current_db,"btest&lrank=%d&num=%d\n", lrank, num); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; return strcmp(reponse, "code=0&on") == 0; } void raa_copylist(raa_db_access *raa_current_db, int from, int to) { char *reponse; if(raa_current_db == NULL) return; sock_printf(raa_current_db,"copylist&lfrom=%d<o=%d\n", from, to); reponse=read_sock(raa_current_db); } void raa_zerolist(raa_db_access *raa_current_db, int rank) { char *reponse; if(raa_current_db == NULL) return; sock_printf(raa_current_db,"zerolist&lrank=%d\n", rank); reponse=read_sock(raa_current_db); } void raa_setliststate(raa_db_access *raa_current_db, int lrank, int locus, int type) { char *reponse, str_type[3]; if(raa_current_db == NULL) return; if(type == 'S') strcpy(str_type, "SQ"); else if(type == 'K') strcpy(str_type, "KW"); else strcpy(str_type, "SP"); sock_printf(raa_current_db,"setliststate&lrank=%d&locus=%c&type=%s\n", lrank, (locus ? 'T' : 'F'), str_type ); reponse=read_sock(raa_current_db); } char *raa_getliststate(raa_db_access *raa_current_db, int lrank, int *locus, int *type, int *count) { Reponse *rep; char *reponse, *code, *countstr, *locusstr, *typestr, *retp = NULL; if(raa_current_db == NULL) return NULL; rep=initreponse(); sock_printf(raa_current_db,"getliststate&lrank=%d\n",lrank); reponse=read_sock(raa_current_db); if(reponse == NULL) return NULL; parse(reponse, rep); code = val(rep,"code"); if(code != NULL && *code == '0') { typestr = val(rep,"type"); if(type != NULL) { if(strcmp(typestr, "SQ") == 0) *type = 'S'; else if(strcmp(typestr, "KW") == 0) *type = 'K'; else *type = 'E'; } if(raa_current_db->namestr != NULL) free(raa_current_db->namestr); /* allocation precedante */ raa_current_db->namestr = val(rep, "name"); countstr = val(rep, "count"); if(count != NULL) *count = atoi(countstr); locusstr = val(rep, "locus"); if(locus != NULL) *locus = (*locusstr == 'T'); free(countstr); free(locusstr); free(typestr); retp = raa_current_db->namestr; } if(code != NULL) free(code); clear_reponse(rep); return retp; } char *raa_residuecount(raa_db_access *raa_current_db, int lrank) { Reponse *rep; char *reponse, *code; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_printf(raa_current_db,"residuecount&lrank=%d\n",lrank); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); code = val(rep,"code"); strcpy(raa_current_db->residuecount, "0"); if(code != NULL && *code == '0') { free(code); code = val(rep,"count"); if(code != NULL) { strcpy(raa_current_db->residuecount, code); free(code); } } clear_reponse(rep); return raa_current_db->residuecount; } int raa_getemptylist(raa_db_access *raa_current_db, char *name) { Reponse *rep; char *reponse, *code, *rankstr, *p; int rank = 0; if(raa_current_db == NULL) return 0; rep=initreponse(); p = protect_quotes(name); sock_printf(raa_current_db, "getemptylist&name=\"%s\"\n", p); free(p); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); code = val(rep,"code"); if(code != NULL && (*code == '0' || *code == '3') ) { rankstr = val(rep, "lrank"); rank = atoi(rankstr); free(rankstr); } if(code != NULL) free(code); clear_reponse(rep); return rank; } int raa_setlistname(raa_db_access *raa_current_db, int lrank, char *name) { Reponse *rep; char *reponse, *code; int retval; if(raa_current_db == NULL) return -1; rep=initreponse(); sock_printf(raa_current_db, "setlistname&lrank=%d&name=\"%s\"\n", lrank, name); reponse=read_sock(raa_current_db); if(reponse == NULL) return -1; parse(reponse, rep); code = val(rep,"code"); if(*code == '0') retval = 0; else if(*code == '3') retval = 1; else retval = -1; free(code); clear_reponse(rep); return retval; } int raa_getlistrank(raa_db_access *raa_current_db, char *name) { Reponse *rep; char *reponse, *rankstr; int rank; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_printf(raa_current_db, "getlistrank&name=\"%s\"\n", name); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); rankstr = val(rep,"lrank"); if(rankstr == NULL) return 0; rank = atoi(rankstr); free(rankstr); clear_reponse(rep); return rank; } int raa_releaselist(raa_db_access *raa_current_db, int lrank) { Reponse *rep; char *reponse, *rankstr; int rank; if(raa_current_db == NULL) return 1; rep=initreponse(); sock_printf(raa_current_db, "releaselist&lrank=%d\n", lrank); reponse=read_sock(raa_current_db); if(reponse == NULL) return 1; parse(reponse, rep); rankstr = val(rep,"code"); if(rankstr == NULL) return 1; rank = atoi(rankstr); free(rankstr); clear_reponse(rep); return rank; } int raa_countfilles(raa_db_access *raa_current_db, int lrank) { Reponse *rep; char *reponse, *rankstr; int rank; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_printf(raa_current_db, "countsubseqs&lrank=%d\n", lrank); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); rankstr = val(rep,"count"); if(rankstr == NULL) return 0; rank = atoi(rankstr); free(rankstr); clear_reponse(rep); return rank; } int raa_alllistranks(raa_db_access *raa_current_db, int **pranks) { Reponse *rep; char *reponse, *rankstr, *p; int count, *ranks, i; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_fputs(raa_current_db, "alllistranks\n"); reponse=read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); rankstr = val(rep,"count"); p = strchr(reponse, '&'); if(rankstr == NULL || p == NULL) return 0; count = atoi(rankstr); ranks = (int *)malloc(count * sizeof(int)); if(ranks == NULL ) return 0; p++; for(i=0; i< count; i++) { sscanf(p, "%d", &ranks[i]); p = strchr(p, ','); if(p == NULL) break; p++; } *pranks = ranks; free(rankstr); clear_reponse(rep); return count; } int raa_fcode(raa_db_access *raa_current_db, raa_file cas, char *name) { char *reponse, *p, type[5]; int value; if(raa_current_db == NULL) return 0; if(cas == raa_aut) strcpy(type, "AUT"); else if(cas == raa_bib) strcpy(type, "BIB"); else if(cas == raa_acc) strcpy(type, "ACC"); else if(cas == raa_smj) strcpy(type, "SMJ"); else if(cas == raa_sub) strcpy(type, "SUB"); else return 0; p = protect_quotes(name); sock_printf(raa_current_db,"fcode&name=\"%s\"&type=%s\n", p, type ); free(p); reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; p = strchr(reponse, '='); if(p == NULL) return 0; p++; sscanf(p, "%u", &value); return value; } int raa_read_first_rec(raa_db_access *raa_current_db, raa_file cas) { int value; char type[5], *p, *reponse; if(raa_current_db == NULL) return 1; if(raa_current_db->first_recs[cas] != 0) return raa_current_db->first_recs[cas]; if(cas == raa_aut) strcpy(type, "AUT"); else if(cas == raa_bib) strcpy(type, "BIB"); else if(cas == raa_acc) strcpy(type, "ACC"); else if(cas == raa_smj) strcpy(type, "SMJ"); else if(cas == raa_sub) strcpy(type, "SUB"); else if(cas == raa_loc) strcpy(type, "LOC"); else if(cas == raa_key) strcpy(type, "KEY"); else if(cas == raa_spec) strcpy(type, "SPEC"); else if(cas == raa_shrt) strcpy(type, "SHRT"); else if(cas == raa_lng) strcpy(type, "LNG"); else if(cas == raa_ext) strcpy(type, "EXT"); else if(cas == raa_txt) strcpy(type, "TXT"); else return 0; sock_printf(raa_current_db,"readfirstrec&type=%s\n", type ); reponse = read_sock(raa_current_db); if(reponse == NULL) return 1; p = strstr(reponse, "count="); if(p == NULL) return 0; sscanf(p + 6, "%u", &value); raa_current_db->first_recs[cas] = value; return value; } char *raa_readsub_pannots(raa_db_access *raa_current_db, int num, int *plength, int *ptype, int *pext, int *plkey, int *plocus, int *pframe, int *pgencode, raa_long *paddr, int *pdiv) /* do both seq_to_annots and readsub and buffer result for one seq */ { Reponse *rep; char *p, *reponse; int code, l; if(raa_current_db == NULL) return NULL; if(num < 2 || num > raa_current_db->nseq) return NULL; if(num != raa_current_db->readsub_data.previous) { sock_printf(raa_current_db,"seq_to_annots&number=%d\nreadsub&num=%u\n", num, num); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; /* process reply to seq_to_annots */ rep=initreponse(); parse(reponse, rep); p = val(rep,"code"); code = atoi(p); free(p); if(code == 0) { p = val(rep,"offset"); raa_current_db->readsub_data.addr = scan_raa_long(p); free(p); p = val(rep,"div"); raa_current_db->readsub_data.div = atoi(p); free(p); } clear_reponse(rep); /* process reply to readsub */ reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; rep=initreponse(); parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return NULL; code = atoi(p); free(p); if(code != 0) { clear_reponse(rep); return NULL; } p = val(rep, "name"); l = strlen(p) + 1; if(l > raa_current_db->readsub_data.lname) { raa_current_db->readsub_data.lname = l; raa_current_db->readsub_data.name = (char *)realloc(raa_current_db->readsub_data.name, raa_current_db->readsub_data.lname); } strcpy(raa_current_db->readsub_data.name, p); free(p); p = val(rep, "length"); raa_current_db->readsub_data.length = atoi(p); free(p); p = val(rep, "type"); raa_current_db->readsub_data.type = atoi_u(p); free(p); p = val(rep, "is_sub"); raa_current_db->readsub_data.locus = atoi_u(p); free(p); p = val(rep, "toext"); raa_current_db->readsub_data.toext = atoi_u(p); if(raa_current_db->readsub_data.locus > 0) raa_current_db->readsub_data.toext = - raa_current_db->readsub_data.toext; free(p); p = val(rep, "plkey"); raa_current_db->readsub_data.lkey = atoi_u(p); free(p); p = val(rep, "frame"); raa_current_db->readsub_data.frame = atoi_u(p); free(p); p = val(rep, "genet"); raa_current_db->readsub_data.gencode = atoi_u(p); free(p); raa_current_db->readsub_data.previous = num; clear_reponse(rep); } if(plength != NULL) *plength = raa_current_db->readsub_data.length; if(ptype != NULL) *ptype = raa_current_db->readsub_data.type; if(plocus != NULL) *plocus = raa_current_db->readsub_data.locus; if(pext != NULL) *pext = raa_current_db->readsub_data.toext; if(plkey != NULL) *plkey = raa_current_db->readsub_data.lkey; if(pframe != NULL) *pframe = raa_current_db->readsub_data.frame; if(pgencode != NULL) *pgencode = raa_current_db->readsub_data.gencode; if(paddr != NULL) *paddr = raa_current_db->readsub_data.addr; if(pdiv != NULL) *pdiv = raa_current_db->readsub_data.div; return raa_current_db->readsub_data.name; } int raa_seq_to_annots(raa_db_access *raa_current_db, int numseq, raa_long *faddr, int *div) { char *p; p = raa_readsub_pannots(raa_current_db, numseq,NULL,NULL,NULL,NULL,NULL,NULL,NULL,faddr,div); return p == NULL; } char *raa_readsub(raa_db_access *raa_current_db, int num, int *plength, int *ptype, int *pext, int *plkey, int *plocus, int *pframe, int *pgencode) { return raa_readsub_pannots(raa_current_db, num,plength,ptype,pext,plkey,plocus,pframe,pgencode,NULL,NULL); } char *raa_readloc(raa_db_access *raa_current_db, int num, int *sub, int *pnuc, int *spec, int *host, int *plref, int *molec, int *placc, int *org) { Reponse *rep; char *p, *reponse; int code; if(raa_current_db == NULL) return NULL; rep=initreponse(); sock_printf(raa_current_db,"readloc&num=%u\n", num); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return NULL; code = atoi(p); free(p); if(code == 0) { if(sub != NULL) { p = val(rep, "sub"); *sub = atoi_u(p); free(p); } if(pnuc != NULL) { p = val(rep, "pnuc"); *pnuc = atoi_u(p); free(p); } if(spec != NULL) { p = val(rep, "spec"); *spec = atoi_u(p); free(p); } if(host != NULL) { p = val(rep, "host"); *host = atoi_u(p); free(p); } if(plref != NULL) { p = val(rep, "plref"); *plref = atoi_u(p); free(p); } if(molec != NULL) { p = val(rep, "molec"); *molec = atoi_u(p); free(p); } if(placc != NULL) { p = val(rep, "placc"); *placc = atoi_u(p); free(p); } if(org != NULL) { p = val(rep, "org"); *org = atoi_u(p); free(p); } p = val(rep, "date"); strcpy(raa_current_db->date, p); free(p); p = raa_current_db->date; } else p = NULL; clear_reponse(rep); return p; } char *raa_readspec(raa_db_access *raa_current_db, int num, char **plibel, int *plsub, int *pdesc, int *psyno, int *plhost) { Reponse *rep; char *p, *reponse; int code; if(raa_current_db == NULL) return NULL; if(num == raa_current_db->readspec_data.previous && raa_current_db->readspec_data.previous != 0) { if(plibel != NULL) { if(*(raa_current_db->readspec_data.libel) != 0) *plibel = raa_current_db->readspec_data.libel; else *plibel = NULL; } if(plsub != NULL) *plsub = raa_current_db->readspec_data.lsub; if(pdesc != NULL) *pdesc = raa_current_db->readspec_data.desc; if(psyno != NULL) *psyno = raa_current_db->readspec_data.syno; if(plhost != NULL) *plhost = raa_current_db->readspec_data.host; return raa_current_db->readspec_data.name; } rep=initreponse(); sock_printf(raa_current_db, "readspec&num=%u\n", num); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return NULL; code = atoi(p); free(p); if(code != 0) { clear_reponse(rep); return NULL; } raa_current_db->readspec_data.previous = num; p = val(rep, "plsub"); raa_current_db->readspec_data.lsub = atoi_u(p); free(p); p = val(rep, "desc"); raa_current_db->readspec_data.desc = atoi_u(p); free(p); p = val(rep, "syno"); raa_current_db->readspec_data.syno = atoi_u(p); free(p); p = val(rep, "host"); raa_current_db->readspec_data.host = atoi_u(p); free(p); p = val(rep, "libel"); if(p != NULL) { strcpy(raa_current_db->readspec_data.libel, p); free(p); } else *(raa_current_db->readspec_data.libel) = 0; p = val(rep, "name"); strcpy(raa_current_db->readspec_data.name, p ); free(p); clear_reponse(rep); return raa_readspec(raa_current_db, num, plibel, plsub, pdesc, psyno, plhost); } char *raa_readkey(raa_db_access *raa_current_db, int num, char **plibel, int *plsub, int *pdesc, int *psyno) { Reponse *rep; char *p, *reponse; int code; if(raa_current_db == NULL) return NULL; if(num == raa_current_db->readkey_data.previous && raa_current_db->readkey_data.previous != 0) { if(plibel != NULL) { if(*(raa_current_db->readkey_data.libel) != 0) *plibel = raa_current_db->readkey_data.libel; else *plibel = NULL; } if(plsub != NULL) *plsub = raa_current_db->readkey_data.lsub; if(pdesc != NULL) *pdesc = raa_current_db->readkey_data.desc; if(psyno != NULL) *psyno = raa_current_db->readkey_data.syno; return raa_current_db->readkey_data.name; } rep=initreponse(); sock_printf(raa_current_db, "readkey&num=%u\n", num); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return NULL; code = atoi(p); free(p); if(code != 0) { clear_reponse(rep); return NULL; } raa_current_db->readkey_data.previous = num; p = val(rep, "plsub"); raa_current_db->readkey_data.lsub = atoi_u(p); free(p); p = val(rep, "desc"); raa_current_db->readkey_data.desc = atoi_u(p); free(p); p = val(rep, "syno"); raa_current_db->readkey_data.syno = atoi_u(p); free(p); p = val(rep, "libel"); if(p != NULL) { strcpy(raa_current_db->readkey_data.libel, p); free(p); } else *(raa_current_db->readkey_data.libel) = 0; p = val(rep, "name"); strcpy(raa_current_db->readkey_data.name, p); free(p); clear_reponse(rep); return raa_readkey(raa_current_db, num, plibel, plsub, pdesc, psyno); } static int load_smj(raa_db_access *raa_current_db, char ***names, unsigned **plongs, char ***libels) { Reponse *rep; char *reponse, *p; int nl, i, code, totsmj, recnum; if(raa_current_db == NULL) return 0; totsmj = raa_read_first_rec(raa_current_db, raa_smj); rep=initreponse(); sock_printf(raa_current_db,"readsmj&num=2&nl=%d\n", totsmj - 1); /* ==>readsmj&num=..&nl=.. code=0&nl=.. recnum=..&name=".."&plong=..{&libel=".."} nl times */ reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return 0; code = atoi(p); free(p); if(code != 0) return 0; p = val(rep,"nl"); if(p == NULL) return 0; nl = atoi(p); free(p); clear_reponse(rep); if(nl == 0) return 0; *names = (char **)calloc(totsmj + 1 , sizeof(char *)); *plongs = (unsigned *)calloc(totsmj + 1 , sizeof(unsigned)); *libels = (char **)calloc(totsmj + 1 , sizeof(char *)); for(i = 0; i < nl; i++) { reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; rep=initreponse(); parse(reponse, rep); p = val(rep, "recnum"); recnum = atoi(p); free(p); p = val(rep, "plong"); (*plongs)[recnum] = atoi_u(p); free(p); p = val(rep, "name"); (*names)[recnum] = p; p = val(rep, "libel"); (*libels)[recnum] = p; clear_reponse(rep); } return totsmj; } char *raa_readsmj(raa_db_access *raa_current_db, int num, char **plibel, int *plong) { if(raa_current_db == NULL) return NULL; if(raa_current_db->readsmj_data.lastrec == 0) { raa_current_db->readsmj_data.lastrec = load_smj(raa_current_db, &raa_current_db->readsmj_data.names, &raa_current_db->readsmj_data.plongs, &raa_current_db->readsmj_data.libels); } if(num <= 1 || num > raa_current_db->readsmj_data.lastrec) return NULL; if(plong != NULL) *plong = raa_current_db->readsmj_data.plongs[num]; if(plibel != NULL) *plibel = raa_current_db->readsmj_data.libels[num]; return raa_current_db->readsmj_data.names[num]; } char *raa_readacc(raa_db_access *raa_current_db, int num, int *plsub) { Reponse *rep; char *p, *reponse; int code; if(raa_current_db == NULL) return NULL; rep=initreponse(); sock_printf(raa_current_db,"readacc&num=%u\n", num); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return NULL; code = atoi(p); free(p); if(code == 0) { if(plsub != NULL) { p = val(rep, "plsub"); *plsub = atoi_u(p); free(p); } p = val(rep, "name"); strcpy(raa_current_db->access, p); free(p); p = raa_current_db->access; } else p = NULL; clear_reponse(rep); return p; } int raa_readext(raa_db_access *raa_current_db, int num, int *mere, int *deb, int *fin) { Reponse *rep; char *p, *reponse; int code, next; if(raa_current_db == NULL) return 0; rep=initreponse(); sock_printf(raa_current_db,"readext&num=%u\n", num); reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; parse(reponse, rep); p = val(rep,"code"); if(p == NULL) return 0; code = atoi(p); free(p); if(code == 0) { if(mere != NULL) { p = val(rep, "mere"); *mere = atoi_u(p); free(p); } if(deb != NULL) { p = val(rep, "debut"); *deb = atoi_u(p); free(p); } if(fin != NULL) { p = val(rep, "fin"); *fin = atoi_u(p); free(p); } p = val(rep, "next"); next = atoi_u(p); free(p); } else next = 0; clear_reponse(rep); return next; } int raa_readlng(raa_db_access *raa_current_db, int num) /* fills the rlng_buffer structure */ { char *p, *reponse; int count, i; if(raa_current_db == NULL) return 0; memset(raa_current_db->rlng_buffer, 0, (raa_current_db->SUBINLNG+1)*sizeof(int)); sock_printf(raa_current_db,"readlng&num=%u\n", num); /* retour code=0&n=xx&x1,x2,...{&next=xx} */ reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; if(strncmp(reponse, "code=0&n=", 9) != 0 || (count = atoi(reponse+9)) == 0) { return 0; } p = strchr(reponse+9, '&'); for(i=0; i < count && i < raa_current_db->SUBINLNG; i++) { raa_current_db->rlng_buffer->sub[i] = atoi_u(p+1); p = strchr(p+1, ','); if(p == NULL) break; } p = strstr(reponse, "next="); if(p!= NULL) raa_current_db->rlng_buffer->next = atoi_u(p+5); else raa_current_db->rlng_buffer->next=0; return raa_current_db->rlng_buffer->next; } static void load_shrt_buffer(raa_db_access *raa_current_db, unsigned point) { char *reponse, *p, *q; int n, i; unsigned val, next, previous; if(raa_current_db == NULL) return; sock_printf(raa_current_db, "readshrt&num=%u&max=%d\n", point, MAX_RDSHRT); /* reponse is: code=0&n=xx&val,next,.... n times ...\n */ reponse = read_sock(raa_current_db); if(reponse == NULL || strncmp(reponse, "code=0&n=", 9) != 0) { return; } n = atoi(reponse + 9); if (n == 0) return; p = strchr(reponse+9, '&'); if(p == NULL) return; q = p + 1; previous = point; for(i = 0; i < n; i++) { p = strtok(q, ","); q = NULL; sscanf(p, "%u", &val); p = strtok(NULL, ","); sscanf(p, "%u", &next); raa_current_db->readshrt_data.shrt_begin = (raa_current_db->readshrt_data.shrt_begin + 1) % S_BUF_SHRT; raa_current_db->readshrt_data.shrt_buffer[raa_current_db->readshrt_data.shrt_begin][0] = previous; raa_current_db->readshrt_data.shrt_buffer[raa_current_db->readshrt_data.shrt_begin][1] = val; raa_current_db->readshrt_data.shrt_buffer[raa_current_db->readshrt_data.shrt_begin][2] = next; previous = next; } if(raa_current_db->readshrt_data.shrt_begin > raa_current_db->readshrt_data.shrt_max - 1) { raa_current_db->readshrt_data.shrt_max = raa_current_db->readshrt_data.shrt_begin + 1; } return; } unsigned raa_readshrt(raa_db_access *raa_current_db, unsigned point, int *pval) { int i; if(raa_current_db == NULL) return 0; if(raa_current_db->readshrt_data.total == 0) raa_current_db->readshrt_data.total = (unsigned)raa_read_first_rec(raa_current_db, raa_shrt); if(point < 2 || point > raa_current_db->readshrt_data.total) return 0; for(i = 0; i < raa_current_db->readshrt_data.shrt_max; i++) { if(raa_current_db->readshrt_data.shrt_buffer[i][0] == point) { if(pval != NULL) *pval = raa_current_db->readshrt_data.shrt_buffer[i][1]; return raa_current_db->readshrt_data.shrt_buffer[i][2]; } } load_shrt_buffer(raa_current_db, point); return raa_readshrt(raa_current_db, point, pval); } static void load_shrt2_aux(raa_db_access *raa_current_db, unsigned point, raa_shortl2_kind kind) { static const char kind_name[][11] = {"sub_of_bib", "spc_of_loc", "bib_of_loc", "aut_of_bib", "bib_of_aut", "sub_of_acc", "key_of_sub", "acc_of_loc"}; char *p, *reponse; int i; if (raa_current_db == NULL) return; sock_printf(raa_current_db, "followshrt2&num=%u&kind=%s&rank=0&max=%d\n", point, kind_name[kind], raa_current_db->readshrt2_data[kind]->size); /* reponse is: code=0&num=xx&rank=xx&n=xx&val,.... n times ...\n */ reponse = read_sock(raa_current_db); if (reponse == NULL || strncmp(reponse, "code=0&", 7) != 0) { return; } raa_current_db->readshrt2_data[kind]->point = point; p = strstr(reponse, "num="); raa_current_db->readshrt2_data[kind]->next = atoi(p + 4); p = strstr(reponse, "n="); raa_current_db->readshrt2_data[kind]->length = atoi(p + 2); p = strchr(p, '&') + 1; for (i = 0; i < raa_current_db->readshrt2_data[kind]->length; i++) { sscanf(p, "%u", raa_current_db->readshrt2_data[kind]->vals+i); p = strchr(p, ',') + 1; } } unsigned raa_followshrt2(raa_db_access *raa_current_db, int *p_point, int *p_rank, raa_shortl2_kind kind) { int rank = *p_rank; unsigned retval; if (raa_current_db->readshrt2_data[kind]->point == *p_point && rank < raa_current_db->readshrt2_data[kind]->length) { retval = raa_current_db->readshrt2_data[kind]->vals[rank++]; if (rank >= raa_current_db->readshrt2_data[kind]->length) { *p_rank = 0; *p_point = raa_current_db->readshrt2_data[kind]->next; } else *p_rank = rank; return retval; } load_shrt2_aux(raa_current_db, *p_point, kind); return raa_followshrt2(raa_current_db, p_point, p_rank, kind); } char *raa_ghelp(raa_db_access *raa_current_db, char *fname, char *topic) /* returns all help topic in one string in private memory */ { char *reponse, *p, *fintext, *tmp; int nl, l, i; if(raa_current_db == NULL) return NULL; sock_printf(raa_current_db,"ghelp&file=%s&item=%s\n", fname, topic); reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; nl = 0; if(strncmp(reponse, "nl=", 3) == 0) nl = atoi(reponse+3); p = strchr(reponse, '&'); if(nl <= 0 || p == NULL) return NULL; fintext = raa_current_db->help; p++; for(i = 0; i < nl; i++) { l = strlen(p) + 1; /* +1 pour ajouter \n */ if( (fintext - raa_current_db->help) + l > raa_current_db->lhelp) { raa_current_db->lhelp += 1000; tmp = (char *)realloc(raa_current_db->help, raa_current_db->lhelp + 1); if(tmp == NULL) { if(raa_current_db->help != NULL) free(raa_current_db->help); raa_current_db->help = NULL; raa_current_db->lhelp = 0; return NULL; } fintext = tmp + (fintext - raa_current_db->help); raa_current_db->help = tmp; } memcpy(fintext, p, l -1); fintext += l; *(fintext - 1) = '\n'; if(i + 1 < nl) reponse = read_sock(raa_current_db); if(reponse == NULL) return NULL; p = reponse; } *fintext = 0; return raa_current_db->help; } struct raa_matchkey { int *ranks; char **names; int count; int current; int no_more; }; static void raa_free_matchkeys(raa_db_access *raa_current_db) { int i; struct raa_matchkey *data = (struct raa_matchkey *)(raa_current_db->matchkey_data); if(data == NULL) return; if(data->count > 0) { for(i = 0; i < data->count; i++) free(data->names[i]); free(data->names); free(data->ranks); } free(data); raa_current_db->matchkey_data = NULL; } static void next_block_matchkeys(raa_db_access *raa_current_db, int num, char *pattern) { const int blocksize = 2001; char *reponse, *p; int count, i; struct raa_matchkey *data; if(raa_current_db == NULL) return; raa_free_matchkeys(raa_current_db); sock_printf(raa_current_db, "nextmatchkey&num=%d", num ); p = protect_quotes(pattern); if(num == 2) sock_printf(raa_current_db, "&pattern=\"%s\"", p ); free(p); sock_printf(raa_current_db, "&count=%d\n", blocksize); reponse = read_sock(raa_current_db); if(reponse == NULL || strncmp(reponse, "code=0&count=", 13) != 0) return; sscanf(reponse + 13, "%d", &count); data = (struct raa_matchkey *)calloc(1, sizeof(struct raa_matchkey)); raa_current_db->matchkey_data = data; if(data == NULL || count == 0) return; data->ranks = (int *)malloc(count * sizeof(int)); data->names = (char **)malloc(count * sizeof(char *)); data->current = 0; data->no_more = (count < blocksize); data->count = count; if(data->ranks == NULL || data->names == NULL) data->count = 0; for(i = 0; i < data->count; i++) { reponse = read_sock(raa_current_db); sscanf(reponse + 4, "%d", &(data->ranks[i]) ); p = strchr(reponse, '&'); p = strchr(p, '=') + 1; data->names[i] = strdup(unprotect_quotes(p)); if(data->names[i] == NULL) { data->count = i; break; } } for(i = data->count; i < count; i++) { read_sock(raa_current_db); } return; } int raa_nextmatchkey(raa_db_access *raa_current_db, int num, char *pattern, char **matching) /* *matching returned in static memory */ { struct raa_matchkey *data; int no_more=0, count; if(raa_current_db == NULL) return 0; if(num == 2) { next_block_matchkeys(raa_current_db, 2, pattern); } data = (struct raa_matchkey *)(raa_current_db->matchkey_data); if(data == NULL) return 0; if(data->current < data->count) { if(matching != NULL) *matching = data->names[data->current]; return data->ranks[(data->current)++]; } count = data->count; if(count > 0) { no_more = data->no_more; } raa_free_matchkeys(raa_current_db); if(count == 0 || no_more) return 0; next_block_matchkeys(raa_current_db, num, NULL); return raa_nextmatchkey(raa_current_db, num, NULL, matching); } int atoi_u(const char *p) { unsigned value; sscanf(p, "%u", &value); return (int)value; } static char *protect_quotes(char *name) /* remplacer tous les " par \" name : une chaine inchangee retourne un pointeur vers la chaine rendue allouee par malloc */ { char *p, *q; int count; char *bis; count = 0; p = name - 1; while( (p=strchr(p+1, '"')) != NULL) count++; if(count == 0) return strdup(name); bis = (char *)malloc(strlen(name) + count + 1); p = name; q = bis; while(TRUE) { if(*p == '"') *(q++) = '\\'; *q = *p; if(*p == 0) break; q++; p++; } return bis; } static char *prepare_remote_file(raa_db_access *raa_current_db, char *oldrequete, char *debut, char *type, int *plrank, char **badfname) { char *p, *q, *reponse, *fin; char *line = raa_current_db->remote_file; int nl, l, code; FILE *in; Reponse *rep; *plrank = 0; *badfname = line; p = strchr(debut, '=') + 1; while(isspace(*p)) p++; if(*p == '"') { /* if filename is bracketed by " */ *(p++) = ' '; fin = strchr(p, '"'); if(fin == NULL) return NULL; *fin = ' '; } else { fin = p; do ++fin; while( *fin != 0 && *fin != ')' && !isspace(*fin) ); } l = fin - p; if(l >= sizeof(raa_current_db->remote_file)) l = sizeof(raa_current_db->remote_file) - 1; memcpy(line, p, l); line[l] = 0; if(fin - p >= sizeof(raa_current_db->remote_file)) return NULL; in = fopen(line, "r"); if(in == NULL) return NULL; nl = 0; while( fgets(line, sizeof(raa_current_db->remote_file), in) != NULL) nl++; rewind(in); sock_printf(raa_current_db, "crelistfromclientdata&type=%s&nl=%d\n", type, nl); if(nl > 0) { while( fgets(line, sizeof(raa_current_db->remote_file), in) != NULL) { l = strlen(line); if(line[l - 1] != '\n') strcpy(line + l, "\n"); sock_fputs(raa_current_db, line); } } fclose(in); reponse = read_sock(raa_current_db); if(reponse == NULL) { strcpy(line, "connection with server is down"); return NULL; } rep = initreponse(); parse(reponse, rep); q = val(rep,"code"); code = atoi(q); free(q); if(code != 0) { if(code == 3) strcpy(line, "too many lists, delete a few"); else sprintf(line, "code=%d", code); return NULL; } q = val(rep,"name"); l = strlen(q); reponse = (char *)malloc( (debut - oldrequete) + 1 + l + 1 + strlen(fin) + 1); p = reponse; memcpy(p, oldrequete, debut - oldrequete); p += debut - oldrequete; *(p++) = ' '; memcpy(p, q, l); p += l; *(p++) = ' '; free(q); strcpy(p, fin); free(oldrequete); q = val(rep,"lrank"); if(q != NULL) { *plrank = atoi(q); free(q); } clear_reponse(rep); return reponse; } static int *add_tmp_blist(raa_db_access *raa_current_db, int lrank, int *list) { if(list == NULL) { /* initialisation */ if(raa_current_db->tmp_prelist != NULL) free(raa_current_db->tmp_prelist); raa_current_db->tmp_total = 10; raa_current_db->tmp_current = 0; list = (int *)malloc(raa_current_db->tmp_total*sizeof(int)); raa_current_db->tmp_prelist = list; return list; } if(raa_current_db->tmp_current >= raa_current_db->tmp_total) { int *tmp; tmp = (int *)realloc(list, (raa_current_db->tmp_total + 10)*sizeof(int)); if(tmp == NULL) return list; raa_current_db->tmp_total += 10; list = tmp; } list[raa_current_db->tmp_current++] = lrank; raa_current_db->tmp_prelist = list; return list; } static char *maj_strstr(char *in, char *target) { char *p, *buffer; buffer = strdup(in); majuscules(buffer); p = strstr(buffer, target); if(p != NULL) p = in + (p - buffer); free(buffer); return p; } static char *raa_requete_remote_file(raa_db_access *raa_current_db, char *oldrequete, int **plist, char **pbadfname) /* rend NULL ou une requete dont les F= FA= FS= FK= ont ete changes en list-name et qui a ete creee par malloc */ { char *oldori, *p; int lrank, *list; oldori = strdup(oldrequete); if(maj_strstr(oldori, "F=") == NULL && maj_strstr(oldori, "FA=") == NULL && maj_strstr(oldori, "FK=") == NULL && maj_strstr(oldori, "FS=") == NULL) { *plist = NULL; return oldori; } list = add_tmp_blist(raa_current_db, 0, NULL); /* initialisation a vide */ while(oldori != NULL && (p = maj_strstr(oldori, "F=")) != NULL) { oldori = prepare_remote_file(raa_current_db, oldori, p, "SQ", &lrank, pbadfname); if(lrank != 0) list = add_tmp_blist(raa_current_db, lrank, list); } while(oldori != NULL && (p = maj_strstr(oldori, "FA=")) != NULL) { oldori = prepare_remote_file(raa_current_db, oldori, p, "AC", &lrank, pbadfname); if(lrank != 0) list = add_tmp_blist(raa_current_db, lrank, list); } while(oldori != NULL && (p = maj_strstr(oldori, "FS=")) != NULL) { oldori = prepare_remote_file(raa_current_db, oldori, p, "SP", &lrank, pbadfname); if(lrank != 0) list = add_tmp_blist(raa_current_db, lrank, list); } while(oldori != NULL && (p = maj_strstr(oldori, "FK=")) != NULL) { oldori = prepare_remote_file(raa_current_db, oldori, p, "KW", &lrank, pbadfname); if(lrank != 0) list = add_tmp_blist(raa_current_db, lrank, list); } list = add_tmp_blist(raa_current_db, 0, list); /* marquage fin de liste par zero */ if(oldori == NULL && list != NULL) { while(*list != 0) raa_releaselist(raa_current_db, *(list++) ); list = NULL; } *plist = list; return oldori; } int raa_savelist(raa_db_access *raa_current_db, int lrank, FILE *out, int use_acc, char *prefix) { char *reponse; int err; if(raa_current_db == NULL) return 1; sock_printf(raa_current_db, "savelist&lrank=%d&type=%c\n", lrank, (use_acc ? 'A' : 'N') ); reponse = read_sock(raa_current_db); if(reponse == NULL) return 1; err = strcmp(reponse, "code=0"); if(err != 0) { return 1; } while(TRUE) { reponse = read_sock(raa_current_db); if(reponse == NULL) return 1; if(strcmp(reponse, "savelist END.") == 0) break; if(prefix != NULL) fputs(prefix, out); fprintf(out, "%s\n", reponse); } return 0; } int raa_modifylist(raa_db_access *raa_current_db, int lrank, char *type, char *operation, int *pnewlist, int (*check_interrupt)(void), int *p_processed ) { Reponse *rep; char *p, *reponse; int code; if(raa_current_db == NULL) return 3; sock_printf(raa_current_db, "modifylist&lrank=%d&type=%s&operation=\"%s\"\n", lrank, type, operation ); sock_flush(raa_current_db); /* tres important */ if(check_interrupt == NULL) { reponse = read_sock(raa_current_db); if(reponse == NULL) return 3; } else { while(TRUE) { reponse = read_sock_timeout(raa_current_db, 500 /* msec */); if(raa_current_db == NULL) return 3; if(reponse != NULL) break; if( check_interrupt() ) { sock_fputs(raa_current_db, "\033" /* esc */ ); sock_flush(raa_current_db); } } } rep = initreponse(); parse(reponse, rep); p = val(rep,"code"); code = atoi(p); free(p); if(code != 0) return code; p = val(rep,"lrank"); *pnewlist = atoi(p); free(p); p = val(rep,"processed"); if(p != NULL && p_processed != NULL) *p_processed = atoi(p); if(p != NULL) free(p); clear_reponse(rep); return 0; } int raa_knowndbs(raa_db_access *raa_current_db, char ***pnames, char ***pdescriptions) { int nl; char **names = NULL, **descriptions = NULL; char *reponse, *p, *q, *r; int l, i; if(raa_current_db == NULL) return 0; sock_printf(raa_current_db, "knowndbs\n" ); reponse = read_sock(raa_current_db); if(reponse == NULL || strncmp(reponse, "nl=", 3) != 0) { return 0; } nl = atoi(reponse + 3); if(nl == 0) return 0; names = (char **) malloc(nl * sizeof(char *)); descriptions = (char **) malloc(nl * sizeof(char *)); for(i = 0; i < nl; i++) { reponse = read_sock(raa_current_db); if(reponse == NULL) return 0; p = strchr(reponse, '|'); if(p != NULL) { *(p++) = 0; q = strchr(p, '|'); if(q != NULL) *(q++) = 0; } l = strlen(reponse); names[i] = (char *)malloc(l+1); strcpy(names[i], reponse); compact(names[i]); if(p != NULL && q != NULL) { while( (r=strchr(p, '\t')) != NULL) *r = ' '; majuscules(p); compact(p); l = strlen(q); descriptions[i] = (char *)malloc(l+20); descriptions[i][0] = 0; if(strcmp(p, "OFF") == 0) strcpy(descriptions[i], "(offline) "); strcat(descriptions[i], q); } else descriptions[i] = NULL; } *pnames = names; *pdescriptions = descriptions; return nl; } char *raa_short_descr(raa_db_access *raa_current_db, int seqnum, char *text, int maxlen, raa_long pinf, int div, char *name) /* to get a description of a sequence or of a subsequence seqnum the sequence number text the string to be loaded with description maxlen the max # of chars allowed in text (\0 is put but not counted in maxlen) return value a pointer to text */ { int l, deb; char *p; text[maxlen]=0; strcpy(text, name); l=strlen(text); if(strchr(name, '.') != NULL) { /* subsequence */ if( (p = raa_read_annots(raa_current_db, pinf, div)) == NULL) return text; p[20]=0; strcat(text,p+4); l=strlen(text); while(text[l-1]==' ') l--; text[l]=0; if( ( p = strchr(p + 21, '/') ) != NULL) { strncat(text, p, maxlen - l); l = strlen(text); if(l > 75) return text; } do { p = raa_next_annots(raa_current_db, NULL); if( strcmptrail(p,20,NULL,0) && strncmp(p,"FT ",10) ) return text; } while(p[21]!='/'); do { strncat(text,p+20,maxlen-l); l=strlen(text); if(l>75) return text; p = raa_next_annots(raa_current_db, NULL); } while ( !strcmptrail(p,20,NULL,0) || !strncmp(p,"FT ",10) ); } else { /* parent sequence */ if( raa_read_annots(raa_current_db, pinf, div) == NULL) return text; p = raa_next_annots(raa_current_db, NULL); if(raa_current_db->nbrf) { deb=17; } else { deb=13; if(raa_current_db->embl || raa_current_db->swissprot) { while (strncmp(p,"DE",2)) { p = raa_next_annots(raa_current_db, NULL); } deb=6; } } do { strncat(text,p+deb-2,maxlen-l); l=strlen(text); if(l>=77) return text; p = raa_next_annots(raa_current_db, NULL); } while( !strncmp(p," ",2) || !strncmp(p,"DE",2) ); } return text; } #define END_COORDINATE_TEST(line) strncmp(line, "extractseqs END.", 16) static int *next_1_coordinate_set(raa_db_access *raa_current_db) { char *p, *line, *q; int start, last, seqnum, elt, i, count; int *table = NULL; line = read_sock(raa_current_db); if(END_COORDINATE_TEST(line) == 0) return NULL; count = 0; p = line; while(TRUE) { p = strchr(p+1, '|'); if( p == NULL) break; count++; } table = (int *)malloc( (3 * count + 1) * sizeof(int)); if(table == NULL) { do line = read_sock(raa_current_db); while(END_COORDINATE_TEST(line) != 0) ; return NULL; } table[0] = count; elt = 1; for(i = 0; i < count; i++) { p = strchr(line, '|'); if(p == NULL) break; q = strchr(line, '='); if(q == NULL || q > p) break; sscanf(q+1, "%d", &seqnum); q = strchr(q+1, '='); if(q == NULL || q > p) break; sscanf(q+1, "%d", &start); q = strchr(q+1, '='); if(q == NULL || q > p) break; sscanf(q+1, "%d", &last); table[elt++] = seqnum; table[elt++] = start; table[elt++] = last; line = p + 1; } return table; } struct coord_series_struct { int count; int **table; int next; } ; void *raa_prep_coordinates(raa_db_access *raa_current_db, int lrank, int seqnum, char *operation, /* "simple","fragment","feature","region" */ char *feature_name, char *bounds, char *min_bounds) /* only one of lrank and seqnum is != 0 to work on a sequence list or on an individual sequence feature_name: used for operations feature and region, NULL otherwise bounds: used for operations fragment and region, NULL otherwise syntax by examples "45,155" "-100,100" "-10,e+100" "E-10,e+100" min_bounds: NULL for operations other than fragment and region can be NULL for fragment and region and means min_bounds same as bounds if not NULL, same syntax as bounds pcount: upon return, set to number of coordinate series return value: NULL if error, or pointer to opaque data */ { char message[200]; char *line; int *v, maxi, **table, rank; struct coord_series_struct *retval; sprintf(message, "extractseqs&%s=%d&format=coordinates&operation=%s", seqnum == 0 ? "lrank" : "seqnum", seqnum == 0 ? lrank : seqnum, operation); sock_fputs(raa_current_db, message); if(strcmp(operation, "feature") == 0 || strcmp(operation, "region") == 0) { sprintf(message, "&feature=%s", feature_name); sock_fputs(raa_current_db, message); } if(strcmp(operation, "fragment") == 0 || strcmp(operation, "region") == 0) { sprintf(message, "&bounds=%s", bounds); sock_fputs(raa_current_db, message); } if(min_bounds != NULL) { sprintf(message, "&minbounds=%s", min_bounds); sock_fputs(raa_current_db, message); } sock_fputs(raa_current_db, "\n"); sock_flush(raa_current_db); line = read_sock(raa_current_db); if(strcmp(line, "code=0") != 0) { return NULL; } maxi = 100; rank = 0; table = (int **)malloc(maxi*sizeof(int *)); if(table == NULL) { do line = read_sock(raa_current_db); while(END_COORDINATE_TEST(line) != 0) ; return NULL; } while( (v = next_1_coordinate_set(raa_current_db)) != NULL) { if(rank >= maxi) { int **vv; vv = (int **)realloc(table, 2*maxi*sizeof(int *)); if(vv == NULL) { do line = read_sock(raa_current_db); while(END_COORDINATE_TEST(line) != 0) ; break; } maxi = 2*maxi; table = vv; } table[rank++] = v; } table = realloc(table, rank*sizeof(int *)); retval = (struct coord_series_struct *)malloc(sizeof(struct coord_series_struct)); if(retval == NULL) return NULL; retval->count = rank; retval->table = table; retval->next = 0; return retval; } int *raa_1_coordinate_set(void *v) /* to be called repetitively as table = raa_1_coordinate_set(v); until returns NULL with the opaque pointer returned by the raa_prep_coordinates call returns int array table in private memory containing 1 + 3*table[0] elements count = table[0] ; j = 0; for(i=0; i < count; i++) { table[j+1] is the acnuc number of the sequence table[j+2] is the start position in this sequence table[j+3] is the end position in this sequence j += 3; } start position > end position <==> fragment is on the complementary strand of the acnuc seq returns NULL when all coordinate series have been processed */ { int *retval, i; struct coord_series_struct *s = (struct coord_series_struct *)v; if(s->next >= s->count) { for(i=0; i < s->count; i++) free(s->table[i]); free(s->table); free(s); return NULL; } retval = s->table[(s->next)++]; return retval; } char *raa_translate_cds(raa_db_access *raa_current_db, int seqnum) /* traduction d'un cds avec codon initiateur traite et * internes ==> X rendue dans memoire allouee ici qu'il ne faut pas modifier retour NULL si pb lecture de la seq */ { int debut_codon, longueur, pos, code, phase; char codon[4], *p; raa_readsub(raa_current_db, seqnum,&longueur,NULL,NULL,NULL,NULL,&phase,&code); debut_codon = phase + 1; longueur = (longueur - debut_codon + 1)/3; raa_current_db->translate_buffer = (char*)realloc(raa_current_db->translate_buffer, longueur + 1); if(raa_current_db->translate_buffer == NULL) { return NULL; } raa_current_db->translate_buffer[0] = raa_translate_init_codon(raa_current_db, seqnum); debut_codon += 3; for(pos = 1; pos < longueur; pos++) { if( raa_gfrag(raa_current_db, seqnum, debut_codon, 3, codon) == 0) return NULL; raa_current_db->translate_buffer[pos] = codaa(codon,code); debut_codon += 3; } raa_current_db->translate_buffer[longueur] = 0; while( (p = strchr(raa_current_db->translate_buffer, '*') ) != NULL && p - raa_current_db->translate_buffer < longueur - 1 ) *p = 'X'; return raa_current_db->translate_buffer; } char raa_translate_init_codon(raa_db_access *raa_current_db, int numseq) { char codon[4]; int point, special_init = TRUE, val, gc, phase, rank = 0; if (raa_current_db->num_5_partial == 0) raa_current_db->num_5_partial = raa_iknum(raa_current_db, "5'-PARTIAL", raa_key); raa_readsub(raa_current_db, numseq, NULL, NULL,NULL, &point, NULL, &phase, &gc); if(phase != 0) special_init = FALSE; else { /* la seq est-elle 5'-PARTIAL ? */ while (point != 0) { val = raa_followshrt2(raa_current_db, &point, &rank, raa_key_of_sub); if (val == raa_current_db->num_5_partial) { special_init = FALSE; break; } } } raa_gfrag(raa_current_db, numseq, phase + 1, 3, codon); if(special_init) /* traduction speciale du codon initiateur */ return init_codon_to_aa(codon, gc); else return codaa(codon, gc); } static void ajout_synonyme(raa_node *secondaire, raa_node *principal) { raa_node *next; if(principal->syno == NULL) { principal->syno = secondaire; secondaire->syno = principal; } else { next = principal->syno; principal->syno = secondaire; secondaire->syno = next; } } static void redresse_branches(raa_node *pere) /* Recursively reverse the order of descendants because it has been reversed */ { struct raa_pair *point, *next1, *next2, *last; point = pere->list_desc; if (!point) return; next1 = point->next; if (next1) point->next = NULL; while (TRUE) { last = point; redresse_branches(point->value); if (!next1) break; next2 = next1->next; next1->next = point; point = next1; next1 = next2; } pere->list_desc = last; } static void ajout_branche(raa_node *pere, raa_node *fils) /* adds a pere->fils branch. The last added branch is the first child of pere. */ { struct raa_pair *nouveau; nouveau = (struct raa_pair *)calloc(1,sizeof(struct raa_pair)); nouveau->value = fils; if( pere->list_desc == NULL) { pere->list_desc = nouveau; } else { nouveau->next = pere->list_desc; pere->list_desc = nouveau; } } static void raa_decode_desc_arbre(char *reponse, raa_node **tab_noeud) /* reponse contient rank&pere&count&"...name..."&"...libel..." synonyme est identifie par pere < 0 et -pere = son principal */ { int num, pere, count, l; char *p, *q, *name, *libel; num = atoi(reponse); p = strchr(reponse, '&'); pere = atoi(p + 1); p = strchr(p+1, '&'); count = atoi(p + 1); /* ne pas brancher un noeud deja branche ailleurs auparavant */ if(tab_noeud[num] != NULL ) return; tab_noeud[num] = (raa_node *)calloc(1, sizeof(raa_node)); tab_noeud[num]->rank = num; if(pere < 0) { /* un synonyme */ ajout_synonyme(tab_noeud[num], tab_noeud[-pere]); } else { tab_noeud[num]->count = count; tab_noeud[num]->parent = tab_noeud[pere]; if(num != 2) ajout_branche(tab_noeud[pere], tab_noeud[num]); } p = strchr(p+1, '&') + 1; q = p; do { q++; if(*q == 0) break; } while(*q != '"' || *(q-1) == '\\'); l = q-p+1; name = (char *)malloc(l+1); strncpy(name, p, l); name[l] = 0; unprotect_quotes(name); tab_noeud[num]->name = name; q++; if(*q == '&') { p = q+1; q = p; do { q++; if(*q == 0) break; } while(*q != '"' || *(q-1) == '\\'); l = q-p+1; libel = (char *)malloc(l+1); strncpy(libel, p, l); libel[l] = 0; unprotect_quotes(libel); tab_noeud[num]->libel = libel; p = (char *)malloc(l+1); strcpy(p, libel); majuscules(p); tab_noeud[num]->libel_upcase = p; if(strncmp(p, "ID:", 3) == 0 || (p = strstr(p, "|ID:")) != NULL) { p += 2; if(*p != ':') p++; sscanf(p + 1, "%d", &(tab_noeud[num]->tid) ); } } } static void raa_calc_taxo_count(raa_node *racine) { struct raa_pair *paire; int count = 0; paire = racine->list_desc; while(paire != NULL) { raa_calc_taxo_count(paire->value); count += paire->value->count; paire = paire->next; } racine->count += count; } int raa_loadtaxonomy(raa_db_access *raa_current_db, char *rootname, int (*progress_function)(int, void *), void *progress_arg, int (*need_interrupt_f)(void *), void *interrupt_arg) /* charge la taxo complete dans raa_current_db->sp_tree et rend 0 ssi OK */ { int totspec, i, maxtid; raa_node **tab_noeud; struct raa_pair *pair, *pair2; char *reponse; int count, pourcent, prev_pourcent = 0; void *opaque; int interrupted; if(raa_current_db == NULL) return 1; if(raa_current_db->sp_tree != NULL) return 0; interrupted = FALSE; sock_fputs(raa_current_db, "zlibloadtaxonomy\n"); sock_flush(raa_current_db); /* reply: code=0&total=xx rank&pere&count&"...name..."&"...libel..." loadtaxonomy END. */ opaque = prepare_sock_gz_r( raa_current_db->raa_sockfdr ); reponse = z_read_sock(opaque); if(reponse == NULL || strncmp(reponse, "code=0&total=", 13) != 0) { return 1; } totspec = atoi(reponse + 13); tab_noeud = (raa_node **)calloc(totspec + 1, sizeof(raa_node *)); count = 0; while(TRUE) { reponse = z_read_sock(opaque); if(strcmp(reponse, "loadtaxonomy END.") == 0) { if(interrupted && (tab_noeud != NULL) ) { for(i = 2; i <= totspec; i++) { if(tab_noeud[i] == NULL) continue; if(tab_noeud[i]->name != NULL) free(tab_noeud[i]->name); if(tab_noeud[i]->libel != NULL) free(tab_noeud[i]->libel); if(tab_noeud[i]->libel_upcase != NULL) free(tab_noeud[i]->libel_upcase); pair = tab_noeud[i]->list_desc; while(pair != NULL) { pair2 = pair->next; free(pair); pair = pair2; } free(tab_noeud[i]); } free(tab_noeud); tab_noeud = NULL; /* just to consume ESC that may have arrived after loadtaxonomy END. */ sock_fputs(raa_current_db, "null_command\n"); read_sock(raa_current_db); } break; } if(tab_noeud != NULL) raa_decode_desc_arbre(reponse, tab_noeud); pourcent = ((++count) * 100) / totspec; if(pourcent > prev_pourcent) { prev_pourcent = pourcent; if( progress_function != NULL && progress_function(pourcent, progress_arg) ) { if( need_interrupt_f != NULL && (! interrupted) && need_interrupt_f(interrupt_arg) ) { sock_fputs(raa_current_db, "\033" /* esc */); sock_flush(raa_current_db); interrupted = TRUE; } } } } close_sock_gz_r(opaque); if(tab_noeud != NULL) { redresse_branches(tab_noeud[2]); raa_calc_taxo_count(tab_noeud[2]); free(tab_noeud[2]->name); tab_noeud[2]->name = strdup(rootname); maxtid = 0; for(i = 2; i <= totspec; i++) if(tab_noeud[i] != NULL && tab_noeud[i]->tid > maxtid) maxtid = tab_noeud[i]->tid; raa_current_db->tid_to_rank = (int *)calloc(maxtid + 1, sizeof(int)); if(raa_current_db->tid_to_rank != NULL) { raa_current_db->max_tid = maxtid; for(i = 2; i <= totspec; i++) { if(tab_noeud[i] != NULL && tab_noeud[i]->tid != 0) raa_current_db->tid_to_rank[tab_noeud[i]->tid] = tab_noeud[i]->rank; } } raa_current_db->sp_tree = tab_noeud; } return (tab_noeud == NULL ? 1 : 0); } char *raa_get_taxon_info(raa_db_access *raa_current_db, char *name, int rank, int tid, int *p_rank, int *p_tid, int *p_parent, struct raa_pair **p_desc_list) /* from a taxon identified by its name or, if name is NULL, by its rank or, if rank is 0, by its taxon ID (tid) computes : - if p_rank != NULL, the taxon rank in *p_rank - if p_tid != NULL, the taxon ID in *p_tid - if p_parent != NULL, the taxon's parent rank in *p_parent (2 indicates that taxon is at top level) - if p_desc_list != NULL, the start of the linked chain of taxon's descending taxa in *p_desc_list returns the taxon name, or NULL if any error */ { int totspec; if(raa_current_db == NULL) return NULL; if(raa_current_db->sp_tree == NULL) raa_loadtaxonomy(raa_current_db, "root", NULL, NULL, NULL, NULL); if(raa_current_db->sp_tree == NULL) return NULL; totspec = raa_read_first_rec(raa_current_db, raa_spec); if(name != NULL) { name = strdup(name); if(name == NULL) return NULL; trim_key(name); majuscules(name); for(rank = 3; rank <= totspec; rank++) { if(raa_current_db->sp_tree[rank] != NULL && strcmp(name, raa_current_db->sp_tree[rank]->name) == 0) break; } free(name); } if(name == NULL && rank == 0 && tid >= 1 && tid <= raa_current_db->max_tid) rank = raa_current_db->tid_to_rank[tid]; if(rank > totspec || rank < 2 || raa_current_db->sp_tree[rank] == NULL) return NULL; if(rank != 2) { while(raa_current_db->sp_tree[rank]->parent == NULL) { rank = raa_current_db->sp_tree[rank]->syno->rank; } } if(p_rank != NULL) *p_rank = rank; if(p_tid != NULL) *p_tid = raa_current_db->sp_tree[rank]->tid; if(p_parent != NULL) *p_parent = ( raa_current_db->sp_tree[rank]->parent != NULL ? raa_current_db->sp_tree[rank]->parent->rank : 0); if(p_desc_list != NULL) *p_desc_list = raa_current_db->sp_tree[rank]->list_desc; return raa_current_db->sp_tree[rank]->name; } static char *raa_getattributes_both(raa_db_access *raa_current_db, const char *id, int rank, int *prank, int *plength, int *pframe, int *pgc, char **pacc, char **pdesc, char **pspecies, char **pseq) /* for a sequence identified by name or acc. no. (id != NULL) or by rank returns rank, name, accession, length, frame, acnuc genetic code ID, one-line description, species, and full sequence. return value: NULL if not found or name (in private memory) pacc, pdesc, pspecies and pseq point to private memory upon return prank, plength, pframe, pgc, pacc, pdesc, pspecies, pseq can be NULL is no such information is needed */ { Reponse *rep; char *p, *reponse; int err; if(raa_current_db == NULL) return NULL; if(id != NULL) sock_printf(raa_current_db, "getattributes&id=%s&seq=%c\n", id, pseq == NULL ? 'F' : 'T'); else sock_printf(raa_current_db, "getattributes&rank=%d&seq=%c\n", rank, pseq == NULL ? 'F' : 'T'); reponse = read_sock(raa_current_db); if(reponse == NULL) { return NULL; } rep=initreponse(); parse(reponse,rep); p=val(rep,"code"); err = atoi(p); free(p); if(err == 0) { if(prank != NULL) { p=val(rep,"rank"); *prank = atoi(p); free(p); } if(plength != NULL) { p=val(rep,"length"); *plength = atoi(p); free(p); } if(pframe != NULL) { p=val(rep,"fr"); if(p != NULL) { *pframe = atoi(p); free(p); } else *pframe = 0; } if(pgc != NULL) { p=val(rep,"gc"); if(p != NULL) { *pgc = atoi(p); free(p); } else *pgc = 0; } p = val(rep, "name"); strcpy(raa_current_db->mnemo, p); free(p); if(pacc != NULL) { p = val(rep, "acc"); strcpy(raa_current_db->access, p); free(p); *pacc = raa_current_db->access; } if(pspecies != NULL) { p = val(rep, "spec"); strcpy(raa_current_db->species, p); free(p); *pspecies = raa_current_db->species; p = raa_current_db->species; while(*(++p) != 0) *p = tolower(*p); } if(pdesc != NULL) { p = val(rep, "descr"); strcpy(raa_current_db->descript, p); free(p); *pdesc = raa_current_db->descript; } if(pseq != NULL) { *pseq = read_sock(raa_current_db); if(*pseq != NULL) { *pseq += 4; /* seq=xxxx */ } } err = 0; } clear_reponse(rep); return (err ? NULL : raa_current_db->mnemo); } char *raa_getattributes(raa_db_access *raa_current_db, const char *id, int *prank, int *plength, int *pframe, int *pgc, char **pacc, char **pdesc, char **pspecies, char **pseq) { return raa_getattributes_both(raa_current_db, id, 0, prank, plength, pframe, pgc, pacc, pdesc, pspecies, pseq); } char *raa_seqrank_attributes(raa_db_access *raa_current_db, int rank, int *plength, int *pframe, int *pgc, char **pacc, char **pdesc, char **pspecies, char **pseq) { return raa_getattributes_both(raa_current_db, NULL, rank, NULL, plength, pframe, pgc, pacc, pdesc, pspecies, pseq); } seaview/csrc/raa_acnuc.h000644 000765 000024 00000025070 12614075644 016060 0ustar00mgouystaff000000 000000 #ifndef RAA_ACNUC_H #define RAA_ACNUC_H #include #include #include #include #if defined(WIN32) #define SOCKBUFS 8192 #endif #ifdef __alpha typedef long raa_long; #define RAA_LONG_FORMAT "%lu" #else typedef long long raa_long; #define RAA_LONG_FORMAT "%llu" #endif #ifndef TRUE #define FALSE 0 #define TRUE (!FALSE) #endif #ifndef ERREUR #define ERREUR 1 #endif struct rlng { /* LONGL series of linked records containing lists of SUBSEQ ranks */ int next; /* to LONGL for next element of the long list, or 0 when list is finished */ int sub[1]; /* array (length given by global SUBINLNG) of ranks of SUBSEQ records or of 0s */ }; #define RAA_GFRAG_BSIZE 10000 struct gfrag_aux { char buffer[RAA_GFRAG_BSIZE + 1]; int lbuf, nseq_buf, first_buf, l_nseq_buf; }; struct readsub_aux { char *name; int lname, previous, length, type, toext, lkey, locus, frame, gencode, div; raa_long addr; }; #define ANNOTCOUNT 40 struct annot_aux { char *annotline[ANNOTCOUNT + 1]; int annotcurrent, annotcount, annotdiv; raa_long annotaddr, annotaddrfirst, annotaddrlast; char annotsbuffer[ 300 ]; }; struct readsp_kw_aux { char name[150], libel[200]; int lsub, desc, syno, host, previous; }; #define BLOCK_ELTS_IN_LIST 500 struct nextelt_aux { int current_rank, previous, total; int tabnum[BLOCK_ELTS_IN_LIST]; char *tabname[BLOCK_ELTS_IN_LIST]; int tablength[BLOCK_ELTS_IN_LIST]; raa_long taboffset[BLOCK_ELTS_IN_LIST]; int tabdiv[BLOCK_ELTS_IN_LIST]; }; #define S_BUF_SHRT 5000 /* number of memorized SHORTL records */ struct readshrt_aux { unsigned shrt_buffer[S_BUF_SHRT][3]; /* [0]=SHORTL_rank [1]=val [2]=next */ int shrt_max, shrt_begin, total; }; typedef struct shrt2_list { int length; int size; unsigned point; unsigned next; unsigned vals[1]; } shrt2_list; struct readsmj_aux { int lastrec; char **names, **libels; unsigned *plongs; }; typedef struct raa_node { char *name; char *libel; char *libel_upcase; int rank; int tid; int count; struct raa_node *parent; struct raa_pair *list_desc; struct raa_node *syno; } raa_node; struct raa_pair { raa_node *value; struct raa_pair *next; }; #define WIDTH_MAX 150 typedef enum { raa_sub_of_bib = 0, raa_spec_of_loc, raa_bib_of_loc, raa_aut_of_bib, raa_bib_of_aut, raa_sub_of_acc, raa_key_of_sub, raa_acc_of_loc } raa_shortl2_kind; typedef struct _raa_db_access { char *dbname; FILE *raa_sockfdr, *raa_sockfdw; int genbank, embl, swissprot, nbrf; int nseq, longa, maxa; int L_MNEMO, WIDTH_SP, WIDTH_KW, WIDTH_SMJ, WIDTH_AUT, WIDTH_BIB, ACC_LENGTH, SUBINLNG, lrtxt, VALINSHRT2; raa_node **sp_tree; /* NULL or the full taxonomy tree */ int max_tid; /* largest correct taxon ID value */ int *tid_to_rank; /* NULL or tid-to-rank table */ struct rlng *rlng_buffer; struct gfrag_aux gfrag_data; struct readsub_aux readsub_data; int first_recs[20]; struct annot_aux annot_data; struct readsp_kw_aux readspec_data, readkey_data; struct nextelt_aux nextelt_data; struct readshrt_aux readshrt_data; struct shrt2_list *readshrt2_data[raa_acc_of_loc+1]; struct readsmj_aux readsmj_data; void *matchkey_data; /* mostly for raa_query/raa_query_win usage */ int tot_key_annots; char **key_annots, **key_annots_min; unsigned char *want_key_annots; #ifdef WIN32 char sock_input[SOCKBUFS]; /* WIN32 socket input buffer */ char *sock_input_pos, *sock_input_end; char sock_output[SOCKBUFS]; /* WIN32 socket output buffer */ unsigned sock_output_lbuf; #endif char buffer[5000]; char remote_file[300]; char *full_line; int max_full_line; int was_here; char *namestr; char residuecount[30]; char *help; int lhelp; int tmp_total; int tmp_current; int *tmp_prelist; char *translate_buffer; int num_5_partial; char mnemo[WIDTH_MAX]; char species[WIDTH_MAX]; char access[WIDTH_MAX]; char descript[WIDTH_MAX]; char date[12]; } raa_db_access; typedef enum { raa_sub = 0, raa_loc, raa_key, raa_spec, raa_shrt, raa_lng, raa_ext, raa_smj, raa_aut, raa_bib, raa_txt, raa_acc } raa_file; typedef void (*raa_char_void_function)(raa_db_access *, char *); /* global variables */ extern raa_char_void_function raa_error_mess_proc;/*this function sd call raa_acnucclose*/ extern int raa_acnucopen (const char *clientid, raa_db_access **psock) ; extern int raa_decode_address(char *url, char **p_ip_name, int *socket, char **p_remote_db); extern int raa_acnucopen_alt (const char *serveurName, int port, const char *db_name, const char *clientid, raa_db_access **psock); extern int raa_open_socket(const char *serveurName, int port, const char *clientid, raa_db_access **psock); extern int raa_opendb(raa_db_access *raa_current_db, const char *db_name); int raa_opendb_pw(raa_db_access *raa_current_db, const char *db_name, void *ptr, char *(*getpasswordf)(void *) ); extern int raa_gfrag(raa_db_access *raa_current_db, int nsub, int first, int lfrag, char *dseq) ; extern void raa_acnucclose(raa_db_access *raa_current_db) ; extern int raa_prep_acnuc_query(raa_db_access *raa_current_db) ; extern int raa_proc_query(raa_db_access *raa_current_db, char *query, char **message, char *nomliste, int *numlist, int *count, int *locus, int *type) ; int raa_nexteltinlist(raa_db_access *raa_current_db, int first, int lrank, char **pname, int *plength) ; int raa_nexteltinlist_annots(raa_db_access *raa_current_db, int first, int lrank, char **pname, int *plength, raa_long *paddr, int *pdiv); raa_long scan_raa_long(char *txt); int raa_seq_to_annots(raa_db_access *raa_current_db, int numseq, raa_long *faddr, int *div); char *print_raa_long(raa_long val, char *buffer); char *raa_read_annots(raa_db_access *raa_current_db, raa_long faddr, int div); char *raa_next_annots(raa_db_access *raa_current_db, raa_long *faddr); char *raa_translate_cds(raa_db_access *raa_current_db, int seqnum); char raa_translate_init_codon(raa_db_access *raa_current_db, int numseq); int raa_iknum(raa_db_access *raa_current_db, char *name, raa_file cas); int raa_isenum(raa_db_access *raa_current_db, char *name); int raa_bcount(raa_db_access *raa_current_db, int lrank); void raa_bit1(raa_db_access *raa_current_db, int lrank, int num); void raa_bit0(raa_db_access *raa_current_db, int lrank, int num); int raa_btest(raa_db_access *raa_current_db, int lrank, int num); void raa_copylist(raa_db_access *raa_current_db, int from, int to); void raa_zerolist(raa_db_access *raa_current_db, int rank); void raa_setliststate(raa_db_access *raa_current_db, int lrank, int locus, int type); char *raa_getliststate(raa_db_access *raa_current_db, int lrank, int *locus, int *type, int *count); char *raa_residuecount(raa_db_access *raa_current_db, int lrank); int raa_getemptylist(raa_db_access *raa_current_db, char *name); int raa_setlistname(raa_db_access *raa_current_db, int lrank, char *name); int raa_getlistrank(raa_db_access *raa_current_db, char *name); int raa_releaselist(raa_db_access *raa_current_db, int lrank); int raa_countfilles(raa_db_access *raa_current_db, int lrank); int raa_alllistranks(raa_db_access *raa_current_db, int **pranks); int raa_fcode(raa_db_access *raa_current_db, raa_file cas, char *name); int raa_read_first_rec(raa_db_access *raa_current_db, raa_file cas); char *raa_readsub(raa_db_access *raa_current_db, int num, int *plength, int *ptype, int *pext, int *plkey, int *plocus, int *pframe, int *pgencode); char *raa_readsub_pannots(raa_db_access *raa_current_db, int num, int *plength, int *ptype, int *pext, int *plkey, int *plocus, int *pframe, int *pgencode, raa_long *paddr, int *pdiv); char *raa_readloc(raa_db_access *raa_current_db, int num, int *sub, int *pnuc, int *spec, int *host, int *plref, int *molec, int *placc, int *org); char *raa_readspec(raa_db_access *raa_current_db, int num, char **plibel, int *plsub, int *desc, int *syno, int *plhost); char *raa_readkey(raa_db_access *raa_current_db, int num, char **plibel, int *plsub, int *desc, int *syno); char *raa_readsmj(raa_db_access *raa_current_db, int num, char **plibel, int *plong); char *raa_readacc(raa_db_access *raa_current_db, int num, int *plsub); int raa_readext(raa_db_access *raa_current_db, int num, int *mere, int *deb, int *fin); int raa_readlng(raa_db_access *raa_current_db, int num); unsigned raa_readshrt(raa_db_access *raa_current_db, unsigned point, int *val); unsigned raa_followshrt2(raa_db_access *raa_current_db, int *p_point, int *p_rank, raa_shortl2_kind kind); char *raa_ghelp(raa_db_access *raa_current_db, char *fname, char *topic); int raa_nextmatchkey(raa_db_access *raa_current_db, int num, char *pattern, char **matching); int raa_savelist(raa_db_access *raa_current_db, int lrank, FILE *out, int use_acc, char *prefix); int raa_modifylist(raa_db_access *raa_current_db, int lrank, char *type /* "length" or "date" */, char *operation /* ">2000" */, int *pnewlrank, int (*check_interrupt)(void) , int *p_processed); int raa_knowndbs(raa_db_access *raa_current_db, char ***pnames, char ***pdescriptions); char *raa_short_descr(raa_db_access *raa_current_db, int seqnum, char *text, int maxlen, raa_long pinf, int div, char *name); void *raa_prep_extract(raa_db_access *raa_current_db, char *format, FILE *outstream, char *choix, char *feature_name, char *bornes, char *min_bornes, char **message, int lrank); int raa_extract_1_seq(void *opaque); int raa_extract_interrupt(raa_db_access *raa_current_db, void *opaque); void *raa_prep_coordinates(raa_db_access *raa_current_db, int lrank, int seqnum, char *operation, /* "simple","fragment","feature","region" */ char *feature_name, char *bounds, char *min_bounds); int *raa_1_coordinate_set(void *); int raa_loadtaxonomy(raa_db_access *raa_current_db, char *rootname, int (*progress_function)(int, void *), void *progress_arg, int (*need_interrupt_f)(void *), void *interrupt_arg); char *raa_get_taxon_info(raa_db_access *raa_current_db, char *name, int rank, int tid, int *p_rank, int *p_tid, int *p_parent, struct raa_pair **p_desc_list); char *raa_getattributes(raa_db_access *raa_current_db, const char *id, int *prank, int *plength, int *pframe, int *pgc, char **pacc, char **pdesc, char **pspecies, char **pseq); char *raa_seqrank_attributes(raa_db_access *raa_current_db, int rank, int *plength, int *pframe, int *pgc, char **pacc, char **pdesc, char **pspecies, char **pseq); int sock_fputs(raa_db_access *raa_current_db, const char *line); int sock_flush(raa_db_access *raa_current_db); char *read_sock(raa_db_access *raa_current_db); int trim_key(char *name); /* remove trailing spaces */ void majuscules(char *name); int atoi_u(const char *p); void compact(char *chaine); int strcmptrail(char *s1, int l1, char *s2, int l2); #endif /* RAA_ACNUC_H */ seaview/csrc/seq.c000644 000765 000024 00000337164 12410062203 014716 0ustar00mgouystaff000000 000000 #include "phylip.h" #include "seq.h" /* version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe. Copyright (c) 1993-2014, Joseph Felsenstein All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ long nonodes, endsite, outgrno, nextree, which; boolean interleaved, printdata, outgropt, treeprint, dotdiff, transvp; steptr weight, category, alias, location, ally; sequence y; void fix_x(node* p,long site, double maxx, long rcategs) { /* dnaml dnamlk */ long i,j; p->underflows[site] += log(maxx); for ( i = 0 ; i < rcategs ; i++ ) { for ( j = 0 ; j < ((long)T - (long)A + 1) ; j++) p->x[site][i][j] /= maxx; } } /* fix_x */ void fix_protx(node* p,long site, double maxx, long rcategs) { /* proml promlk */ long i,m; p->underflows[site] += log(maxx); for ( i = 0 ; i < rcategs ; i++ ) for (m = 0; m <= 19; m++) p->protx[site][i][m] /= maxx; } /* fix_protx */ void alloctemp(node **temp, long *zeros, long endsite) { /*used in dnacomp and dnapenny */ *temp = (node *)Malloc(sizeof(node)); (*temp)->numsteps = (steptr)Malloc(endsite*sizeof(long)); (*temp)->base = (baseptr)Malloc(endsite*sizeof(long)); (*temp)->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray)); memcpy((*temp)->base, zeros, endsite*sizeof(long)); memcpy((*temp)->numsteps, zeros, endsite*sizeof(long)); zeronumnuc(*temp, endsite); } /* alloctemp */ void freetemp(node **temp) { /* used in dnacomp, dnapars, & dnapenny */ free((*temp)->numsteps); free((*temp)->base); free((*temp)->numnuc); free(*temp); } /* freetemp */ void freetree2 (pointarray treenode, long nonodes) { /* The natural complement to alloctree2. Free all elements of all the rings (normally triads) in treenode */ long i; node *p, *q; /* The first spp elements are just nodes, not rings */ for (i = 0; i < spp; i++) free (treenode[i]); /* The rest are rings */ for (i = spp; i < nonodes; i++) { p = treenode[i]->next; while (p != treenode[i]) { q = p->next; free (p); p = q; } /* p should now point to treenode[i], which has yet to be freed */ free (p); } free (treenode); } /* freetree2 */ /*void inputdata(long chars) { * input the names and sequences for each species * * used by dnacomp, dnadist, dnainvar, dnaml, dnamlk, dnapars, & dnapenny * long i, j, k, l, basesread, basesnew=0; Char charstate; boolean allread, done; if (printdata) headings(chars, "Sequences", "---------"); basesread = 0; allread = false; while (!(allread)) { * eat white space -- if the separator line has spaces on it* do { charstate = gettc(infile); } while (charstate == ' ' || charstate == '\t'); ungetc(charstate, infile); if (eoln(infile)) scan_eoln(infile); i = 1; while (i <= spp) { if ((interleaved && basesread == 0) || !interleaved) initname(i-1); j = (interleaved) ? basesread : 0; done = false; while (!done && !eoff(infile)) { if (interleaved) done = true; while (j < chars && !(eoln(infile) || eoff(infile))) { charstate = gettc(infile); if (charstate == '\n' || charstate == '\t') charstate = ' '; if (charstate == ' ' || (charstate >= '0' && charstate <= '9')) continue; uppercase(&charstate); if ((strchr("ABCDGHKMNRSTUVWXY?O-",charstate)) == NULL){ printf("ERROR: bad base: %c at site %5ld of species %3ld\n", charstate, j+1, i); if (charstate == '.') { printf(" Periods (.) may not be used as gap characters.\n"); printf(" The correct gap character is (-)\n"); } exxit(-1); } j++; y[i - 1][j - 1] = charstate; } if (interleaved) continue; if (j < chars) scan_eoln(infile); else if (j == chars) done = true; } if (interleaved && i == 1) basesnew = j; scan_eoln(infile); if ((interleaved && j != basesnew) || (!interleaved && j != chars)) { printf("\nERROR: sequences out of alignment at position %ld", j+1); printf(" of species %ld\n\n", i); exxit(-1); } i++; } if (interleaved) { basesread = basesnew; allread = (basesread == chars); } else allread = (i > spp); } if (!printdata) return; for (i = 1; i <= ((chars - 1) / 60 + 1); i++) { for (j = 1; j <= spp; j++) { for (k = 0; k < nmlngth; k++) putc(nayme[j - 1][k], outfile); fprintf(outfile, " "); l = i * 60; if (l > chars) l = chars; for (k = (i - 1) * 60 + 1; k <= l; k++) { if (dotdiff && (j > 1 && y[j - 1][k - 1] == y[0][k - 1])) charstate = '.'; else charstate = y[j - 1][k - 1]; putc(charstate, outfile); if (k % 10 == 0 && k % 60 != 0) putc(' ', outfile); } putc('\n', outfile); } putc('\n', outfile); } putc('\n', outfile); } * inputdata */ void alloctree(pointarray *treenode, long nonodes, boolean usertree) { /* allocate treenode dynamically */ /* used in dnapars, dnacomp, dnapenny & dnamove */ long i, j; node *p, *q; *treenode = (pointarray)Malloc(nonodes*sizeof(node *)); for (i = 0; i < spp; i++) { (*treenode)[i] = (node *)Malloc(sizeof(node)); (*treenode)[i]->tip = true; (*treenode)[i]->index = i+1; (*treenode)[i]->iter = true; (*treenode)[i]->branchnum = 0; (*treenode)[i]->initialized = true; } if (!usertree) for (i = spp; i < nonodes; i++) { q = NULL; for (j = 1; j <= 3; j++) { p = (node *)Malloc(sizeof(node)); p->tip = false; p->index = i+1; p->iter = true; p->branchnum = 0; p->initialized = false; p->next = q; q = p; } p->next->next->next = p; (*treenode)[i] = p; } } /* alloctree */ void allocx(long nonodes, long rcategs, pointarray treenode, boolean usertree) { /* allocate x dynamically */ /* used in dnaml & dnamlk */ long i, j, k; node *p; for (i = 0; i < spp; i++){ treenode[i]->x = (phenotype)Malloc(endsite*sizeof(ratelike)); treenode[i]->underflows = (double *)Malloc(endsite * sizeof (double)); for (j = 0; j < endsite; j++) treenode[i]->x[j] = (ratelike)Malloc(rcategs*sizeof(sitelike)); } if (!usertree) { for (i = spp; i < nonodes; i++) { p = treenode[i]; for (j = 1; j <= 3; j++) { p->underflows = (double *)Malloc (endsite * sizeof (double)); p->x = (phenotype)Malloc(endsite*sizeof(ratelike)); for (k = 0; k < endsite; k++) p->x[k] = (ratelike)Malloc(rcategs*sizeof(sitelike)); p = p->next; } } } } /* allocx */ void prot_allocx(long nonodes, long rcategs, pointarray treenode, boolean usertree) { /* allocate x dynamically */ /* used in proml */ long i, j, k; node *p; for (i = 0; i < spp; i++){ treenode[i]->protx = (pphenotype)Malloc(endsite*sizeof(pratelike)); treenode[i]->underflows = (double *)Malloc(endsite*sizeof(double)); for (j = 0; j < endsite; j++) treenode[i]->protx[j] = (pratelike)Malloc(rcategs*sizeof(psitelike)); } if (!usertree) { for (i = spp; i < nonodes; i++) { p = treenode[i]; for (j = 1; j <= 3; j++) { p->protx = (pphenotype)Malloc(endsite*sizeof(pratelike)); p->underflows = (double *)Malloc(endsite*sizeof(double)); for (k = 0; k < endsite; k++) p->protx[k] = (pratelike)Malloc(rcategs*sizeof(psitelike)); p = p->next; } } } } /* prot_allocx */ void setuptree(pointarray treenode, long nonodes, boolean usertree) { /* initialize treenodes */ long i; node *p; for (i = 1; i <= nonodes; i++) { if (i <= spp || !usertree) { treenode[i-1]->back = NULL; treenode[i-1]->tip = (i <= spp); treenode[i-1]->index = i; treenode[i-1]->numdesc = 0; treenode[i-1]->iter = true; treenode[i-1]->initialized = true; treenode[i-1]->tyme = 0.0; } } if (!usertree) { for (i = spp + 1; i <= nonodes; i++) { p = treenode[i-1]->next; while (p != treenode[i-1]) { p->back = NULL; p->tip = false; p->index = i; p->numdesc = 0; p->iter = true; p->initialized = false; p->tyme = 0.0; p = p->next; } } } } /* setuptree */ void setuptree2(tree *a) { /* initialize a tree */ /* used in dnaml, dnamlk, & restml */ a->likelihood = -999999.0; a->start = a->nodep[0]->back; a->root = NULL; } /* setuptree2 */ void alloctip(node *p, long *zeros) { /* allocate a tip node */ /* used by dnacomp, dnapars, & dnapenny */ p->numsteps = (steptr)Malloc(endsite*sizeof(long)); p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long)); p->base = (baseptr)Malloc(endsite*sizeof(long)); p->oldbase = (baseptr)Malloc(endsite*sizeof(long)); memcpy(p->base, zeros, endsite*sizeof(long)); memcpy(p->numsteps, zeros, endsite*sizeof(long)); memcpy(p->oldbase, zeros, endsite*sizeof(long)); memcpy(p->oldnumsteps, zeros, endsite*sizeof(long)); } /* alloctip */ void getbasefreqs(double freqa, double freqc, double freqg, double freqt, double *freqr, double *freqy, double *freqar, double *freqcy, double *freqgr, double *freqty, double *ttratio, double *xi, double *xv, double *fracchange, boolean freqsfrom, boolean printdata) { /* used by dnadist, dnaml, & dnamlk */ double aa, bb; if (printdata) { putc('\n', outfile); if (freqsfrom) fprintf(outfile, "Empirical "); fprintf(outfile, "Base Frequencies:\n\n"); fprintf(outfile, " A %10.5f\n", freqa); fprintf(outfile, " C %10.5f\n", freqc); fprintf(outfile, " G %10.5f\n", freqg); fprintf(outfile, " T(U) %10.5f\n", freqt); fprintf(outfile, "\n"); } *freqr = freqa + freqg; *freqy = freqc + freqt; *freqar = freqa / *freqr; *freqcy = freqc / *freqy; *freqgr = freqg / *freqr; *freqty = freqt / *freqy; aa = *ttratio * (*freqr) * (*freqy) - freqa * freqg - freqc * freqt; bb = freqa * (*freqgr) + freqc * (*freqty); *xi = aa / (aa + bb); *xv = 1.0 - *xi; if (*xi < 0.0) { printf("\n WARNING: This transition/transversion ratio\n"); printf(" is impossible with these base frequencies!\n"); *xi = 0.0; *xv = 1.0; (*ttratio) = (freqa*freqg+freqc*freqt)/((*freqr)*(*freqy)); printf(" Transition/transversion parameter reset\n"); printf(" so transition/transversion ratio is %10.6f\n\n", (*ttratio)); } if (freqa <= 0.0) freqa = 0.000001; if (freqc <= 0.0) freqc = 0.000001; if (freqg <= 0.0) freqg = 0.000001; if (freqt <= 0.0) freqt = 0.000001; *fracchange = (*xi) * (2 * freqa * (*freqgr) + 2 * freqc * (*freqty)) + (*xv) * (1.0 - freqa * freqa - freqc * freqc - freqg * freqg - freqt * freqt); } /* getbasefreqs */ void empiricalfreqs(double *freqa, double *freqc, double *freqg, double *freqt, steptr weight, pointarray treenode) { /* Get empirical base frequencies from the data */ /* used in dnaml & dnamlk */ long i, j, k; double sum, suma, sumc, sumg, sumt, w; *freqa = 0.25; *freqc = 0.25; *freqg = 0.25; *freqt = 0.25; for (k = 1; k <= 8; k++) { suma = 0.0; sumc = 0.0; sumg = 0.0; sumt = 0.0; for (i = 0; i < spp; i++) { for (j = 0; j < endsite; j++) { w = weight[j]; sum = (*freqa) * treenode[i]->x[j][0][0]; sum += (*freqc) * treenode[i]->x[j][0][(long)C - (long)A]; sum += (*freqg) * treenode[i]->x[j][0][(long)G - (long)A]; sum += (*freqt) * treenode[i]->x[j][0][(long)T - (long)A]; suma += w * (*freqa) * treenode[i]->x[j][0][0] / sum; sumc += w * (*freqc) * treenode[i]->x[j][0][(long)C - (long)A] / sum; sumg += w * (*freqg) * treenode[i]->x[j][0][(long)G - (long)A] / sum; sumt += w * (*freqt) * treenode[i]->x[j][0][(long)T - (long)A] / sum; } } sum = suma + sumc + sumg + sumt; *freqa = suma / sum; *freqc = sumc / sum; *freqg = sumg / sum; *freqt = sumt / sum; } if (*freqa <= 0.0) *freqa = 0.000001; if (*freqc <= 0.0) *freqc = 0.000001; if (*freqg <= 0.0) *freqg = 0.000001; if (*freqt <= 0.0) *freqt = 0.000001; } /* empiricalfreqs */ void sitesort(long chars, steptr weight) { /* Shell sort keeping sites, weights in same order */ /* used in dnainvar, dnapars, dnacomp & dnapenny */ long gap, i, j, jj, jg, k, itemp; boolean flip, tied; gap = chars / 2; while (gap > 0) { for (i = gap + 1; i <= chars; i++) { j = i - gap; flip = true; while (j > 0 && flip) { jj = alias[j - 1]; jg = alias[j + gap - 1]; tied = true; k = 1; while (k <= spp && tied) { flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]); tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]); k++; } if (!flip) break; itemp = alias[j - 1]; alias[j - 1] = alias[j + gap - 1]; alias[j + gap - 1] = itemp; itemp = weight[j - 1]; weight[j - 1] = weight[j + gap - 1]; weight[j + gap - 1] = itemp; j -= gap; } } gap /= 2; } } /* sitesort */ void sitecombine(long chars) { /* combine sites that have identical patterns */ /* used in dnapars, dnapenny, & dnacomp */ long i, j, k; boolean tied; i = 1; while (i < chars) { j = i + 1; tied = true; while (j <= chars && tied) { k = 1; while (k <= spp && tied) { tied = (tied && y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]); k++; } if (tied) { weight[i - 1] += weight[j - 1]; weight[j - 1] = 0; ally[alias[j - 1] - 1] = alias[i - 1]; } j++; } i = j - 1; } } /* sitecombine */ void sitescrunch(long chars) { /* move so one representative of each pattern of sites comes first */ /* used in dnapars & dnacomp */ long i, j, itemp; boolean done, found; done = false; i = 1; j = 2; while (!done) { if (ally[alias[i - 1] - 1] != alias[i - 1]) { if (j <= i) j = i + 1; if (j <= chars) { do { found = (ally[alias[j - 1] - 1] == alias[j - 1]); j++; } while (!(found || j > chars)); if (found) { j--; itemp = alias[i - 1]; alias[i - 1] = alias[j - 1]; alias[j - 1] = itemp; itemp = weight[i - 1]; weight[i - 1] = weight[j - 1]; weight[j - 1] = itemp; } else done = true; } else done = true; } i++; done = (done || i >= chars); } } /* sitescrunch */ void sitesort2(long sites, steptr aliasweight) { /* Shell sort keeping sites, weights in same order */ /* used in dnaml & dnamnlk */ long gap, i, j, jj, jg, k, itemp; boolean flip, tied; gap = sites / 2; while (gap > 0) { for (i = gap + 1; i <= sites; i++) { j = i - gap; flip = true; while (j > 0 && flip) { jj = alias[j - 1]; jg = alias[j + gap - 1]; tied = (category[jj - 1] == category[jg - 1]); flip = (category[jj - 1] > category[jg - 1]); k = 1; while (k <= spp && tied) { flip = (y[k - 1][jj - 1] > y[k - 1][jg - 1]); tied = (tied && y[k - 1][jj - 1] == y[k - 1][jg - 1]); k++; } if (!flip) break; itemp = alias[j - 1]; alias[j - 1] = alias[j + gap - 1]; alias[j + gap - 1] = itemp; itemp = aliasweight[j - 1]; aliasweight[j - 1] = aliasweight[j + gap - 1]; aliasweight[j + gap - 1] = itemp; j -= gap; } } gap /= 2; } } /* sitesort2 */ void sitecombine2(long sites, steptr aliasweight) { /* combine sites that have identical patterns */ /* used in dnaml & dnamlk */ long i, j, k; boolean tied; i = 1; while (i < sites) { j = i + 1; tied = true; while (j <= sites && tied) { tied = (category[alias[i - 1] - 1] == category[alias[j - 1] - 1]); k = 1; while (k <= spp && tied) { tied = (tied && y[k - 1][alias[i - 1] - 1] == y[k - 1][alias[j - 1] - 1]); k++; } if (!tied) break; aliasweight[i - 1] += aliasweight[j - 1]; aliasweight[j - 1] = 0; ally[alias[j - 1] - 1] = alias[i - 1]; j++; } i = j; } } /* sitecombine2 */ void sitescrunch2(long sites, long i, long j, steptr aliasweight) { /* move so positively weighted sites come first */ /* used by dnainvar, dnaml, dnamlk, & restml */ long itemp; boolean done, found; done = false; while (!done) { if (aliasweight[i - 1] > 0) i++; else { if (j <= i) j = i + 1; if (j <= sites) { do { found = (aliasweight[j - 1] > 0); j++; } while (!(found || j > sites)); if (found) { j--; itemp = alias[i - 1]; alias[i - 1] = alias[j - 1]; alias[j - 1] = itemp; itemp = aliasweight[i - 1]; aliasweight[i - 1] = aliasweight[j - 1]; aliasweight[j - 1] = itemp; } else done = true; } else done = true; } done = (done || i >= sites); } } /* sitescrunch2 */ void makevalues(pointarray treenode, long *zeros, boolean usertree) { /* set up fractional likelihoods at tips */ /* used by dnacomp, dnapars, & dnapenny */ long i, j; char ns = 0; node *p; setuptree(treenode, nonodes, usertree); for (i = 0; i < spp; i++) alloctip(treenode[i], zeros); if (!usertree) { for (i = spp; i < nonodes; i++) { p = treenode[i]; do { allocnontip(p, zeros, endsite); p = p->next; } while (p != treenode[i]); } } for (j = 0; j < endsite; j++) { for (i = 0; i < spp; i++) { switch (y[i][alias[j] - 1]) { case 'A': ns = 1 << A; break; case 'C': ns = 1 << C; break; case 'G': ns = 1 << G; break; case 'U': ns = 1 << T; break; case 'T': ns = 1 << T; break; case 'M': ns = (1 << A) | (1 << C); break; case 'R': ns = (1 << A) | (1 << G); break; case 'W': ns = (1 << A) | (1 << T); break; case 'S': ns = (1 << C) | (1 << G); break; case 'Y': ns = (1 << C) | (1 << T); break; case 'K': ns = (1 << G) | (1 << T); break; case 'B': ns = (1 << C) | (1 << G) | (1 << T); break; case 'D': ns = (1 << A) | (1 << G) | (1 << T); break; case 'H': ns = (1 << A) | (1 << C) | (1 << T); break; case 'V': ns = (1 << A) | (1 << C) | (1 << G); break; case 'N': ns = (1 << A) | (1 << C) | (1 << G) | (1 << T); break; case 'X': ns = (1 << A) | (1 << C) | (1 << G) | (1 << T); break; case '?': ns = (1 << A) | (1 << C) | (1 << G) | (1 << T) | (1 << O); break; case 'O': ns = 1 << O; break; case '-': ns = 1 << O; break; } treenode[i]->base[j] = ns; treenode[i]->numsteps[j] = 0; } } } /* makevalues */ void makevalues2(long categs, pointarray treenode, long endsite, long spp, sequence y, steptr alias) { /* set up fractional likelihoods at tips */ /* used by dnaml & dnamlk */ long i, j, k, l; bases b; for (k = 0; k < endsite; k++) { j = alias[k]; for (i = 0; i < spp; i++) { for (l = 0; l < categs; l++) { for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 0.0; switch (y[i][j - 1]) { case 'A': treenode[i]->x[k][l][0] = 1.0; break; case 'C': treenode[i]->x[k][l][(long)C - (long)A] = 1.0; break; case 'G': treenode[i]->x[k][l][(long)G - (long)A] = 1.0; break; case 'T': treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'U': treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'M': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)C - (long)A] = 1.0; break; case 'R': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)G - (long)A] = 1.0; break; case 'W': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'S': treenode[i]->x[k][l][(long)C - (long)A] = 1.0; treenode[i]->x[k][l][(long)G - (long)A] = 1.0; break; case 'Y': treenode[i]->x[k][l][(long)C - (long)A] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'K': treenode[i]->x[k][l][(long)G - (long)A] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'B': treenode[i]->x[k][l][(long)C - (long)A] = 1.0; treenode[i]->x[k][l][(long)G - (long)A] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'D': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)G - (long)A] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'H': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)C - (long)A] = 1.0; treenode[i]->x[k][l][(long)T - (long)A] = 1.0; break; case 'V': treenode[i]->x[k][l][0] = 1.0; treenode[i]->x[k][l][(long)C - (long)A] = 1.0; treenode[i]->x[k][l][(long)G - (long)A] = 1.0; break; case 'N': for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 1.0; break; case 'X': for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 1.0; break; case '?': for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 1.0; break; case 'O': for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 1.0; break; case '-': for (b = A; (long)b <= (long)T; b = (bases)((long)b + 1)) treenode[i]->x[k][l][(long)b - (long)A] = 1.0; break; } } } } } /* makevalues2 */ void fillin(node *p, node *left, node *rt) { /* sets up for each node in the tree the base sequence at that point and counts the changes. */ long i, j, k, n, purset, pyrset; node *q; purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); if (!left) { memcpy(p->base, rt->base, endsite*sizeof(long)); memcpy(p->numsteps, rt->numsteps, endsite*sizeof(long)); q = rt; } else if (!rt) { memcpy(p->base, left->base, endsite*sizeof(long)); memcpy(p->numsteps, left->numsteps, endsite*sizeof(long)); q = left; } else { for (i = 0; i < endsite; i++) { p->base[i] = left->base[i] & rt->base[i]; p->numsteps[i] = left->numsteps[i] + rt->numsteps[i]; if (p->base[i] == 0) { p->base[i] = left->base[i] | rt->base[i]; if (transvp) { if (!((p->base[i] == purset) || (p->base[i] == pyrset))) p->numsteps[i] += weight[i]; } else p->numsteps[i] += weight[i]; } } q = rt; } if (left && rt) n = 2; else n = 1; for (i = 0; i < endsite; i++) for (j = (long)A; j <= (long)O; j++) p->numnuc[i][j] = 0; for (k = 1; k <= n; k++) { if (k == 2) q = left; for (i = 0; i < endsite; i++) { for (j = (long)A; j <= (long)O; j++) { if (q->base[i] & (1 << j)) p->numnuc[i][j]++; } } } } /* fillin */ long getlargest(long *numnuc) { /* find the largest in array numnuc */ long i, largest; largest = 0; for (i = (long)A; i <= (long)O; i++) if (numnuc[i] > largest) largest = numnuc[i]; return largest; } /* getlargest */ void multifillin(node *p, node *q, long dnumdesc) { /* sets up for each node in the tree the base sequence at that point and counts the changes according to the changes in q's base */ long i, j, b, largest, descsteps, purset, pyrset; memcpy(p->oldbase, p->base, endsite*sizeof(long)); memcpy(p->oldnumsteps, p->numsteps, endsite*sizeof(long)); purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); for (i = 0; i < endsite; i++) { descsteps = 0; for (j = (long)A; j <= (long)O; j++) { b = 1 << j; if ((descsteps == 0) && (p->base[i] & b)) descsteps = p->numsteps[i] - (p->numdesc - dnumdesc - p->numnuc[i][j]) * weight[i]; } if (dnumdesc == -1) descsteps -= q->oldnumsteps[i]; else if (dnumdesc == 0) descsteps += (q->numsteps[i] - q->oldnumsteps[i]); else descsteps += q->numsteps[i]; if (q->oldbase[i] != q->base[i]) { for (j = (long)A; j <= (long)O; j++) { b = 1 << j; if (transvp) { if (b & purset) b = purset; if (b & pyrset) b = pyrset; } if ((q->oldbase[i] & b) && !(q->base[i] & b)) p->numnuc[i][j]--; else if (!(q->oldbase[i] & b) && (q->base[i] & b)) p->numnuc[i][j]++; } } largest = getlargest(p->numnuc[i]); if (q->oldbase[i] != q->base[i]) { p->base[i] = 0; for (j = (long)A; j <= (long)O; j++) { if (p->numnuc[i][j] == largest) p->base[i] |= (1 << j); } } p->numsteps[i] = (p->numdesc - largest) * weight[i] + descsteps; } } /* multifillin */ void sumnsteps(node *p, node *left, node *rt, long a, long b) { /* sets up for each node in the tree the base sequence at that point and counts the changes. */ long i; long ns, rs, ls, purset, pyrset; if (!left) { memcpy(p->numsteps, rt->numsteps, endsite*sizeof(long)); memcpy(p->base, rt->base, endsite*sizeof(long)); } else if (!rt) { memcpy(p->numsteps, left->numsteps, endsite*sizeof(long)); memcpy(p->base, left->base, endsite*sizeof(long)); } else { purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); for (i = a; i < b; i++) { ls = left->base[i]; rs = rt->base[i]; ns = ls & rs; p->numsteps[i] = left->numsteps[i] + rt->numsteps[i]; if (ns == 0) { ns = ls | rs; if (transvp) { if (!((ns == purset) || (ns == pyrset))) p->numsteps[i] += weight[i]; } else p->numsteps[i] += weight[i]; } p->base[i] = ns; } } } /* sumnsteps */ void sumnsteps2(node *p,node *left,node *rt,long a,long b,long *threshwt) { /* counts the changes at each node. */ long i, steps; long ns, rs, ls, purset, pyrset; long term; if (a == 0) p->sumsteps = 0.0; if (!left) memcpy(p->numsteps, rt->numsteps, endsite*sizeof(long)); else if (!rt) memcpy(p->numsteps, left->numsteps, endsite*sizeof(long)); else { purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); for (i = a; i < b; i++) { ls = left->base[i]; rs = rt->base[i]; ns = ls & rs; p->numsteps[i] = left->numsteps[i] + rt->numsteps[i]; if (ns == 0) { ns = ls | rs; if (transvp) { if (!((ns == purset) || (ns == pyrset))) p->numsteps[i] += weight[i]; } else p->numsteps[i] += weight[i]; } } } for (i = a; i < b; i++) { steps = p->numsteps[i]; if ((long)steps <= threshwt[i]) term = steps; else term = threshwt[i]; p->sumsteps += (double)term; } } /* sumnsteps2 */ void multisumnsteps(node *p, node *q, long a, long b, long *threshwt) { /* computes the number of steps between p and q */ long i, j, steps, largest, descsteps, purset, pyrset, b1; long term; if (a == 0) p->sumsteps = 0.0; purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); for (i = a; i < b; i++) { descsteps = 0; for (j = (long)A; j <= (long)O; j++) { if ((descsteps == 0) && (p->base[i] & (1 << j))) descsteps = p->numsteps[i] - (p->numdesc - 1 - p->numnuc[i][j]) * weight[i]; } descsteps += q->numsteps[i]; largest = 0; for (j = (long)A; j <= (long)O; j++) { b1 = (1 << j); if (transvp) { if (b1 & purset) b1 = purset; if (b1 & pyrset) b1 = pyrset; } if (q->base[i] & b1) p->numnuc[i][j]++; if (p->numnuc[i][j] > largest) largest = p->numnuc[i][j]; } steps = (p->numdesc - largest) * weight[i] + descsteps; if ((long)steps <= threshwt[i]) term = steps; else term = threshwt[i]; p->sumsteps += (double)term; } } /* multisumnsteps */ void multisumnsteps2(node *p) { /* counts the changes at each multi-way node. Sums up steps of all descendants */ long i, j, largest, purset, pyrset, b1; node *q; baseptr b; purset = (1 << (long)A) + (1 << (long)G); pyrset = (1 << (long)C) + (1 << (long)T); for (i = 0; i < endsite; i++) { p->numsteps[i] = 0; q = p->next; while (q != p) { if (q->back) { p->numsteps[i] += q->back->numsteps[i]; b = q->back->base; for (j = (long)A; j <= (long)O; j++) { b1 = (1 << j); if (transvp) { if (b1 & purset) b1 = purset; if (b1 & pyrset) b1 = pyrset; } if (b[i] & b1) p->numnuc[i][j]++; } } q = q->next; } largest = getlargest(p->numnuc[i]); p->base[i] = 0; for (j = (long)A; j <= (long)O; j++) { if (p->numnuc[i][j] == largest) p->base[i] |= (1 << j); } p->numsteps[i] += ((p->numdesc - largest) * weight[i]); } } /* multisumnsteps2 */ boolean alltips(node *forknode, node *p) { /* returns true if all descendants of forknode except p are tips; false otherwise. */ node *q, *r; boolean tips; tips = true; r = forknode; q = forknode->next; do { if (q->back && q->back != p && !q->back->tip) tips = false; q = q->next; } while (tips && q != r); return tips; } /* alltips */ void gdispose(node *p, node **grbg, pointarray treenode) { /* go through tree throwing away nodes */ node *q, *r; p->back = NULL; if (p->tip) return; treenode[p->index - 1] = NULL; q = p->next; while (q != p) { gdispose(q->back, grbg, treenode); q->back = NULL; r = q; q = q->next; chuck(grbg, r); } chuck(grbg, q); } /* gdispose */ void preorder(node *p, node *r, node *root, node *removing, node *adding, node *changing, long dnumdesc) { /* recompute number of steps in preorder taking both ancestoral and descendent steps into account. removing points to a node being removed, if any */ node *q, *p1, *p2; if (p && !p->tip && p != adding) { q = p; do { if (p->back != r) { if (p->numdesc > 2) { if (changing) multifillin (p, r, dnumdesc); else multifillin (p, r, 0); } else { p1 = p->next; if (!removing) while (!p1->back) p1 = p1->next; else while (!p1->back || p1->back == removing) p1 = p1->next; p2 = p1->next; if (!removing) while (!p2->back) p2 = p2->next; else while (!p2->back || p2->back == removing) p2 = p2->next; p1 = p1->back; p2 = p2->back; if (p->back == p1) p1 = NULL; else if (p->back == p2) p2 = NULL; memcpy(p->oldbase, p->base, endsite*sizeof(long)); memcpy(p->oldnumsteps, p->numsteps, endsite*sizeof(long)); fillin(p, p1, p2); } } p = p->next; } while (p != q); q = p; do { preorder(p->next->back, p->next, root, removing, adding, NULL, 0); p = p->next; } while (p->next != q); } } /* preorder */ void updatenumdesc(node *p, node *root, long n) { /* set p's numdesc to n. If p is the root, numdesc of p's descendants are set to n-1. */ node *q; q = p; if (p == root && n > 0) { p->numdesc = n; n--; q = q->next; } do { q->numdesc = n; q = q->next; } while (q != p); } /* updatenumdesc */ void add(node *below,node *newtip,node *newfork,node **root, boolean recompute,pointarray treenode,node **grbg,long *zeros) { /* inserts the nodes newfork and its left descendant, newtip, to the tree. below becomes newfork's right descendant. if newfork is NULL, newtip is added as below's sibling */ /* used in dnacomp & dnapars */ node *p; if (below != treenode[below->index - 1]) below = treenode[below->index - 1]; if (newfork) { if (below->back != NULL) below->back->back = newfork; newfork->back = below->back; below->back = newfork->next->next; newfork->next->next->back = below; newfork->next->back = newtip; newtip->back = newfork->next; if (*root == below) *root = newfork; updatenumdesc(newfork, *root, 2); } else { gnutreenode(grbg, &p, below->index, endsite, zeros); p->back = newtip; newtip->back = p; p->next = below->next; below->next = p; updatenumdesc(below, *root, below->numdesc + 1); } if (!newtip->tip) updatenumdesc(newtip, *root, newtip->numdesc); (*root)->back = NULL; if (!recompute) return; if (!newfork) { memcpy(newtip->back->base, below->base, endsite*sizeof(long)); memcpy(newtip->back->numsteps, below->numsteps, endsite*sizeof(long)); memcpy(newtip->back->numnuc, below->numnuc, endsite*sizeof(nucarray)); if (below != *root) { memcpy(below->back->oldbase, zeros, endsite*sizeof(long)); memcpy(below->back->oldnumsteps, zeros, endsite*sizeof(long)); multifillin(newtip->back, below->back, 1); } if (!newtip->tip) { memcpy(newtip->back->oldbase, zeros, endsite*sizeof(long)); memcpy(newtip->back->oldnumsteps, zeros, endsite*sizeof(long)); preorder(newtip, newtip->back, *root, NULL, NULL, below, 1); } memcpy(newtip->oldbase, zeros, endsite*sizeof(long)); memcpy(newtip->oldnumsteps, zeros, endsite*sizeof(long)); preorder(below, newtip, *root, NULL, newtip, below, 1); if (below != *root) preorder(below->back, below, *root, NULL, NULL, NULL, 0); } else { fillin(newtip->back, newtip->back->next->back, newtip->back->next->next->back); if (!newtip->tip) { memcpy(newtip->back->oldbase, zeros, endsite*sizeof(long)); memcpy(newtip->back->oldnumsteps, zeros, endsite*sizeof(long)); preorder(newtip, newtip->back, *root, NULL, NULL, newfork, 1); } if (newfork != *root) { memcpy(below->back->base, newfork->back->base, endsite*sizeof(long)); memcpy(below->back->numsteps, newfork->back->numsteps, endsite*sizeof(long)); preorder(newfork, newtip, *root, NULL, newtip, NULL, 0); } else { fillin(below->back, newtip, NULL); fillin(newfork, newtip, below); memcpy(below->back->oldbase, zeros, endsite*sizeof(long)); memcpy(below->back->oldnumsteps, zeros, endsite*sizeof(long)); preorder(below, below->back, *root, NULL, NULL, newfork, 1); } if (newfork != *root) { memcpy(newfork->oldbase, below->base, endsite*sizeof(long)); memcpy(newfork->oldnumsteps, below->numsteps, endsite*sizeof(long)); preorder(newfork->back, newfork, *root, NULL, NULL, NULL, 0); } } } /* add */ void findbelow(node **below, node *item, node *fork) { /* decide which of fork's binary children is below */ if (fork->next->back == item) *below = fork->next->next->back; else *below = fork->next->back; } /* findbelow */ void re_move(node *item, node **fork, node **root, boolean recompute, pointarray treenode, node **grbg, long *zeros) { /* removes nodes item and its ancestor, fork, from the tree. the new descendant of fork's ancestor is made to be fork's second descendant (other than item). Also returns pointers to the deleted nodes, item and fork. If item belongs to a node with more than 2 descendants, fork will not be deleted */ /* used in dnacomp & dnapars */ node *p, *q, *other = NULL, *otherback = NULL; if (item->back == NULL) { *fork = NULL; return; } *fork = treenode[item->back->index - 1]; if ((*fork)->numdesc == 2) { updatenumdesc(*fork, *root, 0); findbelow(&other, item, *fork); otherback = other->back; if (*root == *fork) { *root = other; if (!other->tip) updatenumdesc(other, *root, other->numdesc); } p = item->back->next->back; q = item->back->next->next->back; if (p != NULL) p->back = q; if (q != NULL) q->back = p; (*fork)->back = NULL; p = (*fork)->next; while (p != *fork) { p->back = NULL; p = p->next; } } else { updatenumdesc(*fork, *root, (*fork)->numdesc - 1); p = *fork; while (p->next != item->back) p = p->next; p->next = item->back->next; } if (!item->tip) { updatenumdesc(item, item, item->numdesc); if (recompute) { memcpy(item->back->oldbase, item->back->base, endsite*sizeof(long)); memcpy(item->back->oldnumsteps, item->back->numsteps, endsite*sizeof(long)); memcpy(item->back->base, zeros, endsite*sizeof(long)); memcpy(item->back->numsteps, zeros, endsite*sizeof(long)); preorder(item, item->back, *root, item->back, NULL, item, -1); } } if ((*fork)->numdesc >= 2) chuck(grbg, item->back); item->back = NULL; if (!recompute) return; if ((*fork)->numdesc == 0) { memcpy(otherback->oldbase, otherback->base, endsite*sizeof(long)); memcpy(otherback->oldnumsteps, otherback->numsteps, endsite*sizeof(long)); if (other == *root) { memcpy(otherback->base, zeros, endsite*sizeof(long)); memcpy(otherback->numsteps, zeros, endsite*sizeof(long)); } else { memcpy(otherback->base, other->back->base, endsite*sizeof(long)); memcpy(otherback->numsteps, other->back->numsteps, endsite*sizeof(long)); } p = other->back; other->back = otherback; if (other == *root) preorder(other, otherback, *root, otherback, NULL, other, -1); else preorder(other, otherback, *root, NULL, NULL, NULL, 0); other->back = p; if (other != *root) { memcpy(other->oldbase,(*fork)->base, endsite*sizeof(long)); memcpy(other->oldnumsteps,(*fork)->numsteps, endsite*sizeof(long)); preorder(other->back, other, *root, NULL, NULL, NULL, 0); } } else { memcpy(item->oldbase, item->base, endsite*sizeof(long)); memcpy(item->oldnumsteps, item->numsteps, endsite*sizeof(long)); memcpy(item->base, zeros, endsite*sizeof(long)); memcpy(item->numsteps, zeros, endsite*sizeof(long)); preorder(*fork, item, *root, NULL, NULL, *fork, -1); if (*fork != *root) preorder((*fork)->back, *fork, *root, NULL, NULL, NULL, 0); memcpy(item->base, item->oldbase, endsite*sizeof(long)); memcpy(item->numsteps, item->oldnumsteps, endsite*sizeof(long)); } } /* remove */ void postorder(node *p) { /* traverses an n-ary tree, suming up steps at a node's descendants */ /* used in dnacomp, dnapars, & dnapenny */ node *q; if (p->tip) return; q = p->next; while (q != p) { postorder(q->back); q = q->next; } zeronumnuc(p, endsite); if (p->numdesc > 2) multisumnsteps2(p); else fillin(p, p->next->back, p->next->next->back); } /* postorder */ void getnufork(node **nufork,node **grbg,pointarray treenode,long *zeros) { /* find a fork not used currently */ long i; i = spp; while (treenode[i] && treenode[i]->numdesc > 0) i++; if (!treenode[i]) gnutreenode(grbg, &treenode[i], i, endsite, zeros); *nufork = treenode[i]; } /* getnufork */ void reroot(node *outgroup, node *root) { /* reorients tree, putting outgroup in desired position. used if the root is binary. */ /* used in dnacomp & dnapars */ node *p, *q; if (outgroup->back->index == root->index) return; p = root->next; q = root->next->next; p->back->back = q->back; q->back->back = p->back; p->back = outgroup; q->back = outgroup->back; outgroup->back->back = q; outgroup->back = p; } /* reroot */ void reroot2(node *outgroup, node *root) { /* reorients tree, putting outgroup in desired position. */ /* used in dnacomp & dnapars */ node *p; p = outgroup->back->next; while (p->next != outgroup->back) p = p->next; root->next = outgroup->back; p->next = root; } /* reroot2 */ void reroot3(node *outgroup, node *root, node *root2, node *lastdesc, node **grbg) { /* reorients tree, putting back outgroup in original position. */ /* used in dnacomp & dnapars */ node *p; p = root->next; while (p->next != root) p = p->next; chuck(grbg, root); p->next = outgroup->back; root2->next = lastdesc->next; lastdesc->next = root2; } /* reroot3 */ void savetraverse(node *p) { /* sets BOOLEANs that indicate which way is down */ node *q; p->bottom = true; if (p->tip) return; q = p->next; while (q != p) { q->bottom = false; savetraverse(q->back); q = q->next; } } /* savetraverse */ void newindex(long i, node *p) { /* assigns index i to node p */ while (p->index != i) { p->index = i; p = p->next; } } /* newindex */ void flipindexes(long nextnode, pointarray treenode) { /* flips index of nodes between nextnode and last node. */ long last; node *temp; last = nonodes; while (treenode[last - 1]->numdesc == 0) last--; if (last > nextnode) { temp = treenode[nextnode - 1]; treenode[nextnode - 1] = treenode[last - 1]; treenode[last - 1] = temp; newindex(nextnode, treenode[nextnode - 1]); newindex(last, treenode[last - 1]); } } /* flipindexes */ boolean parentinmulti(node *anode) { /* sees if anode's parent has more than 2 children */ node *p; while (!anode->bottom) anode = anode->next; p = anode->back; while (!p->bottom) p = p->next; return (p->numdesc > 2); } /* parentinmulti */ long sibsvisited(node *anode, long *place) { /* computes the number of nodes which are visited earlier than anode among its siblings */ node *p; long nvisited; while (!anode->bottom) anode = anode->next; p = anode->back->next; nvisited = 0; do { if (!p->bottom && place[p->back->index - 1] != 0) nvisited++; p = p->next; } while (p != anode->back); return nvisited; } /* sibsvisited */ long smallest(node *anode, long *place) { /* finds the smallest index of sibling of anode */ node *p; long min; while (!anode->bottom) anode = anode->next; p = anode->back->next; if (p->bottom) p = p->next; min = nonodes; do { if (p->back && place[p->back->index - 1] != 0) { if (p->back->index <= spp) { if (p->back->index < min) min = p->back->index; } else { if (place[p->back->index - 1] < min) min = place[p->back->index - 1]; } } p = p->next; if (p->bottom) p = p->next; } while (p != anode->back); return min; } /* smallest */ void bintomulti(node **root, node **binroot, node **grbg, long *zeros) { /* attaches root's left child to its right child and makes the right child new root */ node *left, *right, *newnode, *temp; right = (*root)->next->next->back; left = (*root)->next->back; if (right->tip) { (*root)->next = right->back; (*root)->next->next = left->back; temp = left; left = right; right = temp; right->back->next = *root; } gnutreenode(grbg, &newnode, right->index, endsite, zeros); newnode->next = right->next; newnode->back = left; left->back = newnode; right->next = newnode; (*root)->next->back = (*root)->next->next->back = NULL; *binroot = *root; (*binroot)->numdesc = 0; *root = right; (*root)->numdesc++; (*root)->back = NULL; } /* bintomulti */ void backtobinary(node **root, node *binroot, node **grbg) { /* restores binary root */ node *p; binroot->next->back = (*root)->next->back; (*root)->next->back->back = binroot->next; p = (*root)->next; (*root)->next = p->next; binroot->next->next->back = *root; (*root)->back = binroot->next->next; chuck(grbg, p); (*root)->numdesc--; *root = binroot; (*root)->numdesc = 2; } /* backtobinary */ boolean outgrin(node *root, node *outgrnode) { /* checks if outgroup node is a child of root */ node *p; p = root->next; while (p != root) { if (p->back == outgrnode) return true; p = p->next; } return false; } /* outgrin */ void flipnodes(node *nodea, node *nodeb) { /* flip nodes */ node *backa, *backb; backa = nodea->back; backb = nodeb->back; backa->back = nodeb; backb->back = nodea; nodea->back = backb; nodeb->back = backa; } /* flipnodes */ void moveleft(node *root, node *outgrnode, node **flipback) { /* makes outgroup node to leftmost child of root */ node *p; boolean done; p = root->next; done = false; while (p != root && !done) { if (p->back == outgrnode) { *flipback = p; flipnodes(root->next->back, p->back); done = true; } p = p->next; } } /* moveleft */ void savetree(node *root, long *place, pointarray treenode, node **grbg, long *zeros) { /* record in place where each species has to be added to reconstruct this tree */ /* used by dnacomp & dnapars */ long i, j, nextnode, nvisited; node *p, *q, *r = NULL, *root2, *lastdesc, *outgrnode, *binroot, *flipback; boolean done, newfork; binroot = NULL; lastdesc = NULL; root2 = NULL; flipback = NULL; outgrnode = treenode[outgrno - 1]; if (root->numdesc == 2) bintomulti(&root, &binroot, grbg, zeros); if (outgrin(root, outgrnode)) { if (outgrnode != root->next->back) moveleft(root, outgrnode, &flipback); } else { root2 = root; lastdesc = root->next; while (lastdesc->next != root) lastdesc = lastdesc->next; lastdesc->next = root->next; gnutreenode(grbg, &root, outgrnode->back->index, endsite, zeros); root->numdesc = root2->numdesc; reroot2(outgrnode, root); } savetraverse(root); nextnode = spp + 1; for (i = nextnode; i <= nonodes; i++) if (treenode[i - 1]->numdesc == 0) flipindexes(i, treenode); for (i = 0; i < nonodes; i++) place[i] = 0; place[root->index - 1] = 1; for (i = 1; i <= spp; i++) { p = treenode[i - 1]; while (place[p->index - 1] == 0) { place[p->index - 1] = i; while (!p->bottom) p = p->next; r = p; p = p->back; } if (i > 1) { q = treenode[i - 1]; newfork = true; nvisited = sibsvisited(q, place); if (nvisited == 0) { if (parentinmulti(r)) { nvisited = sibsvisited(r, place); if (nvisited == 0) place[i - 1] = place[p->index - 1]; else if (nvisited == 1) place[i - 1] = smallest(r, place); else { place[i - 1] = -smallest(r, place); newfork = false; } } else place[i - 1] = place[p->index - 1]; } else if (nvisited == 1) { place[i - 1] = place[p->index - 1]; } else { place[i - 1] = -smallest(q, place); newfork = false; } if (newfork) { j = place[p->index - 1]; done = false; while (!done) { place[p->index - 1] = nextnode; while (!p->bottom) p = p->next; p = p->back; done = (p == NULL); if (!done) done = (place[p->index - 1] != j); if (done) { nextnode++; } } } } } if (flipback) flipnodes(outgrnode, flipback->back); else { if (root2) { reroot3(outgrnode, root, root2, lastdesc, grbg); root = root2; } } if (binroot) backtobinary(&root, binroot, grbg); } /* savetree */ void addnsave(node *p, node *item, node *nufork, node **root, node **grbg, boolean multf, pointarray treenode, long *place, long *zeros) { /* adds item to tree and save it. Then removes item. */ node *dummy; if (!multf) add(p, item, nufork, root, false, treenode, grbg, zeros); else add(p, item, NULL, root, false, treenode, grbg, zeros); savetree(*root, place, treenode, grbg, zeros); if (!multf) re_move(item, &nufork, root, false, treenode, grbg, zeros); else re_move(item, &dummy, root, false, treenode, grbg, zeros); } /* addnsave */ void addbestever(long *pos, long *nextree, long maxtrees, boolean collapse, long *place, bestelm *bestrees) { /* adds first best tree */ *pos = 1; *nextree = 1; initbestrees(bestrees, maxtrees, true); initbestrees(bestrees, maxtrees, false); addtree(*pos, nextree, collapse, place, bestrees); } /* addbestever */ void addtiedtree(long pos, long *nextree, long maxtrees, boolean collapse, long *place, bestelm *bestrees) { /* add tied tree */ if (*nextree <= maxtrees) addtree(pos, nextree, collapse, place, bestrees); } /* addtiedtree */ void clearcollapse(pointarray treenode) { /* clears collapse status at a node */ long i; node *p; for (i = 0; i < nonodes; i++) { treenode[i]->collapse = undefined; if (!treenode[i]->tip) { p = treenode[i]->next; while (p != treenode[i]) { p->collapse = undefined; p = p->next; } } } } /* clearcollapse */ void clearbottom(pointarray treenode) { /* clears boolean bottom at a node */ long i; node *p; for (i = 0; i < nonodes; i++) { treenode[i]->bottom = false; if (!treenode[i]->tip) { p = treenode[i]->next; while (p != treenode[i]) { p->bottom = false; p = p->next; } } } } /* clearbottom */ void collabranch(node *collapfrom, node *tempfrom, node *tempto) { /* collapse branch from collapfrom */ long i, j, b, largest, descsteps; boolean done; for (i = 0; i < endsite; i++) { descsteps = 0; for (j = (long)A; j <= (long)O; j++) { b = 1 << j; if ((descsteps == 0) && (collapfrom->base[i] & b)) descsteps = tempfrom->oldnumsteps[i] - (collapfrom->numdesc - collapfrom->numnuc[i][j]) * weight[i]; } done = false; for (j = (long)A; j <= (long)O; j++) { b = 1 << j; if (!done && (tempto->base[i] & b)) { descsteps += (tempto->numsteps[i] - (tempto->numdesc - collapfrom->numdesc - tempto->numnuc[i][j]) * weight[i]); done = true; } } for (j = (long)A; j <= (long)O; j++) tempto->numnuc[i][j] += collapfrom->numnuc[i][j]; largest = getlargest(tempto->numnuc[i]); tempto->base[i] = 0; for (j = (long)A; j <= (long)O; j++) { if (tempto->numnuc[i][j] == largest) tempto->base[i] |= (1 << j); } tempto->numsteps[i] = (tempto->numdesc - largest) * weight[i] + descsteps; } } /* collabranch */ boolean allcommonbases(node *a, node *b, boolean *allsame) { /* see if bases are common at all sites for nodes a and b */ long i; boolean allcommon; allcommon = true; *allsame = true; for (i = 0; i < endsite; i++) { if ((a->base[i] & b->base[i]) == 0) allcommon = false; else if (a->base[i] != b->base[i]) *allsame = false; } return allcommon; } /* allcommonbases */ void findbottom(node *p, node **bottom) { /* find a node with field bottom set at node p */ node *q; if (p->bottom) *bottom = p; else { q = p->next; while(!q->bottom && q != p) q = q->next; *bottom = q; } } /* findbottom */ boolean moresteps(node *a, node *b) { /* see if numsteps of node a exceeds those of node b */ long i; for (i = 0; i < endsite; i++) if (a->numsteps[i] > b->numsteps[i]) return true; return false; } /* moresteps */ boolean passdown(node *desc, node *parent, node *start, node *below, node *item, node *added, node *total, node *tempdsc, node *tempprt, boolean multf) { /* track down to node start to see if an ancestor branch can be collapsed */ node *temp; boolean done, allsame; done = (parent == start); while (!done) { desc = parent; findbottom(parent->back, &parent); if (multf && start == below && parent == below) parent = added; memcpy(tempdsc->base, tempprt->base, endsite*sizeof(long)); memcpy(tempdsc->numsteps, tempprt->numsteps, endsite*sizeof(long)); memcpy(tempdsc->oldbase, desc->base, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, desc->numsteps, endsite*sizeof(long)); memcpy(tempprt->base, parent->base, endsite*sizeof(long)); memcpy(tempprt->numsteps, parent->numsteps, endsite*sizeof(long)); memcpy(tempprt->numnuc, parent->numnuc, endsite*sizeof(nucarray)); tempprt->numdesc = parent->numdesc; multifillin(tempprt, tempdsc, 0); if (!allcommonbases(tempprt, parent, &allsame)) return false; else if (moresteps(tempprt, parent)) return false; else if (allsame) return true; if (parent == added) parent = below; done = (parent == start); if (done && ((start == item) || (!multf && start == below))) { memcpy(tempdsc->base, tempprt->base, endsite*sizeof(long)); memcpy(tempdsc->numsteps, tempprt->numsteps, endsite*sizeof(long)); memcpy(tempdsc->oldbase, start->base, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, start->numsteps, endsite*sizeof(long)); multifillin(added, tempdsc, 0); tempprt = added; } } temp = tempdsc; if (start == below || start == item) fillin(temp, tempprt, below->back); else fillin(temp, tempprt, added); return !moresteps(temp, total); } /* passdown */ boolean trycollapdesc(node *desc, node *parent, node *start, node *below, node *item, node *added, node *total, node *tempdsc, node *tempprt, boolean multf, long *zeros) { /* see if branch between nodes desc and parent can be collapsed */ boolean allsame; if (desc->numdesc == 1) return true; if (multf && start == below && parent == below) parent = added; memcpy(tempdsc->base, zeros, endsite*sizeof(long)); memcpy(tempdsc->numsteps, zeros, endsite*sizeof(long)); memcpy(tempdsc->oldbase, desc->base, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, desc->numsteps, endsite*sizeof(long)); memcpy(tempprt->base, parent->base, endsite*sizeof(long)); memcpy(tempprt->numsteps, parent->numsteps, endsite*sizeof(long)); memcpy(tempprt->numnuc, parent->numnuc, endsite*sizeof(nucarray)); tempprt->numdesc = parent->numdesc - 1; multifillin(tempprt, tempdsc, -1); tempprt->numdesc += desc->numdesc; collabranch(desc, tempdsc, tempprt); if (!allcommonbases(tempprt, parent, &allsame) || moresteps(tempprt, parent)) { if (parent != added) { desc->collapse = nocollap; parent->collapse = nocollap; } return false; } else if (allsame) { if (parent != added) { desc->collapse = tocollap; parent->collapse = tocollap; } return true; } if (parent == added) parent = below; if ((start == item && parent == item) || (!multf && start == below && parent == below)) { memcpy(tempdsc->base, tempprt->base, endsite*sizeof(long)); memcpy(tempdsc->numsteps, tempprt->numsteps, endsite*sizeof(long)); memcpy(tempdsc->oldbase, start->base, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, start->numsteps, endsite*sizeof(long)); memcpy(tempprt->base, added->base, endsite*sizeof(long)); memcpy(tempprt->numsteps, added->numsteps, endsite*sizeof(long)); memcpy(tempprt->numnuc, added->numnuc, endsite*sizeof(nucarray)); tempprt->numdesc = added->numdesc; multifillin(tempprt, tempdsc, 0); if (!allcommonbases(tempprt, added, &allsame)) return false; else if (moresteps(tempprt, added)) return false; else if (allsame) return true; } return passdown(desc, parent, start, below, item, added, total, tempdsc, tempprt, multf); } /* trycollapdesc */ void setbottom(node *p) { /* set field bottom at node p */ node *q; p->bottom = true; q = p->next; do { q->bottom = false; q = q->next; } while (q != p); } /* setbottom */ boolean zeroinsubtree(node *subtree, node *start, node *below, node *item, node *added, node *total, node *tempdsc, node *tempprt, boolean multf, node* root, long *zeros) { /* sees if subtree contains a zero length branch */ node *p; if (!subtree->tip) { setbottom(subtree); p = subtree->next; do { if (p->back && !p->back->tip && !((p->back->collapse == nocollap) && (subtree->collapse == nocollap)) && (subtree->numdesc != 1)) { if ((p->back->collapse == tocollap) && (subtree->collapse == tocollap) && multf && (subtree != below)) return true; /* when root->numdesc == 2 * there is no mandatory step at the root, * instead of checking at the root we check around it * we only need to check p because the first if * statement already gets rid of it for the subtree */ else if ((p->back->index != root->index || root->numdesc > 2) && trycollapdesc(p->back, subtree, start, below, item, added, total, tempdsc, tempprt, multf, zeros)) return true; else if ((p->back->index == root->index && root->numdesc == 2) && !(root->next->back->tip) && !(root->next->next->back->tip) && trycollapdesc(root->next->back, root->next->next->back, start, below, item,added, total, tempdsc, tempprt, multf, zeros)) return true; } p = p->next; } while (p != subtree); p = subtree->next; do { if (p->back && !p->back->tip) { if (zeroinsubtree(p->back, start, below, item, added, total, tempdsc, tempprt, multf, root, zeros)) return true; } p = p->next; } while (p != subtree); } return false; } /* zeroinsubtree */ boolean collapsible(node *item, node *below, node *temp, node *temp1, node *tempdsc, node *tempprt, node *added, node *total, boolean multf, node *root, long *zeros, pointarray treenode) { /* sees if any branch can be collapsed */ node *belowbk; boolean allsame; if (multf) { memcpy(tempdsc->base, item->base, endsite*sizeof(long)); memcpy(tempdsc->numsteps, item->numsteps, endsite*sizeof(long)); memcpy(tempdsc->oldbase, zeros, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, zeros, endsite*sizeof(long)); memcpy(added->base, below->base, endsite*sizeof(long)); memcpy(added->numsteps, below->numsteps, endsite*sizeof(long)); memcpy(added->numnuc, below->numnuc, endsite*sizeof(nucarray)); added->numdesc = below->numdesc + 1; multifillin(added, tempdsc, 1); } else { fillin(added, item, below); added->numdesc = 2; } fillin(total, added, below->back); clearbottom(treenode); if (below->back) { if (zeroinsubtree(below->back, below->back, below, item, added, total, tempdsc, tempprt, multf, root, zeros)) return true; } if (multf) { if (zeroinsubtree(below, below, below, item, added, total, tempdsc, tempprt, multf, root, zeros)) return true; } else if (!below->tip) { if (zeroinsubtree(below, below, below, item, added, total, tempdsc, tempprt, multf, root, zeros)) return true; } if (!item->tip) { if (zeroinsubtree(item, item, below, item, added, total, tempdsc, tempprt, multf, root, zeros)) return true; } if (multf && below->back && !below->back->tip) { memcpy(tempdsc->base, zeros, endsite*sizeof(long)); memcpy(tempdsc->numsteps, zeros, endsite*sizeof(long)); memcpy(tempdsc->oldbase, added->base, endsite*sizeof(long)); memcpy(tempdsc->oldnumsteps, added->numsteps, endsite*sizeof(long)); if (below->back == treenode[below->back->index - 1]) belowbk = below->back->next; else belowbk = treenode[below->back->index - 1]; memcpy(tempprt->base, belowbk->base, endsite*sizeof(long)); memcpy(tempprt->numsteps, belowbk->numsteps, endsite*sizeof(long)); memcpy(tempprt->numnuc, belowbk->numnuc, endsite*sizeof(nucarray)); tempprt->numdesc = belowbk->numdesc - 1; multifillin(tempprt, tempdsc, -1); tempprt->numdesc += added->numdesc; collabranch(added, tempdsc, tempprt); if (!allcommonbases(tempprt, belowbk, &allsame)) return false; else if (allsame && !moresteps(tempprt, belowbk)) return true; else if (belowbk->back) { fillin(temp, tempprt, belowbk->back); fillin(temp1, belowbk, belowbk->back); return !moresteps(temp, temp1); } } return false; } /* collapsible */ void replaceback(node **oldback, node *item, node *forknode, node **grbg, long *zeros) { /* replaces back node of item with another */ node *p; p = forknode; while (p->next->back != item) p = p->next; *oldback = p->next; gnutreenode(grbg, &p->next, forknode->index, endsite, zeros); p->next->next = (*oldback)->next; p->next->back = (*oldback)->back; p->next->back->back = p->next; (*oldback)->next = (*oldback)->back = NULL; } /* replaceback */ void putback(node *oldback, node *item, node *forknode, node **grbg) { /* restores node to back of item */ node *p, *q; p = forknode; while (p->next != item->back) p = p->next; q = p->next; oldback->next = p->next->next; p->next = oldback; oldback->back = item; item->back = oldback; oldback->index = forknode->index; chuck(grbg, q); } /* putback */ void savelocrearr(node *item, node *forknode, node *below, node *tmp, node *tmp1, node *tmp2, node *tmp3, node *tmprm, node *tmpadd, node **root, long maxtrees, long *nextree, boolean multf, boolean bestever, boolean *saved, long *place, bestelm *bestrees, pointarray treenode, node **grbg, long *zeros) { /* saves tied or better trees during local rearrangements by removing item from forknode and adding to below */ node *other, *otherback = NULL, *oldfork, *nufork, *oldback; long pos; boolean found, collapse; if (forknode->numdesc == 2) { findbelow(&other, item, forknode); otherback = other->back; oldback = NULL; } else { other = NULL; replaceback(&oldback, item, forknode, grbg, zeros); } re_move(item, &oldfork, root, false, treenode, grbg, zeros); if (!multf) getnufork(&nufork, grbg, treenode, zeros); else nufork = NULL; addnsave(below, item, nufork, root, grbg, multf, treenode, place, zeros); pos = 0; findtree(&found, &pos, *nextree, place, bestrees); if (other) { add(other, item, oldfork, root, false, treenode, grbg, zeros); if (otherback->back != other) flipnodes(item, other); } else add(forknode, item, NULL, root, false, treenode, grbg, zeros); *saved = false; if (found) { if (oldback) putback(oldback, item, forknode, grbg); } else { if (oldback) chuck(grbg, oldback); re_move(item, &oldfork, root, true, treenode, grbg, zeros); collapse = collapsible(item, below, tmp, tmp1, tmp2, tmp3, tmprm, tmpadd, multf, *root, zeros, treenode); if (!collapse) { if (bestever) addbestever(&pos, nextree, maxtrees, collapse, place, bestrees); else addtiedtree(pos, nextree, maxtrees, collapse, place, bestrees); } if (other) add(other, item, oldfork, root, true, treenode, grbg, zeros); else add(forknode, item, NULL, root, true, treenode, grbg, zeros); *saved = !collapse; } } /* savelocrearr */ void clearvisited(pointarray treenode) { /* clears boolean visited at a node */ long i; node *p; for (i = 0; i < nonodes; i++) { treenode[i]->visited = false; if (!treenode[i]->tip) { p = treenode[i]->next; while (p != treenode[i]) { p->visited = false; p = p->next; } } } } /* clearvisited */ /*void hyprint(long b1, long b2, struct LOC_hyptrav *htrav, pointarray treenode, Char *basechar) { * print out states in sites b1 through b2 at node * long i, j, k, n; boolean dot; bases b; if (htrav->bottom) { if (!outgropt) fprintf(outfile, " "); else fprintf(outfile, "root "); } else fprintf(outfile, "%4ld ", htrav->r->back->index - spp); if (htrav->r->tip) { for (i = 0; i < nmlngth; i++) putc(nayme[htrav->r->index - 1][i], outfile); } else fprintf(outfile, "%4ld ", htrav->r->index - spp); if (htrav->bottom) fprintf(outfile, " "); else if (htrav->nonzero) fprintf(outfile, " yes "); else if (htrav->maybe) fprintf(outfile, " maybe "); else fprintf(outfile, " no "); for (i = b1; i <= b2; i++) { j = location[ally[i - 1] - 1]; htrav->tempset = htrav->r->base[j - 1]; htrav->anc = htrav->hypset[j - 1]; if (!htrav->bottom) htrav->anc = treenode[htrav->r->back->index - 1]->base[j - 1]; dot = dotdiff && (htrav->tempset == htrav->anc && !htrav->bottom); if (dot) putc('.', outfile); else if (htrav->tempset == (1 << A)) putc('A', outfile); else if (htrav->tempset == (1 << C)) putc('C', outfile); else if (htrav->tempset == (1 << G)) putc('G', outfile); else if (htrav->tempset == (1 << T)) putc('T', outfile); else if (htrav->tempset == (1 << O)) putc('-', outfile); else { k = 1; n = 0; for (b = A; b <= O; b = b + 1) { if (((1 << b) & htrav->tempset) != 0) n += k; k += k; } putc(basechar[n - 1], outfile); } if (i % 10 == 0) putc(' ', outfile); } putc('\n', outfile); } * hyprint */ void gnubase(gbases **p, gbases **garbage, long endsite) { /* this and the following are do-it-yourself garbage collectors. Make a new node or pull one off the garbage list */ if (*garbage != NULL) { *p = *garbage; *garbage = (*garbage)->next; } else { *p = (gbases *)Malloc(sizeof(gbases)); (*p)->base = (baseptr)Malloc(endsite*sizeof(long)); } (*p)->next = NULL; } /* gnubase */ void chuckbase(gbases *p, gbases **garbage) { /* collect garbage on p -- put it on front of garbage list */ p->next = *garbage; *garbage = p; } /* chuckbase */ /*void hyptrav(node *r_, long *hypset_, long b1, long b2, boolean bottom_, pointarray treenode, gbases **garbage, Char *basechar) { * compute, print out states at one interior node * struct LOC_hyptrav Vars; long i, j, k; long largest; gbases *ancset; nucarray *tempnuc; node *p, *q; Vars.bottom = bottom_; Vars.r = r_; Vars.hypset = hypset_; gnubase(&ancset, garbage, endsite); tempnuc = (nucarray *)Malloc(endsite*sizeof(nucarray)); Vars.maybe = false; Vars.nonzero = false; if (!Vars.r->tip) zeronumnuc(Vars.r, endsite); for (i = b1 - 1; i < b2; i++) { j = location[ally[i] - 1]; Vars.anc = Vars.hypset[j - 1]; if (!Vars.r->tip) { p = Vars.r->next; for (k = (long)A; k <= (long)O; k++) if (Vars.anc & (1 << k)) Vars.r->numnuc[j - 1][k]++; do { for (k = (long)A; k <= (long)O; k++) if (p->back->base[j - 1] & (1 << k)) Vars.r->numnuc[j - 1][k]++; p = p->next; } while (p != Vars.r); largest = getlargest(Vars.r->numnuc[j - 1]); Vars.tempset = 0; for (k = (long)A; k <= (long)O; k++) { if (Vars.r->numnuc[j - 1][k] == largest) Vars.tempset |= (1 << k); } Vars.r->base[j - 1] = Vars.tempset; } if (!Vars.bottom) Vars.anc = treenode[Vars.r->back->index - 1]->base[j - 1]; Vars.nonzero = (Vars.nonzero || (Vars.r->base[j - 1] & Vars.anc) == 0); Vars.maybe = (Vars.maybe || Vars.r->base[j - 1] != Vars.anc); } hyprint(b1, b2, &Vars, treenode, basechar); Vars.bottom = false; if (!Vars.r->tip) { memcpy(tempnuc, Vars.r->numnuc, endsite*sizeof(nucarray)); q = Vars.r->next; do { memcpy(Vars.r->numnuc, tempnuc, endsite*sizeof(nucarray)); for (i = b1 - 1; i < b2; i++) { j = location[ally[i] - 1]; for (k = (long)A; k <= (long)O; k++) if (q->back->base[j - 1] & (1 << k)) Vars.r->numnuc[j - 1][k]--; largest = getlargest(Vars.r->numnuc[j - 1]); ancset->base[j - 1] = 0; for (k = (long)A; k <= (long)O; k++) if (Vars.r->numnuc[j - 1][k] == largest) ancset->base[j - 1] |= (1 << k); if (!Vars.bottom) Vars.anc = ancset->base[j - 1]; } hyptrav(q->back, ancset->base, b1, b2, Vars.bottom, treenode, garbage, basechar); q = q->next; } while (q != Vars.r); } chuckbase(ancset, garbage); } * hyptrav * void hypstates(long chars, node *root, pointarray treenode, gbases **garbage, Char *basechar) { * fill in and describe states at interior nodes * * used in dnacomp, dnapars, & dnapenny * long i, n; baseptr nothing; fprintf(outfile, "\nFrom To Any Steps? State at upper node\n"); fprintf(outfile, " "); if (dotdiff) fprintf(outfile, " ( . means same as in the node below it on tree)\n"); nothing = (baseptr)Malloc(endsite*sizeof(long)); for (i = 0; i < endsite; i++) nothing[i] = 0; for (i = 1; i <= ((chars - 1) / 40 + 1); i++) { putc('\n', outfile); n = i * 40; if (n > chars) n = chars; hyptrav(root, nothing, i * 40 - 39, n, true, treenode, garbage, basechar); } free(nothing); } * hypstates */ void initbranchlen(node *p) { node *q; p->v = 0.0; if (p->back) p->back->v = 0.0; if (p->tip) return; q = p->next; while (q != p) { initbranchlen(q->back); q = q->next; } q = p->next; while (q != p) { q->v = 0.0; q = q->next; } } /* initbranchlen */ void initmin(node *p, long sitei, boolean internal) { long i; if (internal) { for (i = (long)A; i <= (long)O; i++) { p->cumlengths[i] = 0; p->numreconst[i] = 1; } } else { for (i = (long)A; i <= (long)O; i++) { if (p->base[sitei - 1] & (1 << i)) { p->cumlengths[i] = 0; p->numreconst[i] = 1; } else { p->cumlengths[i] = -1; p->numreconst[i] = 0; } } } } /* initmin */ void initbase(node *p, long sitei) { /* traverse tree to initialize base at internal nodes */ node *q; long i, largest; if (p->tip) return; q = p->next; while (q != p) { if (q->back) { memcpy(q->numnuc, p->numnuc, endsite*sizeof(nucarray)); for (i = (long)A; i <= (long)O; i++) { if (q->back->base[sitei - 1] & (1 << i)) q->numnuc[sitei - 1][i]--; } if (p->back) { for (i = (long)A; i <= (long)O; i++) { if (p->back->base[sitei - 1] & (1 << i)) q->numnuc[sitei - 1][i]++; } } largest = getlargest(q->numnuc[sitei - 1]); q->base[sitei - 1] = 0; for (i = (long)A; i <= (long)O; i++) { if (q->numnuc[sitei - 1][i] == largest) q->base[sitei - 1] |= (1 << i); } } q = q->next; } q = p->next; while (q != p) { initbase(q->back, sitei); q = q->next; } } /* initbase */ void inittreetrav(node *p, long sitei) { /* traverse tree to clear boolean initialized and set up base */ node *q; if (p->tip) { initmin(p, sitei, false); p->initialized = true; return; } q = p->next; while (q != p) { inittreetrav(q->back, sitei); q = q->next; } initmin(p, sitei, true); p->initialized = false; q = p->next; while (q != p) { initmin(q, sitei, true); q->initialized = false; q = q->next; } } /* inittreetrav */ void compmin(node *p, node *desc) { /* computes minimum lengths up to p */ long i, j, minn, cost, desclen, descrecon=0, maxx; maxx = 10 * spp; for (i = (long)A; i <= (long)O; i++) { minn = maxx; for (j = (long)A; j <= (long)O; j++) { if (transvp) { if ( ( ((i == (long)A) || (i == (long)G)) && ((j == (long)A) || (j == (long)G)) ) || ( ((j == (long)C) || (j == (long)T)) && ((i == (long)C) || (i == (long)T)) ) ) cost = 0; else cost = 1; } else { if (i == j) cost = 0; else cost = 1; } if (desc->cumlengths[j] == -1) { desclen = maxx; } else { desclen = desc->cumlengths[j]; } if (minn > cost + desclen) { minn = cost + desclen; descrecon = 0; } if (minn == cost + desclen) { descrecon += desc->numreconst[j]; } } p->cumlengths[i] += minn; p->numreconst[i] *= descrecon; } p->initialized = true; } /* compmin */ void minpostorder(node *p, pointarray treenode) { /* traverses an n-ary tree, computing minimum steps at each node */ node *q; if (p->tip) { return; } q = p->next; while (q != p) { if (q->back) minpostorder(q->back, treenode); q = q->next; } if (!p->initialized) { q = p->next; while (q != p) { if (q->back) compmin(p, q->back); q = q->next; } } } /* minpostorder */ void branchlength(node *subtr1, node *subtr2, double *brlen, pointarray treenode) { /* computes a branch length between two subtrees for a given site */ long i, j, minn, cost, nom, denom; node *temp; if (subtr1->tip) { temp = subtr1; subtr1 = subtr2; subtr2 = temp; } if (subtr1->index == outgrno) { temp = subtr1; subtr1 = subtr2; subtr2 = temp; } minpostorder(subtr1, treenode); minpostorder(subtr2, treenode); minn = 10 * spp; nom = 0; denom = 0; for (i = (long)A; i <= (long)O; i++) { for (j = (long)A; j <= (long)O; j++) { if (transvp) { if ( ( ((i == (long)A) || (i == (long)G)) && ((j == (long)A) || (j == (long)G)) ) || ( ((j == (long)C) || (j == (long)T)) && ((i == (long)C) || (i == (long)T)) ) ) cost = 0; else cost = 1; } else { if (i == j) cost = 0; else cost = 1; } if (subtr1->cumlengths[i] != -1 && (subtr2->cumlengths[j] != -1)) { if (subtr1->cumlengths[i] + cost + subtr2->cumlengths[j] < minn) { minn = subtr1->cumlengths[i] + cost + subtr2->cumlengths[j]; nom = 0; denom = 0; } if (subtr1->cumlengths[i] + cost + subtr2->cumlengths[j] == minn) { nom += subtr1->numreconst[i] * subtr2->numreconst[j] * cost; denom += subtr1->numreconst[i] * subtr2->numreconst[j]; } } } } *brlen = (double)nom/(double)denom; } /* branchlength */ /*void printbranchlengths(node *p) { node *q; long i; if (p->tip) return; q = p->next; do { fprintf(outfile, "%6ld ",q->index - spp); if (q->back->tip) { for (i = 0; i < nmlngth; i++) putc(nayme[q->back->index - 1][i], outfile); } else fprintf(outfile, "%6ld ", q->back->index - spp); fprintf(outfile, " %f\n",q->v); if (q->back) printbranchlengths(q->back); q = q->next; } while (q != p); } * printbranchlengths */ void branchlentrav(node *p, node *root, long sitei, long chars, double *brlen, pointarray treenode) { /* traverses the tree computing tree length at each branch */ node *q; if (p->tip) return; if (p->index == outgrno) p = p->back; q = p->next; do { if (q->back) { branchlength(q, q->back, brlen, treenode); q->v += ((weight[sitei - 1] / 10.0) * (*brlen)/chars); q->back->v += ((weight[sitei - 1] / 10.0) * (*brlen)/chars); if (!q->back->tip) branchlentrav(q->back, root, sitei, chars, brlen, treenode); } q = q->next; } while (q != p); } /* branchlentrav */ void treelength(node *root, long chars, pointarray treenode) { /* calls branchlentrav at each site */ long sitei; double trlen; initbranchlen(root); for (sitei = 1; sitei <= endsite; sitei++) { trlen = 0.0; initbase(root, sitei); inittreetrav(root, sitei); branchlentrav(root, root, sitei, chars, &trlen, treenode); } } /* treelength */ void coordinates(node *p, long *tipy, double f, long *fartemp) { /* establishes coordinates of nodes for display without lengths */ node *q, *first, *last; node *mid1 = NULL, *mid2 = NULL; long numbranches, numb2; if (p->tip) { p->xcoord = 0; p->ycoord = *tipy; p->ymin = *tipy; p->ymax = *tipy; (*tipy) += down; return; } numbranches = 0; q = p->next; do { coordinates(q->back, tipy, f, fartemp); numbranches += 1; q = q->next; } while (p != q); first = p->next->back; q = p->next; while (q->next != p) q = q->next; last = q->back; numb2 = 1; q = p->next; while (q != p) { if (numb2 == (long)(numbranches + 1)/2) mid1 = q->back; if (numb2 == (long)(numbranches/2 + 1)) mid2 = q->back; numb2 += 1; q = q->next; } p->xcoord = (long)((double)(last->ymax - first->ymin) * f); p->ycoord = (long)((mid1->ycoord + mid2->ycoord) / 2); p->ymin = first->ymin; p->ymax = last->ymax; if (p->xcoord > *fartemp) *fartemp = p->xcoord; } /* coordinates */ /*void drawline(long i, double scale, node *root) { * draws one row of the tree diagram by moving up tree * node *p, *q, *r, *first =NULL, *last =NULL; long n, j; boolean extra, done, noplus; p = root; q = root; extra = false; noplus = false; if (i == (long)p->ycoord && p == root) { if (p->index - spp >= 10) fprintf(outfile, " %2ld", p->index - spp); else fprintf(outfile, " %ld", p->index - spp); extra = true; noplus = true; } else fprintf(outfile, " "); do { if (!p->tip) { r = p->next; done = false; do { if (i >= r->back->ymin && i <= r->back->ymax) { q = r->back; done = true; } r = r->next; } while (!(done || r == p)); first = p->next->back; r = p->next; while (r->next != p) r = r->next; last = r->back; } done = (p == q); n = (long)(scale * (p->xcoord - q->xcoord) + 0.5); if (n < 3 && !q->tip) n = 3; if (extra) { n--; extra = false; } if ((long)q->ycoord == i && !done) { if (noplus) { putc('-', outfile); noplus = false; } else putc('+', outfile); if (!q->tip) { for (j = 1; j <= n - 2; j++) putc('-', outfile); if (q->index - spp >= 10) fprintf(outfile, "%2ld", q->index - spp); else fprintf(outfile, "-%ld", q->index - spp); extra = true; noplus = true; } else { for (j = 1; j < n; j++) putc('-', outfile); } } else if (!p->tip) { if ((long)last->ycoord > i && (long)first->ycoord < i && i != (long)p->ycoord) { putc('!', outfile); for (j = 1; j < n; j++) putc(' ', outfile); } else { for (j = 1; j <= n; j++) putc(' ', outfile); } noplus = false; } else { for (j = 1; j <= n; j++) putc(' ', outfile); noplus = false; } if (p != q) p = q; } while (!done); if ((long)p->ycoord == i && p->tip) { for (j = 0; j < nmlngth; j++) putc(nayme[p->index - 1][j], outfile); } putc('\n', outfile); } * drawline * void printree(node *root, double f) { * prints out diagram of the tree * * used in dnacomp, dnapars, & dnapenny * long i, tipy, dummy; double scale; putc('\n', outfile); if (!treeprint) return; putc('\n', outfile); tipy = 1; dummy = 0; coordinates(root, &tipy, f, &dummy); scale = 1.5; putc('\n', outfile); for (i = 1; i <= (tipy - down); i++) drawline(i, scale, root); fprintf(outfile, "\n remember:"); if (outgropt) fprintf(outfile, " (although rooted by outgroup)"); fprintf(outfile, " this is an unrooted tree!\n\n"); } * printree */ void writesteps(long chars, boolean weights, steptr oldweight, node *root) { /* used in dnacomp, dnapars, & dnapenny */ long i, j, k, l; putc('\n', outfile); if (weights) fprintf(outfile, "weighted "); fprintf(outfile, "steps in each site:\n"); fprintf(outfile, " "); for (i = 0; i <= 9; i++) fprintf(outfile, "%4ld", i); fprintf(outfile, "\n *------------------------------------"); fprintf(outfile, "-----\n"); for (i = 0; i <= (chars / 10); i++) { fprintf(outfile, "%5ld", i * 10); putc('|', outfile); for (j = 0; j <= 9; j++) { k = i * 10 + j; if (k == 0 || k > chars) fprintf(outfile, " "); else { l = location[ally[k - 1] - 1]; if (oldweight[k - 1] > 0) fprintf(outfile, "%4ld", oldweight[k - 1] * (root->numsteps[l - 1] / weight[l - 1])); else fprintf(outfile, " 0"); } } putc('\n', outfile); } } /* writesteps */ void treeout(node *p, long nextree, long *col, node *root) { /* write out file with representation of final tree */ /* used in dnacomp, dnamove, dnapars, & dnapenny */ node *q; long i, n; Char c; if (p->tip) { n = strlen(nayme[p->index - 1]); /*for (i = 1; i <= nmlngth; i++) { if (nayme[p->index - 1][i - 1] != ' ') n = i; }*/ for (i = 0; i < n; i++) { c = nayme[p->index - 1][i]; /*if (c == ' ') c = '_';*/ putc(c, outtree); } //*col += n; } else { putc('(', outtree); //(*col)++; q = p->next; while (q != p) { treeout(q->back, nextree, col, root); q = q->next; if (q == p) break; putc(',', outtree); /*(*col)++; if (*col > 60) { putc('\n', outtree); *col = 0; }*/ } putc(')', outtree); //(*col)++; } if (p != root) return; if (nextree > 2) fprintf(outtree, "[%6.4f];\n", 1.0 / (nextree - 1)); else fprintf(outtree, ";\n"); } /* treeout */ void treeout3(node *p, long nextree, long *col, node *root) { /* write out file with representation of final tree */ /* used in dnapars -- writes branch lengths */ node *q; long i, n, w; double x; Char c; if (p->tip) { n = 0; /*for (i = 1; i <= nmlngth; i++) { if (nayme[p->index - 1][i - 1] != ' ') n = i; }*/ n = strlen(nayme[p->index - 1]); for (i = 0; i < n; i++) { c = nayme[p->index - 1][i]; /*if (c == ' ') c = '_';*/ putc(c, outtree); } //*col += n; } else { putc('(', outtree); //(*col)++; q = p->next; while (q != p) { treeout3(q->back, nextree, col, root); q = q->next; if (q == p) break; putc(',', outtree); /*(*col)++; if (*col > 60) { putc('\n', outtree); *col = 0; }*/ } putc(')', outtree); //(*col)++; } x = p->v; if (x > 0.0) w = (long)(0.43429448222 * log(x)); else if (x == 0.0) w = 0; else w = (long)(0.43429448222 * log(-x)) + 1; if (w < 0) w = 0; if (p != root) { fprintf(outtree, ":%*.5f", (int)(w + 7), x); //*col += w + 8; } if (p != root) return; if (nextree > 2) fprintf(outtree, "[%6.4f];\n", 1.0 / (nextree - 1)); else fprintf(outtree, ";\n"); } /* treeout3 */ /* FIXME curtree should probably be passed by reference * void drawline2(long i, double scale, tree curtree) { fdrawline2(outfile, i, scale, &curtree); }* void fdrawline2(FILE *fp, long i, double scale, tree *curtree) { * draws one row of the tree diagram by moving up tree * * used in dnaml, proml, & restml * node *p, *q; long n, j; boolean extra; node *r, *first =NULL, *last =NULL; boolean done; p = curtree->start; q = curtree->start; extra = false; if (i == (long)p->ycoord && p == curtree->start) { if (p->index - spp >= 10) fprintf(fp, " %2ld", p->index - spp); else fprintf(fp, " %ld", p->index - spp); extra = true; } else fprintf(fp, " "); do { if (!p->tip) { r = p->next; done = false; do { if (i >= r->back->ymin && i <= r->back->ymax) { q = r->back; done = true; } r = r->next; } while (!(done || (p != curtree->start && r == p) || (p == curtree->start && r == p->next))); first = p->next->back; r = p; while (r->next != p) r = r->next; last = r->back; if (p == curtree->start) last = p->back; } done = (p->tip || p == q); n = (long)(scale * (q->xcoord - p->xcoord) + 0.5); if (n < 3 && !q->tip) n = 3; if (extra) { n--; extra = false; } if ((long)q->ycoord == i && !done) { if ((long)p->ycoord != (long)q->ycoord) putc('+', fp); else putc('-', fp); if (!q->tip) { for (j = 1; j <= n - 2; j++) putc('-', fp); if (q->index - spp >= 10) fprintf(fp, "%2ld", q->index - spp); else fprintf(fp, "-%ld", q->index - spp); extra = true; } else { for (j = 1; j < n; j++) putc('-', fp); } } else if (!p->tip) { if ((long)last->ycoord > i && (long)first->ycoord < i && (i != (long)p->ycoord || p == curtree->start)) { putc('|', fp); for (j = 1; j < n; j++) putc(' ', fp); } else { for (j = 1; j <= n; j++) putc(' ', fp); } } else { for (j = 1; j <= n; j++) putc(' ', fp); } if (q != p) p = q; } while (!done); if ((long)p->ycoord == i && p->tip) { for (j = 0; j < nmlngth; j++) putc(nayme[p->index-1][j], fp); } putc('\n', fp); } * drawline2 * void drawline3(long i, double scale, node *start) { * draws one row of the tree diagram by moving up tree * * used in dnapars * node *p, *q; long n, j; boolean extra; node *r, *first =NULL, *last =NULL; boolean done; p = start; q = start; extra = false; if (i == (long)p->ycoord) { if (p->index - spp >= 10) fprintf(outfile, " %2ld", p->index - spp); else fprintf(outfile, " %ld", p->index - spp); extra = true; } else fprintf(outfile, " "); do { if (!p->tip) { r = p->next; done = false; do { if (i >= r->back->ymin && i <= r->back->ymax) { q = r->back; done = true; } r = r->next; } while (!(done || (r == p))); first = p->next->back; r = p; while (r->next != p) r = r->next; last = r->back; } done = (p->tip || p == q); n = (long)(scale * (q->xcoord - p->xcoord) + 0.5); if (n < 3 && !q->tip) n = 3; if (extra) { n--; extra = false; } if ((long)q->ycoord == i && !done) { if ((long)p->ycoord != (long)q->ycoord) putc('+', outfile); else putc('-', outfile); if (!q->tip) { for (j = 1; j <= n - 2; j++) putc('-', outfile); if (q->index - spp >= 10) fprintf(outfile, "%2ld", q->index - spp); else fprintf(outfile, "-%ld", q->index - spp); extra = true; } else { for (j = 1; j < n; j++) putc('-', outfile); } } else if (!p->tip) { if ((long)last->ycoord > i && (long)first->ycoord < i && (i != (long)p->ycoord || p == start)) { putc('|', outfile); for (j = 1; j < n; j++) putc(' ', outfile); } else { for (j = 1; j <= n; j++) putc(' ', outfile); } } else { for (j = 1; j <= n; j++) putc(' ', outfile); } if (q != p) p = q; } while (!done); if ((long)p->ycoord == i && p->tip) { for (j = 0; j < nmlngth; j++) putc(nayme[p->index-1][j], outfile); } putc('\n', outfile); } * drawline3 */ void copynode(node *c, node *d, long categs) { long i, j; for (i = 0; i < endsite; i++) for (j = 0; j < categs; j++) memcpy(d->x[i][j], c->x[i][j], sizeof(sitelike)); memcpy(d->underflows,c->underflows,sizeof(double) * endsite); d->tyme = c->tyme; d->v = c->v; d->xcoord = c->xcoord; d->ycoord = c->ycoord; d->ymin = c->ymin; d->ymax = c->ymax; d->iter = c->iter; /* iter used in dnaml only */ d->haslength = c->haslength; /* haslength used in dnamlk only */ d->initialized = c->initialized; /* initialized used in dnamlk only */ } /* copynode */ void prot_copynode(node *c, node *d, long categs) { /* a version of copynode for proml */ long i, j; for (i = 0; i < endsite; i++) for (j = 0; j < categs; j++) memcpy(d->protx[i][j], c->protx[i][j], sizeof(psitelike)); memcpy(d->underflows,c->underflows,sizeof(double) * endsite); d->tyme = c->tyme; d->v = c->v; d->xcoord = c->xcoord; d->ycoord = c->ycoord; d->ymin = c->ymin; d->ymax = c->ymax; d->iter = c->iter; /* iter used in dnaml only */ d->haslength = c->haslength; /* haslength used in dnamlk only */ d->initialized = c->initialized; /* initialized used in dnamlk only */ } /* prot_copynode */ void copy_(tree *a, tree *b, long nonodes, long categs) { /* used in dnamlk */ long i; node *p, *q, *r, *s, *t; for (i = 0; i < spp; i++) { copynode(a->nodep[i], b->nodep[i], categs); if (a->nodep[i]->back) { if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1]) b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]; else if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1]->next) b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next; else b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next->next; } else b->nodep[i]->back = NULL; } for (i = spp; i < nonodes; i++) { if (a->nodep[i]) { p = a->nodep[i]; q = b->nodep[i]; r = p; do { copynode(p, q, categs); if (p->back) { s = a->nodep[p->back->index - 1]; t = b->nodep[p->back->index - 1]; if (s->tip) { if(p->back == s) q->back = t; } else { do { if (p->back == s) q->back = t; s = s->next; t = t->next; } while (s != a->nodep[p->back->index - 1]); } } else q->back = NULL; p = p->next; q = q->next; } while (p != r); } } b->likelihood = a->likelihood; b->start = a->start; /* start used in dnaml only */ b->root = a->root; /* root used in dnamlk only */ } /* copy_ */ void prot_copy_(tree *a, tree *b, long nonodes, long categs) { /* used in promlk */ /* identical to copy_() except for calls to prot_copynode rather */ /* than copynode. */ long i; node *p, *q, *r, *s, *t; for (i = 0; i < spp; i++) { prot_copynode(a->nodep[i], b->nodep[i], categs); if (a->nodep[i]->back) { if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1]) b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]; else if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1]->next ) b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next; else b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next->next; } else b->nodep[i]->back = NULL; } for (i = spp; i < nonodes; i++) { if (a->nodep[i]) { p = a->nodep[i]; q = b->nodep[i]; r = p; do { prot_copynode(p, q, categs); if (p->back) { s = a->nodep[p->back->index - 1]; t = b->nodep[p->back->index - 1]; if (s->tip) { if(p->back == s) q->back = t; } else { do { if (p->back == s) q->back = t; s = s->next; t = t->next; } while (s != a->nodep[p->back->index - 1]); } } else q->back = NULL; p = p->next; q = q->next; } while (p != r); } } b->likelihood = a->likelihood; b->start = a->start; /* start used in dnaml only */ b->root = a->root; /* root used in dnamlk only */ } /* prot_copy_ */ void standev(long chars, long numtrees, long minwhich, double minsteps, double *nsteps, long **fsteps, longer seed) { /* do paired sites test (KHT or SH test) on user-defined trees */ /* used in dnapars & protpars */ long i, j, k; double wt, sumw, sum, sum2, sd; double temp; double **covar, *P, *f, *r; #define SAMPLES 1000 if (numtrees == 2) { fprintf(outfile, "Kishino-Hasegawa-Templeton test\n\n"); fprintf(outfile, "Tree Steps Diff Steps Its S.D."); fprintf(outfile, " Significantly worse?\n\n"); which = 1; while (which <= numtrees) { fprintf(outfile, "%3ld%10.1f", which, nsteps[which - 1] / 10); if (minwhich == which) fprintf(outfile, " <------ best\n"); else { sumw = 0.0; sum = 0.0; sum2 = 0.0; for (i = 0; i < endsite; i++) { if (weight[i] > 0) { wt = weight[i] / 10.0; sumw += wt; temp = (fsteps[which - 1][i] - fsteps[minwhich - 1][i]) / 10.0; sum += wt * temp; sum2 += wt * temp * temp; } } sd = sqrt(sumw / (sumw - 1.0) * (sum2 - sum * sum / sumw)); fprintf(outfile, "%10.1f%12.4f", (nsteps[which - 1] - minsteps) / 10, sd); if ((sum > 0.0) && (sum > 1.95996 * sd)) fprintf(outfile, " Yes\n"); else fprintf(outfile, " No\n"); } which++; } fprintf(outfile, "\n\n"); } else { /* Shimodaira-Hasegawa test using normal approximation */ if(numtrees > MAXSHIMOTREES){ fprintf(outfile, "Shimodaira-Hasegawa test on first %d of %ld trees\n\n" , MAXSHIMOTREES, numtrees); numtrees = MAXSHIMOTREES; } else { fprintf(outfile, "Shimodaira-Hasegawa test\n\n"); } covar = (double **)Malloc(numtrees*sizeof(double *)); sumw = 0.0; for (i = 0; i < endsite; i++) sumw += weight[i] / 10.0; for (i = 0; i < numtrees; i++) covar[i] = (double *)Malloc(numtrees*sizeof(double)); for (i = 0; i < numtrees; i++) { /* compute covariances of trees */ sum = nsteps[i]/(10.0*sumw); for (j = 0; j <=i; j++) { sum2 = nsteps[j]/(10.0*sumw); temp = 0.0; for (k = 0; k < endsite; k++) { if (weight[k] > 0) { wt = weight[k]/10.0; temp = temp + wt*(fsteps[i][k]/10.0-sum) *(fsteps[j][k]/10.0-sum2); } } covar[i][j] = temp; if (i != j) covar[j][i] = temp; } } for (i = 0; i < numtrees; i++) { /* in-place Cholesky decomposition of trees x trees covariance matrix */ sum = 0.0; for (j = 0; j <= i-1; j++) sum = sum + covar[i][j] * covar[i][j]; if (covar[i][i] <= sum) temp = 0.0; else temp = sqrt(covar[i][i] - sum); covar[i][i] = temp; for (j = i+1; j < numtrees; j++) { sum = 0.0; for (k = 0; k < i; k++) sum = sum + covar[i][k] * covar[j][k]; if (fabs(temp) < 1.0E-12) covar[j][i] = 0.0; else covar[j][i] = (covar[j][i] - sum)/temp; } } f = (double *)Malloc(numtrees*sizeof(double)); /* resampled sums */ P = (double *)Malloc(numtrees*sizeof(double)); /* vector of P's of trees */ r = (double *)Malloc(numtrees*sizeof(double)); /* store Normal variates */ for (i = 0; i < numtrees; i++) P[i] = 0.0; sum2 = nsteps[0]/10.0; /* sum2 will be smallest # of steps */ for (i = 1; i < numtrees; i++) if (sum2 > nsteps[i]/10.0) sum2 = nsteps[i]/10.0; for (i = 1; i <= SAMPLES; i++) { /* loop over resampled trees */ for (j = 0; j < numtrees; j++) /* draw Normal variates */ r[j] = normrand(seed); for (j = 0; j < numtrees; j++) { /* compute vectors */ sum = 0.0; for (k = 0; k <= j; k++) sum += covar[j][k]*r[k]; f[j] = sum; } sum = f[1]; for (j = 1; j < numtrees; j++) /* get min of vector */ if (f[j] < sum) sum = f[j]; for (j = 0; j < numtrees; j++) /* accumulate P's */ if (nsteps[j]/10.0-sum2 <= f[j] - sum) P[j] += 1.0/SAMPLES; } fprintf(outfile, "Tree Steps Diff Steps P value"); fprintf(outfile, " Significantly worse?\n\n"); for (i = 0; i < numtrees; i++) { fprintf(outfile, "%3ld%10.1f", i+1, nsteps[i]/10); if ((minwhich-1) == i) fprintf(outfile, " <------ best\n"); else { fprintf(outfile, " %9.1f %10.3f", nsteps[i]/10.0-sum2, P[i]); if (P[i] < 0.05) fprintf(outfile, " Yes\n"); else fprintf(outfile, " No\n"); } } fprintf(outfile, "\n"); free(P); /* free the variables we Malloc'ed */ free(f); free(r); for (i = 0; i < numtrees; i++) free(covar[i]); free(covar); } } /* standev */ void standev2(long numtrees, long maxwhich, long a, long b, double maxlogl, double *l0gl, double **l0gf, steptr aliasweight, longer seed) { /* do paired sites test (KHT or SH) for user-defined trees */ /* used in dnaml, dnamlk, proml, promlk, and restml */ double **covar, *P, *f, *r; long i, j, k; double wt, sumw, sum, sum2, sd; double temp; #define SAMPLES 1000 if (numtrees == 2) { fprintf(outfile, "Kishino-Hasegawa-Templeton test\n\n"); fprintf(outfile, "Tree logL Diff logL Its S.D."); fprintf(outfile, " Significantly worse?\n\n"); which = 1; while (which <= numtrees) { fprintf(outfile, "%3ld %9.1f", which, l0gl[which - 1]); if (maxwhich == which) fprintf(outfile, " <------ best\n"); else { sumw = 0.0; sum = 0.0; sum2 = 0.0; for (i = a; i <= b; i++) { if (aliasweight[i] > 0) { wt = aliasweight[i]; sumw += wt; temp = l0gf[which - 1][i] - l0gf[maxwhich - 1][i]; sum += temp * wt; sum2 += wt * temp * temp; } } temp = sum / sumw; sd = sqrt(sumw / (sumw - 1.0) * (sum2 - sum * sum / sumw )); fprintf(outfile, "%10.1f %11.4f", (l0gl[which - 1])-maxlogl, sd); if ((sum < 0.0) && ((-sum) > 1.95996 * sd)) fprintf(outfile, " Yes\n"); else fprintf(outfile, " No\n"); } which++; } fprintf(outfile, "\n\n"); } else { /* Shimodaira-Hasegawa test using normal approximation */ if(numtrees > MAXSHIMOTREES){ fprintf(outfile, "Shimodaira-Hasegawa test on first %d of %ld trees\n\n" , MAXSHIMOTREES, numtrees); numtrees = MAXSHIMOTREES; } else { fprintf(outfile, "Shimodaira-Hasegawa test\n\n"); } covar = (double **)Malloc(numtrees*sizeof(double *)); sumw = 0.0; for (i = a; i <= b; i++) sumw += aliasweight[i]; for (i = 0; i < numtrees; i++) covar[i] = (double *)Malloc(numtrees*sizeof(double)); for (i = 0; i < numtrees; i++) { /* compute covariances of trees */ sum = l0gl[i]/sumw; for (j = 0; j <=i; j++) { sum2 = l0gl[j]/sumw; temp = 0.0; for (k = a; k <= b ; k++) { if (aliasweight[k] > 0) { wt = aliasweight[k]; temp = temp + wt*(l0gf[i][k]-sum) *(l0gf[j][k]-sum2); } } covar[i][j] = temp; if (i != j) covar[j][i] = temp; } } for (i = 0; i < numtrees; i++) { /* in-place Cholesky decomposition of trees x trees covariance matrix */ sum = 0.0; for (j = 0; j <= i-1; j++) sum = sum + covar[i][j] * covar[i][j]; if (covar[i][i] <= sum) temp = 0.0; else temp = sqrt(covar[i][i] - sum); covar[i][i] = temp; for (j = i+1; j < numtrees; j++) { sum = 0.0; for (k = 0; k < i; k++) sum = sum + covar[i][k] * covar[j][k]; if (fabs(temp) < 1.0E-12) covar[j][i] = 0.0; else covar[j][i] = (covar[j][i] - sum)/temp; } } f = (double *)Malloc(numtrees*sizeof(double)); /* resampled likelihoods */ P = (double *)Malloc(numtrees*sizeof(double)); /* vector of P's of trees */ r = (double *)Malloc(numtrees*sizeof(double)); /* store Normal variates */ for (i = 0; i < numtrees; i++) P[i] = 0.0; for (i = 1; i <= SAMPLES; i++) { /* loop over resampled trees */ for (j = 0; j < numtrees; j++) /* draw Normal variates */ r[j] = normrand(seed); for (j = 0; j < numtrees; j++) { /* compute vectors */ sum = 0.0; for (k = 0; k <= j; k++) sum += covar[j][k]*r[k]; f[j] = sum; } sum = f[1]; for (j = 1; j < numtrees; j++) /* get max of vector */ if (f[j] > sum) sum = f[j]; for (j = 0; j < numtrees; j++) /* accumulate P's */ if (maxlogl-l0gl[j] <= sum-f[j]) P[j] += 1.0/SAMPLES; } fprintf(outfile, "Tree logL Diff logL P value"); fprintf(outfile, " Significantly worse?\n\n"); for (i = 0; i < numtrees; i++) { fprintf(outfile, "%3ld%10.1f", i+1, l0gl[i]); if ((maxwhich-1) == i) fprintf(outfile, " <------ best\n"); else { fprintf(outfile, " %9.1f %10.3f", l0gl[i]-maxlogl, P[i]); if (P[i] < 0.05) fprintf(outfile, " Yes\n"); else fprintf(outfile, " No\n"); } } fprintf(outfile, "\n"); free(P); /* free the variables we Malloc'ed */ free(f); free(r); for (i = 0; i < numtrees; i++) free(covar[i]); free(covar); } } /* standev */ void freetip(node *anode) { /* used in dnacomp, dnapars, & dnapenny */ free(anode->numsteps); free(anode->oldnumsteps); free(anode->base); free(anode->oldbase); } /* freetip */ void freenontip(node *anode) { /* used in dnacomp, dnapars, & dnapenny */ free(anode->numsteps); free(anode->oldnumsteps); free(anode->base); free(anode->oldbase); free(anode->numnuc); } /* freenontip */ void freenodes(long nonodes, pointarray treenode) { /* used in dnacomp, dnapars, & dnapenny */ long i; node *p; for (i = 0; i < spp; i++) freetip(treenode[i]); for (i = spp; i < nonodes; i++) { if (treenode[i] != NULL) { p = treenode[i]->next; do { freenontip(p); p = p->next; } while (p != treenode[i]); freenontip(p); } } } /* freenodes */ void freenode(node **anode) { /* used in dnacomp, dnapars, & dnapenny */ freenontip(*anode); free(*anode); } /* freenode */ void freetree(long nonodes, pointarray treenode) { /* used in dnacomp, dnapars, & dnapenny */ long i; node *p, *q; for (i = 0; i < spp; i++) free(treenode[i]); for (i = spp; i < nonodes; i++) { if (treenode[i] != NULL) { p = treenode[i]->next; do { q = p->next; free(p); p = q; } while (p != treenode[i]); free(p); } } free(treenode); } /* freetree */ void prot_freex_notip(long nonodes, pointarray treenode) { /* used in proml */ long i, j; node *p; for (i = spp; i < nonodes; i++) { p = treenode[i]; if ( p == NULL ) continue; do { for (j = 0; j < endsite; j++){ free(p->protx[j]); p->protx[j] = NULL; } free(p->underflows); p->underflows = NULL; free(p->protx); p->protx = NULL; p = p->next; } while (p != treenode[i]); } } /* prot_freex_notip */ void prot_freex(long nonodes, pointarray treenode) { /* used in proml */ long i, j; node *p; for (i = 0; i < spp; i++) { for (j = 0; j < endsite; j++) free(treenode[i]->protx[j]); free(treenode[i]->protx); free(treenode[i]->underflows); } for (i = spp; i < nonodes; i++) { p = treenode[i]; do { for (j = 0; j < endsite; j++) free(p->protx[j]); free(p->protx); free(p->underflows); p = p->next; } while (p != treenode[i]); } } /* prot_freex */ void freex_notip(long nonodes, pointarray treenode) { /* used in dnaml & dnamlk */ long i, j; node *p; for (i = spp; i < nonodes; i++) { p = treenode[i]; if ( p == NULL ) continue; do { for (j = 0; j < endsite; j++) free(p->x[j]); free(p->underflows); free(p->x); p = p->next; } while (p != treenode[i]); } } /* freex_notip */ void freex(long nonodes, pointarray treenode) { /* used in dnaml & dnamlk */ long i, j; node *p; for (i = 0; i < spp; i++) { for (j = 0; j < endsite; j++) free(treenode[i]->x[j]); free(treenode[i]->x); free(treenode[i]->underflows); } for (i = spp; i < nonodes; i++) { if(treenode[i]){ p = treenode[i]; do { for (j = 0; j < endsite; j++) free(p->x[j]); free(p->x); free(p->underflows); p = p->next; } while (p != treenode[i]); } } } /* freex */ void freegarbage(gbases **garbage) { /* used in dnacomp, dnapars, & dnapenny */ gbases *p; while (*garbage) { p = *garbage; *garbage = (*garbage)->next; free(p->base); free(p); } } /*freegarbage */ void freegrbg(node **grbg) { /* used in dnacomp, dnapars, & dnapenny */ node *p; while (*grbg) { p = *grbg; *grbg = (*grbg)->next; freenontip(p); free(p); } } /*freegrbg */ void collapsetree(node *p, node *root, node **grbg, pointarray treenode, long *zeros) { /* Recurse through tree searching for zero length brances between */ /* nodes (not to tips). If one exists, collapse the nodes together, */ /* removing the branch. */ node *q, *x1, *y1, *x2, *y2; long i, j, index, index2, numd; if (p->tip) return; q = p->next; do { if (!q->back->tip && q->v == 0.000000) { /* merge the two nodes. */ x1 = y2 = q->next; x2 = y1 = q->back->next; while(x1->next != q) x1 = x1-> next; while(y1->next != q->back) y1 = y1-> next; x1->next = x2; y1->next = y2; index = q->index; index2 = q->back->index; numd = treenode[index-1]->numdesc + q->back->numdesc -1; chuck(grbg, q->back); chuck(grbg, q); q = x2; /* update the indicies around the node circle */ do{ if(q->index != index){ q->index = index; } q = q-> next; }while(x2 != q); updatenumdesc(treenode[index-1], root, numd); /* Alter treenode to point to real nodes, and update indicies */ /* acordingly. */ j = 0; i=0; for(i = (index2-1); i < nonodes-1 && treenode[i+1]; i++){ treenode[i]=treenode[i+1]; treenode[i+1] = NULL; x1=x2=treenode[i]; do{ x1->index = i+1; x1 = x1 -> next; } while(x1 != x2); } /* Create a new empty fork in the blank spot of treenode */ x1=NULL; for(i=1; i <=3 ; i++){ gnutreenode(grbg, &x2, index2, endsite, zeros); x2->next = x1; x1 = x2; } x2->next->next->next = x2; treenode[nonodes-1]=x2; if (q->back) collapsetree(q->back, root, grbg, treenode, zeros); } else { if (q->back) collapsetree(q->back, root, grbg, treenode, zeros); q = q->next; } } while (q != p); } /* collapsetree */ void collapsebestrees(node **root, node **grbg, pointarray treenode, bestelm *bestrees, long *place, long *zeros, long chars, boolean recompute, boolean progress) { /* Goes through all best trees, collapsing trees where possible, and */ /* deleting trees that are not unique. */ long i,j, k, pos, nextnode, oldnextree; boolean found; node *dummy; oldnextree = nextree; for(i = 0 ; i < (oldnextree - 1) ; i++){ bestrees[i].collapse = true; } if(progress) printf("Collapsing best trees\n "); k = 0; for(i = 0 ; i < (oldnextree - 1) ; i++){ if(progress){ if(i % (((oldnextree-1) / 72) + 1) == 0) putchar('.'); fflush(stdout); } while(!bestrees[k].collapse) k++; /* Reconstruct tree. */ *root = treenode[0]; add(treenode[0], treenode[1], treenode[spp], root, recompute, treenode, grbg, zeros); nextnode = spp + 2; for (j = 3; j <= spp; j++) { if (bestrees[k].btree[j - 1] > 0) add(treenode[bestrees[k].btree[j - 1] - 1], treenode[j - 1], treenode[nextnode++ - 1], root, recompute, treenode, grbg, zeros); else add(treenode[treenode[-bestrees[k].btree[j - 1]-1]->back->index-1], treenode[j - 1], NULL, root, recompute, treenode, grbg, zeros); } reroot(treenode[outgrno - 1], *root); treelength(*root, chars, treenode); collapsetree(*root, *root, grbg, treenode, zeros); savetree(*root, place, treenode, grbg, zeros); /* move everything down in the bestree list */ for(j = k ; j < (nextree - 2) ; j++){ memcpy(bestrees[j].btree, bestrees[j + 1].btree, spp * sizeof(long)); bestrees[j].gloreange = bestrees[j + 1].gloreange; bestrees[j + 1].gloreange = false; bestrees[j].locreange = bestrees[j + 1].locreange; bestrees[j + 1].locreange = false; bestrees[j].collapse = bestrees[j + 1].collapse; } pos=0; findtree(&found, &pos, nextree-1, place, bestrees); /* put the new tree at the end of the list if it wasn't found */ nextree--; if(!found) addtree(pos, &nextree, false, place, bestrees); /* Deconstruct the tree */ for (j = 1; j < spp; j++){ re_move(treenode[j], &dummy, root, recompute, treenode, grbg, zeros); } } if (progress) { putchar('\n'); #ifdef WIN32 phyFillScreenColor(); #endif } } seaview/csrc/seq.h000644 000765 000024 00000021251 12410062256 014716 0ustar00mgouystaff000000 000000 /* version 3.696. Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe. Copyright (c) 1993-2014, Joseph Felsenstein All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* seq.h: included in dnacomp, dnadist, dnainvar, dnaml, dnamlk, dnamove, dnapars, dnapenny, protdist, protpars, restdist & restml */ #ifndef SEQ_H #define SEQ_H #define ebcdic EBCDIC #define MAXNCH 20 /* All of this came over from cons.h -plc*/ #define OVER 7 #define ADJACENT_PAIRS 1 #define CORR_IN_1_AND_2 2 #define ALL_IN_1_AND_2 3 #define NO_PAIRING 4 #define ALL_IN_FIRST 5 #define TREE1 8 #define TREE2 9 #define FULL_MATRIX 11 #define VERBOSE 22 #define SPARSE 33 /* Number of columns per block in a matrix output */ #define COLUMNS_PER_BLOCK 10 /*end move*/ typedef struct gbases { baseptr base; struct gbases *next; } gbases; typedef struct nuview_data { /* A big 'ol collection of pointers used in nuview */ double *yy, *wwzz, *vvzz, *vzsumr, *vzsumy, *sum, *sumr, *sumy; sitelike *xx; } nuview_data; struct LOC_hyptrav { boolean bottom; node *r; long *hypset; boolean maybe, nonzero; long tempset, anc; } ; extern long nonodes, endsite, outgrno, nextree, which; extern boolean interleaved, printdata, outgropt, treeprint, dotdiff, transvp; extern steptr weight, category, alias, location, ally; extern sequence y; #ifndef OLDC /* function prototypes */ void alloctemp(node **, long *, long); void freetemp(node **); void freetree2 (pointarray, long); void inputdata(long); void alloctree(pointarray *, long, boolean); void allocx(long, long, pointarray, boolean); void prot_allocx(long, long, pointarray, boolean); void setuptree(pointarray, long, boolean); void setuptree2(tree *); void alloctip(node *, long *); void getbasefreqs(double, double, double, double, double *, double *, double *, double *, double *, double *, double *, double *xi, double *, double *, boolean, boolean); void empiricalfreqs(double *,double *,double *,double *,steptr,pointarray); void sitesort(long, steptr); void sitecombine(long); void sitescrunch(long); void sitesort2(long, steptr); void sitecombine2(long, steptr); void sitescrunch2(long, long, long, steptr); void makevalues(pointarray, long *, boolean); void makevalues2(long, pointarray, long, long, sequence, steptr); void fillin(node *, node *, node *); long getlargest(long *); void multifillin(node *, node *, long); void sumnsteps(node *, node *, node *, long, long); void sumnsteps2(node *, node *, node *, long, long, long *); void multisumnsteps(node *, node *, long, long, long *); void multisumnsteps2(node *); boolean alltips(node *, node *); void gdispose(node *, node **, pointarray); void preorder(node *, node *, node *, node *, node *, node *, long); void updatenumdesc(node *, node *, long); void add(node *,node *,node *,node **,boolean,pointarray,node **,long *); void findbelow(node **below, node *item, node *fork); void re_move(node *item, node **fork, node **root, boolean recompute, pointarray, node **, long *); void postorder(node *p); void getnufork(node **, node **, pointarray, long *); void reroot(node *, node *); void reroot2(node *, node *); void reroot3(node *, node *, node *, node *, node **); void savetraverse(node *); void newindex(long, node *); void flipindexes(long, pointarray); boolean parentinmulti(node *); long sibsvisited(node *, long *); long smallest(node *, long *); void bintomulti(node **, node **, node **, long *); void backtobinary(node **, node *, node **); boolean outgrin(node *, node *); void flipnodes(node *, node *); void moveleft(node *, node *, node **); void savetree(node *, long *, pointarray, node **, long *); void addnsave(node *, node *, node *, node **, node **,boolean, pointarray, long *, long *); void addbestever(long *, long *, long, boolean, long *, bestelm *); void addtiedtree(long, long *, long, boolean,long *, bestelm *); void clearcollapse(pointarray); void clearbottom(pointarray); void collabranch(node *, node *, node *); boolean allcommonbases(node *, node *, boolean *); void findbottom(node *, node **); boolean moresteps(node *, node *); boolean passdown(node *, node *, node *, node *, node *, node *, node *, node *, node *, boolean); boolean trycollapdesc(node *, node *, node *, node *, node *, node *, node *, node *, node *, boolean , long *); void setbottom(node *); boolean zeroinsubtree(node *, node *, node *, node *, node *, node *, node *, node *, boolean, node *, long *); boolean collapsible(node *, node *, node *, node *, node *, node *, node *, node *, boolean, node *, long *, pointarray); void replaceback(node **, node *, node *, node **, long *); void putback(node *, node *, node *, node **); void savelocrearr(node *, node *, node *, node *, node *, node *, node *, node *, node *, node **, long, long *, boolean, boolean , boolean *, long *, bestelm *, pointarray , node **, long *); void clearvisited(pointarray); void hyprint(long, long, struct LOC_hyptrav *,pointarray, Char *); void gnubase(gbases **, gbases **, long); void chuckbase(gbases *, gbases **); void hyptrav(node *, long *, long, long, boolean,pointarray, gbases **, Char *); void hypstates(long , node *, pointarray, gbases **, Char *); void initbranchlen(node *p); void initmin(node *, long, boolean); void initbase(node *, long); void inittreetrav(node *, long); void compmin(node *, node *); void minpostorder(node *, pointarray); void branchlength(node *,node *,double *,pointarray); void printbranchlengths(node *); void branchlentrav(node *,node *,long,long,double *,pointarray); void treelength(node *, long, pointarray); void coordinates(node *, long *, double, long *); void drawline(long, double, node *); void printree(node *, double); void writesteps(long, boolean, steptr, node *); void treeout(node *, long, long *, node *); void treeout3(node *, long, long *, node *); void fdrawline2(FILE *fp, long i, double scale, tree *curtree); void drawline2(long, double, tree); void drawline3(long, double, node *); void copynode(node *, node *, long); void prot_copynode(node *, node *, long); void copy_(tree *, tree *, long, long); void prot_copy_(tree *, tree *, long, long); void standev(long, long, long, double, double *, long **, longer); void standev2(long, long, long, long, double, double *, double **, steptr, longer); void freetip(node *); void freenontip(node *); void freenodes(long, pointarray); void freenode(node **); void freetree(long, pointarray); void freex(long, pointarray); void freex_notip(long, pointarray); void prot_freex_notip(long nonodes, pointarray treenode); void prot_freex(long nonodes, pointarray treenode); void freegarbage(gbases **); void freegrbg(node **); void collapsetree(node *, node *, node **, pointarray, long *); void collapsebestrees(node **, node **, pointarray, bestelm *, long *, long *, long, boolean, boolean); void fix_x(node* p,long site, double maxx, long rcategs); void fix_protx(node* p,long site,double maxx, long rcategs); /*function prototypes*/ #endif #endif /* SEQ_H */ seaview/csrc/zsockr.c000644 000765 000024 00000004731 11705315735 015451 0ustar00mgouystaff000000 000000 /* functions to handle zlib-compressed data read from socket */ #include #include #include #include #include #ifdef WIN32 #include #endif /* included functions */ void *prepare_sock_gz_r(FILE *sockr); int z_getc(void *v); char *z_gets(void *v, char *line, size_t len); char *z_read_sock(void *v); int close_sock_gz_r(void *v); #define ZBSIZE 100000 typedef struct { z_stream stream; char z_buffer[ZBSIZE]; /* compressed input buffer */ char text_buffer[4 * ZBSIZE]; /* decompressed buffer */ char *pos, *endbuf; #ifdef WIN32 SOCKET fd; #else int fd; #endif } sock_gz_r; void *prepare_sock_gz_r(FILE *sockr) { int err; sock_gz_r *big; big = (sock_gz_r *)malloc(sizeof(sock_gz_r)); if(big == NULL) return NULL; big->stream.next_in = Z_NULL; big->stream.avail_in = 0; big->stream.avail_out = 0; big->stream.zalloc = Z_NULL; big->stream.zfree = Z_NULL; big->stream.opaque = NULL; big->pos = big->text_buffer; big->endbuf = big->pos; #ifdef WIN32 big->fd = (SOCKET)sockr; #else big->fd = fileno(sockr); #endif err = inflateInit(&big->stream); return err == Z_OK ? (void *)big : NULL; } int z_getc(void *v) { int q; sock_gz_r *big = (sock_gz_r *)v; z_streamp zs; if(big->pos < big->endbuf) { return *(big->pos++); } zs = &(big->stream); zs->next_out = (Bytef *)big->text_buffer; zs->avail_out = sizeof(big->text_buffer); big->pos = (char *)zs->next_out; do { if(zs->avail_in == 0) { int lu; #ifdef WIN32 lu = recv( big->fd , big->z_buffer, ZBSIZE, 0 ); #else lu = read( big->fd , big->z_buffer, ZBSIZE ); #endif if(lu == -1) return EOF; zs->next_in = (Bytef *)big->z_buffer; zs->avail_in = lu; } q = inflate(zs, Z_NO_FLUSH); if(q == Z_STREAM_END) break; if(q != Z_OK) { break; } } while ( (char *)zs->next_out == big->pos); big->endbuf = (char *)zs->next_out; if(big->pos < big->endbuf) return *(big->pos++); else return EOF; } char *z_gets(void *v, char *line, size_t len) { int c; char *p; p = line; while(len > 1) { c = z_getc( v ); if(c == EOF) { if(p == line) return NULL; break; } *(p++) = c; if(c == '\n') break; len--; } *p = 0; return line; } char *z_read_sock(void *v) { static char line[500]; char *p; int l; p = z_gets(v, line, sizeof(line)); if(p == NULL) return NULL; l = strlen(line); if(l > 0 && line[l-1] == '\n') line[l-1] = 0; return line; } int close_sock_gz_r(void *v) { sock_gz_r *big = (sock_gz_r *)v; int val; val = inflateEnd(&(big->stream)); free(big); return val; }