static void emit_alignment(ESL_GETOPTS *go, FILE *ofp, int outfmt, ESL_RANDOMNESS *r, P7_HMM *hmm) { ESL_MSA *msa = NULL; ESL_SQ **sq = NULL; P7_TRACE **tr = NULL; int N = esl_opt_GetInteger(go, "-N"); int optflags = p7_ALL_CONSENSUS_COLS; int i; if ((tr = malloc(sizeof(P7_TRACE *) * N)) == NULL) esl_fatal("failed to allocate trace array"); if ((sq = malloc(sizeof(ESL_SQ *) * N)) == NULL) esl_fatal("failed to allocate seq array"); for (i = 0; i < N; i++) { if ((sq[i] = esl_sq_CreateDigital(hmm->abc)) == NULL) esl_fatal("failed to allocate seq"); if ((tr[i] = p7_trace_Create()) == NULL) esl_fatal("failed to allocate trace"); } for (i = 0; i < N; i++) { if (p7_CoreEmit(r, hmm, sq[i], tr[i]) != eslOK) esl_fatal("Failed to emit sequence"); if (esl_sq_FormatName(sq[i], "%s-sample%d", hmm->name, i+1) != eslOK) esl_fatal("Failed to set sequence name\n"); } p7_tracealign_Seqs(sq, tr, N, hmm->M, optflags, hmm, &msa); eslx_msafile_Write(ofp, msa, outfmt); for (i = 0; i < N; i++) p7_trace_Destroy(tr[i]); free(tr); for (i = 0; i < N; i++) esl_sq_Destroy(sq[i]); free(sq); esl_msa_Destroy(msa); return; }
/* Function: p7_tophits_Alignment() * Synopsis: Create a multiple alignment of all the included domains. * * Purpose: Create a multiple alignment of all domains marked * "includable" in the top hits list <th>, and return it in * <*ret_msa>. * * Use of <optflags> is identical to <optflags> in <p7_tracealign_Seqs()>. * Possible flags include <p7_DIGITIZE>, <p7_ALL_CONSENSUS_COLS>, * and <p7_TRIM>; they may be OR'ed together. Otherwise, pass * <p7_DEFAULT> to set no flags. * * Caller may optionally provide <inc_sqarr>, <inc_trarr>, and * <inc_n> to include additional sequences in the alignment * (the jackhmmer query, for example). Otherwise, pass <NULL, NULL, 0>. * * Returns: <eslOK> on success, and <*ret_msa> points to a new MSA that * the caller is responsible for freeing. * * Returns <eslFAIL> if there are no reported domains that * satisfy reporting thresholds, in which case <*ret_msa> * is <NULL>. * * Throws: <eslEMEM> on allocation failure; <eslECORRUPT> on * unexpected internal data corruption. * * Xref: J4/29: incept. * J4/76: added inc_sqarr, inc_trarr, inc_n, optflags */ int p7_tophits_Alignment(const P7_TOPHITS *th, const ESL_ALPHABET *abc, ESL_SQ **inc_sqarr, P7_TRACE **inc_trarr, int inc_n, int optflags, ESL_MSA **ret_msa) { ESL_SQ **sqarr = NULL; P7_TRACE **trarr = NULL; ESL_MSA *msa = NULL; int ndom = 0; int h, d, y; int M; int status; /* How many domains will be included in the new alignment? * We also set model size M here; every alignment has a copy. */ for (h = 0; h < th->N; h++) if (th->hit[h]->flags & p7_IS_INCLUDED) { for (d = 0; d < th->hit[h]->ndom; d++) if (th->hit[h]->dcl[d].is_included) ndom++; } if (inc_n+ndom == 0) { status = eslFAIL; goto ERROR; } if (inc_n) M = inc_trarr[0]->M; else M = th->hit[0]->dcl[0].ad->M; /* Allocation */ ESL_ALLOC(sqarr, sizeof(ESL_SQ *) * (ndom + inc_n)); ESL_ALLOC(trarr, sizeof(P7_TRACE *) * (ndom + inc_n)); /* Inclusion of preexisting seqs, traces: make copy of pointers */ for (y = 0; y < inc_n; y++) { sqarr[y] = inc_sqarr[y]; trarr[y] = inc_trarr[y]; } for (; y < (ndom+inc_n); y++) { sqarr[y] = NULL; trarr[y] = NULL; } /* Make faux sequences, traces from hit list */ y = inc_n; for (h = 0; h < th->N; h++) if (th->hit[h]->flags & p7_IS_INCLUDED) { for (d = 0; d < th->hit[h]->ndom; d++) if (th->hit[h]->dcl[d].is_included) { if ((status = p7_alidisplay_Backconvert(th->hit[h]->dcl[d].ad, abc, &(sqarr[y]), &(trarr[y]))) != eslOK) goto ERROR; y++; } } /* Make the multiple alignment */ if ((status = p7_tracealign_Seqs(sqarr, trarr, inc_n+ndom, M, optflags, NULL, &msa)) != eslOK) goto ERROR; /* Clean up */ for (y = inc_n; y < ndom+inc_n; y++) esl_sq_Destroy(sqarr[y]); for (y = inc_n; y < ndom+inc_n; y++) p7_trace_Destroy(trarr[y]); free(sqarr); free(trarr); *ret_msa = msa; return eslOK; ERROR: if (sqarr != NULL) { for (y = inc_n; y < ndom+inc_n; y++) if (sqarr[y] != NULL) esl_sq_Destroy(sqarr[y]); free(sqarr); } if (trarr != NULL) { for (y = inc_n; y < ndom+inc_n; y++) if (trarr[y] != NULL) p7_trace_Destroy(trarr[y]); free(trarr); } if (msa != NULL) esl_msa_Destroy(msa); *ret_msa = NULL; return status; }
int main(int argc, char **argv) { ESL_GETOPTS *go = NULL; /* application configuration */ char *hmmfile = NULL; /* HMM file name */ char *seqfile = NULL; /* sequence file name */ char *mapfile = NULL; /* optional mapped MSA file name */ int infmt = eslSQFILE_UNKNOWN; int outfmt = eslMSAFILE_STOCKHOLM; P7_HMMFILE *hfp = NULL; /* open HMM file */ ESL_SQFILE *sqfp = NULL; /* open sequence file */ char *outfile = NULL; /* output filename */ FILE *ofp = stdout; /* output stream */ ESL_SQ **sq = NULL; /* array of sequences */ void *p = NULL; /* tmp ptr for reallocation */ int nseq = 0; /* # of sequences in <seqfile> */ int mapseq = 0; /* # of sequences in mapped MSA */ int totseq = 0; /* # of seqs in all sources */ ESL_ALPHABET *abc = NULL; /* alphabet (set from the HMM file)*/ P7_HMM *hmm = NULL; P7_TRACE **tr = NULL; /* array of tracebacks */ ESL_MSA *msa = NULL; /* resulting multiple alignment */ int msaopts = 0; /* flags to p7_tracealign_Seqs() */ int idx; /* counter over seqs, traces */ int status; /* easel/hmmer return code */ char errbuf[eslERRBUFSIZE]; /* Parse the command line */ go = esl_getopts_Create(options); if (esl_opt_ProcessCmdline(go, argc, argv) != eslOK) cmdline_failure(argv[0], "Failed to parse command line: %s\n", go->errbuf); if (esl_opt_VerifyConfig(go) != eslOK) cmdline_failure(argv[0], "Error in configuration: %s\n", go->errbuf); if (esl_opt_GetBoolean(go, "-h") ) cmdline_help (argv[0], go); if (esl_opt_ArgNumber(go) != 2) cmdline_failure(argv[0], "Incorrect number of command line arguments.\n"); hmmfile = esl_opt_GetArg(go, 1); seqfile = esl_opt_GetArg(go, 2); if (strcmp(hmmfile, "-") == 0 && strcmp(seqfile, "-") == 0) cmdline_failure(argv[0], "Either <hmmfile> or <seqfile> may be '-' (to read from stdin), but not both.\n"); msaopts |= p7_ALL_CONSENSUS_COLS; /* default as of 3.1 */ if (esl_opt_GetBoolean(go, "--trim")) msaopts |= p7_TRIM; /* If caller declared an input format, decode it */ if (esl_opt_IsOn(go, "--informat")) { infmt = esl_sqio_EncodeFormat(esl_opt_GetString(go, "--informat")); if (infmt == eslSQFILE_UNKNOWN) cmdline_failure(argv[0], "%s is not a recognized input sequence file format\n", esl_opt_GetString(go, "--informat")); } /* Determine output alignment file format */ outfmt = eslx_msafile_EncodeFormat(esl_opt_GetString(go, "--outformat")); if (outfmt == eslMSAFILE_UNKNOWN) cmdline_failure(argv[0], "%s is not a recognized output MSA file format\n", esl_opt_GetString(go, "--outformat")); /* Open output stream */ if ( (outfile = esl_opt_GetString(go, "-o")) != NULL) { if ((ofp = fopen(outfile, "w")) == NULL) cmdline_failure(argv[0], "failed to open -o output file %s for writing\n", outfile); } /* If caller forced an alphabet on us, create the one the caller wants */ if (esl_opt_GetBoolean(go, "--amino")) abc = esl_alphabet_Create(eslAMINO); else if (esl_opt_GetBoolean(go, "--dna")) abc = esl_alphabet_Create(eslDNA); else if (esl_opt_GetBoolean(go, "--rna")) abc = esl_alphabet_Create(eslRNA); /* Read one HMM, and make sure there's only one. */ status = p7_hmmfile_OpenE(hmmfile, NULL, &hfp, errbuf); if (status == eslENOTFOUND) p7_Fail("File existence/permissions problem in trying to open HMM file %s.\n%s\n", hmmfile, errbuf); else if (status == eslEFORMAT) p7_Fail("File format problem in trying to open HMM file %s.\n%s\n", hmmfile, errbuf); else if (status != eslOK) p7_Fail("Unexpected error %d in opening HMM file %s.\n%s\n", status, hmmfile, errbuf); status = p7_hmmfile_Read(hfp, &abc, &hmm); if (status == eslEFORMAT) p7_Fail("Bad file format in HMM file %s:\n%s\n", hfp->fname, hfp->errbuf); else if (status == eslEINCOMPAT) p7_Fail("HMM in %s is not in the expected %s alphabet\n", hfp->fname, esl_abc_DecodeType(abc->type)); else if (status == eslEOF) p7_Fail("Empty HMM file %s? No HMM data found.\n", hfp->fname); else if (status != eslOK) p7_Fail("Unexpected error in reading HMMs from %s\n", hfp->fname); status = p7_hmmfile_Read(hfp, &abc, NULL); if (status != eslEOF) p7_Fail("HMM file %s does not contain just one HMM\n", hfp->fname); p7_hmmfile_Close(hfp); /* We're going to build up two arrays: sequences and traces. * If --mapali option is chosen, the first set of sequences/traces is from the provided alignment */ if ( (mapfile = esl_opt_GetString(go, "--mapali")) != NULL) { map_alignment(mapfile, hmm, &sq, &tr, &mapseq); } totseq = mapseq; /* Read digital sequences into an array (possibly concat'ed onto mapped seqs) */ status = esl_sqfile_OpenDigital(abc, seqfile, infmt, NULL, &sqfp); if (status == eslENOTFOUND) p7_Fail("Failed to open sequence file %s for reading\n", seqfile); else if (status == eslEFORMAT) p7_Fail("Sequence file %s is empty or misformatted\n", seqfile); else if (status != eslOK) p7_Fail("Unexpected error %d opening sequence file %s\n", status, seqfile); ESL_RALLOC(sq, p, sizeof(ESL_SQ *) * (totseq + 1)); sq[totseq] = esl_sq_CreateDigital(abc); nseq = 0; while ((status = esl_sqio_Read(sqfp, sq[totseq+nseq])) == eslOK) { nseq++; ESL_RALLOC(sq, p, sizeof(ESL_SQ *) * (totseq+nseq+1)); sq[totseq+nseq] = esl_sq_CreateDigital(abc); } if (status == eslEFORMAT) esl_fatal("Parse failed (sequence file %s):\n%s\n", sqfp->filename, esl_sqfile_GetErrorBuf(sqfp)); else if (status != eslEOF) esl_fatal("Unexpected error %d reading sequence file %s", status, sqfp->filename); esl_sqfile_Close(sqfp); totseq += nseq; /* Remaining initializations, including trace array allocation */ ESL_RALLOC(tr, p, sizeof(P7_TRACE *) * totseq); for (idx = mapseq; idx < totseq; idx++) tr[idx] = p7_trace_CreateWithPP(); p7_tracealign_computeTraces(hmm, sq, mapseq, totseq - mapseq, tr); p7_tracealign_Seqs(sq, tr, totseq, hmm->M, msaopts, hmm, &msa); eslx_msafile_Write(ofp, msa, outfmt); for (idx = 0; idx <= totseq; idx++) esl_sq_Destroy(sq[idx]); /* including sq[nseq] because we overallocated */ for (idx = 0; idx < totseq; idx++) p7_trace_Destroy(tr[idx]); free(sq); free(tr); esl_msa_Destroy(msa); p7_hmm_Destroy(hmm); if (ofp != stdout) fclose(ofp); esl_alphabet_Destroy(abc); esl_getopts_Destroy(go); return eslOK; ERROR: return status; }