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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: nw_formatter.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:04:54  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: nw_formatter.cpp,v 1000.2 2004/06/01 18:04:54 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:  Yuri Kapustin
  35.  *
  36.  * ===========================================================================
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <algo/align/nw_formatter.hpp>
  41. #include <algo/align/nw_aligner.hpp>
  42. #include <algo/align/align_exception.hpp>
  43. #include <objects/seqalign/Score.hpp>
  44. #include <objects/general/Object_id.hpp>
  45. #include <objects/seqalign/Dense_seg.hpp>
  46. #include <objects/seqloc/Seq_id.hpp>
  47. #include <objects/seqalign/Seq_align.hpp>
  48. #include <serial/objostrasn.hpp>
  49. #include <serial/serial.hpp>
  50. #include <iterator>
  51. BEGIN_NCBI_SCOPE
  52. USING_SCOPE(objects);
  53. CNWFormatter::CNWFormatter (const CNWAligner& aligner):
  54.     m_aligner(&aligner)
  55. {
  56. }
  57. void CNWFormatter::AsSeqAlign(CSeq_align* seqalign) const
  58. {
  59.     if(seqalign == 0) {
  60.         NCBI_THROW(CAlgoAlignException,
  61.                    eBadParameter,
  62.                    "Invalid address specified");
  63.     }
  64.     
  65.     const vector<CNWAligner::ETranscriptSymbol>& transcript = 
  66.         *(m_aligner->GetTranscript());
  67.     if(transcript.size() == 0) {
  68.         NCBI_THROW(CAlgoAlignException,
  69.                    eNoData,
  70.                    "Zero size transcript (forgot to run the aligner?)");
  71.     }
  72.     seqalign->Reset();
  73.     // the alignment is pairwise
  74.     seqalign->SetDim(2);
  75.     // this is a global alignment
  76.     seqalign->SetType(CSeq_align::eType_global);
  77.     // seq-ids
  78.     CRef< CSeq_id > id1 ( new CSeq_id );
  79.     CRef< CObject_id > local_oid1 (new CObject_id);
  80.     local_oid1->SetStr(m_Seq1Id);
  81.     id1->SetLocal(*local_oid1);
  82.     CRef< CSeq_id > id2 ( new CSeq_id );
  83.     CRef< CObject_id > local_oid2 (new CObject_id);
  84.     local_oid2->SetStr(m_Seq2Id);
  85.     id2->SetLocal(*local_oid2);
  86.     
  87.     // the score was calculated during the main process
  88.     CRef< CScore > score (new CScore);
  89.     CRef< CObject_id > id (new CObject_id);
  90.     id->SetStr("score");
  91.     score->SetId(*id);
  92.     CRef< CScore::C_Value > val (new CScore::C_Value);
  93.     val->SetInt(m_aligner->GetScore());
  94.     score->SetValue(*val);
  95.     CSeq_align::TScore& scorelist = seqalign->SetScore();
  96.     scorelist.push_back(score);
  97.     // create segments and add them to this seq-align
  98.     CRef< CSeq_align::C_Segs > segs (new CSeq_align::C_Segs);
  99.     CDense_seg& ds = segs->SetDenseg();
  100.     ds.SetDim(2);
  101.     CDense_seg::TIds& ids = ds.SetIds();
  102.     ids.push_back( id1 );
  103.     ids.push_back( id2 );
  104.     CDense_seg::TStarts&  starts  = ds.SetStarts();
  105.     CDense_seg::TLens&    lens    = ds.SetLens();
  106.     CDense_seg::TStrands& strands = ds.SetStrands();
  107.     
  108.     // iterate through transcript
  109.     size_t seg_count = 0;
  110.     {{ 
  111.         const char * const S1 = m_aligner->GetSeq1();
  112.         const char * const S2 = m_aligner->GetSeq2();
  113.         const char *seq1 = S1, *seq2 = S2;
  114.         const char *start1 = seq1, *start2 = seq2;
  115.         vector<CNWAligner::ETranscriptSymbol>::const_reverse_iterator
  116.             ib = transcript.rbegin(),
  117.             ie = transcript.rend(),
  118.             ii;
  119.         
  120.         CNWAligner::ETranscriptSymbol ts = *ib;
  121.         bool intron = (ts == CNWAligner::eTS_Intron);
  122.         char seg_type0 = ((ts == CNWAligner::eTS_Insert || intron )? 1:
  123.                           (ts == CNWAligner::eTS_Delete)? 2: 0);
  124.         size_t seg_len = 0;
  125.         for (ii = ib;  ii != ie; ++ii) {
  126.             ts = *ii;
  127.             intron = (ts == CNWAligner::eTS_Intron);
  128.             char seg_type = ((ts == CNWAligner::eTS_Insert || intron )? 1:
  129.                              (ts == CNWAligner::eTS_Delete)? 2: 0);
  130.             if(seg_type0 != seg_type) {
  131.                 starts.push_back( (seg_type0 == 1)? -1: start1 - S1 );
  132.                 starts.push_back( (seg_type0 == 2)? -1: start2 - S2 );
  133.                 lens.push_back(seg_len);
  134.                 strands.push_back(eNa_strand_plus);
  135.                 strands.push_back(eNa_strand_plus);
  136.                 ++seg_count;
  137.                 start1 = seq1;
  138.                 start2 = seq2;
  139.                 seg_type0 = seg_type;
  140.                 seg_len = 1;
  141.             }
  142.             else {
  143.                 ++seg_len;
  144.             }
  145.             if(seg_type != 1) ++seq1;
  146.             if(seg_type != 2) ++seq2;
  147.         }
  148.         // the last one
  149.         starts.push_back( (seg_type0 == 1)? -1: start1 - S1 );
  150.         starts.push_back( (seg_type0 == 2)? -1: start2 - S2 );
  151.         lens.push_back(seg_len);
  152.         strands.push_back(eNa_strand_plus);
  153.         strands.push_back(eNa_strand_plus);
  154.         ++seg_count;
  155.     }}
  156.     ds.SetNumseg(seg_count);
  157.     ds.SetIds();
  158.     seqalign->SetSegs(*segs);
  159. }
  160. void CNWFormatter::AsText(string* output, ETextFormatType type,
  161.                           size_t line_width) const
  162. {
  163.     CNcbiOstrstream ss;
  164.     const vector<CNWAligner::ETranscriptSymbol>& transcript =
  165.         *(m_aligner->GetTranscript());
  166.     if(transcript.size() == 0) {
  167.         NCBI_THROW(CAlgoAlignException,
  168.                    eNoData,
  169.                    "Zero size transcript (forgot to run the aligner?)");
  170.     }
  171.     switch (type) {
  172.     case eFormatType1: {
  173.         if(m_Seq1Id.size() && m_Seq2Id.size()) {
  174.             ss << '>' << m_Seq1Id << 't' << m_Seq2Id << endl;
  175.         }
  176.         vector<char> v1, v2;
  177.         size_t aln_size = x_ApplyTranscript(&v1, &v2);
  178.         unsigned i1 = 0, i2 = 0;
  179.         for (size_t i = 0;  i < aln_size; ) {
  180.             ss << i << 't' << i1 << ':' << i2 << endl;
  181.             int i0 = i;
  182.             for (size_t jPos = 0;  i < aln_size  &&  jPos < line_width;
  183.                  ++i, ++jPos) {
  184.                 char c = v1[i0 + jPos];
  185.                 ss << c;
  186.                 if(c != '-'  &&  c != '+')
  187.                     i1++;
  188.             }
  189.             ss << endl;
  190.             
  191.             string marker_line(line_width, ' ');
  192.             i = i0;
  193.             for (size_t jPos = 0;  i < aln_size  &&  jPos < line_width;
  194.                  ++i, ++jPos) {
  195.                 char c1 = v1[i0 + jPos];
  196.                 char c  = v2[i0 + jPos];
  197.                 ss << c;
  198.                 if(c != '-' && c != '+')
  199.                     i2++;
  200.                 if(c != c1  &&  c != '-'  &&  c1 != '-'  &&  c1 != '+')
  201.                     marker_line[jPos] = '^';
  202.             }
  203.             ss << endl << marker_line << endl;
  204.         }
  205.     }
  206.     break;
  207.     case eFormatType2: {
  208.         if(m_Seq1Id.size() && m_Seq2Id.size()) {
  209.             ss << '>' << m_Seq1Id << 't' << m_Seq2Id << endl;
  210.         }
  211.         vector<char> v1, v2;
  212.         size_t aln_size = x_ApplyTranscript(&v1, &v2);
  213.         unsigned i1 = 0, i2 = 0;
  214.         for (size_t i = 0;  i < aln_size; ) {
  215.             ss << i << 't' << i1 << ':' << i2 << endl;
  216.             int i0 = i;
  217.             for (size_t jPos = 0;  i < aln_size  &&  jPos < line_width;
  218.                  ++i, ++jPos) {
  219.                 char c = v1[i0 + jPos];
  220.                 ss << c;
  221.                 if(c != '-'  &&  c != '+')
  222.                     i1++;
  223.             }
  224.             ss << endl;
  225.             
  226.             string line2 (line_width, ' ');
  227.             string line3 (line_width, ' ');
  228.             i = i0;
  229.             for (size_t jPos = 0;  i < aln_size  &&  jPos < line_width;
  230.                  ++i, ++jPos) {
  231.                 char c1 = v1[i0 + jPos];
  232.                 char c2  = v2[i0 + jPos];
  233.                 if(c2 != '-' && c2 != '+')
  234.                     i2++;
  235.                 if(c2 == c1)
  236.                     line2[jPos] = '|';
  237.                 line3[jPos] = c2;
  238.             }
  239.             ss << line2 << endl << line3 << endl << endl;
  240.         }
  241.     }
  242.     break;
  243.     case eFormatAsn: {
  244.         CSeq_align seq_align;
  245.         AsSeqAlign(&seq_align);
  246.         CObjectOStreamAsn asn_stream (ss);
  247.         asn_stream << seq_align;
  248.         asn_stream << Separator;
  249.     }
  250.     break;
  251.     case eFormatFastA: {
  252.         vector<char> v1, v2;
  253.         size_t aln_size = x_ApplyTranscript(&v1, &v2);
  254.         
  255.         ss << '>' << m_Seq1Id << endl;
  256.         const vector<char>* pv = &v1;
  257.         for(size_t i = 0; i < aln_size; ++i) {
  258.             for(size_t j = 0; j < line_width && i < aln_size; ++j, ++i) {
  259.                 ss << (*pv)[i];
  260.             }
  261.             ss << endl;
  262.         }
  263.         ss << '>' << m_Seq2Id << endl;
  264.         pv = &v2;
  265.         for(size_t i = 0; i < aln_size; ++i) {
  266.             for(size_t j = 0; j < line_width && i < aln_size; ++j, ++i) {
  267.                 ss << (*pv)[i];
  268.             }
  269.             ss << endl;
  270.         }
  271.     }
  272.     break;
  273.     
  274.     case eFormatExonTable:
  275.     case eFormatExonTableEx: {
  276.         ss.precision(3);
  277.         bool esfL1, esfR1, esfL2, esfR2;
  278.         m_aligner->GetEndSpaceFree(&esfL1, &esfR1, &esfL2, &esfR2);
  279.         const size_t len2 = m_aligner->GetSeqLen2();
  280.         const char* start1 = m_aligner->GetSeq1();
  281.         const char* start2 = m_aligner->GetSeq2();
  282.         const char* p1 = start1;
  283.         const char* p2 = start2;
  284.         int tr_idx_hi0 = transcript.size() - 1, tr_idx_hi = tr_idx_hi0;
  285.         int tr_idx_lo0 = 0, tr_idx_lo = tr_idx_lo0;
  286.         if(esfL1 && transcript[tr_idx_hi0] == CNWAligner::eTS_Insert) {
  287.             while(esfL1 && transcript[tr_idx_hi] == CNWAligner::eTS_Insert) {
  288.                 --tr_idx_hi;
  289.                 ++p2;
  290.             }
  291.         }
  292.         if(esfL2 && transcript[tr_idx_hi0] == CNWAligner::eTS_Delete) {
  293.             while(esfL2 && transcript[tr_idx_hi] == CNWAligner::eTS_Delete) {
  294.                 --tr_idx_hi;
  295.                 ++p1;
  296.             }
  297.         }
  298.         if(esfR1 && transcript[tr_idx_lo0] == CNWAligner::eTS_Insert) {
  299.             while(esfR1 && transcript[tr_idx_lo] == CNWAligner::eTS_Insert) {
  300.                 ++tr_idx_lo;
  301.             }
  302.         }
  303.         if(esfR2 && transcript[tr_idx_lo0] == CNWAligner::eTS_Delete) {
  304.             while(esfR2 && transcript[tr_idx_lo] == CNWAligner::eTS_Delete) {
  305.                 ++tr_idx_lo;
  306.             }
  307.         }
  308.         bool type_ex = type == eFormatExonTableEx;
  309.         vector<char> trans_ex (tr_idx_hi - tr_idx_lo + 1);
  310.         for(int tr_idx = tr_idx_hi; tr_idx >= tr_idx_lo;) {
  311.             const char* p1_beg = p1;
  312.             const char* p2_beg = p2;
  313.             size_t matches = 0, exon_aln_size = 0;
  314.             vector<char>::iterator ii_ex = trans_ex.begin();
  315.             while(tr_idx >= tr_idx_lo && 
  316.                   transcript[tr_idx] < CNWAligner::eTS_Intron) {
  317.                 
  318.                 bool noins = transcript[tr_idx] != CNWAligner::eTS_Insert;
  319.                 bool nodel = transcript[tr_idx] != CNWAligner::eTS_Delete;
  320.                 if(noins && nodel) {
  321.                     if(*p1++ == *p2++) {
  322.                         ++matches;
  323.                         if(type_ex) *ii_ex++ = 'M';
  324.                     }
  325.                     else {
  326.                         if(type_ex) *ii_ex++ = 'R';
  327.                     }
  328.                 } else if( noins ) {
  329.                     ++p1;
  330.                     if(type_ex) *ii_ex++ = 'D';
  331.                 } else {
  332.                     ++p2;
  333.                     if(type_ex) *ii_ex++ = 'I';
  334.                 }
  335.                 --tr_idx;
  336.                 ++exon_aln_size;
  337.             }
  338.             if(exon_aln_size > 0) {
  339.                 if(m_Seq1Id.size() && m_Seq2Id.size()) {
  340.                     ss << m_Seq1Id << 't' << m_Seq2Id << 't';
  341.                 }
  342. else {
  343.     ss << "-t-t";
  344. }
  345.                 float identity = float(matches) / exon_aln_size;
  346.                 ss << identity << 't' << exon_aln_size << 't';
  347.                 size_t beg1  = p1_beg - start1, end1 = p1 - start1 - 1;
  348.                 size_t beg2  = p2_beg - start2, end2 = p2 - start2 - 1;
  349. if(beg1 <= end1) {
  350.     ss << beg1 << 't' << end1 << 't';
  351. }
  352. else {
  353.     ss << "-t-t";
  354. }
  355. ss << beg2 << 't' << end2 << 't';
  356.                 char c1 = (p2_beg >= start2 + 2)? *(p2_beg - 2): ' ';
  357.                 char c2 = (p2_beg >= start2 + 1)? *(p2_beg - 1): ' ';
  358.                 char c3 = (p2 < start2 + len2)? *(p2): ' ';
  359.                 char c4 = (p2 < start2 + len2 - 1)? *(p2+1): ' ';
  360.                 ss << c1 << c2 << "<exon>" << c3 << c4;
  361.                 if(type == eFormatExonTableEx) {
  362.                     ss << 't';
  363.                     copy(trans_ex.begin(), ii_ex, ostream_iterator<char>(ss));
  364.                 }
  365.                 ss << endl;
  366.             }
  367.             // find next exon
  368.             while(tr_idx >= tr_idx_lo &&
  369.                   (transcript[tr_idx] == CNWAligner::eTS_Intron)) {
  370.                 --tr_idx;
  371.                 ++p2;
  372.             }
  373.         }
  374.     }
  375.     break;
  376.     default: {
  377.         NCBI_THROW(CAlgoAlignException, eBadParameter,
  378.                    "Incorrect format specified");
  379.     }
  380.     }
  381.     *output = CNcbiOstrstreamToString(ss);
  382. }
  383. // Transform source sequences according to the transcript.
  384. // Write the results to v1 and v2 leaving source sequences intact.
  385. // Return alignment size.
  386. size_t CNWFormatter::x_ApplyTranscript(vector<char>* pv1, vector<char>* pv2)
  387.     const
  388. {
  389.     const vector<CNWAligner::ETranscriptSymbol>& transcript = 
  390.         *(m_aligner->GetTranscript());
  391.     vector<char>& v1 = *pv1;
  392.     vector<char>& v2 = *pv2;
  393.     vector<CNWAligner::ETranscriptSymbol>::const_reverse_iterator
  394.         ib = transcript.rbegin(),
  395.         ie = transcript.rend(),
  396.         ii;
  397.     const char* iv1 = m_aligner->GetSeq1();
  398.     const char* iv2 = m_aligner->GetSeq2();
  399.     v1.clear();
  400.     v2.clear();
  401.     for (ii = ib;  ii != ie;  ii++) {
  402.         CNWAligner::ETranscriptSymbol ts = *ii;
  403.         char c1, c2;
  404.         switch ( ts ) {
  405.         case CNWAligner::eTS_Insert:
  406.             c1 = '-';
  407.             c2 = *iv2++;
  408.             break;
  409.         case CNWAligner::eTS_Delete:
  410.             c2 = '-';
  411.             c1 = *iv1++;
  412.             break;
  413.         case CNWAligner::eTS_Match:
  414.         case CNWAligner::eTS_Replace:
  415.             c1 = *iv1++;
  416.             c2 = *iv2++;
  417.             break;
  418.         case CNWAligner::eTS_Intron:
  419.             c1 = '+';
  420.             c2 = *iv2++;
  421.             break;
  422.         default:
  423.             c1 = c2 = '?';
  424.             break;
  425.         }
  426.         v1.push_back(c1);
  427.         v2.push_back(c2);
  428.     }
  429.     return v1.size();
  430. }
  431. END_NCBI_SCOPE
  432. /*
  433.  * ===========================================================================
  434.  * $Log: nw_formatter.cpp,v $
  435.  * Revision 1000.2  2004/06/01 18:04:54  gouriano
  436.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  437.  *
  438.  * Revision 1.10  2004/05/21 21:41:02  gorelenk
  439.  * Added PCH ncbi_pch.hpp
  440.  *
  441.  * Revision 1.9  2004/05/18 21:43:40  kapustin
  442.  * Code cleanup
  443.  *
  444.  * Revision 1.8  2004/05/17 14:50:56  kapustin
  445.  * Add/remove/rearrange some includes and object declarations
  446.  *
  447.  * Revision 1.7  2004/03/18 16:30:24  grichenk
  448.  * Changed type of seq-align containers from list to vector.
  449.  *
  450.  * Revision 1.6  2003/10/14 19:26:59  kapustin
  451.  * Format void exons properly
  452.  *
  453.  * Revision 1.5  2003/09/26 14:43:18  kapustin
  454.  * Remove exception specifications
  455.  *
  456.  * Revision 1.4  2003/09/15 21:32:03  kapustin
  457.  * Minor code cleanup
  458.  *
  459.  * Revision 1.3  2003/09/12 19:43:04  kapustin
  460.  * Add checking for empty transcript
  461.  *
  462.  * Revision 1.2  2003/09/03 01:19:32  ucko
  463.  * +<iterator> (needed for ostream_iterator<> with some compilers)
  464.  *
  465.  * Revision 1.1  2003/09/02 22:34:49  kapustin
  466.  * Initial revision
  467.  *
  468.  * ===========================================================================
  469.  */