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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: alnvec.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:40:49  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.59
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: alnvec.cpp,v 1000.2 2004/06/01 19:40:49 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. * Author:  Kamen Todorov, NCBI
  35. *
  36. * File Description:
  37. *   Access to the actual aligned residues
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <objtools/alnmgr/alnvec.hpp>
  43. // Objects includes
  44. #include <objects/seq/Bioseq.hpp>
  45. #include <objects/seq/IUPACna.hpp>
  46. #include <objects/seq/Seq_descr.hpp>
  47. #include <objects/seq/Seqdesc.hpp>
  48. #include <objects/seq/Seq_inst.hpp>
  49. #include <objects/seqset/Seq_entry.hpp>
  50. #include <objects/seqloc/Seq_id.hpp>
  51. #include <objects/seqloc/Seq_interval.hpp>
  52. #include <objects/seqloc/Seq_loc.hpp>
  53. #include <objects/general/Object_id.hpp>
  54. #include <objects/seqfeat/Genetic_code_table.hpp>
  55. // Object Manager includes
  56. #include <objmgr/scope.hpp>
  57. #include <objmgr/seq_vector.hpp>
  58. #include <util/tables/raw_scoremat.h>
  59. BEGIN_NCBI_SCOPE
  60. BEGIN_objects_SCOPE // namespace ncbi::objects::
  61. CAlnVec::CAlnVec(const CDense_seg& ds, CScope& scope) 
  62.     : CAlnMap(ds),
  63.       m_Scope(&scope),
  64.       m_set_GapChar(false),
  65.       m_set_EndChar(false)
  66. {
  67. }
  68. CAlnVec::CAlnVec(const CDense_seg& ds, TNumrow anchor, CScope& scope)
  69.     : CAlnMap(ds, anchor),
  70.       m_Scope(&scope),
  71.       m_set_GapChar(false),
  72.       m_set_EndChar(false)
  73. {
  74. }
  75. CAlnVec::~CAlnVec(void)
  76. {
  77. }
  78. const CBioseq_Handle& CAlnVec::GetBioseqHandle(TNumrow row) const
  79. {
  80.     TBioseqHandleCache::iterator i = m_BioseqHandlesCache.find(row);
  81.     
  82.     if (i != m_BioseqHandlesCache.end()) {
  83.         return i->second;
  84.     } else {
  85.         CBioseq_Handle bioseq_handle = 
  86.             GetScope().GetBioseqHandle(GetSeqId(row));
  87.         if (bioseq_handle) {
  88.             return m_BioseqHandlesCache[row] = bioseq_handle;
  89.         } else {
  90.             string errstr = string("CAlnVec::GetBioseqHandle(): ") 
  91.                 + "Seq-id cannot be resolved: "
  92.                 + GetSeqId(row).AsFastaString();
  93.             
  94.             NCBI_THROW(CAlnException, eInvalidSeqId, errstr);
  95.         }
  96.     }
  97. }
  98. CSeqVector& CAlnVec::x_GetSeqVector(TNumrow row) const
  99. {
  100.     TSeqVectorCache::iterator iter = m_SeqVectorCache.find(row);
  101.     if (iter != m_SeqVectorCache.end()) {
  102.         return *(iter->second);
  103.     } else {
  104.         CSeqVector vec = GetBioseqHandle(row).GetSeqVector
  105.             (CBioseq_Handle::eCoding_Iupac,
  106.              IsPositiveStrand(row) ? 
  107.              CBioseq_Handle::eStrand_Plus :
  108.              CBioseq_Handle::eStrand_Minus);
  109.         CRef<CSeqVector> seq_vec(new CSeqVector(vec));
  110.         return *(m_SeqVectorCache[row] = seq_vec);
  111.     }
  112. }
  113. string& CAlnVec::GetAlnSeqString(string& buffer,
  114.                                  TNumrow row,
  115.                                  const TSignedRange& aln_rng) const
  116. {
  117.     string buff;
  118.     buffer.erase();
  119.     CSeqVector& seq_vec      = x_GetSeqVector(row);
  120.     TSeqPos     seq_vec_size = seq_vec.size();
  121.     
  122.     // get the chunks which are aligned to seq on anchor
  123.     CRef<CAlnMap::CAlnChunkVec> chunk_vec = 
  124.         GetAlnChunks(row, aln_rng, fSkipInserts | fSkipUnalignedGaps);
  125.     
  126.     // for each chunk
  127.     for (int i=0; i<chunk_vec->size(); i++) {
  128.         CConstRef<CAlnMap::CAlnChunk> chunk = (*chunk_vec)[i];
  129.                 
  130.         if (chunk->GetType() & fSeq) {
  131.             // add the sequence string
  132.             if (IsPositiveStrand(row)) {
  133.                 seq_vec.GetSeqData(chunk->GetRange().GetFrom(),
  134.                                    chunk->GetRange().GetTo() + 1,
  135.                                    buff);
  136.             } else {
  137.                 seq_vec.GetSeqData(seq_vec_size - chunk->GetRange().GetTo() - 1,
  138.                                    seq_vec_size - chunk->GetRange().GetFrom(),
  139.                                    buff);
  140.             }
  141.             buffer += buff;
  142.         } else {
  143.             // add appropriate number of gap/end chars
  144.             const int n = chunk->GetAlnRange().GetLength();
  145.             char* ch_buff = new char[n+1];
  146.             char fill_ch;
  147.             if (chunk->GetType() & fNoSeqOnLeft  ||
  148.                 chunk->GetType() & fNoSeqOnRight) {
  149.                 fill_ch = GetEndChar();
  150.             } else {
  151.                 fill_ch = GetGapChar(row);
  152.             }
  153.             memset(ch_buff, fill_ch, n);
  154.             ch_buff[n] = 0;
  155.             buffer += ch_buff;
  156.             delete[] ch_buff;
  157.         }
  158.     }
  159.     return buffer;
  160. }
  161. string& CAlnVec::GetWholeAlnSeqString(TNumrow       row,
  162.                                       string&       buffer,
  163.                                       TSeqPosList * insert_aln_starts,
  164.                                       TSeqPosList * insert_starts,
  165.                                       TSeqPosList * insert_lens,
  166.                                       unsigned int  scrn_width,
  167.                                       TSeqPosList * scrn_lefts,
  168.                                       TSeqPosList * scrn_rights) const
  169. {
  170.     TSeqPos       aln_pos = 0,
  171.         len = 0,
  172.         curr_pos = 0,
  173.         anchor_pos = 0,
  174.         scrn_pos = 0,
  175.         prev_len = 0,
  176.         ttl_len = 0;
  177.     TSignedSeqPos start = -1,
  178.         stop = -1,
  179.         scrn_lft_seq_pos = -1,
  180.         scrn_rgt_seq_pos = -1,
  181.         prev_aln_pos = -1,
  182.         prev_start = -1;
  183.     TNumseg       seg;
  184.     int           pos, nscrns, delta;
  185.     
  186.     TSeqPos aln_len = GetAlnStop() + 1;
  187.     bool anchored = IsSetAnchor();
  188.     bool plus     = IsPositiveStrand(row);
  189.     int  width    = GetWidth(row);
  190.     scrn_width *= width;
  191.     const bool record_inserts = insert_starts && insert_lens;
  192.     const bool record_coords  = scrn_width && scrn_lefts && scrn_rights;
  193.     // allocate space for the row
  194.     char* c_buff = new char[aln_len + 1];
  195.     char* c_buff_ptr = c_buff;
  196.     string buff;
  197.     
  198.     const TNumseg& left_seg = x_GetSeqLeftSeg(row);
  199.     const TNumseg& right_seg = x_GetSeqRightSeg(row);
  200.     // loop through all segments
  201.     for (seg = 0, pos = row, aln_pos = 0, anchor_pos = m_Anchor;
  202.          seg < m_NumSegs;
  203.          ++seg, pos += m_NumRows, anchor_pos += m_NumRows) {
  204.         
  205.         const TSeqPos& seg_len = m_Lens[seg];
  206.         start = m_Starts[pos];
  207.         len = seg_len * width;
  208.         if (anchored  &&  m_Starts[anchor_pos] < 0) {
  209.             if (start >= 0) {
  210.                 // record the insert if requested
  211.                 if (record_inserts) {
  212.                     if (prev_aln_pos == (aln_pos / width)  &&
  213.                         start == (plus ? prev_start + prev_len :
  214.                                   prev_start - len)) {
  215.                         // consolidate the adjacent inserts
  216.                         ttl_len += len;
  217.                         insert_lens->pop_back();
  218.                         insert_lens->push_back(ttl_len);
  219.                         if (!plus) {
  220.                             insert_starts->pop_back();
  221.                             insert_starts->push_back(start);
  222.                         }
  223.                     } else {
  224.                         prev_aln_pos = aln_pos / width;
  225.                         ttl_len = len;
  226.                         insert_starts->push_back(start);
  227.                         insert_aln_starts->push_back(prev_aln_pos);
  228.                         insert_lens->push_back(len);
  229.                     }
  230.                     prev_start = start;
  231.                     prev_len = len;
  232. }
  233.             }
  234.         } else {
  235.             if (start >= 0) {
  236.                 stop = start + len - 1;
  237.                 // add regular sequence to buffer
  238.                 GetSeqString(buff, row, start, stop);
  239.                 memcpy(c_buff_ptr, buff.c_str(), seg_len);
  240.                 c_buff_ptr += seg_len;
  241.                 
  242.                 // take care of coords if necessary
  243.                 if (record_coords) {
  244.                     if (scrn_lft_seq_pos < 0) {
  245.                         scrn_lft_seq_pos = plus ? start : stop;
  246.                         if (scrn_rgt_seq_pos < 0) {
  247.                             scrn_rgt_seq_pos = scrn_lft_seq_pos;
  248.                         }
  249.                     }
  250.                     // previous scrns
  251.                     nscrns = (aln_pos - scrn_pos) / scrn_width;
  252.                     for (int i = 0; i < nscrns; i++) {
  253.                         scrn_lefts->push_back(scrn_lft_seq_pos);
  254.                         scrn_rights->push_back(scrn_rgt_seq_pos);
  255.                         if (i == 0) {
  256.                             scrn_lft_seq_pos = plus ? start : stop;
  257.                         }
  258.                         scrn_pos += scrn_width;
  259.                     }
  260.                     if (nscrns > 0) {
  261.                         scrn_lft_seq_pos = plus ? start : stop;
  262.                     }
  263.                     // current scrns
  264.                     nscrns = (aln_pos + len - scrn_pos) / scrn_width;
  265.                     curr_pos = aln_pos;
  266.                     for (int i = 0; i < nscrns; i++) {
  267.                         delta = (plus ?
  268.                                  scrn_width - (curr_pos - scrn_pos) :
  269.                                  curr_pos - scrn_pos - scrn_width);
  270.                         
  271.                         scrn_lefts->push_back(scrn_lft_seq_pos);
  272.                         if (plus ?
  273.                             scrn_lft_seq_pos < start :
  274.                             scrn_lft_seq_pos > stop) {
  275.                             scrn_lft_seq_pos = (plus ? start : stop) +
  276.                                 delta;
  277.                             scrn_rgt_seq_pos = scrn_lft_seq_pos +
  278.                                 (plus ? -1 : 1);
  279.                         } else {
  280.                             scrn_rgt_seq_pos = scrn_lft_seq_pos + (plus ? -1 : 1)
  281.                                 + delta;
  282.                             scrn_lft_seq_pos += delta;
  283.                         }
  284.                         if (seg == left_seg  &&
  285.                             scrn_lft_seq_pos == scrn_rgt_seq_pos) {
  286.                             if (plus) {
  287.                                 scrn_rgt_seq_pos--;
  288.                             } else {
  289.                                 scrn_rgt_seq_pos++;
  290.                             }
  291.                         }
  292.                         scrn_rights->push_back(scrn_rgt_seq_pos);
  293.                         curr_pos = scrn_pos += scrn_width;
  294.                     }
  295.                     if (aln_pos + len <= scrn_pos) {
  296.                         scrn_lft_seq_pos = -1; // reset
  297.                     }
  298.                     scrn_rgt_seq_pos = plus ? stop : start;
  299.                 }
  300.             } else {
  301.                 // add appropriate number of gap/end chars
  302.                 
  303.                 char* ch_buff = new char[seg_len + 1];
  304.                 char fill_ch;
  305.                 
  306.                 if (seg < left_seg  ||  seg > right_seg) {
  307.                     fill_ch = GetEndChar();
  308.                 } else {
  309.                     fill_ch = GetGapChar(row);
  310.                 }
  311.                 
  312.                 memset(ch_buff, fill_ch, seg_len);
  313.                 ch_buff[seg_len] = 0;
  314.                 memcpy(c_buff_ptr, ch_buff, seg_len);
  315.                 c_buff_ptr += seg_len;
  316.                 delete[] ch_buff;
  317.             }
  318.             aln_pos += len;
  319.         }
  320.     }
  321.     
  322.     // take care of the remaining coords if necessary
  323.     if (record_coords) {
  324.         // previous scrns
  325.         TSeqPos pos_diff = aln_pos - scrn_pos;
  326.         if (pos_diff > 0) {
  327.             nscrns = pos_diff / scrn_width;
  328.             if (pos_diff % scrn_width) {
  329.                 nscrns++;
  330.             }
  331.             for (int i = 0; i < nscrns; i++) {
  332.                 scrn_lefts->push_back(scrn_lft_seq_pos);
  333.                 scrn_rights->push_back(scrn_rgt_seq_pos);
  334.                 if (i == 0) {
  335.                     scrn_lft_seq_pos = scrn_rgt_seq_pos;
  336.                 }
  337.                 scrn_pos += scrn_width;
  338.             }
  339.         }
  340.     }
  341.     c_buff[aln_len] = '';
  342.     buffer = c_buff;
  343.     delete [] c_buff;
  344.     return buffer;
  345. }
  346. //
  347. // CreateConsensus()
  348. //
  349. // compute a consensus sequence given a particular alignment
  350. // the rules for a consensus are:
  351. //   - a segment is consensus gap if > 50% of the sequences are gap at this
  352. //     segment.  50% exactly is counted as sequence
  353. //   - for a segment counted as sequence, for each position, the most
  354. //     frequently occurring base is counted as consensus.  in the case of
  355. //     a tie, the consensus is considered muddied, and the consensus is
  356. //     so marked
  357. //
  358. CRef<CDense_seg> CAlnVec::CreateConsensus(int& consensus_row) const
  359. {
  360.     if ( !m_DS ) {
  361.         return CRef<CDense_seg>();
  362.     }
  363.     int i;
  364.     int j;
  365.     // temporary storage for our consensus
  366.     vector<string> consens(m_NumSegs);
  367.     // determine what the number of segments required for a gapped consensus
  368.     // segment is.  this must be rounded to be at least 50%.
  369.     int gap_seg_thresh = m_NumRows - m_NumRows / 2;
  370.     for (j = 0;  j < m_NumSegs;  ++j) {
  371.         // evaluate for gap / no gap
  372.         int gap_count = 0;
  373.         for (i = 0;  i < m_NumRows;  ++i) {
  374.             if (m_Starts[ j*m_NumRows + i ] == -1) {
  375.                 ++gap_count;
  376.             }
  377.         }
  378.         // check to make sure that this seg is not a consensus
  379.         // gap seg
  380.         if ( gap_count <= gap_seg_thresh ) {
  381.             // we will build a segment with enough bases to match
  382.             consens[j].resize(m_Lens[j]);
  383.             // retrieve all sequences for this segment
  384.             vector<string> segs(m_NumRows);
  385.             for (i = 0;  i < m_NumRows;  ++i) {
  386.                 if (m_Starts[ j*m_NumRows + i ] != -1) {
  387.                     TSeqPos start = m_Starts[j*m_NumRows+i];
  388.                     TSeqPos stop  = start + m_Lens[j];
  389.                     if (IsPositiveStrand(i)) {
  390.                         x_GetSeqVector(i).GetSeqData(start, stop, segs[i]);
  391.                     } else {
  392.                         CSeqVector &  seq_vec = x_GetSeqVector(i);
  393.                         TSeqPos size = seq_vec.size();
  394.                         seq_vec.GetSeqData(size - stop, size - start, segs[i]);
  395.                     }
  396.                     for (int c = 0;  c < segs[i].length();  ++c) {
  397.                         segs[i][c] = FromIupac(segs[i][c]);
  398.                     }
  399.                 }
  400.             }
  401.             typedef multimap<int, unsigned char, greater<int> > TRevMap;
  402.             // 
  403.             // evaluate for a consensus
  404.             //
  405.             for (i = 0;  i < m_Lens[j];  ++i) {
  406.                 // first, we record which bases occur and how often
  407.                 // this is computed in NCBI4na notation
  408.                 int base_count[4];
  409.                 base_count[0] = base_count[1] =
  410.                     base_count[2] = base_count[3] = 0;
  411.                 for (int row = 0;  row < m_NumRows;  ++row) {
  412.                     if (segs[row] != "") {
  413.                         for (int pos = 0;  pos < 4;  ++pos) {
  414.                             if (segs[row][i] & (1<<pos)) {
  415.                                 ++base_count[ pos ];
  416.                             }
  417.                         }
  418.                     }
  419.                 }
  420.                 // we create a sorted list (in descending order) of
  421.                 // frequencies of appearance to base
  422.                 // the frequency is "global" for this position: that is,
  423.                 // if 40% of the sequences are gapped, the highest frequency
  424.                 // any base can have is 0.6
  425.                 TRevMap rev_map;
  426.                 for (int k = 0;  k < 4;  ++k) {
  427.                     // this gets around a potentially tricky idiosyncrasy
  428.                     // in some implementations of multimap.  depending on
  429.                     // the library, the key may be const (or not)
  430.                     TRevMap::value_type p(base_count[k], (1<<k));
  431.                     rev_map.insert(p);
  432.                 }
  433.                 // the base threshold for being considered unique is at least
  434.                 // 70% of the available sequences
  435.                 int base_thresh =
  436.                     ((m_NumRows - gap_count) * 7 + 5) / 10;
  437.                 // now, the first element here contains the best frequency
  438.                 // we scan for the appropriate bases
  439.                 if (rev_map.count(rev_map.begin()->first) == 1 &&
  440.                     rev_map.begin()->first >= base_thresh) {
  441.                     consens[j][i] = ToIupac(rev_map.begin()->second);
  442.                 } else {
  443.                     // now we need to make some guesses based on IUPACna
  444.                     // notation
  445.                     int               count;
  446.                     unsigned char     c    = 0x00;
  447.                     int               freq = 0;
  448.                     TRevMap::iterator curr = rev_map.begin();
  449.                     TRevMap::iterator prev = rev_map.begin();
  450.                     for (count = 0;
  451.                          curr != rev_map.end() &&
  452.                          (freq < base_thresh || prev->first == curr->first);
  453.                          ++curr, ++count) {
  454.                         prev = curr;
  455.                         freq += curr->first;
  456.                         c |= curr->second;
  457.                     }
  458.                     //
  459.                     // catchall
  460.                     //
  461.                     if (count > 2) {
  462.                         consens[j][i] = 'N';
  463.                     } else {
  464.                         consens[j][i] = ToIupac(c);
  465.                     }
  466.                 }
  467.             }
  468.         }
  469.     }
  470.     //
  471.     // now, create a new CDense_seg
  472.     // we create a new CBioseq for our data, add it to our scope, and
  473.     // copy the contents of the CDense_seg
  474.     //
  475.     string data;
  476.     TSignedSeqPos total_bases = 0;
  477.     CRef<CDense_seg> new_ds(new CDense_seg());
  478.     new_ds->SetDim(m_NumRows + 1);
  479.     new_ds->SetNumseg(m_NumSegs);
  480.     new_ds->SetLens() = m_Lens;
  481.     new_ds->SetStarts().reserve(m_Starts.size() + m_NumSegs);
  482.     if ( !m_Strands.empty() ) {
  483.         new_ds->SetStrands().reserve(m_Strands.size() +
  484.                                      m_NumSegs);
  485.     }
  486.     for (i = 0;  i < consens.size();  ++i) {
  487.         // copy the old entries
  488.         for (j = 0;  j < m_NumRows;  ++j) {
  489.             int idx = i * m_NumRows + j;
  490.             new_ds->SetStarts().push_back(m_Starts[idx]);
  491.             if ( !m_Strands.empty() ) {
  492.                 new_ds->SetStrands().push_back(m_Strands[idx]);
  493.             }
  494.         }
  495.         // add our new entry
  496.         // this places the consensus as the last sequence
  497.         // it should preferably be the first, but this would mean adjusting
  498.         // the bioseq handle and seqvector caches, and all row numbers would
  499.         // shift
  500.         if (consens[i].length() != 0) {
  501.             new_ds->SetStarts().push_back(total_bases);
  502.         } else {
  503.             new_ds->SetStarts().push_back(-1);
  504.         }
  505.         
  506.         if ( !m_Strands.empty() ) {
  507.             new_ds->SetStrands().push_back(eNa_strand_unknown);
  508.         }
  509.         total_bases += consens[i].length();
  510.         data += consens[i];
  511.     }
  512.     // copy our IDs
  513.     for (i = 0;  i < m_Ids.size();  ++i) {
  514.         new_ds->SetIds().push_back(m_Ids[i]);
  515.     }
  516.     // now, we construct a new Bioseq and add it to our scope
  517.     // this bioseq must have a local ID; it will be named "consensus"
  518.     // once this is in, the Denseg should resolve all IDs correctly
  519.     {{
  520.          CRef<CBioseq> bioseq(new CBioseq());
  521.          // construct a local sequence ID for this sequence
  522.          CRef<CSeq_id> id(new CSeq_id());
  523.          bioseq->SetId().push_back(id);
  524.          id->SetLocal().SetStr("consensus");
  525.          new_ds->SetIds().push_back(id);
  526.          // add a description for this sequence
  527.          CSeq_descr& desc = bioseq->SetDescr();
  528.          CRef<CSeqdesc> d(new CSeqdesc);
  529.          desc.Set().push_back(d);
  530.          d->SetComment("This is a generated consensus sequence");
  531.          // the main one: Seq-inst
  532.          CSeq_inst& inst = bioseq->SetInst();
  533.          inst.SetRepr(CSeq_inst::eRepr_raw);
  534.          inst.SetMol(CSeq_inst::eMol_na);
  535.          inst.SetLength(data.length());
  536.          CSeq_data& seq_data = inst.SetSeq_data();
  537.          CIUPACna& na = seq_data.SetIupacna();
  538.          na = CIUPACna(data);
  539.          // once we've created the bioseq, we need to add it to the
  540.          // scope
  541.          CRef<CSeq_entry> entry(new CSeq_entry());
  542.          entry->SetSeq(*bioseq);
  543.          GetScope().AddTopLevelSeqEntry(*entry);
  544.     }}
  545.     consensus_row = new_ds->GetIds().size() - 1;
  546.     return new_ds;
  547. }
  548. static SNCBIFullScoreMatrix s_FullScoreMatrix;
  549. int CAlnVec::CalculateScore(const string& s1, const string& s2,
  550.                             bool s1_is_prot, bool s2_is_prot)
  551. {
  552.     // check the lengths
  553.     if (s1_is_prot == s2_is_prot  &&  s1.length() != s2.length()) {
  554.         NCBI_THROW(CAlnException, eInvalidRequest,
  555.                    "CAlnVec::CalculateScore(): "
  556.                    "Strings should have equal lenghts.");
  557.     } else if (s1.length() * (s1_is_prot ? 1 : 3) !=
  558.                s1.length() * (s1_is_prot ? 1 : 3)) {
  559.         NCBI_THROW(CAlnException, eInvalidRequest,
  560.                    "CAlnVec::CalculateScore(): "
  561.                    "Strings lengths do not match.");
  562.     }        
  563.     int score = 0;
  564.     const char * res1 = s1.c_str();
  565.     const char * res2 = s2.c_str();
  566.     const char * end1 = res1 + s1.length();
  567.     const char * end2 = res2 + s2.length();
  568.     
  569.     static bool s_FullScoreMatrixInitialized = false;
  570.     if (s1_is_prot  &&  s2_is_prot) {
  571.         if ( !s_FullScoreMatrixInitialized ) {
  572.             s_FullScoreMatrixInitialized = true;
  573.             NCBISM_Unpack(&NCBISM_Blosum62, &s_FullScoreMatrix);
  574.         }
  575.         
  576.         // use BLOSUM62 matrix
  577.         for ( ;  res1 != end1;  res1++, res2++) {
  578.             score += s_FullScoreMatrix.s[*res1][*res2];
  579.         }
  580.     } else if ( !s1_is_prot  &&  !s2_is_prot ) {
  581.         // use match score/mismatch penalty
  582.         for ( ; res1 != end1;  res1++, res2++) {
  583.             if (*res1 == *res2) {
  584.                 score += 1;
  585.             } else {
  586.                 score -= 3;
  587.             }
  588.         }
  589.     } else {
  590.         string t;
  591.         if (s1_is_prot) {
  592.             TranslateNAToAA(s2, t);
  593.             for ( ;  res1 != end1;  res1++, res2++) {
  594.                 score += s_FullScoreMatrix.s[*res1][*res2];
  595.             }
  596.         } else {
  597.             TranslateNAToAA(s1, t);
  598.             for ( ;  res2 != end2;  res1++, res2++) {
  599.                 score += s_FullScoreMatrix.s[*res1][*res2];
  600.             }
  601.         }
  602.     }
  603.     return score;
  604. }
  605. void CAlnVec::TranslateNAToAA(const string& na, string& aa)
  606. {
  607.     if (na.size() % 3) {
  608.         NCBI_THROW(CAlnException, eTranslateFailure,
  609.                    "CAlnVec::TranslateNAToAA(): "
  610.                    "NA size expected to be divisible by 3");
  611.     }
  612.     const CTrans_table& tbl = CGen_code_table::GetTransTable(1);
  613.     unsigned int i, j = 0, state = 0;
  614.     aa.resize(na.size() / 3);
  615.     string::const_iterator res = na.begin();
  616.     while (res != na.end()) {
  617.         for (i = 0; i < 3; i++, res++) {
  618.             state = tbl.NextCodonState(state, *res);
  619.         }
  620.         aa[j++] = tbl.GetCodonResidue(state);
  621.     }
  622. }
  623. int CAlnVec::CalculateScore(TNumrow row1, TNumrow row2) const
  624. {
  625.     TNumrow       numrows = m_NumRows;
  626.     TNumrow       index1 = row1, index2 = row2;
  627.     TSignedSeqPos start1, start2;
  628.     string        buff1, buff2;
  629.     bool          isAA1, isAA2;
  630.     int           score = 0;
  631.     TSeqPos       len;
  632.     
  633.     isAA1 = GetBioseqHandle(row1).GetBioseqCore()
  634.         ->GetInst().GetMol() == CSeq_inst::eMol_aa;
  635.     isAA2 = GetBioseqHandle(row2).GetBioseqCore()
  636.         ->GetInst().GetMol() == CSeq_inst::eMol_aa;
  637.     CSeqVector&   seq_vec1 = x_GetSeqVector(row1);
  638.     TSeqPos       size1    = seq_vec1.size();
  639.     CSeqVector &  seq_vec2 = x_GetSeqVector(row2);
  640.     TSeqPos       size2    = seq_vec2.size();
  641.     for (TNumseg seg = 0; seg < m_NumSegs; seg++) {
  642.         start1 = m_Starts[index1];
  643.         start2 = m_Starts[index2];
  644.         if (start1 >=0  &&  start2 >= 0) {
  645.             len = m_Lens[seg];
  646.             if (IsPositiveStrand(row1)) {
  647.                 seq_vec1.GetSeqData(start1,
  648.                                     start1 + len,
  649.                                     buff1);
  650.             } else {
  651.                 seq_vec1.GetSeqData(size1 - (start1 + len),
  652.                                     size1 - start1,
  653.                                     buff1);
  654.             }
  655.             if (IsPositiveStrand(row2)) {
  656.                 seq_vec2.GetSeqData(start2,
  657.                                     start2 + len,
  658.                                     buff2);
  659.             } else {
  660.                 seq_vec2.GetSeqData(size2 - (start2 + len),
  661.                                     size2 - start2,
  662.                                     buff2);
  663.             }
  664.             score += CalculateScore(buff1, buff2, isAA1, isAA2);
  665.         }
  666.         index1 += numrows;
  667.         index2 += numrows;
  668.     }
  669.     return score;
  670. }
  671. string& CAlnVec::GetColumnVector(string& buffer,
  672.                                  TSeqPos aln_pos,
  673.                                  TResidueCount * residue_count,
  674.                                  bool gaps_in_count) const
  675. {
  676.     if (aln_pos > GetAlnStop()) {
  677.         aln_pos = GetAlnStop(); // out-of-range adjustment
  678.     }
  679.     TNumseg seg   = GetSeg(aln_pos);
  680.     TSeqPos delta = aln_pos - GetAlnStart(seg);
  681.     TSeqPos len   = GetLen(seg);
  682.     TSignedSeqPos pos;
  683.     for (TNumrow row = 0; row < m_NumRows; row++) {
  684.         pos = GetStart(row, seg);
  685.         if (pos >= 0) {
  686.             // it's a sequence residue
  687.             bool plus = IsPositiveStrand(row);
  688.             if (plus) {
  689.                 pos += delta;
  690.             } else {
  691.                 pos += len - 1 - delta;
  692.             }
  693.             
  694.             CSeqVector& seq_vec = x_GetSeqVector(row);
  695.             if (GetWidth(row) == 3) {
  696.                 string na_buff, aa_buff;
  697.                 if (plus) {
  698.                     seq_vec.GetSeqData(pos, pos + 3, na_buff);
  699.                 } else {
  700.                     TSeqPos size = seq_vec.size();
  701.                     seq_vec.GetSeqData(size - pos - 3, size - pos, na_buff);
  702.                 }
  703.                 TranslateNAToAA(na_buff, aa_buff);
  704.                 buffer[row] = aa_buff[0];
  705.             } else {
  706.                 buffer[row] = seq_vec[plus ? pos : seq_vec.size() - pos - 1];
  707.             }
  708.             if (residue_count) {
  709.                 (*residue_count)[FromIupac(buffer[row])]++;
  710.             }
  711.         } else {
  712.             // it's a gap or endchar
  713.             
  714.             if (GetEndChar() != (buffer[row] = GetGapChar(row))) {
  715.                 // need to check the where the segment is
  716.                 // only if endchar != gap
  717.                 // this saves a check if there're the same
  718.                 TSegTypeFlags type = GetSegType(row, seg);
  719.                 if (type & fNoSeqOnLeft  ||  type & fNoSeqOnRight) {
  720.                     buffer[row] = GetEndChar();
  721.                 }
  722.             }
  723.             if (gaps_in_count) {
  724.                 (*residue_count)[FromIupac(buffer[row])]++;
  725.             }
  726.         }
  727.     } // for row
  728.     return buffer;
  729. }
  730. int CAlnVec::CalculatePercentIdentity(TSeqPos aln_pos) const
  731. {
  732.     string column;
  733.     column.resize(m_NumRows);
  734.     TResidueCount residue_cnt;
  735.     residue_cnt.resize(16, 0);
  736.     GetColumnVector(column, aln_pos, &residue_cnt);
  737.     
  738.     int max = 0, total = 0;
  739.     ITERATE (TResidueCount, i_res, residue_cnt) {
  740.         if (*i_res > max) {
  741.             max = *i_res;
  742.         }
  743.         total += *i_res;
  744.     }
  745.     return 100 * max / total;
  746. }
  747. END_objects_SCOPE // namespace ncbi::objects::
  748. END_NCBI_SCOPE
  749. /*
  750. * ===========================================================================
  751. *
  752. * $Log: alnvec.cpp,v $
  753. * Revision 1000.2  2004/06/01 19:40:49  gouriano
  754. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.59
  755. *
  756. * Revision 1.59  2004/05/21 21:42:51  gorelenk
  757. * Added PCH ncbi_pch.hpp
  758. *
  759. * Revision 1.58  2004/03/30 16:39:09  todorov
  760. * -redundant statement
  761. *
  762. * Revision 1.57  2003/12/22 19:14:12  todorov
  763. * Only left constructors that accept CScope&
  764. *
  765. * Revision 1.56  2003/12/22 18:30:37  todorov
  766. * ObjMgr is no longer created internally. Scope should be passed as a reference in the ctor
  767. *
  768. * Revision 1.55  2003/12/18 19:47:51  todorov
  769. * + GetColumnVector & CalculatePercentIdentity
  770. *
  771. * Revision 1.54  2003/12/10 17:17:39  todorov
  772. * CalcScore now const
  773. *
  774. * Revision 1.53  2003/10/21 14:41:35  grichenk
  775. * Fixed type convertion
  776. *
  777. * Revision 1.52  2003/09/26 16:58:34  todorov
  778. * Fixed the length of c_buff
  779. *
  780. * Revision 1.51  2003/09/23 21:29:34  todorov
  781. * Rearranged variables & fixed a bug
  782. *
  783. * Revision 1.50  2003/09/23 18:37:24  todorov
  784. * bug fix in GetWholeAlnSeqString
  785. *
  786. * Revision 1.49  2003/09/22 21:00:16  todorov
  787. * Consolidated adjacent inserts in GetWholeAlnSeqString
  788. *
  789. * Revision 1.48  2003/09/22 19:03:30  todorov
  790. * Use the new x_GetSeq{Left,Right}Seg methods
  791. *
  792. * Revision 1.47  2003/09/17 15:48:06  jianye
  793. * Added missing [] when de-allocating c_buff
  794. *
  795. * Revision 1.46  2003/09/17 14:46:39  todorov
  796. * Performance optimization: Use char * instead of string
  797. *
  798. * Revision 1.45  2003/09/12 16:16:50  todorov
  799. * TSeqPos->TSignedSeqPos bug fix
  800. *
  801. * Revision 1.44  2003/08/29 18:18:58  dicuccio
  802. * Changed CreateConsensus() API to return a new dense-seg instead of altering the
  803. * current alignment manager
  804. *
  805. * Revision 1.43  2003/08/27 21:19:55  todorov
  806. * using raw_scoremat.h
  807. *
  808. * Revision 1.42  2003/08/25 16:34:59  todorov
  809. * exposed GetWidth
  810. *
  811. * Revision 1.41  2003/08/20 17:50:52  todorov
  812. * resize + direct string access rather than appending
  813. *
  814. * Revision 1.40  2003/08/20 17:23:54  ucko
  815. * TranslateNAToAA: append to strings with += rather than push_back
  816. * (which MSVC lacks); fix a typo while I'm at it.
  817. *
  818. * Revision 1.39  2003/08/20 14:34:58  todorov
  819. * Support for NA2AA Densegs
  820. *
  821. * Revision 1.38  2003/07/23 20:26:14  todorov
  822. * fixed an unaligned pieces coords problem in GetWhole..
  823. *
  824. * Revision 1.37  2003/07/23 20:24:39  todorov
  825. * +aln_starts for the inserts in GetWhole...
  826. *
  827. * Revision 1.36  2003/07/22 19:18:37  todorov
  828. * fixed a 1st seg check in GetWhole...
  829. *
  830. * Revision 1.35  2003/07/21 21:29:39  todorov
  831. * cleaned an expression
  832. *
  833. * Revision 1.34  2003/07/21 17:08:50  todorov
  834. * fixed calc of remaining nscrns in GetWhole...
  835. *
  836. * Revision 1.33  2003/07/18 22:12:51  todorov
  837. * Fixed an anchor bug in GetWholeAlnSeqString
  838. *
  839. * Revision 1.32  2003/07/17 22:45:56  todorov
  840. * +GetWholeAlnSeqString
  841. *
  842. * Revision 1.31  2003/07/15 21:13:54  todorov
  843. * rm bioseq_handle ref
  844. *
  845. * Revision 1.30  2003/07/15 20:54:01  todorov
  846. * exception type fixed
  847. *
  848. * Revision 1.29  2003/07/15 20:46:09  todorov
  849. * Exception if bioseq handle is null
  850. *
  851. * Revision 1.28  2003/06/05 19:03:12  todorov
  852. * Added const refs to Dense-seg members as a speed optimization
  853. *
  854. * Revision 1.27  2003/06/02 16:06:40  dicuccio
  855. * Rearranged src/objects/ subtree.  This includes the following shifts:
  856. *     - src/objects/asn2asn --> arc/app/asn2asn
  857. *     - src/objects/testmedline --> src/objects/ncbimime/test
  858. *     - src/objects/objmgr --> src/objmgr
  859. *     - src/objects/util --> src/objmgr/util
  860. *     - src/objects/alnmgr --> src/objtools/alnmgr
  861. *     - src/objects/flat --> src/objtools/flat
  862. *     - src/objects/validator --> src/objtools/validator
  863. *     - src/objects/cddalignview --> src/objtools/cddalignview
  864. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  865. * replaces the three libmmdb? libs.
  866. *
  867. * Revision 1.26  2003/04/24 16:15:57  vasilche
  868. * Added missing includes and forward class declarations.
  869. *
  870. * Revision 1.25  2003/04/15 14:21:27  vasilche
  871. * Added missing include file.
  872. *
  873. * Revision 1.24  2003/03/29 07:07:31  todorov
  874. * deallocation bug fixed
  875. *
  876. * Revision 1.23  2003/03/05 16:18:17  todorov
  877. * + str len err check
  878. *
  879. * Revision 1.22  2003/02/11 21:32:44  todorov
  880. * fMinGap optional merging algorithm
  881. *
  882. * Revision 1.21  2003/01/29 20:54:37  todorov
  883. * CalculateScore speed optimization
  884. *
  885. * Revision 1.20  2003/01/27 22:48:41  todorov
  886. * Changed CreateConsensus accordingly too
  887. *
  888. * Revision 1.19  2003/01/27 22:30:30  todorov
  889. * Attune to seq_vector interface change
  890. *
  891. * Revision 1.18  2003/01/23 21:31:08  todorov
  892. * Removed the original, inefficient GetXXXString methods
  893. *
  894. * Revision 1.17  2003/01/23 16:31:34  todorov
  895. * Added calc score methods
  896. *
  897. * Revision 1.16  2003/01/17 19:25:04  ucko
  898. * Clear buffer with erase(), as G++ 2.9x lacks string::clear.
  899. *
  900. * Revision 1.15  2003/01/17 18:16:53  todorov
  901. * Added a better-performing set of GetXXXString methods
  902. *
  903. * Revision 1.14  2003/01/16 20:46:17  todorov
  904. * Added Gap/EndChar set flags
  905. *
  906. * Revision 1.13  2003/01/08 16:50:56  todorov
  907. * Fixed TGetChunkFlags in GetAlnSeqString
  908. *
  909. * Revision 1.12  2002/11/04 21:29:08  grichenk
  910. * Fixed usage of const CRef<> and CRef<> constructor
  911. *
  912. * Revision 1.11  2002/10/21 19:15:20  todorov
  913. * added GetAlnSeqString
  914. *
  915. * Revision 1.10  2002/10/08 18:03:15  todorov
  916. * added the default m_EndChar value
  917. *
  918. * Revision 1.9  2002/10/01 14:13:22  dicuccio
  919. * Added handling of strandedness in creation of consensus sequence.
  920. *
  921. * Revision 1.8  2002/09/25 20:20:24  todorov
  922. * x_GetSeqVector uses the strand info now
  923. *
  924. * Revision 1.7  2002/09/25 19:34:54  todorov
  925. * "un-inlined" x_GetSeqVector
  926. *
  927. * Revision 1.6  2002/09/25 18:16:29  dicuccio
  928. * Reworked computation of consensus sequence - this is now stored directly
  929. * in the underlying CDense_seg
  930. * Added exception class; currently used only on access of non-existent
  931. * consensus.
  932. *
  933. * Revision 1.5  2002/09/19 18:24:15  todorov
  934. * New function name for GetSegSeqString to avoid confusion
  935. *
  936. * Revision 1.4  2002/09/19 17:40:16  todorov
  937. * fixed m_Anchor setting in case of consensus
  938. *
  939. * Revision 1.3  2002/09/05 19:30:39  dicuccio
  940. * - added ability to reference a consensus sequence for a given alignment
  941. * - added caching for CSeqVector objects (big performance gain)
  942. * - many small bugs fixed
  943. *
  944. * Revision 1.2  2002/08/29 18:40:51  dicuccio
  945. * added caching mechanism for CSeqVector - this greatly improves speed in
  946. * accessing sequence data.
  947. *
  948. * Revision 1.1  2002/08/23 14:43:52  ucko
  949. * Add the new C++ alignment manager to the public tree (thanks, Kamen!)
  950. *
  951. *
  952. * ===========================================================================
  953. */