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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: nw_aligner.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:04:52  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.48
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: nw_aligner.cpp,v 1000.3 2004/06/01 18:04:52 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, Boris Kiryutin
  35.  *
  36.  * File Description:  CNWAligner implementation
  37.  *                   
  38.  * ===========================================================================
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include <algo/align/nw_aligner.hpp>
  43. #include <algo/align/align_exception.hpp>
  44. BEGIN_NCBI_SCOPE
  45. // IUPACna alphabet (default)
  46. const char g_nwaligner_nucleotides [] = "AGTCBDHKMNRSVWY";
  47. CNWAligner::CNWAligner()
  48.     : m_Wm(GetDefaultWm()),
  49.       m_Wms(GetDefaultWms()),
  50.       m_Wg(GetDefaultWg()),
  51.       m_Ws(GetDefaultWs()),
  52.       m_esf_L1(false), m_esf_R1(false), m_esf_L2(false), m_esf_R2(false),
  53.       m_abc(g_nwaligner_nucleotides),
  54.       m_prg_callback(0),
  55.       m_Seq1(0), m_SeqLen1(0),
  56.       m_Seq2(0), m_SeqLen2(0),
  57.       m_score(kInfMinus)
  58. {
  59.     SetScoreMatrix(0);
  60. }
  61. CNWAligner::CNWAligner( const char* seq1, size_t len1,
  62.                         const char* seq2, size_t len2,
  63.                         const SNCBIPackedScoreMatrix* scoremat )
  64.     : m_Wm(GetDefaultWm()),
  65.       m_Wms(GetDefaultWms()),
  66.       m_Wg(GetDefaultWg()),
  67.       m_Ws(GetDefaultWs()),
  68.       m_esf_L1(false), m_esf_R1(false), m_esf_L2(false), m_esf_R2(false),
  69.       m_abc(g_nwaligner_nucleotides),
  70.       m_prg_callback(0),
  71.       m_Seq1(seq1), m_SeqLen1(len1),
  72.       m_Seq2(seq2), m_SeqLen2(len2),
  73.       m_score(kInfMinus)
  74. {
  75.     SetScoreMatrix(scoremat);
  76.     SetSequences(seq1, len1, seq2, len2);
  77. }
  78. void CNWAligner::SetSequences(const char* seq1, size_t len1,
  79.       const char* seq2, size_t len2,
  80.       bool verify)
  81. {
  82.     if(!seq1 || !seq2) {
  83.         NCBI_THROW(CAlgoAlignException, eBadParameter,
  84.                    "NULL sequence pointer(s) passed");
  85.     }
  86.     if(verify) {
  87.         size_t iErrPos1 = x_CheckSequence(seq1, len1);
  88. if(iErrPos1 < len1) {
  89.     ostrstream oss;
  90.     oss << "The first sequence is inconsistent with the current "
  91. << "scoring matrix type. Symbol " << seq1[iErrPos1] << " at "
  92. << iErrPos1;
  93.     string message = CNcbiOstrstreamToString(oss);
  94.     NCBI_THROW(CAlgoAlignException, eInvalidCharacter, message);
  95. }
  96. size_t iErrPos2 = x_CheckSequence(seq2, len2);
  97. if(iErrPos2 < len2) {
  98.     ostrstream oss;
  99.     oss << "The second sequence is inconsistent with the current "
  100. << "scoring matrix type. Symbol " << seq2[iErrPos2] << " at "
  101. << iErrPos2;
  102.     string message = CNcbiOstrstreamToString(oss);
  103.     NCBI_THROW(CAlgoAlignException, eInvalidCharacter, message);
  104. }
  105.     }
  106.     m_Seq1 = seq1;
  107.     m_SeqLen1 = len1;
  108.     m_Seq2 = seq2;
  109.     m_SeqLen2 = len2;
  110.     m_Transcript.clear();
  111. }
  112. void CNWAligner::SetEndSpaceFree(bool Left1, bool Right1,
  113.                                  bool Left2, bool Right2)
  114. {
  115.     m_esf_L1 = Left1;
  116.     m_esf_R1 = Right1;
  117.     m_esf_L2 = Left2;
  118.     m_esf_R2 = Right2;
  119. }
  120. // evaluate score for each possible alignment;
  121. // fill out backtrace matrix
  122. // bit coding (four bits per value): D E Ec Fc
  123. // D:  1 if diagonal; 0 - otherwise
  124. // E:  1 if space in 1st sequence; 0 if space in 2nd sequence
  125. // Ec: 1 if gap in 1st sequence was extended; 0 if it is was opened
  126. // Fc: 1 if gap in 2nd sequence was extended; 0 if it is was opened
  127. //
  128. const unsigned char kMaskFc  = 0x0001;
  129. const unsigned char kMaskEc  = 0x0002;
  130. const unsigned char kMaskE   = 0x0004;
  131. const unsigned char kMaskD   = 0x0008;
  132. CNWAligner::TScore CNWAligner::x_Align(const char* seg1, size_t len1,
  133.                                        const char* seg2, size_t len2,
  134.                                        vector<ETranscriptSymbol>* transcript)
  135. {
  136.     const size_t N1 = len1 + 1;
  137.     const size_t N2 = len2 + 1;
  138.     vector<TScore> stl_rowV (N2), stl_rowF(N2);
  139.     TScore* rowV    = &stl_rowV[0];
  140.     TScore* rowF    = &stl_rowF[0];
  141.     TScore* pV = rowV - 1;
  142.     const char* seq1 = seg1 - 1;
  143.     const char* seq2 = seg2 - 1;
  144.     const TNCBIScore (*sm) [NCBI_FSM_DIM] = m_ScoreMatrix.s;
  145.     m_terminate = false;
  146.     if(m_prg_callback) {
  147.         m_prg_info.m_iter_total = N1*N2;
  148.         m_prg_info.m_iter_done = 0;
  149.         if(m_terminate = m_prg_callback(&m_prg_info)) {
  150.   return 0;
  151. }
  152.     }
  153.     bool bFreeGapLeft1  = m_esf_L1 && seg1 == m_Seq1;
  154.     bool bFreeGapRight1 = m_esf_R1 && m_Seq1 + m_SeqLen1 - len1 == seg1;
  155.     bool bFreeGapLeft2  = m_esf_L2 && seg2 == m_Seq2;
  156.     bool bFreeGapRight2 = m_esf_R2 && m_Seq2 + m_SeqLen2 - len2 == seg2;
  157.     TScore wgleft1   = bFreeGapLeft1? 0: m_Wg;
  158.     TScore wsleft1   = bFreeGapLeft1? 0: m_Ws;
  159.     TScore wg1 = m_Wg, ws1 = m_Ws;
  160.     // index calculation: [i,j] = i*n2 + j
  161.     vector<unsigned char> stl_bm (N1*N2);
  162.     unsigned char* backtrace_matrix = &stl_bm[0];
  163.     // first row
  164.     size_t k;
  165.     rowV[0] = wgleft1;
  166.     for (k = 1; k < N2; k++) {
  167.         rowV[k] = pV[k] + wsleft1;
  168.         rowF[k] = kInfMinus;
  169.         backtrace_matrix[k] = kMaskE | kMaskEc;
  170.     }
  171.     rowV[0] = 0;
  172.     if(m_prg_callback) {
  173.         m_prg_info.m_iter_done = k;
  174.         m_terminate = m_prg_callback(&m_prg_info);
  175.     }
  176.     // recurrences
  177.     TScore wgleft2   = bFreeGapLeft2? 0: m_Wg;
  178.     TScore wsleft2   = bFreeGapLeft2? 0: m_Ws;
  179.     TScore V  = rowV[N2 - 1];
  180.     TScore V0 = wgleft2;
  181.     TScore E, G, n0;
  182.     unsigned char tracer;
  183.     size_t i, j;
  184.     for(i = 1;  i < N1 && !m_terminate;  ++i) {
  185.         
  186.         V = V0 += wsleft2;
  187.         E = kInfMinus;
  188.         backtrace_matrix[k++] = kMaskFc;
  189.         unsigned char ci = seq1[i];
  190.         if(i == N1 - 1 && bFreeGapRight1) {
  191.                 wg1 = ws1 = 0;
  192.         }
  193.         TScore wg2 = m_Wg, ws2 = m_Ws;
  194.         for (j = 1; j < N2; ++j, ++k) {
  195.             G = pV[j] + sm[ci][(unsigned char)seq2[j]];
  196.             pV[j] = V;
  197.             n0 = V + wg1;
  198.             if(E >= n0) {
  199.                 E += ws1;      // continue the gap
  200.                 tracer = kMaskEc;
  201.             }
  202.             else {
  203.                 E = n0 + ws1;  // open a new gap
  204.                 tracer = 0;
  205.             }
  206.             if(j == N2 - 1 && bFreeGapRight2) {
  207.                 wg2 = ws2 = 0;
  208.             }
  209.             n0 = rowV[j] + wg2;
  210.             if(rowF[j] >= n0) {
  211.                 rowF[j] += ws2;
  212.                 tracer |= kMaskFc;
  213.             }
  214.             else {
  215.                 rowF[j] = n0 + ws2;
  216.             }
  217.             if (E >= rowF[j]) {
  218.                 if(E >= G) {
  219.                     V = E;
  220.                     tracer |= kMaskE;
  221.                 }
  222.                 else {
  223.                     V = G;
  224.                     tracer |= kMaskD;
  225.                 }
  226.             } else {
  227.                 if(rowF[j] >= G) {
  228.                     V = rowF[j];
  229.                 }
  230.                 else {
  231.                     V = G;
  232.                     tracer |= kMaskD;
  233.                 }
  234.             }
  235.             backtrace_matrix[k] = tracer;
  236.         }
  237.         pV[j] = V;
  238.         if(m_prg_callback) {
  239.             m_prg_info.m_iter_done = k;
  240.             if(m_terminate = m_prg_callback(&m_prg_info)) {
  241.                 break;
  242.             }
  243.         }
  244.        
  245.     }
  246.     if(!m_terminate) {
  247.         x_DoBackTrace(backtrace_matrix, N1, N2, transcript);
  248.     }
  249.     return V;
  250. }
  251. CNWAligner::TScore CNWAligner::Run()
  252. {
  253.     if(!m_Seq1 || !m_Seq2) {
  254.         NCBI_THROW(CAlgoAlignException, eNoData,
  255.                    "Sequence data not available for one or both sequences");
  256.     }
  257.     if(!x_CheckMemoryLimit()) {
  258.         NCBI_THROW(CAlgoAlignException, eMemoryLimit, "Out of space");
  259.     }
  260.     m_score = x_Run();
  261.     return m_score;
  262. }
  263. CNWAligner::TScore CNWAligner::x_Run()
  264. {
  265.     try {
  266.     
  267.         if(m_guides.size() == 0) {
  268.             m_score = x_Align(m_Seq1,m_SeqLen1, m_Seq2,m_SeqLen2,
  269.                               &m_Transcript);
  270.         }
  271.         else {
  272.             
  273.             // run the algorithm for every segment between hits
  274.             m_Transcript.clear();
  275.             size_t guides_dim = m_guides.size() / 4;
  276.             size_t q1 = m_SeqLen1, q0, s1 = m_SeqLen2, s0;
  277.             vector<ETranscriptSymbol> trans;
  278.             
  279.             // save original esf settings
  280.             bool esf_L1 = m_esf_L1, esf_R1 = m_esf_R1,
  281.                  esf_L2 = m_esf_L2, esf_R2 = m_esf_R2;
  282.             SetEndSpaceFree(false, esf_R1, false, esf_R2); // last region
  283.             for(size_t istart = 4*guides_dim, i = istart; i != 0; i -= 4) {
  284.                 q0 = m_guides[i - 3] + 1;
  285.                 s0 = m_guides[i - 1] + 1;
  286.                 size_t dim_query = q1 - q0, dim_subj = s1 - s0;
  287.                 x_Align(m_Seq1 + q0, dim_query, m_Seq2 + s0, dim_subj, &trans);
  288.                 copy(trans.begin(), trans.end(), back_inserter(m_Transcript));
  289.                 size_t dim_hit = m_guides[i - 3] - m_guides[i - 4] + 1;
  290.                 for(size_t k = 0; k < dim_hit; ++k) {
  291.                     m_Transcript.push_back(eTS_Match);
  292.                 }
  293.                 q1 = m_guides[i - 4];
  294.                 s1 = m_guides[i - 2];
  295.                 trans.clear();
  296.                 if(i == istart) {  // middle regions
  297.                     SetEndSpaceFree(false, false, false, false);
  298.                 }
  299.             }
  300.             SetEndSpaceFree(esf_L1, false, esf_L2, false); // first region
  301.             x_Align(m_Seq1, q1, m_Seq2, s1, &trans);
  302.             SetEndSpaceFree(esf_L1, esf_R1, esf_L2, esf_R2); // restore
  303.             copy(trans.begin(), trans.end(), back_inserter(m_Transcript));
  304.             m_score = x_ScoreByTranscript();
  305.         }
  306.     }
  307.     
  308.     catch( bad_alloc& ) {
  309.         
  310.         NCBI_THROW(CAlgoAlignException, eMemoryLimit, "Memory limit exceeded");
  311.     }
  312.     
  313.     return m_score;
  314. }
  315. // perform backtrace step;
  316. void CNWAligner::x_DoBackTrace(const unsigned char* backtrace,
  317.                                size_t N1, size_t N2,
  318.                                vector<ETranscriptSymbol>* transcript)
  319. {
  320.     transcript->clear();
  321.     transcript->reserve(N1 + N2);
  322.     size_t k = N1*N2 - 1;
  323.     while (k != 0) {
  324.         unsigned char Key = backtrace[k];
  325.         if (Key & kMaskD) {
  326.             transcript->push_back(eTS_Match);
  327.             k -= N2 + 1;
  328.         }
  329.         else if (Key & kMaskE) {
  330.             transcript->push_back(eTS_Insert); --k;
  331.             while(k > 0 && (Key & kMaskEc)) {
  332.                 transcript->push_back(eTS_Insert);
  333.                 Key = backtrace[k--];
  334.             }
  335.         }
  336.         else {
  337.             transcript->push_back(eTS_Delete);
  338.             k -= N2;
  339.             while(k > 0 && (Key & kMaskFc)) {
  340.                 transcript->push_back(eTS_Delete);
  341.                 Key = backtrace[k];
  342.                 k -= N2;
  343.             }
  344.         }
  345.     }
  346. }
  347. void  CNWAligner::SetPattern(const vector<size_t>& guides)
  348. {
  349.     size_t dim = guides.size();
  350.     const char* err = 0;
  351.     if(dim % 4 == 0) {
  352.         for(size_t i = 0; i < dim; i += 4) {
  353.             if( guides[i] > guides[i+1] || guides[i+2] > guides[i+3] ) {
  354.                 err = "Pattern hits must be specified in plus strand";
  355. break;
  356.             }
  357.             if(i > 4) {
  358.                 if(guides[i] <= guides[i-3] || guides[i+2] <= guides[i-2]){
  359.                     err = "Pattern hits coordinates must be sorted";
  360.                     break;
  361.                 }
  362.             }
  363.             size_t dim1 = guides[i + 1] - guides[i];
  364.             size_t dim2 = guides[i + 3] - guides[i + 2];
  365.             if( dim1 != dim2) {
  366.                 err = "Pattern hits must have equal length on both sequences";
  367.                 break;
  368.             }
  369.             if(guides[i+1] >= m_SeqLen1 || guides[i+3] >= m_SeqLen2) {
  370.                 err = "One or several pattern hits are out of range";
  371.                 break;
  372.             }
  373.         }
  374.     }
  375.     else {
  376.         err = "Pattern must have a dimension multiple of four";
  377.     }
  378.     if(err) {
  379.         NCBI_THROW(CAlgoAlignException, eBadParameter, err);
  380.     }
  381.     else {
  382.         m_guides = guides;
  383.     }
  384. }
  385. void CNWAligner::GetEndSpaceFree(bool* L1, bool* R1, bool* L2, bool* R2) const
  386. {
  387.     if(L1) *L1 = m_esf_L1;
  388.     if(R1) *R1 = m_esf_R1;
  389.     if(L2) *L2 = m_esf_L2;
  390.     if(R2) *R2 = m_esf_R2;
  391. }
  392. // Return transcript as a readable string
  393. string CNWAligner::GetTranscriptString(void) const
  394. {
  395.     const size_t dim = m_Transcript.size();   
  396.     string s;
  397.     s.resize(dim);
  398.     size_t i1 = 0, i2 = 0, i = 0;
  399.     for (int k = dim - 1; k >= 0;  --k) {
  400.         ETranscriptSymbol c0 = m_Transcript[k];
  401.         char c = 0;
  402.         switch ( c0 ) {
  403.             case eTS_Match: 
  404.             case eTS_Replace: {
  405.                 c = (m_Seq1[i1++] == m_Seq2[i2++])? 'M': 'R';
  406.             }
  407.             break;
  408.             case eTS_Insert: {
  409.                 c = 'I';
  410.                 ++i2;
  411.             }
  412.             break;
  413.             case eTS_Delete: {
  414.                 c = 'D';
  415.                 ++i1;
  416.             }
  417.             break;
  418.             case eTS_Intron: {
  419.                 c = '+';
  420.                 ++i2;
  421.             }
  422.             break;
  423.     default: {
  424.       NCBI_THROW(CAlgoAlignException, eInternal,
  425.                          "Unexpected transcript symbol");
  426.     }
  427.   
  428.         }
  429.         s[i++] = c;
  430.     }
  431.     if(i < s.size()) {
  432.         s.resize(i + 1);
  433.     }
  434.     return s;
  435. }
  436. void CNWAligner::SetProgressCallback ( FProgressCallback prg_callback,
  437.        void* data )
  438. {
  439.     m_prg_callback = prg_callback;
  440.     m_prg_info.m_data = data;
  441. }
  442.  
  443. void CNWAligner::SetScoreMatrix(const SNCBIPackedScoreMatrix* psm)
  444. {
  445.     if(psm) {
  446.         m_abc = psm->symbols;
  447. NCBISM_Unpack(psm, &m_ScoreMatrix);
  448.     }
  449.     else { // assume IUPACna
  450.         m_abc = g_nwaligner_nucleotides;
  451. memset(&m_ScoreMatrix.s, m_Wms, sizeof m_ScoreMatrix.s);
  452. // set diag to Wm except ambiguity symbols
  453.         unsigned char c1, c2;
  454. const size_t kNuclSize = strlen(g_nwaligner_nucleotides);
  455. for(size_t i = 0; i < kNuclSize; ++i) {
  456.     c1 = g_nwaligner_nucleotides[i];
  457.     for(size_t j = 0; j < i; ++j) {
  458.         c2 = g_nwaligner_nucleotides[j];
  459. m_ScoreMatrix.s[c1][c2] = m_ScoreMatrix.s[c2][c1] = m_Wms;
  460.     }
  461.     m_ScoreMatrix.s[c1][c1] = i < 4? m_Wm: m_Wms;
  462. }
  463.     }
  464. }
  465. // Check that all characters in sequence are valid for 
  466. // the current sequence type.
  467. // Return an index to the first invalid character
  468. // or len if all characters are valid.
  469. size_t CNWAligner::x_CheckSequence(const char* seq, size_t len) const
  470. {
  471.     char Flags [256];
  472.     memset(Flags, 0, sizeof Flags);
  473.     const size_t abc_size = strlen(m_abc);
  474.     
  475.     size_t k;
  476.     for(k = 0; k < abc_size; ++k) {
  477.         Flags[unsigned(m_abc[k])] = 1;
  478.     }
  479.     for(k = 0; k < len; ++k) {
  480.         if(Flags[unsigned(seq[k])] == 0)
  481.             break;
  482.     }
  483.     return k;
  484. }
  485. CNWAligner::TScore CNWAligner::GetScore() const 
  486. {
  487.   if(m_Transcript.size()) {
  488.       return m_score;
  489.   }
  490.   else {
  491.     NCBI_THROW(CAlgoAlignException, eNoData,
  492.                "Sequences not aligned yet");
  493.   }
  494. }
  495. bool CNWAligner::x_CheckMemoryLimit()
  496. {
  497.     const size_t elem_size = GetElemSize();
  498.     const size_t gdim = m_guides.size();
  499.     const size_t max_mem = kMax_UInt / 2;
  500.     if(gdim) {
  501.         size_t dim1 = m_guides[0], dim2 = m_guides[2];
  502.         double mem = double(dim1)*dim2*elem_size;
  503.         if(mem >= max_mem) {
  504.             return false;
  505.         }
  506.         for(size_t i = 4; i < gdim; i += 4) {
  507.             dim1 = m_guides[i] - m_guides[i-3] + 1;
  508.             dim2 = m_guides[i + 2] - m_guides[i-1] + 1;
  509.             mem = double(dim1)*dim2*elem_size;
  510.             if(mem >= max_mem) {
  511.                 return false;
  512.             }
  513.         }
  514.         dim1 = m_SeqLen1 - m_guides[gdim-3];
  515.         dim2 = m_SeqLen2 - m_guides[gdim-1];
  516.         mem = double(dim1)*dim2*elem_size;
  517.         if(mem >= max_mem) {
  518.             return false;
  519.         }
  520.         return true;
  521.     }
  522.     else {
  523.         double mem = double(m_SeqLen1 + 1)*(m_SeqLen2 + 1)*elem_size;
  524.         return mem < max_mem;
  525.     }
  526. }
  527. CNWAligner::TScore CNWAligner::x_ScoreByTranscript() const
  528. {
  529.     const size_t dim = m_Transcript.size();
  530.     if(dim == 0) return 0;
  531.     vector<ETranscriptSymbol> transcript (dim);
  532.     for(size_t i = 0; i < dim; ++i) {
  533.         transcript[i] = m_Transcript[dim - i - 1];
  534.     }
  535.     TScore score = 0;
  536.     const char* p1 = m_Seq1;
  537.     const char* p2 = m_Seq2;
  538.     int state1;   // 0 = normal, 1 = gap, 2 = intron
  539.     int state2;   // 0 = normal, 1 = gap
  540.     switch(transcript[0]) {
  541.     case eTS_Match:    state1 = state2 = 0; break;
  542.     case eTS_Insert:   state1 = 1; state2 = 0; score += m_Wg; break;
  543.     case eTS_Delete:   state1 = 0; state2 = 1; score += m_Wg; break;
  544.     default: {
  545.         NCBI_THROW(CAlgoAlignException, eInternal,
  546.                    "Invalid transcript symbol");
  547.         }
  548.     }
  549.     const TNCBIScore (*sm) [NCBI_FSM_DIM] = m_ScoreMatrix.s;
  550.     for(size_t i = 0; i < dim; ++i) {
  551.         unsigned char c1 = m_Seq1? *p1: 'N';
  552.         unsigned char c2 = m_Seq2? *p2: 'N';
  553.         switch(transcript[i]) {
  554.         case eTS_Match: {
  555.             state1 = state2 = 0;
  556.             score += sm[c1][c2];
  557.             ++p1; ++p2;
  558.         }
  559.         break;
  560.         case eTS_Insert: {
  561.             if(state1 != 1) score += m_Wg;
  562.             state1 = 1; state2 = 0;
  563.             score += m_Ws;
  564.             ++p2;
  565.         }
  566.         break;
  567.         case eTS_Delete: {
  568.             if(state2 != 1) score += m_Wg;
  569.             state1 = 0; state2 = 1;
  570.             score += m_Ws;
  571.             ++p1;
  572.         }
  573.         break;
  574.         
  575.         default: {
  576.         NCBI_THROW(CAlgoAlignException, eInternal,
  577.                    "Invalid transcript symbol");
  578.         }
  579.         }
  580.     }
  581.     if(m_esf_L1) {
  582.         size_t g = 0;
  583.         for(size_t i = 0; i < dim; ++i) {
  584.             if(transcript[i] == eTS_Insert) ++g; else break;
  585.         }
  586.         if(g > 0) {
  587.             score -= (m_Wg + g*m_Ws);
  588.         }
  589.     }
  590.     if(m_esf_L2) {
  591.         size_t g = 0;
  592.         for(size_t i = 0; i < dim; ++i) {
  593.             if(transcript[i] == eTS_Delete) ++g; else break;
  594.         }
  595.         if(g > 0) {
  596.             score -= (m_Wg + g*m_Ws);
  597.         }
  598.     }
  599.     if(m_esf_R1) {
  600.         size_t g = 0;
  601.         for(int i = dim - 1; i >= 0; --i) {
  602.             if(transcript[i] == eTS_Insert) ++g; else break;
  603.         }
  604.         if(g > 0) {
  605.             score -= (m_Wg + g*m_Ws);
  606.         }
  607.     }
  608.     if(m_esf_R2) {
  609.         size_t g = 0;
  610.         for(int i = dim - 1; i >= 0; --i) {
  611.             if(transcript[i] == eTS_Delete) ++g; else break;
  612.         }
  613.         if(g > 0) {
  614.             score -= (m_Wg + g*m_Ws);
  615.         }
  616.     }
  617.     return score;
  618. }
  619. size_t CNWAligner::GetLeftSeg(size_t* q0, size_t* q1,
  620.                               size_t* s0, size_t* s1,
  621.                               size_t min_size) const
  622. {
  623.     size_t trdim = m_Transcript.size();
  624.     size_t cur = 0, maxseg = 0;
  625.     const char* p1 = m_Seq1;
  626.     const char* p2 = m_Seq2;
  627.     size_t i0 = 0, j0 = 0, imax = i0, jmax = j0;
  628.     for(int k = trdim - 1; k >= 0; --k) {
  629.         switch(m_Transcript[k]) {
  630.             case eTS_Insert: {
  631.                 ++p2;
  632.                 if(cur > maxseg) {
  633.                     maxseg = cur;
  634.                     imax = i0;
  635.                     jmax = j0;
  636.                     if(maxseg >= min_size) goto ret_point;
  637.                 }
  638.                 cur = 0;
  639.             }
  640.             break;
  641.             case eTS_Delete: {
  642.             ++p1;
  643.             if(cur > maxseg) {
  644.                 maxseg = cur;
  645.                 imax = i0;
  646.                 jmax = j0;
  647.                 if(maxseg >= min_size) goto ret_point;
  648.             }
  649.             cur = 0;
  650.             }
  651.             break;
  652.             case eTS_Match:
  653.             case eTS_Replace: {
  654.                 if(*p1 == *p2) {
  655.                     if(cur == 0) {
  656.                         i0 = p1 - m_Seq1;
  657.                         j0 = p2 - m_Seq2;
  658.                     }
  659.                     ++cur;
  660.                 }
  661.                 else {
  662.                     if(cur > maxseg) {
  663.                         maxseg = cur;
  664.                         imax = i0;
  665.                         jmax = j0;
  666.                         if(maxseg >= min_size) goto ret_point;
  667.                     }
  668.                     cur = 0;
  669.                 }
  670.                 ++p1;
  671.                 ++p2;
  672.             }
  673.             break;
  674.             default: {
  675.                 NCBI_THROW(CAlgoAlignException, eInternal,
  676.                            "Invalid transcript symbol");
  677.             }
  678.         }
  679.     }
  680.     if(cur > maxseg) {
  681.       maxseg = cur;
  682.       imax = i0;
  683.       jmax = j0;
  684.     }
  685.  ret_point:
  686.     *q0 = imax; *s0 = jmax;
  687.     *q1 = *q0 + maxseg - 1;
  688.     *s1 = *s0 + maxseg - 1;
  689.     return maxseg;
  690. }
  691. size_t CNWAligner::GetRightSeg(size_t* q0, size_t* q1,
  692.                                size_t* s0, size_t* s1,
  693.                                size_t min_size) const
  694. {
  695.     size_t trdim = m_Transcript.size();
  696.     size_t cur = 0, maxseg = 0;
  697.     const char* seq1_end = m_Seq1 + m_SeqLen1;
  698.     const char* seq2_end = m_Seq2 + m_SeqLen2;
  699.     const char* p1 = seq1_end - 1;
  700.     const char* p2 = seq2_end - 1;
  701.     size_t i0 = m_SeqLen1 - 1, j0 = m_SeqLen2 - 1,
  702.            imax = i0, jmax = j0;
  703.     for(size_t k = 0; k < trdim; ++k) {
  704.         switch(m_Transcript[k]) {
  705.             case eTS_Insert: {
  706.                 --p2;
  707.                 if(cur > maxseg) {
  708.                     maxseg = cur;
  709.                     imax = i0;
  710.                     jmax = j0;
  711.                     if(maxseg >= min_size) goto ret_point;
  712.                 }
  713.                 cur = 0;
  714.             }
  715.             break;
  716.             case eTS_Delete: {
  717.                 --p1;
  718.                 if(cur > maxseg) {
  719.                     maxseg = cur;
  720.                     imax = i0;
  721.                     jmax = j0;
  722.                     if(maxseg >= min_size) goto ret_point;
  723. }
  724.                 cur = 0;
  725.             }
  726.             break;
  727.             case eTS_Match:
  728.             case eTS_Replace: {
  729.                 if(*p1 == *p2) {
  730.                     if(cur == 0) {
  731.                         i0 = p1 - m_Seq1;
  732.                         j0 = p2 - m_Seq2;
  733.                     }
  734.                     ++cur;
  735.                 }
  736.                 else {
  737.                     if(cur > maxseg) {
  738.                         maxseg = cur;
  739.                         imax = i0;
  740.                         jmax = j0;
  741.                         if(maxseg >= min_size) goto ret_point;
  742.                     }
  743.                     cur = 0;
  744.                 }
  745.                 --p1;
  746.                 --p2;
  747.             }
  748.             break;
  749.             default: {
  750.                 NCBI_THROW(CAlgoAlignException, eInternal,
  751.                            "Invalid transcript symbol");
  752.             }
  753.         }
  754.     }
  755.     if(cur > maxseg) {
  756.       maxseg = cur;
  757.       imax = i0;
  758.       jmax = j0;
  759.     }
  760.  ret_point:
  761.     *q1 = imax; *s1 = jmax;
  762.     *q0 = imax - maxseg + 1;
  763.     *s0 = jmax - maxseg + 1;
  764.     return maxseg;
  765. }
  766. size_t CNWAligner::GetLongestSeg(size_t* q0, size_t* q1,
  767.                                  size_t* s0, size_t* s1) const
  768. {
  769.     size_t trdim = m_Transcript.size();
  770.     size_t cur = 0, maxseg = 0;
  771.     const char* p1 = m_Seq1;
  772.     const char* p2 = m_Seq2;
  773.     size_t i0 = 0, j0 = 0, imax = i0, jmax = j0;
  774.     for(int k = trdim-1; k >= 0; --k) {
  775.         switch(m_Transcript[k]) {
  776.             case eTS_Insert: {
  777.                 ++p2;
  778.                 if(cur > maxseg) {
  779.                     maxseg = cur;
  780.                     imax = i0;
  781.                     jmax = j0;
  782.                 }
  783.                 cur = 0;
  784.             }
  785.             break;
  786.             case eTS_Delete: {
  787.             ++p1;
  788.             if(cur > maxseg) {
  789.                 maxseg = cur;
  790.                 imax = i0;
  791.                 jmax = j0;
  792.             }
  793.             cur = 0;
  794.             }
  795.             break;
  796.             case eTS_Match:
  797.             case eTS_Replace: {
  798.                 if(*p1 == *p2) {
  799.                     if(cur == 0) {
  800.                         i0 = p1 - m_Seq1;
  801.                         j0 = p2 - m_Seq2;
  802.                     }
  803.                     ++cur;
  804.                 }
  805.                 else {
  806.     if(cur > maxseg) {
  807.                         maxseg = cur;
  808.                         imax = i0;
  809.                         jmax = j0;
  810.                     }
  811.                     cur = 0;
  812.                 }
  813.                 ++p1;
  814.                 ++p2;
  815.             }
  816.             break;
  817.             default: {
  818.                 NCBI_THROW(CAlgoAlignException, eInternal,
  819.                            "Invalid transcript symbol");
  820.             }
  821.         }
  822.     }
  823.     
  824.     if(cur > maxseg) {
  825.         maxseg = cur;
  826.         imax = i0;
  827.         jmax = j0;
  828.     }
  829.     
  830.     *q0 = imax; *s0 = jmax;
  831.     *q1 = *q0 + maxseg - 1;
  832.     *s1 = *s0 + maxseg - 1;
  833.     return maxseg;
  834. }
  835. END_NCBI_SCOPE
  836. /*
  837.  * ===========================================================================
  838.  * $Log: nw_aligner.cpp,v $
  839.  * Revision 1000.3  2004/06/01 18:04:52  gouriano
  840.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.48
  841.  *
  842.  * Revision 1.48  2004/05/21 21:41:02  gorelenk
  843.  * Added PCH ncbi_pch.hpp
  844.  *
  845.  * Revision 1.47  2004/05/19 13:37:47  kapustin
  846.  * Remove test dumping code
  847.  *
  848.  * Revision 1.46  2004/05/18 21:43:40  kapustin
  849.  * Code cleanup
  850.  *
  851.  * Revision 1.45  2004/05/17 14:50:56  kapustin
  852.  * Add/remove/rearrange some includes and object declarations
  853.  *
  854.  * Revision 1.44  2004/04/23 14:39:47  kapustin
  855.  * Add Splign library and other changes
  856.  *
  857.  * Revision 1.42  2003/12/29 13:03:48  kapustin
  858.  * Return string from GetTranscriptString().
  859.  *
  860.  * Revision 1.41  2003/10/31 19:40:13  kapustin
  861.  * Get rid of some WS and GCC complains
  862.  *
  863.  * Revision 1.40  2003/10/27 20:47:35  kapustin
  864.  * Minor code cleanup
  865.  *
  866.  * Revision 1.39  2003/10/14 18:44:46  kapustin
  867.  * Adjust esf flags during pattern-guided alignment
  868.  *
  869.  * Revision 1.38  2003/09/30 19:50:04  kapustin
  870.  * Make use of standard score matrix interface
  871.  *
  872.  * Revision 1.37  2003/09/26 14:43:18  kapustin
  873.  * Remove exception specifications
  874.  *
  875.  * Revision 1.36  2003/09/15 20:49:11  kapustin
  876.  * Clear the transcript when setting new sequences
  877.  *
  878.  * Revision 1.35  2003/09/04 16:07:38  kapustin
  879.  * Use STL vectors for exception-safe dynamic arrays and matrices
  880.  *
  881.  * Revision 1.34  2003/09/03 17:28:40  kapustin
  882.  * Clean the list of includes
  883.  *
  884.  * Revision 1.33  2003/09/02 22:38:18  kapustin
  885.  * Move format functionality out of the class
  886.  *
  887.  * Revision 1.32  2003/07/09 15:11:22  kapustin
  888.  * Update plain text output with seq ids and use inequalities instead of
  889.  * binary operation to verify intron boundaries
  890.  *
  891.  * Revision 1.31  2003/06/26 20:39:39  kapustin
  892.  * Rename formal parameters in SetEndSpaceFree() to avoid conflict with macro
  893.  * under some configurations
  894.  *
  895.  * Revision 1.30  2003/06/17 17:20:44  kapustin
  896.  * CNWAlignerException -> CAlgoAlignException
  897.  *
  898.  * Revision 1.29  2003/06/17 16:06:13  kapustin
  899.  * Detect all variety of splices in Seq-Align formatter (restored from 1.27)
  900.  *
  901.  * Revision 1.28  2003/06/17 14:51:04  dicuccio
  902.  * Fixed after algo/ rearragnement
  903.  *
  904.  * Revision 1.26  2003/06/02 14:04:49  kapustin
  905.  * Progress indication-related updates
  906.  *
  907.  * Revision 1.25  2003/05/23 18:27:02  kapustin
  908.  * Use weak comparisons in core recurrences. Adjust for new
  909.  * transcript identifiers.
  910.  *
  911.  * Revision 1.24  2003/04/17 14:44:40  kapustin
  912.  * A few changes to eliminate gcc warnings
  913.  *
  914.  * Revision 1.23  2003/04/14 19:00:55  kapustin
  915.  * Add guide creation facility.  x_Run() -> x_Align()
  916.  *
  917.  * Revision 1.22  2003/04/10 19:15:16  kapustin
  918.  * Introduce guiding hits approach
  919.  *
  920.  * Revision 1.21  2003/04/02 20:52:55  kapustin
  921.  * Make FormatAsText virtual. Pass output string as a parameter.
  922.  *
  923.  * Revision 1.20  2003/03/31 15:32:05  kapustin
  924.  * Calculate score independently from transcript
  925.  *
  926.  * Revision 1.19  2003/03/19 16:36:39  kapustin
  927.  * Reverse memory limit condition
  928.  *
  929.  * Revision 1.18  2003/03/18 15:15:51  kapustin
  930.  * Implement virtual memory checking function. Allow separate free end
  931.  * gap specification
  932.  *
  933.  * Revision 1.17  2003/03/17 15:31:46  kapustin
  934.  * Forced conversion to double in memory limit checking to avoid integer
  935.  * overflow
  936.  *
  937.  * Revision 1.16  2003/03/14 19:18:50  kapustin
  938.  * Add memory limit checking. Fix incorrect seq index references when
  939.  * reporting about incorrect input seq character. Support all characters
  940.  * within IUPACna coding
  941.  *
  942.  * Revision 1.15  2003/03/07 13:51:11  kapustin
  943.  * Use zero-based indices to specify seq coordinates in ASN
  944.  *
  945.  * Revision 1.14  2003/03/05 20:13:48  kapustin
  946.  * Simplify FormatAsText(). Fix FormatAsSeqAlign(). Convert sequence
  947.  * alphabets to capitals
  948.  *
  949.  * Revision 1.13  2003/02/11 16:06:54  kapustin
  950.  * Add end-space free alignment support
  951.  *
  952.  * Revision 1.12  2003/02/04 23:04:50  kapustin
  953.  * Add progress callback support
  954.  *
  955.  * Revision 1.11  2003/01/31 02:55:48  lavr
  956.  * User proper argument for ::time()
  957.  *
  958.  * Revision 1.10  2003/01/30 20:32:36  kapustin
  959.  * Add EstiamteRunningTime()
  960.  *
  961.  * Revision 1.9  2003/01/28 12:39:03  kapustin
  962.  * Implement ASN.1 and SeqAlign output
  963.  *
  964.  * Revision 1.8  2003/01/24 16:48:50  kapustin
  965.  * Support more output formats - type 2 and gapped FastA
  966.  *
  967.  * Revision 1.7  2003/01/21 16:34:21  kapustin
  968.  * Get rid of reverse() and reverse_copy() not supported by MSVC and/or ICC
  969.  *
  970.  * Revision 1.6  2003/01/21 12:41:37  kapustin
  971.  * Use class neg infinity constant to specify least possible score
  972.  *
  973.  * Revision 1.5  2003/01/08 15:42:59  kapustin
  974.  * Fix initialization for the first column of the backtrace matrix
  975.  *
  976.  * Revision 1.4  2003/01/06 18:04:10  kapustin
  977.  * CNWAligner: add sequence size verification
  978.  *
  979.  * Revision 1.3  2002/12/31 13:53:13  kapustin
  980.  * CNWAligner::Format() -- use CNcbiOstrstreamToString
  981.  *
  982.  * Revision 1.2  2002/12/12 17:59:28  kapustin
  983.  * Enable spliced alignments
  984.  *
  985.  * Revision 1.1  2002/12/06 17:41:21  ivanov
  986.  * Initial revision
  987.  *
  988.  * ===========================================================================
  989.  */