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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: Dense_seg.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:33:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: Dense_seg.cpp,v 1000.4 2004/06/01 19:33:35 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:  .......
  35.  *
  36.  * File Description:
  37.  *   .......
  38.  *
  39.  * Remark:
  40.  *   This code was originally generated by application DATATOOL
  41.  *   using specifications from the data definition file
  42.  *   'seqalign.asn'.
  43.  */
  44. // standard includes
  45. #include <ncbi_pch.hpp>
  46. #include <algorithm>
  47. #include <objects/seqalign/seqalign_exception.hpp>
  48. // generated includes
  49. #include <objects/seqalign/Dense_seg.hpp>
  50. #include <objects/seqloc/Seq_id.hpp>
  51. #include <objects/seqloc/Seq_loc.hpp>
  52. // generated classes
  53. BEGIN_NCBI_SCOPE
  54. BEGIN_objects_SCOPE // namespace ncbi::objects::
  55. // destructor
  56. CDense_seg::~CDense_seg(void)
  57. {
  58. }
  59. CDense_seg::TNumseg CDense_seg::CheckNumSegs() const
  60. {
  61.     const CDense_seg::TStarts&  starts  = GetStarts();
  62.     const CDense_seg::TStrands& strands = GetStrands();
  63.     const CDense_seg::TLens&    lens    = GetLens();
  64.     const CDense_seg::TWidths&  widths  = GetWidths();
  65.     const size_t& numrows = GetDim();
  66.     const size_t& numsegs = GetNumseg();
  67.     const size_t  num     = numrows * numsegs;
  68.     if (starts.size() != num) {
  69.         string errstr = string("CDense_seg::CheckNumSegs():")
  70.             + " starts.size is inconsistent with dim * numseg";
  71.         NCBI_THROW(CSeqalignException, eInvalidAlignment, errstr);
  72.     }
  73.     if (lens.size() != numsegs) {
  74.         string errstr = string("CDense_seg::CheckNumSegs():")
  75.             + " lens.size is inconsistent with numseg";
  76.         NCBI_THROW(CSeqalignException, eInvalidAlignment, errstr);
  77.     }
  78.     if (strands.size()  &&  strands.size() != num) {
  79.         string errstr = string("CDense_seg::CheckNumSegs():")
  80.             + " strands.size is inconsistent with dim * numseg";
  81.         NCBI_THROW(CSeqalignException, eInvalidAlignment, errstr);
  82.     }
  83.     if (widths.size()  &&  widths.size() != numrows) {
  84.         string errstr = string("CDense_seg::CheckNumSegs():")
  85.             + " widths.size is inconsistent with dim";
  86.         NCBI_THROW(CSeqalignException, eInvalidAlignment, errstr);
  87.     }
  88.     return numsegs;
  89. }
  90. TSeqPos CDense_seg::GetSeqStart(TDim row) const
  91. {
  92.     const TDim&    dim    = GetDim();
  93.     const TNumseg& numseg = CheckNumSegs();
  94.     const TStarts& starts = GetStarts();
  95.     if (row < 0  ||  row >= dim) {
  96.         NCBI_THROW(CSeqalignException, eInvalidRowNumber,
  97.                    "CDense_seg::GetSeqStop():"
  98.                    " Invalid row number");
  99.     }
  100.     TSignedSeqPos start;
  101.     if (CanGetStrands()  &&  GetStrands().size()  &&  GetStrands()[row] == eNa_strand_minus) {
  102.         TNumseg seg = numseg;
  103.         int pos = (seg - 1) * dim + row;
  104.         while (seg--) {
  105.             if ((start = starts[pos]) >= 0) {
  106.                 return start;
  107.             }
  108.             pos -= dim;
  109.         }
  110.     } else {
  111.         TNumseg seg = -1;
  112.         int pos = row;
  113.         while (++seg < numseg) {
  114.             if ((start = starts[pos]) >= 0) {
  115.                 return start;
  116.             }
  117.             pos += dim;
  118.         }
  119.     }
  120.     NCBI_THROW(CSeqalignException, eInvalidAlignment,
  121.                "CDense_seg::GetSeqStart(): Row is empty");
  122. }
  123. TSeqPos CDense_seg::GetSeqStop(TDim row) const
  124. {
  125.     const TDim& dim       = GetDim();
  126.     const TNumseg& numseg = CheckNumSegs();
  127.     const TStarts& starts = GetStarts();
  128.     if (row < 0  ||  row >= dim) {
  129.         NCBI_THROW(CSeqalignException, eInvalidRowNumber,
  130.                    "CDense_seg::GetSeqStop():"
  131.                    " Invalid row number");
  132.     }
  133.     TSignedSeqPos start;
  134.     if (CanGetStrands()  &&  GetStrands().size()  &&  GetStrands()[row] == eNa_strand_minus) {
  135.         TNumseg seg = -1;
  136.         int pos = row;
  137.         while (++seg < numseg) {
  138.             if ((start = starts[pos]) >= 0) {
  139.                 return start + GetLens()[seg] - 1;
  140.             }
  141.             pos += dim;
  142.         }
  143.     } else {
  144.         TNumseg seg = numseg;
  145.         int pos = (seg - 1) * dim + row;
  146.         while (seg--) {
  147.             if ((start = starts[pos]) >= 0) {
  148.                 return start + GetLens()[seg] - 1;
  149.             }
  150.             pos -= dim;
  151.         }        
  152.     }
  153.     NCBI_THROW(CSeqalignException, eInvalidAlignment,
  154.                "CDense_seg::GetSeqStop(): Row is empty");
  155. }
  156. void CDense_seg::Validate(bool full_test) const
  157. {
  158.     const CDense_seg::TStarts&  starts  = GetStarts();
  159.     const CDense_seg::TStrands& strands = GetStrands();
  160.     const CDense_seg::TLens&    lens    = GetLens();
  161.     const CDense_seg::TWidths&  widths  = GetWidths();
  162.     const size_t& numrows = CheckNumRows();
  163.     const size_t& numsegs = CheckNumSegs();
  164.     if (full_test) {
  165.         const size_t  max     = numrows * (numsegs -1);
  166.         bool strands_exist = !strands.empty();
  167.         size_t numseg = 0, numrow = 0, offset = 0;
  168.         for (numrow = 0;  numrow < numrows;  numrow++) {
  169.             TSignedSeqPos min_start = -1, start;
  170.             bool plus = strands_exist ? 
  171.                 strands[numrow] != eNa_strand_minus:
  172.                 true;
  173.             
  174.             if (plus) {
  175.                 offset = 0;
  176.             } else {
  177.                 offset = max;
  178.             }
  179.             
  180.             for (numseg = 0;  numseg < numsegs;  numseg++) {
  181.                 start = starts[offset + numrow];
  182.                 if (start >= 0) {
  183.                     if (start < min_start) {
  184.                         string errstr = string("CDense_seg::Validate():")
  185.                             + " Starts are not consistent!"
  186.                             + " Row=" + NStr::IntToString(numrow) +
  187.                             " Seg=" + NStr::IntToString(plus ? numseg :
  188.                                                         numsegs - 1 - numseg) +
  189.                             " MinStart=" + NStr::IntToString(min_start) +
  190.                             " Start=" + NStr::IntToString(start);
  191.                         
  192.                         NCBI_THROW(CSeqalignException, eInvalidAlignment,
  193.                                    errstr);
  194.                     }
  195.                     min_start = start + 
  196.                         lens[plus ? numseg : numsegs - 1 - numseg] *
  197.                         (widths.size() == numrows ?
  198.                          widths[numrow] : 1);
  199.                 }
  200.                 if (plus) {
  201.                     offset += numrows;
  202.                 } else {
  203.                     offset -= numrows;
  204.                 }
  205.             }
  206.         }
  207.     }
  208. }
  209. //-----------------------------------------------------------------------------
  210. // PRE : none
  211. // POST: same alignment, opposite orientation
  212. void CDense_seg::Reverse(void)
  213. {
  214.     //flip strands
  215.     NON_CONST_ITERATE (CDense_seg::TStrands, i, SetStrands()) {
  216.         switch (*i) {
  217.         case eNa_strand_plus:  *i = eNa_strand_minus; break;
  218.         case eNa_strand_minus: *i = eNa_strand_plus;  break;
  219.         default:                    break;//do nothing if not + or -
  220.         }
  221.     }
  222.     //reverse list o' lengths
  223.     {
  224.         CDense_seg::TLens::iterator f = SetLens().begin();
  225.         CDense_seg::TLens::iterator r = SetLens().end();
  226.         while (f < r) {
  227.             swap(*(f++), *(--r));
  228.         }
  229.     }
  230.     //reverse list o' starts
  231.     CDense_seg::TStarts &starts = SetStarts();
  232.     int f = 0;
  233.     int r = (GetNumseg() - 1) * GetDim();
  234.     while (f < r) {
  235.         for (int i = 0;  i < GetDim();  ++i) {
  236.             swap(starts[f+i], starts[r+i]);
  237.         }
  238.         f += GetDim();
  239.         r -= GetDim();
  240.     }
  241. }
  242. //-----------------------------------------------------------------------------
  243. // PRE : numbers of the rows to swap
  244. // POST: alignment rearranged with row1 where row2 used to be & vice versa
  245. void CDense_seg::SwapRows(TDim row1, TDim row2)
  246. {
  247.     if (row1 >= GetDim()  ||  row1 < 0  ||
  248.         row2 >= GetDim()  ||  row2 < 0) {
  249.         NCBI_THROW(CSeqalignException, eOutOfRange,
  250.                    "Row numbers supplied to CDense_seg::SwapRows must be "
  251.                    "in the range [0, dim)");
  252.     }
  253.     //swap ids
  254.     swap(SetIds()[row1], SetIds()[row2]);
  255.     int idxStop = GetNumseg()*GetDim();
  256.     
  257.     //swap starts
  258.     for(int i = 0; i < idxStop; i += GetDim()) {
  259.         swap(SetStarts()[i+row1], SetStarts()[i+row2]);
  260.     }
  261.     //swap strands
  262.     for(int i = 0; i < idxStop; i += GetDim()) {
  263.         swap(SetStrands()[i+row1], SetStrands()[i+row2]);
  264.     }
  265. }
  266. void CDense_seg::RemapToLoc(TDim row, const CSeq_loc& loc,
  267.                             bool ignore_strand)
  268. {
  269.     if (loc.IsWhole()) {
  270.         return;
  271.     }
  272.     TSeqPos row_stop  = GetSeqStop(row);
  273.     size_t  ttl_loc_len = 0;
  274.     {{
  275.         CSeq_loc_CI seq_loc_i(loc);
  276.         do {
  277.             ttl_loc_len += seq_loc_i.GetRange().GetLength();
  278.         } while (++seq_loc_i);
  279.     }}
  280.     // check the validity of the seq-loc
  281.     if (ttl_loc_len < row_stop + 1) {
  282.         string errstr("CDense_seg::RemapToLoc():"
  283.                       " Seq-loc is not long enough to"
  284.                       " cover the alignment!"
  285.                       " Maximum row seq pos is ");
  286.         errstr += NStr::IntToString(row_stop);
  287.         errstr += " The total seq-loc len is only ";
  288.         errstr += NStr::IntToString(ttl_loc_len);
  289.         errstr += ", it should be at least ";
  290.         errstr += NStr::IntToString(row_stop+1);
  291.         errstr += " (= max seq pos + 1).";
  292.         NCBI_THROW(CSeqalignException, eOutOfRange, errstr);
  293.     }
  294.     const CDense_seg::TStarts&  starts  = GetStarts();
  295.     const CDense_seg::TStrands& strands = GetStrands();
  296.     const CDense_seg::TLens&    lens    = GetLens();
  297.     const size_t& numrows = CheckNumRows();
  298.     const size_t& numsegs = CheckNumSegs();
  299.     CSeq_loc_CI seq_loc_i(loc);
  300.     TSeqPos start, loc_len, len, len_so_far;
  301.     start = seq_loc_i.GetRange().GetFrom();
  302.     len = loc_len = seq_loc_i.GetRange().GetLength();
  303.     len_so_far = 0;
  304.     
  305.     bool row_plus = !strands.size() || strands[row] != eNa_strand_minus;
  306.     bool loc_plus = seq_loc_i.GetStrand() != eNa_strand_minus;
  307.     // iterate through segments
  308.     size_t  idx = loc_plus ? row : (numsegs - 1) * numrows + row;
  309.     TNumseg seg = loc_plus ? 0 : numsegs - 1;
  310.     while (loc_plus ? seg < GetNumseg() : seg >= 0) {
  311.         if (starts[idx] == -1) {
  312.             // ignore gaps in our sequence
  313.             if (loc_plus) {
  314.                 idx += numrows; seg++;
  315.             } else {
  316.                 idx -= numrows; seg--;
  317.             }
  318.             continue;
  319.         }
  320.         // iterate the seq-loc if needed
  321.         if ((loc_plus == row_plus ?
  322.              starts[idx] : ttl_loc_len - starts[idx] - lens[seg])
  323.             > len_so_far + loc_len) {
  324.             if (++seq_loc_i) {
  325.                 len_so_far += len;
  326.                 len   = seq_loc_i.GetRange().GetLength();
  327.                 start = seq_loc_i.GetRange().GetFrom();
  328.             } else {
  329.                 NCBI_THROW(CSeqalignException, eInvalidInputData,
  330.                            "CDense_seg::RemapToLoc():"
  331.                            " Internal error");
  332.             }
  333.             // assert the strand is the same
  334.             if (loc_plus != (seq_loc_i.GetStrand() != eNa_strand_minus)) {
  335.                 NCBI_THROW(CSeqalignException, eInvalidInputData,
  336.                            "CDense_seg::RemapToLoc():"
  337.                            " The strand should be the same accross"
  338.                            " the input seq-loc");
  339.             }
  340.         }
  341.         // offset for the starting position
  342.         if (loc_plus == row_plus) {
  343.             SetStarts()[idx] += start - len_so_far;
  344.         } else {
  345.             SetStarts()[idx] = 
  346.                 start - len_so_far + ttl_loc_len - starts[idx] - lens[seg];
  347.         }
  348.         if (lens[seg] > len) {
  349.             TSignedSeqPos len_diff = lens[seg] - len;
  350.             while (1) {
  351.                 // move to the next loc part that extends beyond our length
  352.                 ++seq_loc_i;
  353.                 if (seq_loc_i) {
  354.                     start = seq_loc_i.GetRange().GetFrom();
  355.                 } else {
  356.                     NCBI_THROW(CSeqalignException, eOutOfRange,
  357.                                "CDense_seg::RemapToLoc():"
  358.                                " Internal error");
  359.                 }
  360.                 // split our segment
  361.                 SetLens().insert(SetLens().begin() + 
  362.                                  (loc_plus ? seg : seg + 1),
  363.                                  len);
  364.                 SetLens()[loc_plus ? seg + 1 : seg] = len_diff;
  365.                 // insert new data to account for our split segment
  366.                 TStarts temp_starts(numrows, -1);
  367.                 for (size_t row_i = 0, tmp_idx = seg * numrows;
  368.                      row_i < numrows;  ++row_i, ++tmp_idx) {
  369.                     TSignedSeqPos& this_start = SetStarts()[tmp_idx];
  370.                     if (this_start != -1) {
  371.                         temp_starts[row_i] = this_start;
  372.                         if (loc_plus == (strands[row_i] != eNa_strand_minus)) {
  373.                             if ((size_t) row == row_i) {
  374.                                 temp_starts[row_i] = start;
  375.                             } else {
  376.                                 temp_starts[row_i] += len;
  377.                             }
  378.                         } else {
  379.                             this_start += len_diff;
  380.                         }
  381.                     }
  382.                 }
  383.                 len_so_far += loc_len;
  384.                 len = loc_len = seq_loc_i.GetRange().GetLength();
  385.                 SetStarts().insert(SetStarts().begin() +
  386.                                    (loc_plus ? seg + 1 : seg) * numrows,
  387.                                    temp_starts.begin(), temp_starts.end());
  388.                 
  389.                 if (strands.size()) {
  390.                     SetStrands().insert
  391.                         (SetStrands().begin(),
  392.                          strands.begin(), strands.begin() + numrows);
  393.                 }
  394.                 SetNumseg()++;
  395.                 
  396.                 if ((len_diff = lens[seg] - len) > 0) {
  397.                     if (loc_plus) {
  398.                         idx += numrows; seg++;
  399.                     } else {
  400.                         idx -= numrows; seg--;
  401.                     }
  402.                 } else {
  403.                     break;
  404.                 }
  405.             }
  406.         } else {
  407.             len -= lens[seg];
  408.         }
  409.         if (loc_plus) {
  410.             idx += numrows; seg++;
  411.         } else {
  412.             idx -= numrows; seg--;
  413.         }
  414.     } // while iterating through segments
  415.     
  416.     // finally, modify the strands if different
  417.     if ( !ignore_strand ) {
  418.         if (loc_plus != row_plus) {
  419.             if (!strands.size()) {
  420.                 // strands do not exist, create them
  421.                 SetStrands().resize(GetNumseg() * GetDim(), eNa_strand_plus);
  422.             }
  423.             for (seg = 0, idx = row;
  424.                  seg < GetNumseg(); seg++, idx += numrows) {
  425.                 SetStrands()[idx] = loc_plus ? eNa_strand_plus : eNa_strand_minus;
  426.             }
  427.         }
  428.     }
  429. }
  430. END_objects_SCOPE // namespace ncbi::objects::
  431. END_NCBI_SCOPE
  432. /*
  433. * ===========================================================================
  434. *
  435. * $Log: Dense_seg.cpp,v $
  436. * Revision 1000.4  2004/06/01 19:33:35  gouriano
  437. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  438. *
  439. * Revision 1.13  2004/05/19 17:25:43  gorelenk
  440. * Added include of PCH - ncbi_pch.hpp
  441. *
  442. * Revision 1.12  2004/05/06 18:23:54  todorov
  443. * + optional ignore_strand param to RemapToLoc
  444. *
  445. * Revision 1.11  2004/03/10 13:04:18  dicuccio
  446. * Compilation fix for Win32: don't add char* and char*
  447. *
  448. * Revision 1.10  2004/03/09 21:57:03  todorov
  449. * Fixed the out-of-range exception txt
  450. *
  451. * Revision 1.9  2004/02/12 20:54:15  yazhuk
  452. * Fixed GetStartPos() GetStopPos() handling of empty m_Strands
  453. *
  454. * Revision 1.8  2003/12/19 20:15:21  todorov
  455. * RemapToLoc should do nothing in case of a whole Seq-loc
  456. *
  457. * Revision 1.7  2003/11/20 21:26:33  todorov
  458. * RemapToLoc bug fixes: + seg inc; + loc_len vs len
  459. *
  460. * Revision 1.6  2003/11/04 14:44:46  todorov
  461. * +RemapToLoc
  462. *
  463. * Revision 1.5  2003/09/25 17:50:14  dicuccio
  464. * Changed testing of STL container size to use empty() and avoid warning on MSVC
  465. *
  466. * Revision 1.4  2003/09/16 15:31:14  todorov
  467. * Added validation methods. Added seq range methods
  468. *
  469. * Revision 1.3  2003/08/26 21:10:49  ucko
  470. * #include Seq_id.hpp
  471. *
  472. * Revision 1.2  2003/08/26 20:28:38  johnson
  473. * added 'SwapRows' method
  474. *
  475. * Revision 1.1  2003/08/13 18:12:03  johnson
  476. * added 'Reverse' method
  477. *
  478. *
  479. * ===========================================================================
  480. */
  481. /* Original file checksum: lines: 64, chars: 1885, CRC32: 4483973b */