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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: test_seqvector_ci.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:47:23  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: test_seqvector_ci.cpp,v 1000.2 2004/06/01 19:47:23 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. *   Test for CSeqVector_CI
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbiapp.hpp>
  44. #include <corelib/ncbienv.hpp>
  45. #include <corelib/ncbiargs.hpp>
  46. #include <corelib/ncbi_system.hpp>
  47. #include <corelib/ncbi_limits.hpp>
  48. #include <util/random_gen.hpp>
  49. // Objects includes
  50. #include <objects/seqloc/Seq_id.hpp>
  51. // Object manager includes
  52. #include <objmgr/object_manager.hpp>
  53. #include <objmgr/scope.hpp>
  54. #include <objmgr/seq_vector.hpp>
  55. #include <objmgr/seq_vector_ci.hpp>
  56. #include <objtools/data_loaders/genbank/gbloader.hpp>
  57. #include <objmgr/bioseq_handle.hpp>
  58. BEGIN_NCBI_SCOPE
  59. using namespace objects;
  60. class CTestApp : public CNcbiApplication
  61. {
  62. public:
  63.     virtual void Init(void);
  64.     virtual int  Run (void);
  65. private:
  66.     void x_TestIterate(CSeqVector_CI& vit,
  67.                        TSeqPos start,
  68.                        TSeqPos stop);
  69.     void x_TestGetData(CSeqVector_CI& vit,
  70.                        TSeqPos start,
  71.                        TSeqPos stop);
  72.     void x_TestVector(TSeqPos start,
  73.                       TSeqPos stop);
  74.     bool x_CheckBuf(const string& buf, size_t pos, size_t len) const;
  75.     CRef<CObjectManager> m_OM;
  76.     CSeqVector m_Vect;
  77.     string m_RefBuf;
  78. };
  79. void CTestApp::Init(void)
  80. {
  81.     // Prepare command line descriptions
  82.     //
  83.     // Create
  84.     auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
  85.     // GI to fetch
  86.     arg_desc->AddDefaultKey("gi", "SeqEntryID",
  87.                             "GI id of the Seq-Entry to fetch",
  88.                             CArgDescriptions::eInteger,
  89.                             "29791621");
  90.     arg_desc->AddDefaultKey("cycles", "RandomCycles",
  91.                             "repeat random test 'cycles' times",
  92.                             CArgDescriptions::eInteger, "100");
  93.     arg_desc->AddDefaultKey("seed", "RandomSeed",
  94.                             "Force random seed",
  95.                             CArgDescriptions::eInteger, "0");
  96.     arg_desc->AddFlag("no_scope", "Use seq vector with null scope");
  97.     // Program description
  98.     string prog_description = "Test for CSeqVector_CIn";
  99.     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
  100.                               prog_description, false);
  101.     // Pass argument descriptions to the application
  102.     //
  103.     SetupArgDescriptions(arg_desc.release());
  104. }
  105. bool CTestApp::x_CheckBuf(const string& buf, size_t pos, size_t len) const
  106. {
  107.     if ( pos > m_RefBuf.size() || pos + len > m_RefBuf.size() ||
  108.          buf.size() != len ) {
  109.         return false;
  110.     }
  111.     return memcmp(buf.data(), m_RefBuf.data()+pos, len) == 0;
  112. }
  113. void CTestApp::x_TestIterate(CSeqVector_CI& vit,
  114.                              TSeqPos start,
  115.                              TSeqPos stop)
  116. {
  117.     if (stop > m_Vect.size()) {
  118.         stop = m_Vect.size();
  119.     }
  120.     if (start != kInvalidSeqPos) {
  121.         if (start > m_Vect.size())
  122.             start = m_Vect.size();
  123.         vit.SetPos(start);
  124.     }
  125.     else {
  126.         start = vit.GetPos();
  127.     }
  128.     // cout << "Testing iterator, " << start << " - " << stop << "... ";
  129.     if (start > stop) {
  130.         // Moving down
  131.         const char* data = m_RefBuf.data();
  132.         for ( TSeqPos pos = start; pos > stop;  ) {
  133.             --vit; --pos;
  134.             if ( vit.GetPos() != pos ) {
  135.                 cout << endl << "ERROR: GetPos failed at position " << pos << endl;
  136.                 throw runtime_error("Test failed");
  137.             }
  138.             if (*vit != data[pos]) {
  139.                 cout << endl << "ERROR: Test failed at position " << pos << endl;
  140.                 throw runtime_error("Test failed");
  141.             }
  142.         }
  143.     }
  144.     else {
  145.         // Moving up
  146.         const char* data = m_RefBuf.data();
  147.         for ( TSeqPos pos = start; pos < stop; ++vit, ++pos ) {
  148.             if ( vit.GetPos() != pos ) {
  149.                 cout << endl << "ERROR: GetPos failed at position " << pos << endl;
  150.                 throw runtime_error("Test failed");
  151.             }
  152.             if (*vit != data[pos]) {
  153.                 cout << endl << "ERROR: Test failed at position " << pos << endl;
  154.                 throw runtime_error("Test failed");
  155.             }
  156.         }
  157.     }
  158.     // cout << "OK" << endl;
  159. }
  160. void CTestApp::x_TestGetData(CSeqVector_CI& vit,
  161.                              TSeqPos start,
  162.                              TSeqPos stop)
  163. {
  164.     if (start == kInvalidSeqPos) {
  165.         start = vit.GetPos();
  166.     }
  167.     if (start > stop)
  168.         swap(start, stop);
  169.     // cout << "Testing GetSeqData(" << start << ", " << stop << ")... " << endl;
  170.     string buf;
  171.     vit.GetSeqData(start, stop, buf);
  172.     if (start >= stop  &&  buf.size() > 0) {
  173.         cout << endl << "ERROR: Test failed -- invalid data length" << endl;
  174.         throw runtime_error("Test failed");
  175.     }
  176.     if (stop > m_Vect.size())
  177.         stop = m_Vect.size();
  178.     if ( !x_CheckBuf(buf, start, stop - start) ) {
  179.         cout << endl << "ERROR: Test failed -- invalid data" << endl;
  180.         throw runtime_error("Test failed");
  181.     }
  182.     // cout << "OK" << endl;
  183. }
  184. void CTestApp::x_TestVector(TSeqPos start,
  185.                             TSeqPos stop)
  186. {
  187.     if (start > m_Vect.size()) {
  188.         start = m_Vect.size();
  189.     }
  190.     if (stop > m_Vect.size()) {
  191.         stop = m_Vect.size();
  192.     }
  193.     // cout << "Testing vector[], " << start << " - " << stop << "... ";
  194.     if (start > stop) {
  195.         // Moving down
  196.         const char* data = m_RefBuf.data();
  197.         for (TSeqPos i = start; i > stop; ) {
  198.             --i;
  199.             if (m_Vect[i] != data[i]) {
  200.                 cout << endl << "ERROR: Test failed at position " << i << endl;
  201.                 throw runtime_error("Test failed");
  202.             }
  203.         }
  204.     }
  205.     else {
  206.         // Moving up
  207.         const char* data = m_RefBuf.data();
  208.         for (TSeqPos i = start; i < stop; ++i) {
  209.             if (m_Vect[i] != data[i]) {
  210.                 cout << endl << "ERROR: Test failed at position " << i << endl;
  211.                 throw runtime_error("Test failed");
  212.             }
  213.         }
  214.     }
  215.     // cout << "OK" << endl;
  216. }
  217. int CTestApp::Run(void)
  218. {
  219.     // Process command line args: get GI to load
  220.     const CArgs& args = GetArgs();
  221.     // GI with many segments of different sizes.
  222.     int gi = args["gi"].AsInteger(); // 29791621;
  223.     m_OM.Reset(new CObjectManager);
  224.     m_OM->RegisterDataLoader(*new CGBDataLoader("ID", 0, 2),
  225.                              CObjectManager::eDefault);
  226.     CScope scope(*m_OM);
  227.     scope.AddDefaults();
  228.     CSeq_id id;
  229.     id.SetGi(gi);
  230.     CBioseq_Handle handle = scope.GetBioseqHandle(id);
  231.     // Check if the handle is valid
  232.     if ( !handle ) {
  233.         cout << "Can not find gi " << gi << endl;
  234.         return 0;
  235.     }
  236.     cout << "Testing gi " << gi << endl;
  237.     // Create seq-vector
  238.     if ( !args["no_scope"] ) {
  239.         m_Vect = handle.GetSeqVector(CBioseq_Handle::eCoding_Iupac);
  240.     }
  241.     else {
  242.         CScope* no_scope = 0;
  243.         m_Vect = CSeqVector(handle.GetSeqMap(), *no_scope,
  244.                             CBioseq_Handle::eCoding_Iupac);
  245.     }
  246.     // Prepare reference data
  247.     m_Vect.GetSeqData(0, m_Vect.size(), m_RefBuf);
  248.     CSeqVector_CI vit = CSeqVector_CI(m_Vect);
  249.     string buf;
  250.     // start > stop test
  251.     cout << "Testing empty range (start > stop)... ";
  252.     vit.GetSeqData(m_Vect.size(), 0, buf);
  253.     if (buf.size() != 0) {
  254.         cout << endl << "ERROR: Test failed -- got non-empty data" << endl;
  255.         throw runtime_error("Empty range test failed");
  256.     }
  257.     cout << "OK" << endl;
  258.     // stop > length test
  259.     cout << "Testing past-end read (stop > size)... ";
  260.     vit.GetSeqData(max<TSeqPos>(m_Vect.size(), 100) - 100,
  261.                    m_Vect.size() + 1,
  262.                    buf);
  263.     if ( !x_CheckBuf(buf,
  264.                      max<TSeqPos>(m_Vect.size(), 100) - 100,
  265.                      min<TSeqPos>(m_Vect.size(), 100)) ) {
  266.         cout << "ERROR: GetSeqData() failed -- invalid data" << endl;
  267.         throw runtime_error("Past-end read test failed");
  268.     }
  269.     cout << "OK" << endl;
  270.     buf = ""; // .erase();
  271.     // Compare iterator with GetSeqData()
  272.     // Not using x_TestIterate() to also check operator bool()
  273.     cout << "Testing basic iterator... ";
  274.     const char* data = m_RefBuf.data();
  275.     const char* c = data;
  276.     const char* data_end = data + m_RefBuf.size();
  277.     for (vit.SetPos(0); vit; ++vit, ++c) {
  278.         if (c == data_end ||  *vit != *c) {
  279.             cout << "ERROR: Invalid data at " << vit.GetPos() << endl;
  280.             throw runtime_error("Basic iterator test failed");
  281.         }
  282.     }
  283.     if (c != data_end) {
  284.         cout << "ERROR: Invalid data length" << endl;
  285.         throw runtime_error("Basic iterator test failed");
  286.     }
  287.     cout << "OK" << endl;
  288.     // Partial retrieval with GetSeqData() test, limit to 2000 bases
  289.     cout << "Testing partial retrieval... ";
  290.     for (unsigned i = max<int>(1, m_Vect.size() / 2 - 2000);
  291.          i <= m_Vect.size() / 2; ++i) {
  292.         x_TestGetData(vit, i, m_Vect.size() - i);
  293.     }
  294.     cout << "OK" << endl;
  295.     // Butterfly test
  296.     cout << "Testing butterfly reading... ";
  297.     for (unsigned i = 1; i < m_Vect.size() / 2; ++i) {
  298.         if (m_Vect[i] != data[i]) {
  299.             cout << "ERROR: Butterfly test failed at position " << i << endl;
  300.             throw runtime_error("Butterfly read test failed");
  301.         }
  302.     }
  303.     cout << "OK" << endl;
  304.     TSeqPos pos1 = 0;
  305.     TSeqPos pos2 = 0;
  306.     TSeqPos pos3 = 0;
  307.     TSeqPos pos4 = 0;
  308.     {{
  309.         const CSeqMap& smap = handle.GetSeqMap();
  310.         CSeqMap_CI map_it = smap.begin_resolved(&scope);
  311.         if ( map_it ) {
  312.             // Should happen for any non-empty sequence
  313.             pos2 = map_it.GetEndPosition();
  314.             ++map_it;
  315.             if ( map_it ) {
  316.                 // Should happen for most segmented sequences
  317.                 pos3 = map_it.GetEndPosition();
  318.                 ++map_it;
  319.                 if ( map_it ) {
  320.                     // May happen for some segmented sequences
  321.                     pos4 = map_it.GetEndPosition();
  322.                 }
  323.             }
  324.         }
  325.     }}
  326.     // ========= Iterator tests ==========
  327.     cout << "Testing iterator - single segment... ";
  328.     // Single segment test, start from the middle of the first segment
  329.     vit = CSeqVector_CI(m_Vect, (pos1 + pos2) / 2);
  330.     // Back to the first segment start
  331.     x_TestIterate(vit, kInvalidSeqPos, pos1);
  332.     // Forward to the first segment end
  333.     x_TestIterate(vit, kInvalidSeqPos, pos2);
  334.     // Back to the first segment start again
  335.     x_TestIterate(vit, kInvalidSeqPos, pos1);
  336.     cout << "OK" << endl;
  337.     // Try to run multi-segment tests
  338.     if ( pos3 ) {
  339.         cout << "Testing iterator - multiple segments... ";
  340.         // Start from the middle of the second segment
  341.         vit = CSeqVector_CI(m_Vect, (pos2 + pos3) / 2);
  342.         // Back to the first segment start
  343.         x_TestIterate(vit, kInvalidSeqPos, pos1);
  344.         // Forward to the second or third segment end
  345.         x_TestIterate(vit, kInvalidSeqPos, pos4 ? pos4 : pos3);
  346.         // Back to the first segment start again
  347.         x_TestIterate(vit, kInvalidSeqPos, pos1);
  348.         cout << "OK" << endl;
  349.     }
  350.     // ========= GetSeqData() tests ==========
  351.     cout << "Testing GetSeqData() - single segment... ";
  352.     // Single segment test, start from the middle of the first segment
  353.     vit = CSeqVector_CI(m_Vect, (pos1 + pos2) / 2);
  354.     // Back to the first segment start
  355.     x_TestGetData(vit, kInvalidSeqPos, pos1);
  356.     // Forward to the first segment end
  357.     x_TestGetData(vit, kInvalidSeqPos, pos2);
  358.     // Back to the first segment start again
  359.     x_TestGetData(vit, kInvalidSeqPos, pos1);
  360.     cout << "OK" << endl;
  361.     // Try to run multi-segment tests
  362.     if ( pos3 ) {
  363.         cout << "Testing GetSeqData() - multiple segments... ";
  364.         // Start from the middle of the second segment
  365.         vit = CSeqVector_CI(m_Vect, (pos2 + pos3) / 2);
  366.         // Back to the first segment start
  367.         x_TestGetData(vit, kInvalidSeqPos, pos1);
  368.         // Forward to the second or third segment end
  369.         x_TestGetData(vit, kInvalidSeqPos, pos4 ? pos4 : pos3);
  370.         // Back to the first segment start again
  371.         x_TestGetData(vit, kInvalidSeqPos, pos1);
  372.         cout << "OK" << endl;
  373.     }
  374.     // ========= CSeqVector[] tests ==========
  375.     cout << "Testing operator[] - single segment... ";
  376.     // Single segment test, start from the middle of the first segment
  377.     // Back to the first segment start
  378.     x_TestVector((pos1 + pos2) / 2, pos1);
  379.     // Forward to the first segment end
  380.     x_TestVector(pos1, pos2);
  381.     // Back to the first segment start again
  382.     x_TestVector(pos2, pos1);
  383.     cout << "OK" << endl;
  384.     // Try to run multi-segment tests
  385.     if ( pos3 ) {
  386.         cout << "Testing operator[] - multiple segments... ";
  387.         // Start from the middle of the second segment
  388.         // Back to the first segment start
  389.         x_TestVector((pos2 + pos3) / 2, pos1);
  390.         // Forward to the second or third segment end
  391.         x_TestVector(pos1, pos4 ? pos4 : pos3);
  392.         // Back to the first segment start again
  393.         x_TestVector(pos4 ? pos4 : pos3, pos1);
  394.         cout << "OK" << endl;
  395.     }
  396.     // Random access tests
  397.     cout << "Testing random access" << endl;
  398.     unsigned int rseed = args["seed"].AsInteger();
  399.     int cycles = args["cycles"].AsInteger();
  400.     if (rseed == 0) {
  401.         rseed = (unsigned)time( NULL );
  402.     }
  403.     cout << "Testing random reading (seed: " << rseed
  404.          << ", cycles: " << cycles << ")... " << endl;
  405.     CRandom random(rseed);
  406.     vit = CSeqVector_CI(m_Vect);
  407.     for (int i = 0; i < cycles; ++i) {
  408.         TSeqPos start = random.GetRand(0, m_Vect.size());
  409.         TSeqPos stop = random.GetRand(0, m_Vect.size());
  410.         switch (i % 3) {
  411.         case 0:
  412.             x_TestIterate(vit, start, stop);
  413.             break;
  414.         case 1:
  415.             x_TestGetData(vit, start, stop);
  416.             break;
  417.         case 2:
  418.             x_TestVector(start, stop);
  419.             break;
  420.         }
  421.     }
  422.     cout << "OK" << endl;
  423.     NcbiCout << "All tests passed" << NcbiEndl;
  424.     return 0;
  425. }
  426. END_NCBI_SCOPE
  427. /////////////////////////////////////////////////////////////////////////////
  428. //  MAIN
  429. USING_NCBI_SCOPE;
  430. int main(int argc, const char* argv[])
  431. {
  432.     return CTestApp().AppMain(argc, argv);
  433. }
  434. /*
  435. * ---------------------------------------------------------------------------
  436. * $Log: test_seqvector_ci.cpp,v $
  437. * Revision 1000.2  2004/06/01 19:47:23  gouriano
  438. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  439. *
  440. * Revision 1.5  2004/05/21 21:42:56  gorelenk
  441. * Added PCH ncbi_pch.hpp
  442. *
  443. * Revision 1.4  2004/04/12 23:24:27  ucko
  444. * Avoid directly "dereferencing" a null scope, to fix the MIPSpro build.
  445. *
  446. * Revision 1.3  2004/04/12 16:49:56  vasilche
  447. * Added option to test CSeqVector with null scope.
  448. *
  449. * Revision 1.2  2004/04/09 20:35:32  vasilche
  450. * Fixed test on short sequences (<100).
  451. *
  452. * Revision 1.1  2003/12/16 17:51:23  kuznets
  453. * Code reorganization
  454. *
  455. * Revision 1.6  2003/11/12 20:16:15  vasilche
  456. * Fixed error: Attempt to delete Object Manager with open scopes.
  457. *
  458. * Revision 1.5  2003/08/29 13:34:48  vasilche
  459. * Rewrote CSeqVector/CSeqVector_CI code to allow better inlining.
  460. * CSeqVector::operator[] made significantly faster.
  461. * Added possibility to have platform dependent byte unpacking functions.
  462. *
  463. * Revision 1.4  2003/08/06 20:51:54  grichenk
  464. * Use CRandom class
  465. *
  466. * Revision 1.3  2003/07/09 18:49:33  grichenk
  467. * Added arguments (seed and cycles), default random cycles set to 20.
  468. *
  469. * Revision 1.2  2003/06/26 17:02:52  grichenk
  470. * Simplified output, decreased number of cycles.
  471. *
  472. * Revision 1.1  2003/06/24 19:50:02  grichenk
  473. * Added test for CSeqVector_CI
  474. *
  475. *
  476. * ===========================================================================
  477. */