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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seq_align_mapper.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:23:43  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seq_align_mapper.cpp,v 1000.1 2004/06/01 19:23:43 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: Aleksey Grichenko
  35. *
  36. * File Description:
  37. *   Alignment mapper
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <objmgr/impl/seq_align_mapper.hpp>
  42. #include <objmgr/seq_id_mapper.hpp>
  43. #include <objmgr/seq_loc_mapper.hpp>
  44. #include <objmgr/objmgr_exception.hpp>
  45. #include <objects/seqalign/seqalign__.hpp>
  46. #include <algorithm>
  47. BEGIN_NCBI_SCOPE
  48. BEGIN_SCOPE(objects)
  49. SAlignment_Segment::SAlignment_Segment(int len, size_t dim)
  50.     : m_Len(len),
  51.       m_Rows(dim),
  52.       m_HaveStrands(false)
  53. {
  54.     return;
  55. }
  56. SAlignment_Segment::SAlignment_Row&
  57. SAlignment_Segment::GetRow(size_t idx)
  58. {
  59.     _ASSERT(m_Rows.size() > idx);
  60.     return m_Rows[idx];
  61. }
  62. SAlignment_Segment::SAlignment_Row&
  63. SAlignment_Segment::CopyRow(size_t idx, const SAlignment_Row& src_row)
  64. {
  65.     SAlignment_Row& dst_row = GetRow(idx);
  66.     dst_row = src_row;
  67.     return dst_row;
  68. }
  69. SAlignment_Segment::SAlignment_Row& SAlignment_Segment::AddRow(size_t idx,
  70.                                                                const CSeq_id& id,
  71.                                                                int start,
  72.                                                                bool is_set_strand,
  73.                                                                ENa_strand strand,
  74.                                                                int width)
  75. {
  76.     SAlignment_Row& row = GetRow(idx);
  77.     row.m_Id = CSeq_id_Handle::GetHandle(id);
  78.     row.m_Start = start < 0 ? kInvalidSeqPos : start;
  79.     row.m_IsSetStrand = is_set_strand;
  80.     row.m_Strand = strand;
  81.     row.m_Width = width;
  82.     m_HaveStrands |= is_set_strand;
  83.     return row;
  84. }
  85. SAlignment_Segment::SAlignment_Row& SAlignment_Segment::AddRow(size_t idx,
  86.                                                                const CSeq_id_Handle& id,
  87.                                                                int start,
  88.                                                                bool is_set_strand,
  89.                                                                ENa_strand strand,
  90.                                                                int width)
  91. {
  92.     SAlignment_Row& row = GetRow(idx);
  93.     row.m_Id = id;
  94.     row.m_Start = start < 0 ? kInvalidSeqPos : start;
  95.     row.m_IsSetStrand = is_set_strand;
  96.     row.m_Strand = strand;
  97.     row.m_Width = width;
  98.     m_HaveStrands |= is_set_strand;
  99.     return row;
  100. }
  101. void SAlignment_Segment::SetScores(const TScores& scores)
  102. {
  103.     m_Scores = scores;
  104. }
  105. CSeq_align_Mapper::CSeq_align_Mapper(const CSeq_align& align)
  106.     : m_OrigAlign(&align),
  107.       m_DstAlign(0),
  108.       m_HaveStrands(false),
  109.       m_HaveWidths(false),
  110.       m_Dim(0),
  111.       m_AlignFlags(eAlign_Normal)
  112. {
  113.     switch ( align.GetSegs().Which() ) {
  114.     case CSeq_align::C_Segs::e_Dendiag:
  115.         x_Init(align.GetSegs().GetDendiag());
  116.         break;
  117.     case CSeq_align::C_Segs::e_Denseg:
  118.         x_Init(align.GetSegs().GetDenseg());
  119.         break;
  120.     case CSeq_align::C_Segs::e_Std:
  121.         x_Init(align.GetSegs().GetStd());
  122.         break;
  123.     case CSeq_align::C_Segs::e_Packed:
  124.         x_Init(align.GetSegs().GetPacked());
  125.         break;
  126.     case CSeq_align::C_Segs::e_Disc:
  127.         x_Init(align.GetSegs().GetDisc());
  128.         break;
  129.     default:
  130.         break;
  131.     }
  132. }
  133. SAlignment_Segment& CSeq_align_Mapper::x_PushSeg(int len, size_t dim)
  134. {
  135.     m_Segs.push_back(SAlignment_Segment(len, dim));
  136.     return m_Segs.back();
  137. }
  138. SAlignment_Segment& CSeq_align_Mapper::x_InsertSeg(TSegments::iterator& where,
  139.                                                    int len,
  140.                                                    size_t dim)
  141. {
  142.     return *m_Segs.insert(where, SAlignment_Segment(len, dim));
  143. }
  144. void CSeq_align_Mapper::x_Init(const TDendiag& diags)
  145. {
  146.     ITERATE(TDendiag, diag_it, diags) {
  147.         const CDense_diag& diag = **diag_it;
  148.         size_t dim = diag.GetDim();
  149.         if (dim != diag.GetIds().size()) {
  150.             ERR_POST(Warning << "Invalid 'ids' size in dendiag");
  151.             dim = min(dim, diag.GetIds().size());
  152.         }
  153.         if (dim != diag.GetStarts().size()) {
  154.             ERR_POST(Warning << "Invalid 'starts' size in dendiag");
  155.             dim = min(dim, diag.GetStarts().size());
  156.         }
  157.         m_HaveStrands = diag.IsSetStrands();
  158.         if (m_HaveStrands && dim != diag.GetStrands().size()) {
  159.             ERR_POST(Warning << "Invalid 'strands' size in dendiag");
  160.             dim = min(dim, diag.GetStrands().size());
  161.         }
  162.         if (dim != m_Dim) {
  163.             if ( m_Dim ) {
  164.                 m_AlignFlags = eAlign_MultiDim;
  165.             }
  166.             m_Dim = max(dim, m_Dim);
  167.         }
  168.         SAlignment_Segment& seg = x_PushSeg(diag.GetLen(), dim);
  169.         ENa_strand strand = eNa_strand_unknown;
  170.         if ( diag.IsSetScores() ) {
  171.             seg.SetScores(diag.GetScores());
  172.         }
  173.         for (size_t row = 0; row < dim; ++row) {
  174.             if ( m_HaveStrands ) {
  175.                 strand = diag.GetStrands()[row];
  176.             }
  177.             seg.AddRow(row,
  178.                 *diag.GetIds()[row],
  179.                 diag.GetStarts()[row],
  180.                 m_HaveStrands,
  181.                 strand,
  182.                 0);
  183.         }
  184.     }
  185. }
  186. void CSeq_align_Mapper::x_Init(const CDense_seg& denseg)
  187. {
  188.     m_Dim = denseg.GetDim();
  189.     size_t numseg = denseg.GetNumseg();
  190.     // claimed dimension may not be accurate :-/
  191.     if (numseg != denseg.GetLens().size()) {
  192.         ERR_POST(Warning << "Invalid 'lens' size in denseg");
  193.         numseg = min(numseg, denseg.GetLens().size());
  194.     }
  195.     if (m_Dim != denseg.GetIds().size()) {
  196.         ERR_POST(Warning << "Invalid 'ids' size in denseg");
  197.         m_Dim = min(m_Dim, denseg.GetIds().size());
  198.     }
  199.     if (m_Dim*numseg != denseg.GetStarts().size()) {
  200.         ERR_POST(Warning << "Invalid 'starts' size in denseg");
  201.         m_Dim = min(m_Dim*numseg, denseg.GetStarts().size()) / numseg;
  202.     }
  203.     m_HaveStrands = denseg.IsSetStrands();
  204.     if (m_HaveStrands && m_Dim*numseg != denseg.GetStrands().size()) {
  205.         ERR_POST(Warning << "Invalid 'strands' size in denseg");
  206.         m_Dim = min(m_Dim*numseg, denseg.GetStrands().size()) / numseg;
  207.     }
  208.     m_HaveWidths = denseg.IsSetWidths();
  209.     ENa_strand strand = eNa_strand_unknown;
  210.     for (size_t seg = 0;  seg < numseg;  seg++) {
  211.         SAlignment_Segment& alnseg = x_PushSeg(denseg.GetLens()[seg], m_Dim);
  212.         if ( seg == 0  &&  denseg.IsSetScores() ) {
  213.             // Set scores for the first segment only to avoid multiple copies
  214.             alnseg.SetScores(denseg.GetScores());
  215.         }
  216.         for (unsigned int row = 0;  row < m_Dim;  row++) {
  217.             if ( m_HaveStrands ) {
  218.                 strand = denseg.GetStrands()[seg*m_Dim + row];
  219.             }
  220.             alnseg.AddRow(row,
  221.                 *denseg.GetIds()[row],
  222.                 denseg.GetStarts()[seg*m_Dim + row],
  223.                 m_HaveStrands,
  224.                 strand,
  225.                 m_HaveWidths ? denseg.GetWidths()[row] : 0);
  226.         }
  227.     }
  228. }
  229. void CSeq_align_Mapper::x_Init(const TStd& sseg)
  230. {
  231.     typedef map<CSeq_id_Handle, int> TSegLenMap;
  232.     TSegLenMap seglens;
  233.     ITERATE ( CSeq_align::C_Segs::TStd, it, sseg ) {
  234.         const CStd_seg& stdseg = **it;
  235.         size_t dim = stdseg.GetDim();
  236.         if (stdseg.IsSetIds()
  237.             && dim != stdseg.GetIds().size()) {
  238.             ERR_POST(Warning << "Invalid 'ids' size in std-seg");
  239.             dim = min(dim, stdseg.GetIds().size());
  240.         }
  241.         SAlignment_Segment& seg = x_PushSeg(0, dim);
  242.         if ( stdseg.IsSetScores() ) {
  243.             seg.SetScores(stdseg.GetScores());
  244.         }
  245.         int seg_len = 0;
  246.         bool multi_width = false;
  247.         ITERATE ( CStd_seg::TLoc, it_loc, (*it)->GetLoc() ) {
  248.             const CSeq_loc& loc = **it_loc;
  249.             const CSeq_id* id = 0;
  250.             int start = -1;
  251.             int len = 0;
  252.             ENa_strand strand = eNa_strand_unknown;
  253.             bool have_strand = false;
  254.             unsigned int row_idx = 0;
  255.             for (CSeq_loc_CI rg(loc); rg; ++rg, ++row_idx) {
  256.                 if (row_idx > dim) {
  257.                     ERR_POST(Warning << "Invalid number of rows in std-seg");
  258.                     dim = row_idx;
  259.                     seg.m_Rows.resize(dim);
  260.                 }
  261.                 id = &rg.GetSeq_id();
  262.                 if ( rg.IsEmpty() ) {
  263.                     start = kInvalidSeqPos;
  264.                 }
  265.                 else {
  266.                     start = rg.GetRange().GetFrom();
  267.                     len = rg.GetRange().GetLength();
  268.                     strand = rg.GetStrand();
  269.                     if (strand != eNa_strand_unknown) {
  270.                         m_HaveStrands = have_strand = true;
  271.                     }
  272.                 }
  273.                 if (len > 0) {
  274.                     if (seg_len == 0) {
  275.                         seg_len = len;
  276.                     }
  277.                     else if (len != seg_len) {
  278.                         multi_width = true;
  279.                         if (len/3 == seg_len) {
  280.                             seg_len = len;
  281.                         }
  282.                         else if (len*3 != seg_len) {
  283.                             NCBI_THROW(CAnnotException, eBadLocation,
  284.                                     "Rows have different lengths in std-seg");
  285.                         }
  286.                     }
  287.                 }
  288.                 seglens[seg.AddRow(row_idx,
  289.                     *id,
  290.                     start,
  291.                     have_strand,
  292.                     strand,
  293.                     0).m_Id] = len;
  294.             }
  295.             if (dim != m_Dim) {
  296.                 if ( m_Dim ) {
  297.                     m_AlignFlags = eAlign_MultiDim;
  298.                 }
  299.                 m_Dim = max(dim, m_Dim);
  300.             }
  301.         }
  302.         seg.m_Len = seg_len;
  303.         if ( multi_width ) {
  304.             // Adjust each segment width. Do not check if sequence always
  305.             // has the same width.
  306.             for (size_t i = 0; i < seg.m_Rows.size(); ++i) {
  307.                 if (seglens[seg.m_Rows[i].m_Id] != seg_len) {
  308.                     seg.m_Rows[i].m_Width = 3;
  309.                 }
  310.             }
  311.         }
  312.         seglens.clear();
  313.         m_HaveWidths |= multi_width;
  314.     }
  315. }
  316. void CSeq_align_Mapper::x_Init(const CPacked_seg& pseg)
  317. {
  318.     m_Dim = pseg.GetDim();
  319.     size_t numseg = pseg.GetNumseg();
  320.     // claimed dimension may not be accurate :-/
  321.     if (numseg != pseg.GetLens().size()) {
  322.         ERR_POST(Warning << "Invalid 'lens' size in packed-seg");
  323.         numseg = min(numseg, pseg.GetLens().size());
  324.     }
  325.     if (m_Dim != pseg.GetIds().size()) {
  326.         ERR_POST(Warning << "Invalid 'ids' size in packed-seg");
  327.         m_Dim = min(m_Dim, pseg.GetIds().size());
  328.     }
  329.     if (m_Dim*numseg != pseg.GetStarts().size()) {
  330.         ERR_POST(Warning << "Invalid 'starts' size in packed-seg");
  331.         m_Dim = min(m_Dim*numseg, pseg.GetStarts().size()) / numseg;
  332.     }
  333.     m_HaveStrands = pseg.IsSetStrands();
  334.     if (m_HaveStrands && m_Dim*numseg != pseg.GetStrands().size()) {
  335.         ERR_POST(Warning << "Invalid 'strands' size in packed-seg");
  336.         m_Dim = min(m_Dim*numseg, pseg.GetStrands().size()) / numseg;
  337.     }
  338.     ENa_strand strand = eNa_strand_unknown;
  339.     for (size_t seg = 0;  seg < numseg;  seg++) {
  340.         SAlignment_Segment& alnseg = x_PushSeg(pseg.GetLens()[seg], m_Dim);
  341.         if ( seg == 0  &&  pseg.IsSetScores() ) {
  342.             // Set scores for the first segment only to avoid multiple copies
  343.             alnseg.SetScores(pseg.GetScores());
  344.         }
  345.         for (unsigned int row = 0;  row < m_Dim;  row++) {
  346.             if ( m_HaveStrands ) {
  347.                 strand = pseg.GetStrands()[seg*m_Dim + row];
  348.             }
  349.             alnseg.AddRow(row, 
  350.                 *pseg.GetIds()[row],
  351.                 (pseg.GetPresent()[seg*m_Dim + row] ?
  352.                 pseg.GetStarts()[seg*m_Dim + row] : kInvalidSeqPos),
  353.                 m_HaveStrands,
  354.                 strand,
  355.                 0);
  356.         }
  357.     }
  358. }
  359. void CSeq_align_Mapper::x_Init(const CSeq_align_set& align_set)
  360. {
  361.     const CSeq_align_set::Tdata& data = align_set.Get();
  362.     ITERATE(CSeq_align_set::Tdata, it, data) {
  363.         m_SubAligns.push_back(CSeq_align_Mapper(**it));
  364.     }
  365. }
  366. // Mapping through CSeq_loc_Conversion_Set
  367. struct CConversionRef_Less
  368. {
  369.     bool operator()(const CRef<CSeq_loc_Conversion>& x,
  370.                     const CRef<CSeq_loc_Conversion>& y) const;
  371. };
  372. bool CConversionRef_Less::operator()(const CRef<CSeq_loc_Conversion>& x,
  373.                                      const CRef<CSeq_loc_Conversion>& y) const
  374. {
  375.     if (x->m_Src_id_Handle != y->m_Src_id_Handle) {
  376.         return x->m_Src_id_Handle < y->m_Src_id_Handle;
  377.     }
  378.     // Leftmost first
  379.     if (x->m_Src_from != y->m_Src_from) {
  380.         return x->m_Src_from < y->m_Src_from;
  381.     }
  382.     // Longest first
  383.     return x->m_Src_to > y->m_Src_to;
  384. }
  385. void CSeq_align_Mapper::Convert(CSeq_loc_Conversion_Set& cvts,
  386.                                 unsigned int loc_index_shift)
  387. {
  388.     m_DstAlign.Reset();
  389.     if (m_SubAligns.size() > 0) {
  390.         NON_CONST_ITERATE(TSubAligns, it, m_SubAligns) {
  391.             it->Convert(cvts, loc_index_shift);
  392.             loc_index_shift += it->m_Dim;
  393.         }
  394.         return;
  395.     }
  396.     x_ConvertAlign(cvts, loc_index_shift);
  397. }
  398. void CSeq_align_Mapper::x_ConvertAlign(CSeq_loc_Conversion_Set& cvts,
  399.                                        unsigned int loc_index_shift)
  400. {
  401.     if (cvts.m_CvtByIndex.size() == 0) {
  402.         // Single mapping
  403.         _ASSERT(cvts.m_SingleConv);
  404.         x_ConvertRow(*cvts.m_SingleConv,
  405.             cvts.m_SingleIndex - loc_index_shift);
  406.         return;
  407.     }
  408.     CSeq_loc_Conversion_Set::TConvByIndex::iterator idx_it =
  409.         cvts.m_CvtByIndex.lower_bound(loc_index_shift);
  410.     for ( ; idx_it != cvts.m_CvtByIndex.end()
  411.         &&  idx_it->first < loc_index_shift + m_Dim; ++idx_it) {
  412.         x_ConvertRow(idx_it->second, idx_it->first - loc_index_shift);
  413.     }
  414. }
  415. void CSeq_align_Mapper::x_ConvertRow(CSeq_loc_Conversion& cvt,
  416.                                      size_t row)
  417. {
  418.     CSeq_id_Handle dst_id;
  419.     TSegments::iterator seg_it = m_Segs.begin();
  420.     for ( ; seg_it != m_Segs.end(); ) {
  421.         if (seg_it->m_Rows.size() <= row) {
  422.             // No such row in the current segment
  423.             ++seg_it;
  424.             m_AlignFlags = eAlign_MultiDim;
  425.             continue;
  426.         }
  427.         CSeq_id_Handle seg_id = x_ConvertSegment(seg_it, cvt, row);
  428.         if (dst_id) {
  429.             if (dst_id != seg_id  &&  m_AlignFlags == eAlign_Normal) {
  430.                 m_AlignFlags = eAlign_MultiId;
  431.             }
  432.             dst_id = seg_id;
  433.         }
  434.     }
  435. }
  436. void CSeq_align_Mapper::x_ConvertRow(TIdMap& cvts,
  437.                                      size_t row)
  438. {
  439.     CSeq_id_Handle dst_id;
  440.     TSegments::iterator seg_it = m_Segs.begin();
  441.     for ( ; seg_it != m_Segs.end(); ) {
  442.         if (seg_it->m_Rows.size() <= row) {
  443.             // No such row in the current segment
  444.             ++seg_it;
  445.             m_AlignFlags = eAlign_MultiDim;
  446.             continue;
  447.         }
  448.         CSeq_id_Handle seg_id = x_ConvertSegment(seg_it, cvts, row);
  449.         if (dst_id) {
  450.             if (dst_id != seg_id  &&  m_AlignFlags == eAlign_Normal) {
  451.                 m_AlignFlags = eAlign_MultiId;
  452.             }
  453.             dst_id = seg_id;
  454.         }
  455.     }
  456. }
  457. CSeq_id_Handle
  458. CSeq_align_Mapper::x_ConvertSegment(TSegments::iterator& seg_it,
  459.                                     CSeq_loc_Conversion& cvt,
  460.                                     size_t row)
  461. {
  462.     TSegments::iterator old_it = seg_it;
  463.     ++seg_it;
  464.     SAlignment_Segment::SAlignment_Row& aln_row = old_it->m_Rows[row];
  465.     if (aln_row.m_Id != cvt.m_Src_id_Handle) {
  466.         return aln_row.m_Id;
  467.     }
  468.     if (aln_row.m_Start == kInvalidSeqPos) {
  469.         // ??? Skipped row - change ID
  470.         aln_row.m_Id = cvt.m_Dst_id_Handle;
  471.         aln_row.SetMapped();
  472.         return aln_row.m_Id;
  473.     }
  474.     TRange rg(aln_row.m_Start, aln_row.m_Start + old_it->m_Len - 1);
  475.     if (!cvt.ConvertInterval(rg.GetFrom(), rg.GetTo(), aln_row.m_Strand) ) {
  476.         // Do not erase the segment, just change the row ID and reset start
  477.         aln_row.m_Start = kInvalidSeqPos;
  478.         aln_row.m_Id = cvt.m_Dst_id_Handle;
  479.         aln_row.SetMapped();
  480.         return aln_row.m_Id;
  481.     }
  482.     // At least part of the interval was converted.
  483.     TSeqPos dl = cvt.m_Src_from <= rg.GetFrom() ?
  484.         0 : cvt.m_Src_from - rg.GetFrom();
  485.     TSeqPos dr = cvt.m_Src_to >= rg.GetTo() ?
  486.         0 : rg.GetTo() - cvt.m_Src_to;
  487.     if (dl > 0) {
  488.         // Add segment for the skipped range
  489.         SAlignment_Segment& lseg = x_InsertSeg(seg_it, dl,
  490.             old_it->m_Rows.size());
  491.         for (size_t r = 0; r < old_it->m_Rows.size(); ++r) {
  492.             SAlignment_Segment::SAlignment_Row& lrow =
  493.                 lseg.CopyRow(r, old_it->m_Rows[r]);
  494.             if (r == row) {
  495.                 lrow.m_Start = kInvalidSeqPos;
  496.                 lrow.m_Id = cvt.m_Dst_id_Handle;
  497.             }
  498.             else if (lrow.m_Start != kInvalidSeqPos &&
  499.                 !lrow.SameStrand(aln_row)) {
  500.                 // Adjust start for minus strand
  501.                 lrow.m_Start += old_it->m_Len - lseg.m_Len;
  502.             }
  503.         }
  504.     }
  505.     rg.SetFrom(rg.GetFrom() + dl);
  506.     SAlignment_Segment& mseg = x_InsertSeg(seg_it,
  507.         rg.GetLength() - dr,
  508.         old_it->m_Rows.size());
  509.     if (!dl  &&  !dr) {
  510.         // copy scores if there's no truncation
  511.         mseg.SetScores(old_it->m_Scores);
  512.     }
  513.     for (size_t r = 0; r < old_it->m_Rows.size(); ++r) {
  514.         SAlignment_Segment::SAlignment_Row& mrow =
  515.             mseg.CopyRow(r, old_it->m_Rows[r]);
  516.         if (r == row) {
  517.             // translate id and coords
  518.             mrow.m_Id = cvt.m_Dst_id_Handle;
  519.             mrow.m_Start = cvt.m_LastRange.GetFrom();
  520.             mrow.m_IsSetStrand |= (cvt.m_LastStrand != eNa_strand_unknown);
  521.             mrow.m_Strand = cvt.m_LastStrand;
  522.             mrow.SetMapped();
  523.             mseg.m_HaveStrands |= mrow.m_IsSetStrand;
  524.         }
  525.         else {
  526.             if (mrow.m_Start != kInvalidSeqPos) {
  527.                 if (mrow.SameStrand(aln_row)) {
  528.                     mrow.m_Start += dl;
  529.                 }
  530.                 else {
  531.                     mrow.m_Start += old_it->m_Len - dl - mseg.m_Len;
  532.                 }
  533.             }
  534.         }
  535.     }
  536.     cvt.m_LastType = cvt.eMappedObjType_not_set;
  537.     dl += rg.GetLength() - dr;
  538.     rg.SetFrom(rg.GetTo() - dr);
  539.     if (dr > 0) {
  540.         // Add the remaining unmapped range
  541.         SAlignment_Segment& rseg = x_InsertSeg(seg_it,
  542.             dr,
  543.             old_it->m_Rows.size());
  544.         for (size_t r = 0; r < old_it->m_Rows.size(); ++r) {
  545.             SAlignment_Segment::SAlignment_Row& rrow =
  546.                 rseg.CopyRow(r, old_it->m_Rows[r]);
  547.             if (r == row) {
  548.                 rrow.m_Start = kInvalidSeqPos;
  549.                 rrow.m_Id = cvt.m_Dst_id_Handle;
  550.             }
  551.             else {
  552.                 if (rrow.SameStrand(aln_row)) {
  553.                     rrow.m_Start += dl;
  554.                 }
  555.             }
  556.         }
  557.     }
  558.     m_Segs.erase(old_it);
  559.     return cvt.m_Dst_id_Handle;
  560. }
  561. CSeq_id_Handle
  562. CSeq_align_Mapper::x_ConvertSegment(TSegments::iterator& seg_it,
  563.                                     TIdMap& id_map,
  564.                                     size_t row)
  565. {
  566.     TSegments::iterator old_it = seg_it;
  567.     SAlignment_Segment& seg = *old_it;
  568.     ++seg_it;
  569.     SAlignment_Segment::SAlignment_Row& aln_row = seg.m_Rows[row];
  570.     if (aln_row.m_Start == kInvalidSeqPos) {
  571.         // skipped row
  572.         return aln_row.m_Id;
  573.     }
  574.     TRange rg(aln_row.m_Start, aln_row.m_Start + seg.m_Len - 1);
  575.     TIdMap::iterator id_it = id_map.find(aln_row.m_Id);
  576.     if (id_it == id_map.end()) {
  577.         // ID not found in the segment, leave the row unchanged
  578.         return aln_row.m_Id;
  579.     }
  580.     TRangeMap& rmap = id_it->second;
  581.     if ( rmap.empty() ) {
  582.         // No mappings for this segment
  583.         return aln_row.m_Id;
  584.     }
  585.     // Sorted mappings
  586.     typedef vector< CRef<CSeq_loc_Conversion> > TSortedConversions;
  587.     TSortedConversions cvts;
  588.     for (TRangeMap::iterator rg_it = rmap.begin(rg); rg_it; ++rg_it) {
  589.         cvts.push_back(rg_it->second);
  590.     }
  591.     sort(cvts.begin(), cvts.end(), CConversionRef_Less());
  592.     bool mapped = false;
  593.     CSeq_id_Handle dst_id;
  594.     EAlignFlags align_flags = eAlign_Normal;
  595.     TSeqPos left_shift = 0;
  596.     for (size_t cvt_idx = 0; cvt_idx < cvts.size(); ++cvt_idx) {
  597.         CSeq_loc_Conversion& cvt = *cvts[cvt_idx];
  598.         if (!cvt.ConvertInterval(rg.GetFrom(), rg.GetTo(), aln_row.m_Strand) ) {
  599.             continue;
  600.         }
  601.         // Check destination id
  602.         if ( dst_id ) {
  603.             if (cvt.m_Dst_id_Handle != dst_id) {
  604.                 align_flags = eAlign_MultiId;
  605.             }
  606.         }
  607.         dst_id = cvt.m_Dst_id_Handle;
  608.         // At least part of the interval was converted.
  609.         TSeqPos dl = cvt.m_Src_from <= rg.GetFrom() ?
  610.             0 : cvt.m_Src_from - rg.GetFrom();
  611.         TSeqPos dr = cvt.m_Src_to >= rg.GetTo() ?
  612.             0 : rg.GetTo() - cvt.m_Src_to;
  613.         if (dl > 0) {
  614.             // Add segment for the skipped range
  615.             SAlignment_Segment& lseg = x_InsertSeg(seg_it,
  616.                 dl, seg.m_Rows.size());
  617.             for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  618.                 SAlignment_Segment::SAlignment_Row& lrow =
  619.                     lseg.CopyRow(r, seg.m_Rows[r]);
  620.                 if (r == row) {
  621.                     lrow.m_Start = kInvalidSeqPos;
  622.                     lrow.m_Id = dst_id;
  623.                 }
  624.                 else if (lrow.m_Start != kInvalidSeqPos) {
  625.                     if (lrow.SameStrand(aln_row)) {
  626.                         lrow.m_Start += left_shift;
  627.                     }
  628.                     else {
  629.                         lrow.m_Start += seg.m_Len - lseg.m_Len - left_shift;
  630.                     }
  631.                 }
  632.             }
  633.         }
  634.         left_shift += dl;
  635.         SAlignment_Segment& mseg = x_InsertSeg(seg_it,
  636.             rg.GetLength() - dl - dr, seg.m_Rows.size());
  637.         if (!dl  &&  !dr) {
  638.             // copy scores if there's no truncation
  639.             mseg.SetScores(seg.m_Scores);
  640.         }
  641.         for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  642.             SAlignment_Segment::SAlignment_Row& mrow =
  643.                 mseg.CopyRow(r, seg.m_Rows[r]);
  644.             if (r == row) {
  645.                 // translate id and coords
  646.                 mrow.m_Id = cvt.m_Dst_id_Handle;
  647.                 mrow.m_Start = cvt.m_LastRange.GetFrom();
  648.                 mrow.m_IsSetStrand |= (cvt.m_LastStrand != eNa_strand_unknown);
  649.                 mrow.m_Strand = cvt.m_LastStrand;
  650.                 mrow.SetMapped();
  651.                 mseg.m_HaveStrands |= mrow.m_IsSetStrand;
  652.             }
  653.             else {
  654.                 if (mrow.m_Start != kInvalidSeqPos) {
  655.                     if (mrow.SameStrand(aln_row)) {
  656.                         mrow.m_Start += left_shift;
  657.                     }
  658.                     else {
  659.                         mrow.m_Start += seg.m_Len - left_shift - mseg.m_Len;
  660.                     }
  661.                 }
  662.             }
  663.         }
  664.         cvt.m_LastType = cvt.eMappedObjType_not_set;
  665.         mapped = true;
  666.         left_shift += mseg.m_Len;
  667.         rg.SetFrom(aln_row.m_Start + left_shift);
  668.     }
  669.     if (align_flags == eAlign_MultiId  &&  m_AlignFlags == eAlign_Normal) {
  670.         m_AlignFlags = align_flags;
  671.     }
  672.     if ( !mapped ) {
  673.         // Do not erase the segment, just change the row ID and reset start
  674.         seg.m_Rows[row].m_Start = kInvalidSeqPos;
  675.         seg.m_Rows[row].m_Id = rmap.begin()->second->m_Dst_id_Handle;
  676.         seg.m_Rows[row].SetMapped();
  677.         return seg.m_Rows[row].m_Id;
  678.     }
  679.     if (rg.GetFrom() <= rg.GetTo()) {
  680.         // Add the remaining unmapped range
  681.         SAlignment_Segment& rseg = x_InsertSeg(seg_it,
  682.             rg.GetLength(), seg.m_Rows.size());
  683.         for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  684.             SAlignment_Segment::SAlignment_Row& rrow =
  685.                 rseg.CopyRow(r, seg.m_Rows[r]);
  686.             if (r == row) {
  687.                 rrow.m_Start = kInvalidSeqPos;
  688.                 rrow.m_Id = dst_id;
  689.             }
  690.             else if (rrow.m_Start != kInvalidSeqPos) {
  691.                 if (rrow.SameStrand(aln_row)) {
  692.                     rrow.m_Start += left_shift;
  693.                 }
  694.             }
  695.         }
  696.     }
  697.     m_Segs.erase(old_it);
  698.     return align_flags == eAlign_MultiId ? CSeq_id_Handle() : dst_id;
  699. }
  700. // Mapping through CSeq_loc_Mapper
  701. void CSeq_align_Mapper::Convert(CSeq_loc_Mapper& mapper)
  702. {
  703.     m_DstAlign.Reset();
  704.     if (m_SubAligns.size() > 0) {
  705.         NON_CONST_ITERATE(TSubAligns, it, m_SubAligns) {
  706.             it->Convert(mapper);
  707.         }
  708.         return;
  709.     }
  710.     x_ConvertAlign(mapper);
  711. }
  712. void CSeq_align_Mapper::x_ConvertAlign(CSeq_loc_Mapper& mapper)
  713. {
  714.     if (m_Segs.size() == 0) {
  715.         return;
  716.     }
  717.     for (size_t row_idx = 0; row_idx < m_Dim; ++row_idx) {
  718.         x_ConvertRow(mapper, row_idx);
  719.     }
  720. }
  721. void CSeq_align_Mapper::x_ConvertRow(CSeq_loc_Mapper& mapper,
  722.                                      size_t row)
  723. {
  724.     CSeq_id_Handle dst_id;
  725.     TSegments::iterator seg_it = m_Segs.begin();
  726.     for ( ; seg_it != m_Segs.end(); ) {
  727.         if (seg_it->m_Rows.size() <= row) {
  728.             // No such row in the current segment
  729.             ++seg_it;
  730.             m_AlignFlags = eAlign_MultiDim;
  731.             continue;
  732.         }
  733.         CSeq_id_Handle seg_id = x_ConvertSegment(seg_it, mapper, row);
  734.         if (dst_id) {
  735.             if (dst_id != seg_id  &&  m_AlignFlags == eAlign_Normal) {
  736.                 m_AlignFlags = eAlign_MultiId;
  737.             }
  738.             dst_id = seg_id;
  739.         }
  740.     }
  741. }
  742. CSeq_id_Handle
  743. CSeq_align_Mapper::x_ConvertSegment(TSegments::iterator& seg_it,
  744.                                     CSeq_loc_Mapper& mapper,
  745.                                     size_t row)
  746. {
  747.     TSegments::iterator old_it = seg_it;
  748.     SAlignment_Segment& seg = *old_it;
  749.     ++seg_it;
  750.     SAlignment_Segment::SAlignment_Row& aln_row = seg.m_Rows[row];
  751.     if (aln_row.m_Start == kInvalidSeqPos) {
  752.         // skipped row
  753.         return aln_row.m_Id;
  754.     }
  755.     CSeq_loc_Mapper::TIdMap::iterator id_it =
  756.         mapper.m_IdMap.find(aln_row.m_Id);
  757.     if (id_it == mapper.m_IdMap.end()) {
  758.         // ID not found in the segment, leave the row unchanged
  759.         return aln_row.m_Id;
  760.     }
  761.     CSeq_loc_Mapper::TRangeMap& rmap = id_it->second;
  762.     if ( rmap.empty() ) {
  763.         // No mappings for this segment
  764.         return aln_row.m_Id;
  765.     }
  766.     // Sorted mappings
  767.     typedef vector< CRef<CMappingRange> > TSortedMappings;
  768.     TSortedMappings mappings;
  769.     CSeq_loc_Mapper::TRangeMap::iterator rg_it = rmap.begin();
  770.     for ( ; rg_it; ++rg_it) {
  771.         mappings.push_back(rg_it->second);
  772.     }
  773.     sort(mappings.begin(), mappings.end(), CMappingRangeRef_Less());
  774.     bool mapped = false;
  775.     CSeq_id_Handle dst_id;
  776.     EAlignFlags align_flags = eAlign_Normal;
  777.     int width_flag = mapper.m_UseWidth ?
  778.         mapper.m_Widths[aln_row.m_Id] : 0;
  779.     int dst_width = width_flag ? 3 : 1;
  780.     TSeqPos start = aln_row.m_Start;
  781.     if (width_flag & CSeq_loc_Mapper::fWidthProtToNuc) {
  782.         dst_width = 1;
  783.         if (aln_row.m_Width == 3) {
  784.             start *= 3;
  785.         }
  786.     }
  787.     else if (!width_flag  &&  aln_row.m_Width == 3) {
  788.         dst_width = 3;
  789.         start *= 3;
  790.     }
  791.     TSeqPos stop = start + seg.m_Len - 1;
  792.     TSeqPos left_shift = 0;
  793.     for (size_t map_idx = 0; map_idx < mappings.size(); ++map_idx) {
  794.         CRef<CMappingRange> mapping(mappings[map_idx]);
  795.         // Adjust mapping coordinates according to width
  796.         if (width_flag & CSeq_loc_Mapper::fWidthProtToNuc) {
  797.             if (width_flag & CSeq_loc_Mapper::fWidthNucToProt) {
  798.                 // Copy mapping
  799.                 mapping.Reset(new CMappingRange(*mappings[map_idx]));
  800.                 mapping->m_Src_from *= 3;
  801.                 mapping->m_Src_to = (mapping->m_Src_to + 1)*3 - 1;
  802.                 mapping->m_Dst_from *= 3;
  803.             }
  804.         }
  805.         else if (!width_flag  &&  aln_row.m_Width == 3) {
  806.             // Copy mapping
  807.             mapping.Reset(new CMappingRange(*mappings[map_idx]));
  808.             mapping->m_Src_from *= 3;
  809.             mapping->m_Src_to = (mapping->m_Src_to + 1)*3 - 1;
  810.             mapping->m_Dst_from *= 3;
  811.         }
  812.         if (!mapping->CanMap(start, stop,
  813.             aln_row.m_IsSetStrand, aln_row.m_Strand)) {
  814.             // Mapping does not apply to this segment/row
  815.             continue;
  816.         }
  817.         // Check destination id
  818.         if ( dst_id ) {
  819.             if (mapping->m_Dst_id_Handle != dst_id) {
  820.                 align_flags = eAlign_MultiId;
  821.             }
  822.         }
  823.         dst_id = mapping->m_Dst_id_Handle;
  824.         // At least part of the interval was converted. Calculate
  825.         // trimming coords, trim each row.
  826.         TSeqPos dl = mapping->m_Src_from <= start ?
  827.             0 : mapping->m_Src_from - start;
  828.         TSeqPos dr = mapping->m_Src_to >= stop ?
  829.             0 : stop - mapping->m_Src_to;
  830.         if (dl > 0) {
  831.             // Add segment for the skipped range
  832.             SAlignment_Segment& lseg = x_InsertSeg(seg_it,
  833.                 dl, seg.m_Rows.size());
  834.             for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  835.                 SAlignment_Segment::SAlignment_Row& lrow =
  836.                     lseg.CopyRow(r, seg.m_Rows[r]);
  837.                 if (r == row) {
  838.                     lrow.m_Start = kInvalidSeqPos;
  839.                     lrow.m_Id = dst_id;
  840.                 }
  841.                 else if (lrow.m_Start != kInvalidSeqPos) {
  842.                     int width = seg.m_Rows[r].m_Width ?
  843.                         seg.m_Rows[r].m_Width : 1;
  844.                     if (lrow.SameStrand(aln_row)) {
  845.                         lrow.m_Start += left_shift/width;
  846.                     }
  847.                     else {
  848.                         lrow.m_Start +=
  849.                             (seg.m_Len - lseg.m_Len - left_shift)/width;
  850.                     }
  851.                 }
  852.             }
  853.         }
  854.         start += dl;
  855.         left_shift += dl;
  856.         // At least part of the interval was converted.
  857.         SAlignment_Segment& mseg = x_InsertSeg(seg_it,
  858.             stop - dr - start + 1, seg.m_Rows.size());
  859.         if (!dl  &&  !dr) {
  860.             // copy scores if there's no truncation
  861.             mseg.SetScores(seg.m_Scores);
  862.         }
  863.         for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  864.             SAlignment_Segment::SAlignment_Row& mrow =
  865.                 mseg.CopyRow(r, seg.m_Rows[r]);
  866.             if (r == row) {
  867.                 // translate id and coords
  868.                 CMappingRange::TRange mapped_rg =
  869.                     mapping->Map_Range(start, stop - dr);
  870.                 ENa_strand dst_strand = eNa_strand_unknown;
  871.                 mapping->Map_Strand(
  872.                     aln_row.m_IsSetStrand,
  873.                     aln_row.m_Strand,
  874.                     &dst_strand);
  875.                 mrow.m_Id = mapping->m_Dst_id_Handle;
  876.                 mrow.m_Start = mapped_rg.GetFrom()/dst_width;
  877.                 mrow.m_IsSetStrand |= (dst_strand != eNa_strand_unknown);
  878.                 mrow.m_Strand = dst_strand;
  879.                 mrow.SetMapped();
  880.                 mseg.m_HaveStrands |= mrow.m_IsSetStrand;
  881.             }
  882.             else {
  883.                 if (mrow.m_Start != kInvalidSeqPos) {
  884.                     int width = seg.m_Rows[r].m_Width ?
  885.                         seg.m_Rows[r].m_Width : 1;
  886.                     if (mrow.SameStrand(aln_row)) {
  887.                         mrow.m_Start += left_shift/width;
  888.                     }
  889.                     else {
  890.                         mrow.m_Start +=
  891.                             (seg.m_Len - left_shift - mseg.m_Len)/width;
  892.                     }
  893.                 }
  894.             }
  895.         }
  896.         left_shift += mseg.m_Len;
  897.         start += mseg.m_Len;
  898.         mapped = true;
  899.     }
  900.     if (align_flags == eAlign_MultiId  &&  m_AlignFlags == eAlign_Normal) {
  901.         m_AlignFlags = align_flags;
  902.     }
  903.     if ( !mapped ) {
  904.         // Do not erase the segment, just change the row ID and reset start
  905.         seg.m_Rows[row].m_Start = kInvalidSeqPos;
  906.         seg.m_Rows[row].m_Id = rmap.begin()->second->m_Dst_id_Handle;
  907.         seg.m_Rows[row].SetMapped();
  908.         return seg.m_Rows[row].m_Id;
  909.     }
  910.     if (start <= stop) {
  911.         // Add the remaining unmapped range
  912.         SAlignment_Segment& rseg = x_InsertSeg(seg_it,
  913.             stop - start + 1, seg.m_Rows.size());
  914.         for (size_t r = 0; r < seg.m_Rows.size(); ++r) {
  915.             SAlignment_Segment::SAlignment_Row& rrow =
  916.                 rseg.CopyRow(r, seg.m_Rows[r]);
  917.             if (r == row) {
  918.                 rrow.m_Start = kInvalidSeqPos;
  919.                 rrow.m_Id = dst_id;
  920.             }
  921.             else if (rrow.m_Start != kInvalidSeqPos) {
  922.                 int width = seg.m_Rows[r].m_Width ?
  923.                     seg.m_Rows[r].m_Width : 1;
  924.                 if (rrow.SameStrand(aln_row)) {
  925.                     rrow.m_Start += left_shift/width;
  926.                 }
  927.             }
  928.         }
  929.     }
  930.     m_Segs.erase(old_it);
  931.     return align_flags == eAlign_MultiId ? CSeq_id_Handle() : dst_id;
  932. }
  933. // Get mapped alignment
  934. void CSeq_align_Mapper::x_GetDstDendiag(CRef<CSeq_align>& dst) const
  935. {
  936.     TDendiag& diags = dst->SetSegs().SetDendiag();
  937.     ITERATE(TSegments, seg_it, m_Segs) {
  938.         const SAlignment_Segment& seg = *seg_it;
  939.         CRef<CDense_diag> diag(new CDense_diag);
  940.         diag->SetDim(seg.m_Rows.size());
  941.         diag->SetLen(seg.m_Len);
  942.         ITERATE(SAlignment_Segment::TRows, row, seg.m_Rows) {
  943.             CRef<CSeq_id> id(new CSeq_id);
  944.             id.Reset(&const_cast<CSeq_id&>(*row->m_Id.GetSeqId()));
  945.             diag->SetIds().push_back(id);
  946.             diag->SetStarts().push_back(row->GetSegStart());
  947.             if (seg.m_HaveStrands) { // per-segment strands
  948.                 diag->SetStrands().push_back(row->m_Strand);
  949.             }
  950.         }
  951.         if ( seg.m_Scores.size() ) {
  952.             diag->SetScores() = seg.m_Scores;
  953.         }
  954.         diags.push_back(diag);
  955.     }
  956. }
  957. void CSeq_align_Mapper::x_GetDstDenseg(CRef<CSeq_align>& dst) const
  958. {
  959.     CDense_seg& dseg = dst->SetSegs().SetDenseg();
  960.     dseg.SetDim(m_Segs.front().m_Rows.size());
  961.     dseg.SetNumseg(m_Segs.size());
  962.     if ( m_Segs.front().m_Scores.size() ) {
  963.         dseg.SetScores() = m_Segs.front().m_Scores;
  964.     }
  965.     ITERATE(SAlignment_Segment::TRows, row, m_Segs.front().m_Rows) {
  966.         CRef<CSeq_id> id(new CSeq_id);
  967.         id.Reset(&const_cast<CSeq_id&>(*row->m_Id.GetSeqId()));
  968.         dseg.SetIds().push_back(id);
  969.         if (m_HaveWidths) {
  970.             dseg.SetWidths().push_back(row->m_Width);
  971.         }
  972.     }
  973.     ITERATE(TSegments, seg_it, m_Segs) {
  974.         dseg.SetLens().push_back(seg_it->m_Len);
  975.         ITERATE(SAlignment_Segment::TRows, row, seg_it->m_Rows) {
  976.             dseg.SetStarts().push_back(row->GetSegStart());
  977.             if (m_HaveStrands) { // per-alignment strands
  978.                 dseg.SetStrands().push_back(row->m_Strand);
  979.             }
  980.         }
  981.     }
  982. }
  983. void CSeq_align_Mapper::x_GetDstStd(CRef<CSeq_align>& dst) const
  984. {
  985.     TStd& std_segs = dst->SetSegs().SetStd();
  986.     ITERATE(TSegments, seg_it, m_Segs) {
  987.         CRef<CStd_seg> std_seg(new CStd_seg);
  988.         std_seg->SetDim(seg_it->m_Rows.size());
  989.         if ( seg_it->m_Scores.size() ) {
  990.             std_seg->SetScores() = seg_it->m_Scores;
  991.         }
  992.         ITERATE(SAlignment_Segment::TRows, row, seg_it->m_Rows) {
  993.             CRef<CSeq_id> id(new CSeq_id);
  994.             id.Reset(&const_cast<CSeq_id&>(*row->m_Id.GetSeqId()));
  995.             std_seg->SetIds().push_back(id);
  996.             CRef<CSeq_loc> loc(new CSeq_loc);
  997.             if (row->m_Start == kInvalidSeqPos) {
  998.                 // empty
  999.                 loc->SetEmpty(*id);
  1000.             }
  1001.             else {
  1002.                 // interval
  1003.                 loc->SetInt().SetId(*id);
  1004.                 TSeqPos len = seg_it->m_Len;
  1005.                 if (row->m_Width) {
  1006.                     len /= row->m_Width;
  1007.                 }
  1008.                 loc->SetInt().SetFrom(row->m_Start);
  1009.                 // len may be 0 after dividing by width
  1010.                 loc->SetInt().SetTo(row->m_Start + (len ? len - 1 : 0));
  1011.                 if (row->m_IsSetStrand) {
  1012.                     loc->SetInt().SetStrand(row->m_Strand);
  1013.                 }
  1014.             }
  1015.             std_seg->SetLoc().push_back(loc);
  1016.         }
  1017.         std_segs.push_back(std_seg);
  1018.     }
  1019. }
  1020. void CSeq_align_Mapper::x_GetDstPacked(CRef<CSeq_align>& dst) const
  1021. {
  1022.     CPacked_seg& pseg = dst->SetSegs().SetPacked();
  1023.     pseg.SetDim(m_Segs.front().m_Rows.size());
  1024.     pseg.SetNumseg(m_Segs.size());
  1025.     if ( m_Segs.front().m_Scores.size() ) {
  1026.         pseg.SetScores() = m_Segs.front().m_Scores;
  1027.     }
  1028.     ITERATE(SAlignment_Segment::TRows, row, m_Segs.front().m_Rows) {
  1029.         CRef<CSeq_id> id(new CSeq_id);
  1030.         id.Reset(&const_cast<CSeq_id&>(*row->m_Id.GetSeqId()));
  1031.         pseg.SetIds().push_back(id);
  1032.     }
  1033.     ITERATE(TSegments, seg_it, m_Segs) {
  1034.         pseg.SetLens().push_back(seg_it->m_Len);
  1035.         ITERATE(SAlignment_Segment::TRows, row, seg_it->m_Rows) {
  1036.             pseg.SetStarts().push_back(row->GetSegStart());
  1037.             pseg.SetPresent().push_back(row->m_Start != kInvalidSeqPos);
  1038.             if (m_HaveStrands) {
  1039.                 pseg.SetStrands().push_back(row->m_Strand);
  1040.             }
  1041.         }
  1042.     }
  1043. }
  1044. void CSeq_align_Mapper::x_GetDstDisc(CRef<CSeq_align>& dst) const
  1045. {
  1046.     CSeq_align_set::Tdata& data = dst->SetSegs().SetDisc().Set();
  1047.     ITERATE(TSubAligns, it, m_SubAligns) {
  1048.         data.push_back(it->GetDstAlign());
  1049.     }
  1050. }
  1051. CRef<CSeq_align> CSeq_align_Mapper::GetDstAlign(void) const
  1052. {
  1053.     if (m_DstAlign) {
  1054.         return m_DstAlign;
  1055.     }
  1056.     CRef<CSeq_align> dst(new CSeq_align);
  1057.     dst->SetType(m_OrigAlign->GetType());
  1058.     if (m_OrigAlign->IsSetDim()) {
  1059.         dst->SetDim(m_OrigAlign->GetDim());
  1060.     }
  1061.     if (m_OrigAlign->IsSetScore()) {
  1062.         dst->SetScore() = m_OrigAlign->GetScore();
  1063.     }
  1064.     if (m_OrigAlign->IsSetBounds()) {
  1065.         dst->SetBounds() = m_OrigAlign->GetBounds();
  1066.     }
  1067.     switch ( m_OrigAlign->GetSegs().Which() ) {
  1068.     case CSeq_align::C_Segs::e_Dendiag:
  1069.         {
  1070.             x_GetDstDendiag(dst);
  1071.             break;
  1072.         }
  1073.     case CSeq_align::C_Segs::e_Denseg:
  1074.         {
  1075.             if (m_AlignFlags == eAlign_Normal) {
  1076.                 x_GetDstDenseg(dst);
  1077.             }
  1078.             else {
  1079.                 x_GetDstDendiag(dst);
  1080.             }
  1081.             break;
  1082.         }
  1083.     case CSeq_align::C_Segs::e_Std:
  1084.         {
  1085.             x_GetDstStd(dst);
  1086.             break;
  1087.         }
  1088.     case CSeq_align::C_Segs::e_Packed:
  1089.         {
  1090.             if (m_AlignFlags == eAlign_Normal) {
  1091.                 x_GetDstPacked(dst);
  1092.             }
  1093.             else {
  1094.                 x_GetDstDendiag(dst);
  1095.             }
  1096.             break;
  1097.         }
  1098.     case CSeq_align::C_Segs::e_Disc:
  1099.         {
  1100.             x_GetDstDisc(dst);
  1101.             break;
  1102.         }
  1103.     default:
  1104.         {
  1105.             dst->Assign(*m_OrigAlign);
  1106.             break;
  1107.         }
  1108.     }
  1109.     return m_DstAlign = dst;
  1110. }
  1111. END_SCOPE(objects)
  1112. END_NCBI_SCOPE
  1113. /*
  1114. * ---------------------------------------------------------------------------
  1115. * $Log: seq_align_mapper.cpp,v $
  1116. * Revision 1000.1  2004/06/01 19:23:43  gouriano
  1117. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  1118. *
  1119. * Revision 1.10  2004/05/27 17:52:11  grichenk
  1120. * Fixed warnings
  1121. *
  1122. * Revision 1.9  2004/05/26 14:57:47  ucko
  1123. * Change some types from unsigned int to size_t for consistency with STL
  1124. * containers' size() methods.
  1125. *
  1126. * Revision 1.8  2004/05/26 14:29:20  grichenk
  1127. * Redesigned CSeq_align_Mapper: preserve non-mapping intervals,
  1128. * fixed strands handling, improved performance.
  1129. *
  1130. * Revision 1.7  2004/05/21 21:42:12  gorelenk
  1131. * Added PCH ncbi_pch.hpp
  1132. *
  1133. * Revision 1.6  2004/05/13 19:10:57  grichenk
  1134. * Preserve scores in mapped alignments
  1135. *
  1136. * Revision 1.5  2004/05/10 20:22:24  grichenk
  1137. * Fixed more warnings (removed inlines)
  1138. *
  1139. * Revision 1.4  2004/04/12 14:35:59  grichenk
  1140. * Fixed mapping of alignments between nucleotides and proteins
  1141. *
  1142. * Revision 1.3  2004/04/07 18:36:12  grichenk
  1143. * Fixed std-seg mapping
  1144. *
  1145. * Revision 1.2  2004/04/01 20:11:17  rsmith
  1146. * add missing break to switch on seq-id types.
  1147. *
  1148. * Revision 1.1  2004/03/30 15:40:35  grichenk
  1149. * Initial revision
  1150. *
  1151. *
  1152. * ===========================================================================
  1153. */