SCORE TraceBack(const ProfPos *PA, unsigned uLengthA, const ProfPos *PB, unsigned uLengthB, const SCORE *DPM_, const SCORE *DPD_, const SCORE *DPI_, PWPath &Path) { #if TRACE Log("\n"); Log("TraceBack LengthA=%u LengthB=%u\n", uLengthA, uLengthB); #endif assert(uLengthB > 0 && uLengthA > 0); const unsigned uPrefixCountA = uLengthA + 1; const unsigned uPrefixCountB = uLengthB + 1; Path.Clear(); unsigned uPrefixLengthA = uLengthA; unsigned uPrefixLengthB = uLengthB; const SCORE scoreM = DPM(uPrefixLengthA, uPrefixLengthB); SCORE scoreD = DPD(uPrefixLengthA, uPrefixLengthB); SCORE scoreI = DPI(uPrefixLengthA, uPrefixLengthB); const ProfPos &LastPPA = PA[uLengthA - 1]; const ProfPos &LastPPB = PB[uLengthB - 1]; scoreD += LastPPA.m_scoreGapClose; scoreI += LastPPB.m_scoreGapClose; char cEdgeType = cInsane; SCORE scoreMax; if (scoreM >= scoreD && scoreM >= scoreI) { scoreMax = scoreM; cEdgeType = 'M'; } else if (scoreD >= scoreM && scoreD >= scoreI) { scoreMax = scoreD; cEdgeType = 'D'; } else { assert(scoreI >= scoreM && scoreI >= scoreD); scoreMax = scoreI; cEdgeType = 'I'; } for (;;) { if ('S' == cEdgeType) break; PWEdge Edge; Edge.cType = cEdgeType; Edge.uPrefixLengthA = uPrefixLengthA; Edge.uPrefixLengthB = uPrefixLengthB; Path.PrependEdge(Edge); char cPrevEdgeType; unsigned uPrevPrefixLengthA = uPrefixLengthA; unsigned uPrevPrefixLengthB = uPrefixLengthB; switch (cEdgeType) { case 'M': { assert(uPrefixLengthA > 0); assert(uPrefixLengthB > 0); const ProfPos &PPA = PA[uPrefixLengthA - 1]; const ProfPos &PPB = PB[uPrefixLengthB - 1]; const SCORE Score = DPM(uPrefixLengthA, uPrefixLengthB); const SCORE scoreMatch = ScoreProfPos2(PPA, PPB); SCORE scoreSM; if (1 == uPrefixLengthA && 1 == uPrefixLengthB) scoreSM = scoreMatch; else scoreSM = MINUS_INFINITY; SCORE scoreMM = MINUS_INFINITY; SCORE scoreDM = MINUS_INFINITY; SCORE scoreIM = MINUS_INFINITY; if (uPrefixLengthA > 1 && uPrefixLengthB > 1) scoreMM = DPM(uPrefixLengthA-1, uPrefixLengthB-1) + scoreMatch; if (uPrefixLengthA > 1) { SCORE scoreTransDM = PA[uPrefixLengthA-2].m_scoreGapClose; scoreDM = DPD(uPrefixLengthA-1, uPrefixLengthB-1) + scoreTransDM + scoreMatch; } if (uPrefixLengthB > 1) { SCORE scoreTransIM = PB[uPrefixLengthB-2].m_scoreGapClose; scoreIM = DPI(uPrefixLengthA-1, uPrefixLengthB-1) + scoreTransIM + scoreMatch; } if (EQ(scoreMM, Score)) cPrevEdgeType = 'M'; else if (EQ(scoreDM, Score)) cPrevEdgeType = 'D'; else if (EQ(scoreIM, Score)) cPrevEdgeType = 'I'; else if (EQ(scoreSM, Score)) cPrevEdgeType = 'S'; else Quit("TraceBack: failed to match M score=%g M=%g D=%g I=%g S=%g", Score, scoreMM, scoreDM, scoreIM, scoreSM); --uPrevPrefixLengthA; --uPrevPrefixLengthB; break; } case 'D': { assert(uPrefixLengthA > 0); const SCORE Score = DPD(uPrefixLengthA, uPrefixLengthB); SCORE scoreMD = MINUS_INFINITY; SCORE scoreDD = MINUS_INFINITY; SCORE scoreSD = MINUS_INFINITY; if (uPrefixLengthB == 0) { if (uPrefixLengthA == 1) scoreSD = PA[0].m_scoreGapOpen; else scoreSD = DPD(uPrefixLengthA - 1, 0); } if (uPrefixLengthA > 1) { const ProfPos &PPA = PA[uPrefixLengthA - 1]; SCORE scoreTransMD = PPA.m_scoreGapOpen; scoreMD = DPM(uPrefixLengthA-1, uPrefixLengthB) + scoreTransMD; scoreDD = DPD(uPrefixLengthA-1, uPrefixLengthB); } if (EQ(Score, scoreMD)) cPrevEdgeType = 'M'; else if (EQ(Score, scoreDD)) cPrevEdgeType = 'D'; else if (EQ(Score, scoreSD)) cPrevEdgeType = 'S'; else Quit("TraceBack: failed to match D"); --uPrevPrefixLengthA; break; } case 'I': { assert(uPrefixLengthB > 0); const SCORE Score = DPI(uPrefixLengthA, uPrefixLengthB); SCORE scoreMI = MINUS_INFINITY; SCORE scoreII = MINUS_INFINITY; SCORE scoreSI = MINUS_INFINITY; if (uPrefixLengthA == 0) { if (uPrefixLengthB == 1) scoreSI = PB[0].m_scoreGapOpen; else scoreSI = DPI(0, uPrefixLengthB - 1); } if (uPrefixLengthB > 1) { const ProfPos &PPB = PB[uPrefixLengthB - 1]; SCORE scoreTransMI = PPB.m_scoreGapOpen; scoreMI = DPM(uPrefixLengthA, uPrefixLengthB-1) + scoreTransMI; scoreII = DPI(uPrefixLengthA, uPrefixLengthB-1); } if (EQ(Score, scoreMI)) cPrevEdgeType = 'M'; else if (EQ(Score, scoreII)) cPrevEdgeType = 'I'; else if (EQ(Score, scoreSI)) cPrevEdgeType = 'S'; else Quit("TraceBack: failed to match I"); --uPrevPrefixLengthB; break; } default: assert(false); } #if TRACE Log("Edge %c%c%u.%u", cPrevEdgeType, cEdgeType, uPrefixLengthA, uPrefixLengthB); Log("\n"); #endif cEdgeType = cPrevEdgeType; uPrefixLengthA = uPrevPrefixLengthA; uPrefixLengthB = uPrevPrefixLengthB; } return scoreMax; }
SCORE ObjScoreDP_Profs(const ProfPos *PA, const ProfPos *PB, unsigned uColCount, SCORE MatchScore[]) { //#if TRACE // Log("Profile 1:\n"); // ListProfile(PA, uColCount, &msa1); // // Log("Profile 2:\n"); // ListProfile(PB, uColCount, &msa2); //#endif SCORE scoreTotal = 0; for (unsigned uColIndex = 0; uColIndex < uColCount; ++uColIndex) { const ProfPos &PPA = PA[uColIndex]; const ProfPos &PPB = PB[uColIndex]; SCORE scoreGap = 0; SCORE scoreMatch = 0; // If gapped column... if (PPA.m_bAllGaps && PPB.m_bAllGaps) scoreGap = 0; else if (PPA.m_bAllGaps) { if (uColCount - 1 == uColIndex || !PA[uColIndex+1].m_bAllGaps) scoreGap = PPB.m_scoreGapClose; if (0 == uColIndex || !PA[uColIndex-1].m_bAllGaps) scoreGap += PPB.m_scoreGapOpen; //if (0 == scoreGap) // scoreGap = PPB.m_scoreGapExtend; } else if (PPB.m_bAllGaps) { if (uColCount - 1 == uColIndex || !PB[uColIndex+1].m_bAllGaps) scoreGap = PPA.m_scoreGapClose; if (0 == uColIndex || !PB[uColIndex-1].m_bAllGaps) scoreGap += PPA.m_scoreGapOpen; //if (0 == scoreGap) // scoreGap = PPA.m_scoreGapExtend; } else scoreMatch = ScoreProfPos2(PPA, PPB); if (0 != MatchScore) MatchScore[uColIndex] = scoreMatch; scoreTotal += scoreMatch + scoreGap; extern bool g_bTracePPScore; extern MSA *g_ptrPPScoreMSA1; extern MSA *g_ptrPPScoreMSA2; if (g_bTracePPScore) { const MSA &msa1 = *g_ptrPPScoreMSA1; const MSA &msa2 = *g_ptrPPScoreMSA2; const unsigned uSeqCount1 = msa1.GetSeqCount(); const unsigned uSeqCount2 = msa2.GetSeqCount(); for (unsigned n = 0; n < uSeqCount1; ++n) Log("%c", msa1.GetChar(n, uColIndex)); Log(" "); for (unsigned n = 0; n < uSeqCount2; ++n) Log("%c", msa2.GetChar(n, uColIndex)); Log(" %10.3f", scoreMatch); if (scoreGap != 0) Log(" %10.3f", scoreGap); Log("\n"); } } delete[] PA; delete[] PB; return scoreTotal; }
SCORE NWDASimple(const ProfPos *PA, unsigned uLengthA, const ProfPos *PB, unsigned uLengthB, PWPath &Path) { assert(uLengthB > 0 && uLengthA > 0); const unsigned uPrefixCountA = uLengthA + 1; const unsigned uPrefixCountB = uLengthB + 1; // Allocate DP matrices const size_t LM = uPrefixCountA*uPrefixCountB; SCORE *DPL_ = new SCORE[LM]; SCORE *DPM_ = new SCORE[LM]; SCORE *DPD_ = new SCORE[LM]; SCORE *DPE_ = new SCORE[LM]; SCORE *DPI_ = new SCORE[LM]; SCORE *DPJ_ = new SCORE[LM]; char *TBM_ = new char[LM]; char *TBD_ = new char[LM]; char *TBE_ = new char[LM]; char *TBI_ = new char[LM]; char *TBJ_ = new char[LM]; memset(TBM_, '?', LM); memset(TBD_, '?', LM); memset(TBE_, '?', LM); memset(TBI_, '?', LM); memset(TBJ_, '?', LM); DPM(0, 0) = 0; DPD(0, 0) = MINUS_INFINITY; DPE(0, 0) = MINUS_INFINITY; DPI(0, 0) = MINUS_INFINITY; DPJ(0, 0) = MINUS_INFINITY; DPM(1, 0) = MINUS_INFINITY; DPD(1, 0) = PA[0].m_scoreGapOpen; DPE(1, 0) = PA[0].m_scoreGapOpen2; TBD(1, 0) = 'D'; TBE(1, 0) = 'E'; DPI(1, 0) = MINUS_INFINITY; DPJ(1, 0) = MINUS_INFINITY; DPM(0, 1) = MINUS_INFINITY; DPD(0, 1) = MINUS_INFINITY; DPE(0, 1) = MINUS_INFINITY; DPI(0, 1) = PB[0].m_scoreGapOpen; DPJ(0, 1) = PB[0].m_scoreGapOpen2; TBI(0, 1) = 'I'; TBJ(0, 1) = 'J'; // Empty prefix of B is special case for (unsigned uPrefixLengthA = 2; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA) { DPM(uPrefixLengthA, 0) = MINUS_INFINITY; DPD(uPrefixLengthA, 0) = DPD(uPrefixLengthA - 1, 0) + g_scoreGapExtend.get(); DPE(uPrefixLengthA, 0) = DPE(uPrefixLengthA - 1, 0) + g_scoreGapExtend2.get(); TBD(uPrefixLengthA, 0) = 'D'; TBE(uPrefixLengthA, 0) = 'E'; DPI(uPrefixLengthA, 0) = MINUS_INFINITY; DPJ(uPrefixLengthA, 0) = MINUS_INFINITY; } // Empty prefix of A is special case for (unsigned uPrefixLengthB = 2; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB) { DPM(0, uPrefixLengthB) = MINUS_INFINITY; DPD(0, uPrefixLengthB) = MINUS_INFINITY; DPE(0, uPrefixLengthB) = MINUS_INFINITY; DPI(0, uPrefixLengthB) = DPI(0, uPrefixLengthB - 1) + g_scoreGapExtend.get(); DPJ(0, uPrefixLengthB) = DPJ(0, uPrefixLengthB - 1) + g_scoreGapExtend2.get(); TBI(0, uPrefixLengthB) = 'I'; TBJ(0, uPrefixLengthB) = 'J'; } // Special case to agree with NWFast, no D-I transitions so... DPD(uLengthA, 0) = MINUS_INFINITY; DPE(uLengthA, 0) = MINUS_INFINITY; // DPI(0, uLengthB) = MINUS_INFINITY; // DPJ(0, uLengthB) = MINUS_INFINITY; // ============ // Main DP loop // ============ SCORE scoreGapCloseB = MINUS_INFINITY; SCORE scoreGapClose2B = MINUS_INFINITY; for (unsigned uPrefixLengthB = 1; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB) { const ProfPos &PPB = PB[uPrefixLengthB - 1]; SCORE scoreGapCloseA = MINUS_INFINITY; SCORE scoreGapClose2A = MINUS_INFINITY; for (unsigned uPrefixLengthA = 1; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA) { const ProfPos &PPA = PA[uPrefixLengthA - 1]; { // Match M=LetterA+LetterB SCORE scoreLL = ScoreProfPos2(PPA, PPB); DPL(uPrefixLengthA, uPrefixLengthB) = scoreLL; SCORE scoreMM = DPM(uPrefixLengthA-1, uPrefixLengthB-1); SCORE scoreDM = DPD(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseA; SCORE scoreEM = DPE(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapClose2A; SCORE scoreIM = DPI(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseB; SCORE scoreJM = DPJ(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapClose2B; SCORE scoreBest; if (scoreMM >= scoreDM && scoreMM >= scoreEM && scoreMM >= scoreIM && scoreMM >= scoreJM) { scoreBest = scoreMM; TBM(uPrefixLengthA, uPrefixLengthB) = 'M'; } else if (scoreDM >= scoreMM && scoreDM >= scoreEM && scoreDM >= scoreIM && scoreDM >= scoreJM) { scoreBest = scoreDM; TBM(uPrefixLengthA, uPrefixLengthB) = 'D'; } else if (scoreEM >= scoreMM && scoreEM >= scoreDM && scoreEM >= scoreIM && scoreEM >= scoreJM) { scoreBest = scoreEM; TBM(uPrefixLengthA, uPrefixLengthB) = 'E'; } else if (scoreIM >= scoreMM && scoreIM >= scoreDM && scoreIM >= scoreEM && scoreIM >= scoreJM) { scoreBest = scoreIM; TBM(uPrefixLengthA, uPrefixLengthB) = 'I'; } else { assert(scoreJM >= scoreMM && scoreJM >= scoreDM && scoreJM >= scoreEM && scoreJM >= scoreIM); scoreBest = scoreJM; TBM(uPrefixLengthA, uPrefixLengthB) = 'J'; } DPM(uPrefixLengthA, uPrefixLengthB) = scoreBest + scoreLL; } { // Delete D=LetterA+GapB SCORE scoreMD = DPM(uPrefixLengthA-1, uPrefixLengthB) + PA[uPrefixLengthA-1].m_scoreGapOpen; SCORE scoreDD = DPD(uPrefixLengthA-1, uPrefixLengthB) + g_scoreGapExtend.get(); SCORE scoreBest; if (scoreMD >= scoreDD) { scoreBest = scoreMD; TBD(uPrefixLengthA, uPrefixLengthB) = 'M'; } else { assert(scoreDD >= scoreMD); scoreBest = scoreDD; TBD(uPrefixLengthA, uPrefixLengthB) = 'D'; } DPD(uPrefixLengthA, uPrefixLengthB) = scoreBest; } { // Delete E=LetterA+GapB SCORE scoreME = DPM(uPrefixLengthA-1, uPrefixLengthB) + PA[uPrefixLengthA-1].m_scoreGapOpen2; SCORE scoreEE = DPE(uPrefixLengthA-1, uPrefixLengthB) + g_scoreGapExtend2.get(); SCORE scoreBest; if (scoreME >= scoreEE) { scoreBest = scoreME; TBE(uPrefixLengthA, uPrefixLengthB) = 'M'; } else { assert(scoreEE >= scoreME); scoreBest = scoreEE; TBE(uPrefixLengthA, uPrefixLengthB) = 'E'; } DPE(uPrefixLengthA, uPrefixLengthB) = scoreBest; } // Insert I=GapA+LetterB { SCORE scoreMI = DPM(uPrefixLengthA, uPrefixLengthB-1) + PB[uPrefixLengthB - 1].m_scoreGapOpen; SCORE scoreII = DPI(uPrefixLengthA, uPrefixLengthB-1) + g_scoreGapExtend.get(); SCORE scoreBest; if (scoreMI >= scoreII) { scoreBest = scoreMI; TBI(uPrefixLengthA, uPrefixLengthB) = 'M'; } else { assert(scoreII > scoreMI); scoreBest = scoreII; TBI(uPrefixLengthA, uPrefixLengthB) = 'I'; } DPI(uPrefixLengthA, uPrefixLengthB) = scoreBest; } // Insert J=GapA+LetterB { SCORE scoreMJ = DPM(uPrefixLengthA, uPrefixLengthB-1) + PB[uPrefixLengthB - 1].m_scoreGapOpen2; SCORE scoreJJ = DPJ(uPrefixLengthA, uPrefixLengthB-1) + g_scoreGapExtend2.get(); SCORE scoreBest; if (scoreMJ >= scoreJJ) { scoreBest = scoreMJ; TBJ(uPrefixLengthA, uPrefixLengthB) = 'M'; } else { assert(scoreJJ > scoreMJ); scoreBest = scoreJJ; TBJ(uPrefixLengthA, uPrefixLengthB) = 'J'; } DPJ(uPrefixLengthA, uPrefixLengthB) = scoreBest; } scoreGapCloseA = PPA.m_scoreGapClose; scoreGapClose2A = PPA.m_scoreGapClose2; } scoreGapCloseB = PPB.m_scoreGapClose; scoreGapClose2B = PPB.m_scoreGapClose2; } #if TRACE Log("\n"); Log("DA Simple DPL:\n"); ListDP(DPL_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple DPM:\n"); ListDP(DPM_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple DPD:\n"); ListDP(DPD_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple DPE:\n"); ListDP(DPE_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple DPI:\n"); ListDP(DPI_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple DPJ:\n"); ListDP(DPJ_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple TBM:\n"); ListTB(TBM_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple TBD:\n"); ListTB(TBD_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple TBE:\n"); ListTB(TBE_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple TBI:\n"); ListTB(TBI_, PA, PB, uPrefixCountA, uPrefixCountB); Log("\n"); Log("DA Simple TBJ:\n"); ListTB(TBJ_, PA, PB, uPrefixCountA, uPrefixCountB); #endif // Trace-back // ========== Path.Clear(); // Find last edge SCORE M = DPM(uLengthA, uLengthB); SCORE D = DPD(uLengthA, uLengthB) + PA[uLengthA-1].m_scoreGapClose; SCORE E = DPE(uLengthA, uLengthB) + PA[uLengthA-1].m_scoreGapClose2; SCORE I = DPI(uLengthA, uLengthB) + PB[uLengthB-1].m_scoreGapClose; SCORE J = DPJ(uLengthA, uLengthB) + PB[uLengthB-1].m_scoreGapClose2; char cEdgeType = '?'; SCORE BestScore = M; cEdgeType = 'M'; if (D > BestScore) { cEdgeType = 'D'; BestScore = D; } if (E > BestScore) { cEdgeType = 'E'; BestScore = E; } if (I > BestScore) { cEdgeType = 'I'; BestScore = I; } if (J > BestScore) { cEdgeType = 'J'; BestScore = J; } #if TRACE Log("DA Simple: MAB=%.4g DAB=%.4g EAB=%.4g IAB=%.4g JAB=%.4g best=%c\n", M, D, E, I, J, cEdgeType); #endif unsigned PLA = uLengthA; unsigned PLB = uLengthB; for (;;) { PWEdge Edge; Edge.cType = XlatEdgeType(cEdgeType); Edge.uPrefixLengthA = PLA; Edge.uPrefixLengthB = PLB; #if TRACE Log("Prepend %c%d.%d\n", Edge.cType, PLA, PLB); #endif Path.PrependEdge(Edge); switch (cEdgeType) { case 'M': assert(PLA > 0); assert(PLB > 0); cEdgeType = TBM(PLA, PLB); --PLA; --PLB; break; case 'D': assert(PLA > 0); cEdgeType = TBD(PLA, PLB); --PLA; break; case 'E': assert(PLA > 0); cEdgeType = TBE(PLA, PLB); --PLA; break; case 'I': assert(PLB > 0); cEdgeType = TBI(PLA, PLB); --PLB; break; case 'J': assert(PLB > 0); cEdgeType = TBJ(PLA, PLB); --PLB; break; default: Quit("Invalid edge %c", cEdgeType); } if (0 == PLA && 0 == PLB) break; } Path.Validate(); // SCORE Score = TraceBack(PA, uLengthA, PB, uLengthB, DPM_, DPD_, DPI_, Path); #if TRACE SCORE scorePath = FastScorePath2(PA, uLengthA, PB, uLengthB, Path); Path.LogMe(); Log("Score = %s Path = %s\n", LocalScoreToStr(BestScore), LocalScoreToStr(scorePath)); #endif if (g_bKeepSimpleDP.get()) { g_DPM.get() = DPM_; g_DPD.get() = DPD_; g_DPE.get() = DPE_; g_DPI.get() = DPI_; g_DPJ.get() = DPJ_; g_TBM.get() = TBM_; g_TBD.get() = TBD_; g_TBE.get() = TBE_; g_TBI.get() = TBI_; g_TBJ.get() = TBJ_; } else { delete[] DPM_; delete[] DPD_; delete[] DPE_; delete[] DPI_; delete[] DPJ_; delete[] TBM_; delete[] TBD_; delete[] TBE_; delete[] TBI_; delete[] TBJ_; } return BestScore; }
SCORE SW(const ProfPos *PA, unsigned uLengthA, const ProfPos *PB, unsigned uLengthB, PWPath &Path) { assert(uLengthB > 0 && uLengthA > 0); const unsigned uPrefixCountA = uLengthA + 1; const unsigned uPrefixCountB = uLengthB + 1; // Allocate DP matrices const size_t LM = uPrefixCountA*uPrefixCountB; SCORE *DPM_ = new SCORE[LM]; SCORE *DPD_ = new SCORE[LM]; SCORE *DPI_ = new SCORE[LM]; DPM(0, 0) = 0; DPD(0, 0) = MINUS_INFINITY; DPI(0, 0) = MINUS_INFINITY; DPM(1, 0) = MINUS_INFINITY; DPD(1, 0) = MINUS_INFINITY; DPI(1, 0) = MINUS_INFINITY; DPM(0, 1) = MINUS_INFINITY; DPD(0, 1) = MINUS_INFINITY; DPI(0, 1) = MINUS_INFINITY; // Empty prefix of B is special case for (unsigned uPrefixLengthA = 2; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA) { // M=LetterA+LetterB, impossible with empty prefix DPM(uPrefixLengthA, 0) = MINUS_INFINITY; // D=LetterA+GapB, never optimal in local alignment with gap penalties DPD(uPrefixLengthA, 0) = MINUS_INFINITY; // I=GapA+LetterB, impossible with empty prefix DPI(uPrefixLengthA, 0) = MINUS_INFINITY; } // Empty prefix of A is special case for (unsigned uPrefixLengthB = 2; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB) { // M=LetterA+LetterB, impossible with empty prefix DPM(0, uPrefixLengthB) = MINUS_INFINITY; // D=LetterA+GapB, impossible with empty prefix DPD(0, uPrefixLengthB) = MINUS_INFINITY; // I=GapA+LetterB, never optimal in local alignment with gap penalties DPI(0, uPrefixLengthB) = MINUS_INFINITY; } SCORE scoreMax = MINUS_INFINITY; unsigned uPrefixLengthAMax = uInsane; unsigned uPrefixLengthBMax = uInsane; // ============ // Main DP loop // ============ SCORE scoreGapCloseB = MINUS_INFINITY; for (unsigned uPrefixLengthB = 1; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB) { const ProfPos &PPB = PB[uPrefixLengthB - 1]; SCORE scoreGapCloseA = MINUS_INFINITY; for (unsigned uPrefixLengthA = 1; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA) { const ProfPos &PPA = PA[uPrefixLengthA - 1]; { // Match M=LetterA+LetterB SCORE scoreLL = ScoreProfPos2(PPA, PPB); SCORE scoreMM = DPM(uPrefixLengthA-1, uPrefixLengthB-1); SCORE scoreDM = DPD(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseA; SCORE scoreIM = DPI(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseB; SCORE scoreBest; if (scoreMM >= scoreDM && scoreMM >= scoreIM) scoreBest = scoreMM; else if (scoreDM >= scoreMM && scoreDM >= scoreIM) scoreBest = scoreDM; else { assert(scoreIM >= scoreMM && scoreIM >= scoreDM); scoreBest = scoreIM; } if (scoreBest < 0) scoreBest = 0; scoreBest += scoreLL; if (scoreBest > scoreMax) { scoreMax = scoreBest; uPrefixLengthAMax = uPrefixLengthA; uPrefixLengthBMax = uPrefixLengthB; } DPM(uPrefixLengthA, uPrefixLengthB) = scoreBest; } { // Delete D=LetterA+GapB SCORE scoreMD = DPM(uPrefixLengthA-1, uPrefixLengthB) + PA[uPrefixLengthA-1].m_scoreGapOpen; SCORE scoreDD = DPD(uPrefixLengthA-1, uPrefixLengthB); SCORE scoreBest; if (scoreMD >= scoreDD) scoreBest = scoreMD; else { assert(scoreDD >= scoreMD); scoreBest = scoreDD; } DPD(uPrefixLengthA, uPrefixLengthB) = scoreBest; } // Insert I=GapA+LetterB { SCORE scoreMI = DPM(uPrefixLengthA, uPrefixLengthB-1) + PB[uPrefixLengthB - 1].m_scoreGapOpen; SCORE scoreII = DPI(uPrefixLengthA, uPrefixLengthB-1); SCORE scoreBest; if (scoreMI >= scoreII) scoreBest = scoreMI; else { assert(scoreII > scoreMI); scoreBest = scoreII; } DPI(uPrefixLengthA, uPrefixLengthB) = scoreBest; } scoreGapCloseA = PPA.m_scoreGapClose; } scoreGapCloseB = PPB.m_scoreGapClose; } #if TRACE Log("DPM:\n"); ListDP(DPM_, PA, PB, uPrefixLengthA, uPrefixLengthB); Log("DPD:\n"); ListDP(DPD_, PA, PB, uPrefixLengthA, uPrefixLengthB); Log("DPI:\n"); ListDP(DPI_, PA, PB, uPrefixLengthA, uPrefixLengthB); #endif assert(scoreMax == DPM(uPrefixLengthAMax, uPrefixLengthBMax)); TraceBackSW(PA, uLengthA, PB, uLengthB, DPM_, DPD_, DPI_, uPrefixLengthAMax, uPrefixLengthBMax, Path); #if TRACE SCORE scorePath = FastScorePath2(PA, uLengthA, PB, uLengthB, Path); Path.LogMe(); Log("Score = %s Path = %s\n", LocalScoreToStr(scoreMax), LocalScoreToStr(scorePath)); #endif delete[] DPM_; delete[] DPD_; delete[] DPI_; return scoreMax; }