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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seq_vector_ci.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:24:26  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.34
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seq_vector_ci.cpp,v 1000.3 2004/06/01 19:24:26 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, Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Seq-vector iterator
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <objmgr/seq_vector.hpp>
  42. #include <objmgr/seq_vector_ci.hpp>
  43. #include <objects/seq/NCBI8aa.hpp>
  44. #include <objects/seq/NCBIpaa.hpp>
  45. #include <objects/seq/NCBIstdaa.hpp>
  46. #include <objects/seq/NCBIeaa.hpp>
  47. #include <objects/seq/NCBIpna.hpp>
  48. #include <objects/seq/NCBI8na.hpp>
  49. #include <objects/seq/NCBI4na.hpp>
  50. #include <objects/seq/NCBI2na.hpp>
  51. #include <objects/seq/IUPACaa.hpp>
  52. #include <objects/seq/IUPACna.hpp>
  53. #include <algorithm>
  54. #include <objmgr/impl/seq_vector_cvt.hpp>
  55. #include <objmgr/objmgr_exception.hpp>
  56. #include <util/random_gen.hpp>
  57. BEGIN_NCBI_SCOPE
  58. BEGIN_SCOPE(objects)
  59. // Internal class to put random bases in place of ambiguities
  60. const size_t kRandomizerPosMask = 0x3f;
  61. const size_t kRandomDataSize    = kRandomizerPosMask + 1;
  62. class CNcbi2naRandomizer : public CObject
  63. {
  64. public:
  65.     // If seed == 0 then use random number for seed
  66.     CNcbi2naRandomizer(CRandom& gen);
  67.     ~CNcbi2naRandomizer(void);
  68.     typedef char* TData;
  69.     void RandomizeData(TData data,    // cache to be randomized
  70.                        size_t count,  // number of bases in the cache
  71.                        TSeqPos pos);  // sequence pos of the cache
  72. private:
  73.     CNcbi2naRandomizer(const CNcbi2naRandomizer&);
  74.     CNcbi2naRandomizer& operator=(const CNcbi2naRandomizer&);
  75.     // First value in each row indicates ambiguity (1) or
  76.     // normal base (0)
  77.     typedef char        TRandomData[kRandomDataSize + 1];
  78.     typedef TRandomData TRandomTable[16];
  79.     TRandomTable m_RandomTable;
  80. };
  81. CNcbi2naRandomizer::CNcbi2naRandomizer(CRandom& gen)
  82. {
  83.     unsigned int bases[4]; // Count of each base in the random distribution
  84.     for (int na4 = 0; na4 < 16; na4++) {
  85.         int bit_count = 0;
  86.         char set_bit = 0;
  87.         for (int bit = 0; bit < 4; bit++) {
  88.             // na4 == 0 is special case (gap) should be treated as 0xf
  89.             if ( !na4  ||  (na4 & (1 << bit)) ) {
  90.                 bit_count++;
  91.                 bases[bit] = 1;
  92.                 set_bit = bit;
  93.             }
  94.             else {
  95.                 bases[bit] = 0;
  96.             }
  97.         }
  98.         if (bit_count == 1) {
  99.             // Single base
  100.             m_RandomTable[na4][0] = 0;
  101.             m_RandomTable[na4][1] = set_bit;
  102.             continue;
  103.         }
  104.         // Ambiguity: create random distribution with possible bases
  105.         m_RandomTable[na4][0] = bit_count; // need any non-zero value
  106.         for (int bit = 0; bit < 4; bit++) {
  107.             bases[bit] *= kRandomDataSize/bit_count +
  108.                 kRandomDataSize % bit_count;
  109.         }
  110.         for (int i = kRandomDataSize - 1; i >= 0; i--) {
  111.             CRandom::TValue rnd = gen.GetRand(0, i);
  112.             for (int base = 0; base < 4; base++) {
  113.                 if (!bases[base]  ||  rnd > bases[base]) {
  114.                     rnd -= bases[base];
  115.                     continue;
  116.                 }
  117.                 m_RandomTable[na4][i + 1] = base;
  118.                 bases[base]--;
  119.                 break;
  120.             }
  121.         }
  122.     }
  123. }
  124. CNcbi2naRandomizer::~CNcbi2naRandomizer(void)
  125. {
  126.     return;
  127. }
  128. void CNcbi2naRandomizer::RandomizeData(TData data,
  129.                                        size_t count,
  130.                                        TSeqPos pos)
  131. {
  132.     for (TData stop = data + count; data < stop; ++data, ++pos) {
  133.         if ( m_RandomTable[(unsigned char)(*data)][0] ) {
  134.             // Ambiguity, use random value
  135.             *data = m_RandomTable[(unsigned char)(*data)]
  136.                 [(pos & kRandomizerPosMask) + 1];
  137.         }
  138.         else {
  139.             // Normal base
  140.             *data = m_RandomTable[(unsigned char)(*data)][1];
  141.         }
  142.     }
  143. }
  144. static const TSeqPos kCacheSize = 1024;
  145. template<class DstIter, class SrcCont>
  146. inline
  147. void copy_8bit_any(DstIter dst, size_t count,
  148.                    const SrcCont& srcCont, size_t srcPos,
  149.                    const char* table, bool reverse)
  150. {
  151.     size_t endPos = srcPos + count;
  152.     if ( endPos < srcPos || endPos > srcCont.size() ) {
  153.         NCBI_THROW(CSeqVectorException, eOutOfRange,
  154.                    "reference out of range of Seq-inst data");
  155.     }
  156.     if ( table ) {
  157.         if ( reverse ) {
  158.             copy_8bit_table_reverse(dst, count, srcCont, srcPos, table);
  159.         }
  160.         else {
  161.             copy_8bit_table(dst, count, srcCont, srcPos, table);
  162.         }
  163.     }
  164.     else {
  165.         if ( reverse ) {
  166.             copy_8bit_reverse(dst, count, srcCont, srcPos);
  167.         }
  168.         else {
  169.             copy_8bit(dst, count, srcCont, srcPos);
  170.         }
  171.     }
  172. }
  173. template<class DstIter, class SrcCont>
  174. inline
  175. void copy_4bit_any(DstIter dst, size_t count,
  176.                    const SrcCont& srcCont, size_t srcPos,
  177.                    const char* table, bool reverse)
  178. {
  179.     size_t endPos = srcPos + count;
  180.     if ( endPos < srcPos || endPos / 2 > srcCont.size() ) {
  181.         NCBI_THROW(CSeqVectorException, eOutOfRange,
  182.                    "reference out of range of Seq-inst data");
  183.     }
  184.     if ( table ) {
  185.         if ( reverse ) {
  186.             copy_4bit_table_reverse(dst, count, srcCont, srcPos, table);
  187.         }
  188.         else {
  189.             copy_4bit_table(dst, count, srcCont, srcPos, table);
  190.         }
  191.     }
  192.     else {
  193.         if ( reverse ) {
  194.             copy_4bit_reverse(dst, count, srcCont, srcPos);
  195.         }
  196.         else {
  197.             copy_4bit(dst, count, srcCont, srcPos);
  198.         }
  199.     }
  200. }
  201. template<class DstIter, class SrcCont>
  202. inline
  203. void copy_2bit_any(DstIter dst, size_t count,
  204.                    const SrcCont& srcCont, size_t srcPos,
  205.                    const char* table, bool reverse)
  206. {
  207.     size_t endPos = srcPos + count;
  208.     if ( endPos < srcPos || endPos / 4 > srcCont.size() ) {
  209.         NCBI_THROW(CSeqVectorException, eOutOfRange,
  210.                    "reference out of range of Seq-inst data");
  211.     }
  212.     if ( table ) {
  213.         if ( reverse ) {
  214.             copy_2bit_table_reverse(dst, count, srcCont, srcPos, table);
  215.         }
  216.         else {
  217.             copy_2bit_table(dst, count, srcCont, srcPos, table);
  218.         }
  219.     }
  220.     else {
  221.         if ( reverse ) {
  222.             copy_2bit_reverse(dst, count, srcCont, srcPos);
  223.         }
  224.         else {
  225.             copy_2bit(dst, count, srcCont, srcPos);
  226.         }
  227.     }
  228. }
  229. // CSeqVector_CI::
  230. CSeqVector_CI::CSeqVector_CI(void)
  231.     : m_Strand(eNa_strand_unknown),
  232.       m_Coding(CSeq_data::e_not_set),
  233.       m_Cache(0),
  234.       m_CachePos(0),
  235.       m_CacheData(0),
  236.       m_CacheEnd(0),
  237.       m_BackupPos(0),
  238.       m_BackupData(0),
  239.       m_BackupEnd(0)
  240. {
  241. }
  242. CSeqVector_CI::~CSeqVector_CI(void)
  243. {
  244.     x_DestroyCache();
  245. }
  246. CSeqVector_CI::CSeqVector_CI(const CSeqVector_CI& sv_it)
  247.     : m_Strand(eNa_strand_unknown),
  248.       m_Coding(CSeq_data::e_not_set),
  249.       m_Cache(0),
  250.       m_CachePos(0),
  251.       m_CacheData(0),
  252.       m_CacheEnd(0),
  253.       m_BackupPos(0),
  254.       m_BackupData(0),
  255.       m_BackupEnd(0),
  256.       m_Randomizer(sv_it.m_Randomizer)
  257. {
  258.     try {
  259.         *this = sv_it;
  260.     }
  261.     catch (...) {
  262.         x_DestroyCache();
  263.         throw;
  264.     }
  265. }
  266. CSeqVector_CI::CSeqVector_CI(const CSeqVector& seq_vector, TSeqPos pos)
  267.     : m_SeqMap(seq_vector.m_SeqMap),
  268.       m_Scope(seq_vector.m_Scope),
  269.       m_Strand(seq_vector.m_Strand),
  270.       m_Coding(seq_vector.m_Coding),
  271.       m_Cache(0),
  272.       m_CachePos(0),
  273.       m_CacheData(0),
  274.       m_CacheEnd(0),
  275.       m_BackupPos(0),
  276.       m_BackupData(0),
  277.       m_BackupEnd(0)
  278. {
  279.     try {
  280.         x_SetPos(pos);
  281.     }
  282.     catch (...) {
  283.         x_DestroyCache();
  284.         throw;
  285.     }
  286. }
  287. void CSeqVector_CI::x_SetVector(CSeqVector& seq_vector)
  288. {
  289.     if ( m_SeqMap ) {
  290.         // reset old values
  291.         m_Seg = CSeqMap_CI();
  292.         x_ResetCache();
  293.         x_ResetBackup();
  294.     }
  295.     m_SeqMap = seq_vector.m_SeqMap;
  296.     m_Scope  = seq_vector.m_Scope;
  297.     m_Strand = seq_vector.m_Strand;
  298.     m_Coding = seq_vector.m_Coding;
  299.     m_CachePos = seq_vector.size();
  300. }
  301. inline
  302. TSeqPos CSeqVector_CI::x_GetSize(void) const
  303. {
  304.     return m_SeqMap->GetLength(m_Scope.GetScopeOrNull());
  305. }
  306. inline
  307. void CSeqVector_CI::x_InitSeg(TSeqPos pos)
  308. {
  309.     m_Seg = m_SeqMap->FindResolved(pos, m_Scope.GetScopeOrNull(), m_Strand);
  310. }
  311. void CSeqVector_CI::SetCoding(TCoding coding)
  312. {
  313.     if ( m_Coding != coding ) {
  314.         TSeqPos pos = GetPos();
  315.         x_ResetCache();
  316.         x_ResetBackup();
  317.         m_Coding = coding;
  318.         x_SetPos(pos);
  319.     }
  320. }
  321. CSeqVector_CI& CSeqVector_CI::operator=(const CSeqVector_CI& sv_it)
  322. {
  323.     if ( this == &sv_it ) {
  324.         return *this;
  325.     }
  326.     m_Scope = sv_it.m_Scope;
  327.     m_SeqMap = sv_it.m_SeqMap;
  328.     m_Strand = sv_it.m_Strand;
  329.     m_Coding = sv_it.GetCoding();
  330.     m_Seg = sv_it.m_Seg;
  331.     m_CachePos = sv_it.x_CachePos();
  332.     m_Randomizer = sv_it.m_Randomizer;
  333.     // copy cache if any
  334.     size_t cache_size = sv_it.x_CacheSize();
  335.     if ( cache_size ) {
  336.         x_InitializeCache();
  337.         m_CacheEnd = m_CacheData + cache_size;
  338.         m_Cache = m_CacheData + sv_it.x_CacheOffset();
  339.         memcpy(m_CacheData, sv_it.m_CacheData, cache_size);
  340.         // copy backup cache if any
  341.         size_t backup_size = sv_it.x_BackupSize();
  342.         if ( backup_size ) {
  343.             m_BackupPos = sv_it.x_BackupPos();
  344.             m_BackupEnd = m_BackupData + backup_size;
  345.             memcpy(m_BackupData, sv_it.m_BackupData, backup_size);
  346.         }
  347.         else {
  348.             x_ResetBackup();
  349.         }
  350.     }
  351.     else {
  352.         x_ResetCache();
  353.         x_ResetBackup();
  354.     }
  355.     return *this;
  356. }
  357. void CSeqVector_CI::x_DestroyCache(void)
  358. {
  359.     m_CachePos = GetPos();
  360.     delete[] m_CacheData;
  361.     m_Cache = m_CacheData = m_CacheEnd = 0;
  362.     delete[] m_BackupData;
  363.     m_BackupData = m_BackupEnd = 0;
  364. }
  365. void CSeqVector_CI::x_InitializeCache(void)
  366. {
  367.     if ( !m_Cache ) {
  368.         m_Cache = m_CacheEnd = m_CacheData = new char[kCacheSize];
  369.         try {
  370.             m_BackupEnd = m_BackupData = new char[kCacheSize];
  371.         }
  372.         catch (...) {
  373.             x_DestroyCache();
  374.             throw;
  375.         }
  376.     }
  377.     else {
  378.         x_ResetCache();
  379.     }
  380. }
  381. inline
  382. void CSeqVector_CI::x_ResizeCache(size_t size)
  383. {
  384.     _ASSERT(size <= kCacheSize);
  385.     if ( !m_CacheData ) {
  386.         x_InitializeCache();
  387.     }
  388.     m_CacheEnd = m_CacheData + size;
  389.     m_Cache = m_CacheData;
  390. }
  391. void CSeqVector_CI::x_UpdateCacheUp(TSeqPos pos)
  392. {
  393.     _ASSERT(pos < x_GetSize());
  394.     TSeqPos segEnd = m_Seg.GetEndPosition();
  395.     _ASSERT(pos >= m_Seg.GetPosition() && pos < segEnd);
  396.     TSeqPos cache_size = min(kCacheSize, segEnd - pos);
  397.     x_FillCache(pos, cache_size);
  398.     m_Cache = m_CacheData;
  399.     _ASSERT(GetPos() == pos);
  400. }
  401. void CSeqVector_CI::x_UpdateCacheDown(TSeqPos pos)
  402. {
  403.     _ASSERT(pos < x_GetSize());
  404.     TSeqPos segStart = m_Seg.GetPosition();
  405.     _ASSERT(pos >= segStart && pos < m_Seg.GetEndPosition());
  406.     TSeqPos cache_offset = min(kCacheSize - 1, pos - segStart);
  407.     x_FillCache(pos - cache_offset, cache_offset + 1);
  408.     m_Cache = m_CacheData + cache_offset;
  409.     _ASSERT(GetPos() == pos);
  410. }
  411. void CSeqVector_CI::x_FillCache(TSeqPos start, TSeqPos count)
  412. {
  413.     _ASSERT(m_Seg.GetType() != CSeqMap::eSeqEnd);
  414.     _ASSERT(start >= m_Seg.GetPosition());
  415.     _ASSERT(start < m_Seg.GetEndPosition());
  416.     x_ResizeCache(count);
  417.     switch ( m_Seg.GetType() ) {
  418.     case CSeqMap::eSeqData:
  419.     {
  420.         const CSeq_data& data = m_Seg.GetRefData();
  421.         CSeqVector::TCoding dataCoding = data.Which();
  422.         CSeqVector::TCoding cacheCoding = x_GetCoding(m_Coding, dataCoding);
  423.         bool reverse = m_Seg.GetRefMinusStrand();
  424.         bool randomize = false;
  425.         if (cacheCoding == CSeq_data::e_Ncbi2na  &&  bool(m_Randomizer)) {
  426.             cacheCoding = CSeq_data::e_Ncbi4na;
  427.             randomize = true;
  428.         }
  429.         const char* table = 0;
  430.         if ( cacheCoding != dataCoding || reverse ) {
  431.             table = CSeqVector::sx_GetConvertTable(dataCoding,
  432.                                                    cacheCoding,
  433.                                                    reverse);
  434.             if ( !table && cacheCoding != dataCoding ) {
  435.                 NCBI_THROW(CSeqVectorException, eCodingError,
  436.                            "Incompatible sequence codings");
  437.             }
  438.         }
  439.         TSeqPos dataPos;
  440.         if ( reverse ) {
  441.             // Revert segment offset
  442.             dataPos = m_Seg.GetRefEndPosition() -
  443.                 (start - m_Seg.GetPosition()) - count;
  444.         }
  445.         else {
  446.             dataPos = m_Seg.GetRefPosition() +
  447.                 (start - m_Seg.GetPosition());
  448.         }
  449.         switch ( dataCoding ) {
  450.         case CSeq_data::e_Iupacna:
  451.             copy_8bit_any(m_Cache, count, data.GetIupacna().Get(), dataPos,
  452.                           table, reverse);
  453.             break;
  454.         case CSeq_data::e_Iupacaa:
  455.             copy_8bit_any(m_Cache, count, data.GetIupacaa().Get(), dataPos,
  456.                           table, reverse);
  457.             break;
  458.         case CSeq_data::e_Ncbi2na:
  459.             copy_2bit_any(m_Cache, count, data.GetNcbi2na().Get(), dataPos,
  460.                             table, reverse);
  461.             break;
  462.         case CSeq_data::e_Ncbi4na:
  463.             copy_4bit_any(m_Cache, count, data.GetNcbi4na().Get(), dataPos,
  464.                           table, reverse);
  465.             break;
  466.         case CSeq_data::e_Ncbi8na:
  467.             copy_8bit_any(m_Cache, count, data.GetNcbi8na().Get(), dataPos,
  468.                           table, reverse);
  469.             break;
  470.         case CSeq_data::e_Ncbipna:
  471.             NCBI_THROW(CSeqVectorException, eCodingError,
  472.                        "Ncbipna conversion not implemented");
  473.         case CSeq_data::e_Ncbi8aa:
  474.             copy_8bit_any(m_Cache, count, data.GetNcbi8aa().Get(), dataPos,
  475.                           table, reverse);
  476.             break;
  477.         case CSeq_data::e_Ncbieaa:
  478.             copy_8bit_any(m_Cache, count, data.GetNcbieaa().Get(), dataPos,
  479.                           table, reverse);
  480.             break;
  481.         case CSeq_data::e_Ncbipaa:
  482.             NCBI_THROW(CSeqVectorException, eCodingError,
  483.                        "Ncbipaa conversion not implemented");
  484.         case CSeq_data::e_Ncbistdaa:
  485.             copy_8bit_any(m_Cache, count, data.GetNcbistdaa().Get(), dataPos,
  486.                           table, reverse);
  487.             break;
  488.         default:
  489.             NCBI_THROW(CSeqVectorException, eCodingError,
  490.                        "Invalid data coding");
  491.         }
  492.         if ( randomize ) {
  493.             m_Randomizer->RandomizeData(m_Cache, count, start);
  494.         }
  495.         break;
  496.     }
  497.     case CSeqMap::eSeqGap:
  498.         // x_GetCoding(m_Coding, CSeq_data::e_not_set);
  499.         fill(m_Cache, m_Cache + count, CSeqVector::x_GetGapChar(m_Coding));
  500.         if (m_Coding == CSeq_data::e_Ncbi2na  &&  bool(m_Randomizer)) {
  501.             m_Randomizer->RandomizeData(m_Cache, count, start);
  502.         }
  503.         break;
  504.     default:
  505.         NCBI_THROW(CSeqVectorException, eDataError,
  506.                    "Invalid segment type");
  507.     }
  508.     m_CachePos = start;
  509. }
  510. void CSeqVector_CI::x_SetPos(TSeqPos pos)
  511. {
  512.     TSeqPos size = x_GetSize();
  513.     if ( pos >= size ) {
  514.         if ( x_CacheSize() ) {
  515.             // save current cache as backup
  516.             x_SwapCache();
  517.             x_ResetCache();
  518.         }
  519.         _ASSERT(x_CacheSize() == 0 && x_CacheOffset() == 0);
  520.         m_CachePos = size;
  521.         _ASSERT(GetPos() == size);
  522.         return;
  523.     }
  524.     _ASSERT(pos - x_CachePos() >= x_CacheSize());
  525.     // update current segment
  526.     x_UpdateSeg(pos);
  527.     // save current cache as backup and restore old backup
  528.     x_SwapCache();
  529.     // check if old backup is suitable
  530.     TSeqPos cache_offset = pos - x_CachePos();
  531.     TSeqPos cache_size = x_CacheSize();
  532.     if ( cache_offset < cache_size ) {
  533.         // can use backup
  534.         _ASSERT(x_CacheSize() &&
  535.                 x_CachePos() >= m_Seg.GetPosition() &&
  536.                 x_CacheEndPos() <= m_Seg.GetEndPosition());
  537.         m_Cache = m_CacheData + cache_offset;
  538.     }
  539.     else {
  540.         // cannot use backup
  541.         x_InitializeCache();
  542.         TSeqPos old_pos = x_BackupPos();
  543.         if ( pos < old_pos && pos >= old_pos - kCacheSize &&
  544.              m_Seg.GetEndPosition() >= old_pos ) {
  545.             x_UpdateCacheDown(old_pos - 1);
  546.             cache_offset = pos - x_CachePos();
  547.             m_Cache = m_CacheData + cache_offset;
  548.         }
  549.         else {
  550.             x_UpdateCacheUp(pos);
  551.         }
  552.     }
  553.     _ASSERT(x_CacheOffset() < x_CacheSize());
  554.     _ASSERT(GetPos() == pos);
  555. }
  556. void CSeqVector_CI::x_UpdateSeg(TSeqPos pos)
  557. {
  558.     if ( m_Seg.IsInvalid() ) {
  559.         x_InitSeg(pos);
  560.     }
  561.     else if ( m_Seg.GetPosition() > pos ) {
  562.         // segment is ahead
  563.         do {
  564.             _ASSERT(m_Seg || m_Seg.GetPosition() == x_GetSize());
  565.             --m_Seg;
  566.         } while ( m_Seg.GetLength() == 0 ); // skip zero length segments
  567.         _ASSERT(m_Seg);
  568.         if ( m_Seg.GetPosition() > pos ) {
  569.             // too far
  570.             x_InitSeg(pos);
  571.         }
  572.     }
  573.     else if ( m_Seg.GetEndPosition() <= pos ) {
  574.         // segment is behind
  575.         do {
  576.             _ASSERT(m_Seg);
  577.             ++m_Seg;
  578.         } while ( m_Seg.GetLength() == 0 ); // skip zero length segments
  579.         _ASSERT(m_Seg);
  580.         if ( m_Seg.GetEndPosition() <= pos ) {
  581.             // too far
  582.             x_InitSeg(pos);
  583.         }
  584.     }
  585.     _ASSERT(pos >= m_Seg.GetPosition() && pos < m_Seg.GetEndPosition());
  586. }
  587. void CSeqVector_CI::GetSeqData(string& buffer, TSeqPos count)
  588. {
  589.     buffer.erase();
  590.     count = min(count, x_GetSize() - GetPos());
  591.     if ( count ) {
  592.         buffer.reserve(count);
  593.         do {
  594.             TCache_I cache = m_Cache;
  595.             TCache_I cache_end = m_CacheEnd;
  596.             TSeqPos chunk_count = min(count, TSeqPos(cache_end - cache));
  597.             _ASSERT(chunk_count > 0);
  598.             TCache_I chunk_end = cache + chunk_count;
  599.             buffer.append(cache, chunk_end);
  600.             if ( chunk_end == cache_end ) {
  601.                 x_NextCacheSeg();
  602.             }
  603.             else {
  604.                 m_Cache = chunk_end;
  605.             }
  606.             count -= chunk_count;
  607.         } while ( count );
  608.     }
  609. }
  610. void CSeqVector_CI::x_NextCacheSeg()
  611. {
  612.     _ASSERT(m_SeqMap);
  613.     TSeqPos pos = x_CacheEndPos();
  614.     // save current cache in backup
  615.     _ASSERT(x_CacheSize());
  616.     x_SwapCache();
  617.     // update segment if needed
  618.     while ( m_Seg.GetEndPosition() <= pos ) {
  619.         if ( !m_Seg ) {
  620.             // end of sequence
  621.             _ASSERT(pos == x_GetSize());
  622.             x_ResetCache();
  623.             m_CachePos = pos;
  624.             return;
  625.         }
  626.         ++m_Seg;
  627.     }
  628.     _ASSERT(m_Seg);
  629.     // Try to re-use backup cache
  630.     if ( pos < x_CacheEndPos() && pos >= x_CachePos() ) {
  631.         m_Cache = m_CacheData + pos - x_CachePos();
  632.     }
  633.     else {
  634.         // can not use backup cache
  635.         x_ResetCache();
  636.         x_UpdateCacheUp(pos);
  637.         _ASSERT(GetPos() == pos);
  638.         _ASSERT(x_CacheSize());
  639.         _ASSERT(x_CachePos() == pos);
  640.     }
  641. }
  642. void CSeqVector_CI::x_PrevCacheSeg()
  643. {
  644.     _ASSERT(m_SeqMap);
  645.     TSeqPos pos = x_CachePos();
  646.     if ( pos-- == 0 ) {
  647.         // Can not go further
  648.         NCBI_THROW(CSeqVectorException, eOutOfRange,
  649.                    "Can not update cache: iterator out of range");
  650.     }
  651.     // save current cache in backup
  652.     x_SwapCache();
  653.     // update segment if needed
  654.     if ( m_Seg.IsInvalid() ) {
  655.         x_InitSeg(pos);
  656.     }
  657.     else {
  658.         while ( m_Seg.GetPosition() > pos ) {
  659.             _ASSERT(m_Seg || m_Seg.GetPosition() == x_GetSize());
  660.             --m_Seg;
  661.         }
  662.     }
  663.     _ASSERT(m_Seg);
  664.     // Try to re-use backup cache
  665.     if ( pos >= x_CachePos()  &&  pos < x_CacheEndPos() ) {
  666.         m_Cache = m_CacheData + pos - x_CachePos();
  667.     }
  668.     else {
  669.         // can not use backup cache
  670.         x_ResetCache();
  671.         x_UpdateCacheDown(pos);
  672.         _ASSERT(GetPos() == pos);
  673.         _ASSERT(x_CacheSize());
  674.         _ASSERT(x_CacheEndPos() == pos+1);
  675.     }
  676. }
  677. void CSeqVector_CI::x_InitRandomizer(CRandom& random_gen)
  678. {
  679.     TSeqPos pos = GetPos();
  680.     x_ResetCache();
  681.     x_ResetBackup();
  682.     m_Randomizer.Reset(new CNcbi2naRandomizer(random_gen));
  683.     x_SetPos(pos);
  684. }
  685. void CSeqVector_CI::SetRandomizeAmbiguities(void)
  686. {
  687.     CRandom random_gen;
  688.     x_InitRandomizer(random_gen);
  689. }
  690. void CSeqVector_CI::SetRandomizeAmbiguities(Uint4 seed)
  691. {
  692.     CRandom random_gen(seed);
  693.     x_InitRandomizer(random_gen);
  694. }
  695. void CSeqVector_CI::SetRandomizeAmbiguities(CRandom& random_gen)
  696. {
  697.     x_InitRandomizer(random_gen);
  698. }
  699. void CSeqVector_CI::SetNoAmbiguities(void)
  700. {
  701.     TSeqPos pos = GetPos();
  702.     x_ResetCache();
  703.     x_ResetBackup();
  704.     m_Randomizer.Reset();
  705.     x_SetPos(pos);
  706. }
  707. END_SCOPE(objects)
  708. END_NCBI_SCOPE
  709. /*
  710. * ---------------------------------------------------------------------------
  711. * $Log: seq_vector_ci.cpp,v $
  712. * Revision 1000.3  2004/06/01 19:24:26  gouriano
  713. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.34
  714. *
  715. * Revision 1.34  2004/05/21 21:42:13  gorelenk
  716. * Added PCH ncbi_pch.hpp
  717. *
  718. * Revision 1.33  2004/05/10 18:27:37  grichenk
  719. * Check cache in x_ResizeCache()
  720. *
  721. * Revision 1.32  2004/04/27 14:45:01  grichenk
  722. * Fixed warnings.
  723. *
  724. * Revision 1.31  2004/04/22 18:34:18  grichenk
  725. * Added optional ambiguity randomizer for ncbi2na coding
  726. *
  727. * Revision 1.30  2004/04/12 16:49:16  vasilche
  728. * Allow null scope in CSeqMap_CI and CSeqVector.
  729. *
  730. * Revision 1.29  2004/04/09 20:34:50  vasilche
  731. * Fixed wrong assertion.
  732. *
  733. * Revision 1.28  2003/11/07 17:00:13  vasilche
  734. * Added check for out of bounds withing CSeq_inst to avoid coredump.
  735. *
  736. * Revision 1.27  2003/10/08 14:16:55  vasilche
  737. * Removed circular reference CSeqVector <-> CSeqVector_CI.
  738. *
  739. * Revision 1.26  2003/09/05 17:29:40  grichenk
  740. * Structurized Object Manager exceptions
  741. *
  742. * Revision 1.25  2003/08/29 13:34:47  vasilche
  743. * Rewrote CSeqVector/CSeqVector_CI code to allow better inlining.
  744. * CSeqVector::operator[] made significantly faster.
  745. * Added possibility to have platform dependent byte unpacking functions.
  746. *
  747. * Revision 1.24  2003/08/21 18:51:34  vasilche
  748. * Fixed compilation errors on translation with reverse.
  749. *
  750. * Revision 1.23  2003/08/21 17:04:10  vasilche
  751. * Fixed bug in making conversion tables.
  752. *
  753. * Revision 1.22  2003/08/21 13:32:04  vasilche
  754. * Optimized CSeqVector iteration.
  755. * Set some CSeqVector values (mol type, coding) in constructor instead of detecting them while iteration.
  756. * Remove unsafe bit manipulations with coding.
  757. *
  758. * Revision 1.21  2003/08/19 18:34:11  vasilche
  759. * Buffer length constant moved to *.cpp file for easier modification.
  760. *
  761. * Revision 1.20  2003/07/21 14:30:48  vasilche
  762. * Fixed buffer destruction and exception processing.
  763. *
  764. * Revision 1.19  2003/07/18 20:41:48  grichenk
  765. * Fixed memory leaks in CSeqVector_CI
  766. *
  767. * Revision 1.18  2003/07/18 19:42:42  vasilche
  768. * Added x_DestroyCache() method.
  769. *
  770. * Revision 1.17  2003/07/01 18:00:41  vasilche
  771. * Fixed unsigned/signed comparison.
  772. *
  773. * Revision 1.16  2003/06/24 19:46:43  grichenk
  774. * Changed cache from vector<char> to char*. Made
  775. * CSeqVector::operator[] inline.
  776. *
  777. * Revision 1.15  2003/06/18 15:01:19  vasilche
  778. * Fixed positioning of CSeqVector_CI in GetSeqData().
  779. *
  780. * Revision 1.14  2003/06/17 20:37:06  grichenk
  781. * Removed _TRACE-s, fixed bug in x_GetNextSeg()
  782. *
  783. * Revision 1.13  2003/06/13 17:22:28  grichenk
  784. * Check if seq-map is not null before using it
  785. *
  786. * Revision 1.12  2003/06/10 15:27:14  vasilche
  787. * Fixed warning
  788. *
  789. * Revision 1.11  2003/06/06 15:09:43  grichenk
  790. * One more fix for coordinates
  791. *
  792. * Revision 1.10  2003/06/05 20:20:22  grichenk
  793. * Fixed bugs in assignment functions,
  794. * fixed minor problems with coordinates.
  795. *
  796. * Revision 1.9  2003/06/04 13:48:56  grichenk
  797. * Improved double-caching, fixed problem with strands.
  798. *
  799. * Revision 1.8  2003/06/02 21:03:59  vasilche
  800. * Grichenko's fix of wrong data in CSeqVector.
  801. *
  802. * Revision 1.7  2003/06/02 16:53:35  dicuccio
  803. * Restore file damaged by last check-in
  804. *
  805. * Revision 1.5  2003/05/31 01:42:51  ucko
  806. * Avoid min(size_t, TSeqPos), as they may be different types.
  807. *
  808. * Revision 1.4  2003/05/30 19:30:08  vasilche
  809. * Fixed compilation on GCC 3.
  810. *
  811. * Revision 1.3  2003/05/30 18:00:29  grichenk
  812. * Fixed caching bugs in CSeqVector_CI
  813. *
  814. * Revision 1.2  2003/05/29 13:35:36  grichenk
  815. * Fixed bugs in buffer fill/copy procedures.
  816. *
  817. * Revision 1.1  2003/05/27 19:42:24  grichenk
  818. * Initial revision
  819. *
  820. *
  821. * ===========================================================================
  822. */