/* * hhbackwardalgorithmscalar.C * * Created on: Apr 10, 2014 * Author: Martin Steinegger, Stefan Haunsberger */ #include "hhposteriordecoder.h" void PosteriorDecoder::backwardAlgorithm(HMM & q, HMM & t, Hit & hit, PosteriorMatrix & p_mm, ViterbiMatrix & celloff_matrix, float shift, const int elem) { // Variable declarations int i, j; // query and template match state indices double pmin; // this is the scaled 1 in the SW algorithm that represents a starting alignment double Cshift = pow(2.0, shift); // score offset transformed into factor in lin-space double scale_prod = scale[q.L + 1]; int jmin; // std::cout << hit.ssm2 << "\t" << ssw << std::endl; // Initialization of top row, i.e. cells (0,j) for (int j = t.L; j >= 1; j--) { if (celloff_matrix.getCellOff(q.L,j,elem)){ p_mm.setPosteriorValue(q.L, j, 0.0); m_prev[j].mm = 0.0; }else { m_prev[j].mm = scale[q.L + 1]; p_mm.setPosteriorValue(q.L, j, p_mm.getPosteriorValue(q.L, j) * scale[q.L + 1] / hit.Pforward); } m_prev[j].mi = m_prev[j].dg = 0.0; } double final_scale_prod = scale[q.L + 1]; for (int i = q.L - 1; i >= 1; i--) { final_scale_prod *= scale[i + 1]; if (final_scale_prod < DBL_MIN * 100) final_scale_prod = 0.0; } if (m_local) pmin = scale[q.L + 1]; else pmin = 0.0; // transform pmin (for local alignment) to scale of present (i'th) row // Backward algorithm // Loop through query positions i for (i = q.L - 1; i >= 1; i--) { // if (v>=5) printf("\n"); if (hit.self) jmin = imin(i + SELFEXCL, t.L); else jmin = 1; // jmin = i+SELFEXCL and not (i+SELFEXCL+1) to set matrix element at boundary to zero // Initialize cells at (i,t.L+1) scale_prod *= scale[i + 1]; if (scale_prod < DBL_MIN * 100) scale_prod = 0.0; if (celloff_matrix.getCellOff(i, t.L, elem)) { p_mm.setPosteriorValue(i, t.L, 0.0); m_curr[t.L].mm = 0.0; } else { m_curr[t.L].mm = scale_prod; p_mm.setPosteriorValue(i, t.L, p_mm.getPosteriorValue(i, t.L) * scale_prod / hit.Pforward); } pmin *= scale[i + 1]; // transform pmin (for local alignment) to scale of present (i'th) row if (pmin < DBL_MIN * 100) pmin = 0.0; m_curr[t.L].im = m_curr[t.L].mi = m_curr[t.L].dg = m_curr[t.L].gd = 0.0; memset(m_curr+jmin, 0, (t.L - 1) * sizeof(PosteriorMatrixCol)); // Loop through template positions j for (j = t.L - 1; j >= jmin; j--) { // Recursion relations // printf("S[%i][%i]=%4.1f ",i,j,Score(q->p[i],t->p[j])); if (!(celloff_matrix.getCellOff(i,j, elem))) { double pmatch = m_prev[j + 1].mm * ProbFwd(q.p[i + 1], t.p[j + 1]) * fpow2(Viterbi::ScoreSS(&q,&t,i+1,j+1, ssw, hit.ssm2, S73, S37, S33)) * Cshift * scale[i + 1]; // save backward profile; More efficient alternative by JS m_curr[j].mm = (+pmin // MM -> EE (End/End, for local alignment) + pmatch * q.tr[i][M2M] * t.tr[j][M2M] // MM -> MM + m_curr[j + 1].gd * t.tr[j][M2D] // MM -> GD (q.tr[i][M2M] is already contained in GD->MM) + m_curr[j + 1].im * q.tr[i][M2I] * t.tr[j][M2M] // MM -> IM + m_prev[j].dg * q.tr[i][M2D] * scale[i + 1] // MM -> DG (t.tr[j][M2M] is already contained in DG->MM) + m_prev[j].mi * q.tr[i][M2M] * t.tr[j][M2I] * scale[i + 1] // MM -> MI ); m_curr[j].gd = (+pmatch * q.tr[i][M2M] * t.tr[j][D2M] // GD -> MM + m_curr[j + 1].gd * t.tr[j][D2D] // DG -> DG ); m_curr[j].im = (+pmatch * q.tr[i][I2M] * t.tr[j][M2M] // IM -> MM + m_curr[j + 1].im * q.tr[i][I2I] * t.tr[j][M2M] // IM -> IM ); m_curr[j].dg = (+pmatch * q.tr[i][D2M] * t.tr[j][M2M] // DG -> MM + m_prev[j].dg * q.tr[i][D2D] * scale[i + 1] // DG -> DG // + B_GD[i][j+1] * q.tr[i][D2M] * t.tr[j][M2D] // DG -> GD ); m_curr[j].mi = (+pmatch * q.tr[i][M2M] * t.tr[j][I2M] // MI -> MM + m_prev[j].mi * q.tr[i][M2M] * t.tr[j][I2I] * scale[i + 1] // MI -> MI // + B_IM[i][j+1] * q.tr[i][M2I] * t.tr[j][I2M] // MI -> IM ); float substitutionScore = ProbFwd(q.p[i], t.p[j]); float actual_backward_single = substitutionScore * Cshift * m_curr[j].mm / hit.Pforward * final_scale_prod / scale_prod; if(actual_backward_single > m_back_forward_matrix_threshold) { MACTriple trip; trip.i = i; trip.j = j; trip.value = actual_backward_single; m_backward_entries.push_back(trip); } } // end else } //end for j // Calculate posterior probability from Forward and Backward matrix elements for (int jj = jmin; jj <= (t.L - 1); jj++) { p_mm.multiplyPosteriorValue(i, jj, m_curr[jj].mm / hit.Pforward); } std::swap(m_prev, m_curr); } // end for i /* // Debugging output if (v>=6) { const int i0=0, i1=q.L; const int j0=0, j1=t.L; double scale_prod[q.L+2]; scale_prod[q.L] = scale[q.L+1]; for (i=q.L-1; i>=1; i--) scale_prod[i] = scale_prod[i+1] * scale[i+1]; printf("\nBwd scale "); for (j=j0; j<=j1; ++j) printf("%3i ",j); printf("\n"); for (i=i0; i<=i1; ++i) { printf("%3i: %9.3G ",i,1/scale_prod[i]); for (j=j0; j<=j1; ++j) printf("%7.4f ",(B_MM[i][j]+B_MI[i][j]+B_IM[i][j]+B_DG[i][j]+B_GD[i][j]) * (ProbFwd(q->p[i],t->p[j])*fpow2(ScoreSS(q,t,i,j)) * Cshift)); printf("\n"); // printf("MM %9.5f ",1/scale[i]); // for (j=j0; j<=j1; ++j) // printf("%7.4f ",B_MM[i][j] * (ProbFwd(q->p[i],t->p[j])*fpow2(ScoreSS(q,t,i,j)) * Cshift)); // printf("\n"); } printf("\nPost scale "); for (j=j0; j<=j1; ++j) printf("%3i ",j); printf("\n"); for (i=i0; i<=i1; ++i) { printf("%3i: %9.3G ",i,1/scale_prod[i]); for (j=j0; j<=j1; ++j) printf("%7.4f ",B_MM[i][j]*P_MM[i][j]/Pforward); printf("\n"); } printf("\n"); } if (v>=4) printf("\nForward total probability ratio: %8.3G\n",Pforward); */ return; }