/* Function: p7_oprofile_MPIPackSize() * Synopsis: Calculates size needed to pack an OPROFILE. * Incept: MSF, Wed Oct 21, 2009 [Janelia] * * Purpose: Calculate an upper bound on the number of bytes * that <p7_oprofile_MPIPack()> will need to pack an * OPROFILE <om> in a packed MPI message for MPI * communicator <comm>; return that number of bytes * in <*ret_n>. * * Returns: <eslOK> on success, and <*ret_n> contains the answer. * * Throws: <eslESYS> if an MPI call fails, and <*ret_n> is 0. */ int p7_oprofile_MPIPackSize(P7_OPROFILE *om, MPI_Comm comm, int *ret_n) { int status; int n = 0; int K = om->abc->Kp; int len = 0; int cnt; int sz; int Q4 = p7O_NQF(om->M); int Q8 = p7O_NQW(om->M); int Q16 = p7O_NQB(om->M); int vsz = sizeof(__m128i); /* MSV Filter information */ if (MPI_Pack_size(5, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(1, MPI_FLOAT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(vsz*Q16, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += (K*sz); /* Viterbi Filter information */ if (MPI_Pack_size(1, MPI_SHORT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += ((p7O_NXSTATES*p7O_NXTRANS+2)*sz); if (MPI_Pack_size(2, MPI_FLOAT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(K*vsz*Q8, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(8*vsz*Q8, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; /* Forward/Backward information */ if (MPI_Pack_size(1, MPI_FLOAT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += (p7O_NXSTATES*p7O_NXTRANS*sz); if (MPI_Pack_size(K*vsz*Q4, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(8*vsz*Q4, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; /* disk offsets */ if (MPI_Pack_size(1, MPI_LONG_LONG_INT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += ((p7_NOFFSETS+2)*sz); /* annotation info */ if (om->name != NULL) len += strlen(om->name) + 1; if (om->acc != NULL) len += strlen(om->acc) + 1; if (om->desc != NULL) len += strlen(om->desc) + 1; if (om->rf != NULL) len += strlen(om->rf) + 1; if (om->mm != NULL) len += strlen(om->mm) + 1; if (om->cs != NULL) len += strlen(om->cs) + 1; if (om->consensus != NULL) len += strlen(om->consensus) + 1; if (MPI_Pack_size(7, MPI_INT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(len, MPI_CHAR, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; cnt = p7_NEVPARAM + p7_NCUTOFFS + p7_MAXABET; if (MPI_Pack_size(cnt, MPI_FLOAT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; /* current model size */ if (MPI_Pack_size(4, MPI_INT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; if (MPI_Pack_size(1, MPI_FLOAT, comm, &sz) != 0) ESL_XEXCEPTION(eslESYS, "pack size failed"); n += sz; *ret_n = n; return eslOK; ERROR: *ret_n = 0; return status; }
/* Function: p7_omx_Create() * Synopsis: Create an optimized dynamic programming matrix. * Incept: SRE, Tue Nov 27 08:48:20 2007 [Janelia] * * Purpose: Allocates a reusable, resizeable <P7_OMX> for models up to * size <allocM> and target sequences up to length * <allocL/allocXL>, for use by any of the various optimized * DP routines. * * To allocate the very memory-efficient one-row matrix * used by *Filter() and *Score() functions that only * calculate scores, <allocM=M>, <allocL=0>, and * <allocXL=0>. * * To allocate the reasonably memory-efficient linear * arrays used by *Parser() functions that only keep * special (X) state scores, <allocM=M>, <allocL=0>, * and <allocXL=L>. * * To allocate a complete matrix suitable for functions * that need the whole DP matrix for traceback, sampling, * posterior decoding, or reestimation, <allocM=M> and * <allocL=allocXL=L>. * * Returns: a pointer to the new <P7_OMX>. * * Throws: <NULL> on allocation failure. */ P7_OMX * p7_omx_Create(int allocM, int allocL, int allocXL) { P7_OMX *ox = NULL; int i; int status; ESL_ALLOC(ox, sizeof(P7_OMX)); ox->dp_mem = NULL; ox->dpb = NULL; ox->dpw = NULL; ox->dpf = NULL; ox->xmx = NULL; ox->x_mem = NULL; /* DP matrix will be allocated for allocL+1 rows 0,1..L; allocQ4*p7X_NSCELLS columns */ ox->allocR = allocL+1; ox->validR = ox->allocR; ox->allocQ4 = p7O_NQF(allocM); ox->allocQ8 = p7O_NQW(allocM); ox->allocQ16 = p7O_NQB(allocM); ox->ncells = ox->allocR * ox->allocQ4 * 4; /* # of DP cells allocated, where 1 cell contains MDI */ /* floats always dominate; +15 for alignment */ ESL_ALLOC(ox->dp_mem, sizeof(vector float) * ox->allocR * ox->allocQ4 * p7X_NSCELLS + 15); ESL_ALLOC(ox->dpb, sizeof(vector unsigned char *) * ox->allocR); ESL_ALLOC(ox->dpw, sizeof(vector signed short *) * ox->allocR); ESL_ALLOC(ox->dpf, sizeof(vector float *) * ox->allocR); /* DP memory shared by <dpb>, <dpw>, <dpf> */ ox->dpb[0] = (vector unsigned char *) ((unsigned long int) ((char *) ox->dp_mem + 15) & (~0xf)); ox->dpw[0] = (vector signed short *) ox->dpb[0]; ox->dpf[0] = (vector float *) ox->dpb[0]; for (i = 1; i <= allocL; i++) { ox->dpf[i] = ox->dpf[0] + i * ox->allocQ4 * p7X_NSCELLS; ox->dpw[i] = ox->dpw[0] + i * ox->allocQ8 * p7X_NSCELLS; ox->dpb[i] = ox->dpb[0] + i * ox->allocQ16; } ox->allocXR = allocXL+1; ESL_ALLOC(ox->x_mem, sizeof(float) * ox->allocXR * p7X_NXCELLS + 15); ox->xmx = (float *) ((unsigned long int) ((char *) ox->x_mem + 15) & (~0xf)); ox->M = 0; ox->L = 0; ox->totscale = 0.0; ox->has_own_scales = TRUE; /* most matrices are Forward, control their own scale factors */ #ifdef p7_DEBUGGING ox->debugging = FALSE; ox->dfp = NULL; #endif return ox; ERROR: p7_omx_Destroy(ox); return NULL; }
/* Function: p7_ViterbiFilter() * Synopsis: Calculates Viterbi score, vewy vewy fast, in limited precision. * Incept: SRE, Tue Nov 27 09:15:24 2007 [Janelia] * * Purpose: Calculates an approximation of the Viterbi score for sequence * <dsq> of length <L> residues, using optimized profile <om>, * and a preallocated one-row DP matrix <ox>. Return the * estimated Viterbi score (in nats) in <ret_sc>. * * Score may overflow (and will, on high-scoring * sequences), but will not underflow. * * The model must be in a local alignment mode; other modes * cannot provide the necessary guarantee of no underflow. * * This is a striped SIMD Viterbi implementation using Intel * VMX integer intrinsics \citep{Farrar07}, in reduced * precision (signed words, 16 bits). * * Args: dsq - digital target sequence, 1..L * L - length of dsq in residues * om - optimized profile * ox - DP matrix * ret_sc - RETURN: Viterbi score (in nats) * * Returns: <eslOK> on success; * <eslERANGE> if the score overflows; in this case * <*ret_sc> is <eslINFINITY>, and the sequence can * be treated as a high-scoring hit. * * Throws: <eslEINVAL> if <ox> allocation is too small, or if * profile isn't in a local alignment mode. (Must be in local * alignment mode because that's what helps us guarantee * limited dynamic range.) * * Xref: [Farrar07] for ideas behind striped SIMD DP. * J2/46-47 for layout of HMMER's striped SIMD DP. * J2/50 for single row DP. * J2/60 for reduced precision (epu8) * J2/65 for initial benchmarking * J2/66 for precision maximization * J4/138-140 for reimplementation in 16-bit precision */ int p7_ViterbiFilter(const ESL_DSQ *dsq, int L, const P7_OPROFILE *om, P7_OMX *ox, float *ret_sc) { vector signed short mpv, dpv, ipv; /* previous row values */ vector signed short sv; /* temp storage of 1 curr row value in progress */ vector signed short dcv; /* delayed storage of D(i,q+1) */ vector signed short xEv; /* E state: keeps max for Mk->E as we go */ vector signed short xBv; /* B state: splatted vector of B[i-1] for B->Mk calculations */ vector signed short Dmaxv; /* keeps track of maximum D cell on row */ int16_t xE, xB, xC, xJ, xN; /* special states' scores */ int16_t Dmax; /* maximum D cell score on row */ int i; /* counter over sequence positions 1..L */ int q; /* counter over vectors 0..nq-1 */ int Q; /* segment length: # of vectors */ vector signed short *dp; /* using {MDI}MX(q) macro requires initialization of <dp> */ vector signed short *rsc; /* will point at om->ru[x] for residue x[i] */ vector signed short *tsc; /* will point into (and step thru) om->tu */ vector signed short negInfv; Q = p7O_NQW(om->M); dp = ox->dpw[0]; /* Check that the DP matrix is ok for us. */ if (Q > ox->allocQ8) ESL_EXCEPTION(eslEINVAL, "DP matrix allocated too small"); if (om->mode != p7_LOCAL && om->mode != p7_UNILOCAL) ESL_EXCEPTION(eslEINVAL, "Fast filter only works for local alignment"); ox->M = om->M; negInfv = esl_vmx_set_s16((signed short)-32768); /* Initialization. In unsigned arithmetic, -infinity is -32768 */ for (q = 0; q < Q; q++) MMXo(q) = IMXo(q) = DMXo(q) = negInfv; xN = om->base_w; xB = xN + om->xw[p7O_N][p7O_MOVE]; xJ = -32768; xC = -32768; xE = -32768; #if p7_DEBUGGING if (ox->debugging) p7_omx_DumpVFRow(ox, 0, xE, 0, xJ, xB, xC); /* first 0 is <rowi>: do header. second 0 is xN: always 0 here. */ #endif for (i = 1; i <= L; i++) { rsc = om->rwv[dsq[i]]; tsc = om->twv; dcv = negInfv; /* "-infinity" */ xEv = negInfv; Dmaxv = negInfv; xBv = esl_vmx_set_s16(xB); /* Right shifts by 1 value (2 bytes). 4,8,12,x becomes x,4,8,12. * Because ia32 is littlendian, this means a left bit shift. * Zeros shift on automatically; replace it with -32768. */ mpv = MMXo(Q-1); mpv = vec_sld(negInfv, mpv, 14); dpv = DMXo(Q-1); dpv = vec_sld(negInfv, dpv, 14); ipv = IMXo(Q-1); ipv = vec_sld(negInfv, ipv, 14); for (q = 0; q < Q; q++) { /* Calculate new MMXo(i,q); don't store it yet, hold it in sv. */ sv = vec_adds(xBv, *tsc); tsc++; sv = vec_max (sv, vec_adds(mpv, *tsc)); tsc++; sv = vec_max (sv, vec_adds(ipv, *tsc)); tsc++; sv = vec_max (sv, vec_adds(dpv, *tsc)); tsc++; sv = vec_adds(sv, *rsc); rsc++; xEv = vec_max(xEv, sv); /* Load {MDI}(i-1,q) into mpv, dpv, ipv; * {MDI}MX(q) is then the current, not the prev row */ mpv = MMXo(q); dpv = DMXo(q); ipv = IMXo(q); /* Do the delayed stores of {MD}(i,q) now that memory is usable */ MMXo(q) = sv; DMXo(q) = dcv; /* Calculate the next D(i,q+1) partially: M->D only; * delay storage, holding it in dcv */ dcv = vec_adds(sv, *tsc); tsc++; Dmaxv = vec_max(dcv, Dmaxv); /* Calculate and store I(i,q) */ sv = vec_adds(mpv, *tsc); tsc++; IMXo(q)= vec_max(sv, vec_adds(ipv, *tsc)); tsc++; } /* Now the "special" states, which start from Mk->E (->C, ->J->B) */ xE = esl_vmx_hmax_s16(xEv); if (xE >= 32767) { *ret_sc = eslINFINITY; return eslERANGE; } /* immediately detect overflow */ xN = xN + om->xw[p7O_N][p7O_LOOP]; xC = ESL_MAX(xC + om->xw[p7O_C][p7O_LOOP], xE + om->xw[p7O_E][p7O_MOVE]); xJ = ESL_MAX(xJ + om->xw[p7O_J][p7O_LOOP], xE + om->xw[p7O_E][p7O_LOOP]); xB = ESL_MAX(xJ + om->xw[p7O_J][p7O_MOVE], xN + om->xw[p7O_N][p7O_MOVE]); /* and now xB will carry over into next i, and xC carries over after i=L */ /* Finally the "lazy F" loop (sensu [Farrar07]). We can often * prove that we don't need to evaluate any D->D paths at all. * * The observation is that if we can show that on the next row, * B->M(i+1,k) paths always dominate M->D->...->D->M(i+1,k) paths * for all k, then we don't need any D->D calculations. * * The test condition is: * max_k D(i,k) + max_k ( TDD(k-2) + TDM(k-1) - TBM(k) ) < xB(i) * So: * max_k (TDD(k-2) + TDM(k-1) - TBM(k)) is precalc'ed in om->dd_bound; * max_k D(i,k) is why we tracked Dmaxv; * xB(i) was just calculated above. */ Dmax = esl_vmx_hmax_s16(Dmaxv); if (Dmax + om->ddbound_w > xB) { /* Now we're obligated to do at least one complete DD path to be sure. */ /* dcv has carried through from end of q loop above */ dcv = vec_sld(negInfv, dcv, 14); tsc = om->twv + 7*Q; /* set tsc to start of the DD's */ for (q = 0; q < Q; q++) { DMXo(q) = vec_max(dcv, DMXo(q)); dcv = vec_adds(DMXo(q), *tsc); tsc++; } /* We may have to do up to three more passes; the check * is for whether crossing a segment boundary can improve * our score. */ do { dcv = vec_sld(negInfv, dcv, 14); tsc = om->twv + 7*Q; /* set tsc to start of the DD's */ for (q = 0; q < Q; q++) { if (! vec_any_gt(dcv, DMXo(q))) break; DMXo(q) = vec_max(dcv, DMXo(q)); dcv = vec_adds(DMXo(q), *tsc); tsc++; } } while (q == Q); } else /* not calculating DD? then just store the last M->D vector calc'ed.*/ DMXo(0) = vec_sld(negInfv, dcv, 14); #if p7_DEBUGGING if (ox->debugging) p7_omx_DumpVFRow(ox, i, xE, 0, xJ, xB, xC); #endif } /* end loop over sequence residues 1..L */ /* finally C->T */ if (xC > -32768) { *ret_sc = (float) xC + (float) om->xw[p7O_C][p7O_MOVE] - (float) om->base_w; /* *ret_sc += L * om->ncj_roundoff; see J4/150 for rationale: superceded by -3.0nat approximation*/ *ret_sc /= om->scale_w; *ret_sc -= 3.0; /* the NN/CC/JJ=0,-3nat approximation: see J5/36. That's ~ L \log \frac{L}{L+3}, for our NN,CC,JJ contrib */ } else *ret_sc = -eslINFINITY; return eslOK; }
/* Function: p7_omx_DumpVFRow() * Synopsis: Dump current row of ViterbiFilter (int16) part of <ox> matrix. * Incept: SRE, Wed Jul 30 16:43:21 2008 [Janelia] * * Purpose: Dump current row of ViterbiFilter (int16) part of DP * matrix <ox> for diagnostics, and include the values of * specials <xE>, etc. The index <rowi> for the current row * is used as a row label. * * If <rowi> is 0, print a header first too. * * The output format is coordinated with <p7_gmx_Dump()> to * facilitate comparison to a known answer. * * Returns: <eslOK> on success. * * Throws: <eslEMEM> on allocation failure. */ int p7_omx_DumpVFRow(P7_OMX *ox, int rowi, int16_t xE, int16_t xN, int16_t xJ, int16_t xB, int16_t xC) { vector signed short *dp = ox->dpw[0]; /* must set <dp> before using {MDI}MX macros */ int M = ox->M; int Q = p7O_NQW(M); int16_t *v = NULL; /* array of unstriped, uninterleaved scores */ int q,z,k; union { vector signed short v; int16_t i[8]; } tmp; int status; ESL_ALLOC(v, sizeof(int16_t) * ((Q*8)+1)); v[0] = 0; /* Header (if we're on the 0th row) */ if (rowi == 0) { fprintf(ox->dfp, " "); for (k = 0; k <= M; k++) fprintf(ox->dfp, "%6d ", k); fprintf(ox->dfp, "%6s %6s %6s %6s %6s\n", "E", "N", "J", "B", "C"); fprintf(ox->dfp, " "); for (k = 0; k <= M+5; k++) fprintf(ox->dfp, "%6s ", "------"); fprintf(ox->dfp, "\n"); } /* Unpack and unstripe, then print M's. */ for (q = 0; q < Q; q++) { tmp.v = MMXo(q); for (z = 0; z < 8; z++) v[q+Q*z+1] = tmp.i[z]; } fprintf(ox->dfp, "%4d M ", rowi); for (k = 0; k <= M; k++) fprintf(ox->dfp, "%6d ", v[k]); /* The specials */ fprintf(ox->dfp, "%6d %6d %6d %6d %6d\n", xE, xN, xJ, xB, xC); /* Unpack and unstripe, then print I's. */ for (q = 0; q < Q; q++) { tmp.v = IMXo(q); for (z = 0; z < 8; z++) v[q+Q*z+1] = tmp.i[z]; } fprintf(ox->dfp, "%4d I ", rowi); for (k = 0; k <= M; k++) fprintf(ox->dfp, "%6d ", v[k]); fprintf(ox->dfp, "\n"); /* Unpack, unstripe, then print D's. */ for (q = 0; q < Q; q++) { tmp.v = DMXo(q); for (z = 0; z < 8; z++) v[q+Q*z+1] = tmp.i[z]; } fprintf(ox->dfp, "%4d D ", rowi); for (k = 0; k <= M; k++) fprintf(ox->dfp, "%6d ", v[k]); fprintf(ox->dfp, "\n\n"); free(v); return eslOK; ERROR: free(v); return status; }
/* Function: p7_omx_GrowTo() * Synopsis: Assure that a DP matrix is big enough. * Incept: SRE, Thu Dec 20 09:27:07 2007 [Janelia] * * Purpose: Assures that an optimized DP matrix <ox> is allocated for * a model up to <allocM> in length; if not, reallocate to * make it so. * * Because the optimized matrix is one-row, only the model * length matters; the target sequence length isn't * relevant. * * Returns: <eslOK> on success, and <gx> may be reallocated upon * return; any data that may have been in <gx> must be * assumed to be invalidated. * * Throws: <eslEMEM> on allocation failure, and any data that may * have been in <gx> must be assumed to be invalidated. */ int p7_omx_GrowTo(P7_OMX *ox, int allocM, int allocL, int allocXL) { void *p; int nqf = p7O_NQF(allocM); /* segment length; total # of striped vectors for uchar */ int nqw = p7O_NQW(allocM); /* segment length; total # of striped vectors for float */ int nqb = p7O_NQB(allocM); /* segment length; total # of striped vectors for float */ size_t ncells = (allocL+1) * nqf * 4; int reset_row_pointers = FALSE; int i; int status; /* If all possible dimensions are already satisfied, the matrix is fine */ if (ox->allocQ4*4 >= allocM && ox->validR > allocL && ox->allocXR >= allocXL+1) return eslOK; /* If the main matrix is too small in cells, reallocate it; * and we'll need to realign/reset the row pointers later. */ if (ncells > ox->ncells) { ESL_RALLOC(ox->dp_mem, p, sizeof(vector float) * (allocL+1) * nqf * p7X_NSCELLS + 15); ox->ncells = ncells; reset_row_pointers = TRUE; } /* If the X beams are too small, reallocate them. */ if (allocXL+1 >= ox->allocXR) { ESL_RALLOC(ox->x_mem, p, sizeof(float) * (allocXL+1) * p7X_NXCELLS + 15); ox->allocXR = allocXL+1; ox->xmx = (float *) ((unsigned long int) ((char *) ox->x_mem + 15) & (~0xf)); } /* If there aren't enough rows, reallocate the row pointers; we'll * realign and reset them later. */ if (allocL >= ox->allocR) { ESL_RALLOC(ox->dpb, p, sizeof(vector unsigned char *) * (allocL+1)); ESL_RALLOC(ox->dpw, p, sizeof(vector signed short * ) * (allocL+1)); ESL_RALLOC(ox->dpf, p, sizeof(vector float *) * (allocL+1)); ox->allocR = allocL+1; reset_row_pointers = TRUE; } /* must we widen the rows? */ if (allocM > ox->allocQ4*4) reset_row_pointers = TRUE; /* must we set some more valid row pointers? */ if (allocL >= ox->validR) reset_row_pointers = TRUE; /* now reset the row pointers, if needed */ if (reset_row_pointers) { ox->dpb[0] = (vector unsigned char *) ((unsigned long int) ((char *) ox->dp_mem + 15) & (~0xf)); ox->dpw[0] = (vector signed short *) ox->dpb[0]; ox->dpf[0] = (vector float *) ox->dpb[0]; ox->validR = ESL_MIN( ox->ncells / (nqf * 4), ox->allocR); for (i = 1; i < ox->validR; i++) { ox->dpb[i] = ox->dpb[0] + i * nqb; ox->dpw[i] = ox->dpw[0] + i * nqw * p7X_NSCELLS; ox->dpf[i] = ox->dpf[0] + i * nqf * p7X_NSCELLS; } ox->allocQ4 = nqf; ox->allocQ8 = nqw; ox->allocQ16 = nqb; } ox->M = 0; ox->L = 0; return eslOK; ERROR: return status; }
/* Function: p7_oprofile_Write() * Synopsis: Write an optimized profile in two files. * Incept: SRE, Wed Jan 21 10:35:28 2009 [Janelia] * * Purpose: Write the MSV filter part of <om> to open binary stream * <ffp>, and the rest of the model to <pfp>. These two * streams will typically be <.h3f> and <.h3p> files * being created by hmmpress. * * Args: ffp - open binary stream for saving MSV filter part * pfp - open binary stream for saving rest of profile * om - optimized profile to save * * Returns: <eslOK> on success. * * Returns <eslFAIL> on any write failure; for example, * if disk is full. * * Throws: (no abnormal error conditions) */ int p7_oprofile_Write(FILE *ffp, FILE *pfp, P7_OPROFILE *om) { int Q4 = p7O_NQF(om->M); int Q8 = p7O_NQW(om->M); int Q16 = p7O_NQB(om->M); int n = strlen(om->name); int x; /* <ffp> is the part of the oprofile that MSVFilter() needs */ if (fwrite((char *) &(v3b_fmagic), sizeof(uint32_t), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->M), sizeof(int), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->abc->type), sizeof(int), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &n, sizeof(int), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) om->name, sizeof(char), n+1, ffp) != n+1) return eslFAIL; if (fwrite((char *) &(om->tbm_b), sizeof(uint8_t), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->tec_b), sizeof(uint8_t), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->tjb_b), sizeof(uint8_t), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->scale_b), sizeof(float), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->base_b), sizeof(uint8_t), 1, ffp) != 1) return eslFAIL; if (fwrite((char *) &(om->bias_b), sizeof(uint8_t), 1, ffp) != 1) return eslFAIL; for (x = 0; x < om->abc->Kp; x++) if (fwrite( (char *) om->rbv[x], sizeof(__m128i), Q16, ffp) != Q16) return eslFAIL; if (fwrite((char *) om->evparam, sizeof(float), p7_NEVPARAM, ffp) != p7_NEVPARAM) return eslFAIL; if (fwrite((char *) om->offs, sizeof(off_t), p7_NOFFSETS, ffp) != p7_NOFFSETS) return eslFAIL; if (fwrite((char *) om->compo, sizeof(float), p7_MAXABET, ffp) != p7_MAXABET) return eslFAIL; /* <pfp> gets the rest of the oprofile */ if (fwrite((char *) &(v3b_pmagic), sizeof(uint32_t), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->M), sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->abc->type), sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &n, sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) om->name, sizeof(char), n+1, pfp) != n+1) return eslFAIL; if (om->acc == NULL) { n = 0; if (fwrite((char *) &n, sizeof(int), 1, pfp) != 1) return eslFAIL; } else { n = strlen(om->acc); if (fwrite((char *) &n, sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) om->acc, sizeof(char), n+1, pfp) != n+1) return eslFAIL; } if (om->desc == NULL) { n = 0; if (fwrite((char *) &n, sizeof(int), 1, pfp) != 1) return eslFAIL; } else { n = strlen(om->desc); if (fwrite((char *) &n, sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) om->desc, sizeof(char), n+1, pfp) != n+1) return eslFAIL; } if (fwrite((char *) om->rf, sizeof(char), om->M+2, pfp) != om->M+2) return eslFAIL; if (fwrite((char *) om->cs, sizeof(char), om->M+2, pfp) != om->M+2) return eslFAIL; if (fwrite((char *) om->consensus, sizeof(char), om->M+2, pfp) != om->M+2) return eslFAIL; /* ViterbiFilter part */ if (fwrite((char *) om->twv, sizeof(__m128i), 8*Q8, pfp) != 8*Q8) return eslFAIL; for (x = 0; x < om->abc->Kp; x++) if (fwrite( (char *) om->rwv[x], sizeof(__m128i), Q8, pfp) != Q8) return eslFAIL; for (x = 0; x < p7O_NXSTATES; x++) if (fwrite( (char *) om->xw[x], sizeof(int16_t), p7O_NXTRANS, pfp) != p7O_NXTRANS) return eslFAIL; if (fwrite((char *) &(om->scale_w), sizeof(float), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->base_w), sizeof(int16_t), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->ddbound_w), sizeof(int16_t), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->ncj_roundoff), sizeof(float), 1, pfp) != 1) return eslFAIL; /* Forward/Backward part */ if (fwrite((char *) om->tfv, sizeof(__m128), 8*Q4, pfp) != 8*Q4) return eslFAIL; for (x = 0; x < om->abc->Kp; x++) if (fwrite( (char *) om->rfv[x], sizeof(__m128), Q4, pfp) != Q4) return eslFAIL; for (x = 0; x < p7O_NXSTATES; x++) if (fwrite( (char *) om->xf[x], sizeof(float), p7O_NXTRANS, pfp) != p7O_NXTRANS) return eslFAIL; if (fwrite((char *) om->cutoff, sizeof(float), p7_NCUTOFFS, pfp) != p7_NCUTOFFS) return eslFAIL; if (fwrite((char *) &(om->nj), sizeof(float), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->mode), sizeof(int), 1, pfp) != 1) return eslFAIL; if (fwrite((char *) &(om->L) , sizeof(int), 1, pfp) != 1) return eslFAIL; return eslOK; }
/* Function: p7_oprofile_ReadRest() * Synopsis: Read the rest of an optimized profile. * Incept: SRE, Wed Jan 21 11:04:56 2009 [Janelia] * * Purpose: Read the rest of an optimized profile <om> from * the <.h3p> file associated with an open HMM * file <hfp>. * * This is the second part of a two-part calling sequence. * The <om> here must be the result of a previous * successful <p7_oprofile_ReadMSV()> call on the same * open <hfp>. * * Args: hfp - open HMM file, from which we've previously * called <p7_oprofile_ReadMSV()>. * om - optimized profile that was successfully * returned by <p7_oprofile_ReadMSV()>. * * Returns: <eslOK> on success, and <om> is now a complete * optimized profile. * * Returns <eslEFORMAT> if <hfp> has no <.h3p> file open, * or on any parsing error, and set <hfp->errbuf> to * an informative error message. * * Throws: <eslESYS> if an <fseek()> fails to reposition the * binary <.h3p> file. * * <eslEMEM> on allocation error. */ int p7_oprofile_ReadRest(P7_HMMFILE *hfp, P7_OPROFILE *om) { uint32_t magic; int M, Q4, Q8; int x,n; char *name = NULL; int alphatype; int status; #ifdef HMMER_THREADS /* lock the mutex to prevent other threads from reading from the optimized * profile at the same time. */ if (hfp->syncRead) { if (pthread_mutex_lock (&hfp->readMutex) != 0) ESL_EXCEPTION(eslESYS, "mutex lock failed"); } #endif if (hfp->errbuf != NULL) hfp->errbuf[0] = '\0'; if (hfp->pfp == NULL) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "no MSV profile file; hmmpress probably wasn't run"); /* Position the <hfp->pfp> using offset stored in <om> */ if (fseeko(hfp->pfp, om->offs[p7_POFFSET], SEEK_SET) != 0) ESL_EXCEPTION(eslESYS, "fseeko() failed"); if (! fread( (char *) &magic, sizeof(uint32_t), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read magic"); if (magic == v3a_pmagic) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "this is an outdated HMM database (3/a format); please hmmpress your HMM file again"); if (magic != v3b_pmagic) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "bad magic; not an HMM database file?"); if (! fread( (char *) &M, sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read model size M"); if (! fread( (char *) &alphatype, sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read alphabet type"); if (! fread( (char *) &n, sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read name length"); if (M != om->M) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "p/f model length mismatch"); if (alphatype != om->abc->type) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "p/f alphabet type mismatch"); ESL_ALLOC(name, sizeof(char) * (n+1)); if (! fread( (char *) name, sizeof(char), n+1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read name"); if (strcmp(name, om->name) != 0) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "p/f name mismatch"); if (! fread((char *) &n, sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read accession length"); if (n > 0) { ESL_ALLOC(om->acc, sizeof(char) * (n+1)); if (! fread( (char *) om->acc, sizeof(char), n+1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read accession"); } if (! fread((char *) &n, sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read description length"); if (n > 0) { ESL_ALLOC(om->desc, sizeof(char) * (n+1)); if (! fread( (char *) om->desc, sizeof(char), n+1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read description"); } if (! fread((char *) om->rf, sizeof(char), M+2, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read rf annotation"); if (! fread((char *) om->cs, sizeof(char), M+2, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read cs annotation"); if (! fread((char *) om->consensus, sizeof(char), M+2, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read consensus annotation"); Q4 = p7O_NQF(om->M); Q8 = p7O_NQW(om->M); if (! fread((char *) om->twv, sizeof(__m128i), 8*Q8, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <tu>, vitfilter transitions"); for (x = 0; x < om->abc->Kp; x++) if (! fread( (char *) om->rwv[x], sizeof(__m128i), Q8, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <ru>[%d], vitfilter emissions for sym %c", x, om->abc->sym[x]); for (x = 0; x < p7O_NXSTATES; x++) if (! fread( (char *) om->xw[x], sizeof(int16_t), p7O_NXTRANS, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <xu>[%d], vitfilter special transitions", x); if (! fread((char *) &(om->scale_w), sizeof(float), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read scale_w"); if (! fread((char *) &(om->base_w), sizeof(int16_t), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read base_w"); if (! fread((char *) &(om->ddbound_w), sizeof(int16_t), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read ddbound_w"); if (! fread((char *) &(om->ncj_roundoff), sizeof(float), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read ddbound_w"); if (! fread((char *) om->tfv, sizeof(__m128), 8*Q4, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <tf> transitions"); for (x = 0; x < om->abc->Kp; x++) if (! fread( (char *) om->rfv[x], sizeof(__m128), Q4, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <rf>[%d] emissions for sym %c", x, om->abc->sym[x]); for (x = 0; x < p7O_NXSTATES; x++) if (! fread( (char *) om->xf[x], sizeof(float), p7O_NXTRANS, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read <xf>[%d] special transitions", x); if (! fread((char *) om->cutoff, sizeof(float), p7_NCUTOFFS, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read Pfam score cutoffs"); if (! fread((char *) &(om->nj), sizeof(float), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read nj"); if (! fread((char *) &(om->mode), sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read mode"); if (! fread((char *) &(om->L) , sizeof(int), 1, hfp->pfp)) ESL_XFAIL(eslEFORMAT, hfp->errbuf, "failed to read L"); #ifdef HMMER_THREADS if (hfp->syncRead) { if (pthread_mutex_unlock (&hfp->readMutex) != 0) ESL_EXCEPTION(eslESYS, "mutex unlock failed"); } #endif free(name); return eslOK; ERROR: #ifdef HMMER_THREADS if (hfp->syncRead) { if (pthread_mutex_unlock (&hfp->readMutex) != 0) ESL_EXCEPTION(eslESYS, "mutex unlock failed"); } #endif if (name != NULL) free(name); return status; }
/* Function: p7_oprofile_MPIUnpack() * Synopsis: Unpacks an OPROFILE from an MPI buffer. * Incept: MSF, Wed Oct 21, 2009 [Janelia] * * Purpose: Unpack a newly allocated OPROFILE from MPI packed buffer * <buf>, starting from position <*pos>, where the total length * of the buffer in bytes is <n>. * * Caller may or may not already know what alphabet the OPROFILE * is expected to be in. A reference to the current * alphabet is passed in <abc>. If the alphabet is unknown, * pass <*abc = NULL>, and when the OPROFILE is received, an * appropriate new alphabet object is allocated and passed * back to the caller via <*abc>. If the alphabet is * already known, <*abc> is that alphabet, and the new * OPROFILE's alphabet type is verified to agree with it. This * mechanism allows an application to let the first OPROFILE * determine the alphabet type for the application, while * still keeping the alphabet under the application's scope * of control. * * Returns: <eslOK> on success. <*pos> is updated to the position of * the next element in <buf> to unpack (if any). <*ret_om> * contains a newly allocated OPROFILE, which the caller is * responsible for free'ing. If <*abc> was passed as * <NULL>, it now points to an <ESL_ALPHABET> object that * was allocated here; caller is responsible for free'ing * this. * * Returns <eslEINCOMPAT> if the OPROFILE is in a different * alphabet than <*abc> said to expect. In this case, * <*abc> is unchanged, <*buf> and <*nalloc> may have been * changed, and <*ret_om> is <NULL>. * * Throws: <eslESYS> on an MPI call failure. <eslEMEM> on allocation failure. * In either case, <*ret_om> is <NULL>, and the state of <buf> * and <*pos> is undefined and should be considered to be corrupted. */ int p7_oprofile_MPIUnpack(char *buf, int n, int *pos, MPI_Comm comm, ESL_ALPHABET **abc, P7_OPROFILE **ret_om) { int status; int M, K, atype; int len; int x; int Q4, Q8, Q16; int vsz = sizeof(vector float); P7_OPROFILE *om = NULL; if (MPI_Unpack(buf, n, pos, &M, 1, MPI_INT, comm) != 0) ESL_XEXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &atype, 1, MPI_INT, comm) != 0) ESL_XEXCEPTION(eslESYS, "mpi unpack failed"); /* Set or verify the alphabet */ if (*abc == NULL) { /* still unknown: set it, pass control of it back to caller */ if ((*abc = esl_alphabet_Create(atype)) == NULL) { status = eslEMEM; goto ERROR; } } else { /* already known: check it */ if ((*abc)->type != atype) { status = eslEINCOMPAT; goto ERROR; } } Q4 = p7O_NQF(M); Q8 = p7O_NQW(M); Q16 = p7O_NQB(M); if ((om = p7_oprofile_Create(M, *abc)) == NULL) { status = eslEMEM; goto ERROR; } om->M = M; K = (*abc)->Kp; /* model configuration */ if (MPI_Unpack(buf, n, pos, &om->L, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->mode, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->nj, 1, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); /* MSV Filter information */ if (MPI_Unpack(buf, n, pos, &om->tbm_b, 1, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->tec_b, 1, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->tjb_b, 1, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->scale_b, 1, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->base_b, 1, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->bias_b, 1, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); for (x = 0; x < K; x++) if (MPI_Unpack(buf, n, pos, om->rbv[x], vsz*Q16, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); /* Viterbi Filter information */ if (MPI_Unpack(buf, n, pos, &om->scale_w, 1, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->base_w, 1, MPI_SHORT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->ddbound_w, 1, MPI_SHORT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->ncj_roundoff, 1, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, om->twv, 8*vsz*Q8, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); for (x = 0; x < p7O_NXSTATES; x++) if (MPI_Unpack(buf, n, pos, om->xw[x], p7O_NXTRANS, MPI_SHORT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); for (x = 0; x < K; x++) if (MPI_Unpack(buf, n, pos, om->rwv[x], vsz*Q8, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); /* Forward/Backward information */ if (MPI_Unpack(buf, n, pos, om->tfv, 8*vsz*Q4, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); for (x = 0; x < p7O_NXSTATES; x++) if (MPI_Unpack(buf, n, pos, om->xf[x], p7O_NXTRANS, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); for (x = 0; x < K; x++) if (MPI_Unpack(buf, n, pos, om->rfv[x], vsz*Q4, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); /* Forward/Backward information */ if (MPI_Unpack(buf, n, pos, om->offs, p7_NOFFSETS, MPI_LONG_LONG_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->roff, 1, MPI_LONG_LONG_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, &om->eoff, 1, MPI_LONG_LONG_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); /* Annotation information */ if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->name, len); if (MPI_Unpack(buf, n, pos, om->name, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->name[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->acc, len); if (MPI_Unpack(buf, n, pos, om->acc, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->acc[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->desc, len); if (MPI_Unpack(buf, n, pos, om->desc, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->desc[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->rf, len); if (MPI_Unpack(buf, n, pos, om->rf, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->rf[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->cs, len); if (MPI_Unpack(buf, n, pos, om->cs, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->cs[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, &len, 1, MPI_INT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (len > 0) { ESL_ALLOC(om->consensus, len); if (MPI_Unpack(buf, n, pos, om->consensus, len, MPI_CHAR, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); om->consensus[len-1] = '\0'; } if (MPI_Unpack(buf, n, pos, om->evparam, p7_NEVPARAM, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, om->cutoff, p7_NCUTOFFS, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); if (MPI_Unpack(buf, n, pos, om->compo, p7_MAXABET, MPI_FLOAT, comm) != 0) ESL_EXCEPTION(eslESYS, "mpi unpack failed"); *ret_om = om; return eslOK; ERROR: if (om != NULL) p7_oprofile_Destroy(om); return status; }
/* Function: p7_oprofile_MPIPack() * Synopsis: Packs an OPROFILE into MPI buffer. * Incept: MSF, Wed Oct 21, 2009 [Janelia] * * Purpose: Packs OPROFILE <om> into an MPI packed message buffer <buf> * of length <n> bytes, starting at byte position <*position>, * for MPI communicator <comm>. * * The caller must know that <buf>'s allocation of <n> * bytes is large enough to append the packed OPROFILE at * position <*pos>. This typically requires a call to * <p7_oprofile_MPIPackSize()> first, and reallocation if * needed. * * Returns: <eslOK> on success; <buf> now contains the * packed <om>, and <*position> is set to the byte * immediately following the last byte of the OPROFILE * in <buf>. * * Throws: <eslESYS> if an MPI call fails; or <eslEMEM> if the * buffer's length <n> was overflowed in trying to pack * <msa> into <buf>. In either case, the state of * <buf> and <*position> is undefined, and both should * be considered to be corrupted. */ int p7_oprofile_MPIPack(P7_OPROFILE *om, char *buf, int n, int *pos, MPI_Comm comm) { int K = om->abc->Kp; int atype = om->abc->type; int len; int x; int Q4 = p7O_NQF(om->M); int Q8 = p7O_NQW(om->M); int Q16 = p7O_NQB(om->M); int vsz = sizeof(vector float); /* model configuration */ if (MPI_Pack(&om->M, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&atype, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->L, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->mode, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->nj, 1, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); /* MSV Filter information */ if (MPI_Pack(&om->tbm_b, 1, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->tec_b, 1, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->tjb_b, 1, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->scale_b, 1, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->base_b, 1, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->bias_b, 1, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); for (x = 0; x < K; x++) if (MPI_Pack( om->rbv[x], vsz*Q16, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); /* Viterbi Filter information */ if (MPI_Pack(&om->scale_w, 1, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->base_w, 1, MPI_SHORT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->ddbound_w, 1, MPI_SHORT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->ncj_roundoff, 1, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack( om->twv, 8*vsz*Q8, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); for (x = 0; x < p7O_NXSTATES; x++) if (MPI_Pack( om->xw[x], p7O_NXTRANS, MPI_SHORT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); for (x = 0; x < K; x++) if (MPI_Pack( om->rwv[x], vsz*Q8, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); /* Forward/Backward information */ if (MPI_Pack( om->tfv, 8*vsz*Q4, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); for (x = 0; x < p7O_NXSTATES; x++) if (MPI_Pack( om->xf[x], p7O_NXTRANS, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); for (x = 0; x < K; x++) if (MPI_Pack( om->rfv[x], vsz*Q4, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); /* Forward/Backward information */ if (MPI_Pack( om->offs, p7_NOFFSETS, MPI_LONG_LONG_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->roff, 1, MPI_LONG_LONG_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack(&om->eoff, 1, MPI_LONG_LONG_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); /* Annotation information */ len = (om->name != NULL) ? strlen(om->name)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->name, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); len = (om->acc != NULL) ? strlen(om->acc)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->acc, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); len = (om->desc != NULL) ? strlen(om->desc)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->desc, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); len = (om->rf != NULL) ? strlen(om->rf)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->rf, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); len = (om->cs != NULL) ? strlen(om->cs)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->cs, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); len = (om->consensus != NULL) ? strlen(om->consensus)+1 : 0; if (MPI_Pack(&len, 1, MPI_INT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (len > 0) if (MPI_Pack( om->consensus, len, MPI_CHAR, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack( om->evparam, p7_NEVPARAM, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack( om->cutoff, p7_NCUTOFFS, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (MPI_Pack( om->compo, p7_MAXABET, MPI_FLOAT, buf, n, pos, comm) != 0) ESL_EXCEPTION(eslESYS, "pack failed"); if (*pos > n) ESL_EXCEPTION(eslEMEM, "buffer overflow"); return eslOK; }
/* Function: p7_ViterbiFilter_longtarget() * Synopsis: Finds windows within potentially long sequence blocks with Viterbi * scores above threshold (vewy vewy fast, in limited precision) * * Purpose: Calculates an approximation of the Viterbi score for regions * of sequence <dsq>, using optimized profile <om>, and a pre- * allocated one-row DP matrix <ox>, and captures the positions * at which such regions exceed the score required to be * significant in the eyes of the calling function (usually * p=0.001). * * The resulting landmarks are converted to subsequence * windows by the calling function * * The model must be in a local alignment mode; other modes * cannot provide the necessary guarantee of no underflow. * * This is a striped SIMD Viterbi implementation using Intel * VMX integer intrinsics \citep{Farrar07}, in reduced * precision (signed words, 16 bits). * * Args: dsq - digital target sequence, 1..L * L - length of dsq in residues * om - optimized profile * ox - DP matrix * filtersc - null or bias correction, required for translating a P-value threshold into a score threshold * P - p-value below which a region is captured as being above threshold * windowlist - RETURN: array of hit windows (start and end of diagonal) for the above-threshold areas * * Returns: <eslOK> on success; * * Throws: <eslEINVAL> if <ox> allocation is too small, or if * profile isn't in a local alignment mode. (Must be in local * alignment mode because that's what helps us guarantee * limited dynamic range.) * * Xref: See p7_ViterbiFilter() */ int p7_ViterbiFilter_longtarget(const ESL_DSQ *dsq, int L, const P7_OPROFILE *om, P7_OMX *ox, float filtersc, double P, P7_HMM_WINDOWLIST *windowlist) { vector signed short mpv, dpv, ipv; /* previous row values */ vector signed short sv; /* temp storage of 1 curr row value in progress */ vector signed short dcv; /* delayed storage of D(i,q+1) */ vector signed short xEv; /* E state: keeps max for Mk->E as we go */ vector signed short xBv; /* B state: splatted vector of B[i-1] for B->Mk calculations */ vector signed short Dmaxv; /* keeps track of maximum D cell on row */ int16_t xE, xB, xC, xJ, xN; /* special states' scores */ int16_t Dmax; /* maximum D cell score on row */ int i; /* counter over sequence positions 1..L */ int q; /* counter over vectors 0..nq-1 */ int Q = p7O_NQW(om->M); /* segment length: # of vectors */ vector signed short *dp = ox->dpw[0]; /* using {MDI}MX(q) macro requires initialization of <dp> */ vector signed short *rsc; /* will point at om->ru[x] for residue x[i] */ vector signed short *tsc; /* will point into (and step thru) om->tu */ vector signed short negInfv; int16_t sc_thresh; float invP; int z; union { vector signed short v; int16_t i[8]; } tmp; windowlist->count = 0; /* * In p7_ViterbiFilter, converting from a scaled int Viterbi score * S (aka xE the score getting to state E) to a probability * goes like this: * vsc = S + om->xw[p7O_E][p7O_MOVE] + om->xw[p7O_C][p7O_MOVE] - om->base_w * ret_sc /= om->scale_w; * vsc -= 3.0; * P = esl_gumbel_surv((vfsc - filtersc) / eslCONST_LOG2 , om->evparam[p7_VMU], om->evparam[p7_VLAMBDA]); * and we're computing the threshold vsc, so invert it: * (vsc - filtersc) / eslCONST_LOG2 = esl_gumbel_invsurv( P, om->evparam[p7_VMU], om->evparam[p7_VLAMBDA]) * vsc = filtersc + eslCONST_LOG2 * esl_gumbel_invsurv( P, om->evparam[p7_VMU], om->evparam[p7_VLAMBDA]) * vsc += 3.0 * vsc *= om->scale_w * S = vsc - (float)om->xw[p7O_E][p7O_MOVE] - (float)om->xw[p7O_C][p7O_MOVE] + (float)om->base_w */ invP = esl_gumbel_invsurv(P, om->evparam[p7_VMU], om->evparam[p7_VLAMBDA]); sc_thresh = (int) ceil ( ( (filtersc + (eslCONST_LOG2 * invP) + 3.0) * om->scale_w ) - (float)om->xw[p7O_E][p7O_MOVE] - (float)om->xw[p7O_C][p7O_MOVE] + (float)om->base_w ); /* Check that the DP matrix is ok for us. */ if (Q > ox->allocQ8) ESL_EXCEPTION(eslEINVAL, "DP matrix allocated too small"); if (om->mode != p7_LOCAL && om->mode != p7_UNILOCAL) ESL_EXCEPTION(eslEINVAL, "Fast filter only works for local alignment"); ox->M = om->M; negInfv = esl_vmx_set_s16((signed short)-32768); /* Initialization. In unsigned arithmetic, -infinity is -32768 */ for (q = 0; q < Q; q++) MMXo(q) = IMXo(q) = DMXo(q) = negInfv; xN = om->base_w; xB = xN + om->xw[p7O_N][p7O_MOVE]; xJ = -32768; xC = -32768; xE = -32768; #if p7_DEBUGGING if (ox->debugging) p7_omx_DumpVFRow(ox, 0, xE, 0, xJ, xB, xC); /* first 0 is <rowi>: do header. second 0 is xN: always 0 here. */ #endif for (i = 1; i <= L; i++) { rsc = om->rwv[dsq[i]]; tsc = om->twv; dcv = negInfv; /* "-infinity" */ xEv = negInfv; Dmaxv = negInfv; xBv = esl_vmx_set_s16(xB); /* Right shifts by 1 value (2 bytes). 4,8,12,x becomes x,4,8,12. * Because ia32 is littlendian, this means a left bit shift. * Zeros shift on automatically; replace it with -32768. */ mpv = MMXo(Q-1); mpv = vec_sld(negInfv, mpv, 14); dpv = DMXo(Q-1); dpv = vec_sld(negInfv, dpv, 14); ipv = IMXo(Q-1); ipv = vec_sld(negInfv, ipv, 14); for (q = 0; q < Q; q++) { /* Calculate new MMXo(i,q); don't store it yet, hold it in sv. */ sv = vec_adds(xBv, *tsc); tsc++; sv = vec_max (sv, vec_adds(mpv, *tsc)); tsc++; sv = vec_max (sv, vec_adds(ipv, *tsc)); tsc++; sv = vec_max (sv, vec_adds(dpv, *tsc)); tsc++; sv = vec_adds(sv, *rsc); rsc++; xEv = vec_max(xEv, sv); /* Load {MDI}(i-1,q) into mpv, dpv, ipv; * {MDI}MX(q) is then the current, not the prev row */ mpv = MMXo(q); dpv = DMXo(q); ipv = IMXo(q); /* Do the delayed stores of {MD}(i,q) now that memory is usable */ MMXo(q) = sv; DMXo(q) = dcv; /* Calculate the next D(i,q+1) partially: M->D only; * delay storage, holding it in dcv */ dcv = vec_adds(sv, *tsc); tsc++; Dmaxv = vec_max(dcv, Dmaxv); /* Calculate and store I(i,q) */ sv = vec_adds(mpv, *tsc); tsc++; IMXo(q)= vec_max(sv, vec_adds(ipv, *tsc)); tsc++; } /* Now the "special" states, which start from Mk->E (->C, ->J->B) */ xE = esl_vmx_hmax_s16(xEv); if (xE >= sc_thresh) { //hit score threshold. Add a window to the list, then reset scores. /* Unpack and unstripe, then find the position responsible for the hit */ for (q = 0; q < Q; q++) { tmp.v = MMXo(q); for (z = 0; z < 8; z++) { // unstripe if ( tmp.i[z] == xE && (q+Q*z+1) <= om->M) { // (q+Q*z+1) is the model position k at which the xE score is found p7_hmmwindow_new(windowlist, 0, i, 0, (q+Q*z+1), 1, 0.0, p7_NOCOMPLEMENT ); } } MMXo(q) = IMXo(q) = DMXo(q) = negInfv; //reset score to start search for next vit window. } } else { xN = xN + om->xw[p7O_N][p7O_LOOP]; xC = ESL_MAX(xC + om->xw[p7O_C][p7O_LOOP], xE + om->xw[p7O_E][p7O_MOVE]); xJ = ESL_MAX(xJ + om->xw[p7O_J][p7O_LOOP], xE + om->xw[p7O_E][p7O_LOOP]); xB = ESL_MAX(xJ + om->xw[p7O_J][p7O_MOVE], xN + om->xw[p7O_N][p7O_MOVE]); /* and now xB will carry over into next i, and xC carries over after i=L */ /* Finally the "lazy F" loop (sensu [Farrar07]). We can often * prove that we don't need to evaluate any D->D paths at all. * * The observation is that if we can show that on the next row, * B->M(i+1,k) paths always dominate M->D->...->D->M(i+1,k) paths * for all k, then we don't need any D->D calculations. * * The test condition is: * max_k D(i,k) + max_k ( TDD(k-2) + TDM(k-1) - TBM(k) ) < xB(i) * So: * max_k (TDD(k-2) + TDM(k-1) - TBM(k)) is precalc'ed in om->dd_bound; * max_k D(i,k) is why we tracked Dmaxv; * xB(i) was just calculated above. */ Dmax = esl_vmx_hmax_s16(Dmaxv); if (Dmax + om->ddbound_w > xB) { /* Now we're obligated to do at least one complete DD path to be sure. */ /* dcv has carried through from end of q loop above */ dcv = vec_sld(negInfv, dcv, 14); tsc = om->twv + 7*Q; /* set tsc to start of the DD's */ for (q = 0; q < Q; q++) { DMXo(q) = vec_max(dcv, DMXo(q)); dcv = vec_adds(DMXo(q), *tsc); tsc++; } /* We may have to do up to three more passes; the check * is for whether crossing a segment boundary can improve * our score. */ do { dcv = vec_sld(negInfv, dcv, 14); tsc = om->twv + 7*Q; /* set tsc to start of the DD's */ for (q = 0; q < Q; q++) { if (! vec_any_gt(dcv, DMXo(q))) break; DMXo(q) = vec_max(dcv, DMXo(q)); dcv = vec_adds(DMXo(q), *tsc); tsc++; } } while (q == Q); } else /* not calculating DD? then just store the last M->D vector calc'ed.*/ DMXo(0) = vec_sld(negInfv, dcv, 14); #if p7_DEBUGGING if (ox->debugging) p7_omx_DumpVFRow(ox, i, xE, 0, xJ, xB, xC); #endif } } /* end loop over sequence residues 1..L */ return eslOK; }