mm_aligner.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:29k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: mm_aligner.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:04:46  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: mm_aligner.cpp,v 1000.1 2004/06/01 18:04:46 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE                          
  13.  *               National Center for Biotechnology Information
  14.  *                                                                          
  15.  *  This software/database is a "United States Government Work" under the   
  16.  *  terms of the United States Copyright Act.  It was written as part of    
  17.  *  the author's official duties as a United States Government employee and 
  18.  *  thus cannot be copyrighted.  This software/database is freely available 
  19.  *  to the public for use. The National Library of Medicine and the U.S.    
  20.  *  Government have not placed any restriction on its use or reproduction.  
  21.  *                                                                          
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy  
  23.  *  and reliability of the software and data, the NLM and the U.S.           
  24.  *  Government do not and cannot warrant the performance or results that    
  25.  *  may be obtained by using this software or data. The NLM and the U.S.    
  26.  *  Government disclaim all warranties, express or implied, including       
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.                                                                
  29.  *                                                                          
  30.  *  Please cite the author in any work or product based on this material.   
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Yuri Kapustin
  35.  *
  36.  * File Description:  CMMAligner implementation
  37.  *                   
  38.  * ===========================================================================
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include "mm_aligner_threads.hpp"
  43. #include <corelib/ncbimtx.hpp>
  44. #include <corelib/ncbi_system.hpp>
  45. #include <algo/align/align_exception.hpp>
  46. BEGIN_NCBI_SCOPE
  47. CMMAligner::CMMAligner():
  48.     m_mt(false),
  49.     m_maxthreads(1)
  50. {
  51. }
  52. CMMAligner::CMMAligner( const char* seq1, size_t len1,
  53.                         const char* seq2, size_t len2,
  54.                         const SNCBIPackedScoreMatrix* scoremat )
  55.   : CNWAligner(seq1, len1, seq2, len2, scoremat),
  56.     m_mt(false),
  57.     m_maxthreads(1)
  58. {
  59. }
  60. void CMMAligner::EnableMultipleThreads(bool allow)
  61. {
  62.     m_maxthreads = (m_mt = allow)? GetCpuCount(): 1;
  63. }
  64. CNWAligner::TScore CMMAligner::x_Run()
  65. {
  66.     m_terminate = false;
  67.     if(m_prg_callback) {
  68.         m_prg_info.m_iter_total = 2*m_SeqLen1*m_SeqLen2;
  69.         m_prg_info.m_iter_done = 0;
  70.         m_terminate = m_prg_callback(&m_prg_info);
  71.     }
  72.     if(m_terminate) {
  73.         return m_score = 0;
  74.     }
  75.     
  76.     m_score = kMin_Int;
  77.     m_TransList.clear();
  78.     m_TransList.push_back(eTS_None);
  79.     SCoordRect m (0, 0, m_SeqLen1 - 1, m_SeqLen2 - 1);
  80.     x_DoSubmatrix(m, m_TransList.end(), false, false); // top-level call
  81.     if(m_terminate) {
  82.         return m_score = 0;
  83.     }
  84.     // reverse_copy not supported by some compilers
  85.     list<ETranscriptSymbol>::const_iterator ii = m_TransList.begin();
  86.     size_t nsize = m_TransList.size() - 1;
  87.     m_Transcript.clear();
  88.     m_Transcript.resize(nsize);
  89.     for(size_t k = 1; k <= nsize; ++k)
  90.         m_Transcript[nsize - k] = *++ii;
  91.     return m_score;
  92. }
  93. // trace bit coding (four bits per value): D E Ec Fc
  94. // D:  1 if diagonal; 0 - otherwise
  95. // E:  1 if space in 1st sequence; 0 if space in 2nd sequence
  96. // Ec: 1 if gap in 1st sequence was extended; 0 if it is was opened
  97. // Fc: 1 if gap in 2nd sequence was extended; 0 if it is was opened
  98. //
  99. const unsigned char kMaskFc  = 0x0001;
  100. const unsigned char kMaskEc  = 0x0002;
  101. const unsigned char kMaskE   = 0x0004;
  102. const unsigned char kMaskD   = 0x0008;
  103. DEFINE_STATIC_FAST_MUTEX (masterlist_mutex);
  104. void CMMAligner::x_DoSubmatrix( const SCoordRect& submatr,
  105.     list<ETranscriptSymbol>::iterator translist_pos,
  106.     bool left_top, bool right_bottom )
  107. {
  108.     if( m_terminate ) {
  109.         return;
  110.     }
  111.     const int dimI = submatr.i2 - submatr.i1 + 1;
  112.     const int dimJ = submatr.j2 - submatr.j1 + 1;
  113.     if(dimI < 1 || dimJ < 1) return;
  114.     bool top_level = submatr.i1 == 0 && submatr.j1 == 0 &&
  115.         submatr.i2 == m_SeqLen1-1 && submatr.j2 == m_SeqLen2-1;
  116.     if(dimI < 3 || dimJ < 3) { // terminal case
  117.         CFastMutexGuard guard (masterlist_mutex);
  118.         list<ETranscriptSymbol> lts;
  119.         TScore score = x_RunTerm(submatr, left_top, right_bottom, lts);
  120.         if(top_level) m_score = score;
  121.         m_TransList.splice(translist_pos, lts);
  122.         return;
  123.     }
  124.     const size_t I = submatr.i1 + dimI / 2;
  125.     const size_t dim = dimJ + 1;
  126.     // run Needleman-Wunsch without storing full traceback matrix
  127.     SCoordRect rtop (submatr.i1, submatr.j1, I, submatr.j2);
  128.     vector<TScore> vEtop (dim), vFtop (dim), vGtop (dim);
  129.     vector<unsigned char> trace_top (dim);
  130.     SCoordRect rbtm (I + 1, submatr.j1, submatr.i2 , submatr.j2);
  131.     vector<TScore> vEbtm (dim), vFbtm (dim), vGbtm (dim);
  132.     vector<unsigned char> trace_btm (dim);
  133.     
  134.     if( m_mt && m_maxthreads > 1 && MM_RequestNewThread(m_maxthreads) ) {
  135.         CThreadRunOnTop* thr2 = new CThreadRunOnTop ( this, &rtop,
  136.                                             &vEtop, &vFtop, &vGtop,
  137.                                             &trace_top, left_top );
  138.         thr2->Run();
  139.         x_RunBtm(rbtm, vEbtm, vFbtm, vGbtm, trace_btm, right_bottom);
  140.         thr2->Join(0);
  141.     }
  142.     else {
  143.         x_RunTop(rtop, vEtop, vFtop, vGtop, trace_top, left_top);
  144.         x_RunBtm(rbtm, vEbtm, vFbtm, vGbtm, trace_btm, right_bottom);
  145.     }
  146.     if( m_terminate ) {
  147.         return;
  148.     }
  149.     // locate the transition point
  150.     size_t trans_pos;
  151.     ETransitionType trans_type;
  152.     TScore score1 = x_FindBestJ ( vEtop, vFtop, vGtop, vEbtm, vFbtm, vGbtm,
  153.                                   trans_pos, trans_type );
  154.     if(top_level)
  155.         m_score = score1;
  156.     // modify traces at the transition point if applicable
  157.     if(trans_type == eII) {
  158.         unsigned char mask_top = kMaskE;
  159.         if(trace_top[trans_pos] & kMaskEc)
  160.             mask_top |= kMaskEc;
  161.         trace_top[trans_pos] = mask_top;
  162.         trace_btm[trans_pos] = kMaskE | kMaskEc;
  163.     }
  164.     if(trans_type == eDD) {
  165.         trace_top[trans_pos] = (trace_top[trans_pos] & kMaskFc)? kMaskFc: 0;
  166.         trace_btm[trans_pos] = kMaskFc;
  167.     }
  168.     // extend a subpath to both directions
  169.     vector<unsigned char>::const_iterator trace_it_top = 
  170.         trace_top.begin() + trans_pos;
  171.     list<ETranscriptSymbol> subpath_left;
  172.     size_t steps_left = x_ExtendSubpath(trace_it_top, false, subpath_left);
  173.     vector<unsigned char>::const_iterator trace_it_btm = 
  174.         trace_btm.begin() + trans_pos;
  175.     list<ETranscriptSymbol> subpath_right;
  176.     size_t steps_right = x_ExtendSubpath(trace_it_btm, true, subpath_right);
  177.     // check if we reached left or top line
  178.     bool bNoLT = false;
  179.     int nc0 = trans_pos - steps_left;
  180.     if(nc0 < 0) {
  181.         NCBI_THROW(CAlgoAlignException, eInternal,
  182.                    "Assertion: LT underflow");
  183.     }
  184.     bool bLeft = nc0 == 0;
  185.     bool bTop  = I == submatr.i1;
  186.     if(bLeft && !bTop) {
  187.         int jump = I - submatr.i1;
  188.         subpath_left.insert(subpath_left.begin(), jump, eTS_Delete);
  189.     }
  190.     if(!bLeft && bTop) {
  191.         subpath_left.insert(subpath_left.begin(), nc0, eTS_Insert);
  192.     }
  193.     if(bLeft || bTop) {
  194.         bNoLT = true;
  195.     }
  196.     // check if we reached right or bottom line
  197.     bool bNoRB = false;
  198.     int nc1 = trans_pos + steps_right;
  199.     if(nc1 > dimJ) {
  200.         NCBI_THROW(CAlgoAlignException, eInternal,
  201.                    "Assertion: RB overflow");
  202.     }
  203.     bool bRight = nc1 == dimJ;
  204.     bool bBottom  = I == submatr.i2 - 1;
  205.     if(bRight && !bBottom) {
  206.         int jump = submatr.i2 - I - 1;
  207.         subpath_right.insert(subpath_right.end(), jump, eTS_Delete);
  208.     }
  209.     if(!bRight && bBottom) {
  210.         int jump = dimJ - nc1;
  211.         subpath_right.insert(subpath_right.end(), jump, eTS_Insert);
  212.     }
  213.     if(bRight || bBottom) {
  214.         bNoRB = true;
  215.     }
  216.     // find out if we have special left-top and/or right-bottom
  217.     // on the new sub-matrices
  218.     bool rb = subpath_left.front() == eTS_Delete;
  219.     bool lt = subpath_right.back() == eTS_Delete;
  220.     // coalesce the pieces together and insert into the master list
  221.     subpath_left.splice( subpath_left.end(), subpath_right );
  222.     list<ETranscriptSymbol>::iterator ti0, ti1;
  223.     {{
  224.         CFastMutexGuard  guard (masterlist_mutex);
  225.         ti0 = translist_pos;
  226.         --ti0;
  227.         m_TransList.splice( translist_pos, subpath_left );
  228.         ++ti0;
  229.         ti1 = translist_pos;
  230.     }}
  231.     // Recurse submatrices:
  232.     SCoordRect rlt;
  233.     if(!bNoLT) {
  234.         // left top
  235.         size_t left_bnd = submatr.j1 + trans_pos - steps_left - 1;
  236.         if(left_bnd >= submatr.j1) {
  237.             rlt.i1 = submatr.i1;
  238.             rlt.j1 = submatr.j1;
  239.             rlt.i2 = I - 1;
  240.             rlt.j2 = left_bnd;
  241.         }
  242.         else {
  243.             NCBI_THROW(CAlgoAlignException, eInternal,
  244.                        "Assertion: Left boundary out of range");
  245.         }
  246.     }
  247.     SCoordRect rrb;
  248.     if(!bNoRB) {
  249.         // right bottom
  250.         size_t right_bnd = submatr.j1 + trans_pos + steps_right;
  251.         if(right_bnd <= submatr.j2) {
  252.             rrb.i1 = I + 2;
  253.             rrb.j1 = right_bnd;
  254.             rrb.i2 = submatr.i2;
  255.             rrb.j2 = submatr.j2;
  256.         }
  257.         else {
  258.             NCBI_THROW(CAlgoAlignException, eInternal,
  259.                        "Assertion: Right boundary out of range");
  260.         }
  261.     }
  262.     if(!bNoLT && !bNoRB) {
  263.         if( m_mt && m_maxthreads > 1 && MM_RequestNewThread(m_maxthreads) ) {
  264.             // find out which rect is larger
  265.             if(rlt.GetArea() > rrb.GetArea()) {
  266.                 // do rb in a second thread
  267.                 CThread* thr2 = new CThreadDoSM( this, &rrb, ti1,
  268.                                                  lt, right_bottom);
  269.                 thr2->Run();
  270.                 // do lt in this thread
  271.                 x_DoSubmatrix(rlt, ti0, left_top, rb);
  272.                 thr2->Join(0);
  273.             }
  274.             else {
  275.                 // do lt in a second thread
  276.                 CThread* thr2 = new CThreadDoSM( this, &rlt, ti0,
  277.                                                  left_top, rb);
  278.                 thr2->Run();
  279.                 // do rb in this thread
  280.                 x_DoSubmatrix(rrb, ti1, lt, right_bottom);
  281.                 thr2->Join(0);
  282.             }
  283.         }
  284.         else {  // just do both
  285.             x_DoSubmatrix(rlt, ti0, left_top, rb);
  286.             x_DoSubmatrix(rrb, ti1, lt, right_bottom);
  287.         }
  288.     }
  289.     else if(!bNoLT) {
  290.         x_DoSubmatrix(rlt, ti0, left_top, rb);
  291.     }
  292.     else if(!bNoRB) {
  293.         x_DoSubmatrix(rrb, ti1, lt, right_bottom);
  294.     }
  295. }
  296. CNWAligner::TScore CMMAligner::x_FindBestJ (
  297.     const vector<TScore>& vEtop, const vector<TScore>& vFtop,
  298.     const vector<TScore>& vGtop, const vector<TScore>& vEbtm,
  299.     const vector<TScore>& vFbtm, const vector<TScore>& vGbtm,
  300.     size_t& pos,
  301.     ETransitionType& trans_type ) const
  302. {
  303.     const size_t dim = vEtop.size();
  304.     TScore score = kMin_Int;
  305.     TScore trans_alts [9];
  306.     bool bFreeGapLeft2  = m_esf_L2 && dim == m_SeqLen2 + 1;
  307.     bool bFreeGapRight2 = m_esf_R2 && dim == m_SeqLen2 + 1;
  308.     for(size_t i = 0; i < dim ; ++i) {
  309.         trans_alts [0] = vEtop[i] + vEbtm[i] - m_Wg;   // II
  310.         trans_alts [1] = vFtop[i] + vEbtm[i];          // DI
  311.         trans_alts [2] = vGtop[i] + vEbtm[i];          // GI
  312.         trans_alts [3] = vEtop[i] + vFbtm[i];          // ID
  313.         TScore wg = (bFreeGapLeft2 && i == 0 || bFreeGapRight2 && i == dim -1)?
  314.                     0: m_Wg;
  315.         trans_alts [4] = vFtop[i] + vFbtm[i] - wg;     // DD
  316.         trans_alts [5] = vGtop[i] + vFbtm[i];          // GD
  317.         trans_alts [6] = vEtop[i] + vGbtm[i];          // IG
  318.         trans_alts [7] = vFtop[i] + vGbtm[i];          // DG
  319.         trans_alts [8] = vGtop[i] + vGbtm[i];          // GG
  320.         for(size_t k = 0; k < 9; ++k) {
  321.             if(trans_alts[k] > score) {
  322.                 score = trans_alts[k];
  323.                 pos = i;
  324.                 trans_type = (ETransitionType)k;
  325.             }
  326.         }
  327.     }
  328.     return score;
  329. }
  330. size_t CMMAligner::x_ExtendSubpath (
  331.     vector<unsigned char>::const_iterator trace_it,
  332.     bool direction,
  333.     list<ETranscriptSymbol>& subpath ) const
  334. {
  335.     subpath.clear();
  336.     size_t step_counter = 0;
  337.     if(direction) {
  338.         while(true) {
  339.             unsigned char Key = *trace_it;
  340.             if (Key & kMaskD) {
  341.                 subpath.push_back(eTS_Match);
  342.                 ++step_counter;
  343.                 break;
  344.             }
  345.             else if (Key & kMaskE) {
  346.                 subpath.push_back(eTS_Insert);
  347.                 ++step_counter;
  348.                 ++trace_it;
  349.                 while(Key & kMaskEc) {
  350.                     Key = *trace_it++;
  351.                     subpath.push_back(eTS_Insert);
  352.                     ++step_counter;
  353.                 }
  354.             }
  355.             else if ((Key & kMaskE) == 0) {
  356.                 subpath.push_back(eTS_Delete);
  357.                 break;
  358.             }
  359.             else {
  360.                 NCBI_THROW(CAlgoAlignException, eInternal,
  361.                            "Assertion: incorrect backtrace symbol "
  362.                            "(right expansion)");
  363.             }
  364.         }
  365.     }
  366.     else {
  367.         while(true) {
  368.             unsigned char Key = *trace_it;
  369.             if (Key & kMaskD) {
  370.                 subpath.push_front(eTS_Match);
  371.                 ++step_counter;
  372.                 break;
  373.             }
  374.             else if (Key & kMaskE) {
  375.                 subpath.push_front(eTS_Insert);
  376.                 ++step_counter;
  377.                 --trace_it;
  378.                 while(Key & kMaskEc) {
  379.                     Key = *trace_it--;
  380.                     subpath.push_front(eTS_Insert);
  381.                     ++step_counter;
  382.                 }
  383.             }
  384.             else if ((Key & kMaskE) == 0) {
  385.                 subpath.push_front(eTS_Delete);
  386.                 break;
  387.             }
  388.             else {
  389.                 NCBI_THROW(CAlgoAlignException, eInternal,
  390.                            "Assertion: incorrect backtrace symbol "
  391.                            "(left expansion)");
  392.             }
  393.         }
  394.     }
  395.     return step_counter;
  396. }
  397. #ifdef NCBI_THREADS
  398. DEFINE_STATIC_FAST_MUTEX (progress_mutex);
  399. #endif
  400. void CMMAligner::x_RunTop ( const SCoordRect& rect,
  401.              vector<TScore>& vE, vector<TScore>& vF, vector<TScore>& vG,
  402.              vector<unsigned char>& trace, bool lt ) const
  403. {
  404.     if( m_terminate ) {
  405.         return;
  406.     }
  407.     const size_t dim1 = rect.i2 - rect.i1 + 1;
  408.     const size_t dim2 = rect.j2 - rect.j1 + 1;
  409.     const size_t N1   = dim1 + 1;
  410.     const size_t N2   = dim2 + 1;
  411.     vector<TScore> stl_rowV (N2), stl_rowF (N2);
  412.     TScore* rowV    = &stl_rowV [0];
  413.     TScore* rowF    = &stl_rowF [0];
  414.     TScore* pV = rowV - 1;
  415.     const char* seq1 = m_Seq1 - 1 + rect.i1;
  416.     const char* seq2 = m_Seq2 - 1 + rect.j1;
  417.     const TNCBIScore (*sm) [NCBI_FSM_DIM] = m_ScoreMatrix.s;
  418.     bool bFreeGapLeft1  = m_esf_L1 && rect.i1 == 0;
  419.     bool bFreeGapLeft2  = m_esf_L2 && rect.j1 == 0;
  420.     bool bFreeGapRight2  = m_esf_R2 && rect.j2 == m_SeqLen2 - 1;
  421.     // progress reporting
  422.     const size_t prg_rep_rate = 100;
  423.     const size_t prg_rep_increment = prg_rep_rate*N2;
  424.     // first row
  425.     TScore wg = bFreeGapLeft1? 0: m_Wg;
  426.     TScore ws = bFreeGapLeft1? 0: m_Ws;
  427.     rowV[0] = wg;
  428.     size_t i, j;
  429.     for (j = 1; j < N2; ++j) {
  430.         rowV[j] = pV[j] + ws;
  431.         rowF[j] = kInfMinus;        
  432.     }
  433.     rowV[0] = 0;
  434.     // recurrences
  435.     wg = bFreeGapLeft2? 0: m_Wg;
  436.     ws = bFreeGapLeft2? 0: m_Ws;
  437.     TScore V  = 0;
  438.     TScore V0 = lt? 0: wg;
  439.     TScore E, G, n0;
  440.     for(i = 1;  i < N1 - 1;  ++i) {
  441.         
  442.         V = V0 += ws;
  443.         E = kInfMinus;
  444.         unsigned char ci = seq1[i];
  445.         TScore wg2 = m_Wg, ws2 = m_Ws;
  446.         for (j = 1; j < N2; ++j) {
  447.             G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  448.             pV[j] = V;
  449.             n0 = V + m_Wg;
  450.             if(E >= n0)
  451.                 E += m_Ws;      // continue the gap
  452.             else
  453.                 E = n0 + m_Ws;  // open a new gap
  454.             if(j == N2 - 1 && bFreeGapRight2)
  455.                 wg2 = ws2 = 0;
  456.             n0 = rowV[j] + wg2;
  457.             if (rowF[j] > n0)
  458.                 rowF[j] += ws2;
  459.             else
  460.                 rowF[j] = n0 + ws2;
  461.             V = (E >= rowF[j])? (E >= G? E: G): (rowF[j] >= G? rowF[j]: G);
  462.         }
  463.         pV[j] = V;
  464.         if( m_prg_callback && i % prg_rep_rate == 0 ) {
  465. #ifdef NCBI_THREADS
  466.             CFastMutexGuard guard (progress_mutex);
  467. #endif
  468.             m_prg_info.m_iter_done += prg_rep_increment;
  469.             if( m_terminate = m_prg_callback(&m_prg_info) ) {
  470.                 break;
  471.             }
  472.         }
  473.     }
  474.     // the last row (i == N1 - 1)
  475.     if(!m_terminate) {
  476.         vG[0] = vE[0] = E = kInfMinus;
  477.         vF[0] = V = V0 += ws;
  478.         trace[0] = kMaskFc;
  479.         unsigned char ci = seq1[i];
  480.         TScore wg2 = m_Wg, ws2 = m_Ws;
  481.         unsigned char tracer;
  482.         for (j = 1; j < N2; ++j) {
  483.             vG[j] = G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  484.             pV[j] = V;
  485.             n0 = V + m_Wg;
  486.             if(E >= n0) {
  487.                 E += m_Ws;      // continue the gap
  488.                 tracer = kMaskEc;
  489.             }
  490.             else {
  491.                 E = n0 + m_Ws;  // open a new gap
  492.                 tracer = 0;
  493.             }
  494.             vE[j] = E;
  495.             if(j == N2 - 1 && bFreeGapRight2) {
  496.                 wg2 = ws2 = 0;
  497.             }
  498.             n0 = rowV[j] + wg2;
  499.             if(rowF[j] >= n0) {
  500.                 rowF[j] += ws2;
  501.                 tracer |= kMaskFc;
  502.             }
  503.             else {
  504.                 rowF[j] = n0 + ws2;
  505.             }
  506.             vF[j] = rowF[j];
  507.             if (E >= rowF[j]) {
  508.                 if(E >= G) {
  509.                     V = E;
  510.                     tracer |= kMaskE;
  511.                 }
  512.                 else {
  513.                     V = G;
  514.                     tracer |= kMaskD;
  515.                 }
  516.             } else {
  517.                 if(rowF[j] >= G) {
  518.                     V = rowF[j];
  519.                 }
  520.                 else {
  521.                     V = G;
  522.                     tracer |= kMaskD;
  523.                 }
  524.             }
  525.             trace[j] = tracer;
  526.         }
  527.     }
  528.     if( m_prg_callback ) {
  529. #ifdef NCBI_THREADS
  530.         CFastMutexGuard guard (progress_mutex);
  531. #endif
  532.         m_prg_info.m_iter_done += (i % prg_rep_rate)*N2;
  533.         m_terminate = m_prg_callback(&m_prg_info);
  534.     }
  535. }
  536.  
  537. void CMMAligner::x_RunBtm(const SCoordRect& rect,
  538.              vector<TScore>& vE, vector<TScore>& vF, vector<TScore>& vG,
  539.              vector<unsigned char>& trace, bool rb) const
  540. {
  541.     if( m_terminate ) {
  542.         return;
  543.     }
  544.     const size_t dim1 = rect.i2 - rect.i1 + 1;
  545.     const size_t dim2 = rect.j2 - rect.j1 + 1;
  546.     const size_t N1   = dim1 + 1;
  547.     const size_t N2   = dim2 + 1;
  548.     vector<TScore> stl_rowV (N2), stl_rowF (N2);
  549.     TScore* rowV    = &stl_rowV [0];
  550.     TScore* rowF    = &stl_rowF [0];
  551.     TScore* pV = rowV + 1;
  552.     const char* seq1 = m_Seq1 + rect.i1;
  553.     const char* seq2 = m_Seq2 + rect.j1;
  554.     const TNCBIScore (*sm) [NCBI_FSM_DIM] = m_ScoreMatrix.s;
  555.     bool bFreeGapRight1  = m_esf_R1 && rect.i2 == m_SeqLen1 - 1;
  556.     bool bFreeGapRight2  = m_esf_R2 && rect.j2 == m_SeqLen2 - 1;
  557.     bool bFreeGapLeft2  =  m_esf_L2 && rect.j1 == 0;
  558.     // progress reporting
  559.     const size_t prg_rep_rate = 100;
  560.     const size_t prg_rep_increment = prg_rep_rate*N2;
  561.     // bottom row
  562.     TScore wg = bFreeGapRight1? 0: m_Wg;
  563.     TScore ws = bFreeGapRight1? 0: m_Ws;
  564.     rowV[N2 - 1] = wg;
  565.     int i, j;
  566.     for (j = N2 - 2; j >= 0; --j) {
  567.         rowV[j] = pV[j] + ws;
  568.         rowF[j] = kInfMinus;
  569.     }
  570.     rowV[N2 - 1] = 0;
  571.     // recurrences
  572.     wg = bFreeGapRight2? 0: m_Wg;
  573.     ws = bFreeGapRight2? 0: m_Ws;
  574.     TScore V  = 0;
  575.     TScore V0 = rb? 0: wg;
  576.     TScore E, G, n0;
  577.     for(i = N1 - 2;  i > 0;  --i) {
  578.         
  579.         V = V0 += ws;
  580.         E = kInfMinus;
  581.         unsigned char ci = seq1[i];
  582.         TScore wg2 = m_Wg, ws2 = m_Ws;
  583.         for (j = N2 - 2; j >= 0; --j) {
  584.             G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  585.             pV[j] = V;
  586.             n0 = V + m_Wg;
  587.             if(E >= n0)
  588.                 E += m_Ws;      // continue the gap
  589.             else
  590.                 E = n0 + m_Ws;  // open a new gap
  591.             if(j == 0 && bFreeGapLeft2) {
  592.                 wg2 = ws2 = 0;
  593.             }
  594.             n0 = rowV[j] + wg2;
  595.             if (rowF[j] > n0)
  596.                 rowF[j] += ws2;
  597.             else
  598.                 rowF[j] = n0 + ws2;
  599.             V = (E >= rowF[j])? (E >= G? E: G): (rowF[j] >= G? rowF[j]: G);
  600.         }
  601.         pV[j] = V;
  602.         if( m_prg_callback && (N1 - i) % prg_rep_rate == 0 ) {
  603. #ifdef NCBI_THREADS
  604.             CFastMutexGuard guard (progress_mutex);
  605. #endif
  606.             m_prg_info.m_iter_done += prg_rep_increment;
  607.             if( m_terminate = m_prg_callback(&m_prg_info) ) {
  608.                 break;
  609.             }
  610.         }
  611.     }
  612.     // the top row (i == 0)
  613.     if(!m_terminate) {
  614.         vF[N2-1] = V = V0 += ws;
  615.         vG[N2-1] = vE[N2-1] = E = kInfMinus;
  616.         trace[N2-1] = kMaskFc;
  617.         unsigned char ci = seq1[i];
  618.         TScore wg2 = m_Wg, ws2 = m_Ws;
  619.         unsigned char tracer;
  620.         for (j = N2 - 2; j >= 0; --j) {
  621.             vG[j] = G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  622.             pV[j] = V;
  623.             n0 = V + m_Wg;
  624.             if(E >= n0) {
  625.                 E += m_Ws;      // continue the gap
  626.                 tracer = kMaskEc;
  627.             }
  628.             else {
  629.                 E = n0 + m_Ws;  // open a new gap
  630.                 tracer = 0;
  631.             }
  632.             vE[j] = E;
  633.             if(j == 0 && bFreeGapLeft2) {
  634.                 wg2 = ws2 = 0;
  635.             }
  636.             n0 = rowV[j] + wg2;
  637.             if(rowF[j] >= n0) {
  638.                 rowF[j] += ws2;
  639.                 tracer |= kMaskFc;
  640.             }
  641.             else {
  642.                 rowF[j] = n0 + ws2;
  643.             }
  644.             vF[j] = rowF[j];
  645.             if (E >= rowF[j]) {
  646.                 if(E >= G) {
  647.                     V = E;
  648.                     tracer |= kMaskE;
  649.                 }
  650.                 else {
  651.                     V = G;
  652.                     tracer |= kMaskD;
  653.                 }
  654.             } else {
  655.                 if(rowF[j] >= G) {
  656.                     V = rowF[j];
  657.                 }
  658.                 else {
  659.                     V = G;
  660.                     tracer |= kMaskD;
  661.                 }
  662.             }
  663.             trace[j] = tracer;
  664.         }
  665.     }
  666.     if( m_prg_callback ) {
  667. #ifdef NCBI_THREADS
  668.         CFastMutexGuard guard (progress_mutex);
  669. #endif
  670.         m_prg_info.m_iter_done += (N1 - i) % prg_rep_rate;
  671.         m_terminate = m_prg_callback(&m_prg_info);
  672.     }
  673. }
  674. CNWAligner::TScore CMMAligner::x_RunTerm(const SCoordRect& rect,
  675.                                          bool left_top, bool right_bottom,
  676.                                          list<ETranscriptSymbol>& subpath)
  677. {
  678.     if( m_terminate ) {
  679.         return 0;
  680.     }
  681.     const size_t N1 = rect.i2 - rect.i1 + 2;
  682.     const size_t N2 = rect.j2 - rect.j1 + 2;
  683.     vector<TScore> stl_rowV (N2), stl_rowF (N2);
  684.     TScore* rowV    = &stl_rowV [0];
  685.     TScore* rowF    = &stl_rowF [0];
  686.     // index calculation: [i,j] = i*n2 + j
  687.     vector<unsigned char> stl_bm (N1*N2);
  688.     unsigned char* backtrace = &stl_bm[0];
  689.     TScore* pV = rowV - 1;
  690.     const char* seq1 = m_Seq1 + rect.i1 - 1;
  691.     const char* seq2 = m_Seq2 + rect.j1 - 1;
  692.     const TNCBIScore (*sm) [NCBI_FSM_DIM] = m_ScoreMatrix.s;
  693.     bool bFreeGapLeft1  = m_esf_L1 && rect.i1 == 0;
  694.     bool bFreeGapRight1 = m_esf_R1 && rect.i2 == m_SeqLen1 - 1;
  695.     bool bFreeGapLeft2  = m_esf_L2 && rect.j1 == 0;
  696.     bool bFreeGapRight2 = m_esf_R2 && rect.j2 == m_SeqLen2 - 1;
  697.     TScore wgleft1   = bFreeGapLeft1? 0: m_Wg;
  698.     TScore wsleft1   = bFreeGapLeft1? 0: m_Ws;
  699.     TScore wg1 = m_Wg, ws1 = m_Ws;
  700.     // first row
  701.     size_t k;
  702.     {
  703.         rowV[0] = wgleft1;
  704.         for (k = 1; k < N2; k++) {
  705.             rowV[k] = pV[k] + wsleft1;
  706.             rowF[k] = kInfMinus;
  707.             backtrace[k] = kMaskE | kMaskEc;
  708.         }
  709.         rowV[0] = 0;
  710.     }
  711.     // recurrences
  712.     TScore wgleft2   = bFreeGapLeft2? 0: m_Wg;
  713.     TScore wsleft2   = bFreeGapLeft2? 0: m_Ws;
  714.     TScore V  = 0;
  715.     TScore V0 = left_top? 0: wgleft2;
  716.     TScore E, G, n0;
  717.     unsigned char tracer;
  718.     size_t i, j;
  719.     for(i = 1;  i < N1;  ++i) {
  720.         
  721.         V = V0 += wsleft2;
  722.         E = kInfMinus;
  723.         backtrace[k++] = kMaskFc;
  724.         unsigned char ci = seq1[i];
  725.         if(i == N1 - 1 && bFreeGapRight1) {
  726.                 wg1 = ws1 = 0;
  727.         }
  728.         TScore wg2 = m_Wg, ws2 = m_Ws;
  729.         for (j = 1; j < N2; ++j, ++k) {
  730.             G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  731.             pV[j] = V;
  732.             n0 = V + wg1;
  733.             if(E >= n0) {
  734.                 E += ws1;      // continue the gap
  735.                 tracer = kMaskEc;
  736.             }
  737.             else {
  738.                 E = n0 + ws1;  // open a new gap
  739.                 tracer = 0;
  740.             }
  741.             if(j == N2 - 1 && bFreeGapRight2) {
  742.                 wg2 = ws2 = 0;
  743.             }
  744.             n0 = rowV[j] + ((right_bottom && j == N2 - 1)? 0: wg2);
  745.             if(rowF[j] >= n0) {
  746.                 rowF[j] += ws2;
  747.                 tracer |= kMaskFc;
  748.             }
  749.             else {
  750.                 rowF[j] = n0 + ws2;
  751.             }
  752.             if (E >= rowF[j]) {
  753.                 if(E >= G) {
  754.                     V = E;
  755.                     tracer |= kMaskE;
  756.                 }
  757.                 else {
  758.                     V = G;
  759.                     tracer |= kMaskD;
  760.                 }
  761.             } else {
  762.                 if(rowF[j] >= G) {
  763.                     V = rowF[j];
  764.                 }
  765.                 else {
  766.                     V = G;
  767.                     tracer |= kMaskD;
  768.                 }
  769.             }
  770.             backtrace[k] = tracer;
  771.         }
  772.         pV[j] = V;
  773.     }
  774.     // fill the subpath
  775.     subpath.clear();
  776.     
  777.     // run backtrace
  778.     k = N1*N2 - 1;
  779.     while (k != 0) {
  780.         unsigned char Key = backtrace[k];
  781.         if (Key & kMaskD) {
  782.             subpath.push_front(eTS_Match);
  783.             k -= N2 + 1;
  784.         }
  785.         else if (Key & kMaskE) {
  786.             subpath.push_front(eTS_Insert); --k;
  787.             while(k > 0 && (Key & kMaskEc)) {
  788.                 subpath.push_front(eTS_Insert);
  789.                 Key = backtrace[k--];
  790.             }
  791.         }
  792.         else {
  793.             subpath.push_front(eTS_Delete);
  794.             k -= N2;
  795.             while(k > 0 && (Key & kMaskFc)) {
  796.                 subpath.push_front(eTS_Delete);
  797.                 Key = backtrace[k];
  798.                 k -= N2;
  799.             }
  800.         }
  801.     }
  802.     return V;
  803. }
  804. bool CMMAligner::x_CheckMemoryLimit()
  805. {
  806.     return true;
  807. }
  808. END_NCBI_SCOPE
  809. /*
  810.  * ===========================================================================
  811.  * $Log: mm_aligner.cpp,v $
  812.  * Revision 1000.1  2004/06/01 18:04:46  gouriano
  813.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  814.  *
  815.  * Revision 1.20  2004/05/21 21:41:01  gorelenk
  816.  * Added PCH ncbi_pch.hpp
  817.  *
  818.  * Revision 1.19  2004/05/18 21:43:40  kapustin
  819.  * Code cleanup
  820.  *
  821.  * Revision 1.18  2004/05/17 14:50:56  kapustin
  822.  * Add/remove/rearrange some includes and object declarations
  823.  *
  824.  * Revision 1.17  2003/09/30 19:50:04  kapustin
  825.  * Make use of standard score matrix interface
  826.  *
  827.  * Revision 1.16  2003/09/26 14:43:18  kapustin
  828.  * Remove exception specifications
  829.  *
  830.  * Revision 1.15  2003/09/04 16:07:38  kapustin
  831.  * Use STL vectors for exception-safe dynamic arrays and matrices
  832.  *
  833.  * Revision 1.14  2003/09/02 22:36:57  kapustin
  834.  * Adjust for transcript symbol name changes
  835.  *
  836.  * Revision 1.13  2003/06/17 17:20:44  kapustin
  837.  * CNWAlignerException -> CAlgoAlignException
  838.  *
  839.  * Revision 1.12  2003/06/17 14:51:04  dicuccio
  840.  * Fixed after algo/ rearragnement
  841.  *
  842.  * Revision 1.11  2003/06/03 18:19:06  rsmith
  843.  * Move static mutex initialization to file from function scope,
  844.  * because of MW compiler choking (wrongly) over complex initialization.
  845.  *
  846.  * Revision 1.10  2003/06/02 14:04:49  kapustin
  847.  * Progress indication-related updates
  848.  *
  849.  * Revision 1.9  2003/05/23 18:26:38  kapustin
  850.  * Use weak comparisons in core recurrences.
  851.  *
  852.  * Revision 1.8  2003/04/14 19:01:49  kapustin
  853.  * Run() -> x_Run()
  854.  *
  855.  * Revision 1.7  2003/03/18 15:15:51  kapustin
  856.  * Implement virtual memory checking function. Allow separate free
  857.  * end gap specification
  858.  *
  859.  * Revision 1.6  2003/03/17 15:30:57  kapustin
  860.  * Support end-space free alignments
  861.  *
  862.  * Revision 1.5  2003/01/30 20:32:06  kapustin
  863.  * Call x_LoadScoringMatrix() from the base class constructor.
  864.  *
  865.  * Revision 1.4  2003/01/28 12:37:40  kapustin
  866.  * Move m_score to the base class
  867.  *
  868.  * Revision 1.3  2003/01/22 13:40:09  kapustin
  869.  * Implement multithreaded algorithm
  870.  *
  871.  * ===========================================================================
  872.  */