int main(int argc, char *argv[]) { char c; int i, j, t, opt_idx, ntrees, nleaves = -1; TreeNode *n, *node_i, *node_j, *lca, *nametree = NULL; TreeNode **tree; List *leaves, ***distance, *tree_fnames, *tot_dist; int mod = FALSE; char **leaf_name; String *trees_arg; FILE *F; struct option long_opts[] = { {"mod", 0, 0, 'm'}, {"tree", 1, 0, 't'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; while ((c = getopt_long(argc, argv, "mt:h", long_opts, &opt_idx)) != -1) { switch (c) { case 'm': mod = TRUE; break; case 't': if (optarg[0] == '(') nametree = tr_new_from_string(optarg); else nametree = tr_new_from_file(phast_fopen(optarg, "r")); break; case 'h': usage(argv[0]); case '?': die("Bad argument. Try '%s -h'.\n", argv[0]); } } if (optind > argc - 1) die("Input filename required. Try '%s -h'.\n", argv[0]); set_seed(-1); /* build a comma-delimited list and pass to get_arg_list; allows possibility of reading from file via '*' operator */ trees_arg = str_new(1000); for (i = optind; i < argc; i++) { str_append_charstr(trees_arg, argv[i]); if (i < argc - 1) str_append_char(trees_arg, ','); } tree_fnames = get_arg_list(trees_arg->chars); ntrees = lst_size(tree_fnames); tree = smalloc(ntrees * sizeof(void*)); /* read trees */ for (t = 0; t < ntrees; t++) { String *fname = lst_get_ptr(tree_fnames, t); if (mod) { TreeModel *m = tm_new_from_file(F = phast_fopen(fname->chars, "r"), 1); tree[t] = tr_create_copy(m->tree); tm_free(m); phast_fclose(F); } else tree[t] = tr_new_from_file(phast_fopen(fname->chars, "r")); } /* initialization */ nleaves = (tree[0]->nnodes + 1)/2; leaves = lst_new_ptr(nleaves); distance = smalloc(nleaves * sizeof(void*)); leaf_name = smalloc(nleaves * sizeof(void*)); for (i = 0; i < nleaves; i++) { distance[i] = smalloc(nleaves * sizeof(void*)); for (j = i+1; j < nleaves; j++) distance[i][j] = lst_new_dbl(ntrees); } if (nametree == NULL) nametree = tree[0]; for (i = 0, j = 0; i < lst_size(nametree->nodes); i++) { n = lst_get_ptr(nametree->nodes, i); if (n->lchild == NULL && n->rchild == NULL) leaf_name[j++] = n->name; } tot_dist = lst_new_dbl(ntrees); /* now compute distances */ for (t = 0; t < ntrees; t++) { /* obtain list of leaves */ lst_clear(leaves); for (i = 0; i < lst_size(tree[t]->nodes); i++) { n = lst_get_ptr(tree[t]->nodes, i); if (n->lchild == NULL && n->rchild == NULL) lst_push_ptr(leaves, n); } if (lst_size(leaves) != nleaves) die("ERROR: trees have different numbers of leaves.\n"); /* look at all pairs */ for (i = 0; i < nleaves; i++) { node_i = lst_get_ptr(leaves, i); for (j = i+1; j < nleaves; j++) { double dist = 0; node_j = lst_get_ptr(leaves, j); /* because ids are assigned in pre-order, the first ancestor of node j that has an id less than i is the LCA of i and j; we seek the sum of distances from both i and j to this node */ for (n = node_j; n->id >= node_i->id; n = n->parent) dist += n->dparent; lca = n; for (n = node_i; n != lca; n = n->parent) dist += n->dparent; lst_push_dbl(distance[i][j], dist); } } lst_push_dbl(tot_dist, tr_total_len(tree[t])); } /* print distances and (optionally) stats */ if (ntrees == 1) { for (i = 0; i < nleaves; i++) { for (j = i+1; j < nleaves; j++) { printf ("%s\t%s\t%f\n", leaf_name[i], leaf_name[j], lst_get_dbl(distance[i][j], 0)); } } printf ("%s\t%s\t%f\n", "(total)", "-", lst_get_dbl(tot_dist, 0)); } else { double mean, stdev; double quantiles[] = {0, 0.025, 0.05, 0.5, 0.95, 0.975, 1}; double quantile_vals[7]; printf("%-15s %-15s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "leaf1", "leaf2", "mean", "stdev", "median", "min", "max", "95%_min", "95%_max", "90%_min", "90%_max"); for (i = 0; i < nleaves; i++) { for (j = i+1; j < nleaves; j++) { mean = lst_dbl_mean(distance[i][j]); stdev = lst_dbl_stdev(distance[i][j]); lst_qsort_dbl(distance[i][j], ASCENDING); lst_dbl_quantiles(distance[i][j], quantiles, 7, quantile_vals); printf("%-15s %-15s %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f\n", leaf_name[i], leaf_name[j], mean, stdev, quantile_vals[3], quantile_vals[0], quantile_vals[6], quantile_vals[1], quantile_vals[5], quantile_vals[2], quantile_vals[4]); } } /* also do total branch len */ mean = lst_dbl_mean(tot_dist); stdev = lst_dbl_stdev(tot_dist); lst_qsort_dbl(tot_dist, ASCENDING); lst_dbl_quantiles(tot_dist, quantiles, 7, quantile_vals); printf("%-15s %-15s %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f\n", "(total)", "-", mean, stdev, quantile_vals[3], quantile_vals[0], quantile_vals[6], quantile_vals[1], quantile_vals[5], quantile_vals[2], quantile_vals[4]); } return 0; }
TreeNode* rph_tree_new(SEXP treeStr) { TreeNode *tree = tr_new_from_string(CHARACTER_VALUE(treeStr)); return tree; }
int main(int argc, char* argv[]) { FILE* F; MSA *msa; int *msa_gap_patterns = NULL; HMM *hmm = NULL; TreeNode *tree = NULL; int i, input_format = SS, msa_idx, quiet_mode = FALSE, ncats, nmsas, ncats_unspooled, indel_nseqs = -1; String *msa_fname, *gff_fname; List *gff_fname_list = NULL, *msa_fname_list = NULL, *msa_length_list = NULL, *model_indels_str = NULL; Matrix *traincounts = NULL; Vector *begcounts = NULL, *statecounts = NULL; CategoryMap *cm = NULL; char c; GapPatternMap *gpm = NULL; GFF_Set *gff; char *reverse_groups_tag = NULL; while ((c = getopt(argc, argv, "i:g:c:m:M:R:I:n:t:P:G:qh")) != -1) { switch(c) { case 'i': input_format = msa_str_to_format(optarg); if (input_format == -1) die("ERROR: bad alignment format.\n"); break; case 'g': gff_fname_list = get_arg_list(optarg); break; case 'c': cm = cm_new_string_or_file(optarg); break; case 'm': msa_fname_list = get_arg_list(optarg); break; case 'M': msa_length_list = str_list_as_int(get_arg_list(optarg)); break; case 'R': reverse_groups_tag = optarg; break; case 'I': model_indels_str = get_arg_list(optarg); break; case 'n': indel_nseqs = get_arg_int(optarg); break; case 't': if (optarg[0] == '(') /* in this case, assume topology given at command line */ tree = tr_new_from_string(optarg); else tree = tr_new_from_file(phast_fopen(optarg, "r")); break; case 'q': quiet_mode = TRUE; break; case 'h': print_usage(); exit(0); case '?': die("ERROR: unrecognized option.\n\nType 'hmm_train -h' for usage.\n"); } } if (msa_fname_list == NULL) die("ERROR: -m required. Type 'hmm_train -h' for usage.\n"); if (gff_fname_list == NULL) die("ERROR: -g required in training mode. Type 'hmm_train -h' for usage.\n"); if (msa_length_list != NULL && msa_fname_list != NULL) die("ERROR: -m and -M are mutually exclusive. Type 'hmm_train -h' for usage.\n"); if (model_indels_str != NULL && tree == NULL) die("ERROR: -I requires -t. Type 'hmm_train -h' for usage.\n"); if (cm == NULL) die("ERROR: category map required.\n"); set_seed(-1); ncats = cm->ncats + 1; ncats_unspooled = cm->unspooler != NULL ? cm->unspooler->nstates_unspooled : ncats; nmsas = (msa_length_list != NULL ? lst_size(msa_length_list) : lst_size(msa_fname_list)); if (model_indels_str != NULL) { if (tree == NULL) die("ERROR: tree is NULL\n"); /*FIXME: indel_ncats broken */ gpm = gp_create_gapcats(cm, model_indels_str, tree, FALSE); ncats = cm->ncats + 1; /* numbers will change */ ncats_unspooled = cm->unspooler == NULL ? ncats : cm->unspooler->nstates_unspooled; } /* allocate memory for storage of "training paths" */ traincounts = mat_new(ncats_unspooled, ncats_unspooled); statecounts = vec_new(ncats_unspooled); begcounts = vec_new(ncats_unspooled); mat_zero(traincounts); vec_zero(statecounts); vec_zero(begcounts); /* create skeleton of new HMM. */ hmm = hmm_new_nstates(ncats_unspooled, 0, 0); /* Main loop: consider each MSA in turn */ for (msa_idx = 0; msa_idx < nmsas; msa_idx++) { if (msa_fname_list != NULL) { msa_fname = (String*)lst_get_ptr(msa_fname_list, msa_idx); F = phast_fopen(msa_fname->chars, "r"); if (!quiet_mode) fprintf(stderr, "Reading alignment from %s ...\n", F == stdin ? "stdin" : msa_fname->chars); msa = msa_new_from_file(F, NULL); phast_fclose(F); } else { /* only lengths of alignments specified */ msa = msa_new(NULL, NULL, 0, lst_get_int(msa_length_list, msa_idx), NULL); /* just a shell in this case */ } gff_fname = (String*)lst_get_ptr(gff_fname_list, msa_idx); if (!quiet_mode) fprintf(stderr, "Reading annotations from %s ...\n", gff_fname->chars); gff = gff_read_set(phast_fopen(gff_fname->chars, "r")); /* convert GFF to coordinate frame of alignment */ if (msa_length_list == NULL) { if (!quiet_mode) fprintf(stderr, "Mapping annotations to alignment ...\n"); msa_map_gff_coords(msa, gff, 1, 0, 0); /* assume seq 1 is ref */ } if (model_indels_str != NULL) { if (!quiet_mode) fprintf(stderr, "Obtaining gap patterns ...\n"); msa_gap_patterns = smalloc(msa->length * sizeof(int)); gp_set_phylo_patterns(gpm, msa_gap_patterns, msa); } /* at this point, we don't actually need the alignment anymore; if using ordered suff stats (likely with large data sets), can free them now, to avoid running out of memory */ if (msa->ss != NULL) { ss_free(msa->ss); msa->ss = NULL; } if (reverse_groups_tag != NULL) { if (!quiet_mode) fprintf(stderr, "Reverse complementing features on negative strand (group by '%s') ...\n", reverse_groups_tag); /* we don't need to reverse complement the whole alignment -- just the gff and possibly the gap pattern array (pass a NULL msa) */ gff_group(gff, reverse_groups_tag); msa_reverse_compl_feats(NULL, gff, msa_gap_patterns); } if (!quiet_mode) fprintf(stderr, "Labeling sites by category ...\n"); msa_label_categories(msa, gff, cm); gff_free_set(gff); if (model_indels_str != NULL) { if (!quiet_mode) fprintf(stderr, "Remapping categories according to gap patterns ...\n"); if (indel_nseqs > 0 && indel_nseqs != msa->nseqs) { /* in this case, we'll simply reassign non-trivial gap patterns randomly. This will achieve the desired effect with minimal coding, as long as the number of sites is not too small (the indel model is probably useless anyway if the number is small) */ int pat, newpat; int npatterns = 4 * indel_nseqs - 5; int complex_allowed[cm->ncats+1]; List *no_complex_names, *no_complex_nums; if (!quiet_mode) fprintf(stderr, "(target number of sequences: %d)\n", indel_nseqs); /* set up index indicating by cat no. whether complex gaps are allowed */ for (i = 0; i < ncats; i++) complex_allowed[i] = 1; no_complex_names = lst_new_ptr(10); str_split(str_new_charstr(NO_COMPLEX), ",", no_complex_names); no_complex_nums = cm_get_category_list(cm, no_complex_names, 1); for (i = 0; i < lst_size(no_complex_nums); i++) complex_allowed[lst_get_int(no_complex_nums, i)] = 0; lst_free(no_complex_nums); lst_free_strings(no_complex_names); lst_free(no_complex_names); /* now reassign all non-null numbers */ for (i = 0; i < msa->length; ) { if ((pat = msa_gap_patterns[i]) != 0) { if (complex_allowed[msa->categories[i]]) newpat = 1 + ((double)npatterns * unif_rand()); /* random number in interval [1, npatterns] */ else newpat = 1 + ((double)(npatterns-1) * unif_rand()); /* random number in interval [1,npatterns-1] (excludes complex gap pattern) */ for (; i < msa->length && msa_gap_patterns[i] == pat; i++) msa_gap_patterns[i] = newpat; /* change for whole sequence */ } else i++; } } /* obtain gapped category number for each site */ for (i = 0; i < msa->length; i++) if (gpm->cat_x_pattern_to_gapcat[msa->categories[i]] != NULL) msa->categories[i] = gpm->cat_x_pattern_to_gapcat[msa->categories[i]][msa_gap_patterns[i]]; } if (!quiet_mode) fprintf(stderr, "Unspooling categories ...\n"); cm_spooled_to_unspooled(cm, msa->categories, msa->length); if (!quiet_mode) fprintf(stderr, "Collecting training data ...\n"); hmm_train_update_counts(traincounts, statecounts, begcounts, msa->categories, msa->length, ncats_unspooled); if (msa_gap_patterns != NULL) sfree(msa_gap_patterns); msa_free(msa); } /* now train HMM, using cumulative data */ hmm_train_from_counts(hmm, traincounts, NULL, statecounts, NULL, begcounts, NULL); /* if modeling indels, adjust begin transitions so probability is distributed among different "gap pattern" states that all correspond to the same ungapped state (category); this helps avoid problems that occur when training on a few large sequences (e.g., whole chromosomes) and then testing on many shorter ones */ if (model_indels_str != NULL) { double tprob[gpm->ncats]; int nst[gpm->ncats]; /* total prob and number of states per spooled, ungapped category */ for (i = 0; i < gpm->ncats; i++) tprob[i] = nst[i] = 0; for (i = 0; i < hmm->nstates; i++) { if (vec_get(hmm->begin_transitions, i) > 0) /* have to go from unspooled space to spooled space, then to ungapped space (HMM states correspond to unspooled, gapped categories). Note that states with nonzero begin probs shouldn't be conditioned on other states. */ tprob[gpm->gapcat_to_cat[cm_unspooled_to_spooled_cat(cm, i)]] += vec_get(hmm->begin_transitions, i); nst[gpm->gapcat_to_cat[cm_unspooled_to_spooled_cat(cm, i)]]++; } for (i = 0; i < hmm->nstates; i++) if (tprob[gpm->gapcat_to_cat[cm_unspooled_to_spooled_cat(cm, i)]] > 0) vec_set(hmm->begin_transitions, i, tprob[gpm->gapcat_to_cat[cm_unspooled_to_spooled_cat(cm, i)]] / nst[gpm->gapcat_to_cat[cm_unspooled_to_spooled_cat(cm, i)]]); /* (uniform prior) */ } /* write trained HMM */ hmm_print(stdout, hmm); if (!quiet_mode) fprintf(stderr, "Done.\n"); return 0; }
int main(int argc, char *argv[]) { char *msa_fname = NULL, *alph = "ACGT"; msa_format_type input_format = UNKNOWN_FORMAT; char c; int opt_idx, seed=-1; String *optstr; List *tmplist = NULL; struct phyloFit_struct *pf; FILE *infile; struct option long_opts[] = { {"msa", 1, 0, 'm'}, {"tree", 1, 0, 't'}, {"subst-mod", 1, 0, 's'}, {"msa-format", 1, 0, 'i'}, {"nrates", 1, 0, 'k'}, {"alpha", 1, 0, 'a'}, {"features", 1, 0, 'g'}, {"catmap", 1, 0, 'c'}, {"log", 1, 0, 'l'}, {"out-root", 1, 0, 'o'}, {"EM", 0, 0, 'E'}, {"error", 1, 0, 'e'}, {"precision", 1, 0, 'p'}, {"do-cats", 1, 0, 'C'}, {"non-overlapping", 0, 0, 'V'}, {"markov", 0, 0, 'N'}, {"reverse-groups", 1, 0, 'R'}, {"init-model", 1, 0, 'M'}, {"init-random", 0, 0, 'r'}, {"init-parsimony", 0, 0, 'y'}, {"print-parsimony", 1, 0, 'Y'}, {"lnl", 0, 0, 'L'}, {"scale-only", 0, 0, 'B'}, {"scale-subtree", 1, 0, 'S'}, {"estimate-freqs", 0, 0, 'F'}, {"sym-freqs", 0, 0, 'W'}, {"no-freqs", 0, 0, 'f'}, {"no-rates", 0, 0, 'n'}, {"no-opt", 1, 0, 'O'}, {"min-informative", 1, 0, 'I'}, {"gaps-as-bases", 0, 0, 'G'}, {"quiet", 0, 0, 'q'}, {"help", 0, 0, 'h'}, {"windows", 1, 0, 'w'}, {"windows-explicit", 1, 0, 'v'}, {"ancestor", 1, 0, 'A'}, {"post-probs", 0, 0, 'P'}, {"expected-subs", 0, 0, 'X'}, {"expected-total-subs", 0, 0, 'Z'}, {"expected-subs-col", 0, 0, 'J'}, {"column-probs", 0, 0, 'U'}, {"rate-constants", 1, 0, 'K'}, {"ignore-branches", 1, 0, 'b'}, {"clock", 0, 0, 'z'}, {"alt-model", 1, 0, 'd'}, {"label-branches", 1, 0, 0}, {"label-subtree", 1, 0, 0}, {"selection", 1, 0, 0}, {"bound", 1, 0, 'u'}, {"seed", 1, 0, 'D'}, {0, 0, 0, 0} }; // NOTE: remaining shortcuts left: HjQx pf = phyloFit_struct_new(0); while ((c = (char)getopt_long(argc, argv, "m:t:s:g:c:C:i:o:k:a:l:w:v:M:p:A:I:K:S:b:d:O:u:Y:e:D:GVENRqLPXZUBFfnrzhWyJ", long_opts, &opt_idx)) != -1) { switch(c) { case 'm': msa_fname = optarg; break; case 't': if (optarg[0] == '(') /* in this case, assume topology given at command line */ pf->tree = tr_new_from_string(optarg); else pf->tree = tr_new_from_file(phast_fopen(optarg, "r")); break; case 's': pf->subst_mod = tm_get_subst_mod_type(optarg); if (pf->subst_mod == UNDEF_MOD) die("ERROR: illegal substitution model. Type \"phyloFit -h\" for usage.\n"); break; case 'g': pf->gff = gff_read_set(phast_fopen(optarg, "r")); break; case 'c': pf->cm = cm_new_string_or_file(optarg); break; case 'C': pf->cats_to_do_str = get_arg_list(optarg); break; case 'V': pf->nonoverlapping = TRUE; break; case 'o': pf->output_fname_root = optarg; break; case 'k': pf->nratecats = get_arg_int_bounds(optarg, 0, INFTY); break; case 'a': pf->alpha = get_arg_dbl(optarg); break; case 'R': pf->reverse_group_tag = optarg; break; case 'i': input_format = msa_str_to_format(optarg); if (input_format == UNKNOWN_FORMAT) die("ERROR: unrecognized alignment format. Type 'phyloFit -h' for usage.\n"); break; case 'l': if (!strcmp(optarg, "-")) pf->logf = stderr; else pf->logf = phast_fopen(optarg, "w+"); break; case 'N': pf->use_conditionals = 1; break; case 'w': tmplist = get_arg_list(optarg); if (lst_size(tmplist) != 2 || str_as_int(lst_get_ptr(tmplist, 0), &(pf->window_size)) != 0 || str_as_int(lst_get_ptr(tmplist, 1), &(pf->window_shift)) != 0) die("ERROR: illegal arguments to --windows.\n"); lst_free_strings(tmplist); lst_free(tmplist); break; case 'v': tmplist = get_arg_list(optarg); if (lst_size(tmplist) % 2 != 0) die("ERROR: argument to --windows-explicit must be a list of even length.\n"); pf->window_coords = str_list_as_int(tmplist); lst_free(tmplist); break; case 'E': pf->use_em = TRUE; break; case 'e': pf->error_fname=optarg; break; case 'p': if (!strcmp(optarg, "LOW")) pf->precision = OPT_LOW_PREC; else if (!strcmp(optarg, "MED")) pf->precision = OPT_MED_PREC; else if (!strcmp(optarg, "HIGH")) pf->precision = OPT_HIGH_PREC; else if (!strcmp(optarg, "VERY_HIGH")) pf->precision = OPT_VERY_HIGH_PREC; else die("ERROR: --precision must be LOW, MED, or HIGH.\n\n"); break; case 'M': pf->input_mod = tm_new_from_file(phast_fopen(optarg, "r"), 1); break; case 'r': pf->random_init = TRUE; break; case 'y': pf->init_parsimony = TRUE; break; case 'Y': pf->init_parsimony = TRUE; pf->parsimony_cost_fname = optarg; pf->parsimony_only=TRUE; break; case 'L': pf->likelihood_only = TRUE; break; case 'q': pf->quiet = TRUE; break; case 'P': pf->do_bases = TRUE; break; case 'X': pf->do_expected_nsubst = TRUE; break; case 'Z': pf->do_expected_nsubst_tot = TRUE; break; case 'J': pf->do_expected_nsubst_col = TRUE; break; case 'U': pf->likelihood_only = TRUE; /* force -L */ pf->nsites_threshold = 0; /* also force this; typical use is with small number of tuples, no tuple_idx */ pf->do_column_probs = TRUE; break; case 'A': pf->root_seqname = optarg; break; case 'I': pf->nsites_threshold = get_arg_int(optarg); break; case 'G': pf->gaps_as_bases = TRUE; alph = "ACGT-"; break; case 'B': pf->estimate_scale_only = TRUE; break; case 'S': pf->subtree_name = optarg; break; case 'F': pf->estimate_backgd = TRUE; break; case 'W': pf->estimate_backgd = TRUE; pf->symfreq = TRUE; break; case 'f': pf->no_freqs = TRUE; break; case 'n': pf->no_rates = TRUE; break; case 'K': tmplist = get_arg_list(optarg); pf->rate_consts = str_list_as_dbl(tmplist); pf->nratecats = lst_size(pf->rate_consts); pf->use_em = 1; lst_free_strings(tmplist); lst_free(tmplist); break; case 'b': pf->ignore_branches = get_arg_list(optarg); break; case 'z': pf->assume_clock = TRUE; break; case 'O': if (pf->nooptstr == NULL) pf->nooptstr = str_new_charstr(optarg); else die("ERROR: no-opt argument can only be used once! parameters can be comma-separated list."); break; case 'd': if (pf->alt_mod_str == NULL) { pf->alt_mod_str = lst_new_ptr(1); } optstr = str_new_charstr(optarg); lst_push_ptr(pf->alt_mod_str, optstr); break; case 0: if (strcmp(long_opts[opt_idx].name, "label-branches") == 0 || strcmp(long_opts[opt_idx].name, "label-subtree") == 0) { optstr = str_new_charstr(optarg); if (pf->label_str == NULL) { pf->label_str = lst_new_ptr(3); pf->label_type = lst_new_int(3); } lst_push_ptr(pf->label_str, optstr); lst_push_int(pf->label_type, strcmp(long_opts[opt_idx].name, "label-branches") == 0 ? BRANCH_TYPE : SUBTREE_TYPE); } else if (strcmp(long_opts[opt_idx].name, "selection") == 0) { pf->selection = get_arg_dbl(optarg); pf->use_selection = TRUE; } else { die("ERROR: unknown option. Type 'phyloFit -h' for usage.\n"); } break; case 'u': if (pf->bound_arg == NULL) pf->bound_arg = lst_new_ptr(1); optstr = str_new_charstr(optarg); lst_push_ptr(pf->bound_arg, optstr); break; case 'D': seed = get_arg_int_bounds(optarg, 1, INFTY); break; case 'h': printf("%s", HELP); exit(0); case '?': die("ERROR: illegal argument. Type 'phyloFit -h' for usage.\n"); } } set_seed(seed); if (msa_fname == NULL) { if (optind >= argc) die("ERROR: missing alignment filename. Type 'phyloFit -h' for usage.\n"); msa_fname = argv[optind]; pf->msa_fname = msa_fname; } infile = phast_fopen(msa_fname, "r"); if (input_format == UNKNOWN_FORMAT) input_format = msa_format_for_content(infile, 1); if (pf->nonoverlapping && (pf->use_conditionals || pf->gff != NULL || pf->cats_to_do_str || input_format == SS)) die("ERROR: cannot use --non-overlapping with --markov, --features,\n--msa-format SS, or --do-cats.\n"); /* read alignment */ if (!pf->quiet) fprintf(stderr, "Reading alignment from %s ...\n", msa_fname); if (input_format == MAF) { pf->msa = maf_read(infile, NULL, tm_order(pf->subst_mod) + 1, NULL, pf->gff, pf->cm, pf->nonoverlapping ? tm_order(pf->subst_mod) + 1 : -1, FALSE, pf->reverse_group_tag, NO_STRIP, FALSE); if (pf->gaps_as_bases) msa_reset_alphabet(pf->msa, alph); } else pf->msa = msa_new_from_file_define_format(infile, input_format, alph); /* set up for categories */ /* first label sites, if necessary */ pf->label_categories = (input_format != MAF); run_phyloFit(pf); if (pf->logf != NULL && pf->logf != stderr && pf->logf != stdout) phast_fclose(pf->logf); if (!pf->quiet) fprintf(stderr, "Done.\n"); sfree(pf); return 0; }