/* Function: p7_GOATrace() * Synopsis: Optimal accuracy decoding: traceback. * Incept: SRE, Fri Feb 29 12:59:11 2008 [Janelia] * * Purpose: The traceback stage of the optimal accuracy decoding algorithm * \citep{Kall05}. * * Caller provides the OA DP matrix <gx> that was just * calculated by <p7_GOptimalAccuracy()>, as well as the * posterior decoding matrix <pp>, which was calculated by * Forward/Backward on a target sequence of length <L> * using the query model <gm>. * * Caller provides an empty traceback structure <tr> to * hold the result, allocated to hold optional posterior * probability annotation on residues (with * <p7_trace_CreateWithPP()>, generally). This will be * internally reallocated as needed for larger traces. * * Args: gm - query profile * pp - posterior decoding matrix created by <p7_PosteriorDecoding()> * gx - OA DP matrix calculated by <p7_OptimalAccuracyDP()> * tr - RESULT: OA traceback, allocated with posterior probs * * Returns: <eslOK> on success, and <tr> contains the OA traceback. * * Throws: <eslEMEM> on allocation error. */ int p7_GOATrace(const P7_PROFILE *gm, const P7_GMX *pp, const P7_GMX *gx, P7_TRACE *tr) { int i = gx->L; /* position in seq (1..L) */ int k = 0; /* position in model (1..M) */ float postprob; int sprv, scur; int status; #ifdef p7_DEBUGGING if (tr->N != 0) ESL_EXCEPTION(eslEINVAL, "trace isn't empty: forgot to Reuse()?"); #endif if ((status = p7_trace_AppendWithPP(tr, p7T_T, k, i, 0.0)) != eslOK) return status; if ((status = p7_trace_AppendWithPP(tr, p7T_C, k, i, 0.0)) != eslOK) return status; sprv = p7T_C; while (sprv != p7T_S) { switch (sprv) { case p7T_M: scur = select_m(gm, gx, i, k); k--; i--; break; case p7T_D: scur = select_d(gm, gx, i, k); k--; break; case p7T_I: scur = select_i(gm, gx, i, k); i--; break; case p7T_N: scur = select_n(i); break; case p7T_C: scur = select_c(gm, pp, gx, i); break; case p7T_J: scur = select_j(gm, pp, gx, i); break; case p7T_E: scur = select_e(gm, gx, i, &k); break; case p7T_B: scur = select_b(gm, gx, i); break; default: ESL_EXCEPTION(eslEINVAL, "bogus state in traceback"); } if (scur == -1) ESL_EXCEPTION(eslEINVAL, "OA traceback choice failed"); postprob = get_postprob(pp, scur, sprv, k, i); if ((status = p7_trace_AppendWithPP(tr, scur, k, i, postprob)) != eslOK) return status; /* For NCJ, we had to defer i decrement. */ if ( (scur == p7T_N || scur == p7T_J || scur == p7T_C) && scur == sprv) i--; sprv = scur; } tr->M = gm->M; tr->L = gx->L; return p7_trace_Reverse(tr); }
/* Function: p7_StochasticTrace() * Synopsis: Sample a traceback from a Forward matrix * Incept: SRE, Fri Aug 8 17:40:18 2008 [UA217, IAD-SFO] * * Purpose: Perform a stochastic traceback from Forward matrix <ox>, * using random number generator <r>, in order to sample an * alignment of model <om> to digital sequence <dsq> of * length <L>. * * The sampled traceback is returned in <tr>, which the * caller provides with at least an initial allocation; * the <tr> allocation will be grown as needed here. * * Args: r - source of random numbers * dsq - digital sequence being aligned, 1..L * L - length of dsq * om - profile * ox - Forward matrix to trace, LxM * tr - storage for the recovered traceback * * Returns: <eslOK> on success * * Throws: <eslEMEM> on allocation error. * <eslEINVAL> on several types of problems, including: * the trace isn't empty (wasn't Reuse()'d); */ int p7_StochasticTrace(ESL_RANDOMNESS *rng, const ESL_DSQ *dsq, int L, const P7_OPROFILE *om, const P7_OMX *ox, P7_TRACE *tr) { int i; /* position in sequence 1..L */ int k; /* position in model 1..M */ int s0, s1; /* choice of a state */ int status; if (tr->N != 0) ESL_EXCEPTION(eslEINVAL, "trace not empty; needs to be Reuse()'d?"); i = L; k = 0; if ((status = p7_trace_Append(tr, p7T_T, k, i)) != eslOK) return status; if ((status = p7_trace_Append(tr, p7T_C, k, i)) != eslOK) return status; s0 = tr->st[tr->N-1]; while (s0 != p7T_S) { switch (s0) { case p7T_M: s1 = select_m(rng, om, ox, i, k); k--; i--; break; case p7T_D: s1 = select_d(rng, om, ox, i, k); k--; break; case p7T_I: s1 = select_i(rng, om, ox, i, k); i--; break; case p7T_N: s1 = select_n(i); break; case p7T_C: s1 = select_c(rng, om, ox, i); break; case p7T_J: s1 = select_j(rng, om, ox, i); break; case p7T_E: s1 = select_e(rng, om, ox, i, &k); break; case p7T_B: s1 = select_b(rng, om, ox, i); break; default: ESL_EXCEPTION(eslEINVAL, "bogus state in traceback"); } if (s1 == -1) ESL_EXCEPTION(eslEINVAL, "Stochastic traceback choice failed"); if ((status = p7_trace_Append(tr, s1, k, i)) != eslOK) return status; if ( (s1 == p7T_N || s1 == p7T_J || s1 == p7T_C) && s1 == s0) i--; s0 = s1; } /* end traceback, at S state */ tr->M = om->M; tr->L = L; return p7_trace_Reverse(tr); }
/* Function: p7_OATrace() * Synopsis: Optimal accuracy decoding: traceback. * Incept: SRE, Mon Aug 18 13:53:33 2008 [Janelia] * * Purpose: The traceback stage of the optimal accuracy decoding algorithm * \citep{Kall05}. * * Caller provides the OA DP matrix <ox> that was just * calculated by <p7_OptimalAccuracyDP()>, as well as the * posterior decoding matrix <pp>, which was calculated by * Forward/Backward on a target sequence using the query * model <gm>. Because the calculation depends only on * <pp>, the target sequence itself need not be provided. * * The resulting optimal accuracy decoding traceback is put * in a caller-provided traceback structure <tr>, which the * caller has allocated for optional posterior probability * annotation on residues (with <p7_trace_CreateWithPP()>, * generally). This structure will be reallocated * internally if necessary. * * Args: om - profile * pp - posterior probability matrix * ox - OA matrix to trace, LxM * tr - storage for the recovered traceback * * Returns: <eslOK> on success. * * Throws: <eslEMEM> on allocation error. * <eslEINVAL> if the trace <tr> isn't empty (needs to be Reuse()'d). */ int p7_OATrace(const P7_OPROFILE *om, const P7_OMX *pp, const P7_OMX *ox, P7_TRACE *tr) { int i = ox->L; /* position in sequence 1..L */ int k = 0; /* position in model 1..M */ int s0, s1; /* choice of a state */ float postprob; int status; if (tr->N != 0) ESL_EXCEPTION(eslEINVAL, "trace not empty; needs to be Reuse()'d?"); if ((status = p7_trace_AppendWithPP(tr, p7T_T, k, i, 0.0)) != eslOK) return status; if ((status = p7_trace_AppendWithPP(tr, p7T_C, k, i, 0.0)) != eslOK) return status; s0 = tr->st[tr->N-1]; while (s0 != p7T_S) { switch (s0) { case p7T_M: s1 = select_m(om, ox, i, k); k--; i--; break; case p7T_D: s1 = select_d(om, ox, i, k); k--; break; case p7T_I: s1 = select_i(om, ox, i, k); i--; break; case p7T_N: s1 = select_n(i); break; case p7T_C: s1 = select_c(om, pp, ox, i); break; case p7T_J: s1 = select_j(om, pp, ox, i); break; case p7T_E: s1 = select_e(om, ox, i, &k); break; case p7T_B: s1 = select_b(om, ox, i); break; default: ESL_EXCEPTION(eslEINVAL, "bogus state in traceback"); } if (s1 == -1) ESL_EXCEPTION(eslEINVAL, "OA traceback choice failed"); postprob = get_postprob(pp, s1, s0, k, i); if ((status = p7_trace_AppendWithPP(tr, s1, k, i, postprob)) != eslOK) return status; if ( (s1 == p7T_N || s1 == p7T_J || s1 == p7T_C) && s1 == s0) i--; s0 = s1; } /* end traceback, at S state */ tr->M = om->M; tr->L = ox->L; return p7_trace_Reverse(tr); }
/* Basic select() implementation on top of poll() */ int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) { int timeout_ms, error, i; int poll_fd_idx = 0; int num_fds = 0; struct pollfd *req = NULL; size_t max_size = sizeof(struct pollfd) * nfds; select_d("select(nfds=%d, readfds=0x%lx, writefds=0x%lx, exceptfds=0x%lx, timeout=0x%lx)", nfds, readfds, writefds, exceptfds, timeout); if ((nfds < 0) || (nfds > FD_SETSIZE+1)) { select_d("select() failed 1"); errno = EINVAL; return -1; } /* Some programs call select() with nfds=0 in order to sleep */ if (nfds == 0) { struct timespec ts = {}; if (timeout == NULL) { errno = EINVAL; return -1; } ts.tv_sec = timeout->tv_sec; ts.tv_nsec = timeout->tv_usec * 1000; nanosleep(&ts, 0); return 0; } req = malloc(max_size); if (req == NULL) { select_d("select() failed no memory"); errno = ENOMEM; return -1; } /* prepare poll request */ for (i=0; i < nfds; i++) { short int events = 0; if (readfds) { /* read_fds */ if (FD_ISSET(i, readfds)) events = POLLIN; } if (writefds) { /* write_fds */ if (FD_ISSET(i, writefds)) events |= POLLOUT; } if (events) { req[poll_fd_idx].fd = i; req[poll_fd_idx].events = events; req[poll_fd_idx].revents = 0; poll_fd_idx++; } } if (timeout) { /* FIXME: we use a ms granularity while select uses timeval (microsec) */ timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec/1000; } else { timeout_ms = -1; } select_d("select() timeout_ms=%d", timeout_ms); /* call poll() */ error = poll(req, poll_fd_idx, timeout_ms); if (error < 0) { select_d("select() poll() failed"); free(req); return -1; } /* handle result */ if (readfds) FD_ZERO(readfds); if (writefds) FD_ZERO(writefds); if (exceptfds) FD_ZERO(exceptfds); for (i=0; i < poll_fd_idx; i++) { if (req[i].revents == 0) continue; if (req[i].revents & POLLNVAL) { errno = EBADF; error = -1; break; } bool event = false; if (readfds) { if (req[i].revents & (POLLIN | POLLHUP | POLLERR)) { FD_SET(req[i].fd, readfds); event = true; } } if (writefds) { if (req[i].revents & (POLLOUT | POLLRDHUP | POLLERR)) { FD_SET(req[i].fd, writefds); event = true; } } if (exceptfds) { if (req[i].revents & POLLPRI) { FD_SET(req[i].fd, exceptfds); event = true; } } if (event) { num_fds++; } } free(req); if (error == -1) return -1; select_d("select() return: %d", num_fds); return num_fds; }